Called once per simulated minute (1,440 times). Return setpoints in MW. Anything you leave out keeps its last value. Your score is societal cost: fuel + start-ups + $10,000 per MWh of blackout + $100 per tonne of CO₂ (lower is better). Unknown keys and non-numbers are ignored, with a warning in the console below naming the key.
return {
coal: 1200, gas: 900, peaker: 0, // thermal targets (units start/stop automatically)
commit: { gas: 4 }, // optional: keep at least N units online
wind: 3000, solar: 3500, // curtailment caps
battery: -300, // + discharge, - charge (auto frequency response adds on top)
dr: true // call demand response (limited calls)
}
state: t (minute 0..1439), frequency, deviation, demand, generation, imbalance, fleets.{nuclear,coal,gas,peaker} (output, online, starting, capacity, onlineMW, unitMW, rampPerMin, startMin, minFrac, cost, co2), fleets.{wind,solar} (available, output, capacity), fleets.battery (soc, socFrac, mwh, mw), dr (callsLeft, active, pending), forecast.{demand,wind,solar}[minute].
memory is yours to keep anything between calls. console.log works. Each call gets 250 ms; loop forever and the run stops, not the page.