Have Sud report its own tick-counted elapsed time to clients
Window._elapsed_min() (client/brewpi_gui.py) reconstructed the dynamic
forecast's x-axis from wall-clock time times the server's nominal
configured sim_warp_factor. But that warp factor is only nominal -
real asyncio/Python scheduling overhead across the 7 concurrent tasks
means the actually-achieved speedup runs measurably below it (~80x
instead of 100x, confirmed by timing HoldRemaining countdowns against
real elapsed time), especially under heavy message/print load. Since
the GUI's reconstruction assumed a precise, constant mapping, the live
measured trace visibly drifted behind the forecast - most visible on
short, transition-dense test schedules where the timing slip is a
large fraction of the total duration.
components/sud.py: Sud now tracks 'elapsed' (tick-counted simulated
seconds since the run started, frozen while PAUSED/IDLE/DONE, reset on
start()) - the ground truth for run progress, immune to real-world
pacing jitter. tasks/sud.py broadcasts it as {'Sud': {'Elapsed': ...}}.
client/brewpi_gui.py: replaced sud_start_time/sud_paused_total/
sud_pause_started_at and all the wall-clock reconstruction in
_elapsed_min() with sud_elapsed_seconds, set directly from the
server's 'Elapsed' broadcasts - simpler too, since pause-freezing is
now handled server-side rather than needing separate client-side
bookkeeping.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LhiQe64F74uHV8jzuoSa5K
This commit is contained in:
@@ -106,6 +106,7 @@ class Sud(AttributeChange):
|
||||
self.step = None
|
||||
self.user_message = None
|
||||
self._paused_from = None
|
||||
self.elapsed = 0.0
|
||||
|
||||
def save(self):
|
||||
"""Returns the currently running sud.json document (EMPTY_SUD if
|
||||
@@ -161,6 +162,7 @@ class Sud(AttributeChange):
|
||||
if self.state not in (SudState.IDLE, SudState.DONE):
|
||||
return
|
||||
self.index = -1
|
||||
self.elapsed = 0.0
|
||||
self._advance()
|
||||
|
||||
def pause(self):
|
||||
@@ -195,6 +197,16 @@ class Sud(AttributeChange):
|
||||
self._finish_step()
|
||||
|
||||
def tick(self, dt):
|
||||
"""Advances the run by dt simulated seconds. 'elapsed' is the tick-
|
||||
counted ground truth for how far the run has actually progressed -
|
||||
clients used to reconstruct this themselves from wall-clock time
|
||||
times the configured warp factor, but the warp factor is only
|
||||
nominal (real asyncio/Python scheduling overhead means the actual
|
||||
achieved speedup runs measurably below it, especially under heavy
|
||||
message/print load), making that reconstruction drift from the
|
||||
truth. Frozen while PAUSED/IDLE/DONE, same as hold_remaining."""
|
||||
if self.state not in (SudState.IDLE, SudState.DONE, SudState.PAUSED):
|
||||
self.elapsed += dt
|
||||
if self.state == SudState.HOLDING:
|
||||
self.hold_remaining -= dt
|
||||
if self.hold_remaining <= 0:
|
||||
|
||||
Reference in New Issue
Block a user