feat(veri): 2026 yükleme hattı — yıl kilitli refresh, geçmiş doldurma, arşiv, kalite kapısı (P-A)
- yokatlas-goc: idempotent şema göçü (yıl kolonları, son_kilavuz_yili, eski_kod, programs_arsiv, veri_meta) + betiklerin ortak yardımcıları - refresh: --yil/--db zorunlu, YIL KİLİDİ (…1 = DB sira<yil-1> ≥%95 ve eksiz ≠), yıl asla r.yil'den türetilmez; ham veri data/ham/*.jsonl.gz, --ham ile API'siz tekrar; benzersiz kod = totalElements; tek transaction + önceki yıl sağlaması; yeni programda …1/2/3 → üç önceki yıl; efektif indeks EFEKTIF_SIRA_SQL ile - gecmis-doldur: yalnız NULL alan; API …1/2/3 → eski_kod → kanıtlı 1:1 ad eşleşmesi - eski-arsivle: güncel kılavuzda olmayanlar → programs_arsiv, netler yeni koda; --kuru - detay: netler bağımsız + yıl sağlaması; kırılım yalnız --kirilim, alan yoksa durur, mevcut değerin üstüne NULL yazılmaz; `yil - 1` varsayımı kalktı - veri-kalite: salt okunur kalite kapısı, zorunlu kontrol kalırsa çıkış kodu 1 - docs/veri/yillik-guncelleme.md: adım adım runbook + geri alma DB commit'lenmedi (arşivleme kararı [Bilal]). Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
230
docs/veri/yillik-guncelleme.md
Normal file
230
docs/veri/yillik-guncelleme.md
Normal file
@@ -0,0 +1,230 @@
|
||||
# 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.
|
||||
|
||||
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.
|
||||
|
||||
## 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
|
||||
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 iki satır:
|
||||
- `ö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 |
|
||||
| `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 |
|
||||
| `scripts/gecmis-doldur.ts` | evet | Yalnız **NULL** geçmiş yıl alanları + `eski_kod` |
|
||||
| `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 = ?`.
|
||||
Reference in New Issue
Block a user