# Eksik Marketlerin Doğrulanması — Detaylı Özet

**Tarih:** 15 Mart 2026  
**Kapsam:** `ai-engine/services/single_match_orchestrator.py` ve `ai-engine/pyt/services/single_match_orchestrator.py`  
**Sonuç:** Tüm marketler zaten implement edilmişti — yalnızca 1 test güncellendi

---

## 1. Amaç

AI Engine'in `single_match_orchestrator.py` dosyasında **OE (Tek/Çift)**, **HTFT (İY/MS)**, **HT_OU05**, **corners**, **cards** ve **handicap** gibi marketlerin prediction pipeline'dan API response'a kadar doğru şekilde aktarılıp aktarılmadığını doğrulamak.

---

## 2. Yapılan Analiz

### 2.1. Odds Parsing Pipeline İncelemesi

Orchestrator'da iki ayrı odds parsing katmanı incelendi:

#### `_parse_odds_json(odds_json)`
- **Kaynak:** Canlı maç JSON verisi (`live_matches.odds` veya `matches.odds`)
- **Çalışma mantığı:** Market isimlerini (`"Maç Sonucu"`, `"2,5 Alt/Üst"`, vb.) regex ile eşleştirip, selection key'leri ile (`"1"`, `"X"`, `"Üst"`, `"Alt"`, vb.) değerleri parse eder
- **Parse edilen marketler:**
  - MS (Maç Sonucu) → `ms_h`, `ms_d`, `ms_a`
  - DC (Çifte Şans) → `dc_1x`, `dc_x2`, `dc_12`
  - OU15/25/35 (Alt/Üst) → `ou15_o`, `ou15_u`, `ou25_o`, `ou25_u`, `ou35_o`, `ou35_u`
  - BTTS (Karşılıklı Gol) → `btts_y`, `btts_n`
  - HT (1. Yarı Sonucu) → `ht_h`, `ht_d`, `ht_a`
  - HT_OU05 (İY 0,5 Alt/Üst) → `ht_ou05_o`, `ht_ou05_u`
  - **OE (Tek/Çift)** → `oe_odd`, `oe_even`
  - **HTFT (İlk Yarı/Maç Sonucu)** → `htft_11`, `htft_1x`, `htft_12`, `htft_x1`, `htft_xx`, `htft_x2`, `htft_21`, `htft_2x`, `htft_22`
  - Basketbol: ML, Total, Spread, HT Total

#### `_parse_relational_odds(rows, parsed)`
- **Kaynak:** `odd_categories` tablosundan gelen relational veri
- **Çalışma mantığı:** `category_name` + `selection_name` eşleştirmesi
- **Ek olarak parse edilen marketler:**
  - **OE** → `"Tek/Çift"` kategorisi, `"tek"/"odd"` → `oe_odd`, `"çift"/"even"` → `oe_even`
  - **HTFT** → `"İlk Yarı/Maç Sonucu"` kategorisi, `"1/1"`, `"1/X"` vb.

### 2.2. Market Board ve API Response İncelemesi

#### `_build_market_rows(data, pred)`
- OE market row'u, prediction'da `odd_even_pick` varsa ve `oe_odd`/`oe_even` odds mevcutsa oluşturuluyor
- 8 standart market + OE = **9 market row**

#### `_build_prediction_package(data, pred, ...)`
`market_board` sözlüğü şu bölümleri içeriyor:

| Bölüm | İçerik |
|--------|--------|
| `MS` | Maç Sonucu olasılıkları |
| `DC` | Çifte Şans |
| `OU25` | 2.5 Alt/Üst |
| `BTTS` | Karşılıklı Gol |
| `HT` | İlk Yarı Sonucu |
| **`OE`** | Tek/Çift olasılıkları |
| **`HT_OU05`** | İY 0.5 Alt/Üst |
| **`others`** | Köşe, kart, handicap tahminleri |

#### `others` Bölümü
```python
"others": {
    "corner_pick": pred.corner_pick,
    "corner_confidence": pred.corner_confidence,
    "card_pick": pred.card_pick,
    "card_confidence": pred.card_confidence,
    "handicap_pick": getattr(pred, "handicap_pick", None),
    "handicap_confidence": getattr(pred, "handicap_confidence", None),
}
```

