Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 42 additions & 0 deletions scripts/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# Testing scripts

Supporting script to simulate an autocross sessions with fake data.

## Example (sim.py)

```
➜ python3 -m venv ./venv
➜ source ./venv/bin/activate
➜ python3 -m pip install -r requirements.txt
➜ python3 sim.py -h
usage: sim.py [-h] -u URL -c CARS -r RUNS

Description of your program

optional arguments:
-h, --help show this help message and exit
-u URL, --url URL URL for API
-c CARS, --cars CARS Number of cars in event
-r RUNS, --runs RUNS Number of runs for each car
➜ python3 sim.py -c 6 -r 2 -u http://localhost:8000
2025-07-13 11:15:08,910 INFO: ##############################################
2025-07-13 11:15:08,911 INFO: # test_race_1752419708.9109545
2025-07-13 11:15:08,911 INFO: # Event 6
2025-07-13 11:15:08,911 INFO: # test_eventId: pjhfibpvoawm
2025-07-13 11:15:08,911 INFO: ##############################################
2025-07-13 11:15:08,919 INFO: Run 1 for car 1
2025-07-13 11:15:08,928 INFO: Run 1 for car 5
2025-07-13 11:15:08,935 INFO: Run 1 for car 2
2025-07-13 11:15:08,943 INFO: Run 1 for car 4
2025-07-13 11:15:08,951 INFO: Run 1 for car 6
2025-07-13 11:15:08,959 INFO: Run 1 for car 3
2025-07-13 11:15:08,965 INFO: Run 2 for car 4
2025-07-13 11:15:08,977 INFO: Run 2 for car 3
2025-07-13 11:15:08,991 INFO: Run 2 for car 2
2025-07-13 11:15:09,003 INFO: Run 2 for car 6
2025-07-13 11:15:09,020 INFO: Run 2 for car 5
2025-07-13 11:15:09,030 INFO: Run 2 for car 1
Delete Event? [Y/n]y
2025-07-13 11:15:11,222 INFO: Event pjhfibpvoawm deleted
2025-07-13 11:15:11,222 INFO: Done
```
6 changes: 6 additions & 0 deletions scripts/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
certifi==2025.7.9
charset-normalizer==3.4.2
idna==3.10
random-username==1.0.2
requests==2.32.4
urllib3==2.2.3
173 changes: 173 additions & 0 deletions scripts/sim.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
import logging
import argparse
import requests
from enum import Enum
import random
import string
from random_username.generate import generate_username
from datetime import datetime
import time

LOG = logging.getLogger(__name__)
logging.basicConfig(format='%(asctime)s %(levelname)s: %(message)s', level=logging.INFO)

BASE_URL = "USER_PROVIDED"

class CarClass(Enum):
SS = ("SS", 0.836)
SSP = ("SSP", 0.857)
XP = ("XP", 0.890)
AM = ("AM", 1.000)
AS = ("AS", 0.826)
ASP = ("ASP", 0.851)
BP = ("BP", 0.874)
BM = ("BM", 0.978)
BS = ("BS", 0.819)
BSP = ("BSP", 0.855)
CP = ("CP", 0.863)
CM = ("CM", 0.899)
CS = ("CS", 0.813)
CSP = ("CSP", 0.859)
DP = ("DP", 0.865)
DM = ("DM", 0.906)
DS = ("DS", 0.811)
DSP = ("DSP", 0.847)
EP = ("EP", 0.858)
EM = ("EM", 0.916)
ES = ("ES", 0.790)
ESP = ("ESP", 0.840)
FP = ("FP", 0.877)
FM = ("FM", 0.917)
FS = ("FS", 0.817)
FSP = ("FSP", 0.831)
FSAE = ("FSAE", 0.980)
GS = ("GS", 0.794)
HCR = ("HCR", 0.814)
HS = ("HS", 0.784)
CAM_T = ("CAM-T", 0.821)
KM = ("KM", 0.937)
HCS = ("HCS", 0.789)
CAM_C = ("CAM-C", 0.825)
SMF = ("SMF", 0.850)
CAM_S = ("CAM-S", 0.844)
SM = ("SM", 0.868)
SSC = ("SSC", 0.809)
SSM = ("SSM", 0.878)
XA = ("XA", 0.846)
SST = ("SST", 0.837)
XB = ("XB", 0.848)
CSM = ("CSM", 0.800)
AST = ("AST(STR)", 0.834)
XU = ("XU", 0.869)
CSX = ("CSX", 0.812)
BST = ("BST(STU)", 0.833)
CST = ("CST", 0.830)
EVX = ("EVX", 0.839)
DST = ("DST(STX)", 0.818)
EST = ("EST(STS)", 0.815)
GST = ("GST(STH)", 0.810)

