Generalize Sud forecast reanchoring to every step boundary
Reanchoring used to only happen when a user confirmed a WAIT_USER step, so anything the schedule advanced through on its own (a ramp reaching target, a hold timing out) left the forecast showing a stale, increasingly wrong prediction once reality diverged from it. _reanchor_forecast() now fires from on_step_changed() on every real transition, splicing in a fresh simulation anchored at the real current temperature/elapsed time instead. Also fixes two bugs surfaced while testing that change: - estimate()'s early-return for an empty/not-yet-loaded schedule still returned the old 4-tuple shape, crashing every connection before a Sud was ever Loaded. - send_forecast() and _reanchor_forecast() can run concurrently (e.g. a fresh Start triggers both at once), and whichever resumed second after its own worker-thread simulation would blindly splice its tail onto whatever the other had already written, producing a spurious connecting line across the plot. Both now carry a generation counter and discard their result if a newer call has since committed. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019qvu5giu7gvRCyEWzf2Vpx
This commit is contained in:
@@ -129,10 +129,10 @@ class SudForecastPlot(FigureCanvasQTAgg):
|
||||
requiring user confirmation - a human's response time genuinely
|
||||
can't be forecast, so it's modeled as a zero-delay auto-confirm
|
||||
there instead of stopping. That assumption gets corrected once the
|
||||
real confirmation actually happens (anchored at the real elapsed
|
||||
time and temperature) - see tasks/sud.py's SudTask.
|
||||
_continue_forecast_after_confirm() - at which point show_forecast()
|
||||
is called again with the corrected curve, replacing the optimistic
|
||||
schedule actually reaches the next real step boundary (anchored at
|
||||
the real elapsed time and temperature) - see tasks/sud.py's
|
||||
SudTask._reanchor_forecast() - at which point show_forecast() is
|
||||
called again with the corrected curve, replacing the optimistic
|
||||
guess outright rather than the GUI patching it up itself."""
|
||||
|
||||
def __init__(self):
|
||||
@@ -894,9 +894,9 @@ class Window(QtWidgets.QMainWindow, Ui_MainWindow):
|
||||
# Computed asynchronously server-side and can arrive slightly
|
||||
# after the schedule itself - applies regardless of whether a
|
||||
# run is in progress, since this can also be a later piecewise
|
||||
# segment appended after a real user confirmation (see
|
||||
# tasks/sud.py's SudTask._continue_forecast_after_confirm()), not
|
||||
# just the initial one computed at Load.
|
||||
# segment appended after a real step transition (see tasks/
|
||||
# sud.py's SudTask._reanchor_forecast()), not just the initial
|
||||
# one computed at Load.
|
||||
if self.sud_empty:
|
||||
return
|
||||
t_min = [seconds / 60.0 for seconds in forecast['T']]
|
||||
|
||||
Reference in New Issue
Block a user