F1 Sim
A Year 7 STEM Day racing simulator where students write a driver's mentality in Python and race it against the rest of the class.

Overview
F1 Sim is a classroom racing strategy simulator built for a single session of a Year 7 STEM experience day. Students edit a small Python car setup and a driver(info) function that runs once per lap, deciding braking, cornering and acceleration aggression, how to behave in traffic, and how to spend the battery. They test against an AI grid, export their car as JSON, and submit it to a teacher-run class championship where qualifying, races and standings run live on the projector.
The design problem was the timetable rather than the technology. STEM Day gives an activity one session, so any coding task has to produce a working result for a complete beginner inside the first ten minutes while still rewarding the students who push further. A blank editor fails the first requirement and a drag and drop toy fails the second.
The answer was to make the deliverable a driver rather than a program. Every student starts from the same working car, a Python dictionary holding team identity, front and rear downforce, fuel load, gear ratio and tyre compound. Below it sits driver(info), called once per lap, returning braking, cornering and acceleration aggression, an overtaking mode of push, defend or cautious, and a battery mode of save, balanced or deploy.
The ceiling stays open because the info passed in each lap is real: tyre wear, fuel remaining, battery charge, lap number, total laps, race position, the gaps to the cars ahead and behind, and the weather. Returning five constants works. One if statement about tyre wear works better. Reading the gap behind and switching to defend is a genuine strategic decision, and students arrive at conditional logic because they want to hold a position rather than because a worksheet asked them to.
Each lap is simulated from circuit segments combined with downforce, gearing, fuel weight and tyre compound, then adjusted for tyre wear, fuel burn, low fuel penalties, battery deployment, grip and weather, and deterministic incident risk. Cars running close together resolve attack, defend and cautious decisions against each other. A balanced reference car is calibrated to an educational reference lap time for each circuit so that results stay comparable between classes.
The classroom deployment is one command on a teacher laptop. It builds the site, prepares a local SQLite database and serves the student page, the teacher dashboard and the API from a single address, then prints the two links and a teacher PIN. Everything, including the Python runtime, is served locally after install, so a lesson never depends on the school internet holding up.
Gallery

The student page. Car setup and driver function on the left, circuit on the right, one button to run it.
FEATURES.
A Driver Mentality, Not A Program
Students edit about ten values across a car setup dictionary and a driver(info) function. The starter car runs unmodified, so every student has a working result before they change anything.
Per Lap Decision Data
The driver function receives tyre wear, fuel, battery, lap number, total laps, position, gaps ahead and behind, and weather, so strategy can respond to the race as it unfolds.
Test Against An AI Grid
Students run their car against a full grid on a fictional oval, Albert Park and Monaco, with an animated circuit, live positions and a per lap table of times, tyre wear, fuel and battery.
Export And Class Submission
Code autosaves in the browser and exports as a single JSON payload. A class code and submission link take a paste, preview it, and upsert by team name so a student can resubmit an improved car.
Teacher Race Control
A PIN-protected dashboard loads every submission, runs qualifying and the race on the projector with live timing, and offers faster or presentation animation speeds to fit the time left.
Five Circuit Championship
Points for the top three in qualifying, the top ten in the race, and a fastest lap bonus for the top three, across an oval, Albert Park, Monaco, Silverstone and Spa. Re-running a circuit replaces its saved result rather than double counting.
Sandboxed Student Python
Pyodide runs student code in a Web Worker with only the math module importable, a time limit that kills accidental infinite loops and replaces the worker, and browser, file and dynamic code access blocked.
Event-Safe Failure
Invalid cars and lap decisions are normalised to documented ranges, and a driver function that errors falls back to a safe default strategy, so one broken submission cannot stop a live class race.
Offline By Design
The Python runtime, circuit data and assets are all served locally after install, and classes, submissions and results live in one SQLite file that can be backed up before an event and restored after it.
Tech Stack
Strict typing across the shared physics, tyre, fuel, battery, overtaking and race engine modules used by both the student tester and teacher race control
Builds the four student and teacher pages, with the deployment base path baked into asset URLs at build time
Runs student Python in the browser inside a Web Worker, served locally so the lesson works without an internet connection
Single server for the built site and the API, with teacher PIN protection, submission size and rate limits, and security headers
Classes, submissions, saved qualifying and race events in one portable database file that a teacher can back up before an event
Hosted copy running under a sub-path on the main site, with classroom data on a persistent named volume
Architecture
One Express server hosts the built site and the API together, so a classroom deployment is a single address and a single command rather than a front end and a back end to coordinate.
Simulation logic lives in a shared module used by both the student tester and teacher race control, so the car a student tuned behaves identically in the class championship.
Student Python executes in a Web Worker through Pyodide, isolated from the page and from the teacher controls, with a time limit that replaces the worker after a runaway loop.
The teacher PIN is shared session protection on class lists, submissions, race control and championship resets, appropriate for a supervised school network rather than individual staff accounts.
Race results are stored per circuit so re-running a track replaces its latest saved event, which keeps championship points correct when a race is restarted mid lesson.
The hosted copy runs under a sub-path, so the asset base path is compiled in and the API router is mounted on the same prefix, with the reverse proxy passing the prefix through rather than stripping it.
Data Model
- •Classes with a display name and a short class code used for student submission links
- •Submissions holding a team name, car colour, the sanitised car setup and the student's raw driver code, upserted by team name within a class
- •Saved events per circuit covering qualifying and race results, replaced rather than duplicated when a track is run again
- •Championship standings derived from saved events, with qualifying points, race points and fastest lap bonuses
- •Circuit definitions with coordinate-derived centre lines and educational reference lap times used to calibrate a balanced car
Challenges
- •Fitting a genuine coding task into one session with complete beginners, solved by shipping a working starter car and reducing the editable surface to about ten meaningful values
- •Keeping a class race running when student code fails, solved by normalising out of range decisions and falling back to a safe default driver instead of aborting the event
- •Running untrusted student Python in a classroom browser, solved with a Web Worker, a math-only import allowlist, blocked dynamic code and attribute access, and an execution time limit
- •Making results comparable rather than random, solved with deterministic incident risk and a balanced reference car calibrated to each circuit's reference lap time
- •Deploying under a sub-path on the main site, where the asset base path is baked in at build time and the API must be mounted on the same prefix, so the path cannot be changed by environment variable alone
Outcomes
- •Live at benjaminhyde.com.au/f1sim, with the same application deployable offline on a teacher laptop for classroom use
- •Run with Year 7 STEM Day groups in 50 minute sessions, where the class championship format held engagement across the whole lesson in a way the previous individual drag racing activity did not
- •A single session activity that produces a working result in minutes and still rewards students who read the per lap data and write conditional strategy
- •A class championship that makes strategy trade-offs visible, where tyre management beats raw qualifying pace in front of the whole room
- •Student code executed safely in the browser with no accounts, no personal data collected, and team names and colours as the only student-supplied display content
- •Classroom data kept in one portable SQLite file that can be backed up before an event and restored afterwards