feat(s54): value_report text + deterministic JSON formatters
This commit is contained in:
parent
878c989f8c
commit
dd566025a4
2 changed files with 128 additions and 0 deletions
|
|
@ -13,8 +13,11 @@ saving realized under two dimensions (the exact bug the ledger's dimension-free
|
|||
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
|
||||
from pydantic import BaseModel
|
||||
|
||||
from portfolio_optimiser.costsim import _ore_to_kr_str
|
||||
from portfolio_optimiser.ledger import SavingsLedger
|
||||
|
||||
|
||||
|
|
@ -82,3 +85,38 @@ def build_value_report(ledger: SavingsLedger) -> ValueReport:
|
|||
overlaps=ledger.overlaps(),
|
||||
provenance=provenance,
|
||||
)
|
||||
|
||||
|
||||
def format_report_text(report: ValueReport) -> str:
|
||||
"""Render the value report as a column-aligned human table: one per-project row (id + realized
|
||||
NOK), a portfolio-total footer, and an overlaps section listing the flagged
|
||||
``(project_id, candidate_identity)`` keys (or a ``ingen overlapp`` line when empty). Every øre
|
||||
value is formatted through the single byte-pinned money edge ``costsim._ore_to_kr_str``
|
||||
(float-free integer ``divmod``), and ``per_project`` is iterated in sorted key order for
|
||||
byte-stability (SC6)."""
|
||||
lines = [
|
||||
"Verdirapport — realiserte besparelser (kun-lesing, ingen modellkall)",
|
||||
"",
|
||||
f"{'prosjekt':<24} {'realisert':>16}",
|
||||
]
|
||||
for pid in sorted(report.per_project):
|
||||
lines.append(f"{pid:<24} {_ore_to_kr_str(report.per_project[pid]):>16}")
|
||||
lines += [
|
||||
"",
|
||||
f"{'portefølje totalt':<24} {_ore_to_kr_str(report.portfolio_total_ore):>16}",
|
||||
"",
|
||||
"Kryss-dimensjon overlapp (talt én gang, flagget):",
|
||||
]
|
||||
if report.overlaps:
|
||||
for project_id, candidate_identity in report.overlaps:
|
||||
lines.append(f" {project_id} / {candidate_identity}")
|
||||
else:
|
||||
lines.append(" ingen overlapp")
|
||||
return "\n".join(lines)
|
||||
|
||||
|
||||
def dump_report_json(report: ValueReport) -> str:
|
||||
"""Byte-deterministic JSON serialization of the value report (the repo-wide idiom
|
||||
``sort_keys=True, indent=2`` + trailing LF; mirrors ``costsim.dump_estimate_table`` /
|
||||
``outbox._dump``). ``overlaps`` tuples serialize to JSON arrays."""
|
||||
return json.dumps(report.model_dump(), sort_keys=True, indent=2) + "\n"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue