BetAssist LITE Wiki
Zentrales Projekt-“Gehirn” - alle wichtigen Infos auf einen Blick.
Quick Links
| Thema | Datei |
|---|---|
| Architektur & Pipeline | architecture.md |
| Datenmodelle | models.md |
| Scraping (Neobet + Flashscore) | scraping.md |
| Scoring-Algorithmus | scoring.md |
| API Endpoints | api.md |
| Export (CSV + Excel) | export.md |
| Staking & Leben-System | staking.md |
| Produkt-Vision & Roadmap | roadmap.md |
Tech Stack
| Komponente | Technologie |
|---|---|
| API | Rust / Axum (Port 3030) |
| Scraping | thirtyfour (WebDriver) + scraper (HTML) |
| Browser | Headless Chrome via ChromeDriver (:9515) |
| Export | CSV (csv crate) + Excel (rust_xlsxwriter) |
| Scheduler | tokio-cron-scheduler (01:00 Uhr daily) |
| Deployment | systemd Services, Nginx Reverse Proxy |
Verzeichnisstruktur
/home/hlorenz/lite/
├── api/ # Rust API (dieses Projekt)
│ ├── src/
│ │ ├── main.rs # Entry Point, Server, Scheduler
│ │ ├── api/ # Axum Routes + Handler
│ │ ├── models/ # Datenstrukturen
│ │ ├── scrapers/ # Browser, Flashscore, Neobet
│ │ ├── services/ # Matcher, Scoring, Pipeline
│ │ └── export/ # CSV + Excel Export
│ └── Cargo.toml
├── exports/ # Generierte CSV/Excel Dateien
├── frontend/ # (geplant)
├── wiki/ # Diese Wiki
└── oldVersionRef/ # Referenz-Dateien
Pipeline (Kurzfassung)
Neobet (Heute+Morgen) → Flashscore (Matches) → League-Matcher
→ H2H (3 Seiten) → Odds (7 Seiten) → Scoring → Export
Mehr Details: architecture.md
Architektur & Pipeline
Gesamtablauf
Die Pipeline wird entweder per API-Call oder Scheduler (01:00 Uhr) ausgeloest.
┌─────────────┐ ┌──────────────────┐ ┌───────────────┐
│ 1. Neobet │────>│ 2. Flashscore │────>│ 3. Matcher │
│ Ligen │ │ Matches │ │ (Dice-Sim.) │
└─────────────┘ └──────────────────┘ └───────┬───────┘
│
gematchte Spiele
│
┌──────────────────┐ ┌───────▼───────┐
│ 5. Odds │<────│ 4. H2H │
│ (7 Seiten) │ │ (3 Seiten) │
└────────┬─────────┘ └───────────────┘
│
┌────────▼─────────┐ ┌───────────────┐
│ 6. Scoring │────>│ 7. Export │
│ (12 Kriterien) │ │ CSV + Excel │
└──────────────────┘ └───────────────┘
Schritt-Detail
1. Neobet Ligen
- URL:
https://neobet.de/de/Sportwetten/Heute+Morgen/Fussball/Alle - Liefert: Liste aller Ligen mit Spielen (Land, Liga)
- Deckt Heute + Morgen in einem Aufruf ab
2. Flashscore Matches
- URL:
https://www.flashscore.com/ - Date Picker Navigation via Pfeil-Buttons (URL-Parameter
?d=wird ignoriert!) - Liefert: Match-Liste mit IDs, Teams, Zeiten, Ligen
3. League Matcher
- Algorithmus: Soerensen-Dice Bigram-Aehnlichkeit
- Gewichtung: 30% Land + 70% Liga
- Schwellwert: 0.6 Confidence
- Ergebnis: Flashscore-Matches die auch auf Neobet verfuegbar sind
4. H2H Scraping (pro Match)
- 3 Seiten: Home, Away, Overall
- Extrahiert: letzte 15 Ergebnisse pro Seite
- Berechnet: Intervalle (o1.5-o4.5, u0.5-u1.5, BTS, 1TS), Durchschnitte, Streaks
5. Odds Scraping (pro Match)
- 7 Seiten: O/U FT, O/U 1H, O/U 2H, BTTS, 1X2, DC, DNB
- Quoten aller Buchmacher gemittelt
- Graceful Handling: Fehler = None, Match wird trotzdem gespeichert
6. Scoring
- 12 Kriterien, Rang-basiertes Punktesystem
- Top 4 Matches pro Kriterium bekommen +1 Punkt
- Ergebnis: max 4 Over-Picks (max 7 Punkte) + max 4 Under-Picks (max 5 Punkte)
7. Export
- CSV: 56 Spalten, flach
- Excel: 3 Worksheets (Daten, Quoten, Wunschliste)
- Pfad:
/home/hlorenz/lite/exports/
Technische Besonderheiten
| Problem | Loesung |
|---|---|
eval_js() gibt null zurueck | driver.source() + scraper crate fuer HTML-Parsing |
Flashscore ignoriert ?d= URL-Param | Date Picker Pfeil-Buttons klicken |
| Neobet Heute vs Morgen | Kombinierte URL Heute+Morgen |
| Rate Limiting | 500ms Delay zwischen H2H-Requests, 2.5s Warte nach Odds-Navigation |
Key Files
| Datei | Verantwortung |
|---|---|
src/main.rs | Server, Logging, Scheduler |
src/services/scraper_service.rs | Pipeline-Orchestrierung |
src/services/matcher.rs | Liga-Matching (Dice) |
src/services/scoring.rs | Scoring-Algorithmus |
src/scrapers/flashscore.rs | Flashscore Scraper (~1000 Zeilen) |
src/scrapers/neobet.rs | Neobet Scraper |
src/scrapers/browser.rs | WebDriver Management |
Datenmodelle
Alle Modelle in src/models/. Jedes Modul hat eigene Datei.
NeobetMatch / NeobetLeague
NeobetLeague { country, league, first_match_time?, match_count? }
NeobetMatch { country, league, home_team, away_team, kickoff_time?, date }
Quelle: Neobet Scraper. Verwendet fuer Liga-Matching.
FlashscoreMatch / FlashscoreLeague
FlashscoreMatch {
match_id, home_team, away_team,
home_team_id, away_team_id, // fuer URL-Konstruktion
kickoff_time?, date,
country, league, h2h_url,
final_score? // nur bei beendeten Spielen
}
FlashscoreLeague { country, league, league_id? }
MatchScore { home, away } // Methods: total_goals(), is_over(), is_btts()
AnalyzedMatch (Hauptstruktur)
Das zentrale Datenobjekt nach H2H-Analyse. Wird fuer Scoring + Export verwendet.
AnalyzedMatch {
h2h_url, kickoff_time, match_name, country, league,
// Durchschnitte (venue-specific)
home_avg_scored?, home_avg_conceded?,
away_avg_scored?, away_avg_conceded?,
sum_conceded?, sum_scored?,
// Backtesting
backtesting_result?, // "2:1" bei beendeten Spielen
// Spiele seit letztem Event
games_since_o15_home?, games_since_o15_away?,
games_since_o25_home?, games_since_o25_away?,
games_since_zero_home?, games_since_zero_away?,
// Intervall-Daten (venue + overall)
intervals: MatchIntervals,
// Quoten (alle Maerkte)
odds?: MatchOdds,
}
MatchIntervals
32 Felder: 16 venue-specific + 16 overall. Jedes Feld ist Option<IntervalData>.
Venue-specific: o15_home/away, o25_home/away, o35_home/away, o45_home/away, u05_home/away, u15_home/away, bts_home/away, ots_home/away
Overall: gleiche 8 Typen mit _overall Suffix.
IntervalData {
intervals: Vec<u32>, // Spiele zwischen Events [3,1,2,5]
current_streak: u32, // Spiele seit letztem Event
raw: String, // "3,1,2,5 (2)" fuer CSV
}
// Methods: parse(s), average(), max(), min()
MatchOdds
MatchOdds {
ou_full_time: Vec<OverUnderOdds>, // pro Schwellwert (0.5-4.5)
ou_first_half: Vec<OverUnderOdds>,
ou_second_half: Vec<OverUnderOdds>,
btts?: BttsOdds,
one_x_two?: OneXTwoOdds,
double_chance?: DoubleChanceOdds,
draw_no_bet?: DrawNoBetOdds,
}
// Lookup: ou_ft(2.5), ou_1h(1.5), ou_2h(1.5)
Quoten-Typen:
| Typ | Felder |
|---|---|
| OverUnderOdds | threshold, over, under, bookmaker_count |
| OneXTwoOdds | home, draw, away, bookmaker_count |
| BttsOdds | yes, no, bookmaker_count |
| DoubleChanceOdds | home_draw, home_away, draw_away, bookmaker_count |
| DrawNoBetOdds | home, away, bookmaker_count |
Scoring-Modelle
ScoringResult { date, total_matches, over_picks, under_picks, over_criteria_count=7, under_criteria_count=5 }
Pick { match_name, kickoff_time, country, league, score, max_score, criteria: Vec<ScoringCriterion> }
ScoringCriterion { name, value, rank }
Export-Modelle
ExportConfig { directory="../exports", csv=true, excel=true, filename_prefix="match_data" }
ExportResult { date, match_count, csv_path?, excel_path?, exported_at, scoring? }
Scraping
Browser-Setup
- WebDriver: thirtyfour 0.35
- ChromeDriver: localhost:9515 (systemd Service)
- Modus: Headless (konfigurierbar via
HEADLESSenv) - Navigation: 4 Versuche mit exponentiellem Backoff
- HTML-Parsing:
driver.source()+scrapercrate (eval_js gibt null zurueck!)
Neobet
URL: https://neobet.de/de/Sportwetten/Heute+Morgen/Fussball/Alle
Ablauf:
- Seite laden, bis zu 30s auf Rendering warten
- HTML-Source holen
- Liga-Links parsen:
a[href*="/Fussball/"] - Land + Liga aus Breadcrumbs extrahieren
Ergebnis: Vec<NeobetLeague> mit Land, Liga, Spielanzahl
Einzelne Liga-Matches: URL Sportwetten/{Heute|Morgen}/Fussball/{Land}/{Liga}
- Team-Paare aus Match-Containern extrahieren
Flashscore
Base URL: https://www.flashscore.com/
Match-Liste
Date Picker Navigation (URL-Param ?d= wird von der SPA ignoriert!):
- Flashscore laden, Cookies wegklicken
- Tage-Differenz berechnen (Heute = 0)
- Overlay-iFrames verstecken (
display:none) - Pfeil-Button klicken:
button[data-day-picker-arrow="next"]oder"prev" - 1.5s Pause nach jedem Klick
- Validierung:
button[data-testid="wcl-dayPickerButton"]Text pruefen (Format “DD/MM Tag”)
Match-Extraktion aus HTML:
- Laender-Header:
div.event__headermitspan.event__title--type - Match-Rows:
div.event__match - Match-ID:
id="g_1_{matchId}" - Team-IDs:
a.event__participant→ href/team/{name}/{teamId}/ - Zeiten:
div.event__time - Scores (beendete Spiele):
span.event__score
H2H (3 Seiten pro Match)
URL-Schema: /match/football/{homeId}/{awayId}/h2h/{tab}/?mid={matchId}
| Tab | Was |
|---|---|
home | Nur Heimspiele des Heimteams + Auswaertsspiele des Auswaertsteams |
away | Umgekehrt |
overall | Alle Spiele beider Teams |
Ablauf pro Seite:
- Navigieren, 3s warten
- “Show more” Buttons in allen Sektionen klicken
- HTML-Source holen
- Score-Elemente:
span.h2h__result > span > span(2 Child-Spans!) - Letzte 15 Ergebnisse pro Team extrahieren
Berechnungen aus Ergebnissen:
- Durchschnitte: avg_scored, avg_conceded (Tore erzielt/kassiert)
- Intervalle: Spiele zwischen Events fuer o1.5, o2.5, o3.5, o4.5, u0.5, u1.5, BTS, 1TS
- Streaks: Aktuelle Serie seit letztem Event
Odds (7 Seiten pro Match)
URL-Schema: Aus h2h_url die Match-Base ableiten, dann /odds/{suffix}/
| Seite | URL-Suffix | Spalten |
|---|---|---|
| O/U Full Time | odds/over-under/full-time/ | 2 + Threshold |
| O/U 1st Half | odds/over-under/1st-half/ | 2 + Threshold |
| O/U 2nd Half | odds/over-under/2nd-half/ | 2 + Threshold |
| BTTS | odds/both-teams-to-score/ | 2 |
| 1X2 | odds/1x2-odds/full-time/ | 3 |
| Double Chance | odds/double-chance/ | 3 |
| Draw No Bet | odds/draw-no-bet/ | 2 |
HTML-Selektoren:
- Zeile:
.ui-table__row - Buchmacher:
img[class*="logoImage"]→ alt - Schwellwert (O/U):
[class*="oddsValue"]→ Text - Quoten:
.oddsCell__odd→ Text
Averaging: Alle Buchmacher-Quoten pro Schwellwert gemittelt.
Error Handling: Graceful - Fehler bei einer Odds-Seite = warn-Log, Match wird ohne diese Quoten gespeichert.
Scoring-Algorithmus
Prinzip
Rang-basiertes Punktesystem. Alle Matches des Tages werden gegeneinander gerankt. Pro Kriterium bekommen die Top 4 Matches je +1 Punkt. Am Ende: Top 4 nach Gesamtpunkten.
Kriterien
Over 2.5 (7 Kriterien, max 7 Punkte)
| # | Kriterium | Richtung | Erklaerung |
|---|---|---|---|
| 1 | SUM Erzielt | DESC | Hohe Torproduktion = gut fuer Over |
| 2 | SUM Kassiert | DESC | Viele kassierte Tore = gut fuer Over |
| 3 | Seit o2.5 H+A | ASC | Kuerzer = kuerzlich passiert = gut |
| 4 | Seit o1.5 H+A | ASC | Kuerzer = gut |
| 5 | o2.5 Intervall | ASC | Niedriger Composite = haeufiger |
| 6 | o1.5 Intervall | ASC | Niedriger Composite = haeufiger |
| 7 | o3.5 Intervall | ASC | Niedriger Composite = haeufiger |
Under 2.5 (5 Kriterien, max 5 Punkte)
| # | Kriterium | Richtung | Erklaerung |
|---|---|---|---|
| 8 | SUM Erzielt | ASC | Wenig Tore = gut fuer Under |
| 9 | SUM Kassiert | ASC | Wenig kassiert = gut fuer Under |
| 10 | Seit 0 Tore H+A | ASC | Kuerzlich 0 Tore = gut |
| 11 | u0.5 Intervall | ASC | Haeufig unter 0.5 = gut |
| 12 | u1.5 Intervall | ASC | Haeufig unter 1.5 = gut |
Intervall-Composite Score
composite = avg(home_streak, away_streak) + avg(home_avg_interval, away_avg_interval)
Niedrigerer Wert = Event passiert haeufiger UND ist aktueller = besser.
Ablauf
- Fuer jedes Kriterium: Werte aller Matches extrahieren, sortieren
- Top
TOP_N = 4Matches bekommen +1 Punkt - Nach allen Kriterien: Matches nach Gesamtpunkten sortieren
- Top 4 Over-Picks + Top 4 Under-Picks (Score > 0) ausgeben
Ergebnis
ScoringResult {
over_picks: max 4 Picks mit score/7
under_picks: max 4 Picks mit score/5
}
Jeder Pick enthaelt die einzelnen Kriterien-Details (Name, Wert, Rang).
API Endpoints
Server: Axum auf 0.0.0.0:3030
CORS: GET/POST/OPTIONS, alle Origins
Binary: /home/hlorenz/lite/api/target/release/betassist-lite
Endpoints
Health Check
GET /health
→ { "status": "ok", "version": "0.1.0" }
Scraping ausloesen
POST /api/v1/scrape/today # Heute scrapen
POST /api/v1/scrape/tomorrow # Morgen scrapen
POST /api/v1/scrape/:date # Beliebiges Datum (YYYY-MM-DD)
Response:
{
"success": true,
"date": "2026-02-22",
"matches_found": 42,
"csv_path": "../exports/match_data_2026-02-22.csv",
"excel_path": "../exports/match_data_2026-02-22.xlsx",
"predictions": { "over_picks": [...], "under_picks": [...] }
}
Predictions abrufen
GET /api/v1/predictions/:date
Liest CSV vom Dateisystem, fuehrt Scoring erneut aus, gibt Ergebnis zurueck.
{
"success": true,
"date": "2026-02-22",
"predictions": {
"over_picks": [...],
"under_picks": [...],
"total_matches": 42
}
}
Noch nicht implementiert (TODO)
GET /api/v1/matches/today # → []
GET /api/v1/matches/:date # → []
GET /api/v1/exports # → []
GET /api/v1/exports/:date # → 404
Scheduler
- Cron:
0 0 1 * * *(taeglich 01:00 Uhr) - Fuehrt aus:
run_today()+run_tomorrow() - Konfigurierbar:
ENABLE_SCHEDULER=true/false
AppState
#![allow(unused)]
fn main() {
AppState {
scraper: RwLock<Option<Arc<ScraperService>>>, // lazy init
config: ScraperConfig,
}
}
ScraperService wird beim ersten API-Call initialisiert (Lazy Pattern).
Export
Verzeichnis: /home/hlorenz/lite/exports/
Dateiname: match_data_{YYYY-MM-DD}.{csv|xlsx}
CSV (56 Spalten)
| Bereich | Spalten | Anzahl |
|---|---|---|
| Match-Info | URL, Zeit, Spiel, Land, Liga | 5 |
| Durchschnitte | Heim/Ausw Erzielt/Kassiert, SUM | 6 |
| Backtesting | Ergebnis | 1 |
| Spiele-seit | o1.5/o2.5/0-Tore H+A | 6 |
| Intervalle (venue) | o1.5-o4.5, u0.5-u1.5, BTS, 1TS je H+A | 16 |
| Intervalle (overall) | gleiche 8 Typen je H+A | 16 |
| Quoten | O/U 2.5 FT, BTTS, 1X2 | 6 |
Intervall-Format in Zellen: "3,1,2,5 (2)" (Intervalle + aktuelle Serie)
Excel (3 Worksheets)
Sheet 1: Hauptdaten
- 50 Spalten (wie CSV ohne Quoten-Spalten)
- Numerische Werte als Zahlen (nicht Strings)
- Fett-Header, angepasste Spaltenbreiten
Sheet 2: “Quoten” (34 Spalten)
| Bereich | Spalten |
|---|---|
| Spiel, Zeit | 2 |
| 1X2 | Heim, Unent., Ausw. (3) |
| BTTS | Ja, Nein (2) |
| Double Chance | 1X, 12, X2 (3) |
| Draw No Bet | Heim, Ausw. (2) |
| O/U Full Time | 0.5-4.5 je Over+Under (10) |
| O/U 1st Half | 0.5-2.5 je Over+Under (6) |
| O/U 2nd Half | 0.5-2.5 je Over+Under (6) |
Nur erstellt wenn mindestens ein Match Quoten hat.
Sheet 3: “Wunschliste”
Over 2.5 Picks (gruen) + Under 2.5 Picks (rot).
| Spalte | Inhalt |
|---|---|
| # | Rang |
| Spiel | Matchname |
| Zeit | Anstosszeit |
| Land | Land |
| Liga | Liga |
| Score | z.B. “5/7” |
| Details | Kriterien-Aufschluesselung |
Nur erstellt wenn Scoring-Ergebnisse vorhanden.
Staking Tables & Leben-System
Referenz: /home/hlorenz/bet-assist-core/app/v0/
Leben (Lives) = Safe Rounds
Maximale Anzahl aufeinanderfolgender Verluste bevor Totalverlust.
Berechnung:
maxLives = quote + RISK_OFFSET
| Risikostufe | Offset | Bei Quote 4 |
|---|---|---|
| risky | 0 | 4 Leben |
| medium | +1 | 5 Leben |
| safe | +2 | 6 Leben |
| ultra_safe | +3 | 7 Leben |
| marathon | +4 | 8 Leben |
| immortal | +5 | 9 Leben |
| eternal | +6 | 10 Leben |
Verhalten:
- GEWINN: Lives werden auf maxLives ZURUECKGESETZT, Loop startet bei Runde 1
- VERLUST: 1 Leben weg, naechste Runde (hoeherer Einsatz), Bankroll bleibt gleich
- 0 Leben: Plan deaktiviert (Totalverlust)
Run Table (Staking Table)
Modifiziertes Martingale: Jede Runde garantiert den GLEICHEN Netto-Gewinn bei Sieg.
Kernformel:
r = quote / (quote - 1)
profit = bankroll / (r^maxRounds - 1)
stake_runde_1 = profit / (quote - 1)
stake_runde_n = (total_gesetzt + profit) / (quote - 1)
stake_letzte = bankroll - total_gesetzt (exakter Rest)
Invariante: potential_win - total_staked = profit (KONSTANT fuer alle Runden!)
Beispiel (Quote=4, medium/5 Runden, Bankroll=100EUR):
| Runde | Einsatz | Gesamt | Gewinn | Netto-Profit |
|---|---|---|---|---|
| 1 | 10.37 | 10.37 | 41.48 | 31.11 |
| 2 | 13.83 | 24.20 | 55.32 | 31.12 |
| 3 | 18.44 | 42.64 | 73.76 | 31.12 |
| 4 | 24.58 | 67.22 | 98.32 | 31.10 |
| 5 | 32.78 | 100.00 | 131.12 | 31.12 |
Skalierung: Basistabelle immer fuer 100 EUR, dann proportional auf tatsaechliche Bankroll.
Ueberlebenswahrscheinlichkeit
win_prob_per_runde = 1 / quote
survival_pro_loop = 1 - (1 - win_prob)^maxRounds
erwartete_loops_bis_totalverlust = 1 / (1 - survival)
| Stufe | Leben (Q=4) | Profit% | Survival/Loop | Loops bis Verlust |
|---|---|---|---|---|
| risky | 4 | ~46% | ~68% | ~3 |
| medium | 5 | ~31% | ~76% | ~4 |
| safe | 6 | ~22% | ~82% | ~5.5 |
| ultra_safe | 7 | ~15% | ~87% | ~7.5 |
| marathon | 8 | ~11% | ~90% | ~10 |
| immortal | 9 | ~8% | ~93% | ~14 |
| eternal | 10 | ~6% | ~95% | ~20 |
Wettplan (Instance)
Drei Bankroll-Werte:
originalBankroll → aendert sich NIE (Referenzwert)
bankroll → Basis fuer Skalierung, steigt nach jedem Gewinn
currentBankroll → Aktuell verfuegbar, sinkt wenn Wette platziert
Eingaben bei Erstellung:
- Name, Buchmacher, Bankroll (min 10 EUR), Quote (2-30)
- Risikostufe, Ziel-Multiplikator (2x, 3x, 5x, 10x)
- Kategorie: standard oder longterm
Gewinn-Pfad:
gewinn = stake * quote
currentBankroll += gewinn
bankroll = currentBankroll (neue Basis)
livesRemaining = maxLives (Reset)
currentLoopRound = 0 (Neustart mit groesserer Bankroll)
→ Ziel pruefen (currentBankroll >= targetAmount?)
Verlust-Pfad:
livesRemaining -= 1
currentLoopRound bleibt (naechste Runde = +1 im Table)
bankroll UNVERAENDERT
→ livesRemaining <= 0? Plan tot.
Alte DB-Felder (Supabase Postgres)
betting_instances:
id, user_id, bookmaker_id, name,
original_bankroll_cents, bankroll_cents, current_bankroll_cents,
target_multiplier, target_amount_cents, target_achieved, final_profit_cents,
quote, risk_factor, run_table_id, category, risk_modifier,
survival_probability, max_lives, lives_remaining, lives_used,
active, locked, current_round, created_at, updated_at
betting_sessions:
id, instance_id, user_id,
current_round, lives_remaining, max_lives,
total_rounds, total_wins, total_losses,
current_loop_active, current_loop_round, current_loop_total_staked_cents,
current_loop_id, can_close, level, total_xp,
created_at, last_updated
Betraege in Cent (Integer) fuer Praezision.
Frontend
Tech Stack
| Komponente | Technologie |
|---|---|
| Framework | React 19 + TypeScript |
| Build Tool | Vite 7 |
| Routing | React Router DOM 7 |
| Auth | Supabase (managed) |
| State | React Hooks + localStorage |
| Styling | Custom CSS (Glassmorphic Design) |
Seiten / Routen
| Route | Seite | Beschreibung |
|---|---|---|
/login | Login | Anmeldung / Registrierung via Supabase |
/ | Dashboard | Aktiver Plan, Tages-Predictions |
/setup/bookmaker | Bookmaker Setup | Wizard: Anbieter waehlen + Einzahlung |
/setup/plan | Plan Setup | Wizard: Risiko, Ziel, Budget, Quote |
/plan/:id | Plan Detail | Run Table, aktive Wetten, Historie |
Auth Flow
- User landet auf
/login(oeffentliche Route) - Registrierung (Name, Email, Passwort) oder Login
- Supabase verwaltet Auth-State via JWT
- Geschuetzte Routen per
AuthGuard(redirect zu Login wenn nicht eingeloggt) - Sign-out loescht Session
Design System
- Farben: Deep Blue Background (
#070b14), Cyan Glow (#00d4ff), Purple (#8b5cf6), Green (#00ff88), Red (#ff3366), Gold (#ffd700) - Fonts: Inter (Body), JetBrains Mono (Zahlen/Betraege)
- Komponenten: Glass Cards (blur + backdrop filter), Pill Buttons, Risk Cards
- Animationen: Fade-in, Heart Break/Gain, Confetti bei Gewinn
- Responsive: Breakpoint bei 640px, Flex/Grid Layouts
State Management
Kein globaler Store - jeder Feature-Bereich hat einen eigenen Hook:
| Hook | localStorage Key | Funktion |
|---|---|---|
useBookmakers() | ba_bookmakers | Wettanbieter verwalten |
usePlans() | ba_plans | Wettplaene CRUD |
useBets() | ba_bets | Wetten + Ergebnisse |
Jeder Hook bietet refresh() zum Neuladen nach Aenderungen.
Betting Flow
- Dashboard zeigt Tages-Predictions von API (
/api/v1/predictions/{date}) - User klickt Pick → Modal mit Details (Match, Liga, Tipp, Quote, Einsatz, Gewinn)
- Bestaetigung → Wette in localStorage gespeichert
- Plan-Detail zeigt aktive Wette mit Win/Loss Buttons
- Win: Lives Reset + Bankroll waechst, Loss: 1 Leben weniger
Run Table
Mathematische Einsatz-Berechnung:
r = quote / (quote - 1)(Martingale-Faktor)- Konstanter Profit pro Runde
- Rekursive Berechnung ueber alle Runden
- Visualisierung mit Fortschrittsbalken zum Ziel
Build & Deployment
# Development
cd /home/hlorenz/lite/frontend
npm run dev # Vite Dev Server auf :5173, Proxy zu API :3030
# Production Build
npm run build # Output in dist/
# Deployment
# Static Files in dist/ werden von Nginx served
# API Proxy ueber Nginx location /api/ → localhost:3030
Verzeichnisstruktur
frontend/
├── src/
│ ├── main.tsx # Entry Point
│ ├── App.tsx # Router Setup
│ ├── pages/ # Seiten-Komponenten
│ ├── components/ # Shared Components
│ ├── hooks/ # Custom Hooks (useStore, useAuth)
│ ├── styles/ # CSS Dateien
│ └── lib/ # Utilities, Supabase Client
├── dist/ # Production Build Output
├── vite.config.ts # Vite Config mit API Proxy
└── package.json
Produkt-Vision & Roadmap
Vision
Minimalistische Wett-Assistent App:
- Login (einmalig)
- Wettkonto einrichten (Anbieter, Bankroll)
- Wettplan definieren (Ziel, Strategie)
- Dashboard: Top-Auswahl passend zum aktiven Plan
- Staking Tables mit “Leben”-System
Geplante Architektur
┌────────────┐ ┌─────────────┐ ┌──────────┐
│ Frontend │────>│ Rust API │────>│ SQLite │
│ (SPA) │<────│ (Axum) │<────│ │
└────────────┘ └──────┬──────┘ └──────────┘
│
┌──────▼──────┐
│ Scraping │
│ Engine │
└─────────────┘
Datenbank (SQLite)
Geplante Tabellen:
| Tabelle | Inhalt |
|---|---|
| users | Login, Auth |
| betting_plans | Ziel, Strategie, Bankroll, Status |
| matches | Tagesergebnisse (AnalyzedMatch Daten) |
| odds | Quoten pro Match |
| picks | Scoring-Ergebnisse, Empfehlungen |
Warum SQLite: Kein separater DB-Server noetig, eingebettet, perfekt fuer Single-Server Setup.
Staking / “Leben”-System
Vollstaendig analysiert! Siehe staking.md fuer Details.
Kurzfassung:
- Leben = quote + risk_offset (4-10 je nach Stufe)
- Martingale-Staking mit konstantem Profit pro Runde
- Gewinn = Lives Reset + Bankroll waechst, Verlust = 1 Leben weg
- 7 Risikostufen: risky bis eternal
Roadmap
Phase 1: Scraping Engine (erledigt)
- Neobet + Flashscore Scraping
- League Matching
- H2H Analyse mit Intervallen
- Odds Scraping (alle 7 Maerkte)
- Scoring-Algorithmus
- CSV + Excel Export
- REST API
- Scheduler (01:00 daily)
- Heute + Morgen Unterstuetzung
- Projekt-Wiki
Phase 2: Frontend (erledigt)
- Alte bet-assist App analysieren (Staking/Leben)
- React + TypeScript + Vite Setup
- Supabase Auth (Login/Registration)
- Wettkonto Setup (Bookmaker + Einzahlung)
- Wettplan Setup (Risiko, Ziel, Budget, Quote)
- Dashboard mit Tages-Predictions
- Betting Flow (Pick → Modal → Bestaetigung)
- Run Table mit Martingale-Berechnung
- Leben-System mit Heart-Visualisierung
- Glassmorphic Design System
- Responsive Layout
- Deployment (Nginx Static Files)
- Wiki Dokumentation
Phase 3: Datenbank + Backend
- SQLite Integration
- Match-Daten in DB speichern
- User-Daten serverseitig (aktuell localStorage)
- Wettplan-Management API
Phase 4: Intelligence
- Plan-basierte Filterung
- Personalisierte Empfehlungen
- Ergebnis-Tracking
- Statistiken/Historie