Remove unreferenced legacy generators, updater, and analysis scripts
The graphify code-graph pass confirmed nothing in the active pipeline (scripts/automation/, shell entrypoints) imports or calls any of these - only scripts/generators/ultimate_ai_ml_eurojackpot_generator.py is wired into automation. Removes: - ultimate_ai_ml_eurojackpot_generator_v2.1_backup.py, a verbatim duplicate of the active generator's classes (UltimateAIMLEurojackpot- Generator, EurojackpotAIMLEngine, PatternEngine, HybridOptimizer) - optimized_eurojackpot_generator.py, a third standalone generator documented in README but never imported - update_historical_data.py, a second data updater never imported - 12 standalone analysis/utility scripts (bereichsanalyse, positions- analyse, NMMHH generators, processors, etc.) with no automation ties History is preserved in git if anything here turns out to still be wanted. README still documents most of these - follow-up needed there. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
5703e6a12c
commit
f23922e05e
16 files changed
-5105
No files matched your search
@@ -1,77 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Erstellt Beispiel-CSV-Dateien für das Eurojackpot-Processing
|
||||
"""
|
||||
|
||||
import pandas as pd
|
||||
import itertools
|
||||
from datetime import datetime, timedelta
|
||||
import random
|
||||
|
||||
def create_all_combinations():
|
||||
"""Erstellt eine CSV mit allen möglichen 5-aus-50 Kombinationen (Beispiel mit ersten 100)."""
|
||||
print("Erstelle Beispiel-Kombinationsdatei...")
|
||||
|
||||
# Für Demo: nur erste 100 Kombinationen von 5 aus 20 Zahlen
|
||||
# (Vollständige 5-aus-50 Kombinationen wären über 2 Millionen!)
|
||||
combinations = []
|
||||
count = 0
|
||||
|
||||
for combo in itertools.combinations(range(1, 21), 5): # 5 aus 20 für Demo
|
||||
combinations.append({
|
||||
'Zahl1': combo[0],
|
||||
'Zahl2': combo[1],
|
||||
'Zahl3': combo[2],
|
||||
'Zahl4': combo[3],
|
||||
'Zahl5': combo[4]
|
||||
})
|
||||
count += 1
|
||||
if count >= 100: # Limitierung für Demo
|
||||
break
|
||||
|
||||
df = pd.DataFrame(combinations)
|
||||
df.to_csv('alle_kombinationen_beispiel.csv', index=False)
|
||||
print(f"Beispiel-Kombinationsdatei erstellt: {len(df)} Kombinationen")
|
||||
return df
|
||||
|
||||
def create_drawn_numbers():
|
||||
"""Erstellt eine CSV mit gezogenen Zahlen (Beispieldaten)."""
|
||||
print("Erstelle Beispiel-Datei mit gezogenen Zahlen...")
|
||||
|
||||
drawn_numbers = []
|
||||
start_date = datetime(2023, 1, 1)
|
||||
|
||||
# 20 zufällige Ziehungen erstellen
|
||||
for i in range(20):
|
||||
date = start_date + timedelta(days=i*7) # Wöchentliche Ziehungen
|
||||
|
||||
# 5 zufällige Zahlen zwischen 1 und 20 (ohne Wiederholung)
|
||||
numbers = sorted(random.sample(range(1, 21), 5))
|
||||
|
||||
drawn_numbers.append({
|
||||
'Datum': date.strftime('%Y-%m-%d'),
|
||||
'Z1': numbers[0],
|
||||
'Z2': numbers[1],
|
||||
'Z3': numbers[2],
|
||||
'Z4': numbers[3],
|
||||
'Z5': numbers[4]
|
||||
})
|
||||
|
||||
df = pd.DataFrame(drawn_numbers)
|
||||
df.to_csv('gezogene_zahlen_beispiel.csv', index=False)
|
||||
print(f"Beispiel-Datei mit gezogenen Zahlen erstellt: {len(df)} Ziehungen")
|
||||
return df
|
||||
|
||||
if __name__ == "__main__":
|
||||
print("=== Erstelle Beispiel-CSV-Dateien ===\n")
|
||||
|
||||
# Seed für reproduzierbare Ergebnisse
|
||||
random.seed(42)
|
||||
|
||||
combinations_df = create_all_combinations()
|
||||
drawn_df = create_drawn_numbers()
|
||||
|
||||
print("\n=== Beispieldateien erstellt ===")
|
||||
print("- alle_kombinationen_beispiel.csv")
|
||||
print("- gezogene_zahlen_beispiel.csv")
|
||||
print("\nSie können jetzt das Hauptscript testen:")
|
||||
@@ -1,165 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Eurojackpot CSV Processor
|
||||
|
||||
Dieses Script liest zwei CSV-Dateien ein:
|
||||
1. Alle möglichen Zahlenkombinationen (5 Zahlen)
|
||||
2. Bereits gezogene Zahlen mit Datumsstempel
|
||||
|
||||
Es markiert in der ersten Datei alle bereits gezogenen Kombinationen mit 1 (sonst 0).
|
||||
"""
|
||||
|
||||
import pandas as pd
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
def load_combinations_file(filepath):
|
||||
"""Lädt die Datei mit allen möglichen Kombinationen."""
|
||||
try:
|
||||
df = pd.read_csv(filepath)
|
||||
print(f"Kombinationen geladen: {len(df)} Zeilen")
|
||||
print(f"Spalten: {list(df.columns)}")
|
||||
return df
|
||||
except Exception as e:
|
||||
print(f"Fehler beim Laden der Kombinationsdatei: {e}")
|
||||
return None
|
||||
|
||||
def load_drawn_numbers_file(filepath):
|
||||
"""Lädt die Datei mit bereits gezogenen Zahlen."""
|
||||
try:
|
||||
df = pd.read_csv(filepath)
|
||||
print(f"Gezogene Zahlen geladen: {len(df)} Zeilen")
|
||||
print(f"Spalten: {list(df.columns)}")
|
||||
return df
|
||||
except Exception as e:
|
||||
print(f"Fehler beim Laden der gezogenen Zahlen: {e}")
|
||||
return None
|
||||
|
||||
def create_combination_key(row, z_columns):
|
||||
"""Erstellt einen eindeutigen Schlüssel aus den 5 Zahlen (sortiert)."""
|
||||
numbers = [row[col] for col in z_columns]
|
||||
return tuple(sorted(numbers))
|
||||
|
||||
def process_eurojackpot_data(combinations_file, drawn_numbers_file, output_file):
|
||||
"""Hauptfunktion zur Verarbeitung der Eurojackpot-Daten."""
|
||||
|
||||
# CSV-Dateien laden
|
||||
print("Lade Kombinationsdatei...")
|
||||
combinations_df = load_combinations_file(combinations_file)
|
||||
if combinations_df is None:
|
||||
return False
|
||||
|
||||
print("\nLade Datei mit gezogenen Zahlen...")
|
||||
drawn_df = load_drawn_numbers_file(drawn_numbers_file)
|
||||
if drawn_df is None:
|
||||
return False
|
||||
|
||||
# Spalten für Zahlen identifizieren
|
||||
# Annahme: In der Kombinationsdatei sind die ersten 5 Spalten die Zahlen
|
||||
# In der gezogenen Zahlen-Datei sind es Z1, Z2, Z3, Z4, Z5
|
||||
|
||||
# Für Kombinationsdatei - erste 5 numerische Spalten verwenden
|
||||
numeric_cols = combinations_df.select_dtypes(include=['number']).columns
|
||||
if len(numeric_cols) >= 5:
|
||||
combo_z_columns = numeric_cols[:5].tolist()
|
||||
else:
|
||||
# Fallback: erste 5 Spalten nehmen
|
||||
combo_z_columns = combinations_df.columns[:5].tolist()
|
||||
|
||||
print(f"Verwendete Spalten für Kombinationen: {combo_z_columns}")
|
||||
|
||||
# Für gezogene Zahlen - Z1 bis Z5 Spalten suchen
|
||||
z_columns = [col for col in drawn_df.columns if col.startswith('Z') and col[1:].isdigit()]
|
||||
z_columns = sorted(z_columns)[:5] # Ersten 5 Z-Spalten nehmen
|
||||
|
||||
if not z_columns:
|
||||
# Fallback: nach Spalten mit "Zahl" im Namen suchen oder numerische Spalten
|
||||
z_columns = [col for col in drawn_df.columns if 'zahl' in col.lower()][:5]
|
||||
if not z_columns:
|
||||
z_columns = drawn_df.select_dtypes(include=['number']).columns[:5].tolist()
|
||||
|
||||
print(f"Verwendete Spalten für gezogene Zahlen: {z_columns}")
|
||||
|
||||
# Set mit allen gezogenen Kombinationen erstellen
|
||||
print("\nErstelle Set mit gezogenen Kombinationen...")
|
||||
drawn_combinations = set()
|
||||
|
||||
for _, row in drawn_df.iterrows():
|
||||
combo_key = create_combination_key(row, z_columns)
|
||||
drawn_combinations.add(combo_key)
|
||||
|
||||
print(f"Anzahl eindeutige gezogene Kombinationen: {len(drawn_combinations)}")
|
||||
|
||||
# Neue Spalte für Markierungen hinzufügen
|
||||
print("\nMarkiere gezogene Kombinationen...")
|
||||
combinations_df['bereits_gezogen'] = 0
|
||||
|
||||
marked_count = 0
|
||||
for idx, row in combinations_df.iterrows():
|
||||
combo_key = create_combination_key(row, combo_z_columns)
|
||||
if combo_key in drawn_combinations:
|
||||
combinations_df.at[idx, 'bereits_gezogen'] = 1
|
||||
marked_count += 1
|
||||
|
||||
print(f"Anzahl markierte Kombinationen: {marked_count}")
|
||||
|
||||
# Ergebnis speichern
|
||||
print(f"\nSpeichere Ergebnis in: {output_file}")
|
||||
combinations_df.to_csv(output_file, index=False)
|
||||
|
||||
# Statistiken ausgeben
|
||||
total_combinations = len(combinations_df)
|
||||
drawn_percentage = (marked_count / total_combinations) * 100 if total_combinations > 0 else 0
|
||||
|
||||
print(f"\n=== STATISTIKEN ===")
|
||||
print(f"Gesamte Kombinationen: {total_combinations:,}")
|
||||
print(f"Bereits gezogene Kombinationen: {marked_count:,}")
|
||||
print(f"Prozentsatz bereits gezogen: {drawn_percentage:.4f}%")
|
||||
print(f"Noch nicht gezogene Kombinationen: {total_combinations - marked_count:,}")
|
||||
|
||||
return True
|
||||
|
||||
def main():
|
||||
"""Hauptfunktion mit Benutzerinteraktion."""
|
||||
print("=== Eurojackpot CSV Processor ===\n")
|
||||
|
||||
# Dateipfade abfragen oder Standard verwenden
|
||||
if len(sys.argv) >= 4:
|
||||
combinations_file = sys.argv[1]
|
||||
drawn_numbers_file = sys.argv[2]
|
||||
output_file = sys.argv[3]
|
||||
else:
|
||||
print("Geben Sie die Dateipfade ein (oder drücken Sie Enter für Standard):")
|
||||
|
||||
combinations_file = input("Pfad zur Kombinationsdatei (alle_kombinationen.csv): ").strip()
|
||||
if not combinations_file:
|
||||
combinations_file = "alle_kombinationen.csv"
|
||||
|
||||
drawn_numbers_file = input("Pfad zur Datei mit gezogenen Zahlen (gezogene_zahlen.csv): ").strip()
|
||||
if not drawn_numbers_file:
|
||||
drawn_numbers_file = "gezogene_zahlen.csv"
|
||||
|
||||
output_file = input("Pfad für Ausgabedatei (kombinationen_markiert.csv): ").strip()
|
||||
if not output_file:
|
||||
output_file = "kombinationen_markiert.csv"
|
||||
|
||||
# Überprüfen ob Dateien existieren
|
||||
if not Path(combinations_file).exists():
|
||||
print(f"Fehler: Kombinationsdatei '{combinations_file}' nicht gefunden!")
|
||||
return
|
||||
|
||||
if not Path(drawn_numbers_file).exists():
|
||||
print(f"Fehler: Datei mit gezogenen Zahlen '{drawn_numbers_file}' nicht gefunden!")
|
||||
return
|
||||
|
||||
# Verarbeitung starten
|
||||
success = process_eurojackpot_data(combinations_file, drawn_numbers_file, output_file)
|
||||
|
||||
if success:
|
||||
print(f"\n✅ Verarbeitung erfolgreich abgeschlossen!")
|
||||
print(f"Ergebnis gespeichert in: {output_file}")
|
||||
else:
|
||||
print("\n❌ Fehler bei der Verarbeitung!")
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -1,220 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Eurojackpot CSV Processor - Angepasst für Semikolon-getrennte CSV-Dateien
|
||||
|
||||
Dieses Script liest zwei CSV-Dateien ein:
|
||||
1. Alle möglichen Zahlenkombinationen (5 Zahlen)
|
||||
2. Bereits gezogene Zahlen mit Datumsstempel
|
||||
|
||||
Es markiert in der ersten Datei alle bereits gezogenen Kombinationen mit 1 (sonst 0).
|
||||
"""
|
||||
|
||||
import pandas as pd
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
def detect_separator(filepath):
|
||||
"""Erkennt das CSV-Trennzeichen automatisch."""
|
||||
try:
|
||||
with open(filepath, 'r', encoding='utf-8') as f:
|
||||
first_line = f.readline()
|
||||
if ';' in first_line and first_line.count(';') > first_line.count(','):
|
||||
return ';'
|
||||
return ','
|
||||
except:
|
||||
return ','
|
||||
|
||||
def load_combinations_file(filepath):
|
||||
"""Lädt die Datei mit allen möglichen Kombinationen."""
|
||||
try:
|
||||
sep = detect_separator(filepath)
|
||||
print(f"Erkanntes Trennzeichen für Kombinationen: '{sep}'")
|
||||
|
||||
df = pd.read_csv(filepath, sep=sep)
|
||||
print(f"Kombinationen geladen: {len(df)} Zeilen")
|
||||
print(f"Spalten: {list(df.columns)}")
|
||||
return df
|
||||
except Exception as e:
|
||||
print(f"Fehler beim Laden der Kombinationsdatei: {e}")
|
||||
return None
|
||||
|
||||
def load_drawn_numbers_file(filepath):
|
||||
"""Lädt die Datei mit bereits gezogenen Zahlen."""
|
||||
try:
|
||||
sep = detect_separator(filepath)
|
||||
print(f"Erkanntes Trennzeichen für gezogene Zahlen: '{sep}'")
|
||||
|
||||
df = pd.read_csv(filepath, sep=sep)
|
||||
print(f"Gezogene Zahlen geladen: {len(df)} Zeilen")
|
||||
print(f"Spalten: {list(df.columns)}")
|
||||
return df
|
||||
except Exception as e:
|
||||
print(f"Fehler beim Laden der gezogenen Zahlen: {e}")
|
||||
return None
|
||||
|
||||
def identify_number_columns(df, is_combinations=True):
|
||||
"""Identifiziert die Spalten mit den Zahlen."""
|
||||
columns = df.columns.tolist()
|
||||
|
||||
if is_combinations:
|
||||
# Für Kombinationsdatei: Z1, Z2, Z3, Z4, Z5 suchen
|
||||
z_cols = [col for col in columns if col.startswith('Z') and len(col) == 2 and col[1:].isdigit()]
|
||||
z_cols = sorted(z_cols)[:5]
|
||||
|
||||
if len(z_cols) >= 5:
|
||||
return z_cols
|
||||
|
||||
# Fallback: erste 5 numerische Spalten
|
||||
numeric_cols = df.select_dtypes(include=['number']).columns[:5].tolist()
|
||||
if len(numeric_cols) >= 5:
|
||||
return numeric_cols
|
||||
|
||||
# Fallback: erste 5 Spalten
|
||||
return columns[:5]
|
||||
|
||||
else:
|
||||
# Für gezogene Zahlen: Z1-Z5 suchen (nicht SZ1, SZ2)
|
||||
z_cols = [col for col in columns if col.startswith('Z') and len(col) == 2 and col[1:].isdigit()]
|
||||
z_cols = [col for col in z_cols if not col.startswith('SZ')] # Superzahlen ausschließen
|
||||
z_cols = sorted(z_cols)[:5]
|
||||
|
||||
if len(z_cols) >= 5:
|
||||
return z_cols
|
||||
|
||||
# Fallback: numerische Spalten (ohne Datum)
|
||||
numeric_cols = df.select_dtypes(include=['number']).columns
|
||||
numeric_cols = [col for col in numeric_cols if 'datum' not in col.lower()][:5]
|
||||
if len(numeric_cols) >= 5:
|
||||
return numeric_cols.tolist()
|
||||
|
||||
# Letzter Fallback
|
||||
return columns[:5]
|
||||
|
||||
def create_combination_key(row, z_columns):
|
||||
"""Erstellt einen eindeutigen Schlüssel aus den 5 Zahlen (sortiert)."""
|
||||
try:
|
||||
numbers = [int(row[col]) for col in z_columns]
|
||||
return tuple(sorted(numbers))
|
||||
except:
|
||||
return None
|
||||
|
||||
def process_eurojackpot_data(combinations_file, drawn_numbers_file, output_file):
|
||||
"""Hauptfunktion zur Verarbeitung der Eurojackpot-Daten."""
|
||||
|
||||
# CSV-Dateien laden
|
||||
print("Lade Kombinationsdatei...")
|
||||
combinations_df = load_combinations_file(combinations_file)
|
||||
if combinations_df is None:
|
||||
return False
|
||||
|
||||
print("\nLade Datei mit gezogenen Zahlen...")
|
||||
drawn_df = load_drawn_numbers_file(drawn_numbers_file)
|
||||
if drawn_df is None:
|
||||
return False
|
||||
|
||||
# Spalten für Zahlen identifizieren
|
||||
combo_z_columns = identify_number_columns(combinations_df, is_combinations=True)
|
||||
drawn_z_columns = identify_number_columns(drawn_df, is_combinations=False)
|
||||
|
||||
print(f"\nVerwendete Spalten für Kombinationen: {combo_z_columns}")
|
||||
print(f"Verwendete Spalten für gezogene Zahlen: {drawn_z_columns}")
|
||||
|
||||
# Datencheck
|
||||
print(f"\nErste Kombination: {combinations_df[combo_z_columns].iloc[0].tolist()}")
|
||||
print(f"Erste gezogene Zahlen: {drawn_df[drawn_z_columns].iloc[0].tolist()}")
|
||||
|
||||
# Set mit allen gezogenen Kombinationen erstellen
|
||||
print("\nErstelle Set mit gezogenen Kombinationen...")
|
||||
drawn_combinations = set()
|
||||
|
||||
for _, row in drawn_df.iterrows():
|
||||
combo_key = create_combination_key(row, drawn_z_columns)
|
||||
if combo_key:
|
||||
drawn_combinations.add(combo_key)
|
||||
|
||||
print(f"Anzahl eindeutige gezogene Kombinationen: {len(drawn_combinations)}")
|
||||
|
||||
# Beispiele anzeigen
|
||||
if drawn_combinations:
|
||||
print(f"Erste 5 gezogene Kombinationen: {list(drawn_combinations)[:5]}")
|
||||
|
||||
# Neue Spalte für Markierungen hinzufügen (falls noch nicht vorhanden)
|
||||
if 'bereits_gezogen' not in combinations_df.columns:
|
||||
combinations_df['bereits_gezogen'] = 0
|
||||
else:
|
||||
combinations_df['bereits_gezogen'] = 0 # Zurücksetzen
|
||||
|
||||
print("\nMarkiere gezogene Kombinationen...")
|
||||
marked_count = 0
|
||||
|
||||
for idx, row in combinations_df.iterrows():
|
||||
combo_key = create_combination_key(row, combo_z_columns)
|
||||
if combo_key and combo_key in drawn_combinations:
|
||||
combinations_df.at[idx, 'bereits_gezogen'] = 1
|
||||
marked_count += 1
|
||||
if marked_count <= 5: # Erste 5 Treffer anzeigen
|
||||
print(f"Treffer gefunden: {combo_key}")
|
||||
|
||||
print(f"Anzahl markierte Kombinationen: {marked_count}")
|
||||
|
||||
# Ergebnis speichern
|
||||
print(f"\nSpeichere Ergebnis in: {output_file}")
|
||||
sep = detect_separator(combinations_file) # Gleiches Trennzeichen wie Eingabe verwenden
|
||||
combinations_df.to_csv(output_file, sep=sep, index=False)
|
||||
|
||||
# Statistiken ausgeben
|
||||
total_combinations = len(combinations_df)
|
||||
drawn_percentage = (marked_count / total_combinations) * 100 if total_combinations > 0 else 0
|
||||
|
||||
print(f"\n=== STATISTIKEN ===")
|
||||
print(f"Gesamte Kombinationen: {total_combinations:,}")
|
||||
print(f"Bereits gezogene Kombinationen: {marked_count:,}")
|
||||
print(f"Prozentsatz bereits gezogen: {drawn_percentage:.4f}%")
|
||||
print(f"Noch nicht gezogene Kombinationen: {total_combinations - marked_count:,}")
|
||||
|
||||
return True
|
||||
|
||||
def main():
|
||||
"""Hauptfunktion mit Benutzerinteraktion."""
|
||||
print("=== Eurojackpot CSV Processor (Fixed) ===\n")
|
||||
|
||||
# Dateipfade abfragen oder Standard verwenden
|
||||
if len(sys.argv) >= 4:
|
||||
combinations_file = sys.argv[1]
|
||||
drawn_numbers_file = sys.argv[2]
|
||||
output_file = sys.argv[3]
|
||||
else:
|
||||
print("Geben Sie die Dateipfade ein (oder drücken Sie Enter für Standard):")
|
||||
|
||||
combinations_file = input("Pfad zur Kombinationsdatei: ").strip()
|
||||
if not combinations_file:
|
||||
combinations_file = "Alle_Eurojackpot_Kombinationen_mit_Status.csv"
|
||||
|
||||
drawn_numbers_file = input("Pfad zur Datei mit gezogenen Zahlen: ").strip()
|
||||
if not drawn_numbers_file:
|
||||
drawn_numbers_file = "/Users/sebastianfrohlich/Library/Mobile Documents/com~apple~CloudDocs/Jupyter Notebooks/Eurojackpot/data/AlleEurojackpotzahlen.csv"
|
||||
|
||||
output_file = input("Pfad für Ausgabedatei: ").strip()
|
||||
if not output_file:
|
||||
output_file = "Kombinationen_markiert_fixed.csv"
|
||||
|
||||
# Überprüfen ob Dateien existieren
|
||||
if not Path(combinations_file).exists():
|
||||
print(f"Fehler: Kombinationsdatei '{combinations_file}' nicht gefunden!")
|
||||
return
|
||||
|
||||
if not Path(drawn_numbers_file).exists():
|
||||
print(f"Fehler: Datei mit gezogenen Zahlen '{drawn_numbers_file}' nicht gefunden!")
|
||||
return
|
||||
|
||||
# Verarbeitung starten
|
||||
success = process_eurojackpot_data(combinations_file, drawn_numbers_file, output_file)
|
||||
|
||||
if success:
|
||||
print(f"\n✅ Verarbeitung erfolgreich abgeschlossen!")
|
||||
print(f"Ergebnis gespeichert in: {output_file}")
|
||||
else:
|
||||
print("\n❌ Fehler bei der Verarbeitung!")
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -1,62 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Vereinfachte Version des Eurojackpot Processors
|
||||
Für spezifische Spaltenstrukturen
|
||||
"""
|
||||
|
||||
import pandas as pd
|
||||
|
||||
def process_eurojackpot_simple(combinations_csv, drawn_numbers_csv, output_csv):
|
||||
"""
|
||||
Vereinfachte Verarbeitung mit festen Spaltenstrukturen
|
||||
|
||||
Parameter:
|
||||
- combinations_csv: CSV mit allen Kombinationen (Spalten: Zahl1, Zahl2, Zahl3, Zahl4, Zahl5)
|
||||
- drawn_numbers_csv: CSV mit gezogenen Zahlen (Spalten: Datum, Z1, Z2, Z3, Z4, Z5)
|
||||
- output_csv: Ausgabedatei
|
||||
"""
|
||||
|
||||
# Dateien laden
|
||||
print("Lade Kombinationsdatei...")
|
||||
combinations = pd.read_csv(combinations_csv)
|
||||
|
||||
print("Lade gezogene Zahlen...")
|
||||
drawn = pd.read_csv(drawn_numbers_csv)
|
||||
|
||||
# Gezogene Kombinationen als Set erstellen (sortiert für Vergleich)
|
||||
drawn_sets = set()
|
||||
for _, row in drawn.iterrows():
|
||||
# Annahme: Spalten Z1, Z2, Z3, Z4, Z5 enthalten die Zahlen
|
||||
numbers = sorted([row['Z1'], row['Z2'], row['Z3'], row['Z4'], row['Z5']])
|
||||
drawn_sets.add(tuple(numbers))
|
||||
|
||||
print(f"Gefundene gezogene Kombinationen: {len(drawn_sets)}")
|
||||
|
||||
# Neue Spalte hinzufügen
|
||||
combinations['bereits_gezogen'] = 0
|
||||
|
||||
# Jede Kombination prüfen
|
||||
marked = 0
|
||||
for idx, row in combinations.iterrows():
|
||||
# Annahme: erste 5 Spalten enthalten die Zahlenkombination
|
||||
combo_cols = combinations.columns[:5]
|
||||
numbers = sorted([row[col] for col in combo_cols])
|
||||
|
||||
if tuple(numbers) in drawn_sets:
|
||||
combinations.at[idx, 'bereits_gezogen'] = 1
|
||||
marked += 1
|
||||
|
||||
# Ergebnis speichern
|
||||
combinations.to_csv(output_csv, index=False)
|
||||
|
||||
print(f"Verarbeitung abgeschlossen!")
|
||||
print(f"Markierte Kombinationen: {marked}")
|
||||
print(f"Ergebnis gespeichert in: {output_csv}")
|
||||
|
||||
# Beispielaufruf
|
||||
if __name__ == "__main__":
|
||||
process_eurojackpot_simple(
|
||||
"alle_kombinationen.csv",
|
||||
"gezogene_zahlen.csv",
|
||||
"kombinationen_markiert.csv"
|
||||
)
|
||||
@@ -1,681 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Eurojackpot Historical Data Updater
|
||||
|
||||
Lädt automatisch die neuesten Eurojackpot-Ziehungen von der offiziellen Website
|
||||
und aktualisiert die lokale CSV-Datei.
|
||||
|
||||
Quellen:
|
||||
- https://www.eurojackpot.de/de/eurojackpot/gewinnzahlen.html
|
||||
- Oder alternative APIs/Websites
|
||||
|
||||
Features:
|
||||
- Automatisches Scraping der neuesten Ziehungen
|
||||
- Duplikate-Vermeidung
|
||||
- Backup vor Update
|
||||
- Validierung der neuen Daten
|
||||
"""
|
||||
|
||||
import pandas as pd
|
||||
import requests
|
||||
from bs4 import BeautifulSoup
|
||||
from datetime import datetime
|
||||
import shutil
|
||||
import os
|
||||
import re
|
||||
from typing import List, Dict, Optional
|
||||
import time
|
||||
|
||||
|
||||
class EurojackpotDataUpdater:
|
||||
"""Aktualisiert historische Eurojackpot-Daten automatisch."""
|
||||
|
||||
def __init__(self, data_file: str):
|
||||
"""
|
||||
Initialisiert den Updater.
|
||||
|
||||
Args:
|
||||
data_file: Pfad zur lokalen CSV-Datei
|
||||
"""
|
||||
self.data_file = data_file
|
||||
self.backup_file = None
|
||||
self.df_existing = None
|
||||
|
||||
# API/Scraping URLs
|
||||
self.sources = {
|
||||
'eurojackpot_de': 'https://www.eurojackpot.de/de/eurojackpot/gewinnzahlen.html',
|
||||
'euro-jackpot_net': 'https://www.euro-jackpot.net/de/gewinnzahlen',
|
||||
'lottode': 'https://www.lotto.de/eurojackpot/gewinnzahlen'
|
||||
}
|
||||
|
||||
print("🔄 EUROJACKPOT DATA UPDATER")
|
||||
print("=" * 60)
|
||||
|
||||
def load_existing_data(self) -> bool:
|
||||
"""Lädt existierende Daten."""
|
||||
try:
|
||||
if not os.path.exists(self.data_file):
|
||||
print(f"⚠️ Datei nicht gefunden: {self.data_file}")
|
||||
print(" Erstelle neue Datei...")
|
||||
self.df_existing = pd.DataFrame(columns=['datum', 'Z1', 'Z2', 'Z3', 'Z4', 'Z5', 'SZ1', 'SZ2'])
|
||||
return True
|
||||
|
||||
self.df_existing = pd.read_csv(self.data_file, sep=';')
|
||||
|
||||
# Datum als datetime
|
||||
if 'datum' in self.df_existing.columns:
|
||||
self.df_existing['datum'] = pd.to_datetime(
|
||||
self.df_existing['datum'],
|
||||
format='%Y-%m-%d',
|
||||
errors='coerce'
|
||||
)
|
||||
|
||||
print(f"✅ Existierende Daten geladen: {len(self.df_existing)} Ziehungen")
|
||||
|
||||
if len(self.df_existing) > 0:
|
||||
latest = self.df_existing['datum'].max()
|
||||
print(f" Neueste Ziehung: {latest.strftime('%Y-%m-%d') if pd.notna(latest) else 'Unbekannt'}")
|
||||
|
||||
return True
|
||||
|
||||
except Exception as e:
|
||||
print(f"❌ Fehler beim Laden: {e}")
|
||||
return False
|
||||
|
||||
def create_backup(self) -> bool:
|
||||
"""Erstellt Backup der existierenden Datei."""
|
||||
if not os.path.exists(self.data_file):
|
||||
return True
|
||||
|
||||
try:
|
||||
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
|
||||
backup_dir = os.path.join(os.path.dirname(self.data_file), "backups")
|
||||
os.makedirs(backup_dir, exist_ok=True)
|
||||
|
||||
filename = os.path.basename(self.data_file)
|
||||
self.backup_file = os.path.join(backup_dir, f"{filename}.backup_{timestamp}")
|
||||
|
||||
shutil.copy2(self.data_file, self.backup_file)
|
||||
print(f"✅ Backup erstellt: {os.path.basename(self.backup_file)}")
|
||||
return True
|
||||
|
||||
except Exception as e:
|
||||
print(f"⚠️ Backup-Fehler: {e}")
|
||||
return False
|
||||
|
||||
def fetch_from_eurojackpot_de(self) -> List[Dict]:
|
||||
"""
|
||||
Scrapt Daten von eurojackpot.de
|
||||
|
||||
Returns:
|
||||
Liste von Ziehungen als Dictionaries
|
||||
"""
|
||||
print("\n🌐 Versuche eurojackpot.de...")
|
||||
|
||||
try:
|
||||
headers = {
|
||||
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36'
|
||||
}
|
||||
|
||||
response = requests.get(self.sources['eurojackpot_de'], headers=headers, timeout=10)
|
||||
response.raise_for_status()
|
||||
|
||||
soup = BeautifulSoup(response.content, 'html.parser')
|
||||
|
||||
# Suche nach Ziehungsergebnissen
|
||||
# Dies ist ein generisches Beispiel - muss an tatsächliche Website-Struktur angepasst werden
|
||||
draws = []
|
||||
|
||||
# Beispiel-Parsing (muss angepasst werden!)
|
||||
result_blocks = soup.find_all('div', class_='drawing-result')
|
||||
|
||||
for block in result_blocks[:10]: # Letzte 10 Ziehungen
|
||||
try:
|
||||
# Datum extrahieren
|
||||
date_elem = block.find('span', class_='date')
|
||||
if not date_elem:
|
||||
continue
|
||||
|
||||
date_str = date_elem.text.strip()
|
||||
date_obj = self._parse_german_date(date_str)
|
||||
|
||||
# Zahlen extrahieren
|
||||
numbers = []
|
||||
number_elems = block.find_all('span', class_='ball')
|
||||
|
||||
for num_elem in number_elems[:5]:
|
||||
num = int(num_elem.text.strip())
|
||||
numbers.append(num)
|
||||
|
||||
# Eurozahlen extrahieren
|
||||
euro_numbers = []
|
||||
euro_elems = block.find_all('span', class_='euro-ball')
|
||||
|
||||
for euro_elem in euro_elems[:2]:
|
||||
euro_num = int(euro_elem.text.strip())
|
||||
euro_numbers.append(euro_num)
|
||||
|
||||
if len(numbers) == 5 and len(euro_numbers) == 2:
|
||||
draws.append({
|
||||
'datum': date_obj,
|
||||
'Z1': numbers[0],
|
||||
'Z2': numbers[1],
|
||||
'Z3': numbers[2],
|
||||
'Z4': numbers[3],
|
||||
'Z5': numbers[4],
|
||||
'SZ1': euro_numbers[0],
|
||||
'SZ2': euro_numbers[1]
|
||||
})
|
||||
|
||||
except Exception as e:
|
||||
continue
|
||||
|
||||
if draws:
|
||||
print(f" ✅ {len(draws)} Ziehungen gefunden")
|
||||
return draws
|
||||
else:
|
||||
print(" ⚠️ Keine Ziehungen gefunden (HTML-Struktur möglicherweise geändert)")
|
||||
return []
|
||||
|
||||
except Exception as e:
|
||||
print(f" ❌ Fehler: {e}")
|
||||
return []
|
||||
|
||||
def fetch_from_euro_jackpot_net(self) -> List[Dict]:
|
||||
"""
|
||||
Scrapt Daten von euro-jackpot.net
|
||||
|
||||
Returns:
|
||||
Liste von Ziehungen
|
||||
"""
|
||||
print("\n🌐 Versuche euro-jackpot.net...")
|
||||
|
||||
try:
|
||||
headers = {
|
||||
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36'
|
||||
}
|
||||
|
||||
response = requests.get(self.sources['euro-jackpot_net'], headers=headers, timeout=10)
|
||||
response.raise_for_status()
|
||||
|
||||
soup = BeautifulSoup(response.content, 'html.parser')
|
||||
|
||||
draws = []
|
||||
|
||||
# Parsing-Logik für diese Website
|
||||
# (Platzhalter - muss an tatsächliche Struktur angepasst werden)
|
||||
|
||||
result_rows = soup.find_all('tr', class_='result-row')
|
||||
|
||||
for row in result_rows[:10]:
|
||||
try:
|
||||
cells = row.find_all('td')
|
||||
|
||||
if len(cells) < 8:
|
||||
continue
|
||||
|
||||
# Datum
|
||||
date_str = cells[0].text.strip()
|
||||
date_obj = self._parse_german_date(date_str)
|
||||
|
||||
# Hauptzahlen
|
||||
numbers = [int(cells[i].text.strip()) for i in range(1, 6)]
|
||||
|
||||
# Eurozahlen
|
||||
euro_numbers = [int(cells[i].text.strip()) for i in range(6, 8)]
|
||||
|
||||
draws.append({
|
||||
'datum': date_obj,
|
||||
'Z1': numbers[0],
|
||||
'Z2': numbers[1],
|
||||
'Z3': numbers[2],
|
||||
'Z4': numbers[3],
|
||||
'Z5': numbers[4],
|
||||
'SZ1': euro_numbers[0],
|
||||
'SZ2': euro_numbers[1]
|
||||
})
|
||||
|
||||
except Exception as e:
|
||||
continue
|
||||
|
||||
if draws:
|
||||
print(f" ✅ {len(draws)} Ziehungen gefunden")
|
||||
else:
|
||||
print(" ⚠️ Keine Ziehungen gefunden")
|
||||
|
||||
return draws
|
||||
|
||||
except Exception as e:
|
||||
print(f" ❌ Fehler: {e}")
|
||||
return []
|
||||
|
||||
def fetch_from_manual_input(self) -> List[Dict]:
|
||||
"""
|
||||
Manuelle Eingabe von neuen Ziehungen.
|
||||
|
||||
Returns:
|
||||
Liste von Ziehungen
|
||||
"""
|
||||
print("\n⌨️ MANUELLE EINGABE")
|
||||
print("=" * 60)
|
||||
print("Gib die neuesten Ziehungen manuell ein.")
|
||||
print("Format: YYYY-MM-DD Z1 Z2 Z3 Z4 Z5 SZ1 SZ2")
|
||||
print("Beispiel: 2025-01-24 7 18 26 37 46 3 11")
|
||||
print("Leer lassen zum Beenden.\n")
|
||||
|
||||
draws = []
|
||||
|
||||
while True:
|
||||
user_input = input(f"Ziehung {len(draws) + 1}: ").strip()
|
||||
|
||||
if not user_input:
|
||||
break
|
||||
|
||||
try:
|
||||
parts = user_input.split()
|
||||
|
||||
if len(parts) != 8:
|
||||
print(" ❌ Ungültiges Format. Bitte 8 Werte eingeben.")
|
||||
continue
|
||||
|
||||
date_obj = datetime.strptime(parts[0], '%Y-%m-%d')
|
||||
numbers = [int(parts[i]) for i in range(1, 6)]
|
||||
euro_numbers = [int(parts[i]) for i in range(6, 8)]
|
||||
|
||||
# Validierung
|
||||
if not all(1 <= n <= 50 for n in numbers):
|
||||
print(" ❌ Hauptzahlen müssen zwischen 1 und 50 liegen.")
|
||||
continue
|
||||
|
||||
if not all(1 <= n <= 12 for n in euro_numbers):
|
||||
print(" ❌ Eurozahlen müssen zwischen 1 und 12 liegen.")
|
||||
continue
|
||||
|
||||
if len(set(numbers)) != 5:
|
||||
print(" ❌ Hauptzahlen müssen eindeutig sein.")
|
||||
continue
|
||||
|
||||
if len(set(euro_numbers)) != 2:
|
||||
print(" ❌ Eurozahlen müssen eindeutig sein.")
|
||||
continue
|
||||
|
||||
draws.append({
|
||||
'datum': date_obj,
|
||||
'Z1': numbers[0],
|
||||
'Z2': numbers[1],
|
||||
'Z3': numbers[2],
|
||||
'Z4': numbers[3],
|
||||
'Z5': numbers[4],
|
||||
'SZ1': euro_numbers[0],
|
||||
'SZ2': euro_numbers[1]
|
||||
})
|
||||
|
||||
print(f" ✅ Ziehung hinzugefügt: {date_obj.strftime('%Y-%m-%d')}")
|
||||
|
||||
except ValueError as e:
|
||||
print(f" ❌ Fehler: {e}")
|
||||
continue
|
||||
|
||||
if draws:
|
||||
print(f"\n✅ {len(draws)} Ziehungen manuell eingegeben")
|
||||
|
||||
return draws
|
||||
|
||||
def _parse_german_date(self, date_str: str) -> datetime:
|
||||
"""
|
||||
Parst deutsches Datumsformat.
|
||||
|
||||
Args:
|
||||
date_str: Datum als String (z.B. "24.01.2025" oder "24. Januar 2025")
|
||||
|
||||
Returns:
|
||||
datetime Objekt
|
||||
"""
|
||||
# Entferne zusätzliche Leerzeichen
|
||||
date_str = re.sub(r'\s+', ' ', date_str.strip())
|
||||
|
||||
# Monatsnamen-Mapping
|
||||
months_de = {
|
||||
'januar': 1, 'februar': 2, 'märz': 3, 'april': 4,
|
||||
'mai': 5, 'juni': 6, 'juli': 7, 'august': 8,
|
||||
'september': 9, 'oktober': 10, 'november': 11, 'dezember': 12
|
||||
}
|
||||
|
||||
# Versuche verschiedene Formate
|
||||
formats = [
|
||||
'%d.%m.%Y',
|
||||
'%d.%m.%y',
|
||||
'%Y-%m-%d',
|
||||
'%d/%m/%Y'
|
||||
]
|
||||
|
||||
for fmt in formats:
|
||||
try:
|
||||
return datetime.strptime(date_str, fmt)
|
||||
except ValueError:
|
||||
continue
|
||||
|
||||
# Versuche mit Monatsnamen
|
||||
for month_name, month_num in months_de.items():
|
||||
if month_name.lower() in date_str.lower():
|
||||
# Extrahiere Tag und Jahr
|
||||
match = re.search(r'(\d{1,2})\.?\s+' + month_name + r'\s+(\d{4})', date_str, re.IGNORECASE)
|
||||
if match:
|
||||
day = int(match.group(1))
|
||||
year = int(match.group(2))
|
||||
return datetime(year, month_num, day)
|
||||
|
||||
# Fallback: aktuelles Datum
|
||||
print(f" ⚠️ Konnte Datum nicht parsen: {date_str}, nutze aktuelles Datum")
|
||||
return datetime.now()
|
||||
|
||||
def fetch_new_draws(self, source: str = 'auto') -> List[Dict]:
|
||||
"""
|
||||
Holt neue Ziehungen von der gewählten Quelle.
|
||||
|
||||
Args:
|
||||
source: 'auto', 'eurojackpot_de', 'euro_jackpot_net', 'manual'
|
||||
|
||||
Returns:
|
||||
Liste von neuen Ziehungen
|
||||
"""
|
||||
print(f"\n🔍 SUCHE NACH NEUEN ZIEHUNGEN (Quelle: {source})")
|
||||
print("=" * 60)
|
||||
|
||||
all_draws = []
|
||||
|
||||
if source == 'auto':
|
||||
# Versuche alle Quellen
|
||||
sources_to_try = [
|
||||
('eurojackpot_de', self.fetch_from_eurojackpot_de),
|
||||
('euro_jackpot_net', self.fetch_from_euro_jackpot_net)
|
||||
]
|
||||
|
||||
for source_name, fetch_func in sources_to_try:
|
||||
draws = fetch_func()
|
||||
if draws:
|
||||
all_draws.extend(draws)
|
||||
break # Erste erfolgreiche Quelle nutzen
|
||||
time.sleep(1) # Pause zwischen Requests
|
||||
|
||||
if not all_draws:
|
||||
print("\n⚠️ Automatisches Scraping fehlgeschlagen.")
|
||||
print(" Möchtest du Daten manuell eingeben? (j/n): ", end='')
|
||||
if input().lower() in ['j', 'ja', 'y', 'yes']:
|
||||
all_draws = self.fetch_from_manual_input()
|
||||
|
||||
elif source == 'eurojackpot_de':
|
||||
all_draws = self.fetch_from_eurojackpot_de()
|
||||
|
||||
elif source == 'euro_jackpot_net':
|
||||
all_draws = self.fetch_from_euro_jackpot_net()
|
||||
|
||||
elif source == 'manual':
|
||||
all_draws = self.fetch_from_manual_input()
|
||||
|
||||
else:
|
||||
print(f"❌ Unbekannte Quelle: {source}")
|
||||
|
||||
return all_draws
|
||||
|
||||
def validate_draw(self, draw: Dict) -> bool:
|
||||
"""
|
||||
Validiert eine Ziehung.
|
||||
|
||||
Args:
|
||||
draw: Ziehungs-Dictionary
|
||||
|
||||
Returns:
|
||||
True wenn valide
|
||||
"""
|
||||
try:
|
||||
# Prüfe Pflichtfelder
|
||||
required_fields = ['datum', 'Z1', 'Z2', 'Z3', 'Z4', 'Z5', 'SZ1', 'SZ2']
|
||||
if not all(field in draw for field in required_fields):
|
||||
return False
|
||||
|
||||
# Prüfe Hauptzahlen (1-50)
|
||||
main_numbers = [draw[f'Z{i}'] for i in range(1, 6)]
|
||||
if not all(1 <= n <= 50 for n in main_numbers):
|
||||
return False
|
||||
|
||||
if len(set(main_numbers)) != 5: # Eindeutig
|
||||
return False
|
||||
|
||||
# Prüfe Eurozahlen (1-12)
|
||||
euro_numbers = [draw['SZ1'], draw['SZ2']]
|
||||
if not all(1 <= n <= 12 for n in euro_numbers):
|
||||
return False
|
||||
|
||||
if len(set(euro_numbers)) != 2: # Eindeutig
|
||||
return False
|
||||
|
||||
# Prüfe Datum
|
||||
if not isinstance(draw['datum'], datetime):
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
except Exception:
|
||||
return False
|
||||
|
||||
def merge_with_existing(self, new_draws: List[Dict]) -> pd.DataFrame:
|
||||
"""
|
||||
Merged neue Ziehungen mit existierenden Daten.
|
||||
|
||||
Args:
|
||||
new_draws: Liste von neuen Ziehungen
|
||||
|
||||
Returns:
|
||||
Zusammengeführter DataFrame
|
||||
"""
|
||||
print(f"\n🔀 MERGE MIT EXISTIERENDEN DATEN")
|
||||
print("=" * 60)
|
||||
|
||||
# Validiere neue Ziehungen
|
||||
valid_draws = [draw for draw in new_draws if self.validate_draw(draw)]
|
||||
|
||||
if len(valid_draws) < len(new_draws):
|
||||
invalid_count = len(new_draws) - len(valid_draws)
|
||||
print(f"⚠️ {invalid_count} ungültige Ziehung(en) übersprungen")
|
||||
|
||||
if not valid_draws:
|
||||
print("❌ Keine gültigen neuen Ziehungen zum Hinzufügen")
|
||||
return self.df_existing
|
||||
|
||||
# Erstelle DataFrame aus neuen Ziehungen
|
||||
df_new = pd.DataFrame(valid_draws)
|
||||
|
||||
# Kombiniere
|
||||
if self.df_existing is None or len(self.df_existing) == 0:
|
||||
df_combined = df_new
|
||||
else:
|
||||
df_combined = pd.concat([self.df_existing, df_new], ignore_index=True)
|
||||
|
||||
# Entferne Duplikate (basierend auf Datum + Zahlen)
|
||||
before_dedup = len(df_combined)
|
||||
df_combined = df_combined.drop_duplicates(
|
||||
subset=['datum', 'Z1', 'Z2', 'Z3', 'Z4', 'Z5'],
|
||||
keep='first'
|
||||
)
|
||||
after_dedup = len(df_combined)
|
||||
|
||||
duplicates_removed = before_dedup - after_dedup
|
||||
if duplicates_removed > 0:
|
||||
print(f"🗑️ {duplicates_removed} Duplikat(e) entfernt")
|
||||
|
||||
# Sortiere nach Datum
|
||||
df_combined = df_combined.sort_values('datum', ascending=True)
|
||||
df_combined = df_combined.reset_index(drop=True)
|
||||
|
||||
# Berechne neue Einträge
|
||||
new_entries = len(df_combined) - len(self.df_existing) if self.df_existing is not None else len(df_combined)
|
||||
|
||||
print(f"✅ Merge abgeschlossen:")
|
||||
print(f" Vorher: {len(self.df_existing) if self.df_existing is not None else 0} Ziehungen")
|
||||
print(f" Neu hinzugefügt: {new_entries} Ziehungen")
|
||||
print(f" Nachher: {len(df_combined)} Ziehungen")
|
||||
|
||||
return df_combined
|
||||
|
||||
def save_updated_data(self, df: pd.DataFrame) -> bool:
|
||||
"""
|
||||
Speichert aktualisierte Daten.
|
||||
|
||||
Args:
|
||||
df: DataFrame zum Speichern
|
||||
|
||||
Returns:
|
||||
True bei Erfolg
|
||||
"""
|
||||
try:
|
||||
# Format Datum als String
|
||||
df_to_save = df.copy()
|
||||
df_to_save['datum'] = df_to_save['datum'].dt.strftime('%Y-%m-%d')
|
||||
|
||||
# Speichern
|
||||
df_to_save.to_csv(self.data_file, sep=';', index=False)
|
||||
|
||||
print(f"\n💾 Daten gespeichert: {self.data_file}")
|
||||
print(f" {len(df)} Ziehungen total")
|
||||
|
||||
if len(df) > 0:
|
||||
latest = df['datum'].max()
|
||||
print(f" Neueste Ziehung: {latest.strftime('%Y-%m-%d')}")
|
||||
|
||||
return True
|
||||
|
||||
except Exception as e:
|
||||
print(f"❌ Fehler beim Speichern: {e}")
|
||||
|
||||
# Restore backup
|
||||
if self.backup_file and os.path.exists(self.backup_file):
|
||||
print("🔄 Stelle Backup wieder her...")
|
||||
shutil.copy2(self.backup_file, self.data_file)
|
||||
print("✅ Backup wiederhergestellt")
|
||||
|
||||
return False
|
||||
|
||||
def update(self, source: str = 'auto', dry_run: bool = False) -> bool:
|
||||
"""
|
||||
Führt komplettes Update durch.
|
||||
|
||||
Args:
|
||||
source: Datenquelle ('auto', 'eurojackpot_de', 'euro_jackpot_net', 'manual')
|
||||
dry_run: Wenn True, keine Änderungen speichern
|
||||
|
||||
Returns:
|
||||
True bei Erfolg
|
||||
"""
|
||||
print(f"\n{'🧪 DRY RUN MODE' if dry_run else '🚀 UPDATE STARTEN'}")
|
||||
print("=" * 60)
|
||||
|
||||
# 1. Lade existierende Daten
|
||||
if not self.load_existing_data():
|
||||
return False
|
||||
|
||||
# 2. Backup erstellen
|
||||
if not dry_run:
|
||||
self.create_backup()
|
||||
|
||||
# 3. Hole neue Ziehungen
|
||||
new_draws = self.fetch_new_draws(source=source)
|
||||
|
||||
if not new_draws:
|
||||
print("\n✅ Keine neuen Ziehungen gefunden - Daten sind aktuell")
|
||||
return True
|
||||
|
||||
# 4. Merge mit existierenden Daten
|
||||
df_updated = self.merge_with_existing(new_draws)
|
||||
|
||||
# 5. Speichern
|
||||
if not dry_run:
|
||||
return self.save_updated_data(df_updated)
|
||||
else:
|
||||
print("\n🧪 DRY RUN - Keine Änderungen gespeichert")
|
||||
print(f" Würde {len(df_updated)} Ziehungen speichern")
|
||||
return True
|
||||
|
||||
|
||||
def main():
|
||||
"""Hauptfunktion für interaktive Nutzung."""
|
||||
print("=" * 70)
|
||||
print(" EUROJACKPOT HISTORICAL DATA UPDATER")
|
||||
print("=" * 70)
|
||||
print()
|
||||
|
||||
# Konfiguration
|
||||
default_data_file = "/Users/sebastianfrohlich/Library/Mobile Documents/com~apple~CloudDocs/Jupyter Notebooks/Eurojackpot/data/AlleEurojackpotzahlen.csv"
|
||||
|
||||
print("📁 KONFIGURATION")
|
||||
print("=" * 60)
|
||||
print(f"Standard-Datei: {default_data_file}")
|
||||
print()
|
||||
|
||||
use_default = input("Standard-Datei verwenden? (j/n): ").lower().strip()
|
||||
|
||||
if use_default in ['j', 'ja', 'y', 'yes', '']:
|
||||
data_file = default_data_file
|
||||
else:
|
||||
data_file = input("Pfad zur Datendatei: ").strip()
|
||||
|
||||
print()
|
||||
print("🌐 DATENQUELLE WÄHLEN")
|
||||
print("=" * 60)
|
||||
print("1. Auto (versucht alle Quellen)")
|
||||
print("2. eurojackpot.de")
|
||||
print("3. euro-jackpot.net")
|
||||
print("4. Manuelle Eingabe")
|
||||
print()
|
||||
|
||||
source_choice = input("Wahl (1-4): ").strip()
|
||||
|
||||
source_map = {
|
||||
'1': 'auto',
|
||||
'2': 'eurojackpot_de',
|
||||
'3': 'euro_jackpot_net',
|
||||
'4': 'manual'
|
||||
}
|
||||
|
||||
source = source_map.get(source_choice, 'auto')
|
||||
|
||||
print()
|
||||
print("🧪 DRY RUN?")
|
||||
print("=" * 60)
|
||||
print("Dry Run = Keine Änderungen, nur Vorschau")
|
||||
dry_run_choice = input("Dry Run aktivieren? (j/n): ").lower().strip()
|
||||
dry_run = dry_run_choice in ['j', 'ja', 'y', 'yes']
|
||||
|
||||
print()
|
||||
|
||||
# Update durchführen
|
||||
updater = EurojackpotDataUpdater(data_file)
|
||||
success = updater.update(source=source, dry_run=dry_run)
|
||||
|
||||
print()
|
||||
print("=" * 70)
|
||||
if success:
|
||||
print("✅ UPDATE ERFOLGREICH ABGESCHLOSSEN")
|
||||
else:
|
||||
print("❌ UPDATE FEHLGESCHLAGEN")
|
||||
print("=" * 70)
|
||||
|
||||
return success
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
import sys
|
||||
|
||||
# Einfache CLI
|
||||
if len(sys.argv) > 1:
|
||||
# Kommandozeilen-Modus
|
||||
data_file = sys.argv[1]
|
||||
source = sys.argv[2] if len(sys.argv) > 2 else 'auto'
|
||||
dry_run = '--dry-run' in sys.argv
|
||||
|
||||
updater = EurojackpotDataUpdater(data_file)
|
||||
success = updater.update(source=source, dry_run=dry_run)
|
||||
sys.exit(0 if success else 1)
|
||||
else:
|
||||
# Interaktiver Modus
|
||||
main()
|
||||
@@ -1,210 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Eurojackpot Zahlen-Umschlüsselung
|
||||
|
||||
Fügt neue Spalten z1, z2, z3, z4, z5 hinzu mit umschlüsselten Werten:
|
||||
1-5 → 1, 6-10 → 2, 11-15 → 3, 16-20 → 4, 21-25 → 5,
|
||||
26-30 → 6, 31-35 → 7, 36-40 → 8, 41-45 → 9, 46-50 → 10
|
||||
"""
|
||||
|
||||
import pandas as pd
|
||||
|
||||
def convert_number_to_group(number):
|
||||
"""Konvertiert eine Zahl (1-50) in eine Gruppe (1-10)."""
|
||||
if 1 <= number <= 5:
|
||||
return 1
|
||||
elif 6 <= number <= 10:
|
||||
return 2
|
||||
elif 11 <= number <= 15:
|
||||
return 3
|
||||
elif 16 <= number <= 20:
|
||||
return 4
|
||||
elif 21 <= number <= 25:
|
||||
return 5
|
||||
elif 26 <= number <= 30:
|
||||
return 6
|
||||
elif 31 <= number <= 35:
|
||||
return 7
|
||||
elif 36 <= number <= 40:
|
||||
return 8
|
||||
elif 41 <= number <= 45:
|
||||
return 9
|
||||
elif 46 <= number <= 50:
|
||||
return 10
|
||||
else:
|
||||
return 0 # Fehlerfall
|
||||
|
||||
def process_number_conversion():
|
||||
"""Führt die Zahlenumschlüsselung durch."""
|
||||
|
||||
# Eingabedatei laden
|
||||
input_file = "/Users/sebastianfrohlich/Library/Mobile Documents/com~apple~CloudDocs/Jupyter Notebooks/Eurojackpot/data/AlleEurojackpotzahlen.csv"
|
||||
|
||||
print("🔢 EUROJACKPOT ZAHLEN-UMSCHLÜSSELUNG")
|
||||
print("="*50)
|
||||
|
||||
# Daten laden
|
||||
print(f"📁 Lade Daten aus: AlleEurojackpotzahlen.csv")
|
||||
df = pd.read_csv(input_file, sep=';')
|
||||
print(f"✅ {len(df)} Ziehungen geladen")
|
||||
|
||||
# Umschlüsselungsschema anzeigen
|
||||
print(f"\n📋 UMSCHLÜSSELUNGSSCHEMA:")
|
||||
print("="*30)
|
||||
ranges = [
|
||||
(1, 5, 1), (6, 10, 2), (11, 15, 3), (16, 20, 4), (21, 25, 5),
|
||||
(26, 30, 6), (31, 35, 7), (36, 40, 8), (41, 45, 9), (46, 50, 10)
|
||||
]
|
||||
|
||||
for start, end, group in ranges:
|
||||
print(f"Zahlen {start:2}-{end:2} → Gruppe {group:2}")
|
||||
|
||||
# Neue Spalten erstellen
|
||||
print(f"\n🔄 Erstelle neue Spalten z1, z2, z3, z4, z5...")
|
||||
|
||||
source_columns = ['Z1', 'Z2', 'Z3', 'Z4', 'Z5']
|
||||
target_columns = ['z1', 'z2', 'z3', 'z4', 'z5']
|
||||
|
||||
for source_col, target_col in zip(source_columns, target_columns):
|
||||
df[target_col] = df[source_col].apply(convert_number_to_group)
|
||||
print(f" {source_col} → {target_col} ✅")
|
||||
|
||||
# Erste 5 Beispiele anzeigen
|
||||
print(f"\n📊 BEISPIEL-UMSCHLÜSSELUNGEN (erste 5 Ziehungen):")
|
||||
print("="*60)
|
||||
print(f"{'Datum':<12} {'Z1→z1':<8} {'Z2→z2':<8} {'Z3→z3':<8} {'Z4→z4':<8} {'Z5→z5':<8}")
|
||||
print("-" * 60)
|
||||
|
||||
for i in range(min(5, len(df))):
|
||||
row = df.iloc[i]
|
||||
datum = row['datum']
|
||||
conversions = []
|
||||
for source_col, target_col in zip(source_columns, target_columns):
|
||||
original = row[source_col]
|
||||
converted = row[target_col]
|
||||
conversions.append(f"{original:2}→{converted}")
|
||||
|
||||
print(f"{datum:<12} {conversions[0]:<8} {conversions[1]:<8} {conversions[2]:<8} {conversions[3]:<8} {conversions[4]:<8}")
|
||||
|
||||
# Statistiken der Umschlüsselung
|
||||
print(f"\n📈 STATISTIKEN DER UMSCHLÜSSELTEN WERTE:")
|
||||
print("="*45)
|
||||
|
||||
# Häufigkeit der Gruppen über alle Positionen
|
||||
all_converted_values = []
|
||||
for target_col in target_columns:
|
||||
all_converted_values.extend(df[target_col].tolist())
|
||||
|
||||
from collections import Counter
|
||||
group_counts = Counter(all_converted_values)
|
||||
|
||||
print(f"Verteilung der Gruppen (1-10) über alle Positionen:")
|
||||
total_values = len(all_converted_values)
|
||||
|
||||
for group in range(1, 11):
|
||||
count = group_counts.get(group, 0)
|
||||
percentage = (count / total_values) * 100
|
||||
original_range = f"{(group-1)*5 + 1}-{group*5}"
|
||||
print(f"Gruppe {group:2} ({original_range:5}): {count:4}x ({percentage:5.1f}%)")
|
||||
|
||||
# Statistiken pro Position
|
||||
print(f"\n📊 VERTEILUNG PRO POSITION:")
|
||||
print("="*35)
|
||||
|
||||
for i, target_col in enumerate(target_columns, 1):
|
||||
position_counts = Counter(df[target_col])
|
||||
print(f"\nPosition z{i} ({target_col}):")
|
||||
for group in range(1, 11):
|
||||
count = position_counts.get(group, 0)
|
||||
percentage = (count / len(df)) * 100
|
||||
print(f" Gruppe {group:2}: {count:3}x ({percentage:4.1f}%)")
|
||||
|
||||
# Häufigste Kombinationen der umschlüsselten Werte
|
||||
print(f"\n🎯 HÄUFIGSTE KOMBINATIONEN (umschlüsselt):")
|
||||
print("="*45)
|
||||
|
||||
# Kombinationen als Strings erstellen
|
||||
df['kombination_umschluesselt'] = df.apply(
|
||||
lambda row: f"{row['z1']}-{row['z2']}-{row['z3']}-{row['z4']}-{row['z5']}", axis=1
|
||||
)
|
||||
|
||||
combination_counts = Counter(df['kombination_umschluesselt'])
|
||||
|
||||
print(f"Top 15 Kombinationen (z1-z2-z3-z4-z5):")
|
||||
for i, (combination, count) in enumerate(combination_counts.most_common(15), 1):
|
||||
percentage = (count / len(df)) * 100
|
||||
print(f"{i:2}. {combination:15} {count:3}x ({percentage:4.1f}%)")
|
||||
|
||||
# Muster-Analyse
|
||||
print(f"\n🔍 MUSTER-ANALYSE:")
|
||||
print("="*25)
|
||||
|
||||
# Aufsteigende Kombinationen
|
||||
ascending_count = 0
|
||||
descending_count = 0
|
||||
|
||||
for _, row in df.iterrows():
|
||||
values = [row[col] for col in target_columns]
|
||||
if values == sorted(values):
|
||||
ascending_count += 1
|
||||
elif values == sorted(values, reverse=True):
|
||||
descending_count += 1
|
||||
|
||||
print(f"Aufsteigende Kombinationen: {ascending_count} ({(ascending_count/len(df)*100):.1f}%)")
|
||||
print(f"Absteigende Kombinationen: {descending_count} ({(descending_count/len(df)*100):.1f}%)")
|
||||
|
||||
# Gleiche Werte
|
||||
same_values_stats = {}
|
||||
for num_same in range(2, 6):
|
||||
count = 0
|
||||
for _, row in df.iterrows():
|
||||
values = [row[col] for col in target_columns]
|
||||
value_counts = Counter(values)
|
||||
if max(value_counts.values()) >= num_same:
|
||||
count += 1
|
||||
same_values_stats[num_same] = count
|
||||
print(f"Mindestens {num_same} gleiche Werte: {count} ({(count/len(df)*100):.1f}%)")
|
||||
|
||||
# Bereiche der umschlüsselten Werte
|
||||
print(f"\n📋 BEREICHSANALYSE (umschlüsselt):")
|
||||
print("="*35)
|
||||
|
||||
# Niedrig (1-3), Mittel (4-7), Hoch (8-10)
|
||||
for i, target_col in enumerate(target_columns, 1):
|
||||
low_count = sum(1 for val in df[target_col] if 1 <= val <= 3)
|
||||
mid_count = sum(1 for val in df[target_col] if 4 <= val <= 7)
|
||||
high_count = sum(1 for val in df[target_col] if 8 <= val <= 10)
|
||||
|
||||
low_pct = (low_count / len(df)) * 100
|
||||
mid_pct = (mid_count / len(df)) * 100
|
||||
high_pct = (high_count / len(df)) * 100
|
||||
|
||||
print(f"z{i}: Niedrig(1-3)={low_pct:4.1f}% | Mittel(4-7)={mid_pct:4.1f}% | Hoch(8-10)={high_pct:4.1f}%")
|
||||
|
||||
# Ausgabedatei speichern
|
||||
output_file = "/Users/sebastianfrohlich/Library/Mobile Documents/com~apple~CloudDocs/Jupyter Notebooks/Eurojackpot/AlleEurojackpotzahlen_umschluesselt.csv"
|
||||
|
||||
print(f"\n💾 DATEI SPEICHERN:")
|
||||
print("="*25)
|
||||
|
||||
# Spalten neu ordnen (Original + neue Spalten)
|
||||
column_order = ['tag', 'datum', 'Z1', 'Z2', 'Z3', 'Z4', 'Z5', 'z1', 'z2', 'z3', 'z4', 'z5', 'SZ1', 'SZ2', 'kombination_umschluesselt']
|
||||
|
||||
# Prüfen welche Spalten existieren
|
||||
available_columns = [col for col in column_order if col in df.columns]
|
||||
df_output = df[available_columns]
|
||||
|
||||
df_output.to_csv(output_file, sep=';', index=False)
|
||||
print(f"✅ Umschlüsselte Daten gespeichert: AlleEurojackpotzahlen_umschluesselt.csv")
|
||||
print(f"📊 Anzahl Spalten: {len(df_output.columns)}")
|
||||
print(f"📈 Anzahl Zeilen: {len(df_output)}")
|
||||
|
||||
print(f"\n🔍 NEUE SPALTEN:")
|
||||
for col in ['z1', 'z2', 'z3', 'z4', 'z5', 'kombination_umschluesselt']:
|
||||
if col in df_output.columns:
|
||||
print(f" ✅ {col}")
|
||||
|
||||
return df_output
|
||||
|
||||
if __name__ == "__main__":
|
||||
result_df = process_number_conversion()
|
||||
Reference in new issue
Block a user