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