Add all local circuit work — year-by-year SVGs and tooling
This commit is contained in:
+338
@@ -0,0 +1,338 @@
|
||||
import requests
|
||||
import json
|
||||
import time
|
||||
import os
|
||||
|
||||
# Please convert this list into a dictionary of country -> locality/city -> Circuit name -> layouts (some circuits have multiple layouts)
|
||||
# it should be available_circuits = { "Argentina": { "Buenos Aires": { "Autódromo Juan y Oscar Gálvez": {1953: "Argentina - Buenos Aires - Autódromo Juan y Oscar Gálvez - 1953-1960.geo.json", 1954: "Argentina - Buenos Aires - Autódromo Juan y Oscar Gálvez - 1953-1960.geo.json", ...} } } }
|
||||
available_circuits = [
|
||||
"Argentina - Buenos Aires - Autódromo Juan y Oscar Gálvez - 1953-1960.geo.json",
|
||||
"France - Rouen - Circuit de Rouen-Les-Essarts - 1957-1968.geo.json",
|
||||
"Singapore - Singapore - Marina Bay Street Circuit - 2008-.geo.json",
|
||||
"Argentina - Buenos Aires - Autódromo Juan y Oscar Gálvez - 1971-1973.geo.json",
|
||||
"Germany - Berlin - AVUS - 1921-1959.geo.json",
|
||||
"South Africa - East London - Prince George Circuit - 1934-1967.geo.json",
|
||||
"Argentina - Buenos Aires - Autódromo Juan y Oscar Gálvez - 1974-1981.geo.json",
|
||||
"Germany - Hockenheim - Hockenheimring - 1932-.geo.json",
|
||||
"South Africa - Kyalami - Kyalami Grand Prix Circuit - 1961-1985.geo.json",
|
||||
"Argentina - Buenos Aires - Autódromo Juan y Oscar Gálvez - 1995-1998.geo.json",
|
||||
"Germany - Nürburg - Nürburgring - 1927-.geo.json",
|
||||
"South Africa - Kyalami - Kyalami Grand Prix Circuit - 1992-1993.geo.json",
|
||||
"Australia - Adelaide - Adelaide Street Circuit - 1985-1995.geo.json",
|
||||
"Great Britain - Aintree - Aintree Circuit - 1954-1962.geo.json",
|
||||
"Spain - Barcelona - Circuit de Barcelona-Catalunya - 1991-.geo.json",
|
||||
"Australia - Melbourne - Albert Park Circuit - 1953-.geo.json",
|
||||
"Great Britain - Brands Hatch - Brands Hatch Circuit - 1964-1974.geo.json",
|
||||
"Spain - Jarama - Circuito del Jarama - 1967-1981.geo.json",
|
||||
"Austria - Spielberg - A1 Ring - 1997-2003.geo.json",
|
||||
"Great Britain - Brands Hatch - Brands Hatch Circuit - 1976-1987.geo.json",
|
||||
"Spain - Jerez - Circuito de Jerez - 1985-1991.geo.json",
|
||||
"Austria - Spielberg - Österreichring - 1969-1976.geo.json",
|
||||
"Great Britain - Silverstone - Silverstone Circuit - 1948-.geo.json",
|
||||
"Spain - Jerez - Circuito de Jerez - 1994-.geo.json",
|
||||
"Austria - Spielberg - Österreichring - 1977-1987.geo.json",
|
||||
"Hungary - Budapest - Hungaroring - 1986-.geo.json",
|
||||
"Spain - Montjuïc - Montjuïc Circuit - 1969-1975.geo.json",
|
||||
"Austria - Spielberg - Red Bull Ring - 2014-.geo.json",
|
||||
"Italy - Imola - Autodromo Enzo e Dino Ferrari - 1953-.geo.json",
|
||||
"Spain - Pedralbes - Pedralbes Circuit - 1946-1954.geo.json",
|
||||
"Austria - Zeltweg - Österreichring - 1963-1968.geo.json",
|
||||
"Italy - Monza - Autodromo Nazionale Monza - 1922-.geo.json",
|
||||
"Spain - Valencia - Valencia Street Circuit - 2008-2012.geo.json",
|
||||
"Azerbaijan - Baku - Baku City Circuit - 2016-.geo.json",
|
||||
"Italy - Pescara - Pescara Circuit - 1924-1957.geo.json",
|
||||
"Sweden - Anderstorp - Scandinavian Raceway - 1968-1977.geo.json",
|
||||
"Bahrain - Sakhir - Bahrain International Circuit - 2002-.geo.json",
|
||||
"Italy - Scarperia e San Piero - Autodromo Internazionale del Mugello - 1914-.geo.json",
|
||||
"Sweden - Anderstorp - Scandinavian Raceway - 1978-1997.geo.json",
|
||||
"Bahrain - Sakhir - Bahrain International Circuit - 2010.geo.json",
|
||||
"Japan - Aida - TI Circuit Aida - 1990-1997.geo.json",
|
||||
"Switzerland - Bern - Circuit Bremgarten - 1934-1954.geo.json",
|
||||
"Belgium - Nivelles - Circuit Nivelles-Baulers - 1971-1974.geo.json",
|
||||
"Japan - Fuji - Fuji Speedway - 1976-1977.geo.json",
|
||||
"Turkey - Istanbul - Intercity Istanbul Park - 2005-.geo.json",
|
||||
"Belgium - Spa Francorchamps - Circuit de Spa-Francorchamps - 1950-1978.geo.json",
|
||||
"Japan - Fuji - Fuji Speedway - 2007-.geo.json",
|
||||
"United Arab Emirates - Yas Marina - Yas Marina Circuit - 2009-.geo.json",
|
||||
"Belgium - Spa Francorchamps - Circuit de Spa-Francorchamps - 1983-.geo.json",
|
||||
"Japan - Suzuka - Suzuka International Racing Course - 1962-.geo.json",
|
||||
"USA - Austin - Circuit of the Americas - 2012-.geo.json",
|
||||
"Belgium - Zolder - Circuit Zolder - 1963-.geo.json",
|
||||
"Malaysia - Sepang - Sepang International Circuit - 1999-.geo.json",
|
||||
"USA - Dallas - Fair Park - 1984.geo.json",
|
||||
"Brazil - Jacarepaguá - Autódromo Internacional Nelson Piquet - 1977-.geo.json",
|
||||
"Mexico - Magdalena Mixhuca - Autódromo Magdalena Mixhuca - 1959-1970.geo.json",
|
||||
"USA - Detroit - Detroit Street Circuit - 1982-1988.geo.json",
|
||||
"Brazil - Sao Paulo - Autódromo José Carlos Pace - Interlagos - 1940-.geo.json",
|
||||
"Mexico - Mexico City - Autódromo Hermanos Rodríguez - 1962-.geo.json",
|
||||
"USA - Indianapolis - Indianapolis Motor Speedway - 1909-.geo.json",
|
||||
"Canada - Montreal - Circuit Gilles-Villeneuve - 1978-.geo.json",
|
||||
"Monaco - Monaco - Circuit de Monaco - 1929-.geo.json",
|
||||
"USA - Las Vegas - Las Vegas Street Circuit - 2023-.geo.json",
|
||||
"Canada - Mont-Tremblant - Circuit Mont-Tremblant - 1964-1970.geo.json",
|
||||
"Morocco - Casablanca - Ain-Diab Circuit - 1957-1958.geo.json",
|
||||
"USA - Long Beach - Long Beach Grand Prix Circuit - 1976-1981.geo.json",
|
||||
"Canada - Mosport - Mosport Park - 1961-1977.geo.json",
|
||||
"Netherlands - Zandvoort - Circuit Zandvoort - 1948-1971.geo.json",
|
||||
"USA - Long Beach - Long Beach Grand Prix Circuit - 1982.geo.json",
|
||||
"China - Shanghai - Shanghai International Circuit - 2004-.geo.json",
|
||||
"Netherlands - Zandvoort - Circuit Zandvoort - 1972-1985.geo.json",
|
||||
"USA - Long Beach - Long Beach Grand Prix Circuit - 1983.geo.json",
|
||||
"France - Clermont-Ferrand - Circuit de Charade - 1958-1988.geo.json",
|
||||
"Netherlands - Zandvoort - Circuit Zandvoort - 2021-.geo.json",
|
||||
"USA - Miami - Miami International Autodrome - 2022-.geo.json",
|
||||
"France - Dijon-Prenois - Circuit de Dijon-Prenois - 1972-1984.geo.json",
|
||||
"Portugal - Estoril - Autódromo do Estoril - 1972-.geo.json",
|
||||
"USA - Phoenix - Phoenix Street Circuit - 1989-1990.geo.json",
|
||||
"France - Le Castellet - Circuit Paul Ricard - 1969-.geo.json",
|
||||
"Portugal - Monsanto - Monsanto Park Circuit - 1954-1959.geo.json",
|
||||
"USA - Phoenix - Phoenix Street Circuit - 1991.geo.json",
|
||||
"France - Le Mans - Circuit de la Sarthe - 1923-1966.geo.json",
|
||||
"Portugal - Oporto - Circuito da Boavista - 1958-1960.geo.json",
|
||||
"USA - Riverside - Riverside International Raceway - 1960.geo.json",
|
||||
"France - Magny-Cours - Circuit de Nevers Magny-Cours - 1960-.geo.json",
|
||||
"Portugal - Portimão - Autódromo Internacional do Algarve - 2008-.geo.json",
|
||||
"USA - Sebring - Sebring International Raceway - 1959.geo.json",
|
||||
"France - Reims - Circuit de Reims-Gueux - 1926-1951.geo.json",
|
||||
"Qatar - Lusail - Losail International Circuit - 2004-.geo.json",
|
||||
"USA - Watkins Glen - Watkins Glen International - 1948-1980.geo.json",
|
||||
"France - Reims - Circuit de Reims-Gueux - 1952-.geo.json",
|
||||
"Russia - Sochi - Sochi Autodrom - 2014-.geo.json",
|
||||
"France - Rouen - Circuit de Rouen-Les-Essarts - 1952.geo.json",
|
||||
"Saudi Arabia - Jeddah - Jeddah Corniche Circuit - 2021-.geo.json"
|
||||
]
|
||||
|
||||
def fetch_all_grand_prix_data():
|
||||
"""
|
||||
Fetches all Formula 1 Grand Prix data from the Ergast API across multiple pages
|
||||
and returns the races.
|
||||
"""
|
||||
base_url = "https://ergast.com/api/f1.json"
|
||||
limit = 100 # Maximum number of results per page
|
||||
offset = 0
|
||||
all_races = []
|
||||
total_races = None
|
||||
|
||||
print("Fetching Grand Prix data from Ergast API...")
|
||||
|
||||
while True:
|
||||
# Construct URL with pagination parameters
|
||||
url = f"{base_url}?limit={limit}&offset={offset}"
|
||||
print(f"Fetching data from offset {offset}...")
|
||||
|
||||
# Add a small delay to avoid hitting rate limits
|
||||
time.sleep(0.5)
|
||||
|
||||
# Make the request
|
||||
response = requests.get(url)
|
||||
|
||||
# Check if request was successful
|
||||
if response.status_code != 200:
|
||||
print(f"Error fetching data: HTTP {response.status_code}")
|
||||
print(response.text)
|
||||
break
|
||||
|
||||
# Parse the JSON response
|
||||
data = response.json()
|
||||
|
||||
# Get total number of races if not already set
|
||||
if total_races is None:
|
||||
total_races = int(data['MRData']['total'])
|
||||
print(f"Total races to fetch: {total_races}")
|
||||
|
||||
# Extract the races from this page
|
||||
races = data['MRData']['RaceTable'].get('Races', [])
|
||||
all_races.extend(races)
|
||||
|
||||
# Update the offset for the next page
|
||||
offset += limit
|
||||
|
||||
# Check if we've fetched all data
|
||||
if offset >= total_races:
|
||||
break
|
||||
|
||||
print(f"Successfully fetched {len(all_races)} races.")
|
||||
return all_races
|
||||
|
||||
def get_circuit_file_mapping():
|
||||
"""
|
||||
Creates a mapping of circuit information to corresponding circuit GeoJSON files.
|
||||
"""
|
||||
circuit_mapping = {}
|
||||
|
||||
# Get circuit files from the circuits directory
|
||||
circuits_dir = "circuits"
|
||||
if os.path.exists(circuits_dir):
|
||||
circuit_files = [f for f in os.listdir(circuits_dir) if f.endswith('.geo.json')]
|
||||
|
||||
for file_name in circuit_files:
|
||||
file_path = os.path.join(circuits_dir, file_name)
|
||||
try:
|
||||
with open(file_path, 'r', encoding='utf-8') as f:
|
||||
data = json.load(f)
|
||||
|
||||
if 'features' in data and len(data['features']) > 0:
|
||||
feature = data['features'][0]
|
||||
if 'properties' in feature:
|
||||
props = feature['properties']
|
||||
|
||||
if 'id' in props and 'Name' in props and 'Location' in props and 'seasons' in props:
|
||||
circuit_id = props['id']
|
||||
circuit_name = props['Name']
|
||||
location = props['Location']
|
||||
seasons = props['seasons']
|
||||
|
||||
# Create a key for each season this circuit was used
|
||||
for season in seasons:
|
||||
key = (circuit_name, location, season)
|
||||
circuit_mapping[key] = file_name
|
||||
except Exception as e:
|
||||
print(f"Error processing circuit file {file_name}: {e}")
|
||||
|
||||
return circuit_mapping
|
||||
|
||||
def create_grand_prix_data(races, circuit_mapping):
|
||||
"""
|
||||
Create a dictionary of grand prix organized by name and season.
|
||||
|
||||
Format:
|
||||
{
|
||||
"Belgian Grand Prix": {
|
||||
"1953": {
|
||||
"circuit": "belgium-circuit.geo.json",
|
||||
"date": "1953-06-22"
|
||||
}
|
||||
}
|
||||
}
|
||||
"""
|
||||
grand_prix_data = {}
|
||||
|
||||
for race in races:
|
||||
race_name = race.get('raceName', 'Unknown Grand Prix')
|
||||
season = race.get('season', 'Unknown')
|
||||
|
||||
# Create the GP entry if it doesn't exist
|
||||
if race_name not in grand_prix_data:
|
||||
grand_prix_data[race_name] = {}
|
||||
|
||||
# Extract circuit info
|
||||
circuit = race.get('Circuit', {})
|
||||
circuit_name = circuit.get('circuitName', 'Unknown Circuit')
|
||||
location = circuit.get('Location', {})
|
||||
locality = location.get('locality', 'Unknown')
|
||||
|
||||
# Create season entry
|
||||
season_entry = {
|
||||
"date": race.get('date', ''),
|
||||
"circuit_name": circuit_name,
|
||||
"location": locality,
|
||||
"country": location.get('country', 'Unknown'),
|
||||
"round": race.get('round', '')
|
||||
}
|
||||
|
||||
# Try to match with a circuit file
|
||||
circuit_key = (circuit_name, locality, int(season))
|
||||
if circuit_key in circuit_mapping:
|
||||
season_entry["circuit"] = circuit_mapping[circuit_key]
|
||||
else:
|
||||
# Try to find a close match
|
||||
for (name, loc, year), file_name in circuit_mapping.items():
|
||||
if name == circuit_name and loc == locality:
|
||||
season_entry["circuit"] = file_name
|
||||
break
|
||||
|
||||
# Add to the grand prix data
|
||||
grand_prix_data[race_name][season] = season_entry
|
||||
|
||||
return grand_prix_data
|
||||
|
||||
def create_seasons_data(races):
|
||||
"""
|
||||
Create a dictionary of races organized by season and round.
|
||||
|
||||
Format:
|
||||
{
|
||||
"1950": {
|
||||
"1": {
|
||||
"name": "British Grand Prix",
|
||||
"date": "1950-05-13",
|
||||
"circuit": {...}
|
||||
}
|
||||
}
|
||||
}
|
||||
"""
|
||||
seasons_data = {}
|
||||
|
||||
for race in races:
|
||||
season = race.get('season', 'Unknown')
|
||||
round_num = race.get('round', 'Unknown')
|
||||
|
||||
# Create the season entry if it doesn't exist
|
||||
if season not in seasons_data:
|
||||
seasons_data[season] = {}
|
||||
|
||||
# Extract essential race information
|
||||
race_name = race.get('raceName', 'Unknown Grand Prix')
|
||||
circuit = race.get('Circuit', {})
|
||||
location = circuit.get('Location', {})
|
||||
|
||||
# Create race entry
|
||||
race_entry = {
|
||||
"name": race_name,
|
||||
"date": race.get('date', ''),
|
||||
"time": race.get('time', ''),
|
||||
"url": race.get('url', ''),
|
||||
"circuit": {
|
||||
"name": circuit.get('circuitName', 'Unknown Circuit'),
|
||||
"url": circuit.get('url', ''),
|
||||
"location": {
|
||||
"lat": location.get('lat', ''),
|
||||
"long": location.get('long', ''),
|
||||
"locality": location.get('locality', ''),
|
||||
"country": location.get('country', '')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Add race results and other data if available
|
||||
if 'Results' in race:
|
||||
race_entry['results'] = race['Results']
|
||||
|
||||
if 'Qualifying' in race:
|
||||
race_entry['qualifying'] = race['Qualifying']
|
||||
|
||||
if 'Sprint' in race:
|
||||
race_entry['sprint'] = race['Sprint']
|
||||
|
||||
# Add to the seasons data
|
||||
seasons_data[season][round_num] = race_entry
|
||||
|
||||
return seasons_data
|
||||
|
||||
def main():
|
||||
# Fetch all race data
|
||||
all_races = fetch_all_grand_prix_data()
|
||||
|
||||
# Get circuit file mapping
|
||||
circuit_mapping = get_circuit_file_mapping()
|
||||
print(f"Found {len(circuit_mapping)} circuit mappings")
|
||||
|
||||
# Create grand prix data
|
||||
grand_prix_data = create_grand_prix_data(all_races, circuit_mapping)
|
||||
print(f"Created grand prix data with {len(grand_prix_data)} entries")
|
||||
|
||||
# Create seasons data
|
||||
seasons_data = create_seasons_data(all_races)
|
||||
print(f"Created seasons data with {len(seasons_data)} seasons")
|
||||
|
||||
# Save to files
|
||||
with open('grand_prix.json', 'w', encoding='utf-8') as f:
|
||||
json.dump(grand_prix_data, f, indent=2, ensure_ascii=False)
|
||||
print("Saved grand_prix.json")
|
||||
|
||||
with open('seasons.json', 'w', encoding='utf-8') as f:
|
||||
json.dump(seasons_data, f, indent=2, ensure_ascii=False)
|
||||
print("Saved seasons.json")
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user