// İl merkezleri arası kuş uçuşu mesafe (km). Profildeki "evden en fazla N km" // filtresi il düzeyinde çalışır: adres/koordinat tutulmaz (KVKK, §8). import { turkishSlugify } from "./slug"; import { IL_MERKEZ, type LatLng } from "./uni-koordinatlar"; const DUNYA_YARICAP_KM = 6371; export function kmMesafe(a: LatLng, b: LatLng): number { const rad = (d: number) => (d * Math.PI) / 180; const dLat = rad(b[0] - a[0]); const dLng = rad(b[1] - a[1]); const h = Math.sin(dLat / 2) ** 2 + Math.cos(rad(a[0])) * Math.cos(rad(b[0])) * Math.sin(dLng / 2) ** 2; return Math.round(2 * DUNYA_YARICAP_KM * Math.asin(Math.sqrt(h))); } /** * DB il adı biçimine (büyük harf, Türkçe) çevirir; bilinmiyorsa null. * Türkçe harfler katlanarak karşılaştırılır: "IZMIR", "izmir", "İzmir" → İZMİR. */ export function ilAdiNormalize(ham: string): string | null { const aday = turkishSlugify(ham); if (!aday) return null; const iller = Object.keys(IL_MERKEZ).map((il) => ({ il, katli: turkishSlugify(il) })); const tam = iller.find((x) => x.katli === aday); if (tam) return tam.il; // "Afyon" → AFYONKARAHİSAR gibi öneki eşleşen tek il varsa onu al const adaylar = iller.filter((x) => x.katli.startsWith(aday)); return adaylar.length === 1 ? adaylar[0].il : null; } /** Ev iline en fazla `km` uzaktaki iller (evin kendisi dahil), yakından uzağa. */ export function yakinIller(evIl: string, km: number): string[] { const ev = IL_MERKEZ[evIl]; if (!ev) return []; return Object.entries(IL_MERKEZ) .map(([il, k]) => ({ il, km: kmMesafe(ev, k) })) .filter((x) => x.km <= km) .sort((a, b) => a.km - b.km) .map((x) => x.il); } /** İki il arası km; biri bilinmiyorsa null. */ export function illerArasiKm(a: string, b: string): number | null { const ka = IL_MERKEZ[a]; const kb = IL_MERKEZ[b]; return ka && kb ? kmMesafe(ka, kb) : null; }