Polish curses dashboard warnings and turbine/generator layout
This commit is contained in:
@@ -486,33 +486,29 @@ class ReactorDashboard:
|
||||
[
|
||||
("Turbines", " ".join(self._turbine_status_lines())),
|
||||
("Rated Elec", f"{len(self.reactor.turbines)*self.reactor.turbines[0].rated_output_mw:7.1f} MW"),
|
||||
("Steam Avail", f"{self._steam_available_power(state):7.1f} MW"),
|
||||
("Unit1 Elec", f"{state.turbines[0].electrical_output_mw:7.1f} MW" if state.turbines else "n/a"),
|
||||
(
|
||||
"Unit2 Elec",
|
||||
f"{state.turbines[1].electrical_output_mw:7.1f} MW" if len(state.turbines) > 1 else "n/a",
|
||||
"Steam",
|
||||
f"h={state.turbines[0].steam_enthalpy:5.0f} kJ/kg avail {self._steam_available_power(state):6.1f} MW "
|
||||
f"flow {state.secondary_loop.mass_flow_rate * max(0.0, state.secondary_loop.steam_quality):6.0f} kg/s"
|
||||
if state.turbines
|
||||
else "n/a",
|
||||
),
|
||||
(
|
||||
"Unit3 Elec",
|
||||
f"{state.turbines[2].electrical_output_mw:7.1f} MW" if len(state.turbines) > 2 else "n/a",
|
||||
"Units Elec",
|
||||
" ".join([f"{t.electrical_output_mw:6.1f}MW" for t in state.turbines]) if state.turbines else "n/a",
|
||||
),
|
||||
("Throttle", f"{self.reactor.turbines[0].throttle:5.2f}" if self.reactor.turbines else "n/a"),
|
||||
(
|
||||
"Condenser",
|
||||
(
|
||||
f"P={state.turbines[0].condenser_pressure:4.2f}/{constants.CONDENSER_MAX_PRESSURE_MPA:4.2f} MPa "
|
||||
f"T={state.turbines[0].condenser_temperature:6.1f}/{constants.CONDENSER_COOLING_WATER_TEMP_K:6.1f}K "
|
||||
f"Foul={state.turbines[0].fouling_penalty*100:4.1f}%"
|
||||
f"T={state.turbines[0].condenser_temperature:6.1f}K Foul={state.turbines[0].fouling_penalty*100:4.1f}%"
|
||||
)
|
||||
if state.turbines
|
||||
else "n/a",
|
||||
),
|
||||
("Electrical", f"{state.total_electrical_output():7.1f} MW"),
|
||||
("Load", f"{self._total_load_supplied(state):7.1f}/{self._total_load_demand(state):7.1f} MW"),
|
||||
("Consumer", f"{consumer_status}"),
|
||||
("Demand", f"{consumer_demand:7.1f} MW"),
|
||||
("Steam Enthalpy", f"{state.turbines[0].steam_enthalpy:7.0f} kJ/kg" if state.turbines else "n/a"),
|
||||
("Steam Flow", f"{state.secondary_loop.mass_flow_rate * max(0.0, state.secondary_loop.steam_quality):7.0f} kg/s"),
|
||||
("Electrical", f"{state.total_electrical_output():7.1f} MW | Load {self._total_load_supplied(state):6.1f}/{self._total_load_demand(state):6.1f} MW"),
|
||||
("Consumer", f"{consumer_status} demand {consumer_demand:6.1f} MW"),
|
||||
],
|
||||
)
|
||||
right_y = self._draw_section(right_win, right_y, "Generators", self._generator_lines(state))
|
||||
@@ -594,7 +590,7 @@ class ReactorDashboard:
|
||||
win: "curses._CursesWindow",
|
||||
start_y: int,
|
||||
title: str,
|
||||
lines: list[tuple[str, str] | str],
|
||||
lines: list[tuple[str, str] | tuple[str, str, int] | str],
|
||||
) -> int:
|
||||
height, width = win.getmaxyx()
|
||||
inner_width = width - 4
|
||||
@@ -605,12 +601,16 @@ class ReactorDashboard:
|
||||
for line in lines:
|
||||
if row >= height - 1:
|
||||
break
|
||||
attr = 0
|
||||
if isinstance(line, tuple):
|
||||
if len(line) == 3:
|
||||
label, value, attr = line
|
||||
else:
|
||||
label, value = line
|
||||
text = f"{label:<18}: {value}"
|
||||
else:
|
||||
text = line
|
||||
win.addstr(row, 4, text[:inner_width])
|
||||
win.addstr(row, 4, text[:inner_width], attr)
|
||||
row += 1
|
||||
return row + 1
|
||||
|
||||
@@ -730,37 +730,44 @@ class ReactorDashboard:
|
||||
]
|
||||
|
||||
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"))
|
||||
lines: list[tuple[str, str] | tuple[str, str, int]] = []
|
||||
lines.append(("SCRAM", "ACTIVE" if self.reactor.shutdown else "CLEAR", curses.color_pair(4) if self.reactor.shutdown else 0))
|
||||
if self.reactor.meltdown:
|
||||
lines.append(("Meltdown", "IN PROGRESS"))
|
||||
lines.append(("Meltdown", "IN PROGRESS", curses.color_pair(4) | curses.A_BOLD))
|
||||
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"
|
||||
heat_attr = curses.color_pair(4) | curses.A_BOLD
|
||||
elif sec_flow_low:
|
||||
heat_text = "ARMED (secondary off/low flow)"
|
||||
heat_attr = curses.color_pair(2) | curses.A_BOLD
|
||||
else:
|
||||
heat_text = "OK"
|
||||
lines.append(("Heat sink", heat_text))
|
||||
heat_attr = curses.color_pair(3)
|
||||
lines.append(("Heat sink", heat_text, heat_attr))
|
||||
|
||||
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"
|
||||
aux_attr = curses.color_pair(2) | curses.A_BOLD
|
||||
elif demand > 0.1:
|
||||
aux_text = f"OK {supplied:5.1f}/{demand:5.1f} MW"
|
||||
aux_attr = curses.color_pair(3)
|
||||
else:
|
||||
aux_text = "Idle"
|
||||
lines.append(("Aux power", aux_text))
|
||||
aux_attr = 0
|
||||
lines.append(("Aux power", aux_text, aux_attr))
|
||||
|
||||
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"))
|
||||
relief_attr = curses.color_pair(2) | curses.A_BOLD if reliefs else 0
|
||||
lines.append(("Relief valves", ", ".join(reliefs) if reliefs else "Closed", relief_attr))
|
||||
lines.append(
|
||||
(
|
||||
"SCRAM trips",
|
||||
@@ -874,7 +881,13 @@ class _DashboardLogHandler(logging.Handler):
|
||||
msg = self.format(record)
|
||||
if msg == self._last_msg:
|
||||
self._repeat_count += 1
|
||||
if self._repeat_count > 3:
|
||||
if self.buffer and self.buffer[-1].startswith(self._last_msg):
|
||||
try:
|
||||
self.buffer[-1] = f"{self._last_msg} (x{self._repeat_count + 1})"
|
||||
except Exception:
|
||||
self.buffer.append(f"{msg} (x{self._repeat_count + 1})")
|
||||
else:
|
||||
self.buffer.append(f"{msg} (x{self._repeat_count + 1})")
|
||||
return
|
||||
else:
|
||||
self._last_msg = msg
|
||||
|
||||
Reference in New Issue
Block a user