Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rtfix #58

Merged
merged 5 commits into from
Aug 10, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion include/nigiri/loader/gtfs/local_to_utc.h
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ void expand_local_to_utc(trip_data const& trip_data,
auto prev_key = conversion_key{date::days{2}, duration_t{-1}};
auto prev_it = utc_time_traffic_days.end();
for (auto day = gtfs_interval.from_; day != gtfs_interval.to_;
day += std::chrono::days{1}) {
day += date::days{1}) {
auto const service_days =
interval{day + first_day_offset, day + last_day_offset + date::days{1}};
if (!selection.overlaps(service_days)) {
Expand Down
5 changes: 5 additions & 0 deletions include/nigiri/types.h
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,11 @@ inline std::ostream& operator<<(std::ostream& out,
<< std::setw(2) << std::setfill('0') << minutes << '.' << days;
}

inline std::ostream& operator<<(std::ostream& out,
nigiri::duration_t const& t) {
return out << std::chrono::duration_cast<nigiri::i32_minutes>(t);
}

inline std::ostream& operator<<(std::ostream& out,
nigiri::unixtime_t const& t) {
date::to_stream(out, "%F %R", t);
Expand Down
19 changes: 13 additions & 6 deletions src/rt/gtfsrt_resolve_run.cc
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,12 @@

namespace nigiri::rt {

std::pair<date::days, duration_t> split(duration_t const i) {
auto const a = static_cast<int>(std::round(i.count() / 1440.));
auto const b = i.count() - a * 1440;
return {date::days{a}, duration_t{b}};
}

void resolve_static(date::sys_days const today,
timetable const& tt,
source_idx_t const src,
Expand Down Expand Up @@ -45,17 +51,18 @@ void resolve_static(date::sys_days const today,

for (auto i = lb; i != end(tt.trip_id_to_idx_) && id_matches(i->first); ++i) {
for (auto const [t, stop_range] : tt.trip_transport_ranges_[i->second]) {
auto const o = tt.transport_first_dep_offset_[t];
auto const gtfs_static_dep =
tt.event_mam(t, stop_range.from_, event_type::kDep).as_duration() +
tt.transport_first_dep_offset_[t];
tt.event_mam(t, stop_range.from_, event_type::kDep).as_duration() + o;

if (start_time.has_value() && gtfs_static_dep != start_time) {
if (start_time.has_value() && gtfs_static_dep != *start_time) {
continue;
}

auto const day_offset = date::days{static_cast<int>(std::floor(
static_cast<float>(tt.transport_first_dep_offset_[t].count()) /
1440U))};
auto const utc_dep =
tt.event_mam(t, stop_range.from_, event_type::kDep).as_duration();
auto const [day_offset, tz_offset_minutes] =
split(gtfs_static_dep - utc_dep);
auto const day_idx = ((start_date.has_value() ? *start_date : today) +
day_offset - tt.internal_interval_days().from_)
.count();
Expand Down
90 changes: 88 additions & 2 deletions test/rt/gtfsrt_resolve_trip_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include "nigiri/loader/gtfs/files.h"
#include "nigiri/loader/gtfs/load_timetable.h"
#include "nigiri/loader/init_finish.h"
#include "nigiri/rt/create_rt_timetable.h"
#include "nigiri/rt/frun.h"
#include "nigiri/rt/gtfsrt_resolve_run.h"
#include "nigiri/rt/gtfsrt_update.h"
Expand Down Expand Up @@ -75,14 +76,21 @@ TEST(rt, gtfsrt_resolve_static_trip) {
load_timetable({}, source_idx_t{0}, test_files(), tt);

{ // test start time >24:00:00

// first dep:
// 49:00 2019-05-03 GMT -02:00
// -> 01:00.2 2019-05-03 GMT -02:00
// -> 23:00.1 2019-05-03 UTC
// -> 23:00 2019-05-04 UTC

auto td = transit_realtime::TripDescriptor();
*td.mutable_start_time() = "49:00:00";
*td.mutable_start_date() = "20190503";
*td.mutable_trip_id() = "T_RE1";

auto const [r, t] = rt::gtfsrt_resolve_run(date::sys_days{2019_y / May / 3},
tt, rtt, source_idx_t{0}, td);
ASSERT_TRUE(r.valid());
EXPECT_TRUE(r.valid());
}

{ // test start time that's on the prev. day in UTC
Expand All @@ -93,7 +101,7 @@ TEST(rt, gtfsrt_resolve_static_trip) {

auto const [r, t] = rt::gtfsrt_resolve_run(date::sys_days{2019_y / May / 4},
tt, rtt, source_idx_t{0}, td);
ASSERT_TRUE(r.valid());
EXPECT_TRUE(r.valid());
}

{ // test without start_time and start_date (assuming "today" as date)
Expand All @@ -109,6 +117,83 @@ TEST(rt, gtfsrt_resolve_static_trip) {
}
}

mem_dir miami_test_files() {
return mem_dir::read(R"(
# agency.txt
agency_id,agency_name,agency_url,agency_timezone,agency_lang
Miami-Dade Transit,Miami-Dade Transit,http://www.miamidade.gov/transit,America/New_York,en

# stops.txt
stop_id,stop_name,stop_lat,stop_lon,stop_code,stop_desc
1,Quail Roost Dr & SW 115 Ave,25.592450,-80.377950,115AQRSN,SW 107TH AVE & SW 112TH ST
3614,SW 107TH AVE @ SW 128TH ST,25.591810,-80.379840,QRSD17A3,
3213,SW 117 AV @ QUAIL ROOST DR,25.590330,-80.380730,C117QUA4,

# routes.txt
agency_id,route_id,route_short_name,route_long_name,route_type,route_color,route_text_color,eligibility_restricted
Miami-Dade Transit,27757,1,SO.MIAMI HTS-PERRINE VIA SOUTHLAND,3,FF00FF,FFFFFF,-999

# trips.txt
route_id,trip_id,service_id,trip_headsign,direction_id,block_id,shape_id,drt_advance_book_min,peak_offpeak
27757,5456914,1,1 - SW 168 St,0,1484970,196385,0.0,0
27757,5456915,1,1 - SW 168 St,0,1484970,196385,0.0,0

# stop_times.txt
trip_id,stop_id,arrival_time,departure_time,timepoint,stop_sequence,shape_dist_traveled,continuous_pickup,continuous_drop_off,start_service_area_radius,end_service_area_radius,departure_buffer
5456914,1,15:15:00,15:15:00,1,1,,-999,-999,-999.0,-999.0,0
5456914,3614,15:15:35,15:15:35,0,2,0.1548,-999,-999,-999.0,-999.0,0
5456914,3213,15:16:20,15:16:20,0,3,0.354,-999,-999,-999.0,-999.0,0
5456915,1,47:15:00,47:15:00,1,1,,-999,-999,-999.0,-999.0,0
5456915,3614,47:15:35,47:15:35,0,2,0.1548,-999,-999,-999.0,-999.0,0
5456915,3213,47:16:20,47:16:20,0,3,0.354,-999,-999,-999.0,-999.0,0

# calendar_dates.txt
service_id,date,exception_type
1,20230904,2

# calendar.txt
service_id,monday,tuesday,wednesday,thursday,friday,saturday,sunday,start_date,end_date
1,1,1,1,1,1,0,0,20230724,20231112
)");
}

TEST(rt, resolve_tz) {
auto tt = timetable{};

tt.date_range_ = {date::sys_days{2023_y / August / 3},
date::sys_days{2023_y / August / 5}};
loader::register_special_stations(tt);
loader::gtfs::load_timetable({}, source_idx_t{0}, miami_test_files(), tt);
loader::finalize(tt);

auto rtt = rt::create_rt_timetable(tt, date::sys_days{2023_y / August / 3});

{
auto td = transit_realtime::TripDescriptor();
td.set_start_date("20230803");
td.set_trip_id("5456914");

auto const r = gtfsrt_resolve_run(date::sys_days{2023_y / August / 3}, tt,
rtt, source_idx_t{0U}, td);
EXPECT_TRUE(r.first.valid());
}

{
// first dep:
// 47:00 2023-08-03 GMT +04:00
// -> 23:00.1 2023-08-03 GMT +04:00
// -> 03:00.2 2023-08-03 UTC
// -> 03:00 2023-08-05 UTC
auto td = transit_realtime::TripDescriptor();
td.set_start_date("20230803");
td.set_trip_id("5456915");

auto const r = gtfsrt_resolve_run(date::sys_days{2023_y / August / 3}, tt,
rtt, source_idx_t{0U}, td);
EXPECT_TRUE(r.first.valid());
}
}

TEST(rt, gtfs_rt_update) {
auto const to_unix = [](auto&& x) {
return std::chrono::time_point_cast<std::chrono::seconds>(x)
Expand Down Expand Up @@ -162,6 +247,7 @@ TEST(rt, gtfs_rt_update) {
rt::gtfsrt_resolve_run(date::sys_days{2019_y / May / 4}, tt,
rtt, source_idx_t{0}, *td)
.first};
ASSERT_TRUE(fr.valid());
for (auto const [from, to] : utl::pairwise(fr)) {
EXPECT_EQ(scheduled[i++], from.scheduled_time(nigiri::event_type::kDep));
EXPECT_EQ(scheduled[i++], to.scheduled_time(nigiri::event_type::kArr));
Expand Down