diff --git a/scripts/tadimlik-uret.ts b/scripts/tadimlik-uret.ts index a869324..4e2c351 100644 --- a/scripts/tadimlik-uret.ts +++ b/scripts/tadimlik-uret.ts @@ -67,9 +67,10 @@ KURALLAR (kesin): - METİN DİYETİ: her alan TEK kısa cümle, dolgu söz yok. - gerekce: bu programın bu aday için neden mantıklı olduğu (TEK cümle, en fazla ~15 kelime, Türkçe). -- riskNotu: yerleşme ihtimali değerlendirmesi (TEK kısa cümle). ASLA "garanti", - "kesin", "yüzde yüz" deme; "yüksek/orta/düşük ihtimal" dili kullan. -- trendOzeti: son 4 yılın taban sıralaması hareketi, TEK cümle (ör. "2022'den +- riskNotu: geçmiş taban verisine dayalı risk değerlendirmesi (TEK kısa cümle). + ASLA garanti/kesin/yüzde/olasılık/ihtimal deme; "güvenli / az riskli / + riskli" etiketleriyle konuş. +- trendOzeti: son 5 yılın taban sıralaması hareketi, TEK cümle (ör. "2022'den beri taban 45B'den 38B'ye indi, bölüm zorlaşıyor"). - Adayın sıralaması yaklaşıktır; kesin sıra telaffuz etme, banda göre konuş.`; @@ -82,9 +83,9 @@ function mockMetin(p: Program, temsiliSira: number, kategori: string | null) { return { gerekce: `(Dev mock) ${p.isim}, ${kategori ? `${kategori} ilgisiyle ve ` : ""}~${temsiliSira.toLocaleString("tr-TR")} bandındaki sıralamanla uyumlu bir aday.`, riskNotu: - "(Dev mock) Taban sıralaması senin civarında; orta-yüksek ihtimalle yerleşilebilir.", + "(Dev mock) Son taban sıralaması sırana yakın; küçük bir kayma sonucu değiştirebilir.", trendOzeti: - "(Dev mock) Son 4 yılda taban sıralaması görece stabil seyretti.", + "(Dev mock) Son 5 yılda taban sıralaması görece stabil seyretti.", }; } diff --git a/src/app/api/soru/route.ts b/src/app/api/soru/route.ts index 305f284..01c0cfc 100644 --- a/src/app/api/soru/route.ts +++ b/src/app/api/soru/route.ts @@ -45,7 +45,8 @@ KURALLAR: sıralaması adayın belirgin altında, Az riskli (sarı) = adayın sıralaması civarında, Riskli (kırmızı) = geçen yıl adayın sıralamasının üzerinde kapandı. Risk sorularında bu etiketleri ve taban sıralarını kullan. -- ASLA yerleşme garantisi verme; "yüksek/orta/düşük ihtimal" dili kullan. +- ASLA yerleşme garantisi verme; olasılık, yüzde ya da "ihtimal" dili kullanma — + güvenli / az riskli / riskli etiketleri ve taban sıralarıyla konuş. - Bilmediğin güncel veriyi uydurma; emin değilsen YÖK Atlas'a bakmasını söyle. - Taban sıralamalarının her yıl değiştiğini gerektiğinde hatırlat. - Cevapları kısa ve öz tut (genelde 3-6 cümle); istenirse detaylandır. diff --git a/src/app/layout.tsx b/src/app/layout.tsx index 6303e82..f9e2ed5 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -52,7 +52,7 @@ export const metadata: Metadata = { template: "%s — KolayTercih", }, description: - "YKS sıralamana göre gerçek YÖK Atlas verisiyle dengeli 24 tercihlik liste. İnsan danışmanın onda bir fiyatına, yapay zekâ destekli tercih danışmanlığı.", + "YKS sıralamana göre gerçek YÖK Atlas verisiyle dengeli 24 tercihlik liste. İnsan danışmandan çok daha düşük fiyata, yapay zekâ destekli tercih danışmanlığı.", applicationName: "KolayTercih", openGraph: { type: "website", diff --git a/src/app/page.tsx b/src/app/page.tsx index 0a06a1e..c9fa786 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -12,7 +12,6 @@ import { TrendingUp, Wallet, } from "lucide-react"; -import Image from "next/image"; import Link from "next/link"; import { Suspense } from "react"; import { ComparisonCell } from "@/features/pazarlama/components/landing-parcalari"; @@ -30,6 +29,7 @@ import { SectionEyebrow, } from "@/components/pixel-decor"; import { MAX_REVIZYON, URUNLER } from "@/lib/credits"; +import { VERI_YIL_SAYISI } from "@/lib/veri-kapsami"; import { Accordion, AccordionContent, @@ -54,9 +54,11 @@ import { import type { Metadata } from "next"; import { JsonLd, + KATALOG_VERI_TARIHI, faqPageJsonLd, softwareApplicationJsonLd, } from "@/lib/seo"; +import { KATALOG_TARIH_METNI } from "@/features/katalog/components/veri-kaynagi"; import { SiteFooter } from "@/components/site-footer"; export const metadata: Metadata = { @@ -87,7 +89,7 @@ const problems = [ icon: Wallet, title: "Danışman lüks haline geldi", description: - "İyi bir tercih danışmanı 2.000–10.000 TL istiyor. Ücretsiz robotlar ise sadece liste filtreliyor, akıl vermiyor.", + "İyi bir tercih danışmanı 1.000–5.000 TL istiyor. Ücretsiz robotlar ise sadece liste filtreliyor, akıl vermiyor.", }, ]; @@ -103,8 +105,7 @@ const steps = [ icon: BarChart3, step: "2", title: "Yapay zekâ veriyi tarasın", - description: - "Son 4 yılın YÖK Atlas verisi — taban sıralaması trendleri, kontenjan değişimleri, doluluk oranları — senin için analiz edilsin.", + description: `Son ${VERI_YIL_SAYISI} yılın YÖK Atlas verisi — taban sıralaması trendleri, kontenjan değişimleri, doluluk oranları — senin için analiz edilsin.`, }, { icon: ShieldCheck, @@ -118,8 +119,7 @@ const steps = [ const faqs = [ { question: "KolayTercih'in önerileri neye dayanıyor?", - answer: - "Tüm öneriler YÖK Atlas'ın resmî verisine dayanır: son 4 yılın taban başarı sıralamaları, kontenjanlar, yerleşme istatistikleri ve doluluk oranları. Yapay zekâ bu veriyi yorumlar; veri olmadan tahmin yürütmez.", + answer: `Tüm öneriler YÖK Atlas'ın resmî verisine dayanır: son ${VERI_YIL_SAYISI} yılın taban başarı sıralamaları, kontenjanlar, yerleşme istatistikleri ve doluluk oranları. Yapay zekâ bu veriyi yorumlar; veri olmadan tahmin yürütmez.`, }, { question: "Ücretsiz tercih robotlarından farkı ne?", @@ -145,7 +145,7 @@ const comparison = [ tercihai: true, }, { - feature: "Son 4 yılın trend analizi", + feature: `Son ${VERI_YIL_SAYISI} yılın trend analizi`, robot: false, danisman: true, tercihai: true, @@ -165,7 +165,7 @@ const comparison = [ { feature: "Fiyat", robot: "Ücretsiz", - danisman: "2.000–10.000 TL", + danisman: "1.000–5.000 TL", tercihai: `${PAKET_FIYATI} TL · tek seferlik`, }, ]; @@ -177,7 +177,7 @@ const paketOzellikleri = [ }, { icon: ShieldCheck, - text: "Her tercih için yerleşme olasılığı ve risk analizi (son 4 yıl)", + text: `Her tercih için yerleşme riski ve trend analizi (son ${VERI_YIL_SAYISI} yıl)`, }, { icon: FileText, text: "Veliyle paylaşılabilir PDF rapor" }, { icon: RefreshCcw, text: `${MAX_REVIZYON} liste revizyon hakkı` }, @@ -222,11 +222,6 @@ export default function Home() { className="mx-auto flex min-h-[calc(100svh-5.5rem)] max-w-6xl flex-col items-center justify-center px-4 pb-4 pt-12 text-center sm:pb-36 sm:pt-4" > - {/*

- KolayTercih, gerçek YÖK Atlas verisiyle çalışan yapay zekâ tercih - danışmanın. İnsan danışmanın binlerce lira aldığı işi — dengeli - liste, risk analizi, soru-cevap — onda bir fiyatına yapar. -

*/}
- Yükseköğretim Kurulu - - YÖK Atlas'ın gerçek verileriyle + Veri: YÖK Atlas {" "} - güvenilir sonuçlar + · son güncelleme{" "} +
@@ -362,7 +352,7 @@ export default function Home() { {[ { value: "23.000+", label: "Taranan lisans programı" }, { - value: "4 yıl", + value: `${VERI_YIL_SAYISI} yıl`, label: "Taban sıralaması trend verisi", }, { value: "%100", label: "Resmî YÖK Atlas kaynağı" }, @@ -481,10 +471,13 @@ export default function Home() { Ne kadar? Ne dahil?

- İnsan danışmanın 2.000–10.000 TL aldığı işi tek seferlik{" "} + İnsan danışmanın 1.000–5.000 TL aldığı işi tek seferlik{" "} {PAKET_FIYATI} TL'ye alırsın. Abonelik yok, gizli ücret yok.

+

+ Danışman fiyat aralığı: Armut, 2026. +

diff --git a/src/app/paket/page.tsx b/src/app/paket/page.tsx index 9e1eab4..4931153 100644 --- a/src/app/paket/page.tsx +++ b/src/app/paket/page.tsx @@ -46,10 +46,10 @@ export default function PaketPage({ Tek seferlik ödeme · Abonelik yok

İnsan danışmanın işini,{" "} - onda bir fiyatına + çok daha düşük fiyata

- Tercih danışmanları bu dönemde 2.000–10.000 TL alıyor. KolayTercih + Tercih danışmanları bu dönemde 1.000–5.000 TL alıyor. KolayTercih aynı işi gerçek YÖK Atlas verisiyle, dakikalar içinde yapar.

diff --git a/src/components/arama-funnel-karti.tsx b/src/components/arama-funnel-karti.tsx index 29b8c5a..6e59359 100644 --- a/src/components/arama-funnel-karti.tsx +++ b/src/components/arama-funnel-karti.tsx @@ -35,7 +35,7 @@ const FUNNEL_METINLERI = [ "Sıralaman ne söylüyor? Birlikte bakalım.", "Her satırı senin için hesaplıyoruz.", "Akıllı tercih, içi rahat bir bekleyiş.", - "Yerleşme ihtimalini görerek seç.", + "Yerleşme riskini görerek seç.", "Sana özel liste birkaç dakikada hazır.", "İlgi alanların ve şehrin, tek listede.", "Boş kalan tercih, kaçan fırsattır.", diff --git a/src/features/katalog/components/veri-kaynagi.tsx b/src/features/katalog/components/veri-kaynagi.tsx index c8f174c..d1485e5 100644 --- a/src/features/katalog/components/veri-kaynagi.tsx +++ b/src/features/katalog/components/veri-kaynagi.tsx @@ -1,7 +1,9 @@ import { KATALOG_VERI_TARIHI } from "@/lib/seo"; import { cn } from "@/lib/utils"; -const TARIH_METNI = new Date( +// Veri tarihinin görünür biçimi ("9 Ağustos 2026") — tek biçim kaynağı; ana +// sayfa hero'sundaki veri satırı da bunu kullanır. +export const KATALOG_TARIH_METNI = new Date( `${KATALOG_VERI_TARIHI}T00:00:00Z`, ).toLocaleDateString("tr-TR", { day: "numeric", @@ -23,7 +25,7 @@ export function VeriKaynagi({

{children} Kaynak: YÖK Atlas 2025 yerleştirme sonuçları. Son güncelleme:{" "} - . + .

); } diff --git a/src/features/odeme/components/paket-satinal.tsx b/src/features/odeme/components/paket-satinal.tsx index 6693d6f..5ebf077 100644 --- a/src/features/odeme/components/paket-satinal.tsx +++ b/src/features/odeme/components/paket-satinal.tsx @@ -12,6 +12,7 @@ import { } from "lucide-react"; import { getCurrentUser } from "@/lib/session"; import { URUNLER, DENEME_KREDISI } from "@/lib/credits"; +import { VERI_YIL_SAYISI } from "@/lib/veri-kapsami"; import { Button } from "@/components/ui/button"; import { Parallax } from "@/components/parallax"; import { Skeleton } from "@/components/ui/skeleton"; @@ -28,7 +29,7 @@ const OZELLIKLER = [ }, { icon: ShieldCheck, - text: "Her tercih için yerleşme olasılığı ve risk analizi (son 4 yıl trend)", + text: `Her tercih için yerleşme riski ve trend analizi (son ${VERI_YIL_SAYISI} yıl)`, }, { icon: FileText, text: "Veliyle paylaşılabilir PDF rapor" }, { icon: RefreshCcw, text: "2 liste revizyon hakkı" }, diff --git a/src/lib/ai/rapor.ts b/src/lib/ai/rapor.ts index 7d6e305..3141b23 100644 --- a/src/lib/ai/rapor.ts +++ b/src/lib/ai/rapor.ts @@ -18,7 +18,12 @@ import { type AdayProgram, } from "../rapor-havuzu"; import { secimOzeti } from "@/features/sihirbaz/sihirbaz-sabitler"; -import { RISK_ETIKET, dilimdenRisk, riskHesapla } from "../risk"; +import { + RISK_ETIKET, + dilimdenRisk, + riskHesapla, + riskNotuMetni, +} from "../risk"; // Yapay zekâdan istenen küçük şema (kullanıcı kararı, 6 Ağu 2026): riskNotu // ve trendOzeti gerçek sıra geçmişinden deterministik üretilir; dilim iskeleti @@ -161,16 +166,7 @@ function trendOzetiUret(p: AdayProgram): string { } function riskNotuUret(p: AdayProgram, adaySira: number): string { - switch (riskHesapla(p.sira2025 ?? p.sira2024, adaySira)) { - case "guvenli": - return "Taban sıralaması senin sıranın belirgin altında; yüksek ihtimalle yerleşirsin."; - case "az-riskli": - return "Taban sıralaması sırana yakın; orta ihtimalle yerleşilebilir."; - case "riskli": - return "Taban sıralaması senin sıranın üstünde kapandı; yerleşme ihtimali düşük."; - default: - return "Güncel taban sıralaması verisi yok; ihtimal öngörülemez, temkinli yaklaş."; - } + return riskNotuMetni(riskHesapla(p.sira2025 ?? p.sira2024, adaySira)); } /** Havuz programını render için gereken bilgiye indirger. */ diff --git a/src/lib/risk.ts b/src/lib/risk.ts index 4b7c151..8d7898d 100644 --- a/src/lib/risk.ts +++ b/src/lib/risk.ts @@ -42,3 +42,22 @@ export function dilimdenRisk(dilim: Dilim | string): RiskSeviyesi { if (dilim === "dengeli") return "az-riskli"; return "riskli"; } + +/** + * Risk seviyesinin tek cümlelik açıklaması (rapor satırları + tadımlık). + * Ürün yerleşme olasılığı HESAPLAMAZ; yalnızca son taban sıralamasını adayın + * sırasıyla kıyaslar. Bu yüzden metin olasılık/ihtimal/"yerleşirsin" demez. + * "Geçen yıl" da denmez: efektif sıra 2025 yoksa 2024'e düşüyor. + */ +export function riskNotuMetni(risk: RiskSeviyesi | null): string { + switch (risk) { + case "guvenli": + return "Son taban sıralaması senin sıranın belirgin altında; geçmiş veriye göre güvenli aralıkta."; + case "az-riskli": + return "Son taban sıralaması sırana yakın; küçük bir kayma sonucu değiştirebilir."; + case "riskli": + return "Son taban sıralaması senin sıranın üstünde kapandı; hayal tercihi olarak düşün."; + default: + return "Güncel taban verisi yok; bu satırı temkinli değerlendir."; + } +} diff --git a/src/lib/tadimlik-havuzu.ts b/src/lib/tadimlik-havuzu.ts index 62dd85b..e1df7ae 100644 --- a/src/lib/tadimlik-havuzu.ts +++ b/src/lib/tadimlik-havuzu.ts @@ -8,6 +8,7 @@ import { turkishSlugify } from "./slug"; import type { PuanTuruKey } from "@/types/yokatlas"; import type { Dilim } from "./rapor-havuzu"; import type { RaporSonuc } from "@/features/rapor/types/rapor"; +import { dilimdenRisk, riskHesapla, riskNotuMetni } from "./risk"; /** Sihirbaz kategorisi seçilmemiş kullanıcı için kova×tür başına fallback satır. */ export const GENEL_KATEGORI = "genel"; @@ -76,13 +77,20 @@ export async function tadimlikSec( ), }); if (satir) { + const program = satir.program as RaporSonuc["programlar"][string]; return { programId: satir.programId, dilim: satir.dilim, gerekce: satir.gerekce, - riskNotu: satir.riskNotu, + // DB'deki riskNotu batch'te LLM'in temsili sıraya göre yazdığı + // cümledir; servis EDİLMEZ. Not, rozetle (tadimlik-satiri.tsx) aynı + // formülden adayın gerçek sırasına göre okuma anında üretilir — metin + // ile rozet çelişemez, olasılık dili sızamaz. + riskNotu: riskNotuMetni( + riskHesapla(program.efektifSira, sira) ?? dilimdenRisk(satir.dilim), + ), trendOzeti: satir.trendOzeti, - program: satir.program as RaporSonuc["programlar"][string], + program, }; } } diff --git a/src/lib/veri-kapsami.ts b/src/lib/veri-kapsami.ts new file mode 100644 index 0000000..937f77a --- /dev/null +++ b/src/lib/veri-kapsami.ts @@ -0,0 +1,6 @@ +/** + * Taban sıralaması geçmişinin kapsadığı yıl sayısı. Veritabanında + * sira2021–sira2025 kolonları var (5 yıl); "son N yıl" diyen tüm metinler bu + * sabitten okur. Yeni veri yılı eklenince (ör. sira2026) burayı güncelle. + */ +export const VERI_YIL_SAYISI = 5;