Files
kolaytercih/scripts/eval/varyant-denetim.ts
bilalgursen 5c583ac8b4 feat(veri): Program.varyant — burs/dil/öğretim türü etiketi tek kaynaktan (program_ozellik)
programs.isim burs/dil varyantını taşımıyor (Başkent Tıp 6 satırda da
"Tıp"); ayırt edici alanlar program_ozellik.burs_orani / ogrenim_dili /
ogrenim_turu. SELECT_COLS üç ilişkili alt sorgu kazanır, programSatiri
varyantEtiketi ile "Burslu · İngilizce" gibi tek etiket üretir; devlet /
Türkçe / örgün programda null. Havuz JSON'una da girer: model aynı adlı
satırları ayırt edebilsin.

Tablo yokluğu koruması bilinçli yok: data/yokatlas.db depoda ve Docker
seed'inde (Dockerfile) program_ozellik tablosuyla geliyor. programs_arsiv
sorguları dokunulmadı (arşivde özellik yok).

Test: pnpm tsx scripts/eval/varyant-denetim.ts (salt okur, çıkış 0).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-07 23:12:03 +03:00

80 lines
3.4 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.
/**
* Program varyant etiketinin MEKANİK testi — parasız, anahtarsız, salt okur.
*
* pnpm tsx scripts/eval/varyant-denetim.ts
*
* react-server koşulu gerekmez: db.ts ve program-varyant.ts saf/sqlite.
* Doğrulananlar: (1) varyantEtiketi birim kuralları, (2) Başkent Tıp'ın 6
* satırının etiketleri birbirinden farklı ve hiçbiri null, (3) dilimAra'nın
* döndürdüğü her satırda `varyant` tanımlı (SELECT_COLS tüm yolu kapsıyor),
* (4) devlet/Türkçe/örgün programda null. data/yokatlas.db'ye yazılmaz.
* Beklenti tutmazsa çıkış kodu 1.
*/
import { dilimAra, programGetir } from "../../src/lib/db";
import { varyantEtiketi, type VaryantGirdisi } from "../../src/lib/program-varyant";
let hata = 0;
function bekle(ad: string, kosul: boolean, detay = ""): void {
console.log(`${kosul ? "✔" : "✘"} ${ad}${detay ? ` — ${detay}` : ""}`);
if (!kosul) hata++;
}
// 1. Birim: etiket kuralları
const birim: [VaryantGirdisi, string | null][] = [
[{ bursOrani: "Burslu", ogrenimDili: "İngilizce", ogrenimTuru: "Örgün Öğretim" }, "Burslu · İngilizce"],
[{ bursOrani: null, ogrenimDili: "Türkçe", ogrenimTuru: "Örgün Öğretim" }, null],
[{ bursOrani: "Ücretli", ogrenimDili: "Türkçe", ogrenimTuru: "İkinci Öğretim" }, "Ücretli · İkinci Öğretim"],
[{ bursOrani: "%50 İndirimli", ogrenimDili: null, ogrenimTuru: null }, "%50 İndirimli"],
// DB'de burs_orani boş string de geliyor (devlet); null gibi davranır
[{ bursOrani: "", ogrenimDili: "Türkçe", ogrenimTuru: "Uzaktan Öğretim" }, "Uzaktan Öğretim"],
];
for (const [girdi, beklenen] of birim) {
const sonuc = varyantEtiketi(girdi);
bekle(
`birim ${JSON.stringify(girdi)}`,
sonuc === beklenen,
`beklenen ${JSON.stringify(beklenen)}, gelen ${JSON.stringify(sonuc)}`,
);
}
// 2. Başkent Tıp ×6: isim hepsinde "Tıp", varyant hepsinde farklı
const BASKENT_TIP = ["200610657", "200610666", "200611488", "200690357", "200690358", "200690359"];
const baskent = BASKENT_TIP.map((id) => ({ id, p: programGetir(id) }));
for (const { id, p } of baskent) {
bekle(
`programGetir(${id}) varyant dolu`,
p != null && p.varyant != null,
p ? `${p.universite} / ${p.isim} → ${p.varyant}` : "bulunamadı",
);
}
const etiketler = baskent.map(({ p }) => p?.varyant ?? null);
bekle(
"Başkent Tıp 6 varyant birbirinden farklı",
new Set(etiketler).size === BASKENT_TIP.length,
etiketler.join(" | "),
);
// 3. dilimAra yolu: her satırda varyant tanımlı (string ya da null)
const { programlar } = dilimAra(100000, "say", "dengeli", { limit: 50 });
const tanimsiz = programlar.filter(
(p) => !("varyant" in p) || (p.varyant !== null && typeof p.varyant !== "string"),
);
bekle(
`dilimAra 50 satırda varyant tanımlı (${programlar.length} satır)`,
programlar.length > 0 && tanimsiz.length === 0,
tanimsiz.map((p) => p.id).join(","),
);
const etiketli = programlar.filter((p) => p.varyant).length;
console.log(` (bilgi) dilimAra örneğinde etiketli satır: ${etiketli}/${programlar.length}`);
// 4. Devlet / Türkçe / örgün → null (Marmara Hukuk)
const marmara = programGetir("107210332");
bekle(
"107210332 Marmara Hukuk varyant null",
marmara != null && marmara.varyant === null,
marmara ? `${marmara.universite} / ${marmara.isim} → ${JSON.stringify(marmara.varyant)}` : "bulunamadı",
);
console.log(hata === 0 ? "\nVaryant denetimi: TEMİZ" : `\nVaryant denetimi: ${hata} hata`);
process.exit(hata === 0 ? 0 : 1);