diff --git a/scripts/veri-kalite.ts b/scripts/veri-kalite.ts index 862e848..67a62fe 100644 --- a/scripts/veri-kalite.ts +++ b/scripts/veri-kalite.ts @@ -33,6 +33,10 @@ import { tabloVar, yilArgumani, } from "./yokatlas-goc"; +// URAP kontrolleri (dosya sonundaki urapKontrolleri) — salt okunur sabit. +import type { Db } from "./yokatlas-goc"; +import { uniSayfaSlug } from "../src/lib/slug"; +import { URAP_DONEM, URAP_SIRA, URAP_TOPLAM } from "../src/lib/urap-siralama"; const TURLER = ["SAYISAL", "EŞİT AĞIRLIK", "SÖZEL", "DİL", "TYT"]; @@ -291,9 +295,94 @@ async function main() { console.log(` şimdi, tüm satırlar (yeni dahil) : ${toplamlar(simdi)}`); } + urapKontrolleri(db, zorunlu, bilgi); + db.close(); console.log(`\nSonuç: ${basarisiz} ZORUNLU kontrol kaldı, ${uyari} uyarı.`); if (basarisiz > 0) process.exit(1); } if (process.argv[1]?.endsWith("veri-kalite.ts")) calistir(main); + +/** + * URAP Türkiye sıralaması sabiti (`src/lib/urap-siralama.ts`) denetimi. + * Amaç: yıllık tazelemede eşleşmeyen bir URAP satırı SESSİZCE DÜŞMESİN — + * düşerse üniversitenin adı değişmiş demektir ve o sayfada sıra kaybolur. + * DB'ye yazmaz; sabit ile DB'deki üniversite slug'larını karşılaştırır. + */ +function urapKontrolleri( + db: Db, + zorunlu: (ad: string, tamam: boolean, detay: string) => void, + bilgi: (ad: string, sorunlu: boolean, detay: string) => void +) { + const kayitlar = Object.entries(URAP_SIRA); + + // (1) Sabitteki her slug DB'de karşılık bulmalı — bulamayan = ad değişikliği. + const dbToplam = new Map(); + const satirlar = db + .prepare("SELECT universite, unitur, COUNT(*) AS n FROM programs GROUP BY 1, 2") + .all() as { universite: string; unitur: string | null; n: number }[]; + for (const r of satirlar) { + const slug = uniSayfaSlug(r.universite); + if (!slug) continue; + const kayit = dbToplam.get(slug) ?? { unitur: null, program: 0 }; + kayit.program += r.n; + if (!kayit.unitur && r.unitur) kayit.unitur = r.unitur; + dbToplam.set(slug, kayit); + } + const karsiliksiz = kayitlar.filter(([slug]) => !dbToplam.has(slug)); + zorunlu( + "URAP: her sıra bir üniversite sayfasına bağlı", + karsiliksiz.length === 0, + karsiliksiz.length === 0 + ? `${kayitlar.length} slug'ın tamamı DB'de var` + : `DB'de karşılığı olmayan (ad değişmiş olabilir): ${karsiliksiz.map(([slug, v]) => `${slug}(#${v.sira})`).join(", ")}` + ); + + // (2) Kayıt sayısı payda ile aynı olmalı — payda kartta gösteriliyor. + zorunlu( + "URAP: kayıt sayısı = URAP_TOPLAM", + kayitlar.length === URAP_TOPLAM, + `kayıt ${kayitlar.length}, URAP_TOPLAM ${URAP_TOPLAM} (dönem ${URAP_DONEM})` + ); + + // (3) Sıralar 1..URAP_TOPLAM; tekrarsız ve boşluksuz. + const siralar = kayitlar.map(([, v]) => v.sira).sort((a, b) => a - b); + const bozukSira = siralar.findIndex((s, i) => s !== i + 1); + zorunlu( + "URAP: sıralar 1..N tekrarsız ve boşluksuz", + bozukSira === -1 && siralar.length === URAP_TOPLAM, + bozukSira === -1 + ? `1..${siralar.length} kesintisiz` + : `${bozukSira + 1}. sırada beklenen ${bozukSira + 1}, gelen ${siralar[bozukSira]}` + ); + + // (4) Puan sıraya göre azalmalı — sıra 1 en yüksek puan. + const sirali = [...kayitlar].sort((a, b) => a[1].sira - b[1].sira); + const bozukPuan = sirali.findIndex( + (k, i) => i > 0 && sirali[i - 1][1].puan < k[1].puan + ); + zorunlu( + "URAP: puanlar sıraya göre azalan", + bozukPuan === -1, + bozukPuan === -1 + ? `${sirali[0][1].puan} → ${sirali[sirali.length - 1][1].puan}` + : `#${sirali[bozukPuan][1].sira} (${sirali[bozukPuan][0]}) puanı bir önceki sıradan yüksek` + ); + + // (5) Kapsama boşluğu: URAP yalnız Türkiye'yi sıralar, KKTC/yurt dışı ve + // yalnız MYO'su olan kurumlar listede olmaz — bu normaldir. Ama büyük bir + // Türkiye üniversitesinin düşmesi neredeyse her zaman ad değişikliğidir. + const disarida = [...dbToplam.entries()].filter(([slug]) => !(slug in URAP_SIRA)); + const turkiyeBuyuk = disarida.filter( + ([, v]) => + (v.unitur === "DEVLET" || v.unitur === "VAKIF") && v.program >= 150 + ); + bilgi( + "URAP: kapsama boşluğu", + turkiyeBuyuk.length > 0, + turkiyeBuyuk.length === 0 + ? `URAP dışında ${disarida.length} kurum (KKTC/yurt dışı, MYO ve yeni üniversiteler); 150+ programlı Türkiye üniversitesi yok` + : `URAP dışında kalan 150+ programlı Türkiye üniversitesi (ad değişmiş olabilir): ${turkiyeBuyuk.map(([slug, v]) => `${slug}(${v.program})`).join(", ")}` + ); +} diff --git a/src/features/katalog/components/universite-icerik.tsx b/src/features/katalog/components/universite-icerik.tsx index 3769ae6..623bd1d 100644 --- a/src/features/katalog/components/universite-icerik.tsx +++ b/src/features/katalog/components/universite-icerik.tsx @@ -30,6 +30,11 @@ import { UniversiteKonumHaritasi } from "./universite-konum-haritasi"; import { uniUlkeKonum } from "@/lib/harita-ulkeler"; import { UniversiteProgramTablosu } from "./universite-program-tablosu"; import { VeriKaynagi } from "./veri-kaynagi"; +import { + URAP_DONEM, + URAP_KAYNAK_URL, + URAP_TOPLAM, +} from "@/lib/urap-siralama"; import { UniLogo } from "@/components/uni-logo"; import { uniLogoYolu } from "@/lib/uni-logolar"; import { Skeleton } from "@/components/ui/skeleton"; @@ -109,6 +114,48 @@ function fakulteOzeti({ return `${adlar[0]}, ${adlar[1]} ve ${adlar.length - 2} birim daha`; } +/** + * Tablonun altındaki AYRI ikinci kaynak satırı. `VeriKaynagi` kullanılmaz ve + * kopyalanmaz: o satır YÖK Atlas'ın yerleştirme yılına ve son güncelleme + * tarihine bağlı, URAP'ın dönemi başka — aynı satırda birleşirlerse URAP + * verisi YÖK Atlas tarihiyle sunulmuş olur. + * + * Atıf pazarlık dışı: URAP'ın izni "urapcenter.org adresine aktif bağlantı" + * şartına bağlı, o yüzden gerçek , yeni sekme, rel="noopener" ve + * nofollow YOK. Sıra payda ("198 üniversite arasında") ve dönem olmadan + * gösterilmez. URAP listesinde olmayan üniversitede sayı yoktur; eksiklik + * gizlenmez, nedeni tek cümleyle yazılır. + */ +function UrapKaynakSatiri({ uni }: { uni: UniDetay }) { + if (!uni.urap) { + const yurtDisi = + uni.unitur === "KKTC" || uni.unitur?.startsWith("YURTDISI"); + return ( +

