import "server-only"; // Ana sayfadaki iki etkileşimli parçanın verisi (sunucuda, build/istek anında): // - Kart destesi demosu (DESIGN.md §4.27): örnek bir sıralamaya göre GERÇEK // programlar. Uydurma taban sıralaması gösterilmez; veri okunamazsa bölüm // hiç çizilmez. // - Süzülen haplar (§4.30): yalnız katalogda sayfası olan bölüm ve şehirler. import { dilimAra } from "@/lib/db"; import { bolumSlugFromIsim, getIlBySlug } from "@/lib/katalog"; import { ozelKontenjanSatiriMi } from "@/lib/rapor-havuzu"; import { riskHesapla, type RiskSeviyesi } from "@/lib/risk"; import { bolumBazAdi, ilSayfaHref, trBaslikDuzeni, turkishSlugify } from "@/lib/slug"; import type { DilimKey } from "@/types/yokatlas"; /** Demonun örnek öğrencisi: Sayısal, 85.000. sıra (§10.1'deki örnekle aynı). */ export const ORNEK_SIRA = 85_000; const ORNEK_TUR = "say" as const; export interface OrnekProgram { id: string; isim: string; universite: string; il: string | null; tabanSira: number; risk: RiskSeviyesi; } /** * Her dilimden birkaç program: sınıra yapışık olanlar yerine dilimin içine * yayılmış (riskli / az riskli / güvenli farkı kartta görünsün), her üniversite * ve her bölüm adı en çok bir kez. */ export function ornekProgramlar(): OrnekProgram[] { try { const gorulenUni = new Set(); const gorulenBolum = new Set(); const sec = (dilim: DilimKey, adet: number, adim: number): OrnekProgram[] => { const { programlar } = dilimAra(ORNEK_SIRA, ORNEK_TUR, dilim, { uniturGrubu: "devlet", barajDisiHaric: true, limit: 600, }); const secilen: OrnekProgram[] = []; for (let i = adim; i < programlar.length && secilen.length < adet; i += adim) { const p = programlar[i]; const bolum = bolumBazAdi(p.isim); const risk = riskHesapla(p.efektifSira, ORNEK_SIRA); if ( p.efektifSira == null || !risk || ozelKontenjanSatiriMi(p.isim) || /\(/.test(p.isim) || gorulenUni.has(p.universite) || gorulenBolum.has(bolum) ) { // Elenen satırın bir sonrakine bak; adım bozulmasın diye geri al i -= adim - 1; continue; } gorulenUni.add(p.universite); gorulenBolum.add(bolum); secilen.push({ id: p.id, isim: p.isim, universite: trBaslikDuzeni(p.universite), il: p.il ? trBaslikDuzeni(p.il) : null, tabanSira: p.efektifSira, risk, }); } return secilen; }; const hayal = sec("hayal", 2, 60); const dengeli = sec("dengeli", 3, 45); const guvenli = sec("garanti", 2, 90); // Sıra karışık: aynı risk art arda gelmesin return [dengeli[0], hayal[0], guvenli[0], dengeli[1], hayal[1], dengeli[2], guvenli[1]].filter( (p): p is OrnekProgram => Boolean(p), ); } catch { return []; } } export interface KatalogHapi { etiket: string; href: string; tur: "bolum" | "sehir"; } const HAP_BOLUMLERI = [ "Tıp", "Hukuk", "Bilgisayar Mühendisliği", "Psikoloji", "Diş Hekimliği", "Hemşirelik", "Mimarlık", "Yazılım Mühendisliği", "Eczacılık", "İşletme", ]; const HAP_SEHIRLERI = ["İstanbul", "Ankara", "İzmir", "Eskişehir", "Bursa", "Antalya"]; /** Bölüm ve şehir hapları; katalogda karşılığı olmayan ad sessizce düşer. */ export function katalogHaplari(): KatalogHapi[] { try { const bolumler: KatalogHapi[] = HAP_BOLUMLERI.flatMap((ad) => { const slug = bolumSlugFromIsim(ad); return slug ? [{ etiket: ad, href: `/bolum/${slug}`, tur: "bolum" as const }] : []; }); const sehirler: KatalogHapi[] = HAP_SEHIRLERI.flatMap((ad) => getIlBySlug(turkishSlugify(ad)) ? [{ etiket: ad, href: ilSayfaHref(ad), tur: "sehir" as const }] : [], ); // Bölüm ve şehir karışık dizilsin: her üç bölümden sonra bir şehir const sonuc: KatalogHapi[] = []; let s = 0; bolumler.forEach((b, i) => { sonuc.push(b); if (i % 2 === 1 && s < sehirler.length) sonuc.push(sehirler[s++]); }); return [...sonuc, ...sehirler.slice(s)]; } catch { return []; } }