fix(veri): kimlik kilidi — kodu başka programa devredilmiş satırlar yakalanır ve onarılır
Kılavuz kodu başka programa devredildiğinde (ör. 209210292: Diş Hekimliği SAY lisans → İlk ve Acil Yardım TYT önlisans) refresh yalnız koda bakıp yıl kolonlarını yazıyordu; satır eski adıyla yeni programın sırasını gösteriyordu. - scripts/kimlik.ts (yeni): kimlik = puan türü + önlisans + baz ad slug'ı. Devir yılı kanıt zinciriyle bulunur (API …1/…2/…3 sıra/puanı DB ile eşleşen ardışık yıllar + netler.puanTuru); API geçmişi kod bazlı ve kirli olduğu için (gk2, bazı basariSirasi3) zincirsiz güvenilmez. Yalnız adı değişen ve API penceresinin tamamında sürekliliği olan satır "ad değişimi"dir, geçmişi korunur. - refresh: uyumsuz satır varsa listeler ve HİÇBİR ŞEY yazmadan durur; --kimlik-onar ile isim/tur/onlisans/fakulte/sure API'den yazılır, devir öncesi tüm yıl kolonları NULL'lanır, eski kimlik + geçmişi programs_arsiv'e <kod>~<yıl> id'siyle kopyalanır, eski yılların netleri oraya taşınır, veri_meta'ya kimlik_onar:<kod> kaydı düşer. Önceki-yıl sağlaması onarılanlar dışındaki satırlar için aynen geçerli. --isim-esitle (varsayılan kapalı): kimliği aynı, yalnız burs/dil eki farklı satırlarda isim API'den. - gecmis-doldur: onarılmış satırda devir öncesi yılları hiçbir kaynaktan doldurmaz (yoksa API'nin kod bazlı …N alanları eski programı geri yazar). - veri-kalite: --ham ile ZORUNLU kimlik kontrolü (0 uyumsuz beklenir); --onceki karşılaştırmasında onarılanlar ayrı doğrulanır. - docs/veri/yillik-guncelleme.md: kimlik kilidi adımı. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
@@ -19,12 +19,17 @@
|
||||
* en az bir ortak değer AYNIYSA (kanıt) → eski satırdan doldurulur, güncel
|
||||
* satıra `eski_kod` yazılır. Kanıtsız ya da çelişkili eşleşme birleştirilmez.
|
||||
*
|
||||
* Kimliği onarılmış satırlar (refresh --kimlik-onar; bkz. kimlik.ts): devir
|
||||
* yılından ÖNCEKİ yıllar hiçbir kaynaktan doldurulmaz — o yıllarda bu kod başka
|
||||
* programa aitti ve API'nin kod bazlı `…N` alanları o programın değerini verir.
|
||||
*
|
||||
* Kullanım:
|
||||
* pnpm gecmis-doldur --yil 2026 --db /tmp/deneme.db [--ham data/ham/2026-….jsonl.gz] [--kuru]
|
||||
*/
|
||||
import path from "node:path";
|
||||
import type Database from "better-sqlite3";
|
||||
import { ILK_YIL } from "../src/lib/veri-yillari";
|
||||
import { onarimKayitlari } from "./kimlik";
|
||||
import { gecmisAlanlari, hamOku, sonHamDosya } from "./refresh";
|
||||
import {
|
||||
argOku,
|
||||
@@ -95,6 +100,16 @@ async function main() {
|
||||
const arsivGetir = tabloVar(db, "programs_arsiv")
|
||||
? db.prepare("SELECT * FROM programs_arsiv WHERE id = ?")
|
||||
: null;
|
||||
// id → devir yılı: bu yıldan önceki kolonlar o satırda BİLEREK boş.
|
||||
const devirYillari = new Map<string, number>();
|
||||
for (const [id, k] of onarimKayitlari(db)) devirYillari.set(id, k.devirYili);
|
||||
let devirOncesiAtlanan = 0;
|
||||
const devirOncesi = (id: string, y: number): boolean => {
|
||||
const devir = devirYillari.get(id);
|
||||
if (devir == null || y >= devir) return false;
|
||||
devirOncesiAtlanan++;
|
||||
return true;
|
||||
};
|
||||
const setCache = new Map<string, Database.Statement<unknown[]>>();
|
||||
const alanYaz = (id: string, kolon: string, deger: number) => {
|
||||
let st = setCache.get(kolon);
|
||||
@@ -109,6 +124,7 @@ async function main() {
|
||||
/** Hedefin NULL alanlarını kaynaktan doldurur; dolu+farklıyı sayar. */
|
||||
const satirdanDoldur = (kaynakAdi: string, hedef: Satir, kaynak: Satir) => {
|
||||
for (const y of gecmisYillar) {
|
||||
if (devirOncesi(hedef.id, y)) continue;
|
||||
for (const olcu of olculer) {
|
||||
const kolon = `${olcu}${y}`;
|
||||
const k = kaynak[kolon] as number | null;
|
||||
@@ -152,6 +168,7 @@ async function main() {
|
||||
for (const g of gecmisAlanlari(r)) {
|
||||
const y = yil - g.fark;
|
||||
if (!gecmisYillar.includes(y)) continue;
|
||||
if (devirOncesi(hedef.id, y)) continue;
|
||||
for (const olcu of ["sira", "puan", "kontenjan"] as const) {
|
||||
const k = g[olcu];
|
||||
if (k == null) continue;
|
||||
@@ -279,6 +296,13 @@ async function main() {
|
||||
if (v.length) console.log(` örnek ${k}: ${v.join(" ; ")}`);
|
||||
}
|
||||
|
||||
if (devirYillari.size) {
|
||||
console.log(
|
||||
`Kimliği onarılmış ${devirYillari.size} satırda devir öncesi yıl BİLEREK boş bırakıldı ` +
|
||||
`(atlanan yıl denemesi: ${devirOncesiAtlanan}).`
|
||||
);
|
||||
}
|
||||
|
||||
console.log(`\nDoldurulan NULL alanlar${kuru ? " (kuru — yazılmadı)" : ""}:`);
|
||||
const toplamlar = new Map<string, number>();
|
||||
for (const [k, n] of [...doldurulan].sort()) {
|
||||
|
||||
Reference in New Issue
Block a user