Yalnız kullanıcıya görünen etiket değişir; iç anahtar, tip, DB değeri, API parametresi, mermaid classDef ve analitik değeri `garanti` olarak kalır (veri göçü yok). - risk.ts: tek kaynak DILIM_ETIKET + dilimdenFarkliRiskEtiketi; rapor listesi, yazdır tablosu, /sonuc sekmeleri, seçimlerim paneli ve meraklısına şeridi buradan okur - "Güvenli · Güvenli" / "Güvenli (Güvenli)": satır detayında risk etiketi yalnız dilimin varsayılanından farklıysa, yazdır ve seçimlerimde yalnız kelime farklıysa yazılır - LLM prompt'ları: `garanti` teknik anahtar, adaya "güvenli" denir sözlüğü (rapor, soru, tadımlık); liste özeti modele görünen dilim adıyla gider - meraklısına şeması (SEMA düğümü, aria-label), 2. bölüm anlatımı ve AGENTS.md şema kuralı görünen adla eşitlendi - "yerleşme garantisi vermez" türü vaat reddi cümleleri aynen kaldı Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
131 lines
4.6 KiB
TypeScript
131 lines
4.6 KiB
TypeScript
import { kategoriEslesir } from "./kategoriler";
|
||
import { DILIM_ETIKET, riskHesapla, type RiskSeviyesi } from "./risk";
|
||
import type { TercihProfili } from "@/features/sihirbaz/sihirbaz-sabitler";
|
||
|
||
export type DegerlendirilecekProgram = {
|
||
isim: string;
|
||
il: string | null;
|
||
unitur?: string | null;
|
||
efektifSira: number | null;
|
||
};
|
||
|
||
export type TercihDegerlendirmesi = {
|
||
risk: RiskSeviyesi | null;
|
||
/** Görünen dilim adı (DILIM_ETIKET) ya da "Veri yetersiz". */
|
||
riskEtiketi: string;
|
||
riskMetni: string;
|
||
olumlu: string[];
|
||
celiskiler: string[];
|
||
};
|
||
|
||
function normalize(deger: string): string {
|
||
return deger.trim().toLocaleUpperCase("tr-TR");
|
||
}
|
||
|
||
export function tercihDegerlendir(
|
||
program: DegerlendirilecekProgram,
|
||
profil: TercihProfili,
|
||
): TercihDegerlendirmesi {
|
||
const risk = riskHesapla(program.efektifSira, profil.sira);
|
||
const olumlu: string[] = [];
|
||
const celiskiler: string[] = [];
|
||
|
||
// Manuel liste satırında fakülte taşınmıyor (ProgramListeSatiri bilinçli
|
||
// omit ediyor); eşleşme yalnızca isim kurallarıyla yapılır.
|
||
if (kategoriEslesir(program.isim, profil.secimler.kategoriler)) {
|
||
olumlu.push("İlgi alanlarınla uyumlu");
|
||
} else {
|
||
celiskiler.push("Seçtiğin ilgi alanlarının dışında görünüyor");
|
||
}
|
||
|
||
if (profil.secimler.iller.length > 0) {
|
||
const seciliIller = new Set(profil.secimler.iller.map(normalize));
|
||
if (program.il && seciliIller.has(normalize(program.il))) {
|
||
olumlu.push("Tercih ettiğin şehirlerden birinde");
|
||
} else {
|
||
celiskiler.push("Tercih ettiğin şehirlerin dışında");
|
||
}
|
||
}
|
||
|
||
if (profil.secimler.universiteTipi !== "farketmez" && program.unitur) {
|
||
const devlet = normalize(program.unitur) === "DEVLET";
|
||
const uyuyor =
|
||
(profil.secimler.universiteTipi === "devlet" && devlet) ||
|
||
(profil.secimler.universiteTipi === "vakif" && !devlet);
|
||
if (uyuyor) olumlu.push("Üniversite türü tercihine uyuyor");
|
||
else celiskiler.push("Üniversite türü tercihinle uyuşmuyor");
|
||
}
|
||
|
||
if (profil.secimler.oncelikler.includes("Kolay yerleşme")) {
|
||
if (risk === "guvenli") {
|
||
olumlu.push("Daha güvenli seçenek önceliğini destekliyor");
|
||
} else if (risk === "riskli") {
|
||
celiskiler.push("Kolay yerleşme önceliğine göre iddialı bir seçim");
|
||
}
|
||
}
|
||
|
||
const riskEtiketi =
|
||
risk === "riskli"
|
||
? DILIM_ETIKET.hayal
|
||
: risk === "az-riskli"
|
||
? DILIM_ETIKET.dengeli
|
||
: risk === "guvenli"
|
||
? DILIM_ETIKET.garanti
|
||
: "Veri yetersiz";
|
||
const riskMetni =
|
||
risk === "riskli"
|
||
? "Geçen yılın taban sıralaması senin sıralamandan daha yukarıda."
|
||
: risk === "az-riskli"
|
||
? "Geçmiş taban sıralamasına göre dengeli aralıkta."
|
||
: risk === "guvenli"
|
||
? "Geçmiş taban sıralamasına göre daha güvenli aralıkta."
|
||
: "Yerleşme riskini hesaplamak için yeterli taban sıra verisi yok.";
|
||
|
||
return {
|
||
risk,
|
||
riskEtiketi,
|
||
riskMetni,
|
||
olumlu: olumlu.slice(0, 3),
|
||
celiskiler: celiskiler.slice(0, 2),
|
||
};
|
||
}
|
||
|
||
export function tercihListesiOzeti(
|
||
programlar: DegerlendirilecekProgram[],
|
||
profil: TercihProfili,
|
||
) {
|
||
const degerlendirmeler = programlar.map((p) => tercihDegerlendir(p, profil));
|
||
const hayal = degerlendirmeler.filter((d) => d.risk === "riskli").length;
|
||
const dengeli = degerlendirmeler.filter(
|
||
(d) => d.risk === "az-riskli",
|
||
).length;
|
||
const dahaGuvenli = degerlendirmeler.filter(
|
||
(d) => d.risk === "guvenli",
|
||
).length;
|
||
const dikkat = degerlendirmeler.filter(
|
||
(d) => d.celiskiler.length > 0,
|
||
).length;
|
||
const gucluUyum = degerlendirmeler.filter(
|
||
(d) => d.olumlu.length >= 2 && d.celiskiler.length === 0,
|
||
).length;
|
||
|
||
let oneri = "Yeni seçimler ekledikçe listenin dengesi burada görünecek.";
|
||
if (programlar.length > 0 && dahaGuvenli === 0) {
|
||
oneri =
|
||
"Listen iddialı seçeneklerde yoğunlaşıyor. Birkaç daha güvenli program eklemek riski dağıtabilir.";
|
||
} else if (programlar.length > 2 && dengeli === 0) {
|
||
oneri =
|
||
"Listen için dengeli aralıkta birkaç program eklemek seçeneklerini güçlendirebilir.";
|
||
} else if (dikkat > Math.max(1, programlar.length / 2)) {
|
||
oneri =
|
||
"Seçtiklerinin çoğu profilinle ayrışıyor. Dikkat notlarını birlikte gözden geçir.";
|
||
} else if (programlar.length >= 24) {
|
||
oneri =
|
||
"24 tercihe ulaştın. Şimdi risk dağılımını ve dikkat notlarını gözden geçir.";
|
||
} else if (programlar.length > 0) {
|
||
oneri = "Listen dengeleniyor; uyum ve risk dağılımını koruyarak ilerle.";
|
||
}
|
||
|
||
return { hayal, dengeli, dahaGuvenli, dikkat, gucluUyum, oneri };
|
||
}
|