+ {yurtDisi + ? "Bu üniversite URAP Türkiye sıralamasında yer almıyor — URAP yalnız Türkiye'deki üniversiteleri sıralıyor." + : `Bu üniversite URAP Türkiye Sıralaması ${URAP_DONEM} listesinde yer almıyor.`} +

+ ); + } + return ( +

+ URAP Türkiye Sıralaması {URAP_DONEM} ({sayi(URAP_TOPLAM)} üniversite + arasında) — akademik yayın ve araştırma performansını ölçer; eğitim + kalitesini ya da iş bulma oranını ölçmez. Kaynak:{" "} + + urapcenter.org + + . +

+ ); +} + export function uniSayfaMetadata(slug: string, sayfa: number): Metadata { const uni = getUniversiteBySlug(slug); if (!uni) return {}; @@ -308,17 +355,37 @@ export function UniversiteIcerik({ {sayi(uni.fakulteSayisi)} + {/* URAP'ta olan üniversitede "Tür" kartının yeri URAP'a + bırakılır (kart sayısı 4'te kalır, ızgara şablonu değişmez); + olmayanda "Tür" yerinde durur — hiçbir sayfada boş kutu yok. + Payda kartın içindedir: "18." tek başına yanıltır. */}
-
- Tür -
-
- {uni.unitur === "DEVLET" - ? "Devlet" - : uni.unitur - ? trBaslikDuzeni(uni.unitur) - : "—"} -
+ {uni.urap ? ( + <> +
+ URAP Türkiye +
+
+ {sayi(uni.urap.sira)} / {sayi(URAP_TOPLAM)} + + {URAP_DONEM} + +
+ + ) : ( + <> +
+ Tür +
+
+ {uni.unitur === "DEVLET" + ? "Devlet" + : uni.unitur + ? trBaslikDuzeni(uni.unitur) + : "—"} +
+ + )}
@@ -371,6 +438,8 @@ export function UniversiteIcerik({ veya o yıl yerleşen çıkmayan program).{" "} + {ilkSayfa ? : null} + u.slug === slug)!; return { ...ozet, + urap: urapSirasiBul(slug), fakulteler: [...gruplar.entries()] .map(([fakulte, programlar]) => ({ fakulte, programlar })) .sort((a, b) => a.fakulte.localeCompare(b.fakulte, "tr-TR")),