Skip to content

Instantly share code, notes, and snippets.

@jacwright
Created May 15, 2023 21:12
Show Gist options
  • Save jacwright/da95b48651c42f52263ef761e5df06c5 to your computer and use it in GitHub Desktop.
Save jacwright/da95b48651c42f52263ef761e5df06c5 to your computer and use it in GitHub Desktop.
Location Cloudflare Durable Objects close to users based on continent and latitude/longitude.
export function getLocationHint(location: Location = {}) {
if (!location.continentCode && !location.point) return 'enam';
const areas = continentCodes[location.continentCode || 'AN'];
let closest = areas[0];
let shortestDistance = Infinity;
if (areas.length === 1 || !location.point) return closest;
const { lat, lon } = location.point;
const userLatLong = [lat, lon] as [number, number];
areas.forEach(area => {
const latLong = locationLatLongs[area];
const distance = getDistance(latLong, userLatLong);
if (distance < shortestDistance) {
shortestDistance = distance;
closest = area;
}
});
return closest;
}
interface Location {
continentCode?: string;
point?: { lat: number; lon: number };
}
type Locations = keyof typeof locationLatLongs;
const locationLatLongs: Record<string, [number, number]> = {
wnam: [37.797958, -122.238303], // Western North America
enam: [39.082657, -77.658312], // Eastern North America
sam: [-9.07816, -59.0535], // South America
weur: [48.851311, 2.295185], // Western Europe
eeur: [44.347606, 25.674957], // Eastern Europe
apac: [1.415, 104.021515], // Asia-Pacific
oc: [-23.045663, 134.341405], // Oceania
afr: [18.598045, 17.183202], // Africa
me: [31.610075, 48.911718], // Middle East
};
const continentCodes: Record<string, Locations[]> = {
AF: ['afr'], // Africa
AN: ['afr', 'apac', 'weur', 'eeur', 'wnam', 'enam', 'oc', 'sam'], // Antarctica
AS: ['apac'], // Asia
EU: ['weur', 'eeur'], // Europe
NA: ['wnam', 'enam'], // North america
OC: ['oc'], // Oceania
SA: ['sam'], // South america
};
// Returns the distance between to lat/long coordinates in km
function getDistance(pos1: [number, number], pos2: [number, number]) {
var R = 6371; // Radius of the earth in km
var dLat = deg2rad(pos2[0] - pos1[0]); // deg2rad below
var dLon = deg2rad(pos2[1] - pos1[1]);
var a =
Math.sin(dLat / 2) * Math.sin(dLat / 2) +
Math.cos(deg2rad(pos1[0])) * Math.cos(deg2rad(pos2[0])) * Math.sin(dLon / 2) * Math.sin(dLon / 2);
var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
var d = R * c; // Distance in km
return d;
}
function deg2rad(deg: number) {
return deg * (Math.PI / 180);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment