aboutsummaryrefslogtreecommitdiffstats
path: root/src/querykv1/joparoute.cpp
diff options
context:
space:
mode:
authorLibravatar Rutger Broekhoff2024-05-02 20:27:40 +0200
committerLibravatar Rutger Broekhoff2024-05-02 20:27:40 +0200
commit17a3ea880402338420699e03bcb24181e4ff3924 (patch)
treeda666ef91e0b60d20aa0b01529644c136fd1f4ab /src/querykv1/joparoute.cpp
downloadoeuf-17a3ea880402338420699e03bcb24181e4ff3924.tar.gz
oeuf-17a3ea880402338420699e03bcb24181e4ff3924.zip
Initial commit
Based on dc4ba6a
Diffstat (limited to 'src/querykv1/joparoute.cpp')
-rw-r--r--src/querykv1/joparoute.cpp102
1 files changed, 102 insertions, 0 deletions
diff --git a/src/querykv1/joparoute.cpp b/src/querykv1/joparoute.cpp
new file mode 100644
index 0000000..94ed359
--- /dev/null
+++ b/src/querykv1/joparoute.cpp
@@ -0,0 +1,102 @@
1// vim:set sw=2 ts=2 sts et:
2
3#include <cstdio>
4#include <iostream>
5#include <string_view>
6
7#include "joparoute.hpp"
8
9using namespace std::string_view_literals;
10
11void jopaRoute(const Options &options, Kv1Records &records, Kv1Index &index) {
12 FILE *out = stdout;
13 if (options.output_file_path != "-"sv)
14 out = fopen(options.output_file_path, "wb");
15 if (!out) {
16 fprintf(stderr, "Open %s: %s\n", options.output_file_path, strerrordesc_np(errno));
17 exit(EXIT_FAILURE);
18 }
19
20 const std::string data_owner_code = "CXX";
21 Kv1JourneyPattern::Key jopa_key(
22 // Of course it is bad to hardcode this, but we really have no time to make
23 // everything nice and dynamic. We're only working with CXX data anyway,
24 // and provide no support for the 'Schedules and Passing Times' KV1
25 // variant.
26 data_owner_code,
27 options.line_planning_number,
28 options.journey_pattern_code);
29
30 const Kv1JourneyPattern *jopa = index.journey_patterns[jopa_key];
31 if (!jopa) {
32 std::cerr << "Journey pattern not found" << std::endl;
33 return;
34 }
35 const Kv1Line *line = jopa->p_line;
36
37 struct Point {
38 bool is_stop = false;
39 const Kv1JourneyPatternTimingLink *jopatili = nullptr;
40 const Kv1Link *link = nullptr;
41 const Kv1Point *point = nullptr;
42 double distance_since_start_of_link = 0;
43 double distance_since_start_of_journey = 0;
44 };
45 std::vector<Point> points;
46
47 for (size_t i = 0; i < records.journey_pattern_timing_links.size(); i++) {
48 const Kv1JourneyPatternTimingLink *jopatili = &records.journey_pattern_timing_links[i];
49 if (jopatili->key.line_planning_number == jopa->key.line_planning_number
50 && jopatili->key.journey_pattern_code == jopa->key.journey_pattern_code) {
51 const Kv1Link::Key link_key(data_owner_code, jopatili->user_stop_code_begin,
52 jopatili->user_stop_code_end, line->transport_type);
53 const Kv1Link *link = index.links[link_key];
54 const Kv1UserStopPoint::Key link_begin_key(data_owner_code, jopatili->user_stop_code_begin);
55 const Kv1UserStopPoint::Key link_end_key(data_owner_code, jopatili->user_stop_code_end);
56 const Kv1UserStopPoint *link_begin = index.user_stop_points[link_begin_key];
57 const Kv1UserStopPoint *link_end = index.user_stop_points[link_end_key];
58
59 points.emplace_back(true, jopatili, link, link_begin->p_point, 0);
60
61 for (size_t j = 0; j < records.point_on_links.size(); j++) {
62 Kv1PointOnLink *pool = &records.point_on_links[j];
63 if (pool->key.user_stop_code_begin == jopatili->user_stop_code_begin
64 && pool->key.user_stop_code_end == jopatili->user_stop_code_end
65 && pool->key.transport_type == jopatili->p_line->transport_type) {
66 points.emplace_back(false, jopatili, link, pool->p_point, pool->distance_since_start_of_link);
67 }
68 }
69
70 points.emplace_back(true, jopatili, link, link_end->p_point, link->distance);
71 }
72 }
73
74 std::sort(points.begin(), points.end(), [](Point &a, Point &b) {
75 if (a.jopatili->key.timing_link_order != b.jopatili->key.timing_link_order)
76 return a.jopatili->key.timing_link_order < b.jopatili->key.timing_link_order;
77 return a.distance_since_start_of_link < b.distance_since_start_of_link;
78 });
79
80 double distance_since_start_of_journey = 0;
81 for (size_t i = 0; i < points.size(); i++) {
82 Point *p = &points[i];
83 if (i > 0) {
84 Point *prev = &points[i - 1];
85 if (p->link != prev->link) {
86 distance_since_start_of_journey += prev->link->distance;
87 }
88 }
89 p->distance_since_start_of_journey = distance_since_start_of_journey + p->distance_since_start_of_link;
90 }
91
92 fputs("is_stop,link_usrstop_begin,link_usrstop_end,point_code,rd_x,rd_y,distance_since_start_of_link,distance_since_start_of_journey\n", out);
93 for (const auto &point : points) {
94 fprintf(out, "%s,%s,%s,%s,%f,%f,%f,%f\n",
95 point.is_stop ? "true" : "false",
96 point.jopatili->user_stop_code_begin.c_str(), point.jopatili->user_stop_code_end.c_str(),
97 point.point->key.point_code.c_str(), point.point->location_x_ew, point.point->location_y_ns,
98 point.distance_since_start_of_link, point.distance_since_start_of_journey);
99 }
100
101 if (options.output_file_path != "-"sv) fclose(out);
102}