fix: params page cfg=None + hot-reload config chaque jour

dashboard/app.py:
  load_sim_config() retourne None (pas {}) quand le fichier est absent
  — {} est falsy en Python, masquait le formulaire même quand la config
  était chargeable mais vide. None est explicitement distinguable.
  load_all_modes() charge toujours depuis sim_001.json (référence 5 modes)
  — sim_002 n'a qu'un seul mode dans son bloc 'modes', le tableau comparatif
  était vide pour S2.
  {% if cfg is not none %} dans le template au lieu de {% if cfg %}
  Message d'avertissement sous le bouton save : prise en compte au prochain jour
  Message d'erreur précis si fichier introuvable (path + hint mount Docker)
  /params/save: vérification if cfg is None

run.py:
  Hot-reload config à chaque tick==0 (frontière de jour) :
    cfg.load(config_path, session_id=SESSION_ID)
    effective_mode mis à jour depuis la config rechargée
    tick_sleep recalculé (TICK_SLEEP_SEC env var prime toujours)
  → Changer mode/drain/encounter via dashboard prend effet le jour suivant
    sans redémarrer le process
This commit is contained in:
Corback
2026-06-16 08:25:59 +00:00
parent dd985c868c
commit 99bd77e18b
2 changed files with 30 additions and 9 deletions
+25 -8
View File
@@ -47,13 +47,21 @@ def execute(sql, params=None):
finally:
conn.close()
def load_sim_config(session_id: int) -> dict:
_REFERENCE_CONFIG_ID = 1 # sim_001.json = référence pour la liste des modes
def load_sim_config(session_id: int) -> dict | None:
"""Retourne le cfg JSON ou None si introuvable (None est falsy ET distinguable de {})."""
path = os.path.join(SIM_CONFIGS_DIR, f"sim_{session_id:03d}.json")
try:
with open(path) as f:
return json.load(f)
except Exception:
return {}
except Exception as e:
return None
def load_all_modes() -> dict:
"""Charge les modes depuis sim_001.json (référence complète des 5 modes)."""
cfg = load_sim_config(_REFERENCE_CONFIG_ID) or {}
return cfg.get("modes", {})
def save_sim_config(session_id: int, cfg: dict):
path = os.path.join(SIM_CONFIGS_DIR, f"sim_{session_id:03d}.json")
@@ -407,7 +415,7 @@ if (el) {
<div class="panel">
<h2>⚙ CONFIG SIM_{{ '%03d' % current_sid }}.JSON</h2>
<form method="POST" action="/params/save?sid={{ current_sid }}">
{% if cfg %}
{% if cfg is not none %}
<div class="cfg-block">
<h3>GÉNÉRAL</h3>
@@ -466,8 +474,17 @@ if (el) {
</div>
<button type="submit" class="btn btn-green">💾 SAUVEGARDER CONFIG</button>
<p style="margin-top:6px;font-size:10px;color:#555">
⚠ Prise en compte au prochain jour (J{{ (session.current_day or 0) + 1 }}).
Pour effet immédiat : STOP → relancer via terminal.
</p>
{% else %}
<p style="color:#ff4444;font-size:11px">Fichier sim_{{ '%03d' % current_sid }}.json introuvable dans {{ sim_configs_dir }}</p>
<p style="color:#ff4444;font-size:11px">
Fichier <code>sim_{{ '%03d' % current_sid }}.json</code> introuvable dans <code>{{ sim_configs_dir }}</code>
</p>
<p style="color:#555;font-size:10px;margin-top:4px">
Vérifier le mount Docker : /home/ubuntu/fallout-venice/src/config → /app/src/config
</p>
{% endif %}
</form>
</div>
@@ -673,7 +690,7 @@ def params():
sid = int(request.args.get("sid", all_sessions[-1]["id"] if all_sessions else 1))
session = query_one("SELECT * FROM sessions WHERE id = %s", (sid,))
cfg = load_sim_config(sid)
modes = cfg.get("modes", {})
modes = load_all_modes() # toujours les 5 modes depuis sim_001 (référence)
flash_msg = request.args.get("msg")
flash_ok = request.args.get("ok", "1") == "1"
return render_template_string(TEMPLATE,
@@ -697,8 +714,8 @@ def params():
def params_save():
sid = int(request.args.get("sid", 1))
cfg = load_sim_config(sid)
if not cfg:
return redirect(url_for("params", sid=sid, msg="Fichier config introuvable", ok=0))
if cfg is None:
return redirect(url_for("params", sid=sid, msg=f"Fichier sim_{sid:03d}.json introuvable dans {SIM_CONFIGS_DIR}", ok=0))
f = request.form