commit 5de1eadfd4e969030c3a04f72fbcf445062edc0a Author: Mika Date: Sat Apr 4 17:36:38 2026 +0000 Add artifact.001/src/artifact_001/core.py diff --git a/artifact.001/src/artifact_001/core.py b/artifact.001/src/artifact_001/core.py new file mode 100644 index 0000000..69bbb9c --- /dev/null +++ b/artifact.001/src/artifact_001/core.py @@ -0,0 +1,73 @@ +import json +from dataclasses import dataclass, asdict +from datetime import datetime +from pathlib import Path +from typing import Any +import os + + +@dataclass +class MeasurementLog: + """Repräsentiert einen einzelnen Messdatensatz.""" + + timestamp: datetime + measured_p: float + freeze_ok: bool + setup_fingerprint: str + policy_hash: str + + def to_serializable(self) -> dict[str, Any]: + """Wandelt das Objekt in eine JSON-kompatible Struktur um.""" + return { + "timestamp": self.timestamp.isoformat(), + "measured_p": self.measured_p, + "freeze_ok": self.freeze_ok, + "setup_fingerprint": self.setup_fingerprint, + "policy_hash": self.policy_hash, + } + + +_OUTPUT_PATH = Path("output/measurement_log.json") + + +def _validate_inputs(timestamp: datetime, measured_p: float, freeze_ok: bool, setup_fingerprint: str, policy_hash: str) -> None: + assert isinstance(timestamp, datetime), "timestamp muss vom Typ datetime sein" + assert isinstance(measured_p, (int, float)), "measured_p muss eine Zahl sein" + assert isinstance(freeze_ok, bool), "freeze_ok muss bool sein" + assert isinstance(setup_fingerprint, str) and setup_fingerprint, "setup_fingerprint darf nicht leer sein" + assert isinstance(policy_hash, str) and policy_hash, "policy_hash darf nicht leer sein" + + +def log_measurement(timestamp: datetime, measured_p: float, freeze_ok: bool, setup_fingerprint: str, policy_hash: str) -> None: + """Protokolliert einen Messdatensatz als JSON-Zeile in output/measurement_log.json. + + Fügt neue Einträge hinzu, ohne bestehende zu überschreiben. + """ + _validate_inputs(timestamp, measured_p, freeze_ok, setup_fingerprint, policy_hash) + + log_entry = MeasurementLog( + timestamp=timestamp, + measured_p=float(measured_p), + freeze_ok=freeze_ok, + setup_fingerprint=setup_fingerprint, + policy_hash=policy_hash, + ).to_serializable() + + os.makedirs(_OUTPUT_PATH.parent, exist_ok=True) + + current_data = [] + if _OUTPUT_PATH.exists(): + try: + with _OUTPUT_PATH.open("r", encoding="utf-8") as f: + content = f.read().strip() + if content: + current_data = json.loads(content) + if not isinstance(current_data, list): + current_data = [] + except (json.JSONDecodeError, OSError): + current_data = [] + + current_data.append(log_entry) + + with _OUTPUT_PATH.open("w", encoding="utf-8") as f: + json.dump(current_data, f, indent=2, ensure_ascii=False)