1use chrono::{DateTime, NaiveDate, Utc};
9use serde::{Deserialize, Serialize};
10
11use crate::models::{NetRelation, Netelement};
12
13pub const DEFAULT_RETRIEVAL_BUFFER_METERS: f64 = 1000.0;
15
16pub const DEFAULT_RINF_ENDPOINT: &str = "https://graph.data.era.europa.eu/repositories/rinf-plus";
18
19pub const COARSE_GEOMETRY_LENGTH_THRESHOLD_METERS: f64 = 250.0;
21
22#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
24pub struct RetrievalArea {
25 pub min_longitude: f64,
26 pub max_longitude: f64,
27 pub min_latitude: f64,
28 pub max_latitude: f64,
29 pub expansion_meters: f64,
30 pub polygon_wkt: String,
31 pub source_crs: String,
32}
33
34#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
36#[serde(rename_all = "snake_case")]
37pub enum WorkflowKind {
38 Projection,
39 PathCalculation,
40 DetectionPreparation,
41 PathReview,
42}
43
44#[derive(Debug, Clone, Serialize, Deserialize)]
46pub struct AutoTopologyRequest {
47 pub workflow_kind: WorkflowKind,
48 pub supplied_topology_present: bool,
49 pub rinf_endpoint_url: String,
50 pub retrieval_area: Option<RetrievalArea>,
51 pub requested_at: DateTime<Utc>,
52}
53
54#[derive(Debug, Clone, Serialize, Deserialize)]
56pub struct RinfNetelementRow {
57 pub netelement_iri: String,
58 pub netelement_id: String,
59 pub wkt: String,
60 pub geometry_point_count: usize,
61 pub length_meters: f64,
62}
63
64#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
66#[serde(rename_all = "PascalCase")]
67pub enum RinfNavigability {
68 Both,
69 AB,
71 BA,
73 None,
74}
75
76#[derive(Debug, Clone, Serialize, Deserialize)]
78pub struct RinfNetrelationRow {
79 pub netrelation_iri: String,
80 pub element_a_id: String,
81 pub element_b_id: String,
82 pub is_on_origin_of_element_a: bool,
83 pub is_on_origin_of_element_b: bool,
84 pub navigability: RinfNavigability,
85 pub valid_on_date: NaiveDate,
86}
87
88#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
90#[serde(rename_all = "snake_case")]
91pub enum TopologyValidationStatus {
92 Valid,
93 MissingCoverage,
94 IncompleteTopology,
95 InvalidInput,
96 EndpointFailure,
97}
98
99#[derive(Debug, Clone, Serialize, Deserialize)]
101pub struct TopologyValidationReport {
102 pub status: TopologyValidationStatus,
103 pub netelement_count: usize,
104 pub netrelation_count: usize,
105 pub coarse_geometry_ids: Vec<String>,
106 pub uncovered_gnss_indices: Vec<usize>,
107 pub message: String,
108}
109
110#[derive(Debug, Clone, Serialize, Deserialize)]
112pub struct RetrievedTopology {
113 pub netelements: Vec<Netelement>,
114 pub netrelations: Vec<NetRelation>,
115 pub retrieval_area: RetrievalArea,
116 pub endpoint_url: String,
117 pub retrieved_at: DateTime<Utc>,
118 pub validation_report: TopologyValidationReport,
119}
120
121#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
123#[serde(rename_all = "snake_case")]
124pub enum TopologySource {
125 SuppliedTopology,
126 EraRinf,
127}
128
129#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
131#[serde(rename_all = "snake_case")]
132pub enum RetrievalStatus {
133 Success,
134 InvalidInput,
135 MissingCoverage,
136 IncompleteTopology,
137 EndpointFailure,
138}
139
140#[derive(Debug, Clone, Serialize, Deserialize)]
142pub struct RetrievalOutcome {
143 pub source_used: TopologySource,
144 pub status: RetrievalStatus,
145 pub detail_message: String,
146 pub diagnostic_area_wkt: Option<String>,
147 pub affected_gnss_indices: Vec<usize>,
148}
149
150impl RetrievalOutcome {
151 pub fn supplied_success() -> Self {
152 Self {
153 source_used: TopologySource::SuppliedTopology,
154 status: RetrievalStatus::Success,
155 detail_message: "Using supplied topology".to_string(),
156 diagnostic_area_wkt: None,
157 affected_gnss_indices: Vec::new(),
158 }
159 }
160}