feat(universite): "Tür" kartının yerine URAP Türkiye sırası

/universite/[slug] metrik ızgarasında takas: URAP listesinde olan
üniversitede "Tür" kartının yerini "URAP TÜRKİYE · 18 / 198 ·
2025-2026" alır, olmayan 31 kurumda "Tür" yerinde kalır. Kart sayısı
4'te kalıyor, lg ızgara şablonu değişmiyor, yeni bileşen yok, hiçbir
sayfada "—" ya da delik yok. Payda kartın içinde: "18." tek başına
yanıltır.

Tablonun altına AYRI ikinci kaynak satırı eklendi; VeriKaynagi
kullanılmadı ve kopyalanmadı, çünkü 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.
Satırda metodoloji uyarısı da var: URAP akademik yayın ve araştırma
performansını ölçer, eğitim kalitesini ya da iş bulma oranını ölçmez.
URAP listesinde olmayan üniversitede eksiklik gizlenmiyor, nedeni tek
cümleyle yazılıyor (KKTC/yurt dışı ile MYO/yeni için ayrı cümle).

URAP'ın yayımlama izni "urapcenter.org adresine aktif bağlantı/atıf
vermek" şartına bağlıdır. Kaynak satırındaki bağlantı bu yüzden gerçek
bir <a href>: adres URAP_KAYNAK_URL sabitinden, target="_blank",
rel="noopener", nofollow YOK. Sıranın göründüğü ekran ile atıfın
göründüğü ekran aynı sayfadır; URAP sayısı yalnız ilk sayfada
gösterildiği için kaynak satırı da yalnız ilk sayfada çiziliyor.

Renk yok, rozet yok; URAP risk dili değildir. /universiteler hub'ında
URAP'a göre sıralama/filtre eklenmedi. URAP 24'lük listeye, /sonuc
tablosuna ve LLM prompt'una girmiyor — dokunulan dosya kümesi bunu
zaten dışlıyor.

veri-kalite.ts'e 5 URAP kontrolü (dosyanın en sonunda, tek satırlık
çağrıyla): (1) her URAP slug'ı bir üniversite sayfasına bağlı —
eşleşmeyen sessizce düşmüyor, adıyla listeleniyor; (2) kayıt sayısı =
URAP_TOPLAM; (3) sıralar 1..N tekrarsız ve boşluksuz; (4) puanlar
sıraya göre azalan; (5) kapsama boşluğu — URAP dışında kalan 150+
programlı bir Türkiye üniversitesi varsa UYARI (ad değişikliği
işareti). Beşi de geçiyor, boşluk 31 kurum.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
bilalgursen
2026-09-23 00:21:36 +03:00
parent 68cb69e458
commit 493267122f
3 changed files with 175 additions and 10 deletions

View File

@@ -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<string, { unitur: string | null; program: number }>();
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(", ")}`
);
}

View File

@@ -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 <a href>, 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 (
<p className="mt-2 text-xs leading-5 text-slate-500">
{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.`}
</p>
);
}
return (
<p className="mt-2 text-xs leading-5 text-slate-500">
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:{" "}
<a
href={URAP_KAYNAK_URL}
target="_blank"
rel="noopener"
className="font-medium text-primary hover:underline"
>
urapcenter.org
</a>
.
</p>
);
}
export function uniSayfaMetadata(slug: string, sayfa: number): Metadata {
const uni = getUniversiteBySlug(slug);
if (!uni) return {};
@@ -308,7 +355,25 @@ export function UniversiteIcerik({
{sayi(uni.fakulteSayisi)}
</dd>
</div>
{/* 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. */}
<div className="rounded-xl border border-slate-200 bg-white p-4">
{uni.urap ? (
<>
<dt className="text-xs font-medium uppercase tracking-wide text-slate-500">
URAP Türkiye
</dt>
<dd className="mt-1 font-heading text-2xl font-bold text-slate-900">
{sayi(uni.urap.sira)} / {sayi(URAP_TOPLAM)}
<span className="mt-0.5 block font-sans text-xs font-medium text-slate-500">
{URAP_DONEM}
</span>
</dd>
</>
) : (
<>
<dt className="text-xs font-medium uppercase tracking-wide text-slate-500">
Tür
</dt>
@@ -319,6 +384,8 @@ export function UniversiteIcerik({
? trBaslikDuzeni(uni.unitur)
: "—"}
</dd>
</>
)}
</div>
<div className="rounded-xl border border-slate-200 bg-white p-4">
<dt className="text-xs font-medium uppercase tracking-wide text-slate-500">
@@ -371,6 +438,8 @@ export function UniversiteIcerik({
veya o yıl yerleşen çıkmayan program).{" "}
</VeriKaynagi>
{ilkSayfa ? <UrapKaynakSatiri uni={uni} /> : null}
<Sayfalama
tabanYol={`/universite/${slug}`}
sayfa={sayfa}

View File

@@ -10,6 +10,7 @@ import type { Program } from "@/types/yokatlas";
import { kategoriBul, type Kategori } from "./kategoriler";
import { uniAdiNormalize } from "./harita";
import { bolumBazAdi, turkishSlugify, trBaslikDuzeni } from "./slug";
import { urapSirasiBul, type UrapSira } from "./urap-siralama";
/**
* Programatik SEO sayfalarının veri katmanı (/bolum, /universite, hub'lar).
@@ -224,6 +225,11 @@ export type UniOzet = {
};
export type UniDetay = UniOzet & {
/**
* URAP Türkiye genel sıralaması; listede olmayan üniversitede null.
* Gösterildiği her yüzeyde URAP_KAYNAK_URL'ye aktif atıf zorunludur.
*/
urap: UrapSira | null;
fakulteler: { fakulte: string; programlar: Program[] }[];
stats: {
minSira: number | null;
@@ -393,6 +399,7 @@ export function getUniversiteBySlug(slug: string): UniDetay | null {
const ozet = getAllUniversiteler().find((u) => 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")),