Initial commit: Eurojackpot analysis and prediction system
This repository contains a comprehensive Eurojackpot lottery analysis and prediction system including: - Historical data analysis and processing - ML-based prediction models - Automated weekly tip generation - Position and range analysis tools - Notification system for results 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
commit
70e0638dee
67 files changed
+8491869
No files matched your search
@@ -0,0 +1,358 @@
|
||||
# Eurojackpot Automation System
|
||||
|
||||
Vollautomatisches System für wöchentliche Tipp-Generierung und Learning nach Ziehungen.
|
||||
|
||||
## 📋 Überblick
|
||||
|
||||
Das System besteht aus 2 Hauptkomponenten:
|
||||
|
||||
1. **Weekly Tip Generator** - Generiert automatisch Tipps vor Ziehungen
|
||||
2. **Auto Update & Learn** - Aktualisiert Daten und lernt nach Ziehungen
|
||||
|
||||
## 🚀 Installation
|
||||
|
||||
### 1. Virtuelle Umgebung aktivieren
|
||||
|
||||
```bash
|
||||
cd "/Users/sebastianfrohlich/Library/Mobile Documents/com~apple~CloudDocs/Jupyter Notebooks/Eurojackpot"
|
||||
source venv/bin/activate
|
||||
```
|
||||
|
||||
### 2. Scripts ausführbar machen
|
||||
|
||||
```bash
|
||||
chmod +x scripts/automation/*.py
|
||||
```
|
||||
|
||||
## 🎯 Manuelle Nutzung
|
||||
|
||||
### Tipps generieren
|
||||
|
||||
```bash
|
||||
# Normale Generierung (prüft ob nötig)
|
||||
python scripts/automation/weekly_tip_generator.py
|
||||
|
||||
# Erzwinge Generierung
|
||||
python scripts/automation/weekly_tip_generator.py --force
|
||||
|
||||
# Generiere 20 Tipps statt 10
|
||||
python scripts/automation/weekly_tip_generator.py --num-tips 20
|
||||
|
||||
# Zeige nur Historie
|
||||
python scripts/automation/weekly_tip_generator.py --history
|
||||
```
|
||||
|
||||
### Nach Ziehung aktualisieren
|
||||
|
||||
```bash
|
||||
# Kompletter Workflow: Update + Evaluation + Learning
|
||||
python scripts/automation/auto_update_and_learn.py
|
||||
```
|
||||
|
||||
## ⏰ Automatisierung mit Cron
|
||||
|
||||
### Setup
|
||||
|
||||
1. Öffne Crontab:
|
||||
```bash
|
||||
crontab -e
|
||||
```
|
||||
|
||||
2. Füge folgende Zeilen hinzu:
|
||||
|
||||
```bash
|
||||
# Pfad zur virtuellen Umgebung
|
||||
EUROJACKPOT_PATH="/Users/sebastianfrohlich/Library/Mobile Documents/com~apple~CloudDocs/Jupyter Notebooks/Eurojackpot"
|
||||
|
||||
# Montag & Donnerstag 09:00 Uhr: Tipps generieren (vor Ziehung)
|
||||
0 9 * * 1,4 cd "$EUROJACKPOT_PATH" && source venv/bin/activate && python scripts/automation/weekly_tip_generator.py >> logs/tips_generation.log 2>&1
|
||||
|
||||
# Dienstag & Freitag 21:00 Uhr: Update nach Ziehung
|
||||
0 21 * * 2,5 cd "$EUROJACKPOT_PATH" && source venv/bin/activate && python scripts/automation/auto_update_and_learn.py >> logs/auto_update.log 2>&1
|
||||
```
|
||||
|
||||
3. Speichern (ESC, :wq in vim)
|
||||
|
||||
### Cron Zeitplan
|
||||
|
||||
```
|
||||
Montag 09:00 → Tipps für Dienstag-Ziehung generieren
|
||||
Dienstag 20:00 → Ziehung findet statt
|
||||
Dienstag 21:00 → Auto-Update & Learning
|
||||
|
||||
Donnerstag 09:00 → Tipps für Freitag-Ziehung generieren
|
||||
Freitag 20:00 → Ziehung findet statt
|
||||
Freitag 21:00 → Auto-Update & Learning
|
||||
```
|
||||
|
||||
### Logs prüfen
|
||||
|
||||
```bash
|
||||
# Erstelle Log-Verzeichnis
|
||||
mkdir -p logs
|
||||
|
||||
# Zeige letzte Tipps-Generierung
|
||||
tail -50 logs/tips_generation.log
|
||||
|
||||
# Zeige letzte Updates
|
||||
tail -50 logs/auto_update.log
|
||||
```
|
||||
|
||||
## 📊 Dateien & Verzeichnisse
|
||||
|
||||
```
|
||||
data/
|
||||
├── generated_tips/ # Generierte Tipps
|
||||
│ ├── weekly_tips_*.csv # Tipp-Dateien
|
||||
│ └── generation_history.json # Historie
|
||||
│
|
||||
├── performance_reports/ # Performance-Reports
|
||||
│ └── report_*.txt # Reports nach Ziehungen
|
||||
│
|
||||
├── learning_log.json # Learning-Historie
|
||||
└── backups/ # Automatische Backups
|
||||
|
||||
logs/
|
||||
├── tips_generation.log # Cron Log für Generierung
|
||||
└── auto_update.log # Cron Log für Updates
|
||||
```
|
||||
|
||||
## 🔍 Features im Detail
|
||||
|
||||
### Weekly Tip Generator
|
||||
|
||||
**Intelligente Prüfung:**
|
||||
- Generiert nur wenn nötig (> 3 Tage seit letzter Generierung)
|
||||
- Berücksichtigt Wochentage (Montag/Donnerstag vor Ziehungen)
|
||||
- Vermeidet unnötige Generierungen
|
||||
|
||||
**Historie-Tracking:**
|
||||
- Speichert alle Generierungen
|
||||
- Trackt Confidence & Quality Scores
|
||||
- Ermöglicht Performance-Analyse über Zeit
|
||||
|
||||
**Ausgabe:**
|
||||
```
|
||||
📊 GENERIERUNGS-HISTORIE
|
||||
======================================================================
|
||||
Nr Datum Tips Confidence Quality Datei
|
||||
----------------------------------------------------------------------
|
||||
1 2025-01-20 09:00 10 0.5823 0.6734 weekly_tips_20250120_090000.csv
|
||||
2 2025-01-16 09:00 10 0.5891 0.6812 weekly_tips_20250116_090000.csv
|
||||
```
|
||||
|
||||
### Auto Update & Learn
|
||||
|
||||
**4-Schritt-Workflow:**
|
||||
|
||||
1. **Daten aktualisieren**
|
||||
- Lädt neueste Ziehung von API
|
||||
- Erstellt automatisches Backup
|
||||
- Validiert Daten
|
||||
|
||||
2. **Neue Ziehung prüfen**
|
||||
- Erkennt automatisch neue Ziehungen
|
||||
- Verhindert Doppel-Verarbeitung
|
||||
- Extrahiert Ziehungsdaten
|
||||
|
||||
3. **Tipps evaluieren**
|
||||
- Vergleicht letzte Tipps mit Ziehung
|
||||
- Zählt Treffer (Main + Euro)
|
||||
- Ermittelt beste Strategien
|
||||
|
||||
4. **Learning Update**
|
||||
- Passt ML-Modelle an
|
||||
- Aktualisiert Predictions
|
||||
- Speichert Performance-Metriken
|
||||
|
||||
**Evaluation Output:**
|
||||
```
|
||||
🎯 EVALUIERE LETZTE TIPPS
|
||||
======================================================================
|
||||
Tip Strategie Main Euro Gesamt Bewertung
|
||||
------------------------------------------------------------
|
||||
#1 PURE-AI 2 1 3 ✅ Gut
|
||||
#2 HYBRID-OPT 3 0 3 ✅ Gut
|
||||
#3 PURE-PATTERN 1 1 2 👍 OK
|
||||
...
|
||||
|
||||
🏆 Bester Tipp: #2 (3 Main + 0 Euro)
|
||||
```
|
||||
|
||||
## 📈 Performance-Reports
|
||||
|
||||
Reports werden automatisch nach jeder Ziehung erstellt:
|
||||
|
||||
```
|
||||
======================================================================
|
||||
EUROJACKPOT PERFORMANCE REPORT
|
||||
======================================================================
|
||||
Erstellt: 2025-01-17 21:05:23
|
||||
|
||||
ZIEHUNG VOM 2025-01-17
|
||||
----------------------------------------------------------------------
|
||||
Hauptzahlen: [3, 9, 12, 24, 39]
|
||||
Eurozahlen: [5, 10]
|
||||
|
||||
EVALUATION DER TIPPS
|
||||
----------------------------------------------------------------------
|
||||
Datei: weekly_tips_20250115_090000.csv
|
||||
Tipps evaluiert: 10
|
||||
Avg Main Matches: 1.80
|
||||
Avg Euro Matches: 0.60
|
||||
Bester Tipp: #5
|
||||
- Main Treffer: 3
|
||||
- Euro Treffer: 1
|
||||
======================================================================
|
||||
```
|
||||
|
||||
## 🛠️ Troubleshooting
|
||||
|
||||
### "No module named 'requests'"
|
||||
|
||||
```bash
|
||||
cd "/Users/sebastianfrohlich/Library/Mobile Documents/com~apple~CloudDocs/Jupyter Notebooks/Eurojackpot"
|
||||
source venv/bin/activate
|
||||
pip install requests beautifulsoup4 pandas numpy scikit-learn
|
||||
```
|
||||
|
||||
### "Permission denied"
|
||||
|
||||
```bash
|
||||
chmod +x scripts/automation/*.py
|
||||
```
|
||||
|
||||
### Cron läuft nicht
|
||||
|
||||
```bash
|
||||
# Prüfe Cron-Service
|
||||
launchctl list | grep cron
|
||||
|
||||
# Prüfe System-Logs
|
||||
tail -f /var/log/system.log | grep cron
|
||||
|
||||
# Test manuell
|
||||
cd "/path/to/eurojackpot"
|
||||
source venv/bin/activate
|
||||
python scripts/automation/weekly_tip_generator.py
|
||||
```
|
||||
|
||||
### Logs sind leer
|
||||
|
||||
Stelle sicher dass das logs-Verzeichnis existiert:
|
||||
```bash
|
||||
mkdir -p logs
|
||||
```
|
||||
|
||||
## 🎯 Best Practices
|
||||
|
||||
### 1. Teste manuell vor Cron
|
||||
|
||||
```bash
|
||||
# Test 1: Tipps generieren
|
||||
python scripts/automation/weekly_tip_generator.py --force
|
||||
|
||||
# Test 2: Update & Learn
|
||||
python scripts/automation/auto_update_and_learn.py
|
||||
```
|
||||
|
||||
### 2. Überwache Logs regelmäßig
|
||||
|
||||
```bash
|
||||
# Wöchentlich prüfen
|
||||
tail -100 logs/tips_generation.log
|
||||
tail -100 logs/auto_update.log
|
||||
```
|
||||
|
||||
### 3. Backup-Strategie
|
||||
|
||||
Backups werden automatisch erstellt, aber zusätzlich:
|
||||
|
||||
```bash
|
||||
# Manuelles Backup
|
||||
cp AlleEurojackpotzahlen.csv "AlleEurojackpotzahlen_$(date +%Y%m%d).csv"
|
||||
```
|
||||
|
||||
### 4. Performance-Analyse
|
||||
|
||||
```bash
|
||||
# Zeige Generierungs-Historie
|
||||
python scripts/automation/weekly_tip_generator.py --history
|
||||
|
||||
# Analysiere Reports
|
||||
cat data/performance_reports/report_*.txt | grep "Avg Main Matches"
|
||||
```
|
||||
|
||||
## 📱 Benachrichtigungen (Optional)
|
||||
|
||||
Füge Benachrichtigungen zu Cron hinzu:
|
||||
|
||||
### macOS Notification
|
||||
|
||||
```bash
|
||||
# In Cron-Zeile hinzufügen:
|
||||
&& osascript -e 'display notification "Eurojackpot Tipps generiert" with title "Automation"'
|
||||
```
|
||||
|
||||
### Email (wenn konfiguriert)
|
||||
|
||||
```bash
|
||||
# In Cron-Zeile:
|
||||
&& echo "Tipps generiert" | mail -s "Eurojackpot Update" your@email.com
|
||||
```
|
||||
|
||||
## 🔄 Workflow-Diagramm
|
||||
|
||||
```
|
||||
WOCHE
|
||||
│
|
||||
├─ Montag 09:00
|
||||
│ └─ 🎲 Generiere Tipps für Dienstag
|
||||
│ └─ weekly_tips_TIMESTAMP.csv
|
||||
│
|
||||
├─ Dienstag 20:00
|
||||
│ └─ 🎰 Ziehung findet statt
|
||||
│
|
||||
├─ Dienstag 21:00
|
||||
│ └─ 🔄 Auto-Update & Learning
|
||||
│ ├─ Daten aktualisieren
|
||||
│ ├─ Tipps evaluieren
|
||||
│ ├─ Learning Update
|
||||
│ └─ Report erstellen
|
||||
│
|
||||
├─ Donnerstag 09:00
|
||||
│ └─ 🎲 Generiere Tipps für Freitag
|
||||
│ └─ weekly_tips_TIMESTAMP.csv
|
||||
│
|
||||
├─ Freitag 20:00
|
||||
│ └─ 🎰 Ziehung findet statt
|
||||
│
|
||||
└─ Freitag 21:00
|
||||
└─ 🔄 Auto-Update & Learning
|
||||
├─ Daten aktualisieren
|
||||
├─ Tipps evaluieren
|
||||
├─ Learning Update
|
||||
└─ Report erstellen
|
||||
```
|
||||
|
||||
## 💡 Tipps
|
||||
|
||||
1. **Erste Woche:** Nutze `--force` um initiale Tipps zu generieren
|
||||
2. **Strategie-Mix:** Das System nutzt automatisch den optimalen Mix
|
||||
3. **Learning:** Nach 4-5 Ziehungen beginnt das System besser zu werden
|
||||
4. **Reports:** Analysiere Reports monatlich für Trend-Analyse
|
||||
5. **Backup:** Die automatischen Backups werden im backups/ Ordner gespeichert
|
||||
|
||||
## 🆘 Support
|
||||
|
||||
Bei Problemen:
|
||||
1. Prüfe Logs: `tail -100 logs/*.log`
|
||||
2. Teste manuell: `python script.py`
|
||||
3. Prüfe venv: `source venv/bin/activate && pip list`
|
||||
4. Checke Cronjobs: `crontab -l`
|
||||
|
||||
---
|
||||
|
||||
**Version:** 1.0
|
||||
**Erstellt:** 2025-01-25
|
||||
**Kompatibel mit:** Ultimate AI-ML Generator V2.1
|
||||
@@ -0,0 +1,445 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Automatischer Eurojackpot Update & Learning Workflow
|
||||
|
||||
Nach jeder Ziehung:
|
||||
1. Aktualisiert Daten von API
|
||||
2. Evaluiert letzte generierte Tipps
|
||||
3. Real-Time Learning Update
|
||||
4. Performance-Report
|
||||
|
||||
Verwendung:
|
||||
python auto_update_and_learn.py
|
||||
|
||||
Oder als Cronjob (nach Ziehung):
|
||||
0 21 * * 2,5 cd /path/to/eurojackpot && source venv/bin/activate && python scripts/automation/auto_update_and_learn.py
|
||||
"""
|
||||
|
||||
import sys
|
||||
import os
|
||||
from datetime import datetime, timedelta
|
||||
import json
|
||||
import pandas as pd
|
||||
|
||||
# Path Setup
|
||||
script_dir = os.path.dirname(os.path.abspath(__file__))
|
||||
project_dir = os.path.dirname(os.path.dirname(script_dir))
|
||||
sys.path.insert(0, project_dir)
|
||||
|
||||
from scripts.utils.update_from_api import EurojackpotAPIUpdater
|
||||
from scripts.generators.ultimate_ai_ml_eurojackpot_generator import UltimateAIMLEurojackpotGenerator
|
||||
from scripts.utils.notifier import EurojackpotNotifier
|
||||
|
||||
|
||||
class AutoUpdateAndLearn:
|
||||
"""Automatisches Update und Learning System."""
|
||||
|
||||
def __init__(self, data_dir: str):
|
||||
self.data_dir = data_dir
|
||||
# CSV file is in Eurojackpot/data folder
|
||||
# data_dir = .../Eurojackpot/data
|
||||
# We need .../Eurojackpot/data/AlleEurojackpotzahlen.csv
|
||||
self.data_file = os.path.join(data_dir, "AlleEurojackpotzahlen.csv")
|
||||
self.tips_dir = os.path.join(data_dir, "generated_tips")
|
||||
self.reports_dir = os.path.join(data_dir, "performance_reports")
|
||||
self.learning_log = os.path.join(data_dir, "learning_log.json")
|
||||
|
||||
os.makedirs(self.reports_dir, exist_ok=True)
|
||||
|
||||
# Initialisiere Notifier
|
||||
self.notifier = EurojackpotNotifier()
|
||||
|
||||
print("🤖 AUTOMATISCHES UPDATE & LEARNING SYSTEM")
|
||||
print("=" * 70)
|
||||
|
||||
def load_learning_log(self) -> dict:
|
||||
"""Lädt Learning Log."""
|
||||
if os.path.exists(self.learning_log):
|
||||
with open(self.learning_log, 'r') as f:
|
||||
return json.load(f)
|
||||
return {"updates": []}
|
||||
|
||||
def save_learning_log(self, log: dict):
|
||||
"""Speichert Learning Log."""
|
||||
with open(self.learning_log, 'w') as f:
|
||||
json.dump(log, f, indent=2)
|
||||
|
||||
def check_for_new_draw(self) -> dict:
|
||||
"""
|
||||
Prüft ob neue Ziehung verfügbar ist.
|
||||
|
||||
Returns:
|
||||
Dict mit neuer Ziehung oder None
|
||||
"""
|
||||
print("\n🔍 PRÜFE AUF NEUE ZIEHUNG")
|
||||
print("=" * 70)
|
||||
|
||||
log = self.load_learning_log()
|
||||
|
||||
# Lade aktuelle Daten
|
||||
try:
|
||||
df = pd.read_csv(self.data_file, sep=';')
|
||||
df['datum'] = pd.to_datetime(df['datum'], format='%Y-%m-%d')
|
||||
|
||||
latest_draw = df.iloc[0] # Neueste Ziehung (sortiert absteigend)
|
||||
latest_date = latest_draw['datum']
|
||||
|
||||
print(f" 📅 Neueste Ziehung in Daten: {latest_date.strftime('%Y-%m-%d')}")
|
||||
|
||||
# Prüfe ob schon verarbeitet
|
||||
if log["updates"]:
|
||||
last_processed = log["updates"][-1].get("draw_date")
|
||||
if last_processed == latest_date.strftime('%Y-%m-%d'):
|
||||
print(f" ⏭️ Bereits verarbeitet")
|
||||
return None
|
||||
|
||||
print(f" ✅ Neue Ziehung gefunden!")
|
||||
|
||||
return {
|
||||
'date': latest_date,
|
||||
'Z1': int(latest_draw['Z1']),
|
||||
'Z2': int(latest_draw['Z2']),
|
||||
'Z3': int(latest_draw['Z3']),
|
||||
'Z4': int(latest_draw['Z4']),
|
||||
'Z5': int(latest_draw['Z5']),
|
||||
'SZ1': int(latest_draw['SZ1']),
|
||||
'SZ2': int(latest_draw['SZ2'])
|
||||
}
|
||||
|
||||
except Exception as e:
|
||||
print(f" ❌ Fehler beim Prüfen: {e}")
|
||||
return None
|
||||
|
||||
def update_data(self) -> bool:
|
||||
"""
|
||||
Aktualisiert Daten von API.
|
||||
|
||||
Returns:
|
||||
True bei Erfolg
|
||||
"""
|
||||
print("\n📥 AKTUALISIERE DATEN VON API")
|
||||
print("=" * 70)
|
||||
|
||||
try:
|
||||
updater = EurojackpotAPIUpdater(self.data_file)
|
||||
success = updater.update(api_name='all', create_backup=True)
|
||||
|
||||
if success:
|
||||
print(" ✅ Daten erfolgreich aktualisiert")
|
||||
else:
|
||||
print(" ⚠️ Update ohne neue Daten")
|
||||
|
||||
return success
|
||||
|
||||
except Exception as e:
|
||||
print(f" ❌ Fehler beim Update: {e}")
|
||||
return False
|
||||
|
||||
def evaluate_tips(self, new_draw: dict) -> dict:
|
||||
"""
|
||||
Evaluiert letzte generierte Tipps gegen neue Ziehung.
|
||||
|
||||
Args:
|
||||
new_draw: Dict mit neuer Ziehung
|
||||
|
||||
Returns:
|
||||
Evaluierungs-Ergebnisse
|
||||
"""
|
||||
print("\n🎯 EVALUIERE LETZTE TIPPS")
|
||||
print("=" * 70)
|
||||
|
||||
# Finde neueste Tipps-Datei
|
||||
if not os.path.exists(self.tips_dir):
|
||||
print(" ⚠️ Keine Tipps zum Evaluieren")
|
||||
return {}
|
||||
|
||||
tip_files = sorted(
|
||||
[f for f in os.listdir(self.tips_dir) if f.endswith('.csv')],
|
||||
reverse=True
|
||||
)
|
||||
|
||||
if not tip_files:
|
||||
print(" ⚠️ Keine Tipps-Dateien gefunden")
|
||||
return {}
|
||||
|
||||
latest_tips_file = os.path.join(self.tips_dir, tip_files[0])
|
||||
print(f" 📁 Evaluiere: {tip_files[0]}")
|
||||
|
||||
try:
|
||||
tips_df = pd.read_csv(latest_tips_file)
|
||||
|
||||
# Extrahiere gezogene Zahlen
|
||||
drawn_main = [new_draw[f'Z{i}'] for i in range(1, 6)]
|
||||
drawn_euro = [new_draw['SZ1'], new_draw['SZ2']]
|
||||
|
||||
print(f" 🎲 Gezogene Zahlen: {drawn_main} + Euro {drawn_euro}")
|
||||
print()
|
||||
|
||||
results = []
|
||||
best_matches = {'main': 0, 'euro': 0, 'tip': None}
|
||||
|
||||
for _, tip in tips_df.iterrows():
|
||||
# Parse Hauptzahlen
|
||||
main_str = tip['Main_Numbers']
|
||||
|
||||
# Handle both formats: "[1, 2, 3]" and "1-2-3"
|
||||
if main_str.startswith('['):
|
||||
# Parse Python list format
|
||||
import ast
|
||||
tip_main = ast.literal_eval(main_str)
|
||||
else:
|
||||
# Parse dash-separated format
|
||||
tip_main = [int(n) for n in main_str.split('-')]
|
||||
|
||||
# Parse Eurozahlen
|
||||
euro_str = tip['Euro_Numbers']
|
||||
if euro_str.startswith('['):
|
||||
import ast
|
||||
tip_euro = ast.literal_eval(euro_str)
|
||||
else:
|
||||
tip_euro = [int(n) for n in euro_str.split('-')]
|
||||
|
||||
# Zähle Treffer
|
||||
main_matches = len(set(tip_main) & set(drawn_main))
|
||||
euro_matches = len(set(tip_euro) & set(drawn_euro))
|
||||
|
||||
total_matches = main_matches + euro_matches
|
||||
|
||||
results.append({
|
||||
'tip_number': tip['Tip_Number'],
|
||||
'strategy': tip['Strategy'],
|
||||
'main_matches': main_matches,
|
||||
'euro_matches': euro_matches,
|
||||
'total_matches': total_matches
|
||||
})
|
||||
|
||||
# Track best
|
||||
if total_matches > (best_matches['main'] + best_matches['euro']):
|
||||
best_matches = {
|
||||
'main': main_matches,
|
||||
'euro': euro_matches,
|
||||
'tip': tip['Tip_Number']
|
||||
}
|
||||
|
||||
# Ausgabe
|
||||
print(f" {'Tip':<5} {'Strategie':<15} {'Main':<6} {'Euro':<6} {'Gesamt':<8} {'Bewertung'}")
|
||||
print(" " + "-" * 60)
|
||||
|
||||
for r in results:
|
||||
rating = self._get_match_rating(r['main_matches'], r['euro_matches'])
|
||||
print(f" #{r['tip_number']:<4} {r['strategy']:<15} "
|
||||
f"{r['main_matches']:<6} {r['euro_matches']:<6} "
|
||||
f"{r['total_matches']:<8} {rating}")
|
||||
|
||||
print()
|
||||
print(f" 🏆 Bester Tipp: #{best_matches['tip']} "
|
||||
f"({best_matches['main']} Main + {best_matches['euro']} Euro)")
|
||||
|
||||
return {
|
||||
'file': tip_files[0],
|
||||
'results': results,
|
||||
'best': best_matches,
|
||||
'avg_main_matches': sum(r['main_matches'] for r in results) / len(results),
|
||||
'avg_euro_matches': sum(r['euro_matches'] for r in results) / len(results)
|
||||
}
|
||||
|
||||
except Exception as e:
|
||||
print(f" ❌ Fehler bei Evaluation: {e}")
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
return {}
|
||||
|
||||
def _get_match_rating(self, main: int, euro: int) -> str:
|
||||
"""Bewertung der Treffer."""
|
||||
total = main + euro
|
||||
|
||||
if main == 5 and euro == 2:
|
||||
return "🏆 JACKPOT!"
|
||||
elif main == 5 and euro == 1:
|
||||
return "💰 Klasse 2"
|
||||
elif main == 5 and euro == 0:
|
||||
return "💰 Klasse 3"
|
||||
elif main == 4 and euro == 2:
|
||||
return "💰 Klasse 4"
|
||||
elif main == 4 and euro == 1:
|
||||
return "💵 Klasse 5"
|
||||
elif total >= 3:
|
||||
return "✅ Gut"
|
||||
elif total >= 2:
|
||||
return "👍 OK"
|
||||
else:
|
||||
return "⚪ Niedrig"
|
||||
|
||||
def perform_learning_update(self, new_draw: dict) -> bool:
|
||||
"""
|
||||
Führt Real-Time Learning Update durch.
|
||||
|
||||
Args:
|
||||
new_draw: Dict mit neuer Ziehung
|
||||
|
||||
Returns:
|
||||
True bei Erfolg
|
||||
"""
|
||||
print("\n🧠 REAL-TIME LEARNING UPDATE")
|
||||
print("=" * 70)
|
||||
|
||||
try:
|
||||
# Initialisiere Generator
|
||||
generator = UltimateAIMLEurojackpotGenerator(
|
||||
self.data_file,
|
||||
fast_mode=True
|
||||
)
|
||||
|
||||
# Learning Update
|
||||
generator.real_time_learner.learn_from_result(new_draw)
|
||||
|
||||
# Performance Tracking
|
||||
generator.performance_tracker.evaluate_predictions(new_draw)
|
||||
|
||||
print(" ✅ Learning Update durchgeführt")
|
||||
print(" 📊 Models wurden angepasst")
|
||||
|
||||
return True
|
||||
|
||||
except Exception as e:
|
||||
print(f" ❌ Fehler beim Learning: {e}")
|
||||
return False
|
||||
|
||||
def generate_report(self, new_draw: dict, evaluation: dict):
|
||||
"""Generiert Performance-Report."""
|
||||
print("\n📊 PERFORMANCE-REPORT")
|
||||
print("=" * 70)
|
||||
|
||||
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
|
||||
report_file = os.path.join(
|
||||
self.reports_dir,
|
||||
f"report_{timestamp}.txt"
|
||||
)
|
||||
|
||||
report = []
|
||||
report.append("=" * 70)
|
||||
report.append("EUROJACKPOT PERFORMANCE REPORT")
|
||||
report.append("=" * 70)
|
||||
report.append(f"Erstellt: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
|
||||
report.append("")
|
||||
report.append(f"ZIEHUNG VOM {new_draw['date'].strftime('%Y-%m-%d')}")
|
||||
report.append("-" * 70)
|
||||
report.append(f"Hauptzahlen: {[new_draw[f'Z{i}'] for i in range(1, 6)]}")
|
||||
report.append(f"Eurozahlen: [{new_draw['SZ1']}, {new_draw['SZ2']}]")
|
||||
report.append("")
|
||||
|
||||
if evaluation:
|
||||
report.append("EVALUATION DER TIPPS")
|
||||
report.append("-" * 70)
|
||||
report.append(f"Datei: {evaluation['file']}")
|
||||
report.append(f"Tipps evaluiert: {len(evaluation['results'])}")
|
||||
report.append(f"Avg Main Matches: {evaluation['avg_main_matches']:.2f}")
|
||||
report.append(f"Avg Euro Matches: {evaluation['avg_euro_matches']:.2f}")
|
||||
report.append(f"Bester Tipp: #{evaluation['best']['tip']}")
|
||||
report.append(f" - Main Treffer: {evaluation['best']['main']}")
|
||||
report.append(f" - Euro Treffer: {evaluation['best']['euro']}")
|
||||
|
||||
report.append("")
|
||||
report.append("=" * 70)
|
||||
|
||||
# Speichern
|
||||
with open(report_file, 'w') as f:
|
||||
f.write('\n'.join(report))
|
||||
|
||||
# Ausgabe
|
||||
for line in report:
|
||||
print(line)
|
||||
|
||||
print(f"\n📁 Report gespeichert: {os.path.basename(report_file)}")
|
||||
|
||||
def run(self):
|
||||
"""Führt kompletten Workflow aus."""
|
||||
print()
|
||||
print("=" * 70)
|
||||
print("START: AUTOMATISCHER UPDATE & LEARNING WORKFLOW")
|
||||
print("=" * 70)
|
||||
|
||||
# 1. Update Daten
|
||||
print("\n[SCHRITT 1/4] Daten aktualisieren")
|
||||
self.update_data()
|
||||
|
||||
# 2. Prüfe auf neue Ziehung
|
||||
print("\n[SCHRITT 2/4] Neue Ziehung prüfen")
|
||||
new_draw = self.check_for_new_draw()
|
||||
|
||||
if not new_draw:
|
||||
print("\n⏭️ Keine neue Ziehung - Workflow beendet")
|
||||
return True
|
||||
|
||||
# 3. Evaluiere Tipps
|
||||
print("\n[SCHRITT 3/4] Tipps evaluieren")
|
||||
evaluation = self.evaluate_tips(new_draw)
|
||||
|
||||
# 4. Learning Update
|
||||
print("\n[SCHRITT 4/4] Learning Update")
|
||||
self.perform_learning_update(new_draw)
|
||||
|
||||
# Report
|
||||
self.generate_report(new_draw, evaluation)
|
||||
|
||||
# Log Update
|
||||
log = self.load_learning_log()
|
||||
log["updates"].append({
|
||||
"timestamp": datetime.now().isoformat(),
|
||||
"draw_date": new_draw['date'].strftime('%Y-%m-%d'),
|
||||
"evaluation": evaluation.get('best', {}),
|
||||
"avg_matches": {
|
||||
'main': evaluation.get('avg_main_matches', 0),
|
||||
'euro': evaluation.get('avg_euro_matches', 0)
|
||||
}
|
||||
})
|
||||
self.save_learning_log(log)
|
||||
|
||||
# Sende Benachrichtigung
|
||||
try:
|
||||
best_match = {
|
||||
'main_matches': evaluation.get('best', {}).get('main', 0),
|
||||
'euro_matches': evaluation.get('best', {}).get('euro', 0)
|
||||
}
|
||||
|
||||
evaluation_summary = {
|
||||
'avg_main': evaluation.get('avg_main_matches', 0),
|
||||
'avg_euro': evaluation.get('avg_euro_matches', 0)
|
||||
}
|
||||
|
||||
self.notifier.send_draw_results(new_draw, evaluation_summary, best_match)
|
||||
except Exception as e:
|
||||
print(f"⚠️ Benachrichtigung fehlgeschlagen: {e}")
|
||||
|
||||
print("\n" + "=" * 70)
|
||||
print("✅ WORKFLOW ERFOLGREICH ABGESCHLOSSEN")
|
||||
print("=" * 70)
|
||||
|
||||
return True
|
||||
|
||||
|
||||
def main():
|
||||
"""Hauptfunktion."""
|
||||
import argparse
|
||||
|
||||
parser = argparse.ArgumentParser(
|
||||
description="Automatisches Update & Learning nach Ziehung"
|
||||
)
|
||||
parser.add_argument(
|
||||
'--data-dir',
|
||||
type=str,
|
||||
default="/Users/sebastianfrohlich/Library/Mobile Documents/com~apple~CloudDocs/Jupyter Notebooks/Eurojackpot/data",
|
||||
help='Daten-Verzeichnis'
|
||||
)
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
# Run Workflow
|
||||
workflow = AutoUpdateAndLearn(args.data_dir)
|
||||
success = workflow.run()
|
||||
|
||||
sys.exit(0 if success else 1)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -0,0 +1,278 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Wöchentlicher Eurojackpot Tipp-Generator
|
||||
|
||||
Automatisiert:
|
||||
1. Prüft ob neue Tipps nötig sind (basierend auf letzter Generierung)
|
||||
2. Generiert 10 Ultimate Tipps
|
||||
3. Speichert mit Timestamp
|
||||
4. Trackt Generierungs-Historie
|
||||
|
||||
Verwendung:
|
||||
python weekly_tip_generator.py
|
||||
|
||||
Oder als Cronjob:
|
||||
0 9 * * 2,5 cd /path/to/eurojackpot && source venv/bin/activate && python scripts/automation/weekly_tip_generator.py
|
||||
"""
|
||||
|
||||
import sys
|
||||
import os
|
||||
from datetime import datetime, timedelta
|
||||
import json
|
||||
|
||||
# Füge Parent-Verzeichnisse zum Path hinzu
|
||||
script_dir = os.path.dirname(os.path.abspath(__file__))
|
||||
project_dir = os.path.dirname(os.path.dirname(script_dir))
|
||||
generators_dir = os.path.join(project_dir, 'scripts', 'generators')
|
||||
sys.path.insert(0, project_dir)
|
||||
sys.path.insert(0, generators_dir)
|
||||
|
||||
# Import des Ultimate Generators
|
||||
from scripts.generators.ultimate_ai_ml_eurojackpot_generator import UltimateAIMLEurojackpotGenerator
|
||||
from scripts.utils.notifier import EurojackpotNotifier
|
||||
|
||||
|
||||
class WeeklyTipGenerator:
|
||||
"""Automatischer wöchentlicher Tipp-Generator."""
|
||||
|
||||
def __init__(self, data_dir: str):
|
||||
self.data_dir = data_dir
|
||||
# CSV file is in Eurojackpot/data folder
|
||||
# data_dir = .../Eurojackpot/data
|
||||
# We need .../Eurojackpot/data/AlleEurojackpotzahlen.csv
|
||||
self.data_file = os.path.join(data_dir, "AlleEurojackpotzahlen.csv")
|
||||
self.tips_dir = os.path.join(data_dir, "generated_tips")
|
||||
self.history_file = os.path.join(self.tips_dir, "generation_history.json")
|
||||
|
||||
os.makedirs(self.tips_dir, exist_ok=True)
|
||||
|
||||
# Initialisiere Notifier
|
||||
self.notifier = EurojackpotNotifier()
|
||||
|
||||
print("🤖 AUTOMATISCHER WÖCHENTLICHER TIPP-GENERATOR")
|
||||
print("=" * 70)
|
||||
|
||||
def load_history(self) -> dict:
|
||||
"""Lädt Generierungs-Historie."""
|
||||
if os.path.exists(self.history_file):
|
||||
with open(self.history_file, 'r') as f:
|
||||
return json.load(f)
|
||||
return {"generations": []}
|
||||
|
||||
def save_history(self, history: dict):
|
||||
"""Speichert Historie."""
|
||||
with open(self.history_file, 'w') as f:
|
||||
json.dump(history, f, indent=2)
|
||||
|
||||
def needs_new_tips(self) -> bool:
|
||||
"""
|
||||
Prüft ob neue Tipps nötig sind.
|
||||
|
||||
Logik:
|
||||
- Eurojackpot: Dienstag & Freitag Ziehungen
|
||||
- Generiere Tipps wenn:
|
||||
a) Noch nie generiert
|
||||
b) Letzte Generierung > 3 Tage her
|
||||
c) Es ist Montag oder Donnerstag (vor Ziehung)
|
||||
"""
|
||||
history = self.load_history()
|
||||
|
||||
if not history["generations"]:
|
||||
print(" ℹ️ Noch nie Tipps generiert")
|
||||
return True
|
||||
|
||||
last_gen = history["generations"][-1]
|
||||
last_date = datetime.fromisoformat(last_gen["timestamp"])
|
||||
days_since = (datetime.now() - last_date).days
|
||||
|
||||
print(f" 📅 Letzte Generierung: {last_date.strftime('%Y-%m-%d %H:%M')}")
|
||||
print(f" ⏱️ Vor {days_since} Tagen")
|
||||
|
||||
# Wenn > 3 Tage her
|
||||
if days_since > 3:
|
||||
print(" ✅ Mehr als 3 Tage her - neue Tipps nötig")
|
||||
return True
|
||||
|
||||
# Prüfe Wochentag (0=Montag, 4=Freitag)
|
||||
today = datetime.now().weekday()
|
||||
|
||||
# Montag (vor Dienstag-Ziehung)
|
||||
if today == 0 and days_since >= 1:
|
||||
print(" ✅ Montag - generiere für Dienstag-Ziehung")
|
||||
return True
|
||||
|
||||
# Donnerstag (vor Freitag-Ziehung)
|
||||
if today == 3 and days_since >= 1:
|
||||
print(" ✅ Donnerstag - generiere für Freitag-Ziehung")
|
||||
return True
|
||||
|
||||
print(" ⏭️ Keine neuen Tipps nötig")
|
||||
return False
|
||||
|
||||
def generate_tips(self, num_tips: int = 10, force: bool = False) -> bool:
|
||||
"""
|
||||
Generiert neue Tipps.
|
||||
|
||||
Args:
|
||||
num_tips: Anzahl Tipps
|
||||
force: Ignoriere needs_new_tips Check
|
||||
|
||||
Returns:
|
||||
True bei Erfolg
|
||||
"""
|
||||
print("\n🎯 TIPP-GENERIERUNG")
|
||||
print("=" * 70)
|
||||
|
||||
# Check ob nötig
|
||||
if not force and not self.needs_new_tips():
|
||||
print("\n⏭️ Keine Generierung nötig")
|
||||
return True
|
||||
|
||||
print(f"\n🚀 Generiere {num_tips} Ultimate Tipps...")
|
||||
print("-" * 70)
|
||||
|
||||
try:
|
||||
# Initialisiere Generator
|
||||
generator = UltimateAIMLEurojackpotGenerator(
|
||||
self.data_file,
|
||||
fast_mode=True
|
||||
)
|
||||
|
||||
# Generiere Tipps
|
||||
tips = generator.generate_ultimate_tips(num_tips=num_tips)
|
||||
|
||||
if not tips:
|
||||
print("\n❌ Keine Tipps generiert")
|
||||
return False
|
||||
|
||||
# Speichere Tipps
|
||||
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
|
||||
output_file = os.path.join(
|
||||
self.tips_dir,
|
||||
f"weekly_tips_{timestamp}.csv"
|
||||
)
|
||||
|
||||
generator.export_tips_to_csv(tips, output_file)
|
||||
|
||||
# Update Historie
|
||||
history = self.load_history()
|
||||
history["generations"].append({
|
||||
"timestamp": datetime.now().isoformat(),
|
||||
"num_tips": len(tips),
|
||||
"file": os.path.basename(output_file),
|
||||
"avg_confidence": sum(t['confidence'] for t in tips) / len(tips),
|
||||
"avg_quality": sum(t['quality'] for t in tips) / len(tips)
|
||||
})
|
||||
self.save_history(history)
|
||||
|
||||
print("\n" + "=" * 70)
|
||||
print("✅ TIPPS ERFOLGREICH GENERIERT")
|
||||
print(f"📁 Datei: {os.path.basename(output_file)}")
|
||||
print(f"📊 Anzahl: {len(tips)}")
|
||||
print(f"🎯 Avg Confidence: {history['generations'][-1]['avg_confidence']:.4f}")
|
||||
print(f"💎 Avg Quality: {history['generations'][-1]['avg_quality']:.4f}")
|
||||
print("=" * 70)
|
||||
|
||||
# Sende Benachrichtigung
|
||||
try:
|
||||
# Finde besten Tipp (höchste Confidence)
|
||||
best_tip = max(tips, key=lambda t: t.get('confidence', 0))
|
||||
|
||||
# Formatiere für Notification
|
||||
best_tip_formatted = {
|
||||
'main_numbers': best_tip.get('main_numbers', '?'),
|
||||
'euro_numbers': best_tip.get('euro_numbers', '?'),
|
||||
'confidence': best_tip.get('confidence', 0),
|
||||
'strategy': best_tip.get('strategy', 'UNKNOWN')
|
||||
}
|
||||
|
||||
timestamp_formatted = datetime.now().strftime('%Y-%m-%d %H:%M')
|
||||
self.notifier.send_tips_generated(tips, timestamp_formatted, best_tip_formatted)
|
||||
except Exception as e:
|
||||
print(f"⚠️ Benachrichtigung fehlgeschlagen: {e}")
|
||||
|
||||
return True
|
||||
|
||||
except Exception as e:
|
||||
print(f"\n❌ Fehler bei Generierung: {e}")
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
return False
|
||||
|
||||
def show_history(self):
|
||||
"""Zeigt Generierungs-Historie."""
|
||||
history = self.load_history()
|
||||
|
||||
if not history["generations"]:
|
||||
print("\n ℹ️ Noch keine Generierungen")
|
||||
return
|
||||
|
||||
print("\n📊 GENERIERUNGS-HISTORIE")
|
||||
print("=" * 70)
|
||||
print(f"{'Nr':<4} {'Datum':<20} {'Tips':<6} {'Confidence':<12} {'Quality':<12} {'Datei'}")
|
||||
print("-" * 70)
|
||||
|
||||
for i, gen in enumerate(reversed(history["generations"][-10:]), 1):
|
||||
timestamp = datetime.fromisoformat(gen["timestamp"])
|
||||
print(f"{i:<4} {timestamp.strftime('%Y-%m-%d %H:%M'):<20} "
|
||||
f"{gen['num_tips']:<6} {gen['avg_confidence']:<12.4f} "
|
||||
f"{gen['avg_quality']:<12.4f} {gen['file']}")
|
||||
|
||||
print("-" * 70)
|
||||
print(f"Total: {len(history['generations'])} Generierungen")
|
||||
|
||||
|
||||
def main():
|
||||
"""Hauptfunktion."""
|
||||
import argparse
|
||||
|
||||
parser = argparse.ArgumentParser(
|
||||
description="Wöchentlicher Eurojackpot Tipp-Generator"
|
||||
)
|
||||
parser.add_argument(
|
||||
'--force',
|
||||
action='store_true',
|
||||
help='Generiere Tipps auch wenn nicht nötig'
|
||||
)
|
||||
parser.add_argument(
|
||||
'--num-tips',
|
||||
type=int,
|
||||
default=10,
|
||||
help='Anzahl Tipps zu generieren (default: 10)'
|
||||
)
|
||||
parser.add_argument(
|
||||
'--history',
|
||||
action='store_true',
|
||||
help='Zeige nur Historie'
|
||||
)
|
||||
parser.add_argument(
|
||||
'--data-dir',
|
||||
type=str,
|
||||
default="/Users/sebastianfrohlich/Library/Mobile Documents/com~apple~CloudDocs/Jupyter Notebooks/Eurojackpot/data",
|
||||
help='Daten-Verzeichnis'
|
||||
)
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
# Initialisiere
|
||||
generator = WeeklyTipGenerator(args.data_dir)
|
||||
|
||||
# Zeige Historie wenn gewünscht
|
||||
if args.history:
|
||||
generator.show_history()
|
||||
return
|
||||
|
||||
# Generiere Tipps
|
||||
success = generator.generate_tips(
|
||||
num_tips=args.num_tips,
|
||||
force=args.force
|
||||
)
|
||||
|
||||
# Zeige Historie
|
||||
generator.show_history()
|
||||
|
||||
sys.exit(0 if success else 1)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in new issue
Block a user