fix(havuz): B2 — başarı sırası barajını geçemeyen adaya o bölüm önerilmesin [KARAR]
Havuz yalnız taban sırasına bakıyordu; hayal dilimi "adayın üstünde kapanan her şey" olduğu için barajın hemen dışındaki adaya tam da yazamayacağı bölümler düşüyordu (52.000 sıralı adaya tıp, 310.000'e mühendislik). Kaynak uydurma tablo değil: program_ozellik.min_basari_sirasi (YÖK Atlas API, 2026 kılavuzu; katalogdaki "baraj … sıra" satırı ve danışmanın tercihBaraji alanı da aynı kolonu okur). db.havuzAdaylari artık min_basari_sirasi < adayın sırası olan programları SQL'de çıkarır; barajı boş program süzülmez. Kanıt (havuzdaki baraj dışı program, önce → sonra): a04 4 → 0, a06 11 → 0, a08 11 → 0, p03 17 → 0; 40 profilin hepsinde 0. a07 (SÖZ 310.000, eğitim): alandaki programların tamamı barajlı olduğu için alan artık gerçekten gevşiyor (24 hayal → 5/13/6). Bilinen sınır: kolon bazı barajlı bölümlerde boş (ör. 16 tıp, 11 hukuk satırı) — veri işi, raporda. /meraklisina şeması (aday havuzu düğümü), 4. bölüm anlatımı, aria-label ve figcaption aynı kuralla güncellendi. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
@@ -89,6 +89,16 @@ export type OzellikSuzgeci = {
|
||||
|
||||
let ozellikTablosuVar: boolean | null = null;
|
||||
|
||||
function ozellikTablosuVarMi(): boolean {
|
||||
if (ozellikTablosuVar == null) {
|
||||
ozellikTablosuVar =
|
||||
getDb()
|
||||
.prepare("SELECT 1 FROM sqlite_master WHERE type='table' AND name='program_ozellik'")
|
||||
.get() !== undefined;
|
||||
}
|
||||
return ozellikTablosuVar;
|
||||
}
|
||||
|
||||
function ozellikFiltreSql(o?: OzellikSuzgeci): { sql: string; args: (string | number)[] } {
|
||||
if (!o) return { sql: "", args: [] };
|
||||
const kosul: string[] = [];
|
||||
@@ -104,19 +114,27 @@ function ozellikFiltreSql(o?: OzellikSuzgeci): { sql: string; args: (string | nu
|
||||
args.push(o.ucretUst);
|
||||
}
|
||||
if (kosul.length === 0) return { sql: "", args: [] };
|
||||
if (ozellikTablosuVar == null) {
|
||||
ozellikTablosuVar =
|
||||
getDb()
|
||||
.prepare("SELECT 1 FROM sqlite_master WHERE type='table' AND name='program_ozellik'")
|
||||
.get() !== undefined;
|
||||
}
|
||||
if (!ozellikTablosuVar) return { sql: "", args: [] };
|
||||
if (!ozellikTablosuVarMi()) return { sql: "", args: [] };
|
||||
return {
|
||||
sql: `AND id IN (SELECT id FROM program_ozellik WHERE ${kosul.join(" AND ")})`,
|
||||
args,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Başarı sırası barajı: `program_ozellik.min_basari_sirasi` programı tercih
|
||||
* edebilmek için gereken en düşük sıradır (YÖK Atlas'tan, kılavuz yılına ait;
|
||||
* ör. tıp 50.000). Adayın sırası bundan kötüyse o programı yazamaz. Barajı
|
||||
* boş olan program (barajsız ya da veride eksik) süzülmez.
|
||||
*/
|
||||
function barajFiltreSql(sira: number): { sql: string; args: number[] } {
|
||||
if (!ozellikTablosuVarMi()) return { sql: "", args: [] };
|
||||
return {
|
||||
sql: "AND id NOT IN (SELECT id FROM program_ozellik WHERE min_basari_sirasi < ?)",
|
||||
args: [sira],
|
||||
};
|
||||
}
|
||||
|
||||
function uniturFiltreSql(grup?: UniturGrubu): { sql: string; args: string[] } {
|
||||
if (grup === "devlet") return { sql: "AND unitur = ?", args: ["DEVLET"] };
|
||||
if (grup === "vakif")
|
||||
@@ -155,6 +173,8 @@ export function dilimAra(
|
||||
iller?: string[];
|
||||
uniturGrubu?: UniturGrubu;
|
||||
ozellik?: OzellikSuzgeci;
|
||||
/** Adayın sırasıyla yazamayacağı (baraj dışı) programları çıkar */
|
||||
barajDisiHaric?: boolean;
|
||||
limit?: number;
|
||||
offset?: number;
|
||||
} = {}
|
||||
@@ -176,16 +196,27 @@ export function dilimAra(
|
||||
: "";
|
||||
const unitur = uniturFiltreSql(opts.uniturGrubu);
|
||||
const ozellik = ozellikFiltreSql(opts.ozellik);
|
||||
const baraj = opts.barajDisiHaric
|
||||
? barajFiltreSql(sira)
|
||||
: { sql: "", args: [] };
|
||||
|
||||
const { alt, ust } = dilimAraligi(sira, dilim);
|
||||
if (ust != null && ust < alt) return { programlar: [], toplam: 0 };
|
||||
const siraKosulu =
|
||||
ust != null ? `${EFEKTIF_SIRA} BETWEEN ? AND ?` : `${EFEKTIF_SIRA} >= ?`;
|
||||
const siraArgs = ust != null ? [alt, ust] : [alt];
|
||||
const args = [tur, onlisans, ...illerListe, ...unitur.args, ...ozellik.args, ...siraArgs];
|
||||
const args = [
|
||||
tur,
|
||||
onlisans,
|
||||
...illerListe,
|
||||
...unitur.args,
|
||||
...ozellik.args,
|
||||
...baraj.args,
|
||||
...siraArgs,
|
||||
];
|
||||
|
||||
const base = `FROM programs
|
||||
WHERE tur = ? AND onlisans = ? ${ilFiltre} ${unitur.sql} ${ozellik.sql}
|
||||
WHERE tur = ? AND onlisans = ? ${ilFiltre} ${unitur.sql} ${ozellik.sql} ${baraj.sql}
|
||||
AND ${EFEKTIF_SIRA} IS NOT NULL
|
||||
AND ${siraKosulu}`;
|
||||
// hayal: sınıra en yakın (en büyük taban) önce; diğerleri en yakından uzağa
|
||||
@@ -246,6 +277,7 @@ export function searchByRank(
|
||||
* alandan karışık geldiği için seçilen alan olduğundan az görünüyordu. Bu
|
||||
* yüzden havuz dilimin tamamını alır, alan/il süzgecini kendisi uygular ve
|
||||
* en son kırpar (bkz. lib/rapor-havuzu.ts). En büyük puan türü ~9 bin satır.
|
||||
* Adayın başarı sırası barajını geçemediği programlar buraya hiç girmez.
|
||||
*/
|
||||
export function havuzAdaylari(
|
||||
sira: number,
|
||||
@@ -253,7 +285,7 @@ export function havuzAdaylari(
|
||||
opts: { uniturGrubu?: UniturGrubu; ozellik?: OzellikSuzgeci } = {}
|
||||
): Record<DilimKey, Program[]> {
|
||||
// LIMIT -1: SQLite'ta "sınırsız"
|
||||
const ortak = { ...opts, limit: -1 };
|
||||
const ortak = { ...opts, barajDisiHaric: true, limit: -1 };
|
||||
return {
|
||||
hayal: dilimAra(sira, turKey, "hayal", ortak).programlar,
|
||||
dengeli: dilimAra(sira, turKey, "dengeli", ortak).programlar,
|
||||
|
||||
@@ -214,6 +214,9 @@ function dilimEkle(r: {
|
||||
* "24'ten az" kararı o alanda/ilde gerçekten kaç program olduğuna bakar.
|
||||
* Bir filtre gevşediğinde ona uyan programlar havuzdan düşmez: önce onlar
|
||||
* alınır, boşluk sıraya en yakın diğer programlarla dolar.
|
||||
*
|
||||
* Adayın yazamayacağı programlar hiçbir basamakta havuza girmez: başarı
|
||||
* sırası barajının gerisinde kaldığı bölümler ve özel kontenjan satırları.
|
||||
*/
|
||||
export function havuzOlustur(
|
||||
params: RaporParams,
|
||||
@@ -242,7 +245,8 @@ export function havuzOlustur(
|
||||
// Bırakmazsa profil gevşetilir ve aşağıdaki sihirbaz akışı aynen sürer;
|
||||
// liste yine kurulur, gevşetme yapay zekâya ve adaya söylenir.
|
||||
const suzgec = profilSuzgeci(profil, iller.length > 0);
|
||||
// Dilimin tamamı; özel kontenjan satırları (KKTC uyruklu, M.T.O.K.) hariç
|
||||
// Dilimin tamamı; adayın barajını geçemediği programlar (SQL) ve özel
|
||||
// kontenjan satırları (KKTC uyruklu, M.T.O.K.) hariç
|
||||
const adaylar = (ozellik?: OzellikSuzgeci) =>
|
||||
dilimEkle(
|
||||
havuzAdaylari(params.sira, params.tur, { uniturGrubu, ozellik }),
|
||||
|
||||
Reference in New Issue
Block a user