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:
bilalgursen
2026-10-05 01:17:01 +03:00
parent 22ac604233
commit 0a11b15304
4 changed files with 55 additions and 16 deletions

View File

@@ -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,

View File

@@ -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 }),