def __new__(cls, class_name, multi):
entry = object.__new__(cls)
entry._value_ = class_name
entry.class_name = str(class_name)
entry.multi = multi
return entry

def __str__(self):
return self.class_name

class CarEntry:
def __init__(self, event_id, car_num):
self.event_id = event_id
self.car_num = car_num
self.total_runs = 0
self.car_class = random.choice(list(CarClass))
self.driver_name = generate_username(1)[0]

def add_run(self, run_num):
self.total_runs +=1
base_time = random.randint(30000, 50000) / 1000.0
pax_time = round(base_time * self.car_class.multi, 3)
cones = random.randint(0, 10) // random.randint(1, 15)

runData = {
"eventId": str(self.event_id),
"runNumber": str(run_num),
"carNumber": str(self.car_num),
"rawTime": str(base_time),
"paxTime": str(pax_time),
"carClass": str(self.car_class),
"driverName": str(self.driver_name),
"cones": str(cones),
}
req = requests.post(f"{BASE_URL}/api/runs/{self.event_id}", json=runData)

if req.status_code == 200:
return
LOG.error(req.text)

class Event:
def __init__(self, num_cars, num_runs):
self.event_id = ''.join(random.choice(string.ascii_lowercase) for i in range(12))
self.num_runs = num_runs
self.cars = []
for car_num in range(1, num_cars + 1):
self.cars.append(CarEntry(event_id = self.event_id, car_num=car_num))

def do_runs(self):
run = 0
for run_num in range(1, self.num_runs + 1):
random.shuffle(self.cars)
for car in self.cars:
LOG.info(f"Run {run_num} for car {car.car_num}")
run += 1
car.add_run(run_num=run)

def add_event(self):
club = f"test_race_{time.time()}"
event_num = random.randint(1, 20)
locaton = f"test_eventId: {self.event_id}"
runData = {
"clubName": club,
"eventLocation": locaton,
"eventDate": datetime.today().strftime('%Y-%m-%d'),
"eventNumber": str(event_num),
"eventId": str(self.event_id),
}
LOG.info(f"##############################################")
LOG.info(f"# {club}")
LOG.info(f"# Event {event_num}")
LOG.info(f"# {locaton}")
LOG.info(f"##############################################")

req = requests.post(f"{BASE_URL}/api/events", json=runData)
if req.status_code == 200:
return
raise Exception(f"Could not create event: {req.text}")

def delete_event(self):
req = requests.get(f"{BASE_URL}/api/event/delete/{self.event_id}")
if req.status_code == 200:
LOG.info(f"Event {self.event_id} deleted")
return
raise Exception(f"Could not delete event: {req.text}")

if __name__ == '__main__':
parser = argparse.ArgumentParser(description='Description of your program')
parser.add_argument('-u', '--url', help='URL for API', required=True)
parser.add_argument('-c', '--cars', type=int, help='Number of cars in event', required=True)
parser.add_argument('-r', '--runs', type=int, help='Number of runs for each car', required=True)
args = vars(parser.parse_args())
BASE_URL = args['url']
event = Event(num_cars=int(args['cars']), num_runs=int(args['runs']))
event.add_event()
event.do_runs()
prompt = ""
while prompt not in ['y', 'n']:
prompt = input("Delete Event? [Y/n]").lower()
if prompt == '':
prompt = 'y'
if prompt == 'y':
event.delete_event()
LOG.info("Done")