NeonClary
Add Decidron network simulator
808ab9a
Raw
History Blame Contribute Delete
1.97 kB
"""Performance statistics for the Decidron simulator.
Aggregates per-sensor, per-command, and per-output counts plus latency
and last-run timestamps -- a deterministic stand-in for the patent's
"results determined and scored" step.
"""
from __future__ import annotations
import time
from collections import defaultdict
class StatsCollector:
def __init__(self) -> None:
self.sensors: dict[str, dict] = defaultdict(self._blank)
self.commands: dict[str, dict] = defaultdict(self._blank)
self.outputs: dict[str, dict] = defaultdict(self._blank)
self.total_runs: int = 0
self.total_matches: int = 0
@staticmethod
def _blank() -> dict:
return {"count": 0, "matches": 0, "last_run": None, "avg_latency_ms": 0.0}
@staticmethod
def _update(bucket: dict, matched: bool, latency_ms: float) -> None:
n = bucket["count"]
bucket["count"] = n + 1
if matched:
bucket["matches"] += 1
# incremental average latency
bucket["avg_latency_ms"] = (bucket["avg_latency_ms"] * n + latency_ms) / (n + 1)
bucket["last_run"] = time.time()
def record(
self,
sensor: str,
command: str,
output: str | None,
matched: bool,
latency_ms: float,
) -> None:
self.total_runs += 1
if matched:
self.total_matches += 1
self._update(self.sensors[sensor], matched, latency_ms)
self._update(self.commands[command], matched, latency_ms)
if matched and output:
self._update(self.outputs[output], True, latency_ms)
def reset(self) -> None:
self.__init__()
def as_dict(self) -> dict:
return {
"total_runs": self.total_runs,
"total_matches": self.total_matches,
"per_sensor": dict(self.sensors),
"per_command": dict(self.commands),
"per_output": dict(self.outputs),
}