Initial commit: existing turf_saas codebase

Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
ML Engineer
2026-04-25 17:18:43 +02:00
commit ed07c8a3d1
137 changed files with 36398 additions and 0 deletions

262
weather_module_v2.py Executable file
View File

@@ -0,0 +1,262 @@
#!/usr/bin/env python3
"""
Weather Module v2 - With Database Storage
Tracks weather history for performance analysis
"""
import requests
from datetime import datetime
import sqlite3
DB_PATH = "/home/h3r7/turf_scraper/turf.db"
# Hippodrome coordinates
HIPPODROMES = {
'auteuil': (48.8718, 2.2525),
'chantilly': (49.1939, 2.4744),
'deauville': (49.3563, 0.0775),
'vincennes': (48.8414, 2.4375),
'longchamp': (48.8641, 2.2372),
'saint-cloud': (48.8419, 2.1039),
'pau': (43.2917, -0.3708),
'cagnes-sur-mer': (43.6689, 7.1914),
'lyon-parilly': (45.7378, 4.8092),
'lyon': (45.7378, 4.8092),
'marseille': (43.2964, 5.3695),
'cagnes': (43.6689, 7.1914),
'le croise larroche': (50.6692, 3.0775),
'mons': (50.4547, 3.9522),
}
def init_weather_db():
"""Initialize weather table"""
conn = sqlite3.connect(DB_PATH)
c = conn.cursor()
c.execute('''
CREATE TABLE IF NOT EXISTS weather (
id INTEGER PRIMARY KEY AUTOINCREMENT,
date TEXT NOT NULL,
hippodrome TEXT,
temperature REAL,
humidity INTEGER,
wind_speed REAL,
precipitation REAL,
weather_code INTEGER,
ground_condition TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
)
''')
c.execute('''
CREATE TABLE IF NOT EXISTS horse_weather_performance (
id INTEGER PRIMARY KEY AUTOINCREMENT,
date TEXT,
race_date TEXT,
horse_name TEXT,
position INTEGER,
hippodrome TEXT,
temperature REAL,
ground_condition TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
)
''')
conn.commit()
conn.close()
print("Weather tables initialized!")
def get_weather(hippodrome, date=None):
"""Get weather from Open-Meteo API"""
hippo_key = hippodrome.lower().strip()
# Try to find matching hippodrome
coords = None
for name, coord in HIPPODROMES.items():
if name in hippo_key or hippo_key in name:
coords = coord
break
if not coords:
return {'error': f'Hippodrome non trouvé: {hippodrome}'}
lat, lon = coords
url = "https://api.open-meteo.com/v1/forecast"
params = {
'latitude': lat,
'longitude': lon,
'current': 'temperature_2m,relative_humidity_2m,precipitation,rain,weather_code,wind_speed_10m',
'timezone': 'Europe/Paris'
}
try:
r = requests.get(url, params=params, timeout=10)
data = r.json()
if 'current' in data:
current = data['current']
weather = {
'hippodrome': hippodrome,
'temperature': current.get('temperature_2m'),
'humidity': current.get('relative_humidity_2m'),
'precipitation': current.get('precipitation'),
'rain': current.get('rain'),
'weather_code': current.get('weather_code'),
'wind_speed': current.get('wind_speed_10m'),
'ground_condition': get_ground_condition(current),
'timestamp': datetime.now().isoformat()
}
return weather
except Exception as e:
return {'error': str(e)}
return {'error': 'Unknown error'}
def get_ground_condition(weather_data):
"""Determine ground condition"""
if isinstance(weather_data, dict):
precip = weather_data.get('precipitation', 0)
else:
precip = 0
if precip > 10:
return 'TRES_LOURD'
elif precip > 5:
return 'LOURD'
elif precip > 1:
return 'SOUPLE'
else:
return 'BON'
def weather_code_to_desc(code):
"""Weather code to description"""
codes = {
0: "Ciel dégagé", 1: "Mainly clear", 2: "Partly cloudy", 3: "Overcast",
45: "Brouillard", 48: "Brouillard",
51: "Bruine légère", 53: "Bruine", 55: "Bruine dense",
61: "Pluie légère", 63: "Pluie", 65: "Pluie forte",
71: "Neige légère", 73: "Neige", 75: "Neige forte",
80: "Averses", 81: "Averses", 82: "Averses fortes",
95: "Orage", 96: "Orage grêle",
}
return codes.get(code, f"Code {code}")
def save_weather(date, hippodrome, weather):
"""Save weather to database"""
conn = sqlite3.connect(DB_PATH)
c = conn.cursor()
c.execute('''
INSERT INTO weather (date, hippodrome, temperature, humidity, wind_speed, precipitation, weather_code, ground_condition)
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
''', (
date,
hippodrome,
weather.get('temperature'),
weather.get('humidity'),
weather.get('wind_speed'),
weather.get('precipitation'),
weather.get('weather_code'),
weather.get('ground_condition')
))
conn.commit()
conn.close()
print(f"Weather saved: {hippodrome} - {weather.get('ground_condition')}")
def save_horse_weather_performance(date, race_date, horse_name, position, hippodrome, temperature, ground_condition):
"""Save horse performance with weather"""
conn = sqlite3.connect(DB_PATH)
c = conn.cursor()
c.execute('''
INSERT INTO horse_weather_performance (date, race_date, horse_name, position, hippodrome, temperature, ground_condition)
VALUES (?, ?, ?, ?, ?, ?, ?)
''', (date, race_date, horse_name, position, hippodrome, temperature, ground_condition))
conn.commit()
conn.close()
def get_horse_weather_stats(horse_name):
"""Get horse performance by weather conditions"""
conn = sqlite3.connect(DB_PATH)
c = conn.cursor()
c.execute('''
SELECT
ground_condition,
COUNT(*) as races,
SUM(CASE WHEN position <= 3 THEN 1 ELSE 0 END) as podiums,
ROUND(CAST(SUM(CASE WHEN position <= 3 THEN 1 ELSE 0 END) AS FLOAT) / COUNT(*) * 100, 1) as podium_rate
FROM horse_weather_performance
WHERE horse_name = ?
GROUP BY ground_condition
''', (horse_name,))
results = c.fetchall()
conn.close()
stats = {}
for row in results:
stats[row[0]] = {
'races': row[1],
'podiums': row[2],
'podium_rate': row[3]
}
return stats
def analyze_weather_advantage(horse_name):
"""Analyze horse performance by weather"""
stats = get_horse_weather_stats(horse_name)
if not stats:
return {'message': 'Pas de données météo pour ce cheval'}
# Find best ground condition
best = None
best_rate = 0
for condition, data in stats.items():
if data['podium_rate'] > best_rate:
best_rate = data['podium_rate']
best = condition
return {
'horse': horse_name,
'best_ground': best,
'best_rate': best_rate,
'all_conditions': stats
}
# Test
if __name__ == "__main__":
init_weather_db()
print("\n" + "="*50)
print("WEATHER MODULE v2 - TEST")
print("="*50)
# Get weather for today's races
hippodromes = ['Auteuil', 'Vincennes', 'Pau', 'Cagnes-sur-Mer']
today = datetime.now().strftime('%Y-%m-%d')
for hippo in hippodromes:
w = get_weather(hippo)
if 'error' not in w:
print(f"\n{hippo}:")
print(f" {w.get('temperature')}°C, {w.get('humidity')}%, {w.get('wind_speed')} km/h")
print(f" Terrain: {w.get('ground_condition')}")
save_weather(today, hippo, w)
# Test horse weather analysis
print("\n" + "="*50)
print("HORSE WEATHER ANALYSIS TEST")
print("="*50)
# Save some test data
save_horse_weather_performance(today, today, 'PASSIONATA', 1, 'Auteuil', 13, 'BON')
save_horse_weather_performance(today, today, 'PASSIONATA', 2, 'Vincennes', 10, 'SOUPLE')
result = analyze_weather_advantage('PASSIONATA')
print(f"\nPASSIONATA: {result}")