Documentation Index Fetch the complete documentation index at: https://mintlify.com/TracingInsights-Archive/Stats/llms.txt
Use this file to discover all available pages before exploring further.
The results.py script fetches race results including finishing positions, points awarded, and race outcomes for each driver.
Script Overview
Location: ~/workspace/source/results.py
The script uses the RaceResultsFetcher class to:
Fetch race results for specific rounds
Handle rate limiting automatically
Save results to the appropriate race directory
Log all operations for debugging
API Endpoint
url = f "https://api.jolpi.ca/ergast/f1/ { season } / { round_num } /results.json"
RaceResultsFetcher Class
Initialization
class RaceResultsFetcher :
def __init__ ( self , base_dir = "." ):
self .base_dir = Path(base_dir)
self .base_url = "https://api.jolpi.ca/ergast/f1"
# Rate limits
self .burst_limit = 4 # requests per second
self .last_request_time = 0
Rate-Limited Requests
The class implements adaptive rate limiting:
def make_request ( self , url ):
"""Make a request to the API with rate limiting"""
# Ensure we don't exceed burst limit
current_time = time.time()
time_since_last_request = current_time - self .last_request_time
if time_since_last_request < ( 1 / self .burst_limit):
sleep_time = ( 1 / self .burst_limit) - time_since_last_request
logger.debug( f "Rate limiting: sleeping for { sleep_time :.2f} seconds" )
time.sleep(sleep_time)
logger.debug( f "Making request to: { url } " )
response = requests.get(url)
self .last_request_time = time.time()
if response.status_code == 429 :
logger.warning( "Rate limit exceeded. Waiting 30 seconds before retrying." )
time.sleep( 30 )
return self .make_request(url)
if response.status_code != 200 :
logger.error(
f "Error fetching data: { response.status_code } - { response.text } "
)
return None
return response.json()
def get_race_info ( self , season , round_num ):
"""Get race information for a specific season and round"""
url = f " { self .base_url } / { season } / { round_num } .json"
data = self .make_request(url)
if not data:
return None
races = data.get( "MRData" , {}).get( "RaceTable" , {}).get( "Races" , [])
if races:
return races[ 0 ]
return None
Fetching Results
def get_race_results ( self , season , round_num ):
"""Get race results for a specific season and round"""
url = f " { self .base_url } / { season } / { round_num } /results.json"
return self .make_request(url)
Main Fetch Method
def fetch_round ( self , season , round_num ):
"""Fetch race results for a specific season and round"""
logger.info( f "Fetching results for season { season } , round { round_num } " )
# Create season directory
season_dir = self .base_dir / str (season)
os.makedirs(season_dir, exist_ok = True )
# Get race info
race_info = self .get_race_info(season, round_num)
if not race_info:
logger.warning( f "No race info found for season { season } , round { round_num } " )
return
race_name = self .get_race_folder_name(race_info)
# Create race directory
race_dir = season_dir / race_name
os.makedirs(race_dir, exist_ok = True )
# Get race results
race_results = self .get_race_results(season, round_num)
if race_results:
race_results_path = race_dir / "results.json"
self .save_json(race_results, race_results_path)
else :
logger.warning( f "No results found for season { season } , round { round_num } " )
Output Structure
Stored at: {year}/{race-name}/results.json
{
"MRData" : {
"series" : "f1" ,
"url" : "https://api.jolpi.ca/ergast/f1/1950/5/results.json" ,
"limit" : "30" ,
"offset" : "0" ,
"total" : "14" ,
"RaceTable" : {
"season" : "1950" ,
"round" : "5" ,
"Races" : [
{
"season" : "1950" ,
"round" : "5" ,
"raceName" : "Belgian Grand Prix" ,
"Circuit" : {
"circuitId" : "spa" ,
"circuitName" : "Circuit de Spa-Francorchamps" ,
"Location" : {
"lat" : "50.4372" ,
"long" : "5.97139" ,
"locality" : "Spa" ,
"country" : "Belgium"
}
},
"date" : "1950-06-18" ,
"Results" : [
{
"number" : "10" ,
"position" : "1" ,
"positionText" : "1" ,
"points" : "8" ,
"Driver" : {
"driverId" : "fangio" ,
"givenName" : "Juan" ,
"familyName" : "Fangio" ,
"dateOfBirth" : "1911-06-24" ,
"nationality" : "Argentine"
},
"Constructor" : {
"constructorId" : "alfa" ,
"name" : "Alfa Romeo" ,
"nationality" : "Swiss"
},
"grid" : "2" ,
"laps" : "35" ,
"status" : "Finished" ,
"Time" : {
"millis" : "10046000" ,
"time" : "2:47"
}
}
]
}
]
}
}
}
Usage Example
Basic Usage
from results import RaceResultsFetcher
fetcher = RaceResultsFetcher( base_dir = "." )
fetcher.fetch_round( 2024 , 1 ) # Fetch results for 2024 Bahrain GP
Multiple Rounds
fetcher = RaceResultsFetcher( base_dir = "." )
for round_num in range ( 1 , 22 ):
fetcher.fetch_round( 2024 , round_num)
logger.info( "Race results fetching completed" )
The script includes logging to both a file (race_results_fetch.log) and the console for easy monitoring.
Results Data Fields
Each result contains:
Field Description numberDriver’s car number positionFinishing position positionTextPosition as text (handles special cases) pointsChampionship points awarded DriverDriver information (name, nationality, etc.) ConstructorTeam information gridStarting grid position lapsNumber of laps completed statusFinish status (Finished, Retired, etc.) TimeFinishing time (winner) or gap to winner FastestLapFastest lap information (when available)
Not all fields are available for all races, especially historical data. Always check for the existence of fields before accessing them.
Logging Configuration
The script uses structured logging:
logging.basicConfig(
level = logging. INFO ,
format = " %(asctime)s - %(name)s - %(levelname)s - %(message)s " ,
handlers = [
logging.FileHandler( "race_results_fetch.log" ),
logging.StreamHandler()
]
)
Events Must run first to create race directories
Qualifying Fetch qualifying results next