Source code for diveplan.dive.formatters.json
"""JSON report formatter — machine-readable dive plan document."""
import json
from diveplan.dive.dive_report import DiveReport
from diveplan.dive.formatters import BaseFormatter
__all__ = ["JsonFormatter"]
[docs]
class JsonFormatter(BaseFormatter):
"""Serialize the whole report to a JSON document.
Depths in metres, durations in seconds, gases by name with exact
fractions alongside.
"""
NAME = "json"
def __init__(self, *, indent: int | None = 2):
self.indent = indent
[docs]
def format(self, report: DiveReport) -> str:
"""Render the report as a JSON document string."""
variations = None
if report.tts_variations is not None:
variations = {
"per_meter_s": report.tts_variations.per_meter.total_seconds(),
"per_minute_s": report.tts_variations.per_minute.total_seconds(),
}
document = {
"model": report.model_name,
"runtime_s": report.runtime.total_seconds(),
"max_depth_m": round(report.max_depth.depth_m, 2),
"segments": [
{
"runtime_s": row.runtime.total_seconds(),
"start_depth_m": round(row.start_depth_m, 2),
"end_depth_m": round(row.end_depth_m, 2),
"duration_s": row.duration.total_seconds(),
"gas": {
"name": row.gas.name,
"fo2": row.gas.fo2,
"fhe": row.gas.fhe,
},
"kind": row.kind,
}
for row in report.rows
],
"consumption_l": {
gas.name: round(litres, 1) for gas, litres in report.consumption_l
},
"sac": {
"bottom_l_min": report.sac_bottom,
"deco_l_min": report.sac_deco,
"rock_bottom_factor": report.sac_factor,
},
"rock_bottom_l": round(report.rock_bottom_l, 1),
"cns_percent": round(report.cns, 1),
"otu": round(report.otus, 1),
"tts_variations": variations,
}
return json.dumps(document, indent=self.indent)