How a run works
A PyRasp run always happens in the same order: circuit.py builds the board, the board is powered on, and main.py runs as the program on the Pi. Understanding that order explains most of the odd things you might see — why a wiring error stops everything before your program starts, why the bill only changes after you press Run, and why ten simulated seconds take a moment rather than ten.
Step 1 — circuit.py builds the board and the bill
When PyRasp runs circuit.py, every Pi(), every part and every >> wire is collected into one board document. That document is two things at once:
- the board you see, and the board the program will talk to;
- the bill — every part is a purchase, and boards are free.
In the workspace this happens when you press Run, Run tests or Submit — never while you type, so a half-written line doesn't flash errors at you. That build updates the board view and the cost. If it fails, there is no board at all: the error is shown under the editor and the previous board is left alone. (Opening a task builds once, quietly, so you see the board where you left it.)
Step 2 — power-on
Run builds circuit.py one more time, creates the simulated board from it, and switches it on. Nothing on the board is alive until this moment; main.py cannot start before it.
Step 3 — main.py runs
main.py executes as if it were the file run by python main.py on the Pi. The same gpiozero, RPi.GPIO or bus library calls you would use on real hardware read and write the simulated header, and what the program prints goes to the console.
Simulated time is what makes this practical: when the program sleeps, waits for a button or polls a sensor, the simulator advances the clock straight to the next moment that matters instead of waiting in real time. The program sees a correct time.sleep(0.5); you just don't pay for it.
Run tests: the judge
With a task open, Run tests does more than Run:
- It applies the objective's environment: the sensors named in the task become ideal and set to the objective's values, so two makers judge the same circuit under the same conditions.
- It turns the objective's stimuli into scheduled actions — "press the button at 2 s", "make it dark at 5 s".
- It runs
main.pyfor the objective's fixed duration, fast-forwarding through sleeps as usual, while recording pin levels and part states. - It evaluates the objective's checks — was the LED on between 0.5 s and 3 s, did the buzzer switch on exactly twice, is nothing damaged — and reports a verdict for each.
All checks passing means accepted. A failed check means rejected, with the detail shown in the Results tab.
Submit: the server's judge
In the daily contest, Submit sends both files to the server. The server stores the submission, runs the same judge against the same objective, and applies the verdict to your attempt:
- Your time is counted up to the moment you submitted, not until the judge finished — so a slow judge does not cost you seconds.
- Each submission that comes back rejected, build-error or over-budget adds a five-minute penalty. A judge failure (
error) does not count against you. - The first accepted submission ends the attempt, and the score is your time plus a cost penalty plus the penalties for wrong submissions. Lower wins.
Submissions and verdicts has the full rules and the score arithmetic.
Going deeper
- Budget is checked before anything runs. In the judge, the build's bill is compared with the objective's budget first; an over-budget build is refused as
over-budgetwithout runningmain.py. The workspace disables Submit for the same reason. - Runs are deterministic. The judge starts from a fixed seed, so the same files always produce the same result; a test that passes once passes every time.
- The same judge everywhere. Run tests and Submit run the same checks against the same objective, so practice matches the contest exactly.
- What "fast-forward" means. Simulated time only jumps over idleness. A program that polls in a tight loop without sleeping is run a slice at a time, and a program waiting on an edge lets time pass so stimuli can happen. The full runtime story, including
sleep,datetime, threads and the console, is in the runtime. - After the run the program is stopped where it was waiting and the board is released; a
finallyblock or a background thread does not get one last turn. That is also why a program that merely reaches its end does not keep a pin driven — see the runtime.