- Add volumen field to all sud JSON pot entries (30 L)
- Fix parseSudDoc to read from nested doc.pot (was using stale flat keys)
- SVG widget shows transparent rectangular pot with stirrer, thermometer
with live temperature, and water fill level (water_mass/volumen) when
a sud is loaded; no water shown when no sud is loaded
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DGKe8JzTM2Gr1fdx9wYXTi
Top-level pot_mass/pot_material/L/Td/grain_mass/water_mass and their
per-step overrides are now grouped under a 'pot' sub-object, matching
the structure already applied to sud_0010.json's parent level. Updated
all sude/*.json files and the parsing/consuming code in components/sud.py,
tasks/sud.py, components/sud_forecast.py, and scripts/demos/sud/demo_sud.py.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01T52JH848ojhXXHn1bAzdC3
Sud now parses top-level grain_mass/water_mass (sibling to pot_mass/
pot_material/L/Td, defaulting to 0/0) - what's actually in the pot before
the brew starts, as opposed to default.step's grain_mass/water_mass, which
is just inert template filler. All sude/*.json docs gain explicit values
matching what their first step already resolved to.
tasks/sud.py's apply_plant_params() now takes grain_mass/water_mass
directly instead of a step dict: on_step_changed() still passes the active
step's own (these vary as malt goes in/water boils off), but the Load
handler now reads Sud.grain_mass/water_mass directly instead of parsing
schedule[0]. The GUI's status-line mass preview (shown immediately on
Load, before Start) does the same.
Also fixes a latent bug found along the way: _continue_forecast_after_confirm()'s
reconstructed sub-doc was missing L/Td/grain_mass/water_mass entirely,
silently falling back to generic defaults instead of the real Sud's own
values - invisible only because every current sude/*.json happens to use
those same defaults.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DkkuG48uHFCGKe6dPSERFk
Sud now parses top-level L/Td fields from sude/*.json (defaulting to 0.2/30,
matching the old hardcoded server constants), and derive_plant_params()
returns them alongside M/C - constant for the whole brew, unlike M/C which
vary per step with grain/water mass. All sude/*.json docs gain explicit
L/Td fields.
Callers (tasks/sud.py, SudForecastEstimator, demo_sud.py) switch from the
narrow set_thermal_params(M, C)/set_model_params(M, C) to the full
set_plant_params(params)/set_model_plant_params(params), since
derive_plant_params() now always returns all four keys; both narrow setters
are removed as dead code.
Caught along the way: Pot.set_plant_params() unconditionally rebuilt the
Delay ring buffer, which was harmless when only ever called once at
construction - but now running on every Sud step change, it was wiping
in-flight delayed power at each step boundary. Fixed to only rebuild when
Td actually changes; verified this restores the exact original forecast
result for sud_0010.json.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DkkuG48uHFCGKe6dPSERFk