Files
kolaytercih/src/lib/harita-ulkeler.ts
bilalgursen 259534fa9c feat(katalog+tasarim): şehir adları her yerde link; piksel yüzeylere beyaz ton
- ilSayfaHref: üniversite sayfası il hapı, /universiteler listesi, bölüm /
  sonuç / listem / tadımlık satırlarındaki il metası şehir sayfasına gider.
- Şehir kümeleri tüm (üniversite, il) çiftlerinden: DB'deki her il değerinin
  sayfası var (ODTÜ Ankara + KKTC); dev'de eski globalThis önbelleğine dayanıklı.
- PikselZemin ton="acik", CtaBandi/CtaSiraForm ton="beyaz": /universiteler
  altı ve /meraklisina kapanışı beyaz, diğer bantlar mavi (dönüşümlü).
- ilUlkeHaritasi: il değerinden ülke haritası + şehir konumu.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-24 14:56:11 +03:00

220 lines
7.2 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// Türkiye dışındaki (KKTC ve yurtdışı) üniversitelerin ülke haritası çözümü.
// Kontür verisi harita-ulkeler-verisi.ts'te (scripts/ulke-harita-uret.ts üretir).
import {
ULKE_HARITALARI,
type UlkeKodu,
type UlkeHarita,
} from "./harita-ulkeler-verisi";
import type { LatLng } from "./uni-koordinatlar";
export {
ULKE_HARITALARI,
ULKE_HARITA_GENISLIK,
ULKE_HARITA_YUKSEKLIK,
} from "./harita-ulkeler-verisi";
export type { UlkeKodu, UlkeHarita } from "./harita-ulkeler-verisi";
/** Schema.org addressCountry için ISO 3166-1 alpha-2 kodları. */
export const ULKE_ISO: Record<UlkeKodu, string> = {
kktc: "CY",
azerbaycan: "AZ",
kirgizistan: "KG",
kazakistan: "KZ",
"bosna-hersek": "BA",
makedonya: "MK",
arnavutluk: "AL",
};
type Sehir = { ulke: UlkeKodu; ad: string; koord: LatLng };
/** DB'deki il değerlerinden ve düzeltme tablosundan şehir anahtarları. */
const SEHIRLER: Record<string, Sehir> = {
GİRNE: { ulke: "kktc", ad: "Girne", koord: [35.341, 33.319] },
LEFKOŞA: { ulke: "kktc", ad: "Lefkoşa", koord: [35.19, 33.365] },
GAZİMAĞUSA: { ulke: "kktc", ad: "Gazimağusa", koord: [35.125, 33.941] },
GÜZELYURT: { ulke: "kktc", ad: "Güzelyurt", koord: [35.198, 32.994] },
LEFKE: { ulke: "kktc", ad: "Lefke", koord: [35.111, 32.849] },
"BAKÜ-AZERBAYCAN": {
ulke: "azerbaycan",
ad: "Bakü",
koord: [40.409, 49.867],
},
"BİŞKEK-KIRGIZİSTAN": {
ulke: "kirgizistan",
ad: "Bişkek",
koord: [42.875, 74.603],
},
"TÜRKİSTAN-KAZAKİSTAN": {
ulke: "kazakistan",
ad: "Türkistan",
koord: [43.297, 68.252],
},
"SARAYBOSNA - BOSNA - HERSEK": {
ulke: "bosna-hersek",
ad: "Saraybosna",
koord: [43.856, 18.413],
},
ÜSKÜP: { ulke: "makedonya", ad: "Üsküp", koord: [41.997, 21.428] },
TİRAN: { ulke: "arnavutluk", ad: "Tiran", koord: [41.328, 19.818] },
};
type SehirAnahtari = keyof typeof SEHIRLER;
/**
* Kaynak verideki gürültü için üniversite adına göre düzeltme:
* - Uluslararası Balkan Üniversitesi Üsküp'tedir; YÖK Atlas satırlarının
* çoğu il'i yanlışlıkla "SARAYBOSNA - BOSNA - HERSEK" der.
* - Tiran New York Üniversitesi'nin il alanı boştur.
* - ODTÜ ve ASBÜ'nün KKTC kampüs satırları vardır ama ana kampüs Türkiye'de;
* null → Türkiye haritasında kalır.
* Anahtar: uniAdiNormalize edilmiş adın tr-TR büyük harf hali.
*/
const UNI_DUZELTME: Record<string, SehirAnahtari | null> = {
"ULUSLARARASI BALKAN ÜNİVERSİTESİ": "ÜSKÜP",
"TİRAN NEW YORK ÜNİVERSİTESİ": "TİRAN",
"KIBRIS AYDIN ÜNİVERSİTESİ": "GİRNE", // il alanı yalnızca "KIBRIS"
"ORTA DOĞU TEKNİK ÜNİVERSİTESİ": null,
"ANKARA SOSYAL BİLİMLER ÜNİVERSİTESİ": null,
};
/** il değeri Türkiye dışını mı gösteriyor? ("KIBRIS" genel değeri dahil) */
const YURTDISI_IL = new Set([...Object.keys(SEHIRLER), "KIBRIS"]);
/**
* Ad sonundaki "(KKTC-LEFKOŞA)" ekinden şehir anahtarı. YÖK Atlas'ta 100'den
* fazla KKTC satırının il alanı şehir değil genel "KIBRIS"tır (Doğu Akdeniz,
* Yakın Doğu, Lefke Avrupa, Uluslararası Final, Kıbrıs Sağlık ve Toplum
* Bilimleri); şehir yalnızca üniversite adının parantezinde durur. Bu ek
* okunmazsa o programlar hiçbir haritaya düşmez, "haritada gösterilemiyor"
* sayısına yazılır.
*/
function ektenSehir(universite: string): SehirAnahtari | null {
const ek = universite.match(/\(([^)]*)\)\s*$/)?.[1];
if (!ek) return null;
// "KKTC-GAZİMAĞUSA" → "GAZİMAĞUSA"; ülke öneki olmayan "(ANKARA)" gibi
// ekler SEHIRLER'de karşılık bulmadığından kendiliğinden elenir.
const sehir = ek.split("-").pop()!.trim().toLocaleUpperCase("tr-TR");
return sehir in SEHIRLER ? (sehir as SehirAnahtari) : null;
}
/** Üniversite adı + il'den şehir anahtarı; şehri bilinmeyen KKTC'de ülke. */
type Cozum = { anahtar: SehirAnahtari } | { ulke: UlkeKodu } | null;
function coz(universite: string, il: string | null): Cozum {
const ad = universite
.replace(/\s*\([^)]*\)\s*$/, "")
.trim()
.toLocaleUpperCase("tr-TR");
if (ad in UNI_DUZELTME) {
const anahtar = UNI_DUZELTME[ad];
return anahtar === null ? null : { anahtar };
}
if (!il || !YURTDISI_IL.has(il)) return null;
if (il in SEHIRLER) return { anahtar: il as SehirAnahtari };
// il "KIBRIS": ülke bilinir, şehir adın parantez ekinden okunur;
// o da yoksa ülke seviyesinde kalır (şehir pini çizilemez)
const ekSehir = ektenSehir(universite);
return ekSehir ? { anahtar: ekSehir } : { ulke: "kktc" };
}
export type UlkeKonum = {
ulke: UlkeKodu;
ulkeAd: string;
iso: string;
harita: UlkeHarita;
/** Şehir adı; genel "KIBRIS" gibi şehri bilinmeyen durumda null */
sehir: string | null;
};
/**
* Üniversite Türkiye dışındaysa ülke haritası + şehir adı döner;
* Türkiye'deyse (veya çözülemiyorsa) null — Türkiye haritası kullanılır.
*/
export function uniUlkeKonum(
universite: string,
il: string | null,
): UlkeKonum | null {
const cozum = coz(universite, il);
if (!cozum) return null;
const ulke = "anahtar" in cozum ? SEHIRLER[cozum.anahtar].ulke : cozum.ulke;
const harita = ULKE_HARITALARI[ulke];
return {
ulke,
ulkeAd: harita.ad,
iso: ULKE_ISO[ulke],
harita,
sehir: "anahtar" in cozum ? SEHIRLER[cozum.anahtar].ad : null,
};
}
/** Yurtdışı şehir merkezinin kendi ülke haritasındaki viewBox konumu. */
export type YurtdisiKonum = {
ulke: UlkeKodu;
ulkeAd: string;
sehir: string;
x: number;
y: number;
};
function sehirKonumu(anahtar: SehirAnahtari): YurtdisiKonum {
const sehir = SEHIRLER[anahtar];
const { ad, proje } = ULKE_HARITALARI[sehir.ulke];
const [lat, lng] = sehir.koord;
return {
ulke: sehir.ulke,
ulkeAd: ad,
sehir: sehir.ad,
x: proje.ax * lng + proje.bx,
y: proje.ay * lat + proje.by,
};
}
/** Yurtdışı üniversitenin şehir konumu; şehir çözülemiyorsa null. */
export function yurtdisiUniKonum(
universite: string,
il: string | null,
): YurtdisiKonum | null {
const cozum = coz(universite, il);
return cozum && "anahtar" in cozum ? sehirKonumu(cozum.anahtar) : null;
}
/**
* Yalnızca il değerinden ülke haritası (şehir sayfası). "KIBRIS" genel
* değeri ülke seviyesinde kalır; "ÜSKÜP-MAKEDONYA" gibi ülke ekli değerler
* ilk parçasıyla çözülür. Türkiye ili ya da bilinmeyen değer → null.
*/
export function ilUlkeHaritasi(il: string): {
ulke: UlkeKodu;
ulkeAd: string;
harita: UlkeHarita;
sehir: YurtdisiKonum | null;
} | null {
const anahtar =
il in SEHIRLER
? (il as SehirAnahtari)
: (() => {
const ilk = il.split("-")[0].trim();
return ilk in SEHIRLER ? (ilk as SehirAnahtari) : null;
})();
const ulke: UlkeKodu | null = anahtar
? SEHIRLER[anahtar].ulke
: il === "KIBRIS"
? "kktc"
: null;
if (!ulke) return null;
const harita = ULKE_HARITALARI[ulke];
return {
ulke,
ulkeAd: harita.ad,
harita,
sehir: anahtar ? sehirKonumu(anahtar) : null,
};
}
/** Yalnızca il değerinden (kilitli satırlar) yurtdışı şehir konumu. */
export function yurtdisiIlKonum(il: string | null): YurtdisiKonum | null {
return il && il in SEHIRLER ? sehirKonumu(il as SehirAnahtari) : null;
}