Surface protection warnings in dashboard
This commit is contained in:
@@ -44,7 +44,7 @@ class ReactorDashboard:
|
||||
self.reset_requested = False
|
||||
self._last_state: Optional[PlantState] = None
|
||||
self._trend_history: deque[tuple[float, float, float]] = deque(maxlen=120)
|
||||
self.log_buffer: deque[str] = deque(maxlen=4)
|
||||
self.log_buffer: deque[str] = deque(maxlen=8)
|
||||
self._log_handler: Optional[logging.Handler] = None
|
||||
self._previous_handlers: list[logging.Handler] = []
|
||||
self._logger = logging.getLogger("reactor_sim")
|
||||
@@ -297,7 +297,7 @@ class ReactorDashboard:
|
||||
def _draw(self, stdscr: "curses._CursesWindow", state: PlantState) -> None:
|
||||
stdscr.erase()
|
||||
height, width = stdscr.getmaxyx()
|
||||
min_status = 4
|
||||
min_status = 6
|
||||
if height < min_status + 12 or width < 70:
|
||||
stdscr.addstr(
|
||||
0,
|
||||
@@ -308,8 +308,9 @@ class ReactorDashboard:
|
||||
stdscr.refresh()
|
||||
return
|
||||
|
||||
status_height = min_status
|
||||
data_height = height - status_height
|
||||
log_rows = max(2, min(len(self.log_buffer) + 2, 8))
|
||||
status_height = min(height - 1, max(min_status, min_status + log_rows))
|
||||
data_height = max(1, height - status_height)
|
||||
right_width = max(28, width // 3)
|
||||
left_width = width - right_width
|
||||
if left_width < 50:
|
||||
@@ -442,6 +443,7 @@ class ReactorDashboard:
|
||||
)
|
||||
right_y = self._draw_section(right_win, right_y, "Generators", self._generator_lines(state))
|
||||
right_y = self._draw_section(right_win, right_y, "Power Stats", self._power_lines(state))
|
||||
right_y = self._draw_section(right_win, right_y, "Protections / Warnings", self._protection_lines(state))
|
||||
right_y = self._draw_section(right_win, right_y, "Maintenance", self._maintenance_lines())
|
||||
self._draw_health_bars(right_win, right_y)
|
||||
|
||||
@@ -487,7 +489,9 @@ class ReactorDashboard:
|
||||
f"Failures: {', '.join(self.reactor.health_monitor.failure_log)}",
|
||||
curses.color_pair(4) | curses.A_BOLD,
|
||||
)
|
||||
log_y = 3
|
||||
log_y = 4
|
||||
else:
|
||||
log_y = 3
|
||||
for record in list(self.log_buffer):
|
||||
if log_y >= win.getmaxyx()[0] - 1:
|
||||
break
|
||||
@@ -599,6 +603,40 @@ class ReactorDashboard:
|
||||
]
|
||||
return lines
|
||||
|
||||
def _protection_lines(self, state: PlantState) -> list[tuple[str, str]]:
|
||||
lines: list[tuple[str, str]] = []
|
||||
lines.append(("SCRAM", "ACTIVE" if self.reactor.shutdown else "CLEAR"))
|
||||
if self.reactor.meltdown:
|
||||
lines.append(("Meltdown", "IN PROGRESS"))
|
||||
sec_flow_low = state.secondary_loop.mass_flow_rate <= 1.0 or not self.reactor.secondary_pump_active
|
||||
heat_sink_risk = sec_flow_low and state.core.power_output_mw > 50.0
|
||||
if heat_sink_risk:
|
||||
heat_text = "TRIPPED low secondary flow >50 MW"
|
||||
elif sec_flow_low:
|
||||
heat_text = "ARMED (secondary off/low flow)"
|
||||
else:
|
||||
heat_text = "OK"
|
||||
lines.append(("Heat sink", heat_text))
|
||||
|
||||
draws = getattr(state, "aux_draws", {}) or {}
|
||||
demand = draws.get("total_demand", 0.0)
|
||||
supplied = draws.get("supplied", 0.0)
|
||||
if demand > 0.1 and supplied + 1e-6 < demand:
|
||||
aux_text = f"DEFICIT {supplied:5.1f}/{demand:5.1f} MW"
|
||||
elif demand > 0.1:
|
||||
aux_text = f"OK {supplied:5.1f}/{demand:5.1f} MW"
|
||||
else:
|
||||
aux_text = "Idle"
|
||||
lines.append(("Aux power", aux_text))
|
||||
|
||||
reliefs = []
|
||||
if self.reactor.primary_relief_open:
|
||||
reliefs.append("Primary")
|
||||
if self.reactor.secondary_relief_open:
|
||||
reliefs.append("Secondary")
|
||||
lines.append(("Relief valves", ", ".join(reliefs) if reliefs else "Closed"))
|
||||
return lines
|
||||
|
||||
def _steam_pressure(self, state: PlantState) -> float:
|
||||
# Only report steam pressure if quality/flow indicate steam is present.
|
||||
if state.secondary_loop.steam_quality < 0.05 or state.secondary_loop.mass_flow_rate < 100.0:
|
||||
|
||||
Reference in New Issue
Block a user