All checks were successful
Deploy / deploy (push) Successful in 6m50s
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>
269 lines
15 KiB
Markdown
269 lines
15 KiB
Markdown
# 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 = ?`.
|