diff options
| author | Rutger Broekhoff | 2024-05-02 20:27:40 +0200 |
|---|---|---|
| committer | Rutger Broekhoff | 2024-05-02 20:27:40 +0200 |
| commit | 17a3ea880402338420699e03bcb24181e4ff3924 (patch) | |
| tree | da666ef91e0b60d20aa0b01529644c136fd1f4ab /src/querykv1/joparoute.cpp | |
| download | oeuf-17a3ea880402338420699e03bcb24181e4ff3924.tar.gz oeuf-17a3ea880402338420699e03bcb24181e4ff3924.zip | |
Initial commit
Based on dc4ba6a
Diffstat (limited to 'src/querykv1/joparoute.cpp')
| -rw-r--r-- | src/querykv1/joparoute.cpp | 102 |
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 | |||
| 9 | using namespace std::string_view_literals; | ||
| 10 | |||
| 11 | void 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 | } | ||