---

## 3. Sonuç: Tüm Marketler Zaten Kodlanmıştı

Implementation plan'daki 6 maddenin tamamı **her iki orchestrator dosyasında da** (`pyt/services/` ve root `services/`) mevcut:

| # | Özellik | Dosya Konumları | Durum |
|---|---------|-----------------|-------|
| 1 | OE odds parsing (`_parse_odds_json`) | `pyt`: satır 1305-1307, `root`: satır 1572 | ✅ |
| 2 | OE odds parsing (`_parse_relational_odds`) | `pyt`: satır 1403-1407, `root`: satır 1671 | ✅ |
| 3 | HTFT odds parsing (her iki parser) | `pyt`: satır 1308-1317 / 1408-1415 | ✅ |
| 4 | OE odds wiring (`_build_market_rows`) | `pyt`: satır 2367-2373, `root`: satır 2670 | ✅ |
| 5 | OE + HT_OU05 (`market_board`) | `pyt`: satır 1826-1839 | ✅ |
| 6 | `others` section (corners/cards/handicap) | `pyt`: satır 1841-1851, `root`: satır 2111 | ✅ |

---

## 4. Yapılan Tek Kod Değişikliği: Test Güncellemesi

**Dosya:** `ai-engine/tests/test_single_match_orchestrator.py`

### Sorun
`test_parse_odds_json_uses_exact_market_match_and_ignores_collisions` testi, HTFT parsing henüz yokken yazılmıştı. Test şu assertion'ı içeriyordu:

```python
self.assertNotIn("htft_11", parsed)  # HTFT parse edilmemeli
```

HTFT parsing artık aktif olduğu için bu assertion başarısız oluyordu.

### Düzeltme
```diff
- self.assertNotIn("htft_11", parsed)
+ self.assertEqual(parsed["htft_11"], 4.30)
```

Test verisi `"İlk Yarı/Maç Sonucu": {"1/1": "4.30"}` içerdiği için, HTFT parser bu değeri doğru şekilde `htft_11 = 4.30` olarak alıyor.

---

## 5. Test Sonuçları

```
17 passed in 1.51s
```

Tüm birim testleri başarılı ✅

---

## 6. Önemli Notlar

### Dosya Senkronizasyonu
Projede orchestrator'ın **iki kopyası** bulunuyor:
- `ai-engine/pyt/services/single_match_orchestrator.py` — Docker/production kopyası
- `ai-engine/services/single_match_orchestrator.py` — Root/development kopyası

Her iki dosya da aynı implementasyonu içeriyor.

### Market Akışı (End-to-End)
```
Mackolik (web scraping)
  → live_matches.odds (JSON) / odd_categories (relational)
    → _parse_odds_json() / _parse_relational_odds()
      → odds_data dict (ms_h, oe_odd, htft_11, ...)
        → _build_market_rows() → market bazlı satırlar
        → _build_prediction_package() → market_board + others
          → NestJS API → Frontend
```

### Parse Edilen Tüm Odds Key'leri

**Futbol:**
| Grup | Key'ler |
|------|---------|
| MS | `ms_h`, `ms_d`, `ms_a` |
| DC | `dc_1x`, `dc_x2`, `dc_12` |
| OU | `ou15_o/u`, `ou25_o/u`, `ou35_o/u` |
| BTTS | `btts_y`, `btts_n` |
| HT | `ht_h`, `ht_d`, `ht_a` |
| HT_OU05 | `ht_ou05_o`, `ht_ou05_u` |
| OE | `oe_odd`, `oe_even` |
| HTFT | `htft_11`, `htft_1x`, `htft_12`, `htft_x1`, `htft_xx`, `htft_x2`, `htft_21`, `htft_2x`, `htft_22` |

**Basketbol:**
| Grup | Key'ler |
|------|---------|
| ML | `ml_h`, `ml_a` |
| Total | `tot_line`, `tot_o`, `tot_u` |
| Spread | `spread_home_line`, `spread_h`, `spread_a` |
| HT Total | `ht_tot_line`, `ht_tot_o`, `ht_tot_u` |
