map and chainage calculation

This commit is contained in:
2026-07-07 22:42:47 +05:30
parent 05ce1f2cdb
commit 308d6bc129
17 changed files with 4178 additions and 48 deletions

View File

@@ -148,6 +148,24 @@ pub struct VideoRow {
// pending | annotated | assigned | in-progress | verified | re-verified.
pub assigned_to: Option<String>,
pub workflow_status: String,
// Road type label ('' = unassigned) — injected into the export/claim JSON.
pub road_type: String,
// GPS pipeline: pending | ok | none | error (+ measured track length / last error).
pub gps_status: String,
pub gps_len_m: Option<f64>,
pub gps_error: Option<String>,
// Data quality: raw fix count + biggest dropout — the table compares the count
// against the video duration (≈1 fix/s) and flags mismatches.
pub gps_sample_count: Option<i32>,
pub gps_max_gap_s: Option<f64>,
// Real container duration from the scan (raw NAS videos have no fps/frame_count).
pub duration_s: Option<f64>,
// Client-calibrated chainage + the immutable GPS-measured (sr) chainage, meters.
pub chainage_start_m: Option<f64>,
pub chainage_end_m: Option<f64>,
pub sr_chainage_start_m: Option<f64>,
pub sr_chainage_end_m: Option<f64>,
pub route_seq: Option<i32>,
// "Raise hand" signal — anyone may raise (to start a conversation) or lower it.
pub hand_raised: bool,
pub hand_raised_by: Option<String>,
@@ -163,6 +181,61 @@ pub struct VideoRow {
pub passes: serde_json::Value,
}
/// One row of `GET /api/projects/:id/map` — a video as the map sees it. `track` is
/// the (transport-downsampled) effective polyline: corrected when kept, else raw;
/// None until the GPS sweep has scanned the video (or when it has no metadata).
#[derive(Serialize, sqlx::FromRow)]
pub struct MapVideo {
pub id: i32,
pub file_name: String,
pub rel_path: String,
pub status: String,
pub workflow_status: String,
pub ignored: bool,
pub hand_raised: bool,
pub assigned_to: Option<String>,
pub claimed_by: Option<String>,
pub annotation_count: i32,
pub road_type: String,
pub gps_status: String,
pub gps_len_m: Option<f64>,
pub gps_error: Option<String>,
pub chainage_start_m: Option<f64>,
pub chainage_end_m: Option<f64>,
pub sr_chainage_start_m: Option<f64>,
pub sr_chainage_end_m: Option<f64>,
pub route_seq: Option<i32>,
pub remark_count: i64,
pub track: Option<Value>,
pub corrected: bool,
// Who/what produced the correction ('auto' or a username) + its summary note.
pub gps_corrected_by: Option<String>,
pub gps_corrected_note: Option<String>,
// Data quality from the raw scan: fix count + biggest dropout between fixes.
pub gps_sample_count: Option<i32>,
pub gps_max_gap_s: Option<f64>,
}
/// `GET /api/projects/:id/road_types` — a label + how many videos carry it.
#[derive(Serialize, sqlx::FromRow)]
pub struct RoadTypeRow {
pub name: String,
pub video_count: i64,
}
/// `POST /api/projects/:id/road_types {names}` — replace the label set (admin).
#[derive(Deserialize)]
pub struct RoadTypesRequest {
pub names: Vec<String>,
}
/// `POST /api/projects/:id/road_type_assign {video_ids, road_type}` — bulk-assign.
#[derive(Deserialize)]
pub struct RoadTypeAssignRequest {
pub video_ids: Vec<i32>,
pub road_type: String, // '' = clear
}
/// `POST /api/videos/:id/hand {raised}` — raise/lower the hand on a video.
#[derive(Deserialize)]
pub struct HandRequest {