#pragma once #include "frame_result.hpp" #include "door_risk.hpp" namespace cms { template inline std::optional optionalField(Json const& value,char const* key) { auto it=value.find(key);return it==value.end()||it->is_null()?std::nullopt:std::optional(it->get()); } inline FrameResult makeFrameResult(Json const& record,Json const& risk, CaptureMetadata capture) { FrameResult out; out.frame_index=record.at("frame_index").get(); out.track_ids=record.at("track_ids").get>(); out.boxes=record.at("boxes").get>>(); out.capture=capture; auto& r=out.risk; r.status=risk.at("status");r.risk_score=optionalField(risk,"risk_score"); r.risk_level=risk.at("risk_level");r.decision=risk.at("decision"); r.source=optionalField(risk,"source");r.track_id=optionalField(risk,"track_id");r.side=optionalField(risk,"side"); auto const& d=risk.at("door_mask"); r.door_mask={d.at("status"),d.at("annotation_index"),optionalField(d,"path"),d.at("format"),d.at("area_px")}; r.warning_distance_relative=risk.at("warning_distance_relative");r.release_distance_relative=risk.at("release_distance_relative"); for(auto const& j:risk.at("regions")) { RegionRisk v; v.status=j.at("status");v.risk_score=optionalField(j,"risk_score"); v.risk_level=j.at("risk_level");v.decision=j.at("decision");v.source=j.at("source"); v.track_id=j.at("track_id");v.side=j.at("side");v.state=optionalField(j,"state"); v.region_area_px=optionalField(j,"region_area_px");v.door_overlap_px=optionalField(j,"door_overlap_px"); v.region_overlap_ratio=optionalField(j,"region_overlap_ratio");v.min_distance_px=optionalField(j,"min_distance_px"); v.region_scale_px=optionalField(j,"region_scale_px");v.distance_relative=optionalField(j,"distance_relative"); r.regions.push_back(std::move(v)); } return out; } }