790 lines
32 KiB
Markdown
790 lines
32 KiB
Markdown
# Suggest-Bet-BE — Comprehensive Project Summary
|
||
|
||
> **Son güncelleme:** 2026-03-12
|
||
> **Bu doküman**, projeyi hiç bilmeyen bir AI veya geliştiricinin projeyi A-Z anlaması için hazırlanmıştır.
|
||
|
||
---
|
||
|
||
## 1. Proje Amacı ve Genel Bakış
|
||
|
||
**Suggest-Bet-BE**, yapay zeka destekli bir **spor bahis tahmin ve analiz platformu** backend servisidir. Platform, kullanıcılara:
|
||
|
||
- Futbol ve basketbol maçları için **AI destekli tahminler** sunar
|
||
- Akıllı **kupon önerileri** oluşturur (SAFE, BALANCED, AGGRESSIVE, VALUE, MIRACLE stratejileri)
|
||
- **Canlı skor takibi** ve **oran izleme** sağlar
|
||
- **Mackolik.com** üzerinden veri scraping ile güncel ve tarihsel maç verileri toplar
|
||
- **Google Gemini AI** ile doğal dil maç yorumu üretir
|
||
- Kullanıcı kuponlarını kaydeder ve sonuçlarını takip eder (ROI, Win Rate)
|
||
|
||
### Teknoloji Stack
|
||
|
||
| Katman | Teknoloji |
|
||
|--------|-----------|
|
||
| **Backend (API)** | NestJS 11 (TypeScript) |
|
||
| **AI Engine** | Python FastAPI (v20+) |
|
||
| **Veritabanı** | PostgreSQL 16 + Prisma ORM |
|
||
| **Kuyruk** | BullMQ + Redis (Opsiyonel) |
|
||
| **Cache** | Redis veya In-Memory fallback |
|
||
| **Auth** | JWT + Passport (Access + Refresh Token) |
|
||
| **AI** | Google Gemini API, Custom Python ML Engine |
|
||
| **Scraping** | Axios + Cheerio (Mackolik HTML parsing) |
|
||
| **Loglama** | Pino (Structured Logging) |
|
||
| **i18n** | nestjs-i18n (TR, EN) |
|
||
| **API Docs** | Swagger (NestJS/Swagger) |
|
||
| **Deploy** | Docker + Docker Compose |
|
||
| **Social** | Twitter API v2 (Social poster) |
|
||
|
||
---
|
||
|
||
## 2. Mimari Genel Bakış
|
||
|
||
```
|
||
┌──────────────────────────────────────────────────────────────────┐
|
||
│ CLIENTS (Web/Mobile) │
|
||
└───────────────────────────────┬──────────────────────────────────┘
|
||
│ HTTP/REST
|
||
┌───────────────────────────────▼──────────────────────────────────┐
|
||
│ NestJS Backend (Port 3005) │
|
||
│ ┌─────────┬──────────┬──────────┬──────────┬─────────────────┐ │
|
||
│ │ Auth │ Admin │ Matches │ Leagues │ Predictions │ │
|
||
│ │ Module │ Module │ Module │ Module │ Module │ │
|
||
│ ├─────────┼──────────┼──────────┼──────────┼─────────────────┤ │
|
||
│ │ Coupons │ Analysis │ Gemini │ Social- │ Health │ │
|
||
│ │ Module │ Module │ Module │ Poster │ Module │ │
|
||
│ └─────────┴──────────┴──────────┴──────────┴─────────────────┘ │
|
||
│ ┌──────────────────────────────────────────────────────────────┐ │
|
||
│ │ Services: AiService | MatchAnalysis | Scraper │ │
|
||
│ ├──────────────────────────────────────────────────────────────┤ │
|
||
│ │ Tasks: DataFetcher (Cron) | LiveUpdater | LimitResetter │ │
|
||
│ ├──────────────────────────────────────────────────────────────┤ │
|
||
│ │ Feeder: FeederService | Scraper | Transformer | Persistence│ │
|
||
│ └──────────────────────────────────────────────────────────────┘ │
|
||
└────┬─────────────────┬────────────────────┬──────────────────────┘
|
||
│ │ │
|
||
▼ ▼ ▼
|
||
┌─────────┐ ┌──────────────┐ ┌──────────────────┐
|
||
│PostgreSQL│ │ Redis/BullMQ │ │ AI Engine (py) │
|
||
│ (3.6GB) │ │ (Opsiyonel) │ │ FastAPI:8000 │
|
||
└─────────┘ └──────────────┘ └──────────────────┘
|
||
│
|
||
┌───────▼───────┐
|
||
│ Mackolik API │
|
||
│ (Veri Kaynağı) │
|
||
└───────────────┘
|
||
```
|
||
|
||
---
|
||
|
||
## 3. Veritabanı Şeması (27 Tablo)
|
||
|
||
### 3.1 Enum'lar
|
||
|
||
| Enum | Değerler |
|
||
|------|----------|
|
||
| `Sport` | `football`, `basketball` |
|
||
| `UserRole` | `user`, `superadmin` |
|
||
| `SubscriptionStatus` | `free`, `active`, `expired` |
|
||
| `PlayerPosition` | `goalkeeper`, `defender`, `midfielder`, `striker` |
|
||
| `EventType` | `goal`, `card`, `substitute` |
|
||
| `MatchPosition` | `home`, `away` |
|
||
|
||
### 3.2 Temel Tablolar ve İlişkileri
|
||
|
||
#### Spor Verileri (Büyük Tablolar)
|
||
|
||
| Tablo | Kayıt (~) | Açıklama |
|
||
|-------|-----------|----------|
|
||
| `matches` | 237K | Kalıcı maç kayıtları (finished maçlar) |
|
||
| `live_matches` | 82 | Aktif/yaklaşan canlı maçlar (günlük döngüsel) |
|
||
| `match_player_participation` | 3.3M | Oyuncu maç katılımları (ilk 11 + yedek) |
|
||
| `match_player_events` | 1.5M | Maç olayları (gol, kart, oyuncu değişikliği) |
|
||
| `match_player_stats` | 345K | Oyuncu istatistikleri (basketbol odaklı) |
|
||
| `match_team_stats` | 311K | Takım istatistikleri (possession, shots, basketbol box score) |
|
||
| `match_officials` | — | Hakem bilgileri |
|
||
| `match_ai_features` | — | AI feature vektörleri (ELO, form skoru, eksik oyuncu etkisi) |
|
||
|
||
#### Oran/Bahis Verileri
|
||
|
||
| Tablo | Kayıt (~) | Açıklama |
|
||
|-------|-----------|----------|
|
||
| `odd_categories` | 3.2M | Bahis kategorileri (Maç Sonucu, Alt/Üst vb.) |
|
||
| `odd_selections` | 8.5M | Bahis seçimleri (1, X, 2, Alt, Üst vb.) ve oranları |
|
||
| `odds_history` | — | Oran değişim geçmişi |
|
||
|
||
#### Referans Verileri
|
||
|
||
| Tablo | Kayıt (~) | Açıklama |
|
||
|-------|-----------|----------|
|
||
| `countries` | 160 | Ülkeler |
|
||
| `leagues` | 1,505 | Ligler (Süper Lig, Premier League vb.) |
|
||
| `teams` | 19,595 | Takımlar |
|
||
| `players` | 217K | Oyuncular |
|
||
| `official_roles` | — | Hakem rolleri |
|
||
|
||
#### Kullanıcı ve Sistem
|
||
|
||
| Tablo | Açıklama |
|
||
|-------|----------|
|
||
| `users` | Kullanıcı hesapları (email, role, subscription) |
|
||
| `refresh_tokens` | JWT refresh tokenları |
|
||
| `usage_limits` | Günlük analiz/kupon kullanım limitleri |
|
||
| `user_coupons` | Kullanıcı kuponları (PENDING/WON/LOST) |
|
||
| `user_coupon_items` | Kupon içindeki tekil bahisler |
|
||
| `analyses` | Kullanıcı analiz geçmişi (JSON) |
|
||
| `predictions` | AI tahmin cache (6 saat TTL) |
|
||
| `ai_predictions_log` | AI tahmin logları (accuracy tracking) |
|
||
| `app_settings` | Uygulama ayarları (key-value) |
|
||
| `translations` | Çeviri verileri (DB-tabanlı i18n) |
|
||
|
||
### 3.3 Kritik İlişkiler
|
||
|
||
```
|
||
Country 1──N League 1──N Match N──1 Team (home/away)
|
||
Match 1──N OddCategory 1──N OddSelection 1──N OddsHistory
|
||
Match 1──N MatchPlayerParticipation N──1 Player
|
||
Match 1──N MatchPlayerEvents N──1 Player
|
||
Match 1──1 Prediction
|
||
Match 1──1 MatchAiFeature
|
||
User 1──N Analysis
|
||
User 1──N UserCoupon 1──N UserCouponItem N──1 Match
|
||
User 1──1 UsageLimit
|
||
```
|
||
|
||
---
|
||
|
||
## 4. NestJS Modülleri (12 Modül)
|
||
|
||
### 4.1 Auth Module (`src/modules/auth/`)
|
||
|
||
JWT tabanlı kimlik doğrulama sistemi.
|
||
|
||
| Dosya | Açıklama |
|
||
|-------|----------|
|
||
| `auth.controller.ts` | Register, Login, Refresh, Logout endpointleri |
|
||
| `auth.service.ts` | bcrypt ile şifre hash, JWT token üretimi, refresh token yönetimi |
|
||
| `guards/auth.guards.ts` | `JwtAuthGuard`, `RolesGuard`, `PermissionsGuard` (global) |
|
||
| `strategies/jwt.strategy.ts` | Passport JWT strategy |
|
||
| `dto/auth.dto.ts` | `RegisterDto`, `LoginDto`, `RefreshTokenDto`, `TokenResponseDto` |
|
||
|
||
**Akış:** Register → Password hash (bcrypt, 12 rounds) → User + UsageLimit oluştur → JWT Access (15m) + Refresh Token (7d) üret
|
||
|
||
### 4.2 Admin Module (`src/modules/admin/`)
|
||
|
||
Superadmin yönetim paneli. `@Roles('superadmin')` decorator ile korunur.
|
||
|
||
**Fonksiyonlar:**
|
||
- **Kullanıcı yönetimi:** Listeleme, detay, rol değiştirme, abonelik güncelleme, aktif/pasif toggle, soft delete
|
||
- **App Settings:** Key-value ayar okuma/yazma (Redis cache ile)
|
||
- **Usage Limits:** Tüm kullanıcı limitlerini listeleme ve toplu sıfırlama
|
||
- **Analytics:** Toplam kullanıcı, aktif, premium, maç ve tahmin sayıları
|
||
|
||
### 4.3 Matches Module (`src/modules/matches/`)
|
||
|
||
Maç listeleme ve detay servisi.
|
||
|
||
| Metot | Açıklama |
|
||
|-------|----------|
|
||
| `findMatches()` | Filtreleme (sport, league, status, date, team) ile maç arama. `live_matches` tablosundan |
|
||
| `findUpcomingMatches()` | Kupon üretici için yaklaşan maçları bulma (son 24 saat dahil) |
|
||
| `getMatchesAndStructureByIds()` | Maçları lig bazında grupla, odds JSON'ı yapılandır, frontend formatına dönüştür |
|
||
| `getActiveLeagues()` | Raw SQL ile aktif ligleri ve canlı maç sayılarını getir (Mackolik-tarzı öncelik sıralama) |
|
||
| `listMatches()` | Sayfalı maç listesi (`matches` tablosundan) |
|
||
| `getMatchDetailsById()` | Tam maç detayı: kadro, istatistik, oran, olaylar. Önce `matches`, bulamazsa `live_matches` |
|
||
|
||
**Önemli:** Takım logoları için `https://file.mackolikfeeds.com/teams/{teamId}` URL şablonu kullanılır.
|
||
|
||
### 4.4 Leagues Module (`src/modules/leagues/`)
|
||
|
||
Lig, ülke ve takım keşif servisi.
|
||
|
||
**Fonksiyonlar:** Ülke listesi, Lig listesi (sport filtre), Takım arama, Takım detay, Takım son maçları, Head-to-head karşılaştırma
|
||
|
||
### 4.5 Predictions Module (`src/modules/predictions/`)
|
||
|
||
AI tahmin servisi. **Redis/BullMQ gerektirir** (conditional module loading).
|
||
|
||
| Dosya | Açıklama |
|
||
|-------|----------|
|
||
| `predictions.controller.ts` | health, upcoming, value-bets, history, getPrediction, generate, smart-coupon |
|
||
| `predictions.service.ts` | BullMQ kuyruğu ile tahmin işleme, cache (6 saat TTL, v20plus model check) |
|
||
| `queues/predictions.queue.ts` | BullMQ kuyruk yöneticisi |
|
||
| `queues/predictions.processor.ts` | Kuyruk işleyici (worker) |
|
||
| `services/ai-feature-store.service.ts` | AI feature hesaplama (V17, şu an devre dışı) |
|
||
|
||
**Akış:** İstek → Cache kontrolü (Prediction tablosu, 6 saat TTL) → BullMQ kuyruğa ekle → AI Engine çağır → Sonuç cache'le
|
||
|
||
### 4.6 Coupons Module (`src/modules/coupons/`)
|
||
|
||
Akıllı kupon üretici ve kullanıcı kupon yönetimi.
|
||
|
||
| Servis | Açıklama |
|
||
|--------|----------|
|
||
| `SmartCouponService` | AI Engine v20+ ile maç analizi, kupon üretimi, Gemini ile Türkçe yorum. 5 strateji destekler |
|
||
| `UserCouponService` | Kupon oluşturma, bahis settlement (MS 1/X/2, Alt/Üst, KG Var/Yok), kullanıcı istatistikleri (ROI, Win Rate) |
|
||
| `CouponsService` | Legacy servis (şu an boş) |
|
||
|
||
**Kupon Stratejileri:**
|
||
- `SAFE` — Düşük risk, yüksek güvenilirlik (%78+ confidence, 2 maç)
|
||
- `BALANCED` — Orta risk/oran dengesi
|
||
- `AGGRESSIVE` — Yüksek oran, düşük güvenilirlik
|
||
- `VALUE` — EV+ (Expected Value pozitif) bahisler
|
||
- `MIRACLE` — Çok yüksek oran, çok düşük güvenilirlik
|
||
|
||
### 4.7 Analysis Module (`src/modules/analysis/`)
|
||
|
||
Maç analiz orkestratörü.
|
||
|
||
**Fonksiyonlar:**
|
||
- `analyzeCoupon()` — Çoklu maç analizi. URL parse → Scrape → AI Engine çağrısı
|
||
- `checkUsageLimit()` — Free (10 analiz/3 kupon) vs Premium (50 analiz/10 kupon) limit kontrolü
|
||
- `recordUsage()` — Kullanım kaydı
|
||
- `getAnalysisHistory()` — Analiz geçmişi
|
||
|
||
### 4.8 Gemini Module (`src/modules/gemini/`)
|
||
|
||
Google Gemini AI entegrasyonu. `ENABLE_GEMINI=true` ve `GOOGLE_API_KEY` gerektirir.
|
||
|
||
**API'ler:**
|
||
- `generateText()` — Tek prompt ile metin üretimi
|
||
- `chat()` — Multi-turn sohbet
|
||
- `generateJSON<T>()` — Yapısal JSON üretimi (schema destekli)
|
||
|
||
**Kullanım:** Maç yorumu üretimi (SmartCouponService içinde, Türkçe, bahis terminolojisi ile)
|
||
|
||
### 4.9 Social Poster Module (`src/modules/social-poster/`)
|
||
|
||
Sosyal medya paylaşım sistemi (Twitter).
|
||
|
||
| Servis | Açıklama |
|
||
|--------|----------|
|
||
| `twitter.service.ts` | Twitter API v2 ile tweet gönderimi |
|
||
| `image-renderer.service.ts` | Canvas ile tahmin kartı görsel üretimi |
|
||
| `caption-generator.service.ts` | Gemini ile paylaşım metni üretimi |
|
||
| `social-poster.service.ts` | Orkestratör: tahmin → görsel → metin → paylaş |
|
||
| `meta.service.ts` | Meta (Instagram/Facebook) entegrasyonu (yapılacak) |
|
||
|
||
### 4.10 Feeder Module (`src/modules/feeder/`)
|
||
|
||
Tarihsel veri toplama sistemi (Mackolik scraping).
|
||
|
||
| Servis | Açıklama |
|
||
|--------|----------|
|
||
| `feeder.service.ts` | Ana orkestratör. Tarihsel tarama (2023-06-01'den bugüne), ters kronolojik, resume desteği |
|
||
| `feeder-scraper.service.ts` | HTTP istekleri: livescores, match header, key events, stats, lineups, odds |
|
||
| `feeder-transformer.service.ts` | Ham veriyi DB modeline dönüştürme |
|
||
| `feeder-persistence.service.ts` | Prisma ile veritabanına kayıt, duplicate kontrolü, state yönetimi |
|
||
|
||
**Konfigürasyon:** Concurrency=20, 300ms delay, 50 max retry, 502 exponential backoff
|
||
|
||
### 4.11 Health Module (`src/modules/health/`)
|
||
|
||
Sistem sağlık kontrolleri: liveness, readiness, AI Engine health.
|
||
|
||
### 4.12 Users Module (`src/modules/users/`)
|
||
|
||
Kullanıcı CRUD operasyonları. BaseController/BaseService kalıtımı ile generic yapı.
|
||
|
||
---
|
||
|
||
## 5. Servisler (`src/services/`)
|
||
|
||
| Servis | Dosya | Açıklama |
|
||
|--------|-------|----------|
|
||
| **AiService** | `ai.service.ts` | Python AI Engine bridge. `POST /v20plus/analyze/{matchId}` çağırır, response'u frontend kontratına map'ler. Analysis strategy üretir (oran bazlı taktik) |
|
||
| **MatchAnalysisService** | `match-analysis.service.ts` | 7 fazlı analiz orkestratörü: URL Parse → Scrape → Python Engine → Strategy → Similar Matches → Final Prediction → DB Save |
|
||
| **ScraperService** | `scraper.service.ts` | Mackolik HTML scraping: Cheerio ile `data-settings` ve `window.dataLayer` parse. Odds, lineup, stats, event çekimi |
|
||
|
||
---
|
||
|
||
## 6. Zamanlanmış Görevler (`src/tasks/`)
|
||
|
||
| Görev | Cron | Açıklama |
|
||
|-------|------|----------|
|
||
| `DataFetcherTask.fetchLiveMatches()` | `*/15 * * * *` | Mackolik API'den futbol maçlarını çek, `live_matches` tablosuna yaz. Top league filtresi |
|
||
| `DataFetcherTask.fetchOddsForPreMatches()` | `*/15 * * * *` | Başlamamış maçların oranlarını çek (futbol + basketbol). Retry logic (502/timeout) |
|
||
| `DataFetcherTask.fetchBasketballMatches()` | Manuel | Basketbol maçlarını çek. `basketball_top_leagues.json` filtresi |
|
||
| `LiveUpdaterTask.updateLiveScores()` | `*/15 * * * *` | Canlı maç skorlarını güncelle (Mackolik match-info API) |
|
||
| `LiveUpdaterTask.finalizeFinishedMatches()` | `*/30 * * * *` | Bitmiş maçları `live_matches` → `matches` tablosuna migrate et |
|
||
| `LimitResetterTask.resetUsageLimits()` | `0 3 * * *` | Günlük kullanım limitlerini sıfırla (03:00 Istanbul) |
|
||
| `LimitResetterTask.cleanupOldData()` | `0 4 * * *` | 30 günlük AI logları sil, 1 günlük bitmiş live_matches sil |
|
||
| `LimitResetterTask.checkSubscriptions()` | `0 0 * * *` | Süresi dolmuş abonelikleri `expired` yap |
|
||
|
||
---
|
||
|
||
## 7. AI Engine (Python/FastAPI) — `ai-engine/`
|
||
|
||
Bağımsız Python mikro servis. Default port: `8000`.
|
||
|
||
### 7.1 Endpointler
|
||
|
||
| Method | Endpoint | Açıklama |
|
||
|--------|----------|----------|
|
||
| `POST` | `/v20plus/analyze/{match_id}` | Tekil maç analizi (ana endpoint) |
|
||
| `GET` | `/v20plus/analyze-htms/{match_id}` | İlk yarı - Maç sonu analizi |
|
||
| `GET` | `/v20plus/analyze-htft/{match_id}` | HT/FT olasılıkları (timeout destekli) |
|
||
| `POST` | `/v20plus/coupon` | Akıllı kupon üretimi (strateji + filtreleme) |
|
||
| `GET` | `/v20plus/daily-banker` | Günün banko maçları |
|
||
| `GET` | `/v20plus/reversal-watchlist` | Score reversal izleme listesi |
|
||
| `GET` | `/health` | Sağlık kontrolü |
|
||
|
||
### 7.2 Mimari
|
||
|
||
```
|
||
ai-engine/
|
||
├── main.py # FastAPI app, route tanımları
|
||
├── services/
|
||
│ └── single_match_orchestrator.py # V20+ ana orkestratör (singleton)
|
||
├── core/ # Çekirdek algoritmalar
|
||
├── features/ # Feature engineering
|
||
├── models/ # ML modelleri
|
||
├── training/ # Model eğitim scriptleri
|
||
├── config/ # Konfigürasyon
|
||
├── utils/ # Yardımcı fonksiyonlar
|
||
└── tests/ # Test dosyaları
|
||
```
|
||
|
||
### 7.3 Tahmin Çıktı Yapısı (SingleMatchPredictionPackage)
|
||
|
||
```typescript
|
||
{
|
||
model_version: "v20plus.X",
|
||
match_info: { match_id, match_name, home_team, away_team, league, match_date_ms },
|
||
data_quality: { label: "HIGH"|"MEDIUM"|"LOW", score, flags, lineup_counts },
|
||
risk: { level: "LOW"|"MEDIUM"|"HIGH"|"EXTREME", score, is_surprise_risk, warnings },
|
||
engine_breakdown: { team, player, odds, referee }, // 4 motor ağırlığı
|
||
main_pick: { market, pick, probability, confidence, odds, bet_grade, edge, ... },
|
||
value_pick: { ... },
|
||
bet_advice: { playable, suggested_stake_units, reason },
|
||
bet_summary: [{ market, pick, raw_confidence, calibrated_confidence, bet_grade, ... }],
|
||
supporting_picks: [...],
|
||
aggressive_pick: { market, pick, probability, confidence, odds },
|
||
scenario_top5: [{ score, prob }],
|
||
score_prediction: { ft, ht, xg_home, xg_away, xg_total },
|
||
market_board: { ... },
|
||
reasoning_factors: ["..."],
|
||
ai_commentary: "Gemini üretimi Türkçe yorum"
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 8. API Endpointleri (50 Toplam)
|
||
|
||
### Auth (4 endpoint) — Public
|
||
|
||
| Method | Path | Açıklama |
|
||
|--------|------|----------|
|
||
| `POST` | `/api/auth/register` | Kayıt ol |
|
||
| `POST` | `/api/auth/login` | Giriş yap |
|
||
| `POST` | `/api/auth/refresh` | Token yenile |
|
||
| `POST` | `/api/auth/logout` | Çıkış yap (refresh token invalid) |
|
||
|
||
### Users (5 endpoint) — Auth gerekli
|
||
|
||
| Method | Path | Açıklama |
|
||
|--------|------|----------|
|
||
| `GET` | `/api/users` | Kullanıcı listesi |
|
||
| `GET` | `/api/users/:id` | Kullanıcı detay |
|
||
| `PUT` | `/api/users/:id` | Kullanıcı güncelle |
|
||
| `POST` | `/api/users/:id/restore` | Silinmiş kullanıcıyı geri al |
|
||
|
||
### Admin (11 endpoint) — Superadmin
|
||
|
||
| Method | Path | Açıklama |
|
||
|--------|------|----------|
|
||
| `GET` | `/api/admin/users` | Tüm kullanıcılar (paginated) |
|
||
| `GET` | `/api/admin/users/:id` | Kullanıcı detay |
|
||
| `PUT` | `/api/admin/users/:id/role` | Rol değiştir |
|
||
| `PUT` | `/api/admin/users/:id/subscription` | Abonelik güncelle |
|
||
| `PUT` | `/api/admin/users/:id/toggle-active` | Aktif/Pasif toggle |
|
||
| `DELETE` | `/api/admin/users/:id` | Soft-delete |
|
||
| `GET` | `/api/admin/settings` | Tüm ayarlar |
|
||
| `PUT` | `/api/admin/settings/:key` | Ayar güncelle |
|
||
| `GET` | `/api/admin/usage-limits` | Kullanım limitleri |
|
||
| `POST` | `/api/admin/usage-limits/reset-all` | Toplu limit sıfırla |
|
||
| `GET` | `/api/admin/analytics/overview` | Sistem istatistikleri |
|
||
|
||
### Matches (4 endpoint) — Public
|
||
|
||
| Method | Path | Açıklama |
|
||
|--------|------|----------|
|
||
| `GET` | `/api/matches` | Maç listesi (paginated) |
|
||
| `POST` | `/api/matches/query` | Gelişmiş maç sorgusu (filtreleme) |
|
||
| `GET` | `/api/matches/leagues/active` | Aktif ligler (cached 1dk) |
|
||
| `GET` | `/api/matches/:id` | Maç detayı (kadro, stat, oran, olaylar) |
|
||
|
||
### Leagues (8 endpoint) — Public
|
||
|
||
| Method | Path | Açıklama |
|
||
|--------|------|----------|
|
||
| `GET` | `/api/leagues` | Tüm ligler |
|
||
| `GET` | `/api/leagues/:id` | Lig detay |
|
||
| `GET` | `/api/leagues/countries` | Ülke listesi |
|
||
| `GET` | `/api/leagues/countries/:id` | Ülke detay + ligleri |
|
||
| `GET` | `/api/leagues/teams/search` | Takım arama |
|
||
| `GET` | `/api/leagues/teams/:id` | Takım detay |
|
||
| `GET` | `/api/leagues/teams/:id/matches` | Takım son maçları |
|
||
| `GET` | `/api/leagues/teams/h2h` | Head-to-head |
|
||
|
||
### Analysis (2 endpoint) — Auth gerekli
|
||
|
||
| Method | Path | Açıklama |
|
||
|--------|------|----------|
|
||
| `POST` | `/api/analysis/analyze-matches` | Çoklu maç analizi |
|
||
| `GET` | `/api/analysis/history` | Analiz geçmişi |
|
||
|
||
### Coupon (6 endpoint) — Mixed
|
||
|
||
| Method | Path | Açıklama |
|
||
|--------|------|----------|
|
||
| `POST` | `/api/coupon/analyze-match` | Tekil maç analizi (V20) — Public |
|
||
| `POST` | `/api/coupon/daily-banko` | Günün bankosu (2 maç, %78+) — Public |
|
||
| `POST` | `/api/coupon/suggest` | Akıllı kupon öner (5 strateji) — Public |
|
||
| `POST` | `/api/coupon/create` | Kupon kaydet — Auth |
|
||
| `GET` | `/api/coupon/my-stats` | Kullanıcı istatistikleri — Auth |
|
||
| `GET` | `/api/coupon/history` | Kupon geçmişi — Auth |
|
||
|
||
### Predictions (7 endpoint) — Requires Redis
|
||
|
||
| Method | Path | Açıklama |
|
||
|--------|------|----------|
|
||
| `GET` | `/api/predictions/health` | AI Engine health |
|
||
| `GET` | `/api/predictions/upcoming` | Yaklaşan tahminler |
|
||
| `GET` | `/api/predictions/value-bets` | EV+ fırsatları |
|
||
| `GET` | `/api/predictions/history` | Tahmin geçmişi & doğruluk |
|
||
| `GET` | `/api/predictions/:matchId` | Tekil maç tahmini (cached) |
|
||
| `POST` | `/api/predictions/generate` | Tahmin üret |
|
||
| `POST` | `/api/predictions/smart-coupon` | Smart Coupon (V20 AI) |
|
||
|
||
### Health (3 endpoint) — Public
|
||
|
||
| Method | Path | Açıklama |
|
||
|--------|------|----------|
|
||
| `GET` | `/api/health` | Readiness |
|
||
| `GET` | `/api/health/live` | Liveness |
|
||
| `GET` | `/api/health/detail` | Detaylı sağlık |
|
||
|
||
---
|
||
|
||
## 9. Common Layer (`src/common/`)
|
||
|
||
| Dosya | Açıklama |
|
||
|-------|----------|
|
||
| `base/base.service.ts` | Generic BaseService<T> (findAll, findOne, create, update, delete) |
|
||
| `base/base.controller.ts` | Generic BaseController<T> (CRUD endpointleri) |
|
||
| `decorators/index.ts` | `@Public()`, `@Roles()`, `@CurrentUser()` decoratorları |
|
||
| `dto/pagination.dto.ts` | `PaginationDto` — page, limit, sortBy, sortOrder, search |
|
||
| `filters/global-exception.filter.ts` | GlobalExceptionFilter — HTTP 200 wrapper, dev stack trace, i18n error keys |
|
||
| `interceptors/response.interceptor.ts` | ResponseInterceptor — Standart API response wrapper |
|
||
| `types/api-response.type.ts` | `ApiResponse<T>`, `createSuccessResponse()`, `createErrorResponse()`, `createPaginatedResponse()` |
|
||
| `queues/queue.module.ts` | BullMQ module konfigürasyonu |
|
||
| `utils/image.util.ts` | Canvas yardımcı fonksiyonları |
|
||
|
||
### Standart API Response Formatı
|
||
|
||
```json
|
||
{
|
||
"success": true,
|
||
"status": 200,
|
||
"message": "Success",
|
||
"data": { ... },
|
||
"errors": []
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 10. Güvenlik & Guard Sistemi
|
||
|
||
Tüm guard'lar **global** olarak uygulanır (`app.module.ts`):
|
||
|
||
1. **ThrottlerGuard** — Rate limiting (default: 100 req/60s)
|
||
2. **JwtAuthGuard** — JWT token doğrulama (`@Public()` ile bypass)
|
||
3. **RolesGuard** — Rol tabanlı erişim (`@Roles('superadmin')`)
|
||
4. **PermissionsGuard** — İzin tabanlı erişim kontrolü
|
||
|
||
**Password:** bcrypt, 12 salt rounds
|
||
**Token:** JWT Access (15dk) + UUID Refresh Token (7 gün, DB'de saklanır)
|
||
|
||
---
|
||
|
||
## 11. Veri Akış Diyagramları
|
||
|
||
### 11.1 Canlı Maç Veri Akışı
|
||
|
||
```
|
||
Mackolik API (her 15dk)
|
||
│
|
||
▼
|
||
DataFetcherTask.fetchLiveMatches()
|
||
│
|
||
├─→ Country upsert
|
||
├─→ League upsert
|
||
├─→ Team upsert (home + away)
|
||
└─→ LiveMatch upsert (top_leagues.json filtresi)
|
||
|
||
│ (her 15dk)
|
||
▼
|
||
DataFetcherTask.fetchOddsForPreMatches()
|
||
│
|
||
└─→ LiveMatch.odds (JSON) + oddsUpdatedAt güncelle
|
||
|
||
│ (her 15dk)
|
||
▼
|
||
LiveUpdaterTask.updateLiveScores()
|
||
│
|
||
└─→ LiveMatch score/state güncelle
|
||
|
||
│ (her 30dk)
|
||
▼
|
||
LiveUpdaterTask.finalizeFinishedMatches()
|
||
│
|
||
└─→ LiveMatch → Match tablosuna migrate
|
||
```
|
||
|
||
### 11.2 Tahmin İstek Akışı
|
||
|
||
```
|
||
Client POST /api/coupon/analyze-match
|
||
│
|
||
▼
|
||
SmartCouponService.analyzeMatch(matchId)
|
||
│
|
||
├─→ AI Engine POST /v20plus/analyze/{matchId}
|
||
│ │
|
||
│ └─→ SingleMatchOrchestrator.analyze_match()
|
||
│ │
|
||
│ └─→ DB'den veri çek → ML modeli → Tahmin paketi
|
||
│
|
||
├─→ GeminiService.generateText() (commentary, Türkçe)
|
||
│
|
||
└─→ SingleMatchPredictionPackage döndür
|
||
```
|
||
|
||
---
|
||
|
||
## 12. Konfigürasyon
|
||
|
||
### Environment Variables
|
||
|
||
| Değişken | Açıklama | Default |
|
||
|----------|----------|---------|
|
||
| `NODE_ENV` | Ortam | `development` |
|
||
| `PORT` | Sunucu portu | `3005` |
|
||
| `DATABASE_URL` | PostgreSQL bağlantısı | — |
|
||
| `JWT_SECRET` | JWT imza anahtarı | — |
|
||
| `JWT_ACCESS_EXPIRATION` | Access token süresi | `15m` |
|
||
| `JWT_REFRESH_EXPIRATION` | Refresh token süresi | `7d` |
|
||
| `REDIS_ENABLED` | Redis/BullMQ aktif mi | `false` |
|
||
| `REDIS_HOST` | Redis host | `localhost` |
|
||
| `REDIS_PORT` | Redis port | `6379` |
|
||
| `AI_ENGINE_URL` | Python AI Engine URL | `http://127.0.0.1:8000` |
|
||
| `ENABLE_GEMINI` | Gemini AI aktif mi | `false` |
|
||
| `GOOGLE_API_KEY` | Gemini API anahtarı | — |
|
||
|
||
### Config Dosyaları
|
||
|
||
| Dosya | Açıklama |
|
||
|-------|----------|
|
||
| `top_leagues.json` | Futbol top lig ID'leri (canlı maç filtresi) |
|
||
| `basketball_top_leagues.json` | Basketbol top lig ID'leri |
|
||
| `src/config/configuration.ts` | NestJS config factory'leri |
|
||
| `src/config/env.validation.ts` | Zod ile env doğrulama |
|
||
|
||
---
|
||
|
||
## 13. Build & Run Komutları
|
||
|
||
```bash
|
||
# Development
|
||
npm run start:dev # NestJS watch mode (port 3005)
|
||
|
||
# Production
|
||
npm run build && npm run start:prod
|
||
|
||
# Feeder (Data Collection)
|
||
npm run feeder:historical # Tarihsel veri taraması (2023-06→bugün)
|
||
npm run feeder:fill-gaps # Eksik veri tamamlama
|
||
npm run feeder:basketball # Basketbol verisi
|
||
npm run feeder:live # Canlı veri
|
||
|
||
# Database
|
||
npx prisma generate # Prisma client güncelle
|
||
npx prisma migrate dev # Migration çalıştır
|
||
npx prisma db seed # Seed data
|
||
|
||
# Testing
|
||
npm run test # Unit testler
|
||
npm run test:e2e # E2E testler
|
||
|
||
# AI Engine (Python)
|
||
cd ai-engine && uvicorn main:app --host 0.0.0.0 --port 8000 --reload
|
||
|
||
# Swagger
|
||
npm run swagger:summary # Endpoint export
|
||
```
|
||
|
||
---
|
||
|
||
## 14. Docker Deployment
|
||
|
||
```yaml
|
||
# docker-compose.yml (3 servis)
|
||
services:
|
||
backend: # NestJS (port 3005)
|
||
ai-engine: # Python FastAPI (port 8000)
|
||
postgres: # PostgreSQL 16 (port 5432)
|
||
redis: # Redis (opsiyonel, port 6379)
|
||
```
|
||
|
||
---
|
||
|
||
## 15. Bilinen Durumlar ve Notlar
|
||
|
||
1. **Predictions modülü** Redis gerektirir (`REDIS_ENABLED=true`). Redis yoksa bu modül yüklenmez.
|
||
2. **Gemini AI** opsiyoneldir. Devre dışıyken maç yorumu `null` döner.
|
||
3. **Feeder V17 AI feature hesaplama** devre dışı bırakılmıştır — V20 modeli Python tarafında çalışır.
|
||
4. **Lineup scraping** V20 optimizasyonu için devre dışıdır — sadece Team Stats kullanılır.
|
||
5. **Global Exception Filter** tüm hataları HTTP 200 olarak döner, gerçek status body içindedir.
|
||
6. **Abonelik sistemi** Free/Active/Expired — Free: 10 analiz + 3 kupon/gün, Active: 50 + 10.
|
||
7. **Veri kaynağı** tek: Mackolik.com — hem canlı API hem HTML scraping.
|
||
8. **Social Poster** Twitter API v2 ile çalışır, Instagram/Meta henüz implemente edilmemiştir.
|
||
|
||
---
|
||
|
||
## 16. Canlı Veritabanı Analizi (MCP ile PostgreSQL Sorguları)
|
||
|
||
> Aşağıdaki veriler **2026-03-12** tarihinde canlı veritabanından çekilmiştir.
|
||
|
||
### 16.1 Genel İstatistikler
|
||
|
||
| Metrik | Değer |
|
||
|--------|-------|
|
||
| **Toplam DB Boyutu** | **3,658 MB (3.6 GB)** |
|
||
| **Toplam Tablo** | 27 |
|
||
| **Veri Aralığı** | 2023-06-01 → 2026-03-12 |
|
||
|
||
### 16.2 Tablo Boyutları (Büyükten Küçüğe)
|
||
|
||
| Tablo | Kayıt Sayısı | Toplam Boyut | Veri | Index |
|
||
|-------|-------------|--------------|------|-------|
|
||
| `odd_selections` | **8,511,132** | 1,070 MB | 543 MB | 526 MB |
|
||
| `match_player_participation` | **3,342,839** | 1,077 MB | 430 MB | 648 MB |
|
||
| `odd_categories` | **3,161,172** | 689 MB | 294 MB | 394 MB |
|
||
| `match_player_events` | **1,453,227** | 356 MB | 239 MB | 117 MB |
|
||
| `match_player_stats` | **344,688** | 120 MB | 60 MB | 60 MB |
|
||
| `match_team_stats` | **310,991** | 91 MB | 37 MB | 54 MB |
|
||
| `match_officials` | **340,824** | 75 MB | 29 MB | 47 MB |
|
||
| `matches` | **236,859** | 100 MB | 60 MB | 40 MB |
|
||
| `players` | **217,040** | 64 MB | 26 MB | 37 MB |
|
||
| `teams` | **19,595** | 5.2 MB | — | — |
|
||
| `leagues` | **1,505** | 760 KB | — | — |
|
||
| `live_matches` | **82** | 1 MB | — | — |
|
||
| `countries` | **160** | 120 KB | — | — |
|
||
| `match_ai_features` | **279** | 152 KB | — | — |
|
||
| `predictions` | **3** | 192 KB | — | — |
|
||
| `users` | **1** | 80 KB | — | — |
|
||
| `refresh_tokens` | **8** | 80 KB | — | — |
|
||
| `usage_limits` | **1** | 80 KB | — | — |
|
||
| `app_settings` | **3** | 64 KB | — | — |
|
||
| `official_roles` | **5** | 48 KB | — | — |
|
||
| `translations` | **0** | 48 KB | — | — |
|
||
| `analyses` | **0** | 32 KB | — | — |
|
||
| `odds_history` | **0** | 32 KB | — | — |
|
||
| `user_coupons` | **0** | 32 KB | — | — |
|
||
| `ai_predictions_log` | **0** | 32 KB | — | — |
|
||
| `user_coupon_items` | **0** | 24 KB | — | — |
|
||
|
||
### 16.3 Spor Bazlı Dağılım
|
||
|
||
| Spor | Maç Sayısı | Lig Sayısı | Takım (~) | Ort. Ev Skoru | Ort. Deplasman Skoru |
|
||
|------|-----------|-----------|----------|--------------|---------------------|
|
||
| **Futbol** | 189,291 | 1,094 | ~23,958 | **1.55** | **1.27** |
|
||
| **Basketbol** | 47,568 | 304 | ~5,770 | **84.36** | **81.57** |
|
||
|
||
### 16.4 Maç Olayları Dağılımı
|
||
|
||
| Olay Tipi | Toplam |
|
||
|-----------|--------|
|
||
| `substitute` (Oyuncu Değişikliği) | **787,101** |
|
||
| `card` (Kart) | **409,136** |
|
||
| `goal` (Gol) | **256,990** |
|
||
|
||
### 16.5 Canlı Maçlar (live_matches — 82 Kayıt)
|
||
|
||
| Spor | Durum | Status | Sayı |
|
||
|------|-------|--------|------|
|
||
| Futbol | `pre` (başlamamış) | timestamp | 41 |
|
||
| Futbol | `post` (bitmiş) | state | 4 |
|
||
| Futbol | `live` (canlı) | minutes | 1 |
|
||
| Basketbol | `pre` (başlamamış) | timestamp | 23 |
|
||
| Basketbol | `post` (bitmiş) | state | 13 |
|
||
|
||
### 16.6 Türkiye Ligleri (En Çok Maç)
|
||
|
||
| Lig | Maç Sayısı |
|
||
|-----|-----------|
|
||
| Nesine 3. Lig | 1,511 |
|
||
| Nesine 2. Lig | 1,295 |
|
||
| Trendyol 1. Lig | 988 |
|
||
| Trendyol Süper Lig | 959 |
|
||
| Türkiye Sigorta BSL (Basketbol) | 637 |
|
||
| Türkiye Sigorta TBL (Basketbol) | 450 |
|
||
| Ziraat Türkiye Kupası | 438 |
|
||
| Halkbank KBSL (Kadınlar Basketbol) | 436 |
|
||
| Halkbank Kadınlar Basketbol 1.Ligi | 383 |
|
||
|
||
### 16.7 Global Top 10 Lig (En Çok Maç)
|
||
|
||
| Lig | Ülke | Maç |
|
||
|-----|------|-----|
|
||
| Segunda Lig RFEF | İspanya | 3,848 |
|
||
| Non Lig Premier | İngiltere | 3,553 |
|
||
| NBA | ABD | 3,529 |
|
||
| Bölgesel Lig | Almanya | 3,457 |
|
||
| Hazırlık Maçları | Dünya | 3,454 |
|
||
| Serie C | İtalya | 2,923 |
|
||
| Ulusal Lig N/S | İngiltere | 2,843 |
|
||
| RFEF 3. Lig | İspanya | 2,297 |
|
||
| 2. Lig | İsveç | 2,202 |
|
||
| 3. Lig | Norveç | 2,188 |
|
||
|
||
### 16.8 Feeder Scan Durumu (app_settings)
|
||
|
||
| Scan Job | Son İşlenen Tarih | Güncelleme |
|
||
|----------|-------------------|------------|
|
||
| `historical_scan_state_football_basketball` | **2026-03-11** | 2026-03-11 21:03 |
|
||
| `historical_scan_state_football_filtered_desc` | **2025-09-01** | 2026-02-26 09:27 |
|
||
| `historical_scan_state_football_filtered` | **2023-10-16** | 2026-02-12 18:03 |
|
||
|
||
### 16.9 Kullanıcı Durumu
|
||
|
||
| Metrik | Değer |
|
||
|--------|-------|
|
||
| Toplam kullanıcı | **1** (test@test.com) |
|
||
| Rol | `user` |
|
||
| Abonelik | `free` |
|
||
| Kayıt tarihi | 2026-02-09 |
|
||
| Aktif kupon | 0 |
|
||
| Analiz geçmişi | 0 |
|
||
|
||
### 16.10 Hakem Rolleri
|
||
|
||
| ID | Rol |
|
||
|----|-----|
|
||
| 1 | Orta Hakem |
|
||
| 2 | Yardımcı Hakem |
|
||
| 3 | 4. Hakem |
|
||
| 4 | VAR |
|
||
| 5 | AVAR |
|
||
|
||
### 16.11 Boş/Kullanılmamış Tablolar
|
||
|
||
Aşağıdaki tablolar henüz production verisine sahip değildir:
|
||
|
||
- `translations` — DB tabanlı i18n (dosya tabanlı i18n kullanılıyor)
|
||
- `analyses` — Kullanıcı analiz kayıtları (kullanıcı yok)
|
||
- `odds_history` — Oran değişim takibi (henüz implemente edilmemiş)
|
||
- `user_coupons` / `user_coupon_items` — Kullanıcı kuponları (kullanıcı yok)
|
||
- `ai_predictions_log` — AI tahmin loglama (cleanup job siliyor veya henüz üretilmemiş)
|