- Update plist to use new project path structure - Simplify plist by removing comments - Add run_tip_generator.sh script for easier execution - Update data directory path in weekly_tip_generator.py - Add generated weekly tips from 2026-01-08 - Update generation history with latest run Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
279 lines
8.7 KiB
Python
279 lines
8.7 KiB
Python
#!/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/Projekte/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()
|