# Derin Teknik Düzeltmeler ve Analiz Günlüğü

**Dosya:** `02_deep_fixes_log.md`
**Amaç:** Son geliştirme döngüsünde çözülen karmaşık sorunların teknik detaylarını belgelemek.

---

## 1. Live Match Synchronization & DB Safety

### Sorun Tanımı

Canlı maçlar (Live Matches), ana `matches` tablosuna henüz işlenmemiş olabiliyor. Ancak sistem bunları analiz etmeye çalıştığında:

1. `match_player_participation` tablosuna oyuncu eklemeye çalışıyor -> `matches` tablosunda ID olmadığı için **Foreign Key Constraint Error** alıyordu.
2. Veri tabana yazılamadığı için Python scripti "Lineup not found" hatasıyla patlıyordu.

### Uygulanan Çözüm

**Dual-Persistence Strategy (Çift Yazma Stratejisi):**

- **Logic:** `FeederPersistenceService.saveLineups` ve `saveOdds` metodları artık önce `matches` tablosunda `matchId` var mı diye kontrol ediyor.
- **Varsa:** Hem ilişkisel tablolara (`match_player_participation`) hem de `live_matches` JSON kolonuna yazıyor.
- **Yoksa (Sadece Canlı):** İlişkisel tabloları tamamen pas geçiyor (SKIP), veriyi sadece `live_matches.lineups` ve `live_matches.odds` JSON kolonlarına strüktüre edilmiş olarak yazıyor.

**Fallback Mechanism (Python & NestJS):**

- **NestJS:** `getPlayerCount` metodu önce ilişkisel tabloyu sayıyor. Sayı 0 ise `live_matches` JSON'ını parse edip oradaki oyuncu sayısını dönüyor.
- **Python:** `_run_model` içinde önce SQL sorgusu ile kadro çekmeye çalışıyor. Liste boşsa, `live_matches` tablosundaki JSON kolonunu çekip manuel parse ediyor.

---

## 2. Model Score & Context Mapping (Kritik)

### Sorun Tanımı

Kullanıcı, modelin skor tahminlerinin ve maç sonucu (1/X/2) tercihlerinin tutarsız olduğundan şikayetçiydi ("Home win diyor ama skor 0-1" gibi).

### Tespit Edilen Kök Nedenler

1.  **HT/FT Sıralaması:** Model eğitimi `ht*3 + ft` (0=X, 1=1, 2=2) mantığıyla yapılmıştı. Ancak tahmin scripti etiketleri `1/1, 1/X...` gibi rastgele bir sırayla diziyordu. Bu yüzden `1/1` tahmini `X/X` gibi görünüyordu.
2.  **Beraberlik (Draw) Körlüğü:** Data Feeder, beraberlik oranını `X` etiketiyle kaydediyordu (Mackolik verisi). Python scripti ise sadece `0` etiketini "Beraberlik" olarak kabul ediyordu. Sonuç olarak model "Beraberlik Oranı: 0.0" görüyordu (yani oran yok). Bu, modelin maçın dengesini yanlış anlamasına neden oluyordu.
3.  **Away Bias (Deplasman Yanlılığı):** Backtest verileri, modelin sistematik olarak deplasman takımına fazla gol yazdığını (%15-20 fazla) gösterdi.

### Uygulanan Çözüm

1.  **Etiket Düzeltmesi:** `htft_labels` listesi `[X/X, X/1, X/2, 1/X, 1/1, 1/2, 2/X, 2/1, 2/2]` olarak, eğitim verisiyle %100 uyumlu hale getirildi.
2.  **Oran Normalizasyonu:** Python scripti artık hem `0` hem `X` etiketlerini beraberlik oranı olarak kabul ediyor.
3.  **Skor Kalibrasyonu:** Backtest sonrası optimizasyon katsayıları eklendi.
    - `HOME_GOAL_SCALE = 1.00`
    - `AWAY_GOAL_SCALE = 0.85`

---

## 3. Akıllı Kupon Servisi (Smart Coupon)

### Yapı

NestJS tarafında `SmartCouponService` ve Python tarafında `smart_coupon_service.py` (CLI) işbirliği ile çalışır.

### Akış

1.  **Request:** POST `/api/coupon/analyze-match` { matchId }
2.  **Pre-Check 1 (Kadro):** DB'de kadro var mı?
    - Yoksa -> `FeederService.refreshMatch(lineups)` -> Tekrar kontrol -> Hâlâ yoksa Hata Fırlat ("Yetersiz Veri").
3.  **Pre-Check 2 (Oran):** DB'de oran var mı?
    - Yoksa -> `FeederService.refreshMatch(odds)` -> Log bas (Engelleyici değil).
4.  **Prediction:** Python scripti çalıştırılır (`--analyze --json`).
    - Script: DB veya JSON Fallback'ten veriyi okur.
    - Script: Modeli çalıştırır, kalibrasyon katsayılarını uygular.
    - Script: JSON döner.
5.  **Response:** NestJS JSON'ı parse edip kullanıcıya döner.

---

## Gelecek İçin Notlar

- **Database:** `live_matches` tablosundaki JSON kolonları artık kritik öneme sahip. Bunların şeması `Prisma` tarafında `Json` olarak tanımlı ama iç yapısı kod içinde (`FeederPersistence`) belirleniyor. Yapıyı değiştirirken dikkatli olunmalı.
- **Model:** V17 modeli şu an stabil. V18'e geçilirse `player_model_v17.py` değiştirilmeli ve `smart_coupon_service.py` içindeki scale faktörleri sıfırlanıp tekrar backtest yapılmalı.
