// Kayıtlı listenin üretildiği tercihler (rapor params) ile kullanıcının şu // anki tercih profilini karşılaştırır. /listem başlığındaki "Tercihlerin // değişmiş" butonu ve açtığı güncelleme modalı bu farktan doğar. // // İzomorfik: yalnızca tip ve etiket sabitlerine bağlı — hem client bileşeni // hem sunucu tarafı tüketebilir. // // Eski akışla üretilmiş raporlarda sihirbaz alanları (kategoriler/iller/ // universiteTipi/oncelikler) hiç yok. Olmayan alan "değişmiş" sayılmaz: // kıyaslanacak bir değer yokken kullanıcıyı 3 kredilik güncellemeye // çağırmak dürüst olmaz. Sıralama ve puan türü her raporda dolu olduğundan // onlar her zaman kıyaslanır. import { PUAN_TURU_ETIKET, UNIVERSITE_TIPI_ETIKET, oncelikNormalize, type TercihProfili, } from "@/features/sihirbaz/sihirbaz-sabitler"; import type { RaporParams } from "./types/rapor"; export type FarkAlani = | "sira" | "tur" | "kategoriler" | "iller" | "universiteTipi" | "oncelikler"; export const FARK_ETIKET: Record = { sira: "başarı sıralaman", tur: "puan türün", kategoriler: "ilgi alanların", iller: "şehir tercihlerin", universiteTipi: "devlet/vakıf tercihin", oncelikler: "önceliklerin", }; // Sıra bağımsız küme kıyası: sihirbaz seçimleri tekrarsız olarak doğrulanır // (bkz. sihirbazDogrula), aynı seçimlerin farklı sırayla kaydedilmesi // "değişiklik" değildir. function kumeFarkli( eski: readonly string[] | undefined, yeni: readonly string[], ): boolean { if (!eski) return false; if (eski.length !== yeni.length) return true; const kume = new Set(eski); return yeni.some((x) => !kume.has(x)); } function liste(degerler: readonly string[] | undefined): string { return degerler && degerler.length > 0 ? degerler.join(", ") : "—"; } export function tercihFarki( params: RaporParams, profil: TercihProfili, ): FarkAlani[] { const farklar: FarkAlani[] = []; const s = profil.secimler; if (Math.round(params.sira) !== Math.round(profil.sira)) farklar.push("sira"); if (params.tur !== profil.tur) farklar.push("tur"); if (kumeFarkli(params.kategoriler, s.kategoriler)) farklar.push("kategoriler"); if (kumeFarkli(params.iller, s.iller)) farklar.push("iller"); if ( params.universiteTipi !== undefined && params.universiteTipi !== s.universiteTipi ) { farklar.push("universiteTipi"); } if (kumeFarkli(params.oncelikler?.map(oncelikNormalize), s.oncelikler)) { farklar.push("oncelikler"); } return farklar; } export type FarkSatiri = { alan: FarkAlani; etiket: string; eski: string; yeni: string }; /** Değişen her alanın eski → yeni değeri; uyarıda tek tek gösterilir. */ export function farkSatirlari( params: RaporParams, profil: TercihProfili, farklar: FarkAlani[], ): FarkSatiri[] { const s = profil.secimler; const sayi = (n: number) => Math.round(n).toLocaleString("tr-TR"); return farklar.map((alan) => { const ortak = { alan, etiket: FARK_ETIKET[alan] }; switch (alan) { case "sira": return { ...ortak, eski: `${sayi(params.sira)}.`, yeni: `${sayi(profil.sira)}.` }; case "tur": return { ...ortak, eski: PUAN_TURU_ETIKET[params.tur] ?? params.tur, yeni: PUAN_TURU_ETIKET[profil.tur] ?? profil.tur, }; case "kategoriler": return { ...ortak, eski: liste(params.kategoriler), yeni: liste(s.kategoriler) }; case "iller": return { ...ortak, eski: liste(params.iller), yeni: liste(s.iller) }; case "universiteTipi": return { ...ortak, eski: UNIVERSITE_TIPI_ETIKET[params.universiteTipi ?? "farketmez"], yeni: UNIVERSITE_TIPI_ETIKET[s.universiteTipi], }; case "oncelikler": return { ...ortak, eski: liste(params.oncelikler?.map(oncelikNormalize)), yeni: liste(s.oncelikler), }; } }); }