feat: instrument model
This commit is contained in:
102
backend/routers/instrument_models.py
Normal file
102
backend/routers/instrument_models.py
Normal file
@@ -0,0 +1,102 @@
|
||||
"""
|
||||
Instrument Models Router — graphes causaux exhaustifs par instrument.
|
||||
"""
|
||||
from typing import Any, Dict, List, Optional
|
||||
from fastapi import APIRouter, HTTPException, Query
|
||||
from pydantic import BaseModel
|
||||
|
||||
router = APIRouter(prefix="/api/instrument-models", tags=["instrument-models"])
|
||||
|
||||
|
||||
class OverrideBody(BaseModel):
|
||||
value: float
|
||||
note: Optional[str] = ""
|
||||
|
||||
|
||||
@router.get("", response_model=List[Dict[str, Any]])
|
||||
def list_instrument_models():
|
||||
"""Liste tous les modèles (métadonnées, sans valeurs calculées)."""
|
||||
from services.database import get_conn
|
||||
from services.instrument_models import INSTRUMENT_MODELS
|
||||
conn = get_conn()
|
||||
try:
|
||||
rows = conn.execute(
|
||||
"SELECT instrument, updated_at FROM instrument_models ORDER BY instrument"
|
||||
).fetchall()
|
||||
result = []
|
||||
for r in rows:
|
||||
inst = r["instrument"]
|
||||
meta = INSTRUMENT_MODELS.get(inst, {})
|
||||
node_counts = {"structural": 0, "event_driven": 0, "output": 0}
|
||||
for n in meta.get("nodes", []):
|
||||
node_counts[n.get("type", "structural")] = node_counts.get(n.get("type", "structural"), 0) + 1
|
||||
result.append({
|
||||
"instrument": inst,
|
||||
"name": meta.get("name", inst),
|
||||
"description": meta.get("description", ""),
|
||||
"n_structural": node_counts["structural"],
|
||||
"n_event_driven": node_counts["event_driven"],
|
||||
"updated_at": r["updated_at"],
|
||||
})
|
||||
return result
|
||||
finally:
|
||||
conn.close()
|
||||
|
||||
|
||||
@router.get("/{instrument}")
|
||||
def get_instrument_model(
|
||||
instrument: str,
|
||||
at_date: Optional[str] = Query(None, description="YYYY-MM-DD (défaut: aujourd'hui)"),
|
||||
) -> Dict[str, Any]:
|
||||
"""Graphe complet avec valeurs courantes des nœuds."""
|
||||
from services.database import get_conn
|
||||
from services.instrument_models import get_model_state
|
||||
conn = get_conn()
|
||||
try:
|
||||
state = get_model_state(conn, instrument.upper(), at_date)
|
||||
if not state:
|
||||
raise HTTPException(status_code=404, detail=f"Modèle introuvable pour {instrument.upper()}")
|
||||
return state
|
||||
finally:
|
||||
conn.close()
|
||||
|
||||
|
||||
@router.put("/{instrument}/nodes/{node_id}/override")
|
||||
def set_override(instrument: str, node_id: str, body: OverrideBody) -> Dict[str, Any]:
|
||||
"""Définit ou met à jour la valeur manuelle d'un nœud structurel."""
|
||||
from services.database import get_conn
|
||||
from services.instrument_models import set_node_override
|
||||
conn = get_conn()
|
||||
try:
|
||||
set_node_override(conn, instrument.upper(), node_id, body.value, body.note or "")
|
||||
return {"ok": True, "instrument": instrument.upper(), "node_id": node_id, "value": body.value}
|
||||
finally:
|
||||
conn.close()
|
||||
|
||||
|
||||
@router.delete("/{instrument}/nodes/{node_id}/override")
|
||||
def clear_override(instrument: str, node_id: str) -> Dict[str, Any]:
|
||||
"""Supprime l'override manuel d'un nœud (retour à valeur neutre / events)."""
|
||||
from services.database import get_conn
|
||||
from services.instrument_models import clear_node_override
|
||||
conn = get_conn()
|
||||
try:
|
||||
clear_node_override(conn, instrument.upper(), node_id)
|
||||
return {"ok": True, "instrument": instrument.upper(), "node_id": node_id}
|
||||
finally:
|
||||
conn.close()
|
||||
|
||||
|
||||
@router.get("/{instrument}/nodes/{node_id}/overrides")
|
||||
def get_node_overrides(instrument: str) -> List[Dict[str, Any]]:
|
||||
"""Toutes les overrides manuelles pour un instrument."""
|
||||
from services.database import get_conn
|
||||
conn = get_conn()
|
||||
try:
|
||||
rows = conn.execute(
|
||||
"SELECT node_id, value, note, set_at FROM instrument_node_overrides WHERE instrument=? ORDER BY set_at DESC",
|
||||
(instrument.upper(),)
|
||||
).fetchall()
|
||||
return [dict(r) for r in rows]
|
||||
finally:
|
||||
conn.close()
|
||||
Reference in New Issue
Block a user