Initial commit: Lotto number generator project
This project includes multiple AI/ML-based lottery number generators for German Lotto 6aus49, including pattern analysis, weighted predictions, and hybrid approaches. Features automated weekly tip generation, performance tracking, and Telegram bot integration. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,301 @@
|
||||
#!/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}",
|
||||
'Quality': f"{tip['quality']:.4f}"
|
||||
})
|
||||
|
||||
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,
|
||||
default="/Users/sebastianfrohlich/Library/Mobile Documents/com~apple~CloudDocs/Jupyter Notebooks/Lotto/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