feat(veri): program_ozellik tablosu — YÖK Atlas API'den ücret, burs, dil, öğretim türü, akreditasyon, kadro, baraj, ilçe, koşullar
scripts/program-ozellik.ts (pnpm ozellik --yil --db [--ham]) API'nin kılavuz alanlarını program_ozellik ve kosul tablolarına yazar; 25 Eyl 2026 çekimi: 21.493 program, 194 koşul metni. src/lib/program-ozellik.ts okuyucu + öğrenciye okunan kısa özet. Tablo yoksa okuma boş döner. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
137
src/lib/program-ozellik.ts
Normal file
137
src/lib/program-ozellik.ts
Normal file
@@ -0,0 +1,137 @@
|
||||
// Program özellikleri: YÖK Atlas API'sinden scripts/program-ozellik.ts ile
|
||||
// `program_ozellik` ve `kosul` tablolarına yazılan, yıl anlamı olmayan alanlar
|
||||
// (ücret, burs, dil, öğretim türü, akreditasyon, kadro, baraj, ilçe, koşullar).
|
||||
// Sıra/puan/kontenjan gibi yıllık alanlar burada DEĞİL (bkz. db.ts).
|
||||
import { getDb } from "./db";
|
||||
|
||||
export type ProgramOzellik = {
|
||||
id: string;
|
||||
/** Vakıf/KKTC yıllık öğrenim ücreti (TL, KDV dahil, kılavuz yılı); devlette null */
|
||||
ucret: number | null;
|
||||
/** "Burslu" | "%50 İndirimli" | "%25 İndirimli" | "Ücretli"; devlette null */
|
||||
bursOrani: string | null;
|
||||
/** "Türkçe" | "İngilizce" | "İngilizce (%30)" | "Almanca" … */
|
||||
ogrenimDili: string | null;
|
||||
/** "Örgün Öğretim" | "Uzaktan Öğretim" | "Açık Öğretim" | "UOLP" */
|
||||
ogrenimTuru: string | null;
|
||||
/** Program akreditasyonu (MÜDEK, TEPDAD, FEDEK …) */
|
||||
akreditasyon: string | null;
|
||||
/** Üniversite akreditasyonu (YÖKAK …) */
|
||||
uniAkreditasyon: string | null;
|
||||
prof: number | null;
|
||||
doc: number | null;
|
||||
dou: number | null;
|
||||
argor: number | null;
|
||||
/** Tercih edebilmek için gereken en düşük başarı sırası (baraj) */
|
||||
minBasariSirasi: number | null;
|
||||
/** Kampüs ilçesi (büyük harf, API'den) */
|
||||
ilce: string | null;
|
||||
/** Yerleşme koşulu kodları (kosul tablosundan metne çevrilir) */
|
||||
kosulKodlari: string[];
|
||||
/** Kılavuz yılı */
|
||||
yil: number;
|
||||
};
|
||||
|
||||
type HamSatir = {
|
||||
id: string;
|
||||
ucret: number | null;
|
||||
burs_orani: string | null;
|
||||
ogrenim_dili: string | null;
|
||||
ogrenim_turu: string | null;
|
||||
akreditasyon: string | null;
|
||||
uni_akreditasyon: string | null;
|
||||
prof: number | null;
|
||||
doc: number | null;
|
||||
dou: number | null;
|
||||
argor: number | null;
|
||||
min_basari_sirasi: number | null;
|
||||
ilce: string | null;
|
||||
kosul_kodlari: string | null;
|
||||
yil: number;
|
||||
};
|
||||
|
||||
const OZELLIK_COLS = `id, ucret, burs_orani, ogrenim_dili, ogrenim_turu, akreditasyon,
|
||||
uni_akreditasyon, prof, doc, dou, argor, min_basari_sirasi, ilce, kosul_kodlari, yil`;
|
||||
|
||||
function satir(r: HamSatir): ProgramOzellik {
|
||||
return {
|
||||
id: r.id,
|
||||
ucret: r.ucret,
|
||||
bursOrani: r.burs_orani,
|
||||
ogrenimDili: r.ogrenim_dili,
|
||||
ogrenimTuru: r.ogrenim_turu,
|
||||
akreditasyon: r.akreditasyon,
|
||||
uniAkreditasyon: r.uni_akreditasyon,
|
||||
prof: r.prof,
|
||||
doc: r.doc,
|
||||
dou: r.dou,
|
||||
argor: r.argor,
|
||||
minBasariSirasi: r.min_basari_sirasi,
|
||||
ilce: r.ilce,
|
||||
kosulKodlari: r.kosul_kodlari ? r.kosul_kodlari.split(",") : [],
|
||||
yil: r.yil,
|
||||
};
|
||||
}
|
||||
|
||||
/** Tablo yoksa (eski DB) her okuma null/boş döner; sayfa kırılmaz. */
|
||||
function tabloVar(): boolean {
|
||||
return (
|
||||
getDb()
|
||||
.prepare("SELECT 1 FROM sqlite_master WHERE type='table' AND name='program_ozellik'")
|
||||
.get() !== undefined
|
||||
);
|
||||
}
|
||||
|
||||
export function programOzellikGetir(id: string): ProgramOzellik | null {
|
||||
if (!tabloVar()) return null;
|
||||
const r = getDb()
|
||||
.prepare(`SELECT ${OZELLIK_COLS} FROM program_ozellik WHERE id = ?`)
|
||||
.get(id) as HamSatir | undefined;
|
||||
return r ? satir(r) : null;
|
||||
}
|
||||
|
||||
export function programOzellikleriGetir(
|
||||
ids: readonly string[]
|
||||
): Record<string, ProgramOzellik> {
|
||||
const sonuc: Record<string, ProgramOzellik> = {};
|
||||
if (ids.length === 0 || !tabloVar()) return sonuc;
|
||||
const satirlar = getDb()
|
||||
.prepare(
|
||||
`SELECT ${OZELLIK_COLS} FROM program_ozellik WHERE id IN (${ids.map(() => "?").join(",")})`
|
||||
)
|
||||
.all(...ids) as HamSatir[];
|
||||
for (const r of satirlar) sonuc[r.id] = satir(r);
|
||||
return sonuc;
|
||||
}
|
||||
|
||||
/** Koşul kodlarının kılavuz metinleri, kod sırasıyla. Bilinmeyen kod atlanır. */
|
||||
export function kosulMetinleri(kodlar: readonly string[]): { kod: string; metin: string }[] {
|
||||
if (kodlar.length === 0 || !tabloVar()) return [];
|
||||
const satirlar = getDb()
|
||||
.prepare(`SELECT kod, metin FROM kosul WHERE kod IN (${kodlar.map(() => "?").join(",")})`)
|
||||
.all(...kodlar) as { kod: string; metin: string }[];
|
||||
const harita = new Map(satirlar.map((s) => [s.kod, s.metin]));
|
||||
return kodlar.flatMap((k) => (harita.has(k) ? [{ kod: k, metin: harita.get(k)! }] : []));
|
||||
}
|
||||
|
||||
/** Kadro toplamı (prof + doç + dr. öğr. üyesi); hiçbiri yoksa null. */
|
||||
export function ogretimUyesiToplami(o: ProgramOzellik): number | null {
|
||||
const parcalar = [o.prof, o.doc, o.dou].filter((x): x is number => x != null);
|
||||
return parcalar.length ? parcalar.reduce((a, b) => a + b, 0) : null;
|
||||
}
|
||||
|
||||
/** Öğrenciye okunan kısa özet: "İngilizce · Burslu · MÜDEK akreditasyonlu". */
|
||||
export function ozellikOzeti(o: ProgramOzellik): string[] {
|
||||
const parcalar: string[] = [];
|
||||
if (o.ogrenimDili && o.ogrenimDili !== "Türkçe") parcalar.push(o.ogrenimDili);
|
||||
if (o.ogrenimTuru && o.ogrenimTuru !== "Örgün Öğretim") parcalar.push(o.ogrenimTuru);
|
||||
if (o.bursOrani) parcalar.push(o.bursOrani);
|
||||
if (o.ucret != null && o.bursOrani !== "Burslu") {
|
||||
parcalar.push(`yıllık ${o.ucret.toLocaleString("tr-TR")} TL`);
|
||||
}
|
||||
if (o.akreditasyon) parcalar.push(`${o.akreditasyon} akreditasyonlu`);
|
||||
if (o.minBasariSirasi != null) {
|
||||
parcalar.push(`baraj ${o.minBasariSirasi.toLocaleString("tr-TR")}. sıra`);
|
||||
}
|
||||
return parcalar;
|
||||
}
|
||||
Reference in New Issue
Block a user