summaryrefslogtreecommitdiffstats
path: root/server/src/datex2.cppm
diff options
context:
space:
mode:
authorRutger Broekhoff2026-08-28 22:17:10 +0200
committerRutger Broekhoff2026-08-28 22:17:10 +0200
commit70643a9e4821bd11c3f363f1708fe420965467d1 (patch)
tree65572b58e247248846628940a2aaca197a15d784 /server/src/datex2.cppm
parent173cd34bdd0717d3f4beeac76b3296ecd46ada0d (diff)
downloadroutemon-70643a9e4821bd11c3f363f1708fe420965467d1.tar.gz
routemon-70643a9e4821bd11c3f363f1708fe420965467d1.zip
Format again
Diffstat (limited to 'server/src/datex2.cppm')
-rw-r--r--server/src/datex2.cppm142
1 files changed, 71 insertions, 71 deletions
diff --git a/server/src/datex2.cppm b/server/src/datex2.cppm
index b4c795f..7c20347 100644
--- a/server/src/datex2.cppm
+++ b/server/src/datex2.cppm
@@ -31,7 +31,7 @@ export struct situation
31{ 31{
32 std::string id; 32 std::string id;
33 std::optional<geo::point> location = 33 std::optional<geo::point> location =
34 std::nullopt; // as shown on the map, not used for querying 34 std::nullopt; // as shown on the map, not used for querying
35 std::vector<std::string> comments = {}; 35 std::vector<std::string> comments = {};
36 std::vector<std::shared_ptr<road_closure>> road_closures = {}; 36 std::vector<std::shared_ptr<road_closure>> road_closures = {};
37}; 37};
@@ -54,13 +54,13 @@ export class loader
54{ 54{
55 // ETRS 89 (EPSG:4258) -> WGS 84 (EPSG:4326) 55 // ETRS 89 (EPSG:4258) -> WGS 84 (EPSG:4326)
56 bgeo::srs::transformation< 56 bgeo::srs::transformation<
57 bgeo::srs::static_epsg<4258>, bgeo::srs::static_epsg<4326>> 57 bgeo::srs::static_epsg<4258>, bgeo::srs::static_epsg<4326>>
58 etrs89_to_wgs84_{}; 58 etrs89_to_wgs84_{};
59 59
60 std::multiset<std::string> warnings_; 60 std::multiset<std::string> warnings_;
61 61
62 auto add_location_from_xml(road_closure& rc, pugi::xml_node const& loc_xml) 62 auto add_location_from_xml(road_closure& rc, pugi::xml_node const& loc_xml)
63 -> void 63 -> void
64 { 64 {
65 auto loc_xml_type = std::string_view{loc_xml.attribute("xsi:type").value()}; 65 auto loc_xml_type = std::string_view{loc_xml.attribute("xsi:type").value()};
66 if (loc_xml_type == "loc:ItineraryByIndexedLocations") 66 if (loc_xml_type == "loc:ItineraryByIndexedLocations")
@@ -79,15 +79,15 @@ export class loader
79 return; 79 return;
80 80
81 auto const srs_name = 81 auto const srs_name =
82 std::string_view{loc_gml_xml.attribute("srsName").value()}; 82 std::string_view{loc_gml_xml.attribute("srsName").value()};
83 if (srs_name != "WGS 84"sv) 83 if (srs_name != "WGS 84"sv)
84 { 84 {
85 warnings_.insert( 85 warnings_.insert(
86 std::format("don't now how to handle the CRS {}", srs_name)); 86 std::format("don't now how to handle the CRS {}", srs_name));
87 return; 87 return;
88 } 88 }
89 auto const pos_list_str = 89 auto const pos_list_str =
90 std::string_view{loc_gml_xml.child_value("loc:posList")}; 90 std::string_view{loc_gml_xml.child_value("loc:posList")};
91 // lat1 long1 lat2 long2 ... lat(n-1) long(n-1) latn longn 91 // lat1 long1 lat2 long2 ... lat(n-1) long(n-1) latn longn
92 92
93 auto ls = std::make_shared<geo::linestring>(); 93 auto ls = std::make_shared<geo::linestring>();
@@ -97,13 +97,13 @@ export class loader
97 for (auto const lat_or_long_str : std::views::split(pos_list_str, " "sv)) 97 for (auto const lat_or_long_str : std::views::split(pos_list_str, " "sv))
98 { 98 {
99 auto mlat_or_long = 99 auto mlat_or_long =
100 util::parse_double(std::string_view{lat_or_long_str}); 100 util::parse_double(std::string_view{lat_or_long_str});
101 if (!mlat_or_long) 101 if (!mlat_or_long)
102 { 102 {
103 warnings_.insert( 103 warnings_.insert(
104 std::format( 104 std::format(
105 "failed to parse coordinate {:?}", 105 "failed to parse coordinate {:?}",
106 std::string_view{lat_or_long_str})); 106 std::string_view{lat_or_long_str}));
107 return; 107 return;
108 } 108 }
109 109
@@ -131,7 +131,7 @@ export class loader
131 else if (loc_xml_type == "loc:PointLocation") 131 else if (loc_xml_type == "loc:PointLocation")
132 { 132 {
133 auto const& coords_xml = 133 auto const& coords_xml =
134 loc_xml.child("loc:pointByCoordinates").child("loc:pointCoordinates"); 134 loc_xml.child("loc:pointByCoordinates").child("loc:pointCoordinates");
135 if (!coords_xml) 135 if (!coords_xml)
136 return; 136 return;
137 137
@@ -157,28 +157,28 @@ export class loader
157 else 157 else
158 { 158 {
159 warnings_.insert( 159 warnings_.insert(
160 std::format( 160 std::format(
161 "don't know how to hande location of type {}, ignoring", 161 "don't know how to hande location of type {}, ignoring",
162 loc_xml.attribute("xsi:type").value())); 162 loc_xml.attribute("xsi:type").value()));
163 return; 163 return;
164 } 164 }
165 } 165 }
166 166
167 auto handle_road_or_carriageway_or_lane_management( 167 auto handle_road_or_carriageway_or_lane_management(
168 pugi::xml_node const& record_xml, std::weak_ptr<situation> parent) 168 pugi::xml_node const& record_xml, std::weak_ptr<situation> parent)
169 -> std::optional<std::shared_ptr<road_closure>> 169 -> std::optional<std::shared_ptr<road_closure>>
170 { 170 {
171 auto const type = 171 auto const type =
172 std::string_view{record_xml 172 std::string_view{record_xml
173 .child("sit:roadOrCarriagewayOrLaneManagementType") 173 .child("sit:roadOrCarriagewayOrLaneManagementType")
174 .child_value()}; 174 .child_value()};
175 if (type != "carriagewayClosures" && type != "roadClosed") 175 if (type != "carriagewayClosures" && type != "roadClosed")
176 // TODO: checken of er nog andere types fietsers de doorgang zouden 176 // TODO: checken of er nog andere types fietsers de doorgang zouden
177 // kunnen blokkeren? 177 // kunnen blokkeren?
178 return std::nullopt; 178 return std::nullopt;
179 179
180 auto const& restricted_vehicle_types_xml = 180 auto const& restricted_vehicle_types_xml =
181 record_xml.child("sit:forVehiclesWithCharacteristicsOf"); 181 record_xml.child("sit:forVehiclesWithCharacteristicsOf");
182 bool likely_restriction_for_bikes = restricted_vehicle_types_xml.empty(); 182 bool likely_restriction_for_bikes = restricted_vehicle_types_xml.empty();
183 for (auto const vehicle_type_xml : 183 for (auto const vehicle_type_xml :
184 restricted_vehicle_types_xml.children("com:vehicleType")) 184 restricted_vehicle_types_xml.children("com:vehicleType"))
@@ -199,20 +199,20 @@ export class loader
199 auto const& validity_xml = record_xml.child("sit:validity"); 199 auto const& validity_xml = record_xml.child("sit:validity");
200 if (validity_xml 200 if (validity_xml
201 && validity_xml.child_value("com:validityStatus") 201 && validity_xml.child_value("com:validityStatus")
202 == "definedByValidityTimeSpec"sv) 202 == "definedByValidityTimeSpec"sv)
203 { 203 {
204 auto const& validity_spec_xml = 204 auto const& validity_spec_xml =
205 validity_xml.child("com:validityTimeSpecification"); 205 validity_xml.child("com:validityTimeSpecification");
206 206
207 auto valid_periods = std::vector<time::period>{}; 207 auto valid_periods = std::vector<time::period>{};
208 auto exception_periods = std::vector<time::period>{}; 208 auto exception_periods = std::vector<time::period>{};
209 209
210 // TODO: com:overallEndTime may be missing (according to the DATEX 210 // TODO: com:overallEndTime may be missing (according to the DATEX
211 // II v3 data model) 211 // II v3 data model)
212 auto const overall_start_time = parse_timestamp( 212 auto const overall_start_time =
213 validity_spec_xml.child_value("com:overallStartTime")); 213 parse_timestamp(validity_spec_xml.child_value("com:overallStartTime"));
214 auto const overall_end_time = 214 auto const overall_end_time =
215 parse_timestamp(validity_spec_xml.child_value("com:overallEndTime")); 215 parse_timestamp(validity_spec_xml.child_value("com:overallEndTime"));
216 if (overall_start_time && overall_end_time 216 if (overall_start_time && overall_end_time
217 && *overall_start_time < *overall_end_time) 217 && *overall_start_time < *overall_end_time)
218 { 218 {
@@ -221,10 +221,10 @@ export class loader
221 for (auto const valid_period_xml : 221 for (auto const valid_period_xml :
222 validity_xml.children("com:validPeriod")) 222 validity_xml.children("com:validPeriod"))
223 { 223 {
224 auto const start_of_period = parse_timestamp( 224 auto const start_of_period =
225 valid_period_xml.child_value("com:startOfPeriod")); 225 parse_timestamp(valid_period_xml.child_value("com:startOfPeriod"));
226 auto const end_of_period = 226 auto const end_of_period =
227 parse_timestamp(valid_period_xml.child_value("com:endOfPeriod")); 227 parse_timestamp(valid_period_xml.child_value("com:endOfPeriod"));
228 if (start_of_period && end_of_period 228 if (start_of_period && end_of_period
229 && *start_of_period < *end_of_period) 229 && *start_of_period < *end_of_period)
230 { 230 {
@@ -235,9 +235,9 @@ export class loader
235 validity_xml.children("com:exceptionPeriod")) 235 validity_xml.children("com:exceptionPeriod"))
236 { 236 {
237 auto const start_of_period = parse_timestamp( 237 auto const start_of_period = parse_timestamp(
238 exception_period_xml.child_value("com:startOfPeriod")); 238 exception_period_xml.child_value("com:startOfPeriod"));
239 auto const end_of_period = parse_timestamp( 239 auto const end_of_period = parse_timestamp(
240 exception_period_xml.child_value("com:endOfPeriod")); 240 exception_period_xml.child_value("com:endOfPeriod"));
241 if (start_of_period && end_of_period 241 if (start_of_period && end_of_period
242 && *start_of_period < *end_of_period) 242 && *start_of_period < *end_of_period)
243 { 243 {
@@ -246,19 +246,19 @@ export class loader
246 } 246 }
247 247
248 validity = 248 validity =
249 time::period_seq{valid_periods.begin(), valid_periods.end()}.except( 249 time::period_seq{valid_periods.begin(), valid_periods.end()}.except(
250 time::period_seq{ 250 time::period_seq{
251 exception_periods.begin(), exception_periods.end() 251 exception_periods.begin(), exception_periods.end()
252 }); 252 });
253 } 253 }
254 else 254 else
255 { 255 {
256 warnings_.insert( 256 warnings_.insert(
257 std::format( 257 std::format(
258 "invalid overall start / end time (start time: {}, end " 258 "invalid overall start / end time (start time: {}, end "
259 "time: {})", 259 "time: {})",
260 validity_spec_xml.child_value("com:overallStartTime"), 260 validity_spec_xml.child_value("com:overallStartTime"),
261 validity_spec_xml.child_value("com:overallEndTime"))); 261 validity_spec_xml.child_value("com:overallEndTime")));
262 return std::nullopt; 262 return std::nullopt;
263 } 263 }
264 } 264 }
@@ -272,7 +272,7 @@ export class loader
272 272
273public: 273public:
274 [[nodiscard]] auto load_situation_publication(std::string const& filename) 274 [[nodiscard]] auto load_situation_publication(std::string const& filename)
275 -> situation_publication 275 -> situation_publication
276 { 276 {
277 auto doc = pugi::xml_document{}; 277 auto doc = pugi::xml_document{};
278 if (auto result = doc.load_file(filename.c_str()); !result) 278 if (auto result = doc.load_file(filename.c_str()); !result)
@@ -281,10 +281,10 @@ public:
281 } 281 }
282 auto payload_xml = doc.child("mc:messageContainer").child("mc:payload"); 282 auto payload_xml = doc.child("mc:messageContainer").child("mc:payload");
283 auto mpublication_time = 283 auto mpublication_time =
284 parse_timestamp(payload_xml.child_value("com:publicationTime")); 284 parse_timestamp(payload_xml.child_value("com:publicationTime"));
285 if (!mpublication_time) 285 if (!mpublication_time)
286 throw std::runtime_error{ 286 throw std::runtime_error{
287 "provided publication does not name publication time" 287 "provided publication does not name publication time"
288 }; 288 };
289 289
290 auto situations = std::vector<std::shared_ptr<situation>>{}; 290 auto situations = std::vector<std::shared_ptr<situation>>{};
@@ -302,26 +302,26 @@ public:
302 for (auto const record_xml : sit_xml.children("sit:situationRecord")) 302 for (auto const record_xml : sit_xml.children("sit:situationRecord"))
303 { 303 {
304 auto const record_type = 304 auto const record_type =
305 std::string_view{record_xml.attribute("xsi:type").value()}; 305 std::string_view{record_xml.attribute("xsi:type").value()};
306 auto const primary_record_types = std::unordered_set<std::string_view>{ 306 auto const primary_record_types = std::unordered_set<std::string_view>{
307 "sit:Roadworks", 307 "sit:Roadworks",
308 /* { */ "sit:MaintenanceWorks", 308 /* { */ "sit:MaintenanceWorks",
309 /* | */ "sit:ConstructionWorks", 309 /* | */ "sit:ConstructionWorks",
310 /* } */ 310 /* } */
311 "sit:Obstruction", 311 "sit:Obstruction",
312 /* { */ "sit:EnvironmentalObstruction", 312 /* { */ "sit:EnvironmentalObstruction",
313 /* | */ "sit:GeneralObstruction", 313 /* | */ "sit:GeneralObstruction",
314 /* | */ "sit:InfrastructureDamageObstruction", 314 /* | */ "sit:InfrastructureDamageObstruction",
315 /* } */ 315 /* } */
316 "sit:Activity", 316 "sit:Activity",
317 /* { */ "sit:PublicEvent", 317 /* { */ "sit:PublicEvent",
318 /* } */ 318 /* } */
319 }; 319 };
320 320
321 if (record_type == "sit:RoadOrCarriagewayOrLaneManagement") 321 if (record_type == "sit:RoadOrCarriagewayOrLaneManagement")
322 { 322 {
323 if (auto rc = handle_road_or_carriageway_or_lane_management( 323 if (auto rc =
324 record_xml, sit)) 324 handle_road_or_carriageway_or_lane_management(record_xml, sit))
325 { 325 {
326 sit->road_closures.push_back(*rc); 326 sit->road_closures.push_back(*rc);
327 } 327 }
@@ -335,10 +335,10 @@ public:
335 // (comment_xml.child_value("sit:commentType") 335 // (comment_xml.child_value("sit:commentType")
336 // == "internalNote"sv) { 336 // == "internalNote"sv) {
337 auto candidate = std::optional<std::pair< 337 auto candidate = std::optional<std::pair<
338 std::string_view, std::string_view>>{}; // (text, language) 338 std::string_view, std::string_view>>{}; // (text, language)
339 for (auto const comment_value_xml : comment_xml.child("sit:comment") 339 for (auto const comment_value_xml : comment_xml.child("sit:comment")
340 .child("com:values") 340 .child("com:values")
341 .children("com:value")) 341 .children("com:value"))
342 { 342 {
343 if (!candidate 343 if (!candidate
344 || comment_value_xml.attribute("lang").value() == "nl"sv 344 || comment_value_xml.attribute("lang").value() == "nl"sv
@@ -346,8 +346,8 @@ public:
346 && comment_value_xml.attribute("lang").value() == "nl"sv)) 346 && comment_value_xml.attribute("lang").value() == "nl"sv))
347 { 347 {
348 candidate = std::make_pair( 348 candidate = std::make_pair(
349 comment_value_xml.child_value(), 349 comment_value_xml.child_value(),
350 comment_value_xml.attribute("lang").value()); 350 comment_value_xml.attribute("lang").value());
351 } 351 }
352 } 352 }
353 if (candidate) 353 if (candidate)
@@ -355,7 +355,7 @@ public:
355 auto already_present = false; 355 auto already_present = false;
356 for (auto const& comment : sit->comments) 356 for (auto const& comment : sit->comments)
357 already_present = 357 already_present =
358 already_present || comment == candidate->first; 358 already_present || comment == candidate->first;
359 if (!already_present) 359 if (!already_present)
360 { 360 {
361 sit->comments.emplace_back(candidate->first); 361 sit->comments.emplace_back(candidate->first);
@@ -365,19 +365,19 @@ public:
365 } 365 }
366 366
367 if (auto const location_ref_xml = 367 if (auto const location_ref_xml =
368 record_xml.child("sit:locationReference")) 368 record_xml.child("sit:locationReference"))
369 { 369 {
370 if (location_ref_xml.attribute("xsi:type").value() 370 if (location_ref_xml.attribute("xsi:type").value()
371 == "loc:PointLocation"sv) 371 == "loc:PointLocation"sv)
372 { 372 {
373 if (auto const coords_xml = 373 if (auto const coords_xml =
374 location_ref_xml.child("loc:pointByCoordinates") 374 location_ref_xml.child("loc:pointByCoordinates")
375 .child("loc:pointCoordinates")) 375 .child("loc:pointCoordinates"))
376 { 376 {
377 auto const mlat = 377 auto const mlat =
378 util::parse_double(coords_xml.child_value("loc:latitude")); 378 util::parse_double(coords_xml.child_value("loc:latitude"));
379 auto const mlon = 379 auto const mlon =
380 util::parse_double(coords_xml.child_value("loc:longitude")); 380 util::parse_double(coords_xml.child_value("loc:longitude"));
381 if (mlat && mlon) 381 if (mlat && mlon)
382 { 382 {
383 // Vaag genoeg zegt NDW dat het hier om WGS 383 // Vaag genoeg zegt NDW dat het hier om WGS
@@ -404,8 +404,8 @@ public:
404 } 404 }
405 405
406 return { 406 return {
407 .publication_time = *mpublication_time, 407 .publication_time = *mpublication_time,
408 .situations = situations, 408 .situations = situations,
409 }; 409 };
410 } 410 }
411 411