Add Python TrainSim with loop track map and physics.
FastAPI server, replaceable JSON config, tests, Dockerfile. Pairs with ATO via spec/interface.md contract. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
parent
45c95836ef
commit
9c5ef3a5cd
18 changed files with 414 additions and 18 deletions
4
tests/conftest.py
Normal file
4
tests/conftest.py
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
sys.path.insert(0, str(Path(__file__).resolve().parents[1]))
|
||||
26
tests/test_api.py
Normal file
26
tests/test_api.py
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
import os
|
||||
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
os.environ.setdefault("SIM_CONFIG", "config/sim.default.json")
|
||||
os.environ.setdefault("TRACK_CONFIG", "config/track.default.json")
|
||||
|
||||
from trainsim.app import create_app # noqa: E402
|
||||
|
||||
client = TestClient(create_app())
|
||||
|
||||
|
||||
def test_health():
|
||||
assert client.get("/health").json()["status"] == "ok"
|
||||
|
||||
|
||||
def test_state_shape():
|
||||
s = client.get("/train/state").json()
|
||||
assert "speed_mps" in s and "track_length_m" in s
|
||||
|
||||
|
||||
def test_actuate_and_start():
|
||||
client.post("/sim/start")
|
||||
client.post("/train/actuate", json={"traction_pct": 50, "brake_pct": 0})
|
||||
s = client.get("/train/state").json()
|
||||
assert s["sim_running"] is True
|
||||
22
tests/test_physics.py
Normal file
22
tests/test_physics.py
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
from trainsim.config_loader import SimParams
|
||||
from trainsim.physics import Train
|
||||
|
||||
|
||||
def test_train_accelerates_with_traction():
|
||||
p = SimParams(1000, 20, 0.15, 0.25, 0.02, 25)
|
||||
t = Train()
|
||||
t.sim_running = True
|
||||
t.actuate(100, 0)
|
||||
for _ in range(120):
|
||||
t.tick(p, 0.05)
|
||||
assert t.speed_mps > 0.5
|
||||
|
||||
|
||||
def test_brake_slows_train():
|
||||
p = SimParams(1000, 20, 0.15, 0.25, 0.02, 25)
|
||||
t = Train(speed_mps=10.0)
|
||||
t.sim_running = True
|
||||
t.actuate(0, 100)
|
||||
for _ in range(200):
|
||||
t.tick(p, 0.05)
|
||||
assert t.speed_mps < 10.0
|
||||
Loading…
Add table
Add a link
Reference in a new issue