Files
kolaytercih/src/lib/tercih-degerlendirme.ts
bilalgursen 5853b7d091 feat(etiket): görünen "Garanti" dilim adı site genelinde "Güvenli"
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>
2026-09-21 16:03:22 +03:00

131 lines
4.6 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.
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 };
}