This section provides a detailed breakdown of the key components of the Race Simulation App's code. By understanding how the code is structured, you can gain insights into how the simulation works, and how different parts of the app contribute to generating realistic race outcomes.
The code begins by importing necessary libraries and setting up the Flask app:
from flask import Flask, render_template, request, jsonify
import numpy as np
import pandas as pd
import random
import matplotlib.pyplot as plt
import io
import base64
import matplotlib
matplotlib.use('Agg') # Use the non-GUI Agg backend
app = Flask(__name__)
Explanation: This block of code imports various libraries that are essential for different functionalities in the app:
Flask
: Used for setting up the web framework.NumPy
and Pandas
: Used for handling numerical data and dataframes.Random
: Used for generating random numbers, which are essential for simulating race conditions.Matplotlib
: Used for generating visualizations like histograms and lap time graphs.Next, the code defines the driver ratings and information:
driver_ratings = {
'VER': {'Pace': 95, 'Racecraft': 95, 'Awareness': 94, 'Experience': 92},
'HAM': {'Pace': 93, 'Racecraft': 96, 'Awareness': 93, 'Experience': 97},
'LEC': {'Pace': 92, 'Racecraft': 88, 'Awareness': 86, 'Experience': 72},
...
}
driver_info = {
'1': 'VER',
'44': 'HAM',
'63': 'RUS',
...
}
Explanation: This section defines the drivers' ratings across four key attributes: Pace, Racecraft, Awareness, and Experience. These attributes are crucial for determining how each driver will perform during the race. The `driver_info` dictionary maps driver numbers to their respective codes (e.g., '1' for Verstappen as 'VER').
The heart of the app is the race simulation logic:
def run_simulation(driver, strategy, num_simulations, initial_position):
driver_abbr = driver_info[driver]
num_laps = 70
...
for _ in range(num_simulations):
current_tire_index = 0 # Start with the first tire in the sequence
race_lap_times = {d: [] for d in driver_info.keys()}
for lap in range(1, num_laps + 1):
if lap == 1:
sorted_drivers = list(driver_info.keys())
sorted_drivers.remove(driver)
sorted_drivers.insert(initial_position - 1, driver)
else:
sorted_drivers = sorted(race_lap_times.keys(), key=lambda d: race_lap_times[d][-1] if race_lap_times[d] else float('inf'))
for idx, d in enumerate(sorted_drivers):
ratings = driver_ratings[driver_info[d]]
prime_time = driver_prime_times[driver_info[d]]
...
Explanation: The `run_simulation` function handles the core simulation logic. Here’s what happens:
After the simulations are run, the results are visualized using Matplotlib:
def plot_histogram(positions):
plt.figure(figsize=(10, 6))
plt.hist(positions, bins=range(1, 22), edgecolor='black', alpha=0.7)
plt.xlabel('Finishing Position')
plt.ylabel('Frequency')
plt.title('Finishing Positions Histogram')
img = io.BytesIO()
plt.savefig(img, format='png')
img.seek(0)
img_url = base64.b64encode(img.getvalue()).decode('utf8')
plt.close()
return 'data:image/png;base64,{}'.format(img_url)
Explanation: This function creates histograms to display the distribution of finishing positions for the simulated races. The histogram provides a visual summary of where drivers are most likely to finish, which can be compared to actual race outcomes. The generated plot is then converted into a base64 string so that it can be easily rendered in the web application.
The final part of the code is responsible for serving the Flask application:
@app.route('/')
def index():
return render_template('index.html', drivers=driver_info)
@app.route('/simulate', methods=['POST'])
def simulate():
data = request.json
driver = data['driver']
strategy = data['strategy']
num_simulations = int(data['num_simulations'])
initial_position = int(data['initial_position'])
results = run_simulation(driver, strategy, num_simulations, initial_position)
img = plot_histogram(results)
return jsonify({'image': img})
if __name__ == '__main__':
app.run(host='0.0.0.0', port=5005, debug=True, use_reloader=False)
Explanation: This section includes the Flask routes that handle requests: