2025-12-16 14:47:59 +01:00
|
|
|
|
#!/usr/bin/env python3
|
|
|
|
|
|
"""
|
|
|
|
|
|
Wöchentlicher Lotto 6aus49 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 * * 3,6 cd /path/to/lotto && 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_hybrid_generator import UltimateAIMLHybridGenerator
|
|
|
|
|
|
from scripts.utils.notifier import LottoNotifier
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class WeeklyTipGenerator:
|
|
|
|
|
|
"""Automatischer wöchentlicher Tipp-Generator für Lotto 6aus49."""
|
|
|
|
|
|
|
|
|
|
|
|
def __init__(self, data_dir: str):
|
|
|
|
|
|
self.data_dir = data_dir
|
|
|
|
|
|
# CSV file is in Lotto/data folder
|
|
|
|
|
|
# data_dir = .../Lotto/data
|
|
|
|
|
|
# We need .../Lotto/data/AlleLottozahlen.csv
|
|
|
|
|
|
self.data_file = os.path.join(data_dir, "AlleLottozahlen.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 = LottoNotifier()
|
|
|
|
|
|
|
|
|
|
|
|
print("🤖 AUTOMATISCHER WÖCHENTLICHER LOTTO 6AUS49 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:
|
|
|
|
|
|
- Lotto 6aus49: Mittwoch & Samstag Ziehungen
|
|
|
|
|
|
- Generiere Tipps wenn:
|
|
|
|
|
|
a) Noch nie generiert
|
|
|
|
|
|
b) Letzte Generierung > 3 Tage her
|
|
|
|
|
|
c) Es ist Dienstag oder Freitag (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, 2=Mittwoch, 5=Samstag)
|
|
|
|
|
|
today = datetime.now().weekday()
|
|
|
|
|
|
|
|
|
|
|
|
# Dienstag (vor Mittwoch-Ziehung)
|
|
|
|
|
|
if today == 1 and days_since >= 1:
|
|
|
|
|
|
print(" ✅ Dienstag - generiere für Mittwoch-Ziehung")
|
|
|
|
|
|
return True
|
|
|
|
|
|
|
|
|
|
|
|
# Freitag (vor Samstag-Ziehung)
|
|
|
|
|
|
if today == 4 and days_since >= 1:
|
|
|
|
|
|
print(" ✅ Freitag - generiere für Samstag-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 Lotto 6aus49 Tipps...")
|
|
|
|
|
|
print("-" * 70)
|
|
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
|
# Initialisiere Generator
|
|
|
|
|
|
generator = UltimateAIMLHybridGenerator(
|
|
|
|
|
|
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_lotto_tips_{timestamp}.csv"
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
self._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 = {
|
|
|
|
|
|
'numbers': best_tip.get('numbers', []),
|
|
|
|
|
|
'superzahl': best_tip.get('superzahl', 0),
|
|
|
|
|
|
'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 _export_tips_to_csv(self, tips, filepath):
|
|
|
|
|
|
"""Exportiert Tips als CSV."""
|
|
|
|
|
|
import pandas as pd
|
|
|
|
|
|
|
|
|
|
|
|
rows = []
|
|
|
|
|
|
for tip in tips:
|
|
|
|
|
|
numbers_str = '-'.join([str(n) for n in tip['numbers']])
|
|
|
|
|
|
|
|
|
|
|
|
rows.append({
|
|
|
|
|
|
'Tip_Number': tip['tip_number'],
|
|
|
|
|
|
'Numbers': numbers_str,
|
|
|
|
|
|
'Superzahl': tip['superzahl'],
|
|
|
|
|
|
'Strategy': tip['strategy'],
|
|
|
|
|
|
'AI_Score': f"{tip['ai_score']:.4f}",
|
|
|
|
|
|
'Pattern_Weight': f"{tip['pattern_weight']:.4f}",
|
|
|
|
|
|
'Confidence': f"{tip['confidence']:.4f}",
|
2026-06-10 13:34:43 +02:00
|
|
|
|
'Quality': f"{tip['quality']:.4f}",
|
|
|
|
|
|
'Popularity_Score': f"{UltimateAIMLHybridGenerator._calculate_popularity_score(tip['numbers']):.4f}"
|
2025-12-16 14:47:59 +01:00
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
df_export = pd.DataFrame(rows)
|
|
|
|
|
|
df_export.to_csv(filepath, index=False)
|
|
|
|
|
|
print(f"\n💾 Tips exported to: {filepath}")
|
|
|
|
|
|
|
|
|
|
|
|
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 Lotto 6aus49 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,
|
2026-01-08 18:33:41 +01:00
|
|
|
|
default="/Users/sebastianfrohlich/Projekte/Lotto/data",
|
2025-12-16 14:47:59 +01:00
|
|
|
|
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()
|