Files
kolaytercih/docs/veri/yillik-guncelleme.md
bilalgursen 507bf53a95
All checks were successful
Deploy / deploy (push) Successful in 6m50s
feat(seo): kapanan 28 bölüm + 2 üniversite sayfası benzer sayfaya kalıcı yönlendirilir
Arşivlenen slug'lar 200 + 'sayfa yok' dönüyordu (soft 404). Eşlemenin tek kaynağı
src/lib/kapanan-sluglar.ts; alt yollar (/sayfa/N) hedefin köküne gider; zincir ya da
çift kaynak build'i durdurur. Yıllık güncelleme kılavuzuna 5b adımı eklendi.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-21 23:34:52 +03:00

269 lines
15 KiB
Markdown
Raw Permalink 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.
# Yıllık veri güncellemesi (YÖK Atlas → `data/yokatlas.db`)
Her yıl yerleştirme sonuçları açıklandıktan sonra **bir kez** yapılır. Bu sayfayı
yukarıdan aşağıya izleyen biri, betiklerin içini bilmeden güncellemeyi
tamamlayabilir. Toplam süre: yaklaşık **30 dakika** (çoğu bekleme ve gözle kontrol).
> Ürünün bütün değeri bu verinin doğruluğuna dayanır. Yanlış bir taban sıralaması,
> bir öğrencinin yanlış tercih yapması demektir. Bu yüzden betikler şüphede
> **durur**; "DURDU:" ile başlayan bir mesaj hata değil, emniyet kilididir.
> Kilidi aşmaya çalışma — mesajı oku, aşağıdaki "Bir şey durursa" tablosuna bak.
Örneklerde yeni yıl `2027` diye yazıldı; o yıl hangisiyse onu yaz.
## 0. Ne zaman?
- ÖSYM yerleştirme sonuçlarını açıklar (genelde **Ağustos sonu**), YÖK Atlas verisini
birkaç gün–birkaç hafta sonra günceller. Tarih her yıl değişir → **doğrulanmalı**.
- Erken koşmanın zararı yok: YÖK Atlas henüz güncellenmediyse 3. adım
"`… hâlâ 2026 verisi`" diyerek **hiçbir şey yazmadan** durur. Bir hafta sonra tekrar dene.
- Dosya indirmen gerekmez. Veri, YÖK Atlas'ın herkese açık tercih kılavuzu
servisinden (`https://yokatlas.yok.gov.tr/api/tercih-kilavuz/search`) betikle çekilir:
43 istek, aralarında yarım saniye — kaynağı yormaz. Betiği art arda defalarca koşma;
ilk çekimden sonra hep kaydedilmiş ham dosyayı (`--ham`) kullan.
## 1. Hazırlık (5 dk)
```bash
git switch -c veri/2027 # main'de çalışma
```
`src/lib/veri-yillari.ts` dosyasında **tek satırı** değiştir:
```ts
export const SON_YIL = 2027;
```
Betikler ve site yılı yalnız buradan okur. Betiğe verdiğin `--yil` bununla aynı
değilse betik durur (yanlış kolona yazmayı önler).
## 2. Kopya al — asıl dosyaya dokunma (1 dk)
Dev sunucusu açıksa kapat. Sonra:
```bash
mkdir -p /tmp/veri-2027
sqlite3 data/yokatlas.db ".backup '/tmp/veri-2027/once.db'" # güncelleme ÖNCESİ hâl (geri dönüş + karşılaştırma)
cp /tmp/veri-2027/once.db /tmp/veri-2027/yeni.db # üzerinde çalışılacak kopya
```
Bundan sonraki her adım **`/tmp/veri-2027/yeni.db`** üzerinde koşar. `data/yokatlas.db`
ancak 8. adımda, her şey yeşilken değişir.
## 3. Yeni yılı çek (3 dk)
```bash
pnpm refresh --yil 2027 --db /tmp/veri-2027/yeni.db
```
Ne yapar: şemaya `sira2027/puan2027/kontenjan2027/yerlesen2027` kolonlarını ekler,
**yıl kilidini** sınar, tüm kılavuzu çeker, ham hâlini `data/ham/2027-<tarih>.jsonl.gz`
olarak saklar (git'e girmez), sonra tek seferde DB'ye yazar.
Görmen gerekenler:
```
Yıl kilidi: basariSirasi1 = sira2026 → 480/480 (%100.0); eksiz basariSirasi = sira2026 → 0/480 (%0.0)
Çekilen: 21… kayıt, benzersiz kod: 21…, kodsuz: 0, API toplamı: 21… ← üç sayı aynı
Güncellenen: 19…, eklenen: 1…, atlanan: 0
```
- **Yıl kilidi** şunu kanıtlar: servisin "bir önceki yıl" diye verdiği sıralar bizim
2026 kolonumuzla birebir aynı **ve** "bu yıl" diye verdikleri ondan farklı. Yani
yazacağımız veri gerçekten 2027'dir. (Servisteki `yil` alanına güvenilmez; 2026'da
bu alan yüzünden 2025 verisi bozulmak üzereydi.)
- "atlanan" 0 değilse satırlar altında listelenir: kaynağın puan türü vermediği yeni
programlardır; uydurulmaz. Sayıyı not et.
- Bu betik mevcut programların **eski yıl kolonlarına dokunmaz**; dokunursa kendi
sağlaması bunu yakalar ve her şeyi geri alır.
- **Kimlik kilidi.** ÖSYM bazen bir kılavuz kodunu BAŞKA programa verir (2025'te
`209210292` "Diş Hekimliği"nden "İlk ve Acil Yardım" önlisansına geçti). Betik her
mevcut satırın puan türü / önlisans / bölüm adını servistekiyle kıyaslar; uyuşmayan
varsa listeyi basıp **hiçbir şey yazmadan durur** (`KİMLİĞİ KAYMIŞ N satır`). Listeye
göz at (yılda birkaç–birkaç on satır beklenir; yüzlerce ise servis biçim değiştirmiştir,
veri mühendisine göster), sonra aynı komutu `--kimlik-onar` ekleyerek, ham dosyadan
tekrarla: `pnpm refresh --yil 2027 --db <db> --ham data/ham/2027-<tarih>.jsonl.gz --kimlik-onar`.
Onarım: ad/tür/önlisans/fakülte/süre servisten yazılır; devirden **önceki** yılların
tüm değerleri o satırda boşaltılır (başka programa aitti), eski kimlik + geçmişi
`programs_arsiv`'e `<kod>~<yıl>` id'siyle kopyalanır, eski yılların netleri oraya
taşınır. Çıktıdaki `KİMLİĞİ ONARILAN` tablosunu commit mesajına/rapora koy.
"AD DEĞİŞİMİ" yazan satırlarda yalnız ad güncellenir, geçmiş korunur.
Aynı işlemi servise gitmeden tekrarlamak için (ör. 8. adımda):
`pnpm refresh --yil 2027 --db <db> --ham data/ham/2027-<tarih>.jsonl.gz`
## 4. Geçmiş boşluklarını doldur (1 dk)
```bash
pnpm gecmis-doldur --yil 2027 --db /tmp/veri-2027/yeni.db
```
Kılavuz kodu değişen ya da yeni koda taşınan programların eski yıllarını tamamlar.
Yalnız **boş** alanı doldurur; dolu değeri asla ezmez, tahmin yapmaz. Kaynak sırası:
servisin kendi geçmiş alanları → servisin bildirdiği eski kod → aynı üniversitede
bire bir aynı adlı ve en az bir yılı kanıtla örtüşen tek satır.
Çıktının sonundaki "**Dolu olup kaynağın FARKLI söylediği alanlar**" listesine bak.
Birkaç onluk fark olağandır (kaynak eski sıraları ufak düzeltmelerle yeniden yayımlıyor;
2026'da `sira2024` farklarının %95'i on binde birin altındaydı). **Binlerce satırda büyük
fark** görürsen dur ve veri mühendisine sor.
## 5. Kılavuzdan çıkan programlar: önce sadece raporla (1 dk)
```bash
pnpm eski-arsivle --yil 2027 --db /tmp/veri-2027/yeni.db --kuru
```
Hiçbir şey yazmaz. Şunu söyler: bu yılın kılavuzunda **olmayan** kaç satır var ve
bunlar siteden kalkarsa hangi `/bolum/...` ve `/universite/...` sayfaları tamamen
kapanır (adlarıyla). Bu liste **[BİLAL] kararıdır** — sayfa kapanışı SEO'yu etkiler,
gerekirse yönlendirme (redirect) eklenir.
Onaydan sonra gerçek taşıma (silmez; satırlar `programs_arsiv` tablosuna geçer):
```bash
pnpm eski-arsivle --yil 2027 --db /tmp/veri-2027/yeni.db
```
Neden gerekli: arşivlenmezse eski kodlu satırlar listelerde bir yıl önceki sırayla
görünmeye devam eder; öğrenci o kodu tercih ekranında bulamaz, kodu değişen program
iki kez listelenir.
### 5b. Kapanan sayfaları yönlendir (5–15 dk)
`--kuru` raporundaki `KAPANACAK /bolum/<slug>` ve `KAPANACAK /universite/<slug>`
listelerindeki her adres (ve `--kimlik-onar` sonrası kapanan sayfa olduysa onlar da)
`src/lib/kapanan-sluglar.ts` içindeki `KAPANAN_SLUGLAR` listesine eklenir; site bu
adresleri yaşayan en yakın sayfaya **kalıcı (308)** yönlendirir (`next.config.ts` →
`redirects()`, `/sayfa/N` alt yolları dahil). Eklemezsen kapanan adres Google'da
"sayfa yok" gövdesiyle kalır.
- Hedef sırası: (1) program/kurum **ad değiştirdiyse yeni adı** — kanıt: aynı
üniversitede geçmiş yıl sıraları yeni adlı satıra birebir taşınmış, ya da Resmî
Gazete kararı; (2) aynı alanın lisans/önlisans karşılığı; (3) emin değilsen hub:
`/bolumler` ya da `/universiteler`. Uydurma eşleme yapma; `gerekce` alanına kanıtı yaz.
- Hedef slug `programs` tablosundan türemeli ve kendisi listede **kaynak** olmamalı
(zincir). Zinciri dosyadaki `kapananYonlendirmeleri()` build'de yakalar; hedefin
yaşadığını sen kontrol et: 8. adımda hedef adresi tarayıcıda aç.
- Bu yıl **yeniden açılan** bir sayfa listede kaynak olarak duruyorsa kaydını sil —
yönlendirme sayfadan önce çalışır, silmezsen yeni sayfa hiç görünmez. Kontrol:
8. adımda listedeki `kaynak` adlarını `/bolumler` ve `/universiteler` sayfasında ara;
çıkan varsa kaydını sil.
- Hedef seçimi SEO'yu etkilediği için **[BİLAL] kararıdır**; listeyi commit'ten önce göster.
## 6. İndeks + dosyayı toparla (1 dk)
```bash
pnpm db:index --db /tmp/veri-2027/yeni.db --vacuum
```
Son satırda `USING INDEX idx_programs_tur_onlisans_efektif` yazmalı. Yazmıyorsa betik
zaten hata verir: sitedeki sıralama aralığı sorguları yavaşlar.
## 7. Kalite kapısı (1 dk)
```bash
pnpm veri-kalite --yil 2027 --db /tmp/veri-2027/yeni.db --onceki /tmp/veri-2027/once.db --arsivli --ham data/ham/2027-<tarih>.jsonl.gz
echo "çıkış kodu: $?" # 0 olmalı
```
(`--arsivli`'yi yalnız 5. adımda gerçek arşivlemeyi yaptıysan ekle.)
- Her satır `GEÇTİ`, `KALDI`, `UYARI` ya da `bilgi` ile başlar. **Tek bir `KALDI` varsa
yayına çıkılmaz**; çıkış kodu 1 olur.
- En önemli üç satır:
- `kimlik (tur/önlisans/baz ad = API) — … uyumsuz: 0` — her kod hâlâ aynı programı
gösteriyor (uyumsuzsa satır eski adıyla başka programın sırasını gösterir).
- `önceki DB: geçmiş yıllar korunmuş — … değişen/silinen satır: 0`
- `sira2027/sira2026 ∈ [0,5; 2] — … (%9x)` — programların büyük çoğunluğunun sırası
bir yılda yarıya inmez, iki katına çıkmaz. Oran düşükse yıllar kaymıştır.
- `UYARI`'lar bilgilendirir (ör. ili boş 110 program, yetim net satırları); yeni bir
uyarı türü ya da sayıda sıçrama varsa veri mühendisine göster.
Elle 3 program seç (biri çok bilinen: ör. Boğaziçi Bilgisayar Mühendisliği), YÖK Atlas
sitesindeki 2027 taban sırasıyla karşılaştır:
```bash
sqlite3 /tmp/veri-2027/yeni.db "SELECT id, universite, isim, sira2026, sira2027, puan2027 FROM programs WHERE isim LIKE 'Bilgisayar Mühendisliği%' AND universite LIKE 'BOĞAZİÇİ%';"
```
## 8. Yerine koy ve siteyi kontrol et (5 dk)
```bash
cp /tmp/veri-2027/yeni.db data/yokatlas.db
rm -f data/yokatlas.db-wal data/yokatlas.db-shm # eski dosyanın artıkları; yenisi temiz (checkpoint yapılmış)
pnpm build # katalog sayfaları yeni veriden üretilir; hata vermemeli
```
Netler (yerleşen son kişinin netleri) ayrı bir servisten gelir ve genelde daha geç
güncellenir; hazır olduğunda:
```bash
pnpm detay --yil 2027 --db data/yokatlas.db # ~127 istek, ~2 dk; yıl sağlaması tutmazsa durur
```
`--kirilim` bayrağını **kullanma**: kontenjan kırılımını (okul birincisi, şehit-gazi…)
sitede okuyan kod yok ve servis bu alanları Eylül 2026'dan beri yayımlamıyor. Bayrak
verilse bile alanlar yoksa adım kendini durdurur, mevcut değerlerin üstüne boş yazmaz.
Yıl değişince koddaki metinler (`"son 6 yıl"`, başlıklardaki yıl vb.) `veri-yillari.ts`
sabitlerinden türediği için kendiliğinden güncellenir. Elle yıl yazılmış yer kaldıysa bul:
```bash
grep -rnE "sira20[0-9]{2}|20(2[1-9])[–-]20" src scripts --include='*.ts' --include='*.tsx' | grep -v veri-yillari
```
Tadımlık havuzu ve kayıtlı raporlar eski sıralarla üretilmiştir → yayından sonra prod'da
`pnpm tadimlik --force` (Bilal koşar; ayrıntı `scripts/tadimlik-uret.ts` başlığında).
## 9. Commit ve yayın
```bash
git add src/lib/veri-yillari.ts data/yokatlas.db
git commit -m "veri: 2027 yerleştirme verisi"
```
`data/ham/` git'e girmez (yerelde sakla; bir sonraki yıl karşılaştırma için işe yarar).
Push öncesi `AGENTS.md`'deki "Push öncesi build zorunlu" kuralı geçerli. Yayın kararı Bilal'in.
## Geri alma
| Ne zaman | Nasıl | Süre |
|---|---|---|
| 8. adımdan önce | Hiçbir şey yapma; `data/yokatlas.db` hiç değişmedi. `/tmp/veri-2027/` silinebilir. | 0 |
| 8. adımdan sonra, commit'ten önce | `git checkout -- data/yokatlas.db data/yokatlas.db-wal data/yokatlas.db-shm` | 1 dk |
| Commit/yayından sonra | `git revert <commit>` + yeniden yayın. `SON_YIL` da aynı commit'te geri döner; site bir önceki yılın verisiyle tutarlı çalışır. | 10 dk |
| Yalnız arşivlemeyi geri almak | `INSERT INTO programs SELECT * FROM programs_arsiv; DELETE FROM programs_arsiv;` (kopyada dene, sonra `pnpm db:index`). Netler yeni kodda kalır; zararsız. | 5 dk |
`/tmp/veri-2027/once.db` dosyasını yayından bir hafta sonrasına kadar silme.
## Bir şey durursa
| Mesaj | Anlamı | Ne yap |
|---|---|---|
| `--yil … ≠ SON_YIL` | 1. adım atlanmış | `veri-yillari.ts`'i güncelle |
| `eksiz alanları hâlâ <geçen yıl> verisi` | YÖK Atlas henüz yeni yılı yayımlamamış | Bekle, bir hafta sonra tekrar dene |
| `"…1" alanları DB'deki … verisiyle eşleşmiyor` | Servis bir yıl daha ilerlemiş (bir yılı atladık) **ya da** servis biçim değiştirmiş **ya da** yanlış DB | Yazma. Veri mühendisine göster |
| `Benzersiz kod sayısı … ≠ API toplamı` | Çekim sırasında servis sayfaları kaydırdı | Birkaç dakika sonra 3. adımı tekrarla (DB'ye bir şey yazılmadı) |
| `Aynı üniversitede birden fazla unitur` | Bir kurumun türü iki farklı yazılmış | Listelenen kurumları veri mühendisine göster; `scripts/unitur-onar.ts` |
| `Güncel satır sayısı … refresh kaydıyla uyuşmuyor` (arşivle) | refresh yarım kalmış | 3. adımı tekrarla; arşivleme bilerek çalışmıyor |
| `N satırın kimliği API ile uyuşmuyor` (refresh) | Kılavuz kodu başka programa devredilmiş (ya da program ad değiştirmiş) | Listeye bak; 3. adımdaki gibi `--ham … --kimlik-onar` ile tekrarla (DB'ye bir şey yazılmadı) |
| `veri-kalite` içinde `KALDI` | O kontrol tutmadı | Yayına çıkma; satırdaki sayıyı ve örnek kodları veri mühendisine ilet |
## Betikler ve dokundukları
| Betik | Yazar mı? | Ne yazar |
|---|---|---|
| `scripts/yokatlas-goc.ts` (`pnpm yokatlas:goc`) | evet | Yalnız şema: yıl kolonları, `son_kilavuz_yili`, `eski_kod`, `programs_arsiv`, `veri_meta`. refresh bunu kendisi çağırır. |
| `scripts/refresh.ts` | evet | `sira/puan/kontenjan/yerlesen<yıl>`, `son_kilavuz_yili`, `eski_kod`; yeni programlar; ham dosya. `--kimlik-onar` ile: kimliği kaymış satırın ad/tür/önlisans/fakülte/süresi, devir öncesi yıl kolonları (NULL), `programs_arsiv` kopyası, `netler.program_id`, `veri_meta` `kimlik_onar:<kod>` |
| `scripts/gecmis-doldur.ts` | evet | Yalnız **NULL** geçmiş yıl alanları + `eski_kod`; kimliği onarılmış satırda devir öncesi yılları doldurmaz |
| `scripts/eski-arsivle.ts` | `--kuru` ile hayır | Satır taşıma `programs` → `programs_arsiv`; `netler.program_id` yeni koda |
| `scripts/db-index.ts` | evet | İndeks, `--vacuum`, WAL checkpoint |
| `scripts/veri-kalite.ts` | **hayır** | Salt okunur; çıkış kodu 0/1 |
| `scripts/detay.ts` | evet | `netler`; `--kirilim` ile (alanlar varsa) bir önceki yılın kırılım kolonları |
Kolon sözlüğü: `son_kilavuz_yili` = programın görüldüğü son tercih kılavuzu (NULL = 2024
ve öncesi, bilinmiyor). `eski_kod` = kılavuz kodu değiştiyse bir önceki kod — kayıtlı
listelerdeki eski kodları yeni koda çevirmek için `SELECT id FROM programs WHERE eski_kod = ?`.