From f23922e05ec20bbb7df8e05b836d22c4948062b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Fr=C3=B6hlich?= Date: Mon, 10 Aug 2026 18:53:39 +0200 Subject: [PATCH] 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 --- .../analysis/bereichskombinationen_analyse.py | 188 --- .../analysis/eurojackpot_bereichsanalyse.py | 217 --- scripts/analysis/positionsanalyse.py | 208 --- scripts/analysis/simple_bereichsanalyse.py | 54 - .../analysis/treffer_analyse_umschluesselt.py | 270 ---- scripts/generators/eurojackpot_generator.py | 141 -- .../optimized_eurojackpot_generator.py | 806 ---------- scripts/generators/tipp_generator_nmmhh.py | 234 --- scripts/generators/tipp_generator_nmmhh_v2.py | 234 --- ...ai_ml_eurojackpot_generator_v2.1_backup.py | 1338 ----------------- scripts/utils/create_example_files.py | 77 - scripts/utils/eurojackpot_processor.py | 165 -- scripts/utils/eurojackpot_processor_fixed.py | 220 --- scripts/utils/eurojackpot_simple.py | 62 - scripts/utils/update_historical_data.py | 681 --------- scripts/utils/zahlen_umschluesseln.py | 210 --- 16 files changed, 5105 deletions(-) delete mode 100644 scripts/analysis/bereichskombinationen_analyse.py delete mode 100644 scripts/analysis/eurojackpot_bereichsanalyse.py delete mode 100644 scripts/analysis/positionsanalyse.py delete mode 100644 scripts/analysis/simple_bereichsanalyse.py delete mode 100644 scripts/analysis/treffer_analyse_umschluesselt.py delete mode 100644 scripts/generators/eurojackpot_generator.py delete mode 100644 scripts/generators/optimized_eurojackpot_generator.py delete mode 100644 scripts/generators/tipp_generator_nmmhh.py delete mode 100644 scripts/generators/tipp_generator_nmmhh_v2.py delete mode 100644 scripts/generators/ultimate_ai_ml_eurojackpot_generator_v2.1_backup.py delete mode 100644 scripts/utils/create_example_files.py delete mode 100644 scripts/utils/eurojackpot_processor.py delete mode 100644 scripts/utils/eurojackpot_processor_fixed.py delete mode 100644 scripts/utils/eurojackpot_simple.py delete mode 100644 scripts/utils/update_historical_data.py delete mode 100644 scripts/utils/zahlen_umschluesseln.py diff --git a/scripts/analysis/bereichskombinationen_analyse.py b/scripts/analysis/bereichskombinationen_analyse.py deleted file mode 100644 index 6d3883d..0000000 --- a/scripts/analysis/bereichskombinationen_analyse.py +++ /dev/null @@ -1,188 +0,0 @@ -#!/usr/bin/env python3 -""" -Eurojackpot Bereichskombinationen-Analyse - -Analysiert die Kombinationen von Zahlenbereichen in den gezogenen 5er-Kombinationen. -Focus auf Z1-Z4 wie gewünscht. -""" - -import pandas as pd -from collections import Counter, defaultdict - -def get_range_for_number(number): - """Bestimmt den Bereich für eine gegebene Zahl.""" - if 1 <= number <= 10: - return 'A(1-10)' - elif 11 <= number <= 20: - return 'B(11-20)' - elif 21 <= number <= 30: - return 'C(21-30)' - elif 31 <= number <= 40: - return 'D(31-40)' - elif 41 <= number <= 50: - return 'E(41-50)' - else: - return 'Unknown' - -def analyze_range_combinations(): - """Analysiert Bereichskombinationen in Eurojackpot-Ziehungen.""" - - # Daten laden - df = pd.read_csv("/Users/sebastianfrohlich/Library/Mobile Documents/com~apple~CloudDocs/Jupyter Notebooks/Eurojackpot/data/AlleEurojackpotzahlen.csv", sep=';') - - print(f"🎲 EUROJACKPOT BEREICHSKOMBINATIONEN-ANALYSE") - print(f"Anzahl analysierte Ziehungen: {len(df)}") - print("="*60) - - # Analyse für Z1-Z4 (wie gewünscht) - z_columns_z1_z4 = ['Z1', 'Z2', 'Z3', 'Z4'] - - # Alle Kombinationen sammeln - combinations_z1_z4 = [] - range_patterns_z1_z4 = [] - - for _, row in df.iterrows(): - # Bereiche für Z1-Z4 bestimmen - ranges = [get_range_for_number(row[col]) for col in z_columns_z1_z4] - range_pattern = '|'.join(sorted(ranges)) # Sortiert für einheitliche Muster - - combinations_z1_z4.append(tuple(ranges)) - range_patterns_z1_z4.append(range_pattern) - - # Auch vollständige Z1-Z5 Analyse - z_columns_all = ['Z1', 'Z2', 'Z3', 'Z4', 'Z5'] - combinations_all = [] - range_patterns_all = [] - - for _, row in df.iterrows(): - ranges = [get_range_for_number(row[col]) for col in z_columns_all] - range_pattern = '|'.join(sorted(ranges)) - - combinations_all.append(tuple(ranges)) - range_patterns_all.append(range_pattern) - - # Häufigkeitsanalyse - print("\n📊 ANALYSE Z1-Z4 (4 Zahlen):") - print("="*40) - - pattern_counts_z1_z4 = Counter(range_patterns_z1_z4) - - print(f"Häufigste Bereichskombinationen (Z1-Z4):") - for i, (pattern, count) in enumerate(pattern_counts_z1_z4.most_common(15), 1): - percentage = (count / len(df)) * 100 - print(f"{i:2}. {pattern:30} {count:3}x ({percentage:4.1f}%)") - - print(f"\n📊 VERGLEICH: ANALYSE Z1-Z5 (alle 5 Zahlen):") - print("="*40) - - pattern_counts_all = Counter(range_patterns_all) - - print(f"Häufigste Bereichskombinationen (Z1-Z5):") - for i, (pattern, count) in enumerate(pattern_counts_all.most_common(15), 1): - percentage = (count / len(df)) * 100 - print(f"{i:2}. {pattern:35} {count:3}x ({percentage:4.1f}%)") - - # Analyse der Bereichsverteilung in Kombinationen - print(f"\n🎯 BEREICHSVERTEILUNG IN KOMBINATIONEN:") - print("="*50) - - # Wie oft kommt jeder Bereich in Z1-Z4 vor? - range_in_combination_counts = defaultdict(int) - - for combination in combinations_z1_z4: - for range_name in set(combination): # set() um Duplikate zu vermeiden - range_in_combination_counts[range_name] += 1 - - print("Häufigkeit der Bereiche in Z1-Z4 Kombinationen:") - for range_name in ['A(1-10)', 'B(11-20)', 'C(21-30)', 'D(31-40)', 'E(41-50)']: - count = range_in_combination_counts[range_name] - percentage = (count / len(df)) * 100 - print(f"{range_name}: {count:3} Kombinationen ({percentage:4.1f}%)") - - # Analyse: Wie viele verschiedene Bereiche pro Kombination? - print(f"\n📈 BEREICHSVIELFALT PRO KOMBINATION (Z1-Z4):") - print("="*45) - - diversity_counts = defaultdict(int) - - for combination in combinations_z1_z4: - unique_ranges = len(set(combination)) - diversity_counts[unique_ranges] += 1 - - for num_ranges in sorted(diversity_counts.keys()): - count = diversity_counts[num_ranges] - percentage = (count / len(df)) * 100 - print(f"{num_ranges} verschiedene Bereiche: {count:3} Kombinationen ({percentage:4.1f}%)") - - # Spezielle Muster - print(f"\n🔍 SPEZIELLE MUSTER (Z1-Z4):") - print("="*35) - - # Alle aus dem gleichen Bereich - same_range_count = sum(1 for combo in combinations_z1_z4 if len(set(combo)) == 1) - print(f"Alle 4 Zahlen aus gleichem Bereich: {same_range_count} ({(same_range_count/len(df)*100):.1f}%)") - - # Alle aus verschiedenen Bereichen (4 verschiedene) - all_different_count = sum(1 for combo in combinations_z1_z4 if len(set(combo)) == 4) - print(f"Alle 4 Zahlen aus verschiedenen Bereichen: {all_different_count} ({(all_different_count/len(df)*100):.1f}%)") - - # Benachbarte Bereiche-Analyse - print(f"\n🏠 BENACHBARTE BEREICHE-ANALYSE (Z1-Z4):") - print("="*40) - - adjacent_patterns = { - 'A+B': 0, # 1-10 + 11-20 - 'B+C': 0, # 11-20 + 21-30 - 'C+D': 0, # 21-30 + 31-40 - 'D+E': 0, # 31-40 + 41-50 - } - - for combination in combinations_z1_z4: - ranges_set = set(combination) - if 'A(1-10)' in ranges_set and 'B(11-20)' in ranges_set: - adjacent_patterns['A+B'] += 1 - if 'B(11-20)' in ranges_set and 'C(21-30)' in ranges_set: - adjacent_patterns['B+C'] += 1 - if 'C(21-30)' in ranges_set and 'D(31-40)' in ranges_set: - adjacent_patterns['C+D'] += 1 - if 'D(31-40)' in ranges_set and 'E(41-50)' in ranges_set: - adjacent_patterns['D+E'] += 1 - - for pattern, count in adjacent_patterns.items(): - percentage = (count / len(df)) * 100 - print(f"Benachbarte Bereiche {pattern}: {count:3} Kombinationen ({percentage:4.1f}%)") - - # Export der Ergebnisse - print(f"\n💾 EXPORT DER ERGEBNISSE:") - print("="*30) - - # DataFrame für Z1-Z4 Kombinationen erstellen - results_data = [] - for i, row in df.iterrows(): - ranges_z1_z4 = [get_range_for_number(row[col]) for col in z_columns_z1_z4] - pattern = '|'.join(sorted(ranges_z1_z4)) - diversity = len(set(ranges_z1_z4)) - - results_data.append({ - 'datum': row['datum'], - 'Z1': row['Z1'], - 'Z2': row['Z2'], - 'Z3': row['Z3'], - 'Z4': row['Z4'], - 'Z1_bereich': ranges_z1_z4[0], - 'Z2_bereich': ranges_z1_z4[1], - 'Z3_bereich': ranges_z1_z4[2], - 'Z4_bereich': ranges_z1_z4[3], - 'bereichsmuster': pattern, - 'anzahl_bereiche': diversity - }) - - results_df = pd.DataFrame(results_data) - output_file = "/Users/sebastianfrohlich/Library/Mobile Documents/com~apple~CloudDocs/Jupyter Notebooks/Eurojackpot/bereichskombinationen_z1_z4.csv" - results_df.to_csv(output_file, sep=';', index=False) - print(f"✅ Detailergebnisse gespeichert: bereichskombinationen_z1_z4.csv") - - return pattern_counts_z1_z4, pattern_counts_all - -if __name__ == "__main__": - analyze_range_combinations() diff --git a/scripts/analysis/eurojackpot_bereichsanalyse.py b/scripts/analysis/eurojackpot_bereichsanalyse.py deleted file mode 100644 index d3dbc14..0000000 --- a/scripts/analysis/eurojackpot_bereichsanalyse.py +++ /dev/null @@ -1,217 +0,0 @@ -#!/usr/bin/env python3 -""" -Eurojackpot Bereichsanalyse - -Analysiert, in welchen Zahlenbereichen am häufigsten Zahlen gezogen wurden. -""" - -import pandas as pd -import matplotlib.pyplot as plt -import seaborn as sns -import numpy as np -from collections import Counter - -def load_drawn_numbers(filepath): - """Lädt die gezogenen Eurojackpot-Zahlen.""" - try: - df = pd.read_csv(filepath, sep=';') - print(f"Gezogene Zahlen geladen: {len(df)} Ziehungen") - print(f"Spalten: {list(df.columns)}") - return df - except Exception as e: - print(f"Fehler beim Laden: {e}") - return None - -def analyze_number_ranges(df): - """Analysiert die Häufigkeit von Zahlen in verschiedenen Bereichen.""" - - # Alle gezogenen Zahlen sammeln (Z1-Z5) - all_numbers = [] - for col in ['Z1', 'Z2', 'Z3', 'Z4', 'Z5']: - all_numbers.extend(df[col].tolist()) - - print(f"Gesamtanzahl gezogene Zahlen: {len(all_numbers)}") - - # Häufigkeit jeder Zahl - number_counts = Counter(all_numbers) - - # Bereiche definieren - ranges = { - '1-10': (1, 10), - '11-20': (11, 20), - '21-30': (21, 30), - '31-40': (31, 40), - '41-50': (41, 50) - } - - # Analyse pro Bereich - range_analysis = {} - - for range_name, (start, end) in ranges.items(): - numbers_in_range = [num for num in all_numbers if start <= num <= end] - - range_analysis[range_name] = { - 'anzahl_ziehungen': len(numbers_in_range), - 'prozent': (len(numbers_in_range) / len(all_numbers)) * 100, - 'haeufigste_zahl': max(number_counts.items(), - key=lambda x: x[1] if start <= x[0] <= end else 0), - 'durchschnitt': np.mean(numbers_in_range) if numbers_in_range else 0, - 'zahlen_im_bereich': sorted(set(numbers_in_range)) - } - - return range_analysis, number_counts - -def create_visualizations(range_analysis, number_counts, output_dir): - """Erstellt Visualisierungen der Analyse.""" - - # 1. Balkendiagramm: Häufigkeit pro Bereich - plt.figure(figsize=(12, 8)) - - ranges = list(range_analysis.keys()) - counts = [range_analysis[r]['anzahl_ziehungen'] for r in ranges] - percentages = [range_analysis[r]['prozent'] for r in ranges] - - plt.subplot(2, 2, 1) - bars = plt.bar(ranges, counts, color=['#FF6B6B', '#4ECDC4', '#45B7D1', '#96CEB4', '#FECA57']) - plt.title('Anzahl gezogener Zahlen pro Bereich', fontsize=14, fontweight='bold') - plt.ylabel('Anzahl Ziehungen') - plt.xticks(rotation=45) - - # Prozente auf Balken anzeigen - for bar, pct in zip(bars, percentages): - plt.text(bar.get_x() + bar.get_width()/2, bar.get_height() + 5, - f'{pct:.1f}%', ha='center', va='bottom', fontweight='bold') - - # 2. Heatmap: Häufigkeit einzelner Zahlen - plt.subplot(2, 2, 2) - numbers = list(range(1, 51)) - frequencies = [number_counts.get(num, 0) for num in numbers] - - # Als 5x10 Matrix darstellen - freq_matrix = np.array(frequencies).reshape(5, 10) - - sns.heatmap(freq_matrix, annot=True, fmt='d', cmap='YlOrRd', - xticklabels=list(range(1, 11)), - yticklabels=[f'{i*10+1}-{(i+1)*10}' for i in range(5)]) - plt.title('Häufigkeit einzelner Zahlen', fontsize=14, fontweight='bold') - - # 3. Liniendiagramm: Häufigkeit aller Zahlen - plt.subplot(2, 2, 3) - plt.plot(numbers, frequencies, marker='o', linewidth=2, markersize=4) - plt.title('Häufigkeitsverteilung aller Zahlen (1-50)', fontsize=14, fontweight='bold') - plt.xlabel('Zahl') - plt.ylabel('Häufigkeit') - plt.grid(True, alpha=0.3) - - # Bereiche farblich markieren - colors = ['#FF6B6B', '#4ECDC4', '#45B7D1', '#96CEB4', '#FECA57'] - for i, (range_name, color) in enumerate(zip(range_analysis.keys(), colors)): - start = i * 10 + 1 - end = (i + 1) * 10 - plt.axvspan(start, end, alpha=0.2, color=color, label=range_name) - - plt.legend() - - # 4. Pie Chart: Prozentuale Verteilung - plt.subplot(2, 2, 4) - plt.pie(percentages, labels=ranges, autopct='%1.1f%%', - colors=['#FF6B6B', '#4ECDC4', '#45B7D1', '#96CEB4', '#FECA57'], - startangle=90) - plt.title('Prozentuale Verteilung nach Bereichen', fontsize=14, fontweight='bold') - - plt.tight_layout() - plt.savefig(f'{output_dir}/eurojackpot_bereichsanalyse.png', dpi=300, bbox_inches='tight') - plt.show() - -def print_detailed_analysis(range_analysis, number_counts): - """Gibt detaillierte Analyseergebnisse aus.""" - - print("\n" + "="*60) - print("🎯 EUROJACKPOT BEREICHSANALYSE") - print("="*60) - - total_numbers = sum(analysis['anzahl_ziehungen'] for analysis in range_analysis.values()) - - for range_name, analysis in range_analysis.items(): - print(f"\n📊 BEREICH {range_name}:") - print(f" Anzahl Ziehungen: {analysis['anzahl_ziehungen']:,}") - print(f" Prozentanteil: {analysis['prozent']:.2f}%") - print(f" Durchschnittswert: {analysis['durchschnitt']:.1f}") - - # Top 3 Zahlen in diesem Bereich - start, end = map(int, range_name.split('-')) - range_numbers = [(num, count) for num, count in number_counts.items() - if start <= num <= end] - range_numbers.sort(key=lambda x: x[1], reverse=True) - - print(f" Top 3 Zahlen: ", end="") - for i, (num, count) in enumerate(range_numbers[:3]): - print(f"{num} ({count}x)", end="") - if i < 2 and i < len(range_numbers) - 1: - print(", ", end="") - print() - - # Allgemeine Statistiken - print(f"\n📈 ALLGEMEINE STATISTIKEN:") - print(f" Gesamte gezogene Zahlen: {total_numbers:,}") - print(f" Durchschnitt pro Bereich: {total_numbers/5:.1f}") - - # Häufigste und seltenste Zahlen insgesamt - most_common = number_counts.most_common(5) - least_common = number_counts.most_common()[-5:] - - print(f"\n🔥 HÄUFIGSTE ZAHLEN GESAMT:") - for i, (num, count) in enumerate(most_common, 1): - print(f" {i}. Zahl {num}: {count} mal gezogen") - - print(f"\n❄️ SELTENSTE ZAHLEN GESAMT:") - for i, (num, count) in enumerate(reversed(least_common), 1): - print(f" {i}. Zahl {num}: {count} mal gezogen") - - # Empfehlungen - print(f"\n💡 ERKENNTNISSE:") - best_range = max(range_analysis.keys(), key=lambda x: range_analysis[x]['prozent']) - worst_range = min(range_analysis.keys(), key=lambda x: range_analysis[x]['prozent']) - - print(f" • Bester Bereich: {best_range} ({range_analysis[best_range]['prozent']:.1f}%)") - print(f" • Schwächster Bereich: {worst_range} ({range_analysis[worst_range]['prozent']:.1f}%)") - print(f" • Unterschied: {range_analysis[best_range]['prozent'] - range_analysis[worst_range]['prozent']:.1f} Prozentpunkte") - -def main(): - """Hauptfunktion.""" - - # Pfade - input_file = "/Users/sebastianfrohlich/Library/Mobile Documents/com~apple~CloudDocs/Jupyter Notebooks/Eurojackpot/data/AlleEurojackpotzahlen.csv" - output_dir = "/Users/sebastianfrohlich/Library/Mobile Documents/com~apple~CloudDocs/Jupyter Notebooks/Eurojackpot" - - # Daten laden - print("🔄 Lade Eurojackpot-Daten...") - df = load_drawn_numbers(input_file) - - if df is None: - print("❌ Fehler beim Laden der Daten!") - return - - # Analyse durchführen - print("\n🔍 Führe Bereichsanalyse durch...") - range_analysis, number_counts = analyze_number_ranges(df) - - # Ergebnisse ausgeben - print_detailed_analysis(range_analysis, number_counts) - - # Visualisierungen erstellen - print(f"\n📊 Erstelle Visualisierungen...") - try: - create_visualizations(range_analysis, number_counts, output_dir) - print(f"✅ Diagramm gespeichert: {output_dir}/eurojackpot_bereichsanalyse.png") - except Exception as e: - print(f"⚠️ Visualisierung konnte nicht erstellt werden: {e}") - print("💡 Installieren Sie matplotlib und seaborn: pip install matplotlib seaborn") - - # CSV-Export der Analyse - results_df = pd.DataFrame.from_dict(range_analysis, orient='index') - results_df.to_csv(f'{output_dir}/bereichsanalyse_ergebnisse.csv', sep=';') - print(f"✅ Ergebnisse gespeichert: {output_dir}/bereichsanalyse_ergebnisse.csv") - -if __name__ == "__main__": - main() diff --git a/scripts/analysis/positionsanalyse.py b/scripts/analysis/positionsanalyse.py deleted file mode 100644 index 463ff77..0000000 --- a/scripts/analysis/positionsanalyse.py +++ /dev/null @@ -1,208 +0,0 @@ -#!/usr/bin/env python3 -""" -Eurojackpot Positionsanalyse - -Analysiert, welche Bereiche an welchen Positionen (Z1, Z2, Z3, Z4, Z5) am häufigsten stehen. -""" - -import pandas as pd -from collections import defaultdict -import numpy as np - -def get_range_for_number(number): - """Bestimmt den Bereich für eine gegebene Zahl.""" - if 1 <= number <= 10: - return 'A(1-10)' - elif 11 <= number <= 20: - return 'B(11-20)' - elif 21 <= number <= 30: - return 'C(21-30)' - elif 31 <= number <= 40: - return 'D(31-40)' - elif 41 <= number <= 50: - return 'E(41-50)' - else: - return 'Unknown' - -def analyze_positions(): - """Führt eine detaillierte Positionsanalyse durch.""" - - # Daten laden - df = pd.read_csv("/Users/sebastianfrohlich/Library/Mobile Documents/com~apple~CloudDocs/Jupyter Notebooks/Eurojackpot/data/AlleEurojackpotzahlen.csv", sep=';') - - print(f"🎯 EUROJACKPOT POSITIONSANALYSE") - print(f"Anzahl analysierte Ziehungen: {len(df)}") - print("="*60) - - # Positionen definieren - positions = ['Z1', 'Z2', 'Z3', 'Z4', 'Z5'] - ranges = ['A(1-10)', 'B(11-20)', 'C(21-30)', 'D(31-40)', 'E(41-50)'] - - # Matrix für Positions-Bereich-Kombinationen - position_range_matrix = defaultdict(lambda: defaultdict(int)) - - # Daten sammeln - for _, row in df.iterrows(): - for pos in positions: - range_name = get_range_for_number(row[pos]) - position_range_matrix[pos][range_name] += 1 - - # 1. Übersichtstabelle erstellen - print(f"\n📊 POSITIONS-BEREICH-MATRIX:") - print("="*60) - print(f"{'Position':<8} {'A(1-10)':<12} {'B(11-20)':<12} {'C(21-30)':<12} {'D(31-40)':<12} {'E(41-50)':<12}") - print("-" * 60) - - for pos in positions: - line = f"{pos:<8} " - for range_name in ranges: - count = position_range_matrix[pos][range_name] - percentage = (count / len(df)) * 100 - line += f"{count:3}({percentage:4.1f}%) " - print(line) - - # 2. Beste Bereiche pro Position - print(f"\n🏆 BESTE BEREICHE PRO POSITION:") - print("="*40) - - for pos in positions: - best_range = max(ranges, key=lambda r: position_range_matrix[pos][r]) - best_count = position_range_matrix[pos][best_range] - best_percentage = (best_count / len(df)) * 100 - - # Alle Bereiche für diese Position sortiert - sorted_ranges = sorted(ranges, key=lambda r: position_range_matrix[pos][r], reverse=True) - - print(f"\n{pos}: {best_range} führt mit {best_count} ({best_percentage:.1f}%)") - print(f" Ranking: ", end="") - for i, range_name in enumerate(sorted_ranges, 1): - count = position_range_matrix[pos][range_name] - percentage = (count / len(df)) * 100 - print(f"{i}.{range_name}({percentage:.1f}%)", end="") - if i < len(sorted_ranges): - print(" > ", end="") - print() - - # 3. Beste Positionen pro Bereich - print(f"\n🎯 BESTE POSITIONEN PRO BEREICH:") - print("="*40) - - for range_name in ranges: - best_position = max(positions, key=lambda p: position_range_matrix[p][range_name]) - best_count = position_range_matrix[best_position][range_name] - best_percentage = (best_count / len(df)) * 100 - - # Alle Positionen für diesen Bereich sortiert - sorted_positions = sorted(positions, key=lambda p: position_range_matrix[p][range_name], reverse=True) - - print(f"\n{range_name}: Position {best_position} führt mit {best_count} ({best_percentage:.1f}%)") - print(f" Ranking: ", end="") - for i, pos in enumerate(sorted_positions, 1): - count = position_range_matrix[pos][range_name] - percentage = (count / len(df)) * 100 - print(f"{i}.{pos}({percentage:.1f}%)", end="") - if i < len(sorted_positions): - print(" > ", end="") - print() - - # 4. Spezielle Analysen - print(f"\n📈 SPEZIELLE POSITIONSANALYSEN:") - print("="*45) - - # Niedrige vs. hohe Bereiche pro Position - for pos in positions: - low_ranges = position_range_matrix[pos]['A(1-10)'] + position_range_matrix[pos]['B(11-20)'] - high_ranges = position_range_matrix[pos]['D(31-40)'] + position_range_matrix[pos]['E(41-50)'] - middle_range = position_range_matrix[pos]['C(21-30)'] - - low_pct = (low_ranges / len(df)) * 100 - high_pct = (high_ranges / len(df)) * 100 - middle_pct = (middle_range / len(df)) * 100 - - print(f"{pos}: Niedrig(A+B)={low_pct:4.1f}% | Mitte(C)={middle_pct:4.1f}% | Hoch(D+E)={high_pct:4.1f}%") - - # 5. Gleichverteilungs-Analyse - print(f"\n⚖️ GLEICHVERTEILUNGS-ANALYSE:") - print("="*35) - - expected_per_range = len(df) / 5 # Erwartete Gleichverteilung - - print(f"Erwartete Gleichverteilung pro Bereich und Position: {expected_per_range:.1f}") - print(f"\nAbweichungen von der Gleichverteilung:") - - for pos in positions: - print(f"\n{pos}:") - for range_name in ranges: - actual = position_range_matrix[pos][range_name] - deviation = actual - expected_per_range - deviation_pct = (deviation / expected_per_range) * 100 - - symbol = "📈" if deviation > 0 else "📉" if deviation < 0 else "⚖️" - print(f" {range_name}: {actual:3} ({deviation:+4.1f}, {deviation_pct:+5.1f}%) {symbol}") - - # 6. Heatmap-Daten für Export - print(f"\n💾 DATENEXPORT:") - print("="*20) - - # Erstelle eine Matrix für bessere Visualisierung - matrix_data = [] - for pos in positions: - row_data = {'Position': pos} - for range_name in ranges: - count = position_range_matrix[pos][range_name] - percentage = (count / len(df)) * 100 - row_data[range_name] = count - row_data[f"{range_name}_Prozent"] = percentage - matrix_data.append(row_data) - - matrix_df = pd.DataFrame(matrix_data) - - # Zusätzliche Statistiken hinzufügen - stats_data = [] - for _, row in df.iterrows(): - row_data = {'datum': row['datum']} - for pos in positions: - row_data[f"{pos}_Zahl"] = row[pos] - row_data[f"{pos}_Bereich"] = get_range_for_number(row[pos]) - stats_data.append(row_data) - - stats_df = pd.DataFrame(stats_data) - - # Export - matrix_output = "/Users/sebastianfrohlich/Library/Mobile Documents/com~apple~CloudDocs/Jupyter Notebooks/Eurojackpot/positions_matrix.csv" - stats_output = "/Users/sebastianfrohlich/Library/Mobile Documents/com~apple~CloudDocs/Jupyter Notebooks/Eurojackpot/positions_details.csv" - - matrix_df.to_csv(matrix_output, sep=';', index=False) - stats_df.to_csv(stats_output, sep=';', index=False) - - print(f"✅ Positionsmatrix gespeichert: positions_matrix.csv") - print(f"✅ Detaildaten gespeichert: positions_details.csv") - - # 7. Strategische Empfehlungen - print(f"\n💡 STRATEGISCHE EMPFEHLUNGEN:") - print("="*35) - - # Finde die besten Kombinationen pro Position - recommendations = {} - for pos in positions: - best_range = max(ranges, key=lambda r: position_range_matrix[pos][r]) - recommendations[pos] = best_range - - print(f"Optimale Bereichsauswahl pro Position:") - for pos, best_range in recommendations.items(): - count = position_range_matrix[pos][best_range] - percentage = (count / len(df)) * 100 - print(f" {pos}: {best_range} ({percentage:.1f}%)") - - # Berechne theoretische Erfolgswahrscheinlichkeit - theoretical_success = 1.0 - for pos, best_range in recommendations.items(): - prob = position_range_matrix[pos][best_range] / len(df) - theoretical_success *= prob - - print(f"\nTheoretische Erfolgswahrscheinlichkeit dieser Kombination: {theoretical_success*100:.4f}%") - - return position_range_matrix, matrix_df - -if __name__ == "__main__": - analyze_positions() diff --git a/scripts/analysis/simple_bereichsanalyse.py b/scripts/analysis/simple_bereichsanalyse.py deleted file mode 100644 index 65f4894..0000000 --- a/scripts/analysis/simple_bereichsanalyse.py +++ /dev/null @@ -1,54 +0,0 @@ -#!/usr/bin/env python3 -""" -Einfache Eurojackpot Bereichsanalyse -""" - -import pandas as pd -from collections import Counter - -def analyze_ranges(): - """Analysiert Zahlenbereiche in Eurojackpot-Daten.""" - - # Daten laden - df = pd.read_csv("/Users/sebastianfrohlich/Library/Mobile Documents/com~apple~CloudDocs/Jupyter Notebooks/Eurojackpot/data/AlleEurojackpotzahlen.csv", sep=';') - - print(f"Anzahl Ziehungen: {len(df)}") - - # Alle Zahlen sammeln - all_numbers = [] - for col in ['Z1', 'Z2', 'Z3', 'Z4', 'Z5']: - all_numbers.extend(df[col].tolist()) - - # Bereiche definieren - ranges = { - '1-10': list(range(1, 11)), - '11-20': list(range(11, 21)), - '21-30': list(range(21, 31)), - '31-40': list(range(31, 41)), - '41-50': list(range(41, 51)) - } - - print(f"\nGesamt gezogene Zahlen: {len(all_numbers)}") - print("="*50) - - # Analyse pro Bereich - for range_name, range_numbers in ranges.items(): - count = sum(1 for num in all_numbers if num in range_numbers) - percentage = (count / len(all_numbers)) * 100 - - print(f"{range_name:6}: {count:4} Zahlen ({percentage:5.1f}%)") - - print("="*50) - - # Häufigste Zahlen - number_counts = Counter(all_numbers) - print("\nHäufigste 10 Zahlen:") - for num, count in number_counts.most_common(10): - print(f"Zahl {num:2}: {count:3} mal") - - print("\nSeltenste 10 Zahlen:") - for num, count in number_counts.most_common()[-10:]: - print(f"Zahl {num:2}: {count:3} mal") - -if __name__ == "__main__": - analyze_ranges() diff --git a/scripts/analysis/treffer_analyse_umschluesselt.py b/scripts/analysis/treffer_analyse_umschluesselt.py deleted file mode 100644 index 32dcfd8..0000000 --- a/scripts/analysis/treffer_analyse_umschluesselt.py +++ /dev/null @@ -1,270 +0,0 @@ -#!/usr/bin/env python3 -""" -Eurojackpot Treffer-Analyse (umschlüsselte Werte) - -Analysiert, wo die größten Treffer-Wahrscheinlichkeiten bei den umschlüsselten Werten liegen. -""" - -import pandas as pd -from collections import Counter, defaultdict -import numpy as np - -def analyze_hit_probabilities(): - """Analysiert die Treffer-Wahrscheinlichkeiten der umschlüsselten Werte.""" - - # Umschlüsselte Daten laden - df = pd.read_csv("/Users/sebastianfrohlich/Library/Mobile Documents/com~apple~CloudDocs/Jupyter Notebooks/Eurojackpot/AlleEurojackpotzahlen_umschluesselt.csv", sep=';') - - print("🎯 TREFFER-ANALYSE UMSCHLÜSSELTE WERTE (1-10)") - print("="*60) - print(f"Analysierte Ziehungen: {len(df)}") - - # 1. Einzelne Gruppen-Wahrscheinlichkeiten pro Position - print(f"\n🏆 HÖCHSTE TREFFER-WAHRSCHEINLICHKEITEN PRO POSITION:") - print("="*55) - - positions = ['z1', 'z2', 'z3', 'z4', 'z5'] - position_stats = {} - - for pos in positions: - group_counts = Counter(df[pos]) - total = len(df) - - # Beste Gruppe für diese Position - best_group = max(group_counts, key=group_counts.get) - best_count = group_counts[best_group] - best_probability = (best_count / total) * 100 - - position_stats[pos] = { - 'best_group': best_group, - 'probability': best_probability, - 'count': best_count, - 'all_groups': group_counts - } - - print(f"\n{pos.upper()}: Gruppe {best_group} führt mit {best_probability:.1f}% ({best_count}/{total})") - - # Top 3 für diese Position - top_3 = group_counts.most_common(3) - print(f" Top 3: ", end="") - for i, (group, count) in enumerate(top_3): - prob = (count / total) * 100 - print(f"{i+1}.Gruppe {group}({prob:.1f}%)", end="") - if i < 2: - print(" > ", end="") - print() - - # 2. Beste Gesamtkombination - print(f"\n🔥 OPTIMAL-KOMBINATION (höchste Einzelwahrscheinlichkeiten):") - print("="*60) - - optimal_combination = [] - total_probability = 1.0 - - for pos in positions: - best_group = position_stats[pos]['best_group'] - probability = position_stats[pos]['probability'] / 100 - optimal_combination.append(best_group) - total_probability *= probability - - print(f"{pos}: Gruppe {best_group} ({position_stats[pos]['probability']:.1f}%)") - - optimal_string = '-'.join(map(str, optimal_combination)) - print(f"\nOptimal-Kombination: {optimal_string}") - print(f"Theoretische Wahrscheinlichkeit: {total_probability*100:.6f}%") - print(f"Das entspricht etwa 1 in {1/total_probability:,.0f} Ziehungen") - - # 3. Tatsächlich aufgetretene häufigste Kombinationen - print(f"\n📊 REAL AUFGETRETENE HÄUFIGSTE KOMBINATIONEN:") - print("="*50) - - combination_counts = Counter(df['kombination_umschluesselt']) - - print(f"Top 20 real aufgetretene Kombinationen:") - for i, (combination, count) in enumerate(combination_counts.most_common(20), 1): - probability = (count / len(df)) * 100 - print(f"{i:2}. {combination:15} {count}x ({probability:.2f}%)") - - # 4. Bereichs-Kombinationen mit höchster Wahrscheinlichkeit - print(f"\n🎲 BEREICHS-KOMBINATIONEN MIT HÖCHSTER WAHRSCHEINLICHKEIT:") - print("="*60) - - # Niedrig (1-3), Mittel (4-7), Hoch (8-10) Kombinationen - range_combinations = defaultdict(int) - - for _, row in df.iterrows(): - ranges = [] - for pos in positions: - val = row[pos] - if 1 <= val <= 3: - ranges.append('N') # Niedrig - elif 4 <= val <= 7: - ranges.append('M') # Mittel - else: - ranges.append('H') # Hoch - - range_pattern = ''.join(ranges) - range_combinations[range_pattern] += 1 - - print(f"Häufigste Bereichsmuster (N=Niedrig1-3, M=Mittel4-7, H=Hoch8-10):") - sorted_patterns = sorted(range_combinations.items(), key=lambda x: x[1], reverse=True) - - for i, (pattern, count) in enumerate(sorted_patterns[:15], 1): - probability = (count / len(df)) * 100 - pattern_readable = pattern.replace('N', 'Niedrig').replace('M', 'Mittel').replace('H', 'Hoch') - print(f"{i:2}. {pattern:5} ({pattern_readable:25}) {count:3}x ({probability:5.1f}%)") - - # 5. Positions-spezifische Empfehlungen - print(f"\n💡 POSITIONS-SPEZIFISCHE EMPFEHLUNGEN:") - print("="*45) - - recommendations = {} - - for pos in positions: - group_counts = position_stats[pos]['all_groups'] - total = len(df) - - # Top 3 Gruppen für maximale Abdeckung - top_groups = [group for group, count in group_counts.most_common(3)] - top_coverage = sum(group_counts[group] for group in top_groups) - coverage_percentage = (top_coverage / total) * 100 - - recommendations[pos] = { - 'top_groups': top_groups, - 'coverage': coverage_percentage - } - - print(f"\n{pos.upper()}: Empfohlene Gruppen {top_groups}") - print(f" Abdeckung: {coverage_percentage:.1f}% aller Ziehungen") - - # Wahrscheinlichkeitsverteilung - print(f" Verteilung: ", end="") - for group in top_groups: - prob = (group_counts[group] / total) * 100 - print(f"Gruppe {group}({prob:.1f}%)", end="") - if group != top_groups[-1]: - print(", ", end="") - print() - - # 6. Strategische Kombinationen - print(f"\n🎯 STRATEGISCHE KOMBINATIONEN FÜR MAXIMALE TREFFER:") - print("="*55) - - # Berechne verschiedene Strategien - strategies = { - 'Konservativ': { - 'z1': [1, 2], # Top 2 der Position z1 - 'z2': [3, 4], # Top 2 der Position z2 - 'z3': [5, 6], # Top 2 der Position z3 - 'z4': [7, 8], # Top 2 der Position z4 - 'z5': [9, 10] # Top 2 der Position z5 - }, - 'Ausgewogen': { - 'z1': [1, 2, 3], # Top 3 jeder Position - 'z2': [3, 4, 5], - 'z3': [4, 5, 6, 7], - 'z4': [6, 7, 8], - 'z5': [8, 9, 10] - }, - 'Optimal': {} # Wird basierend auf tatsächlichen Daten gefüllt - } - - # Optimal-Strategie basierend auf echten Top-3 pro Position - for pos in positions: - top_3_groups = recommendations[pos]['top_groups'] - strategies['Optimal'][pos] = top_3_groups - - for strategy_name, strategy in strategies.items(): - if strategy: # Nur wenn Strategie gefüllt ist - print(f"\n{strategy_name}-Strategie:") - total_combinations = 1 - coverage_per_position = [] - - for pos in positions: - recommended_groups = strategy[pos] - pos_stats = position_stats[pos]['all_groups'] - total_pos = len(df) - - # Abdeckung dieser Gruppen - coverage = sum(pos_stats.get(group, 0) for group in recommended_groups) - coverage_pct = (coverage / total_pos) * 100 - coverage_per_position.append(coverage_pct) - - total_combinations *= len(recommended_groups) - - print(f" {pos}: Gruppen {recommended_groups} ({coverage_pct:.1f}% Abdeckung)") - - avg_coverage = np.mean(coverage_per_position) - print(f" Durchschnittliche Abdeckung: {avg_coverage:.1f}%") - print(f" Mögliche Kombinationen: {total_combinations:,}") - - # 7. Heiße und kalte Zahlen - print(f"\n🔥❄️ HEISSE UND KALTE GRUPPEN:") - print("="*35) - - # Alle Gruppen über alle Positionen sammeln - all_groups = [] - for pos in positions: - all_groups.extend(df[pos].tolist()) - - group_total_counts = Counter(all_groups) - total_appearances = len(all_groups) - expected_per_group = total_appearances / 10 # 10 Gruppen - - print(f"Erwartete Häufigkeit pro Gruppe: {expected_per_group:.1f}") - print(f"\nHeisse Gruppen (über Erwartung):") - hot_groups = [] - for group in range(1, 11): - actual = group_total_counts.get(group, 0) - deviation = actual - expected_per_group - if deviation > 0: - hot_groups.append((group, actual, deviation)) - - hot_groups.sort(key=lambda x: x[2], reverse=True) - for group, count, deviation in hot_groups: - percentage = (count / total_appearances) * 100 - print(f" Gruppe {group}: {count} (+{deviation:.1f}, {percentage:.1f}%)") - - print(f"\nKalte Gruppen (unter Erwartung):") - cold_groups = [] - for group in range(1, 11): - actual = group_total_counts.get(group, 0) - deviation = actual - expected_per_group - if deviation < 0: - cold_groups.append((group, actual, deviation)) - - cold_groups.sort(key=lambda x: x[2]) - for group, count, deviation in cold_groups: - percentage = (count / total_appearances) * 100 - print(f" Gruppe {group}: {count} ({deviation:.1f}, {percentage:.1f}%)") - - # 8. Export der Empfehlungen - print(f"\n💾 EMPFEHLUNGEN EXPORT:") - print("="*25) - - # Erstelle Empfehlungs-DataFrame - recommendation_data = [] - - # Für jede Position die besten Empfehlungen - for pos in positions: - pos_recommendations = recommendations[pos] - for group in pos_recommendations['top_groups']: - prob = (position_stats[pos]['all_groups'][group] / len(df)) * 100 - recommendation_data.append({ - 'position': pos, - 'gruppe': group, - 'wahrscheinlichkeit_prozent': prob, - 'anzahl_auftreten': position_stats[pos]['all_groups'][group], - 'empfehlung_rang': pos_recommendations['top_groups'].index(group) + 1 - }) - - rec_df = pd.DataFrame(recommendation_data) - output_file = "/Users/sebastianfrohlich/Library/Mobile Documents/com~apple~CloudDocs/Jupyter Notebooks/Eurojackpot/treffer_empfehlungen_umschluesselt.csv" - rec_df.to_csv(output_file, sep=';', index=False) - - print(f"✅ Empfehlungen gespeichert: treffer_empfehlungen_umschluesselt.csv") - - return position_stats, recommendations - -if __name__ == "__main__": - analyze_hit_probabilities() diff --git a/scripts/generators/eurojackpot_generator.py b/scripts/generators/eurojackpot_generator.py deleted file mode 100644 index 2523004..0000000 --- a/scripts/generators/eurojackpot_generator.py +++ /dev/null @@ -1,141 +0,0 @@ -import csv -from itertools import combinations -import time - -print("=== EUROJACKPOT KOMBINATIONS-GENERATOR ===") -print("Erstellt alle möglichen Kombinationen mit Status (gezogen/nicht gezogen)") -print() - -# Pfade -eurojackpot_file = '/Users/sebastianfrohlich/Downloads/EJ_ab_2018.csv' -output_file = '/Users/sebastianfrohlich/Desktop/Alle_Eurojackpot_Kombinationen_mit_Status.csv' -missing_file = '/Users/sebastianfrohlich/Desktop/Fehlende_Eurojackpot_Kombinationen.csv' - -# Schritt 1: Einlesen der gezogenen Kombinationen -print("Schritt 1: Lade gezogene Eurojackpot-Kombinationen...") -existing_combinations = set() - -try: - with open(eurojackpot_file, 'r', encoding='utf-8') as file: - lines = file.readlines() - - for line in lines[1:]: # Header überspringen - parts = line.strip().split(';') - if len(parts) >= 6: # Mindestens Datum + 5 Zahlen - try: - numbers = [] - for i in range(1, 6): # Spalten 1-5 (nach Datum) - if i < len(parts) and parts[i].strip().isdigit(): - numbers.append(int(parts[i].strip())) - - if len(numbers) == 5: # Vollständige Kombination - combo = frozenset(numbers) - existing_combinations.add(combo) - - except (ValueError, IndexError): - continue - - print(f" ✓ {len(existing_combinations)} gezogene Kombinationen geladen") - - # Beispiele anzeigen - if existing_combinations: - print(" Beispiele:") - for i, combo in enumerate(list(existing_combinations)[:3]): - sorted_combo = sorted(list(combo)) - print(f" {sorted_combo}") - if len(existing_combinations) > 3: - print(f" ... und {len(existing_combinations)-3} weitere") - -except FileNotFoundError: - print(f" ⚠️ Datei nicht gefunden: {eurojackpot_file}") - existing_combinations = set() -except Exception as e: - print(f" ⚠️ Fehler beim Lesen: {e}") - existing_combinations = set() - -print() - -# Schritt 2: Generierung aller möglichen Kombinationen -print("Schritt 2: Generiere alle möglichen Kombinationen (5 aus 50)...") -total_combinations = 2118760 # C(50,5) -print(f" Gesamtanzahl zu verarbeitender Kombinationen: {total_combinations:,}") - -all_combinations = [] -count = 0 -start_time = time.time() - -for combo in combinations(range(1, 51), 5): - count += 1 - - # Fortschritt anzeigen - if count % 100000 == 0: - elapsed = time.time() - start_time - rate = count / elapsed if elapsed > 0 else 0 - remaining = (total_combinations - count) / rate if rate > 0 else 0 - print(f" Fortschritt: {count:,} / {total_combinations:,} " - f"({count/total_combinations*100:.1f}%) " - f"- {rate:,.0f}/s - noch ~{remaining/60:.1f} min") - - # Prüfen ob Kombination bereits gezogen wurde - sorted_combo = sorted(combo) - is_drawn = 1 if frozenset(combo) in existing_combinations else 0 - - # Zur Liste hinzufügen (Z1, Z2, Z3, Z4, Z5, gezogen) - combination_row = sorted_combo + [is_drawn] - all_combinations.append(combination_row) - -print(f" ✓ Alle {len(all_combinations):,} Kombinationen generiert") -print() - -# Schritt 3: Statistiken berechnen -print("Schritt 3: Berechne Statistiken...") -drawn_combinations = sum(1 for combo in all_combinations if combo[5] == 1) -undrawn_combinations = len(all_combinations) - drawn_combinations - -print(f" Gesamt mögliche Kombinationen: {len(all_combinations):,}") -print(f" Bereits gezogene Kombinationen: {drawn_combinations:,}") -print(f" Noch nicht gezogene Kombinationen: {undrawn_combinations:,}") -if len(all_combinations) > 0: - percentage = drawn_combinations / len(all_combinations) * 100 - print(f" Anteil gezogener Kombinationen: {percentage:.6f}%") -print() - -# Schritt 4: Hauptdatei speichern -print("Schritt 4: Speichere Hauptdatei...") -try: - with open(output_file, 'w', newline='', encoding='utf-8') as outfile: - writer = csv.writer(outfile, delimiter=';') - writer.writerow(['Z1', 'Z2', 'Z3', 'Z4', 'Z5', 'gezogen']) # Header - for combo in all_combinations: - writer.writerow(combo) - print(f" ✓ Hauptdatei gespeichert: {output_file}") -except Exception as e: - print(f" ⚠️ Fehler beim Speichern der Hauptdatei: {e}") - -# Schritt 5: Datei mit fehlenden Kombinationen speichern -print("Schritt 5: Speichere Datei mit fehlenden Kombinationen...") -try: - missing_combinations = [combo[:5] for combo in all_combinations if combo[5] == 0] - with open(missing_file, 'w', newline='', encoding='utf-8') as outfile: - writer = csv.writer(outfile, delimiter=';') - writer.writerow(['Z1', 'Z2', 'Z3', 'Z4', 'Z5']) # Header - for combo in missing_combinations: - writer.writerow(combo) - print(f" ✓ Datei mit fehlenden Kombinationen gespeichert: {missing_file}") - print(f" ✓ {len(missing_combinations):,} fehlende Kombinationen") -except Exception as e: - print(f" ⚠️ Fehler beim Speichern der fehlenden Kombinationen: {e}") - -print() -print("=== FERTIG ===") -print("Erstellte Dateien:") -print(f"1. {output_file}") -print(f" - Alle {len(all_combinations):,} Kombinationen mit Status") -print(f"2. {missing_file}") -if 'missing_combinations' in locals(): - print(f" - {len(missing_combinations):,} noch nicht gezogene Kombinationen") -print() -print("Format der Hauptdatei:") -print("Z1;Z2;Z3;Z4;Z5;gezogen") -print("1;2;3;4;5;0") -print("...") diff --git a/scripts/generators/optimized_eurojackpot_generator.py b/scripts/generators/optimized_eurojackpot_generator.py deleted file mode 100644 index c4923cd..0000000 --- a/scripts/generators/optimized_eurojackpot_generator.py +++ /dev/null @@ -1,806 +0,0 @@ -#!/usr/bin/env python3 -""" -Ultimativer Eurojackpot Tipp-Generator mit Multi-Ziehungs-Trend-Analyse - -Kombiniert multiple Optimierungsstrategien: -- Historische Häufigkeitsanalyse -- Positionsbasierte Gewichtung -- Multi-Ziehungs-Trend-Analyse (NEU!) -- Zahlen-Momentum-Tracking -- Sequenzielle Abhängigkeiten -- Zyklische Muster-Erkennung -""" - -import pandas as pd -import random -import numpy as np -from itertools import combinations -from collections import Counter, defaultdict, deque -import datetime - -class UltimativerEurojackpotGenerator: - def __init__(self, data_path="/Users/sebastianfrohlich/Library/Mobile Documents/com~apple~CloudDocs/Jupyter Notebooks/AlleEurojackpotzahlen.csv"): - self.data_path = data_path - self.df = None - self.drawn_combinations = set() - - # Basis-Analyse (Original) - self.number_frequencies = Counter() - self.position_frequencies = defaultdict(Counter) - self.pattern_frequencies = Counter() - self.supernumber_frequencies = {'sz1': Counter(), 'sz2': Counter()} - self.number_distances = [] - - # Multi-Ziehungs-Trend-Analyse (NEU!) - self.number_sequences = defaultdict(list) - self.momentum_scores = {} - self.trend_predictions = {} - self.sequential_dependencies = defaultdict(lambda: defaultdict(int)) - self.cycle_patterns = {} - self.hot_numbers = [] - self.warm_numbers = [] - self.cold_numbers = [] - - # Initialisierung - self.load_and_analyze_all_data() - - def load_and_analyze_all_data(self): - """Lädt Daten und führt alle Analysen durch.""" - try: - self.df = pd.read_csv(self.data_path, sep=';') - - # Chronologische Sortierung für Trend-Analyse - if 'Datum' in self.df.columns: - self.df['Datum'] = pd.to_datetime(self.df['Datum'], format='%d.%m.%Y') - self.df = self.df.sort_values('Datum') - - print(f"🚀 ULTIMATIVER EUROJACKPOT GENERATOR") - print("=" * 60) - print(f"📊 Analysiere {len(self.df)} Ziehungen mit Multi-Trend-Analyse...") - - # Basis-Analysen durchführen - self._perform_basic_analysis() - - # Multi-Ziehungs-Trend-Analysen durchführen (NEU!) - self._perform_momentum_analysis() - self._perform_sequential_analysis() - self._perform_cycle_analysis() - self._generate_trend_predictions() - - print(f"✅ Komplette Analyse abgeschlossen!") - self._print_ultimate_analysis_summary() - - except Exception as e: - print(f"❌ Fehler beim Laden der Daten: {e}") - return False - - return True - - def _perform_basic_analysis(self): - """Führt die ursprünglichen Basis-Analysen durch.""" - for _, row in self.df.iterrows(): - # Gezogene Kombinationen - combo = tuple(sorted([row['Z1'], row['Z2'], row['Z3'], row['Z4'], row['Z5']])) - self.drawn_combinations.add(combo) - - # Zahlenfrequenzen - numbers = [row['Z1'], row['Z2'], row['Z3'], row['Z4'], row['Z5']] - for num in numbers: - self.number_frequencies[num] += 1 - - # Positionsfrequenzen - sorted_numbers = sorted(numbers) - for i, num in enumerate(sorted_numbers): - self.position_frequencies[f'pos_{i+1}'][num] += 1 - - # Muster analysieren - pattern = self._get_pattern(sorted_numbers) - self.pattern_frequencies[pattern] += 1 - - # Superzahlen - self.supernumber_frequencies['sz1'][row['SZ1']] += 1 - self.supernumber_frequencies['sz2'][row['SZ2']] += 1 - - # Zahlenabstände - distances = [sorted_numbers[i+1] - sorted_numbers[i] for i in range(4)] - self.number_distances.extend(distances) - - def _perform_momentum_analysis(self, window_size=15): - """Führt Multi-Ziehungs-Momentum-Analyse durch (NEU!)""" - print(f"\n🔥 MOMENTUM-ANALYSE (Fenster: {window_size})") - - # Zahlensequenzen über Zeit aufbauen - for number in range(1, 51): - sequence = [] - for _, row in self.df.iterrows(): - drawn_numbers = [row['Z1'], row['Z2'], row['Z3'], row['Z4'], row['Z5']] - sequence.append(1 if number in drawn_numbers else 0) - self.number_sequences[number] = sequence - - # Momentum-Scores berechnen - momentum_results = {} - for number in range(1, 51): - recent_sequence = self.number_sequences[number][-window_size:] - - hit_rate = sum(recent_sequence) / len(recent_sequence) - trend_score = self._calculate_trend_score(recent_sequence) - recency_score = self._calculate_recency_score(recent_sequence) - - # Kombinierter Momentum-Score mit Gewichtung - momentum_score = (hit_rate * 0.4) + (trend_score * 0.4) + (recency_score * 0.2) - - momentum_results[number] = { - 'hit_rate': hit_rate, - 'trend_score': trend_score, - 'recency_score': recency_score, - 'momentum_score': momentum_score, - 'status': self._get_momentum_status(momentum_score) - } - - self.momentum_scores = momentum_results - - # Zahlen in Kategorien einteilen - sorted_momentum = sorted(momentum_results.items(), - key=lambda x: x[1]['momentum_score'], reverse=True) - - self.hot_numbers = [num for num, data in sorted_momentum[:20] - if data['momentum_score'] > 0.35] - self.warm_numbers = [num for num, data in sorted_momentum[20:35] - if 0.2 <= data['momentum_score'] <= 0.35] - self.cold_numbers = [num for num, data in sorted_momentum[35:] - if data['momentum_score'] < 0.2][:15] - - print(f"🔥 {len(self.hot_numbers)} heiße Zahlen identifiziert") - print(f"🌡️ {len(self.warm_numbers)} warme Zahlen identifiziert") - print(f"🧊 {len(self.cold_numbers)} kalte Zahlen identifiziert") - - def _perform_sequential_analysis(self, look_back=3): - """Analysiert sequenzielle Abhängigkeiten zwischen Ziehungen (NEU!)""" - print(f"\n🔗 SEQUENZIELLE ABHÄNGIGKEITEN (Look-back: {look_back})") - - for i in range(look_back, len(self.df)): - current_numbers = set([self.df.iloc[i]['Z1'], self.df.iloc[i]['Z2'], - self.df.iloc[i]['Z3'], self.df.iloc[i]['Z4'], - self.df.iloc[i]['Z5']]) - - for j in range(1, look_back + 1): - prev_numbers = set([self.df.iloc[i-j]['Z1'], self.df.iloc[i-j]['Z2'], - self.df.iloc[i-j]['Z3'], self.df.iloc[i-j]['Z4'], - self.df.iloc[i-j]['Z5']]) - - for prev_num in prev_numbers: - for curr_num in current_numbers: - self.sequential_dependencies[f"lag_{j}"][f"{prev_num}_{curr_num}"] += 1 - - print(f"🔗 Sequenzielle Muster für {look_back} Ziehungen analysiert") - - def _perform_cycle_analysis(self, max_cycle_length=15): - """Analysiert zyklische Muster (NEU!)""" - print(f"\n🔄 ZYKLUS-ANALYSE") - - pattern_sequence = [] - for _, row in self.df.iterrows(): - numbers = sorted([row['Z1'], row['Z2'], row['Z3'], row['Z4'], row['Z5']]) - pattern = self._get_pattern(numbers) - pattern_sequence.append(pattern) - - # Zyklen erkennen - self.cycle_patterns = {} - for cycle_length in range(3, max_cycle_length + 1): - cycles = self._find_pattern_cycles(pattern_sequence, cycle_length) - if cycles: - self.cycle_patterns[cycle_length] = cycles - - cycle_count = sum(len(cycles) for cycles in self.cycle_patterns.values()) - print(f"🔄 {cycle_count} zyklische Muster erkannt") - - def _generate_trend_predictions(self): - """Generiert Trend-basierte Vorhersagen (NEU!)""" - print(f"\n🎯 TREND-VORHERSAGEN GENERIEREN") - - for number in range(1, 51): - if number in self.momentum_scores: - momentum_data = self.momentum_scores[number] - - # Multi-Faktor-Vorhersage-Score - momentum_weight = momentum_data['momentum_score'] * 0.4 - frequency_weight = (self.number_frequencies[number] / len(self.df)) * 0.3 - trend_weight = max(0, momentum_data['trend_score']) * 0.3 - - prediction_score = momentum_weight + frequency_weight + trend_weight - - self.trend_predictions[number] = { - 'prediction_score': prediction_score, - 'recommendation': self._get_prediction_recommendation(prediction_score), - 'confidence': self._get_confidence_level(prediction_score) - } - - print(f"🎯 Trend-Vorhersagen für alle 50 Zahlen generiert") - - def _calculate_trend_score(self, sequence): - """Berechnet Trend-Score für eine Zahlensequenz.""" - if len(sequence) < 2: - return 0 - - x = np.arange(len(sequence)) - y = np.array(sequence) - weights = np.exp(x / len(x)) # Neuere Ziehungen wichtiger - - try: - coeffs = np.polyfit(x, y, 1, w=weights) - return coeffs[0] # Steigung = Trend - except: - return 0 - - def _calculate_recency_score(self, sequence): - """Berechnet Recency-Score.""" - try: - last_hit_index = len(sequence) - 1 - sequence[::-1].index(1) - recency = 1 - (len(sequence) - 1 - last_hit_index) / len(sequence) - return recency - except ValueError: - return 0 - - def _get_momentum_status(self, score): - """Klassifiziert Momentum-Status.""" - if score > 0.5: - return "🔥 SEHR HEISS" - elif score > 0.35: - return "🌡️ HEISS" - elif score > 0.2: - return "😐 WARM" - elif score > 0.1: - return "🧊 KÜHL" - else: - return "❄️ EISKALT" - - def _get_prediction_recommendation(self, score): - """Empfehlung basierend auf Vorhersage-Score.""" - if score > 0.4: - return "SEHR EMPFOHLEN" - elif score > 0.25: - return "EMPFOHLEN" - elif score > 0.15: - return "NEUTRAL" - else: - return "VERMEIDEN" - - def _get_confidence_level(self, score): - """Konfidenz-Level für Vorhersagen.""" - if score > 0.4: - return "HOCH" - elif score > 0.25: - return "MITTEL" - else: - return "NIEDRIG" - - def _find_pattern_cycles(self, sequence, cycle_length): - """Findet zyklische Muster.""" - cycle_patterns = defaultdict(list) - - for i in range(len(sequence) - cycle_length): - pattern = ''.join(sequence[i:i+cycle_length]) - cycle_patterns[pattern].append(i) - - return {pattern: positions for pattern, positions in cycle_patterns.items() - if len(positions) >= 2} - - def _get_pattern(self, numbers): - """Bestimmt N/M/H-Muster.""" - pattern = [] - for num in numbers: - if 1 <= num <= 15: - pattern.append('N') - elif 16 <= num <= 35: - pattern.append('M') - else: - pattern.append('H') - return ''.join(pattern) - - def _print_ultimate_analysis_summary(self): - """Gibt detaillierte Analyse-Zusammenfassung aus.""" - print(f"\n📈 ULTIMATE ANALYSE-ZUSAMMENFASSUNG:") - print("=" * 55) - - # Top Trend-Empfehlungen - print("\n🎯 TOP 10 TREND-EMPFEHLUNGEN:") - top_predictions = sorted(self.trend_predictions.items(), - key=lambda x: x[1]['prediction_score'], reverse=True)[:10] - for i, (number, data) in enumerate(top_predictions): - momentum_status = self.momentum_scores[number]['status'] - print(f"{i+1:2}. Zahl {number:2}: Score {data['prediction_score']:.3f} " - f"({data['recommendation']}) {momentum_status}") - - # Top Muster mit Trend-Integration - print(f"\n🎨 TOP MUSTER (kombiniert mit Trends):") - for pattern, count in self.pattern_frequencies.most_common(5): - percentage = (count / len(self.drawn_combinations)) * 100 - print(f" {pattern}: {count}x ({percentage:.1f}%)") - - # Zyklische Erkenntnisse - if self.cycle_patterns: - print(f"\n🔄 ERKANNTE ZYKLEN:") - total_cycles = sum(len(cycles) for cycles in self.cycle_patterns.values()) - print(f" Insgesamt {total_cycles} zyklische Muster erkannt") - - def generate_ultimate_combination(self): - """Generiert ultimativ optimierte Kombination mit allen Methoden.""" - max_attempts = 1000 - - for attempt in range(max_attempts): - numbers = [] - - # Strategie-Mix basierend auf Trends: - # 40% Top-Trend-Zahlen, 30% Heiße Zahlen, 20% Position-optimiert, 10% Balance - - # 2 Zahlen aus Top-Trend-Empfehlungen (40%) - top_trend_numbers = [num for num, data in sorted(self.trend_predictions.items(), - key=lambda x: x[1]['prediction_score'], reverse=True)[:15] - if data['recommendation'] in ['SEHR EMPFOHLEN', 'EMPFOHLEN']] - - if len(top_trend_numbers) >= 2: - trend_picks = random.sample(top_trend_numbers[:10], 2) - numbers.extend(trend_picks) - - # 2 Zahlen aus heißen Zahlen (30%) - if len(self.hot_numbers) >= 2: - remaining_hot = [n for n in self.hot_numbers if n not in numbers] - if len(remaining_hot) >= 2: - hot_picks = random.sample(remaining_hot[:8], min(2, len(remaining_hot))) - numbers.extend(hot_picks) - - # 1 Zahl positions-optimiert oder warm (30%) - remaining_slots = 5 - len(numbers) - if remaining_slots > 0: - if self.warm_numbers: - remaining_warm = [n for n in self.warm_numbers if n not in numbers] - if remaining_warm: - warm_pick = random.choice(remaining_warm[:5]) - numbers.append(warm_pick) - - # Auffüllen bis 5 Zahlen - while len(numbers) < 5: - available_numbers = [n for n in range(1, 51) if n not in numbers] - - # Gewichtete Auswahl basierend auf Trend-Scores - weights = [self.trend_predictions[n]['prediction_score'] for n in available_numbers] - if sum(weights) > 0: - additional_number = random.choices(available_numbers, weights=weights)[0] - else: - additional_number = random.choice(available_numbers) - - numbers.append(additional_number) - - # Sortieren und validieren - numbers = sorted(numbers[:5]) - - if self._validate_ultimate_combination(numbers): - return numbers - - # Fallback - return self._generate_fallback_combination() - - def _validate_ultimate_combination(self, numbers): - """Erweiterte Validierung mit Trend-Kriterien.""" - # Basis-Validierung - if tuple(numbers) in self.drawn_combinations: - return False - - if len(set(numbers)) != 5: - return False - - # Trend-Validierung - hot_count = sum(1 for n in numbers if n in self.hot_numbers) - high_trend_count = sum(1 for n in numbers - if self.trend_predictions[n]['recommendation'] == 'SEHR EMPFOHLEN') - - # Mindestens 1 heiße oder 1 sehr empfohlene Zahl - if hot_count == 0 and high_trend_count == 0: - return False - - # Standard-Validierungen - distances = [numbers[i+1] - numbers[i] for i in range(4)] - if min(distances) < 2 or max(distances) > 18: - return False - - even_count = sum(1 for n in numbers if n % 2 == 0) - if even_count == 0 or even_count == 5: - return False - - total = sum(numbers) - if total < 80 or total > 170: - return False - - return True - - def _generate_fallback_combination(self): - """Fallback mit Trend-Integration.""" - numbers = [] - - # Basis: NMMHH mit Trend-Gewichtung - ranges = { - 'N': [n for n in range(1, 16) if n in self.hot_numbers + self.warm_numbers] or list(range(1, 16)), - 'M': [n for n in range(16, 36) if n in self.hot_numbers + self.warm_numbers] or list(range(16, 36)), - 'H': [n for n in range(36, 51) if n in self.hot_numbers + self.warm_numbers] or list(range(36, 51)) - } - - numbers.extend(random.sample(ranges['N'][:10], 1)) - numbers.extend(random.sample(ranges['M'][:15], 2)) - numbers.extend(random.sample(ranges['H'][:10], 2)) - - return sorted(numbers) - - def get_optimized_supernumbers(self): - """Trend-optimierte Superzahlen-Auswahl.""" - # Integration von Trend-Daten für Superzahlen - sz1_trends = {} - sz2_trends = {} - - # Letzte 10 Ziehungen analysieren - recent_df = self.df.tail(10) - - for sz1 in range(1, 13): # Eurojackpot SZ1: 1-12 - recent_count = (recent_df['SZ1'] == sz1).sum() - total_count = self.supernumber_frequencies['sz1'][sz1] - trend_score = (recent_count / 10) * 0.6 + (total_count / len(self.df)) * 0.4 - sz1_trends[sz1] = trend_score - - for sz2 in range(1, 11): # Eurojackpot SZ2: 1-10 - recent_count = (recent_df['SZ2'] == sz2).sum() - total_count = self.supernumber_frequencies['sz2'][sz2] - trend_score = (recent_count / 10) * 0.6 + (total_count / len(self.df)) * 0.4 - sz2_trends[sz2] = trend_score - - # Gewichtete Auswahl - sz1_candidates = list(sz1_trends.keys()) - sz1_weights = list(sz1_trends.values()) - sz1 = random.choices(sz1_candidates, weights=sz1_weights)[0] - - sz2_candidates = list(sz2_trends.keys()) - sz2_weights = list(sz2_trends.values()) - sz2 = random.choices(sz2_candidates, weights=sz2_weights)[0] - - return sz1, sz2 - - def generate_ultimate_tips(self, num_tips=10): - """Generiert ultimative Tipps mit kompletter Multi-Trend-Integration.""" - print(f"\n🚀 ULTIMATE TIPP-GENERIERUNG") - print("=" * 50) - print(f"🎯 Kombiniert ALLE Optimierungsstrategien:") - print(f" ✅ Historische Häufigkeitsanalyse") - print(f" ✅ Positionsbasierte Gewichtung") - print(f" ✅ Multi-Ziehungs-Momentum-Analyse") - print(f" ✅ Sequenzielle Abhängigkeiten") - print(f" ✅ Zyklische Muster-Erkennung") - print(f" ✅ Trend-Vorhersage-Algorithmus") - - generated_tips = [] - strategy_distribution = Counter() - - print(f"\n🎲 GENERIERE {num_tips} ULTIMATE TIPPS:") - print("=" * 60) - print(f"{'Nr':<3} {'Zahlen':<20} {'Muster':<7} {'🔥':<3} {'🎯':<3} {'Status'}") - print("-" * 60) - - attempts = 0 - max_attempts = num_tips * 50 - - while len(generated_tips) < num_tips and attempts < max_attempts: - attempts += 1 - - combination = self.generate_ultimate_combination() - - if combination and tuple(combination) not in [tuple(tip['zahlen']) for tip in generated_tips]: - pattern = self._get_pattern(combination) - - # Trend-Analyse des Tipps - hot_count = sum(1 for n in combination if n in self.hot_numbers) - trend_count = sum(1 for n in combination - if self.trend_predictions[n]['recommendation'] in ['SEHR EMPFOHLEN', 'EMPFOHLEN']) - - # Superzahlen - sz1, sz2 = self.get_optimized_supernumbers() - - # Strategie-Klassifikation - if hot_count >= 3: - strategy = "🔥 MOMENTUM" - elif trend_count >= 3: - strategy = "🎯 TREND" - elif pattern in ['NMMHH', 'MNMHH', 'NHMHM']: - strategy = "🎨 MUSTER" - else: - strategy = "⚖️ BALANCE" - - strategy_distribution[strategy] += 1 - - tip = { - 'tipp_nr': len(generated_tips) + 1, - 'zahlen': combination, - 'z1': combination[0], - 'z2': combination[1], - 'z3': combination[2], - 'z4': combination[3], - 'z5': combination[4], - 'sz1': sz1, - 'sz2': sz2, - 'muster': pattern, - 'summe': sum(combination), - 'hot_count': hot_count, - 'trend_count': trend_count, - 'strategy': strategy - } - - generated_tips.append(tip) - - # Status ausgeben - zahlen_str = f"{combination[0]:2}-{combination[1]:2}-{combination[2]:2}-{combination[3]:2}-{combination[4]:2}" - print(f"{len(generated_tips):2}. {zahlen_str:<20} {pattern:<7} {hot_count:<3} {trend_count:<3} {strategy}") - - # Ultimate Zusammenfassung - print(f"\n🏆 ULTIMATE OPTIMIERUNGS-ZUSAMMENFASSUNG:") - print("=" * 50) - print(f"✅ {len(generated_tips)} Ultimate Tipps generiert") - print(f"🎯 Erfolgsrate: {(len(generated_tips)/attempts)*100:.1f}%") - print(f"📊 Durchschnitt {sum(tip['hot_count'] for tip in generated_tips)/len(generated_tips):.1f} heiße Zahlen pro Tipp") - print(f"🔮 Durchschnitt {sum(tip['trend_count'] for tip in generated_tips)/len(generated_tips):.1f} Trend-Zahlen pro Tipp") - - # Strategie-Verteilung - print(f"\n📈 STRATEGIE-VERTEILUNG:") - for strategy, count in strategy_distribution.most_common(): - print(f" {strategy}: {count} Tipps") - - # Komplette Tipp-Ausgabe - print(f"\n🎯 ULTIMATE TIPP-EMPFEHLUNGEN:") - print("=" * 70) - print(f"{'Nr':<3} {'Hauptzahlen':<20} {'SZ1':<4} {'SZ2':<4} {'Muster':<7} {'Strategie':<12} {'Score'}") - print("-" * 70) - - for tip in generated_tips: - zahlen_str = f"{tip['z1']:2}-{tip['z2']:2}-{tip['z3']:2}-{tip['z4']:2}-{tip['z5']:2}" - - # Ultimate Score berechnen - ultimate_score = (tip['hot_count'] * 0.3 + tip['trend_count'] * 0.4 + - (5 if tip['muster'] in ['NMMHH', 'MNMHH'] else 3) * 0.3) - - print(f"{tip['tipp_nr']:2}. {zahlen_str:<20} {tip['sz1']:<4} {tip['sz2']:<4} " - f"{tip['muster']:<7} {tip['strategy']:<12} {ultimate_score:.1f}") - - # Export mit Ultimate Features - self._export_ultimate_tips(generated_tips) - - return generated_tips - - def _export_ultimate_tips(self, tips): - """Exportiert Ultimate Tipps mit erweiterten Daten.""" - timestamp = datetime.datetime.now().strftime("%Y%m%d_%H%M%S") - output_file = f"/Users/sebastianfrohlich/Library/Mobile Documents/com~apple~CloudDocs/Jupyter Notebooks/Eurojackpot/ultimate_tipps_{timestamp}.csv" - - # Erweiterte Daten für Export - export_data = [] - for tip in tips: - tip_data = tip.copy() - - # Zusätzliche Trend-Daten hinzufügen - tip_data['trend_scores'] = [self.trend_predictions[n]['prediction_score'] - for n in tip['zahlen']] - tip_data['avg_trend_score'] = np.mean(tip_data['trend_scores']) - tip_data['momentum_ratings'] = [self.momentum_scores[n]['status'] - for n in tip['zahlen']] - - export_data.append(tip_data) - - tips_df = pd.DataFrame(export_data) - tips_df.to_csv(output_file, sep=';', index=False) - - print(f"\n💾 ULTIMATE EXPORT:") - print("=" * 25) - print(f"✅ Ultimate Tipps gespeichert: ultimate_tipps_{timestamp}.csv") - print(f"🚀 Multi-Trend-Analyse integriert") - print(f"🎯 Höchste Optimierungsstufe erreicht") - print(f"📊 Erweiterte Trend-Daten enthalten") - -def main(): - """Hauptfunktion für Ultimate Generator.""" - print("🚀 ULTIMATE EUROJACKPOT GENERATOR") - print("🎯 Mit Multi-Ziehungs-Trend-Integration") - print("=" * 50) - - # Generator initialisieren (lädt und analysiert automatisch alle Daten) - generator = UltimativerEurojackpotGenerator() - - # Ultimate Tipps generieren - tips = generator.generate_ultimate_tips(10) - - print(f"\n🏆 ULTIMATE OPTIMIERUNG ABGESCHLOSSEN!") - print("=" * 45) - print(f"🚀 10 Ultimate Tipps mit Multi-Trend-Analyse generiert") - print(f"📈 Maximale Trefferwahrscheinlichkeit durch:") - print(f" • Momentum-Analyse über 15 Ziehungen") - print(f" • Sequenzielle Abhängigkeiten") - print(f" • Zyklische Muster-Erkennung") - print(f" • Positionsbasierte Optimierung") - print(f" • Trend-Vorhersage-Algorithmus") - print(f"🍀 Viel Erfolg bei der nächsten Ziehung!") - - # Zusätzliche Ultimate Insights - print(f"\n💡 ULTIMATE INSIGHTS:") - print("=" * 30) - - # Top 5 Trend-Zahlen für nächste Ziehung - top_trend_numbers = sorted(generator.trend_predictions.items(), - key=lambda x: x[1]['prediction_score'], reverse=True)[:5] - print(f"🎯 TOP 5 TREND-ZAHLEN für nächste Ziehung:") - for i, (number, data) in enumerate(top_trend_numbers): - momentum_status = generator.momentum_scores[number]['status'] - print(f" {i+1}. Zahl {number:2}: {data['recommendation']} {momentum_status}") - - # Empfohlene Muster basierend auf Zyklen - if generator.cycle_patterns: - print(f"\n🔄 ZYKLUS-EMPFEHLUNG:") - # Finde das wahrscheinlichste nächste Muster basierend auf Zyklen - recent_patterns = [] - for _, row in generator.df.tail(5).iterrows(): - numbers = sorted([row['Z1'], row['Z2'], row['Z3'], row['Z4'], row['Z5']]) - pattern = generator._get_pattern(numbers) - recent_patterns.append(pattern) - - print(f" Letzte 5 Muster: {' → '.join(recent_patterns)}") - - # Empfehlung basierend auf häufigsten Mustern - top_pattern = generator.pattern_frequencies.most_common(1)[0] - print(f" Empfohlenes Muster: {top_pattern[0]} ({(top_pattern[1]/len(generator.df))*100:.1f}% Erfolgsrate)") - - # Momentum-Warnung - very_hot = [n for n in generator.hot_numbers - if generator.momentum_scores[n]['momentum_score'] > 0.5] - if very_hot: - print(f"\n🔥 MOMENTUM-ALERT:") - print(f" SEHR HEIßE Zahlen: {very_hot[:5]}") - print(f" → Mindestens 1-2 dieser Zahlen in Tipps verwenden!") - - return tips - -# Zusätzliche Utility-Funktionen für erweiterte Analyse - -def analyze_tip_quality(generator, tip_numbers): - """Analysiert die Qualität eines einzelnen Tipps.""" - quality_score = 0 - analysis = {} - - # Momentum-Analyse - hot_count = sum(1 for n in tip_numbers if n in generator.hot_numbers) - analysis['hot_numbers'] = hot_count - quality_score += hot_count * 0.2 - - # Trend-Analyse - trend_scores = [generator.trend_predictions[n]['prediction_score'] for n in tip_numbers] - avg_trend = np.mean(trend_scores) - analysis['avg_trend_score'] = avg_trend - quality_score += avg_trend * 0.3 - - # Positions-Analyse - position_quality = 0 - for i, num in enumerate(sorted(tip_numbers)): - pos_freq = generator.position_frequencies[f'pos_{i+1}'][num] - if pos_freq > 0: - position_quality += pos_freq - analysis['position_quality'] = position_quality - quality_score += (position_quality / len(generator.df)) * 0.2 - - # Muster-Analyse - pattern = generator._get_pattern(sorted(tip_numbers)) - pattern_freq = generator.pattern_frequencies[pattern] - pattern_score = pattern_freq / len(generator.df) - analysis['pattern'] = pattern - analysis['pattern_score'] = pattern_score - quality_score += pattern_score * 0.3 - - analysis['total_quality_score'] = quality_score - analysis['quality_rating'] = get_quality_rating(quality_score) - - return analysis - -def get_quality_rating(score): - """Konvertiert Quality-Score in Rating.""" - if score > 0.8: - return "🏆 PREMIUM" - elif score > 0.6: - return "🥇 SEHR GUT" - elif score > 0.4: - return "🥈 GUT" - elif score > 0.2: - return "🥉 DURCHSCHNITT" - else: - return "⚠️ SCHWACH" - -def predict_jackpot_probability(generator, tip_numbers): - """Schätzt Jackpot-Wahrscheinlichkeit basierend auf Trends.""" - base_probability = 1 / 139838160 # Mathematische Grundwahrscheinlichkeit - - # Trend-Multiplikator berechnen - trend_multiplier = 1.0 - - for number in tip_numbers: - momentum_score = generator.momentum_scores[number]['momentum_score'] - trend_score = generator.trend_predictions[number]['prediction_score'] - - # Zahlen mit hohem Momentum/Trend erhöhen die relative Wahrscheinlichkeit - number_multiplier = 1 + (momentum_score * 0.1) + (trend_score * 0.15) - trend_multiplier *= number_multiplier - - # Pattern-Bonus - pattern = generator._get_pattern(sorted(tip_numbers)) - pattern_frequency = generator.pattern_frequencies[pattern] / len(generator.df) - pattern_multiplier = 1 + (pattern_frequency * 0.2) - - estimated_probability = base_probability * trend_multiplier * pattern_multiplier - - return { - 'base_probability': base_probability, - 'trend_multiplier': trend_multiplier, - 'pattern_multiplier': pattern_multiplier, - 'estimated_probability': estimated_probability, - 'improvement_factor': (estimated_probability / base_probability) - } - -def export_detailed_analysis(generator, tips, filename_suffix="detailed"): - """Exportiert detaillierte Analyse aller Tipps.""" - timestamp = datetime.datetime.now().strftime("%Y%m%d_%H%M%S") - output_file = f"/Users/sebastianfrohlich/Library/Mobile Documents/com~apple~CloudDocs/Jupyter Notebooks/Eurojackpot/analysis_{filename_suffix}_{timestamp}.csv" - - detailed_data = [] - - for tip in tips: - tip_analysis = analyze_tip_quality(generator, tip['zahlen']) - probability_analysis = predict_jackpot_probability(generator, tip['zahlen']) - - detailed_entry = { - **tip, - **tip_analysis, - **probability_analysis, - 'individual_momentum_scores': [generator.momentum_scores[n]['momentum_score'] for n in tip['zahlen']], - 'individual_trend_scores': [generator.trend_predictions[n]['prediction_score'] for n in tip['zahlen']], - 'number_frequencies': [generator.number_frequencies[n] for n in tip['zahlen']] - } - - detailed_data.append(detailed_entry) - - # DataFrame erstellen und exportieren - df_detailed = pd.DataFrame(detailed_data) - df_detailed.to_csv(output_file, sep=';', index=False) - - print(f"\n📊 DETAILLIERTE ANALYSE EXPORTIERT:") - print(f" 📁 Datei: analysis_{filename_suffix}_{timestamp}.csv") - print(f" 📈 Enthält Quality-Scores, Trend-Analysen und Wahrscheinlichkeits-Schätzungen") - -if __name__ == "__main__": - # Reproduzierbarer Zufallsseed - random.seed(42) - np.random.seed(42) - - # Ultimate Generator starten - tips = main() - - # Optional: Detaillierte Analyse exportieren - if tips: - print(f"\n📊 ERWEITERTE ANALYSE VERFÜGBAR:") - print("=" * 40) - - # Beispiel: Analysiere ersten Tipp detailliert - if len(tips) > 0: - generator = UltimativerEurojackpotGenerator() - - sample_tip = tips[0]['zahlen'] - quality_analysis = analyze_tip_quality(generator, sample_tip) - probability_analysis = predict_jackpot_probability(generator, sample_tip) - - print(f"\n🔍 BEISPIEL-ANALYSE für Tipp 1 ({sample_tip}):") - print(f" 🏆 Quality-Rating: {quality_analysis['quality_rating']}") - print(f" 📈 Quality-Score: {quality_analysis['total_quality_score']:.3f}") - print(f" 🔥 Heiße Zahlen: {quality_analysis['hot_numbers']}/5") - print(f" 🎯 Avg. Trend-Score: {quality_analysis['avg_trend_score']:.3f}") - print(f" 🎨 Muster: {quality_analysis['pattern']} (Score: {quality_analysis['pattern_score']:.3f})") - print(f" 📊 Verbesserungs-Faktor: {probability_analysis['improvement_factor']:.2f}x") - - # Optional: Detaillierte Analyse aller Tipps exportieren - export_detailed_analysis(generator, tips) \ No newline at end of file diff --git a/scripts/generators/tipp_generator_nmmhh.py b/scripts/generators/tipp_generator_nmmhh.py deleted file mode 100644 index 02fbb5e..0000000 --- a/scripts/generators/tipp_generator_nmmhh.py +++ /dev/null @@ -1,234 +0,0 @@ -#!/usr/bin/env python3 -""" -Eurojackpot Tipp-Generator für NMMHH-Muster - -Generiert 10 Tipp-Felder basierend auf dem erfolgreichsten NMMHH-Muster, -die keine bereits gezogenen Kombinationen enthalten. -""" - -import pandas as pd -import random -from itertools import combinations - -def load_drawn_numbers(): - """Lädt alle bereits gezogenen Kombinationen.""" - df = pd.read_csv("/Users/sebastianfrohlich/Library/Mobile Documents/com~apple~CloudDocs/Jupyter Notebooks/AlleEurojackpotzahlen.csv", sep=';') - - drawn_combinations = set() - for _, row in df.iterrows(): - # Sortierte Kombination für Vergleich - combo = tuple(sorted([row['Z1'], row['Z2'], row['Z3'], row['Z4'], row['Z5']])) - drawn_combinations.add(combo) - - print(f"🚫 {len(drawn_combinations)} bereits gezogene Kombinationen geladen") - return drawn_combinations - -def generate_nmmhh_numbers(): - """Generiert Zahlen nach dem NMMHH-Muster.""" - - # Bereichsdefinition basierend auf umschlüsselter Analyse - ranges = { - 'N': list(range(1, 16)), # Niedrig: Gruppen 1-3 (Zahlen 1-15) - 'M': list(range(16, 36)), # Mittel: Gruppen 4-7 (Zahlen 16-35) - 'H': list(range(36, 51)) # Hoch: Gruppen 8-10 (Zahlen 36-50) - } - - # NMMHH-Muster: 1 Niedrig, 2 Mittel, 2 Hoch - selected_numbers = [] - - # 1 Niedrige Zahl (Position z1) - selected_numbers.extend(random.sample(ranges['N'], 1)) - - # 2 Mittlere Zahlen (Positionen z2, z3) - selected_numbers.extend(random.sample(ranges['M'], 2)) - - # 2 Hohe Zahlen (Positionen z4, z5) - selected_numbers.extend(random.sample(ranges['H'], 2)) - - # Sortieren für Eurojackpot-Format - return sorted(selected_numbers) - -def generate_optimized_nmmhh_numbers(): - """Generiert optimierte NMMHH-Zahlen basierend auf Positionsanalyse.""" - - # Optimierte Bereiche basierend auf Treffer-Analyse - optimized_ranges = { - 'z1': [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15], # Niedrig (sehr wahrscheinlich) - 'z2': [11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25], # Niedrig-Mittel - 'z3': [21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35], # Mittel - 'z4': [31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45], # Mittel-Hoch - 'z5': [41, 42, 43, 44, 45, 46, 47, 48, 49, 50] # Hoch (sehr wahrscheinlich) - } - - selected_numbers = [] - - # Position z1: Niedrig - selected_numbers.append(random.choice(optimized_ranges['z1'][:10])) # Fokus auf 1-10 - - # Position z2: Niedrig-Mittel - selected_numbers.append(random.choice(optimized_ranges['z2'][5:])) # Fokus auf 16-25 - - # Position z3: Mittel - selected_numbers.append(random.choice(optimized_ranges['z3'])) # 21-35 - - # Position z4: Mittel-Hoch - selected_numbers.append(random.choice(optimized_ranges['z4'][5:])) # Fokus auf 36-45 - - # Position z5: Hoch - selected_numbers.append(random.choice(optimized_ranges['z5'])) # 41-50 - - # Duplikate vermeiden und sortieren - selected_numbers = list(set(selected_numbers)) - - # Falls durch Duplikat-Entfernung weniger als 5 Zahlen - while len(selected_numbers) < 5: - all_available = list(range(1, 51)) - missing_number = random.choice([n for n in all_available if n not in selected_numbers]) - selected_numbers.append(missing_number) - - return sorted(selected_numbers[:5]) - -def generate_tips_nmmhh(num_tips=10): - """Generiert Tipps basierend auf NMMHH-Muster ohne bereits gezogene Kombinationen.""" - - print("🎯 EUROJACKPOT TIPP-GENERATOR (NMMHH-MUSTER)") - print("="*50) - - # Bereits gezogene Kombinationen laden - drawn_combinations = load_drawn_numbers() - - # Häufigste Zahlen pro Position aus der Analyse - frequent_numbers = { - 'z1': [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15], - 'z2': [11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25], - 'z3': [21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35], - 'z4': [31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45], - 'z5': [36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50] - } - - print(f"\n📋 NMMHH-MUSTER BEDEUTUNG:") - print("N = Niedrig (1-15), M = Mittel (16-35), H = Hoch (36-50)") - print("Muster: 1 Niedrig + 2 Mittel + 2 Hoch = 14.7% Erfolgsrate!") - - generated_tips = [] - attempts = 0 - max_attempts = 10000 - - print(f"\n🎲 GENERIERE {num_tips} OPTIMIERTE TIPPS:") - print("="*40) - - while len(generated_tips) < num_tips and attempts < max_attempts: - attempts += 1 - - # Verschiedene Generierungsstrategien abwechseln - if attempts % 3 == 0: - tip = generate_optimized_nmmhh_numbers() - else: - tip = generate_nmmhh_numbers() - - # Prüfen ob bereits gezogen - tip_tuple = tuple(sorted(tip)) - - if tip_tuple not in drawn_combinations and tip not in generated_tips: - generated_tips.append(tip) - - # Muster-Verifikation - pattern = [] - for num in tip: - if 1 <= num <= 15: - pattern.append('N') - elif 16 <= num <= 35: - pattern.append('M') - else: - pattern.append('H') - - pattern_str = ''.join(pattern) - - print(f"Tipp {len(generated_tips):2}: {tip[0]:2}-{tip[1]:2}-{tip[2]:2}-{tip[3]:2}-{tip[4]:2} (Muster: {pattern_str})") - - if len(generated_tips) < num_tips: - print(f"\n⚠️ Nur {len(generated_tips)} von {num_tips} Tipps generiert nach {attempts} Versuchen") - else: - print(f"\n✅ Alle {num_tips} Tipps erfolgreich generiert!") - - print(f"\n📊 MUSTER-ANALYSE DER GENERIERTEN TIPPS:") - print("="*45) - - pattern_counts = {} - for tip in generated_tips: - pattern = [] - for num in tip: - if 1 <= num <= 15: - pattern.append('N') - elif 16 <= num <= 35: - pattern.append('M') - else: - pattern.append('H') - - pattern_str = ''.join(pattern) - pattern_counts[pattern_str] = pattern_counts.get(pattern_str, 0) + 1 - - for pattern, count in sorted(pattern_counts.items(), key=lambda x: x[1], reverse=True): - print(f"Muster {pattern}: {count} Tipps") - - # Zusätzliche Superzahlen-Empfehlungen - print(f"\n🎲 SUPERZAHLEN-EMPFEHLUNGEN:") - print("="*30) - - # Lade Superzahlen-Statistiken - df = pd.read_csv("/Users/sebastianfrohlich/Library/Mobile Documents/com~apple~CloudDocs/Jupyter Notebooks/AlleEurojackpotzahlen.csv", sep=';') - - sz1_counts = df['SZ1'].value_counts().head(5) - sz2_counts = df['SZ2'].value_counts().head(5) - - print(f"Top 5 SZ1: {list(sz1_counts.index)}") - print(f"Top 5 SZ2: {list(sz2_counts.index)}") - - # Empfohlene Superzahlen für die Tipps - recommended_sz1 = list(sz1_counts.index)[:3] - recommended_sz2 = list(sz2_counts.index)[:3] - - print(f"\n🎯 KOMPLETTE TIPP-EMPFEHLUNGEN:") - print("="*40) - print(f"{'Tipp':<5} {'Hauptzahlen':<20} {'SZ1':<4} {'SZ2':<4}") - print("-" * 40) - - final_tips = [] - for i, tip in enumerate(generated_tips, 1): - sz1 = random.choice(recommended_sz1) - sz2 = random.choice(recommended_sz2) - - tip_str = f"{tip[0]:2}-{tip[1]:2}-{tip[2]:2}-{tip[3]:2}-{tip[4]:2}" - print(f"{i:2}. {tip_str:<20} {sz1:<4} {sz2:<4}") - - final_tips.append({ - 'tipp_nr': i, - 'z1': tip[0], - 'z2': tip[1], - 'z3': tip[2], - 'z4': tip[3], - 'z5': tip[4], - 'sz1': sz1, - 'sz2': sz2, - 'muster': ''.join(['N' if n <= 15 else 'M' if n <= 35 else 'H' for n in tip]) - }) - - # Export der Tipps - print(f"\n💾 TIPPS EXPORTIEREN:") - print("="*25) - - tips_df = pd.DataFrame(final_tips) - output_file = "/Users/sebastianfrohlich/Library/Mobile Documents/com~apple~CloudDocs/Jupyter Notebooks/Eurojackpot/eurojackpot_tipps_nmmhh.csv" - tips_df.to_csv(output_file, sep=';', index=False) - - print(f"✅ 10 Tipps gespeichert: eurojackpot_tipps_nmmhh.csv") - print(f"📈 Basierend auf NMMHH-Muster mit 14.7% historischer Erfolgsrate") - print(f"🚫 Keine bereits gezogenen Kombinationen enthalten") - - return final_tips - -if __name__ == "__main__": - # Zufallsseed für reproduzierbare Ergebnisse (optional) - random.seed(42) - - tips = generate_tips_nmmhh(10) diff --git a/scripts/generators/tipp_generator_nmmhh_v2.py b/scripts/generators/tipp_generator_nmmhh_v2.py deleted file mode 100644 index 02fbb5e..0000000 --- a/scripts/generators/tipp_generator_nmmhh_v2.py +++ /dev/null @@ -1,234 +0,0 @@ -#!/usr/bin/env python3 -""" -Eurojackpot Tipp-Generator für NMMHH-Muster - -Generiert 10 Tipp-Felder basierend auf dem erfolgreichsten NMMHH-Muster, -die keine bereits gezogenen Kombinationen enthalten. -""" - -import pandas as pd -import random -from itertools import combinations - -def load_drawn_numbers(): - """Lädt alle bereits gezogenen Kombinationen.""" - df = pd.read_csv("/Users/sebastianfrohlich/Library/Mobile Documents/com~apple~CloudDocs/Jupyter Notebooks/AlleEurojackpotzahlen.csv", sep=';') - - drawn_combinations = set() - for _, row in df.iterrows(): - # Sortierte Kombination für Vergleich - combo = tuple(sorted([row['Z1'], row['Z2'], row['Z3'], row['Z4'], row['Z5']])) - drawn_combinations.add(combo) - - print(f"🚫 {len(drawn_combinations)} bereits gezogene Kombinationen geladen") - return drawn_combinations - -def generate_nmmhh_numbers(): - """Generiert Zahlen nach dem NMMHH-Muster.""" - - # Bereichsdefinition basierend auf umschlüsselter Analyse - ranges = { - 'N': list(range(1, 16)), # Niedrig: Gruppen 1-3 (Zahlen 1-15) - 'M': list(range(16, 36)), # Mittel: Gruppen 4-7 (Zahlen 16-35) - 'H': list(range(36, 51)) # Hoch: Gruppen 8-10 (Zahlen 36-50) - } - - # NMMHH-Muster: 1 Niedrig, 2 Mittel, 2 Hoch - selected_numbers = [] - - # 1 Niedrige Zahl (Position z1) - selected_numbers.extend(random.sample(ranges['N'], 1)) - - # 2 Mittlere Zahlen (Positionen z2, z3) - selected_numbers.extend(random.sample(ranges['M'], 2)) - - # 2 Hohe Zahlen (Positionen z4, z5) - selected_numbers.extend(random.sample(ranges['H'], 2)) - - # Sortieren für Eurojackpot-Format - return sorted(selected_numbers) - -def generate_optimized_nmmhh_numbers(): - """Generiert optimierte NMMHH-Zahlen basierend auf Positionsanalyse.""" - - # Optimierte Bereiche basierend auf Treffer-Analyse - optimized_ranges = { - 'z1': [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15], # Niedrig (sehr wahrscheinlich) - 'z2': [11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25], # Niedrig-Mittel - 'z3': [21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35], # Mittel - 'z4': [31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45], # Mittel-Hoch - 'z5': [41, 42, 43, 44, 45, 46, 47, 48, 49, 50] # Hoch (sehr wahrscheinlich) - } - - selected_numbers = [] - - # Position z1: Niedrig - selected_numbers.append(random.choice(optimized_ranges['z1'][:10])) # Fokus auf 1-10 - - # Position z2: Niedrig-Mittel - selected_numbers.append(random.choice(optimized_ranges['z2'][5:])) # Fokus auf 16-25 - - # Position z3: Mittel - selected_numbers.append(random.choice(optimized_ranges['z3'])) # 21-35 - - # Position z4: Mittel-Hoch - selected_numbers.append(random.choice(optimized_ranges['z4'][5:])) # Fokus auf 36-45 - - # Position z5: Hoch - selected_numbers.append(random.choice(optimized_ranges['z5'])) # 41-50 - - # Duplikate vermeiden und sortieren - selected_numbers = list(set(selected_numbers)) - - # Falls durch Duplikat-Entfernung weniger als 5 Zahlen - while len(selected_numbers) < 5: - all_available = list(range(1, 51)) - missing_number = random.choice([n for n in all_available if n not in selected_numbers]) - selected_numbers.append(missing_number) - - return sorted(selected_numbers[:5]) - -def generate_tips_nmmhh(num_tips=10): - """Generiert Tipps basierend auf NMMHH-Muster ohne bereits gezogene Kombinationen.""" - - print("🎯 EUROJACKPOT TIPP-GENERATOR (NMMHH-MUSTER)") - print("="*50) - - # Bereits gezogene Kombinationen laden - drawn_combinations = load_drawn_numbers() - - # Häufigste Zahlen pro Position aus der Analyse - frequent_numbers = { - 'z1': [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15], - 'z2': [11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25], - 'z3': [21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35], - 'z4': [31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45], - 'z5': [36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50] - } - - print(f"\n📋 NMMHH-MUSTER BEDEUTUNG:") - print("N = Niedrig (1-15), M = Mittel (16-35), H = Hoch (36-50)") - print("Muster: 1 Niedrig + 2 Mittel + 2 Hoch = 14.7% Erfolgsrate!") - - generated_tips = [] - attempts = 0 - max_attempts = 10000 - - print(f"\n🎲 GENERIERE {num_tips} OPTIMIERTE TIPPS:") - print("="*40) - - while len(generated_tips) < num_tips and attempts < max_attempts: - attempts += 1 - - # Verschiedene Generierungsstrategien abwechseln - if attempts % 3 == 0: - tip = generate_optimized_nmmhh_numbers() - else: - tip = generate_nmmhh_numbers() - - # Prüfen ob bereits gezogen - tip_tuple = tuple(sorted(tip)) - - if tip_tuple not in drawn_combinations and tip not in generated_tips: - generated_tips.append(tip) - - # Muster-Verifikation - pattern = [] - for num in tip: - if 1 <= num <= 15: - pattern.append('N') - elif 16 <= num <= 35: - pattern.append('M') - else: - pattern.append('H') - - pattern_str = ''.join(pattern) - - print(f"Tipp {len(generated_tips):2}: {tip[0]:2}-{tip[1]:2}-{tip[2]:2}-{tip[3]:2}-{tip[4]:2} (Muster: {pattern_str})") - - if len(generated_tips) < num_tips: - print(f"\n⚠️ Nur {len(generated_tips)} von {num_tips} Tipps generiert nach {attempts} Versuchen") - else: - print(f"\n✅ Alle {num_tips} Tipps erfolgreich generiert!") - - print(f"\n📊 MUSTER-ANALYSE DER GENERIERTEN TIPPS:") - print("="*45) - - pattern_counts = {} - for tip in generated_tips: - pattern = [] - for num in tip: - if 1 <= num <= 15: - pattern.append('N') - elif 16 <= num <= 35: - pattern.append('M') - else: - pattern.append('H') - - pattern_str = ''.join(pattern) - pattern_counts[pattern_str] = pattern_counts.get(pattern_str, 0) + 1 - - for pattern, count in sorted(pattern_counts.items(), key=lambda x: x[1], reverse=True): - print(f"Muster {pattern}: {count} Tipps") - - # Zusätzliche Superzahlen-Empfehlungen - print(f"\n🎲 SUPERZAHLEN-EMPFEHLUNGEN:") - print("="*30) - - # Lade Superzahlen-Statistiken - df = pd.read_csv("/Users/sebastianfrohlich/Library/Mobile Documents/com~apple~CloudDocs/Jupyter Notebooks/AlleEurojackpotzahlen.csv", sep=';') - - sz1_counts = df['SZ1'].value_counts().head(5) - sz2_counts = df['SZ2'].value_counts().head(5) - - print(f"Top 5 SZ1: {list(sz1_counts.index)}") - print(f"Top 5 SZ2: {list(sz2_counts.index)}") - - # Empfohlene Superzahlen für die Tipps - recommended_sz1 = list(sz1_counts.index)[:3] - recommended_sz2 = list(sz2_counts.index)[:3] - - print(f"\n🎯 KOMPLETTE TIPP-EMPFEHLUNGEN:") - print("="*40) - print(f"{'Tipp':<5} {'Hauptzahlen':<20} {'SZ1':<4} {'SZ2':<4}") - print("-" * 40) - - final_tips = [] - for i, tip in enumerate(generated_tips, 1): - sz1 = random.choice(recommended_sz1) - sz2 = random.choice(recommended_sz2) - - tip_str = f"{tip[0]:2}-{tip[1]:2}-{tip[2]:2}-{tip[3]:2}-{tip[4]:2}" - print(f"{i:2}. {tip_str:<20} {sz1:<4} {sz2:<4}") - - final_tips.append({ - 'tipp_nr': i, - 'z1': tip[0], - 'z2': tip[1], - 'z3': tip[2], - 'z4': tip[3], - 'z5': tip[4], - 'sz1': sz1, - 'sz2': sz2, - 'muster': ''.join(['N' if n <= 15 else 'M' if n <= 35 else 'H' for n in tip]) - }) - - # Export der Tipps - print(f"\n💾 TIPPS EXPORTIEREN:") - print("="*25) - - tips_df = pd.DataFrame(final_tips) - output_file = "/Users/sebastianfrohlich/Library/Mobile Documents/com~apple~CloudDocs/Jupyter Notebooks/Eurojackpot/eurojackpot_tipps_nmmhh.csv" - tips_df.to_csv(output_file, sep=';', index=False) - - print(f"✅ 10 Tipps gespeichert: eurojackpot_tipps_nmmhh.csv") - print(f"📈 Basierend auf NMMHH-Muster mit 14.7% historischer Erfolgsrate") - print(f"🚫 Keine bereits gezogenen Kombinationen enthalten") - - return final_tips - -if __name__ == "__main__": - # Zufallsseed für reproduzierbare Ergebnisse (optional) - random.seed(42) - - tips = generate_tips_nmmhh(10) diff --git a/scripts/generators/ultimate_ai_ml_eurojackpot_generator_v2.1_backup.py b/scripts/generators/ultimate_ai_ml_eurojackpot_generator_v2.1_backup.py deleted file mode 100644 index f8501f4..0000000 --- a/scripts/generators/ultimate_ai_ml_eurojackpot_generator_v2.1_backup.py +++ /dev/null @@ -1,1338 +0,0 @@ -#!/usr/bin/env python3 -""" -ULTIMATE AI-ML HYBRID EUROJACKPOT GENERATOR V2.1 -Kombiniert ALLE besten Features für maximale Gewinnchancen - -🎰 EUROJACKPOT REGELN: -- 5 Zahlen aus 50 (Hauptzahlen) -- 2 Eurozahlen aus 12 (Sternzahlen) - -🧠 AI/ML FEATURES: -- Random Forest + Gradient Boosting + Neural Networks Ensemble -- LSTM & CNN Deep Learning (optional) -- Real-Time Learning mit kontinuierlicher Anpassung -- Advanced Feature Engineering (Trends, Gaps, Saisonal) -- Model Persistence & Performance Tracking - -🎨 PATTERN FEATURES: -- Historische Pattern-Analyse (NNMMHH, etc.) -- Bereichs-Diversität Optimierung -- Gerade/Ungerade Balance -- Multi-Strategy Generation - -⚡ HYBRID FEATURES: -- 4 Strategien: Pure AI, Pure Pattern, Hybrid-Optimized, Ensemble-Best -- Adaptive Gewichtung basierend auf Performance -- Multi-Objective Optimization -- Portfolio-Diversifikation -""" - -import pandas as pd -import numpy as np -import random -from collections import Counter, defaultdict, deque -import datetime -import pickle -import os -import json - -# ML Imports -try: - from sklearn.ensemble import RandomForestRegressor, GradientBoostingRegressor - from sklearn.neural_network import MLPRegressor - from sklearn.preprocessing import StandardScaler - from sklearn.model_selection import train_test_split - from sklearn.metrics import r2_score - import joblib - ML_AVAILABLE = True -except ImportError: - ML_AVAILABLE = False - -# Deep Learning (optional) -try: - import tensorflow as tf - from tensorflow.keras.models import Sequential - from tensorflow.keras.layers import LSTM, Dense, Dropout - from tensorflow.keras.optimizers import Adam - DEEP_LEARNING_AVAILABLE = True -except ImportError: - DEEP_LEARNING_AVAILABLE = False - - -class UltimateAIMLEurojackpotGenerator: - """ - Ultimate Eurojackpot Generator - ALLE Strategien kombiniert - """ - - def __init__(self, data_path, fast_mode=True): - self.data_path = data_path - self.df = None - self.fast_mode = fast_mode - - # Core Systems - self.ai_ml_engine = EurojackpotAIMLEngine(fast_mode=fast_mode) - self.pattern_engine = EurojackpotPatternEngine() - self.hybrid_optimizer = EurojackpotHybridOptimizer(fast_mode=fast_mode) - self.feature_engineer = EurojackpotFeatureEngineer() - self.real_time_learner = EurojackpotRealTimeLearner() - self.performance_tracker = EurojackpotPerformanceTracker() - - # Strategy Management - self.strategy_weights = { - 'pure_ai': 0.30, - 'pure_pattern': 0.25, - 'hybrid_optimized': 0.30, - 'ensemble_best': 0.15 - } - - # Configuration - self.model_cache_path = os.path.join(os.path.dirname(data_path), "eurojackpot_ml_models") - self.is_trained = False - - print("🚀 ULTIMATE AI-ML HYBRID EUROJACKPOT GENERATOR V2.1") - print("=" * 70) - print("🎰 5 aus 50 + 2 aus 12 | 🧠 AI/ML + 🎨 Pattern + ⚡ Hybrid") - if fast_mode: - print("⚡ FAST MODE: Aktiviert") - print("=" * 70) - - # Initialize - self.initialize_system() - - def initialize_system(self): - """Initialisiert alle Systeme.""" - print("\n🔧 SYSTEM INITIALIZATION...") - print("-" * 70) - - # 1. Load Data - print("📊 Loading data...", end=" ", flush=True) - if not self._load_data(): - return - print("✅") - - # 2. Feature Engineering - print("🔍 Feature Engineering...", end=" ", flush=True) - self.features_df = self.feature_engineer.create_features(self.df) - print(f"✅ ({len(self.features_df.columns)} features)") - - # 3. Initialize Pattern Engine - print("🎨 Analyzing patterns...", end=" ", flush=True) - self.pattern_engine.initialize(self.df) - print(f"✅ ({len(self.pattern_engine.pattern_frequencies)} patterns)") - - # 4. Initialize AI/ML Engine - print("🧠 Initializing AI/ML Engine...") - self.ai_ml_engine.data_file = self.data_path # Setze data_file für Retraining-Check - self.ai_ml_engine.initialize(self.df, self.features_df, self.model_cache_path) - - # 5. Initialize Hybrid Optimizer - print("⚡ Initializing Hybrid Optimizer...", end=" ", flush=True) - self.hybrid_optimizer.initialize(self.ai_ml_engine, self.pattern_engine) - print("✅") - - # 6. Initialize Real-Time Learning - print("📚 Activating Real-Time Learning...", end=" ", flush=True) - self.real_time_learner.initialize(self.features_df) - print("✅") - - self.is_trained = self.ai_ml_engine.is_trained - - print("\n✅ ALL SYSTEMS READY!") - self._print_system_status() - - def _load_data(self): - """Lädt und validiert Eurojackpot-Daten.""" - try: - self.df = pd.read_csv(self.data_path, sep=';') - - if 'datum' in self.df.columns: - self.df['datum'] = pd.to_datetime(self.df['datum'], format='%Y-%m-%d', errors='coerce') - self.df = self.df.sort_values('datum') - - # Validate Eurojackpot structure - required_cols = ['Z1', 'Z2', 'Z3', 'Z4', 'Z5', 'SZ1', 'SZ2'] - if not all(col in self.df.columns for col in required_cols): - print("❌ Fehlende Spalten") - return False - - return True - - except Exception as e: - print(f"❌ Error: {e}") - return False - - def _print_system_status(self): - """Zeigt System-Status.""" - print("\n📊 SYSTEM STATUS:") - print(f" 🧠 ML Available: {'✅' if ML_AVAILABLE else '❌ (pip install scikit-learn)'}") - print(f" 🚀 Deep Learning: {'✅' if DEEP_LEARNING_AVAILABLE else '⚠️ Optional'}") - print(f" 🎯 Models Trained: {'✅' if self.is_trained else '⚠️ Using fallback'}") - print(f" 📁 Data Size: {len(self.df):,} drawings") - print(f" 🎨 Patterns: {len(self.pattern_engine.pattern_frequencies)}") - print(f" ⚡ Fast Mode: {'ON' if self.fast_mode else 'OFF'}") - - def generate_ultimate_tips(self, num_tips=10): - """ - Generiert Ultimate Eurojackpot Tips. - """ - print(f"\n🎯 GENERATING {num_tips} ULTIMATE EUROJACKPOT TIPS") - print("=" * 100) - - if len(self.df) == 0: - print("❌ Keine Daten verfügbar") - return [] - - # Get AI Predictions - print("🧠 Computing AI predictions...", end=" ", flush=True) - main_predictions = self.ai_ml_engine.predict_main_numbers(self.features_df) - euro_predictions = self.ai_ml_engine.predict_euro_numbers(self.features_df) - - main_predictions = self.real_time_learner.adjust_main_predictions(main_predictions) - euro_predictions = self.real_time_learner.adjust_euro_predictions(euro_predictions) - print("✅") - - # Determine Strategy Distribution - distribution = self._calculate_strategy_distribution(num_tips) - - print(f"\n📊 STRATEGY DISTRIBUTION:") - for strategy, count in distribution.items(): - weight = self.strategy_weights[strategy] - print(f" {strategy.upper()}: {count} tips (Weight: {weight:.1%})") - - # Show Top Predictions - self._show_top_predictions(main_predictions, euro_predictions) - - # Generate Tips - print(f"\n🎲 GENERATING TIPS...") - all_tips = [] - tip_counter = 1 - - for strategy, count in distribution.items(): - strategy_name = strategy.upper() - print(f" {strategy_name}...", end=" ", flush=True) - tips = self._generate_tips_by_strategy( - strategy, count, tip_counter, main_predictions, euro_predictions - ) - all_tips.extend(tips) - tip_counter += len(tips) - print(f"✅ ({count} tips)") - - # Output all tips - print(f"\n📋 RESULTS:") - print("=" * 100) - print("Nr 5 Main Numbers 2 Euro Strategy Main-AI Euro-AI Pattern Confidence Quality") - print("-" * 100) - - for tip in all_tips: - self._print_tip_line(tip) - - # Analysis - self._analyze_portfolio(all_tips) - - # Update adaptive weights - self._update_strategy_weights(all_tips) - - # Track performance - self.performance_tracker.log_generated_tips(all_tips) - - return all_tips - - def _calculate_strategy_distribution(self, num_tips): - """Berechnet Tip-Verteilung.""" - distribution = {} - remaining = num_tips - - for strategy, weight in sorted(self.strategy_weights.items(), key=lambda x: x[1], reverse=True): - count = max(1, int(num_tips * weight)) - count = min(count, remaining) - distribution[strategy] = count - remaining -= count - - if remaining > 0: - best_strategy = max(self.strategy_weights.items(), key=lambda x: x[1])[0] - distribution[best_strategy] += remaining - - return distribution - - def _show_top_predictions(self, main_predictions, euro_predictions): - """Zeigt Top AI Predictions.""" - print(f"\n🧠 TOP 10 MAIN NUMBER PREDICTIONS:") - sorted_main = sorted(main_predictions.items(), key=lambda x: x[1], reverse=True)[:10] - - for i, (num, score) in enumerate(sorted_main, 1): - status = "🔥" if score > 0.7 else "🌡️" if score > 0.5 else "💧" - print(f" {i:2}. Zahl {num:2}: {score:.4f} {status}") - - print(f"\n⭐ TOP EURO NUMBER PREDICTIONS:") - sorted_euro = sorted(euro_predictions.items(), key=lambda x: x[1], reverse=True)[:6] - - for i, (num, score) in enumerate(sorted_euro, 1): - status = "🔥" if score > 0.7 else "🌡️" if score > 0.5 else "💧" - print(f" {i}. Euro-Zahl {num:2}: {score:.4f} {status}") - - def _generate_tips_by_strategy(self, strategy, count, start_number, main_preds, euro_preds): - """Generiert Tips für Strategie.""" - tips = [] - - for i in range(count): - tip_number = start_number + i - - if strategy == 'pure_ai': - tip = self._generate_pure_ai_tip(tip_number, main_preds, euro_preds) - elif strategy == 'pure_pattern': - tip = self._generate_pure_pattern_tip(tip_number, main_preds, euro_preds) - elif strategy == 'hybrid_optimized': - tip = self._generate_hybrid_tip(tip_number, main_preds, euro_preds) - else: # ensemble_best - tip = self._generate_ensemble_tip(tip_number, main_preds, euro_preds) - - tips.append(tip) - - return tips - - def _generate_pure_ai_tip(self, tip_number, main_preds, euro_preds): - """Pure AI Strategie.""" - random.seed(42 + tip_number * 13) - - # Main numbers - sorted_main = sorted(main_preds.items(), key=lambda x: x[1], reverse=True) - top_candidates = [num for num, score in sorted_main[:35]] - - selected_main = [] - for position in range(5): - candidates = [n for n in top_candidates if n not in selected_main] - - if not candidates: - candidates = [n for n in range(1, 51) if n not in selected_main] - - if candidates: - weights = [main_preds.get(c, 0.1) + random.random() * 0.15 for c in candidates] - if selected_main: - for i, c in enumerate(candidates): - diversity = self._calculate_diversity_score(c, selected_main) - weights[i] *= (1 + diversity * 0.3) - - choice = random.choices(candidates, weights=weights)[0] - selected_main.append(choice) - - selected_main = sorted(selected_main) - - # Euro numbers - sorted_euro = sorted(euro_preds.items(), key=lambda x: x[1], reverse=True) - top_euro = [num for num, score in sorted_euro[:8]] - - selected_euro = [] - for position in range(2): - candidates = [n for n in top_euro if n not in selected_euro] - if not candidates: - candidates = [n for n in range(1, 13) if n not in selected_euro] - - if candidates: - weights = [euro_preds.get(c, 0.1) + random.random() * 0.1 for c in candidates] - choice = random.choices(candidates, weights=weights)[0] - selected_euro.append(choice) - - selected_euro = sorted(selected_euro) - - # Scores - main_ai_score = np.mean([main_preds.get(n, 0.1) for n in selected_main]) - euro_ai_score = np.mean([euro_preds.get(n, 0.1) for n in selected_euro]) - pattern_weight = self.pattern_engine.calculate_pattern_weight(selected_main) - confidence = main_ai_score * 0.5 + euro_ai_score * 0.3 + pattern_weight * 0.2 - quality = self._calculate_quality_score(selected_main, selected_euro, main_preds, euro_preds, pattern_weight) - - return { - 'tip_number': tip_number, - 'main_numbers': selected_main, - 'euro_numbers': selected_euro, - 'strategy': 'PURE-AI', - 'main_ai_score': main_ai_score, - 'euro_ai_score': euro_ai_score, - 'pattern_weight': pattern_weight, - 'confidence': confidence, - 'quality': quality - } - - def _generate_pure_pattern_tip(self, tip_number, main_preds, euro_preds): - """Pure Pattern Strategie.""" - random.seed(42 + tip_number * 17) - - # Main numbers mit Pattern - top_patterns = self.pattern_engine.get_top_patterns(10) - target_pattern = top_patterns[tip_number % len(top_patterns)] if top_patterns else 'NNMMH' - - selected_main = self.pattern_engine.generate_for_pattern(target_pattern, tip_number) - - # Euro numbers - frequency based - selected_euro = self._get_smart_euro_numbers(tip_number, euro_preds) - - # Scores - pattern_weight = self.pattern_engine.calculate_pattern_weight(selected_main) - main_ai_score = np.mean([main_preds.get(n, 0.1) for n in selected_main]) - euro_ai_score = np.mean([euro_preds.get(n, 0.1) for n in selected_euro]) - confidence = pattern_weight * 0.6 + main_ai_score * 0.25 + euro_ai_score * 0.15 - quality = self._calculate_quality_score(selected_main, selected_euro, main_preds, euro_preds, pattern_weight) - - return { - 'tip_number': tip_number, - 'main_numbers': selected_main, - 'euro_numbers': selected_euro, - 'strategy': 'PURE-PATTERN', - 'main_ai_score': main_ai_score, - 'euro_ai_score': euro_ai_score, - 'pattern_weight': pattern_weight, - 'confidence': confidence, - 'quality': quality, - 'target_pattern': target_pattern - } - - def _generate_hybrid_tip(self, tip_number, main_preds, euro_preds): - """Hybrid Strategie.""" - result = self.hybrid_optimizer.optimize(tip_number, main_preds, euro_preds) - - quality = self._calculate_quality_score( - result['main_numbers'], result['euro_numbers'], - main_preds, euro_preds, result['pattern_weight'] - ) - - return { - 'tip_number': tip_number, - 'main_numbers': result['main_numbers'], - 'euro_numbers': result['euro_numbers'], - 'strategy': 'HYBRID-OPT', - 'main_ai_score': result['main_ai_score'], - 'euro_ai_score': result['euro_ai_score'], - 'pattern_weight': result['pattern_weight'], - 'confidence': result['confidence'], - 'quality': quality - } - - def _generate_ensemble_tip(self, tip_number, main_preds, euro_preds): - """Ensemble Strategie.""" - random.seed(42 + tip_number * 23) - - # Main numbers - ensemble approach - sorted_main = sorted(main_preds.items(), key=lambda x: x[1], reverse=True) - ai_candidates = [num for num, score in sorted_main[:25]] - - top_patterns = self.pattern_engine.get_top_patterns(3) - pattern_candidates = [] - for pattern in top_patterns[:2]: - pcands = self.pattern_engine.generate_for_pattern(pattern, tip_number) - pattern_candidates.extend(pcands) - - all_candidates = list(set(ai_candidates + pattern_candidates)) - - selected_main = [] - for position in range(5): - best_candidate = None - best_score = -1 - - for candidate in all_candidates: - if candidate not in selected_main: - ai_s = main_preds.get(candidate, 0.1) - pattern_s = self.pattern_engine.get_number_pattern_score(candidate) - diversity_s = self._calculate_diversity_score(candidate, selected_main) if selected_main else 0.5 - - ensemble_score = (ai_s * 0.4 + pattern_s * 0.3 + diversity_s * 0.3) - - if ensemble_score > best_score: - best_score = ensemble_score - best_candidate = candidate - - if best_candidate: - selected_main.append(best_candidate) - else: - available = [n for n in range(1, 51) if n not in selected_main] - if available: - selected_main.append(random.choice(available)) - - selected_main = sorted(selected_main[:5]) - - # Euro numbers - best from AI - selected_euro = self._get_smart_euro_numbers(tip_number, euro_preds) - - # Scores - main_ai_score = np.mean([main_preds.get(n, 0.1) for n in selected_main]) - euro_ai_score = np.mean([euro_preds.get(n, 0.1) for n in selected_euro]) - pattern_weight = self.pattern_engine.calculate_pattern_weight(selected_main) - confidence = (main_ai_score * 0.4 + euro_ai_score * 0.3 + pattern_weight * 0.3) - quality = self._calculate_quality_score(selected_main, selected_euro, main_preds, euro_preds, pattern_weight) - - return { - 'tip_number': tip_number, - 'main_numbers': selected_main, - 'euro_numbers': selected_euro, - 'strategy': 'ENSEMBLE', - 'main_ai_score': main_ai_score, - 'euro_ai_score': euro_ai_score, - 'pattern_weight': pattern_weight, - 'confidence': confidence, - 'quality': quality - } - - def _calculate_diversity_score(self, candidate, selected): - """Berechnet Diversität.""" - if not selected: - return 0.5 - - distances = [abs(candidate - s) for s in selected] - avg_distance = np.mean(distances) - distance_score = min(avg_distance / 10.0, 1.0) - - def get_range(n): - if n <= 10: return 0 - elif n <= 20: return 1 - elif n <= 30: return 2 - elif n <= 40: return 3 - else: return 4 - - candidate_range = get_range(candidate) - selected_ranges = [get_range(s) for s in selected] - range_counts = Counter(selected_ranges) - - if range_counts[candidate_range] < 2: - range_score = 0.8 - else: - range_score = 0.3 - - return (distance_score * 0.6 + range_score * 0.4) - - def _get_smart_euro_numbers(self, tip_number, euro_preds): - """Intelligente Euro-Zahlen Auswahl.""" - sorted_euro = sorted(euro_preds.items(), key=lambda x: x[1], reverse=True) - - # Strategy based on tip number - if tip_number <= 3: - # Top predictions - return sorted([num for num, _ in sorted_euro[:2]]) - else: - # Mix of top and diversity - top_euros = [num for num, _ in sorted_euro[:6]] - random.seed(42 + tip_number * 7) - return sorted(random.sample(top_euros, 2)) - - def _calculate_quality_score(self, main_numbers, euro_numbers, main_preds, euro_preds, pattern_weight): - """Berechnet Qualität.""" - # Main quality - main_scores = [main_preds.get(n, 0.1) for n in main_numbers] - main_quality = np.mean(main_scores) * (1 + np.std(main_scores) * 0.5) - - # Euro quality - euro_scores = [euro_preds.get(n, 0.1) for n in euro_numbers] - euro_quality = np.mean(euro_scores) - - # Pattern quality - pattern_quality = pattern_weight - - # Diversity - distances = [] - for i, n1 in enumerate(main_numbers): - for n2 in main_numbers[i+1:]: - distances.append(abs(n1 - n2)) - diversity_quality = min(np.mean(distances) / 10.0, 1.0) if distances else 0.5 - - quality = (main_quality * 0.4 + euro_quality * 0.25 + pattern_quality * 0.2 + diversity_quality * 0.15) - return min(quality, 1.0) - - def _print_tip_line(self, tip): - """Druckt Tip-Zeile.""" - main_str = '-'.join([f"{n:2d}" for n in tip['main_numbers']]) - euro_str = '-'.join([f"{n:2d}" for n in tip['euro_numbers']]) - - quality_emoji = "⭐" if tip['quality'] > 0.7 else "🌟" if tip['quality'] > 0.5 else "💫" - - print(f"{tip['tip_number']:2d} {main_str} {euro_str} " - f"{tip['strategy']:<14} {tip['main_ai_score']:.4f} {tip['euro_ai_score']:.4f} " - f"{tip['pattern_weight']:.4f} {tip['confidence']:.4f} {quality_emoji} {tip['quality']:.3f}") - - def _analyze_portfolio(self, tips): - """Analysiert Portfolio.""" - print(f"\n📊 PORTFOLIO ANALYSIS:") - print("=" * 70) - - strategy_stats = defaultdict(lambda: {'count': 0, 'avg_conf': [], 'avg_quality': []}) - - for tip in tips: - strategy = tip['strategy'] - strategy_stats[strategy]['count'] += 1 - strategy_stats[strategy]['avg_conf'].append(tip['confidence']) - strategy_stats[strategy]['avg_quality'].append(tip['quality']) - - for strategy, stats in strategy_stats.items(): - avg_conf = np.mean(stats['avg_conf']) - avg_qual = np.mean(stats['avg_quality']) - print(f"{strategy}:") - print(f" Count: {stats['count']}, Confidence: {avg_conf:.4f}, Quality: {avg_qual:.4f}") - - best_by_confidence = max(tips, key=lambda x: x['confidence']) - best_by_quality = max(tips, key=lambda x: x['quality']) - - print(f"\n⭐ TOP RECOMMENDATIONS:") - print(f"\n🎯 Highest Confidence:") - main_str = '-'.join([f"{n:2d}" for n in best_by_confidence['main_numbers']]) - euro_str = '-'.join([f"{n:2d}" for n in best_by_confidence['euro_numbers']]) - print(f" Tip #{best_by_confidence['tip_number']}: {main_str} + Euro {euro_str}") - print(f" Strategy: {best_by_confidence['strategy']}, Confidence: {best_by_confidence['confidence']:.4f}") - - print(f"\n💎 Highest Quality:") - main_str = '-'.join([f"{n:2d}" for n in best_by_quality['main_numbers']]) - euro_str = '-'.join([f"{n:2d}" for n in best_by_quality['euro_numbers']]) - print(f" Tip #{best_by_quality['tip_number']}: {main_str} + Euro {euro_str}") - print(f" Strategy: {best_by_quality['strategy']}, Quality: {best_by_quality['quality']:.4f}") - - def _update_strategy_weights(self, tips): - """Updated Strategie-Gewichte.""" - strategy_performance = defaultdict(list) - - for tip in tips: - perf_score = (tip['confidence'] * 0.6 + tip['quality'] * 0.4) - strategy_performance[tip['strategy']].append(perf_score) - - strategy_avg = {} - total = 0 - - for strategy in ['pure_ai', 'pure_pattern', 'hybrid_optimized', 'ensemble_best']: - strategy_key = { - 'pure_ai': 'PURE-AI', - 'pure_pattern': 'PURE-PATTERN', - 'hybrid_optimized': 'HYBRID-OPT', - 'ensemble_best': 'ENSEMBLE' - }[strategy] - - if strategy_key in strategy_performance: - avg = np.mean(strategy_performance[strategy_key]) - strategy_avg[strategy] = avg - total += avg - - if total > 0: - for strategy in self.strategy_weights: - if strategy in strategy_avg: - new_weight = strategy_avg[strategy] / total - self.strategy_weights[strategy] = ( - self.strategy_weights[strategy] * 0.7 + new_weight * 0.3 - ) - - print(f"\n🔄 UPDATED STRATEGY WEIGHTS:") - for strategy, weight in sorted(self.strategy_weights.items(), key=lambda x: x[1], reverse=True): - print(f" {strategy.upper()}: {weight:.1%}") - - def export_tips_to_csv(self, tips, filepath=None): - """Exportiert Tips als CSV.""" - if not filepath: - timestamp = datetime.datetime.now().strftime("%Y%m%d_%H%M%S") - filepath = f"eurojackpot_ultimate_tips_{timestamp}.csv" - - rows = [] - for tip in tips: - main_str = '-'.join([str(n) for n in tip['main_numbers']]) - euro_str = '-'.join([str(n) for n in tip['euro_numbers']]) - - rows.append({ - 'Tip_Number': tip['tip_number'], - 'Main_Numbers': main_str, - 'Euro_Numbers': euro_str, - 'Strategy': tip['strategy'], - 'Main_AI_Score': f"{tip['main_ai_score']:.4f}", - 'Euro_AI_Score': f"{tip['euro_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}") - return filepath - - -# ============================================================================ -# EUROJACKPOT-SPECIFIC SUPPORT CLASSES -# ============================================================================ - -class EurojackpotAIMLEngine: - """AI/ML Engine für Eurojackpot.""" - - def __init__(self, fast_mode=True): - self.models_main = {} - self.models_euro = {} - self.trained_models_main = {} - self.trained_models_euro = {} - self.scaler = StandardScaler() - self.is_trained = False - self.fast_mode = fast_mode - - def initialize(self, df, features_df, cache_path): - """Initialisiert AI/ML mit intelligentem Retraining.""" - self.cache_path = cache_path - self.data_file = None # Wird vom Generator gesetzt - - if not ML_AVAILABLE: - print(" ⚠️ ML not available - using fallback") - return - - # Setup models - n_estimators = 100 if self.fast_mode else 200 - self.models_main = { - 'random_forest': RandomForestRegressor( - n_estimators=n_estimators, max_depth=8, random_state=42, n_jobs=-1 - ), - 'gradient_boost': GradientBoostingRegressor( - n_estimators=n_estimators, learning_rate=0.1, max_depth=5, random_state=42 - ) - } - - self.models_euro = { - 'random_forest': RandomForestRegressor( - n_estimators=n_estimators, max_depth=6, random_state=42, n_jobs=-1 - ) - } - - # Intelligentes Retraining - main_cache = os.path.join(cache_path, "trained_models_main.pkl") - euro_cache = os.path.join(cache_path, "trained_models_euro.pkl") - needs_retrain = self._needs_retraining(main_cache, euro_cache) - - if os.path.exists(main_cache) and os.path.exists(euro_cache) and not needs_retrain: - print(" 📂 Loading cached models...", end=" ", flush=True) - self._load_models() - print("✅") - elif len(df) >= 50: - if needs_retrain: - print(" 🔄 Data updated - retraining models...") - self._train_models(df, features_df) - else: - print(" ⚠️ Insufficient data - using fallback") - - def _needs_retraining(self, main_cache, euro_cache): - """Prüft ob Retraining nötig ist.""" - if not os.path.exists(main_cache) or not os.path.exists(euro_cache): - return True - - # Prüfe ob CSV neuer als Cache - data_file = self.data_file or os.path.join( - os.path.dirname(self.cache_path), - "AlleEurojackpotzahlen.csv" - ) - - if os.path.exists(data_file): - # Verwende das neuere der beiden Caches - cache_mtime = max( - os.path.getmtime(main_cache), - os.path.getmtime(euro_cache) - ) - data_mtime = os.path.getmtime(data_file) - - if data_mtime > cache_mtime: - print(" 🔍 Detected updated data (CSV newer than cache)") - return True - - return False - - def _train_models(self, df, features_df): - """Trainiert Modelle.""" - print(" 🎯 Training AI models for Eurojackpot...") - - # Train for main numbers (top 40) - print(" Training main numbers...", end=" ", flush=True) - number_freq = Counter() - for _, row in df.iterrows(): - for col in ['Z1', 'Z2', 'Z3', 'Z4', 'Z5']: - number_freq[int(row[col])] += 1 - - top_main = [num for num, _ in number_freq.most_common(40)] - self.trained_models_main = self._train_number_set(df, features_df, top_main, 'main') - print("✅") - - # Train for euro numbers (all 12) - print(" Training euro numbers...", end=" ", flush=True) - euro_numbers = list(range(1, 13)) - self.trained_models_euro = self._train_number_set(df, features_df, euro_numbers, 'euro') - print("✅") - - self._save_models() - self.is_trained = True - print(f" ✅ AI models trained") - - def _train_number_set(self, df, features_df, numbers, number_type): - """Trainiert für Number-Set.""" - training_results = {} - models = self.models_main if number_type == 'main' else self.models_euro - - for number in numbers: - X, y = self._prepare_training_data(df, features_df, number, number_type) - - if len(X) < 20: - continue - - X_train, X_test, y_train, y_test = train_test_split( - X, y, test_size=0.2, random_state=42 - ) - - scaler = StandardScaler() - X_train_scaled = scaler.fit_transform(X_train) - X_test_scaled = scaler.transform(X_test) - - number_models = {} - - for model_name, model in models.items(): - try: - model.fit(X_train_scaled, y_train) - y_pred = model.predict(X_test_scaled) - score = r2_score(y_test, y_pred) - - number_models[model_name] = { - 'model': model, - 'scaler': scaler, - 'score': max(score, 0.1) - } - except: - pass - - if number_models: - training_results[number] = number_models - - return training_results - - def _prepare_training_data(self, df, features_df, number, number_type): - """Bereitet Training vor.""" - X = [] - y = [] - - window_size = 3 - cols = ['Z1', 'Z2', 'Z3', 'Z4', 'Z5'] if number_type == 'main' else ['SZ1', 'SZ2'] - - for i in range(window_size, min(len(features_df), 100)): - features = [] - for j in range(i - window_size, i): - row_features = features_df.iloc[j].values.tolist() - features.extend(row_features[:4]) - - X.append(features) - - current_numbers = [int(df.iloc[i][col]) for col in cols if col in df.iloc[i]] - y.append(1 if number in current_numbers else 0) - - return np.array(X), np.array(y) - - def predict_main_numbers(self, features_df): - """Vorhersage Main Numbers.""" - predictions = {} - - if not self.is_trained or not self.trained_models_main: - for num in range(1, 51): - predictions[num] = 0.2 + random.random() * 0.3 - return predictions - - current_features = self._get_current_features(features_df) - - for number in range(1, 51): - if number not in self.trained_models_main: - predictions[number] = 0.15 + (number % 10) * 0.03 - continue - - predictions[number] = self._predict_single_number( - number, self.trained_models_main[number], current_features - ) - - return predictions - - def predict_euro_numbers(self, features_df): - """Vorhersage Euro Numbers.""" - predictions = {} - - if not self.is_trained or not self.trained_models_euro: - for num in range(1, 13): - predictions[num] = 0.2 + random.random() * 0.3 - return predictions - - current_features = self._get_current_features(features_df) - - for number in range(1, 13): - if number not in self.trained_models_euro: - predictions[number] = 0.15 + (number % 5) * 0.05 - continue - - predictions[number] = self._predict_single_number( - number, self.trained_models_euro[number], current_features - ) - - return predictions - - def _predict_single_number(self, number, models, features): - """Einzelne Vorhersage.""" - ensemble_pred = 0 - total_weight = 0 - - for model_name, model_data in models.items(): - try: - model = model_data['model'] - scaler = model_data['scaler'] - score = model_data['score'] - - features_scaled = scaler.transform([features]) - pred = model.predict(features_scaled)[0] - - weight = score - ensemble_pred += pred * weight - total_weight += weight - except: - pass - - if total_weight > 0: - return np.clip(ensemble_pred / total_weight, 0, 1) - else: - return 0.2 + random.random() * 0.2 - - def _get_current_features(self, features_df): - """Current Features.""" - if len(features_df) == 0: - return [0.0] * 12 - - features = [] - for i in range(max(0, len(features_df)-3), len(features_df)): - row_features = features_df.iloc[i].values.tolist() - features.extend(row_features[:4]) - - while len(features) < 12: - features.append(0.0) - - return features[:12] - - def _save_models(self): - """Speichert Modelle.""" - os.makedirs(self.cache_path, exist_ok=True) - - with open(os.path.join(self.cache_path, "trained_models_main.pkl"), 'wb') as f: - pickle.dump(self.trained_models_main, f) - - with open(os.path.join(self.cache_path, "trained_models_euro.pkl"), 'wb') as f: - pickle.dump(self.trained_models_euro, f) - - def _load_models(self): - """Lädt Modelle.""" - try: - with open(os.path.join(self.cache_path, "trained_models_main.pkl"), 'rb') as f: - self.trained_models_main = pickle.load(f) - - with open(os.path.join(self.cache_path, "trained_models_euro.pkl"), 'rb') as f: - self.trained_models_euro = pickle.load(f) - - self.is_trained = True - except: - pass - - -class EurojackpotPatternEngine: - """Pattern Engine für Eurojackpot.""" - - def __init__(self): - self.pattern_frequencies = Counter() - self.pattern_weights = {} - self.number_patterns = defaultdict(list) - - def initialize(self, df): - """Initialisiert.""" - self._analyze_patterns(df) - self._analyze_number_patterns(df) - - def _analyze_patterns(self, df): - """Analysiert Patterns (5 Zahlen aus 50).""" - for _, row in df.iterrows(): - numbers = sorted([row['Z1'], row['Z2'], row['Z3'], row['Z4'], row['Z5']]) - pattern = self._get_pattern(numbers) - self.pattern_frequencies[pattern] += 1 - - total = sum(self.pattern_frequencies.values()) - for pattern, count in self.pattern_frequencies.items(): - self.pattern_weights[pattern] = count / total if total > 0 else 0 - - def _analyze_number_patterns(self, df): - """Analysiert Zahlen-Muster.""" - for _, row in df.tail(100).iterrows(): - numbers = [row['Z1'], row['Z2'], row['Z3'], row['Z4'], row['Z5']] - for num in numbers: - self.number_patterns[num].append(numbers) - - def _get_pattern(self, numbers): - """Pattern (5 Zahlen -> 5 Bereiche à 10).""" - pattern = "" - for num in numbers: - if num <= 10: - pattern += "N" - elif num <= 20: - pattern += "M1" - elif num <= 30: - pattern += "M2" - elif num <= 40: - pattern += "H1" - else: - pattern += "H2" - return pattern - - def calculate_pattern_weight(self, numbers): - """Pattern-Gewicht.""" - pattern = self._get_pattern(sorted(numbers)) - return self.pattern_weights.get(pattern, 0.01) - - def get_top_patterns(self, count): - """Top Patterns.""" - return [p for p, _ in self.pattern_frequencies.most_common(count)] - - def generate_for_pattern(self, target_pattern, seed): - """Generiert für Pattern.""" - random.seed(42 + seed * 19) - - # Simplified: just use ranges - ranges = { - 'N': list(range(1, 11)), - 'M1': list(range(11, 21)), - 'M2': list(range(21, 31)), - 'H1': list(range(31, 41)), - 'H2': list(range(41, 51)) - } - - selected = [] - - # Parse pattern and select - # For simplicity, distribute evenly - all_ranges = list(ranges.values()) - for i in range(5): - range_pool = all_ranges[i % len(all_ranges)] - available = [n for n in range_pool if n not in selected] - if available: - selected.append(random.choice(available)) - - while len(selected) < 5: - available = [n for n in range(1, 51) if n not in selected] - if available: - selected.append(random.choice(available)) - - return sorted(selected[:5]) - - def get_number_pattern_score(self, number): - """Pattern-Score.""" - if number not in self.number_patterns: - return 0.1 - - frequency = len(self.number_patterns[number]) - max_freq = max(len(patterns) for patterns in self.number_patterns.values()) if self.number_patterns else 1 - - return min(frequency / max_freq, 1.0) if max_freq > 0 else 0.1 - - -class EurojackpotHybridOptimizer: - """Hybrid Optimizer für Eurojackpot.""" - - def __init__(self, fast_mode=True): - self.ai_engine = None - self.pattern_engine = None - self.fast_mode = fast_mode - self.iterations = 50 if fast_mode else 150 - - def initialize(self, ai_engine, pattern_engine): - """Initialisiert.""" - self.ai_engine = ai_engine - self.pattern_engine = pattern_engine - - def optimize(self, seed, main_preds, euro_preds): - """Optimization.""" - # Ensure different results for each tip by using a unique seed combination - random.seed(42 + seed * 29 + seed * seed) - - best_score = -1 - best_main = None - best_euro = None - best_main_ai = 0 - best_euro_ai = 0 - best_pattern = 0 - - for attempt in range(self.iterations): - main_candidate = self._generate_main_candidate(main_preds, attempt, seed) - euro_candidate = self._generate_euro_candidate(euro_preds, attempt, seed) - - main_ai_score = np.mean([main_preds.get(n, 0.1) for n in main_candidate]) - euro_ai_score = np.mean([euro_preds.get(n, 0.1) for n in euro_candidate]) - pattern_weight = self.pattern_engine.calculate_pattern_weight(main_candidate) - - diversity = self._calculate_diversity(main_candidate) - - combined_score = ( - main_ai_score * 0.4 + - euro_ai_score * 0.25 + - pattern_weight * 0.25 + - diversity * 0.1 - ) - - if combined_score > best_score: - best_score = combined_score - best_main = main_candidate - best_euro = euro_candidate - best_main_ai = main_ai_score - best_euro_ai = euro_ai_score - best_pattern = pattern_weight - - return { - 'main_numbers': best_main if best_main else sorted(random.sample(range(1, 51), 5)), - 'euro_numbers': best_euro if best_euro else sorted(random.sample(range(1, 13), 2)), - 'main_ai_score': best_main_ai, - 'euro_ai_score': best_euro_ai, - 'pattern_weight': best_pattern, - 'confidence': best_score - } - - def _generate_main_candidate(self, main_preds, attempt, seed): - """Main Kandidat.""" - # Add attempt-based variation to ensure diversity - random.seed(42 + seed * 29 + attempt * 7) - - if attempt < self.iterations // 3: - sorted_preds = sorted(main_preds.items(), key=lambda x: x[1], reverse=True) - candidates = [num for num, _ in sorted_preds[:30]] - return sorted(random.sample(candidates, min(5, len(candidates)))) - - elif attempt < 2 * self.iterations // 3: - top_patterns = self.pattern_engine.get_top_patterns(5) - if top_patterns: - pattern = random.choice(top_patterns) - return self.pattern_engine.generate_for_pattern(pattern, seed + attempt) - - sorted_preds = sorted(main_preds.items(), key=lambda x: x[1], reverse=True) - ai_nums = [num for num, _ in sorted_preds[:20]] - - selected = random.sample(ai_nums, min(3, len(ai_nums))) - remaining = [n for n in range(1, 51) if n not in selected] - selected.extend(random.sample(remaining, 5 - len(selected))) - - return sorted(selected[:5]) - - def _generate_euro_candidate(self, euro_preds, attempt, seed): - """Euro Kandidat.""" - # Add variation for euro numbers too - random.seed(42 + seed * 17 + attempt * 5) - - sorted_euro = sorted(euro_preds.items(), key=lambda x: x[1], reverse=True) - - # Vary the candidate pool based on attempt - if attempt < self.iterations // 3: - top_euros = [num for num, _ in sorted_euro[:4]] # Top 4 - elif attempt < 2 * self.iterations // 3: - top_euros = [num for num, _ in sorted_euro[:8]] # Top 8 - else: - top_euros = [num for num, _ in sorted_euro[:10]] # Top 10 - - return sorted(random.sample(top_euros, min(2, len(top_euros)))) - - def _calculate_diversity(self, numbers): - """Diversität.""" - if len(numbers) < 2: - return 0.5 - - distances = [] - for i, n1 in enumerate(numbers): - for n2 in numbers[i+1:]: - distances.append(abs(n1 - n2)) - - avg_distance = np.mean(distances) - return min(avg_distance / 12.0, 1.0) - - -class EurojackpotFeatureEngineer: - """Feature Engineering für Eurojackpot.""" - - def create_features(self, df): - """Erstellt Features.""" - features_list = [] - - for i in range(len(df)): - features = self._extract_features(df, i) - features_list.append(features) - - return pd.DataFrame(features_list) - - def _extract_features(self, df, idx): - """Extrahiert Features.""" - features = {} - - for window in [5, 10]: - start = max(0, idx - window) - hist = df.iloc[start:idx] - - if len(hist) > 0: - all_nums = [] - for _, row in hist.iterrows(): - all_nums.extend([row['Z1'], row['Z2'], row['Z3'], row['Z4'], row['Z5']]) - features[f'freq_{window}'] = len(set(all_nums)) / (window * 5) if window > 0 else 0 - else: - features[f'freq_{window}'] = 0 - - if 'datum' in df.columns and pd.notna(df.iloc[idx].get('datum')): - date = df.iloc[idx]['datum'] - features['day_of_week'] = date.dayofweek - features['seasonal'] = np.sin(2 * np.pi * date.dayofyear / 365) - else: - features['day_of_week'] = 0 - features['seasonal'] = 0 - - return features - - -class EurojackpotRealTimeLearner: - """Real-Time Learning für Eurojackpot.""" - - def __init__(self): - self.learning_rate = 0.1 - self.adjustments_main = {} - self.adjustments_euro = {} - self.stats = defaultdict(int) - - def initialize(self, features_df): - """Initialisiert.""" - self.features_df = features_df - - def adjust_main_predictions(self, predictions): - """Passt Main an.""" - adjusted = {} - - for number, pred in predictions.items(): - adjustment = self.adjustments_main.get(number, 0) - adjusted[number] = np.clip(pred + adjustment * self.learning_rate, 0, 1) - - return adjusted - - def adjust_euro_predictions(self, predictions): - """Passt Euro an.""" - adjusted = {} - - for number, pred in predictions.items(): - adjustment = self.adjustments_euro.get(number, 0) - adjusted[number] = np.clip(pred + adjustment * self.learning_rate, 0, 1) - - return adjusted - - def learn_from_result(self, drawing): - """Lernt aus Ziehung.""" - actual_main = [drawing[f'Z{i}'] for i in range(1, 6)] - actual_euro = [drawing['SZ1'], drawing['SZ2']] - - # Main - for number in range(1, 51): - if number not in self.adjustments_main: - self.adjustments_main[number] = 0 - - if number in actual_main: - self.adjustments_main[number] += 0.01 - else: - self.adjustments_main[number] -= 0.005 - - self.adjustments_main[number] *= 0.99 - - # Euro - for number in range(1, 13): - if number not in self.adjustments_euro: - self.adjustments_euro[number] = 0 - - if number in actual_euro: - self.adjustments_euro[number] += 0.01 - else: - self.adjustments_euro[number] -= 0.005 - - self.adjustments_euro[number] *= 0.99 - - self.stats['cycles'] += 1 - - def get_stats(self): - """Stats.""" - return dict(self.stats) - - -class EurojackpotPerformanceTracker: - """Performance Tracking für Eurojackpot.""" - - def __init__(self): - self.generated_tips = [] - self.evaluations = [] - - def log_generated_tips(self, tips): - """Loggt Tips.""" - self.generated_tips.extend(tips) - - def evaluate_predictions(self, drawing): - """Evaluiert.""" - actual_main = [drawing[f'Z{i}'] for i in range(1, 6)] - actual_euro = [drawing['SZ1'], drawing['SZ2']] - - if self.generated_tips: - recent = self.generated_tips[-10:] - - for tip in recent: - main_matches = len(set(tip['main_numbers']) & set(actual_main)) - euro_matches = len(set(tip['euro_numbers']) & set(actual_euro)) - - self.evaluations.append({ - 'main_matches': main_matches, - 'euro_matches': euro_matches, - 'strategy': tip['strategy'], - 'timestamp': datetime.datetime.now() - }) - - def get_statistics(self): - """Stats.""" - return { - 'total_tips': len(self.generated_tips), - 'total_evaluations': len(self.evaluations) - } - - -# ============================================================================ -# MAIN -# ============================================================================ - -def main(): - """Main Function.""" - print("🚀 ULTIMATE AI-ML HYBRID EUROJACKPOT GENERATOR V2.1") - print("⚡ OPTIMIZED VERSION with Progress Indicators") - print("=" * 70) - - data_path = "/Users/sebastianfrohlich/Library/Mobile Documents/com~apple~CloudDocs/Jupyter Notebooks/AlleEurojackpotzahlen.csv" - - try: - # Initialize with fast mode - generator = UltimateAIMLEurojackpotGenerator(data_path, fast_mode=True) - - # Generate Tips - tips = generator.generate_ultimate_tips(10) - - if tips: - print("\n🏆 GENERATION COMPLETED!") - print("=" * 70) - print(f"✅ {len(tips)} Ultimate Eurojackpot Tips generated") - print(f"🧠 AI/ML: {'✅' if ML_AVAILABLE else '⚠️'}") - print(f"🎨 Patterns: ✅") - print(f"⚡ Optimization: ✅") - print(f"📚 Learning: ✅") - - # Export option - export = input("\n💾 Tips als CSV exportieren? (j/n): ").lower().strip() - if export in ['j', 'ja', 'y', 'yes']: - generator.export_tips_to_csv(tips) - - print("\n💡 EUROJACKPOT ADVANTAGES:") - print(" 🎰 5 aus 50 + 2 aus 12 optimiert") - print(" 🔬 4 Strategien: Pure-AI, Pure-Pattern, Hybrid, Ensemble") - print(" 🧠 Separate AI für Hauptzahlen + Eurozahlen") - print(" 🎨 Pattern-Analyse für 5er-Kombinationen") - print(" ⚡ Multi-Objective Optimization") - print(" 📚 Real-Time Learning") - print(" ⚡ Fast Mode: Optimierte Performance") - - except Exception as e: - print(f"❌ Error: {e}") - import traceback - traceback.print_exc() - - -if __name__ == "__main__": - random.seed(42) - np.random.seed(42) - main() diff --git a/scripts/utils/create_example_files.py b/scripts/utils/create_example_files.py deleted file mode 100644 index abdbdfa..0000000 --- a/scripts/utils/create_example_files.py +++ /dev/null @@ -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:") diff --git a/scripts/utils/eurojackpot_processor.py b/scripts/utils/eurojackpot_processor.py deleted file mode 100644 index a08c395..0000000 --- a/scripts/utils/eurojackpot_processor.py +++ /dev/null @@ -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() diff --git a/scripts/utils/eurojackpot_processor_fixed.py b/scripts/utils/eurojackpot_processor_fixed.py deleted file mode 100644 index 6ea4cca..0000000 --- a/scripts/utils/eurojackpot_processor_fixed.py +++ /dev/null @@ -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() diff --git a/scripts/utils/eurojackpot_simple.py b/scripts/utils/eurojackpot_simple.py deleted file mode 100644 index a5e0fbb..0000000 --- a/scripts/utils/eurojackpot_simple.py +++ /dev/null @@ -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" - ) diff --git a/scripts/utils/update_historical_data.py b/scripts/utils/update_historical_data.py deleted file mode 100644 index b1cb881..0000000 --- a/scripts/utils/update_historical_data.py +++ /dev/null @@ -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() diff --git a/scripts/utils/zahlen_umschluesseln.py b/scripts/utils/zahlen_umschluesseln.py deleted file mode 100644 index 0ad5b2d..0000000 --- a/scripts/utils/zahlen_umschluesseln.py +++ /dev/null @@ -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()