Skip to content

Commit

Permalink
RSL: Fix revert forecast for routes with major delays (#410)
Browse files Browse the repository at this point in the history
  • Loading branch information
pablohoch authored Nov 23, 2023
1 parent dfed437 commit 6bb2d3d
Show file tree
Hide file tree
Showing 13 changed files with 75 additions and 23 deletions.
22 changes: 13 additions & 9 deletions docs/api/schemas/motis/paxmon.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -550,23 +550,23 @@ PaxMonFilterGroupsRequest:
If set to `false`, the reroute log information in the response is
empty.
examples: 0
examples: false
filter_by_start:
description: |
A list of station IDs. If non-empty, only groups departing at one
of the listed stations are included in the response.
Set to an empty array to disable this filter.
examples:
- []
- [ ]
filter_by_destination:
description: |
A list of station IDs. If non-empty, only groups arriving at one
of the listed stations are included in the response.
Set to an empty array to disable this filter.
examples:
- []
- [ ]
filter_by_via:
description: |
A list of station IDs. If non-empty, only groups with a transfer at one
Expand All @@ -578,31 +578,31 @@ PaxMonFilterGroupsRequest:
Set to an empty array to disable this filter.
examples:
- []
- [ ]
filter_by_group_id:
description: |
A list of group IDs. If non-empty, only these groups are included
in the response.
Set to an empty array to disable this filter.
examples:
- []
- [ ]
filter_by_data_source:
description: |
A list of group data sources. If non-empty, only groups with these
data sources are included in the repsonse.
data sources are included in the response.
Set to an empty array to disable this filter.
examples:
- []
- [ ]
filter_by_train_nr:
description: |
A list of train numbers. If non-empty, only groups using a train
with one of the given train numbers are included in the response.
Set to an empty array to disable this filter.
examples:
- []
- [ ]
filter_by_time:
description: |
Filter groups by time.
Expand All @@ -629,7 +629,7 @@ PaxMonFilterGroupsRequest:
Set to an empty array to disable this filter.
examples:
- []
- [ ]
PaxMonGroupWithStats:
description: TODO
fields:
Expand Down Expand Up @@ -1708,6 +1708,10 @@ PaxMonMetrics:
total_timing:
description: >
Total time spent by passenger monitoring and forecast in milliseconds
reactivated_group_routes:
description: >
Number of passenger group routes that were affected by a real-time
update that are no longer broken, but were broken before this update
PaxMonMetricsResponse:
description: |
Contains metrics for the requested universe.
Expand Down
2 changes: 1 addition & 1 deletion modules/paxforecast/src/monitoring_update.cc
Original file line number Diff line number Diff line change
Expand Up @@ -313,7 +313,7 @@ void handle_unbroken_transfers(paxforecast& mod, universe& uv,
auto unbroken_transfers = std::vector<passenger_group_with_route>{};

for (auto const& event : *mon_update->events()) {
if (event->type() != PaxMonEventType_NO_PROBLEM) {
if (event->type() != PaxMonEventType_REACTIVATED) {
continue;
}

Expand Down
4 changes: 3 additions & 1 deletion modules/paxmon/include/motis/paxmon/monitoring_event.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ namespace motis::paxmon {
enum class monitoring_event_type : std::uint8_t {
NO_PROBLEM,
BROKEN_TRANSFER,
MAJOR_DELAY_EXPECTED
MAJOR_DELAY_EXPECTED,
REACTIVATED
};

inline std::ostream& operator<<(std::ostream& out,
Expand All @@ -27,6 +28,7 @@ inline std::ostream& operator<<(std::ostream& out,
return out << "BROKEN_TRANSFER";
case monitoring_event_type::MAJOR_DELAY_EXPECTED:
return out << "MAJOR_DELAY_EXPECTED";
case monitoring_event_type::REACTIVATED: return out << "REACTIVATED";
}
return out;
}
Expand Down
8 changes: 7 additions & 1 deletion modules/paxmon/include/motis/paxmon/rt_update_context.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,20 @@

#include <set>

#include "motis/core/schedule/trip.h"
#include "motis/hash_map.h"

#include "motis/paxmon/index_types.h"

namespace motis::paxmon {

struct rt_update_context {
void reset() {
group_routes_affected_by_last_update_.clear();
previous_broken_status_.clear();
}

std::set<passenger_group_with_route> group_routes_affected_by_last_update_;
mcd::hash_map<passenger_group_with_route, bool> previous_broken_status_;
};

} // namespace motis::paxmon
2 changes: 2 additions & 0 deletions modules/paxmon/include/motis/paxmon/statistics.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ struct tick_statistics {
ok_group_routes_ += rhs.ok_group_routes_;
broken_group_routes_ += rhs.broken_group_routes_;
major_delay_group_routes_ += rhs.major_delay_group_routes_;
reactivated_group_routes_ += rhs.reactivated_group_routes_;

t_reachability_ += rhs.t_reachability_;
t_localization_ += rhs.t_localization_;
Expand Down Expand Up @@ -86,6 +87,7 @@ struct tick_statistics {
std::uint64_t ok_group_routes_{};
std::uint64_t broken_group_routes_{};
std::uint64_t major_delay_group_routes_{};
std::uint64_t reactivated_group_routes_{};

// timing (ms)
std::uint64_t t_reachability_{};
Expand Down
6 changes: 5 additions & 1 deletion modules/paxmon/src/api/metrics.cc
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,14 @@ msg_ptr metrics(paxmon_data& data, msg_ptr const& msg) {

auto const metrics_to_fbs = [&](metrics_storage<tick_statistics> const& m) {
std::vector<std::uint64_t> affected_group_routes, ok_group_routes,
broken_group_routes, major_delay_group_routes, total_timing;
broken_group_routes, major_delay_group_routes, reactivated_group_routes,
total_timing;

affected_group_routes.reserve(m.size());
ok_group_routes.reserve(m.size());
broken_group_routes.reserve(m.size());
major_delay_group_routes.reserve(m.size());
reactivated_group_routes.reserve(m.size());
total_timing.reserve(m.size());

for (auto i = 0UL; i < m.size(); ++i) {
Expand All @@ -33,13 +35,15 @@ msg_ptr metrics(paxmon_data& data, msg_ptr const& msg) {
ok_group_routes.push_back(entry.ok_group_routes_);
broken_group_routes.push_back(entry.broken_group_routes_);
major_delay_group_routes.push_back(entry.major_delay_group_routes_);
reactivated_group_routes.push_back(entry.reactivated_group_routes_);
total_timing.push_back(entry.t_rt_updates_applied_total_);
}

return CreatePaxMonMetrics(
mc, m.start_time(), m.size(), mc.CreateVector(affected_group_routes),
mc.CreateVector(ok_group_routes), mc.CreateVector(broken_group_routes),
mc.CreateVector(major_delay_group_routes),
mc.CreateVector(reactivated_group_routes),
mc.CreateVector(total_timing));
};

Expand Down
5 changes: 3 additions & 2 deletions modules/paxmon/src/paxmon.cc
Original file line number Diff line number Diff line change
Expand Up @@ -740,9 +740,10 @@ void paxmon::rt_updates_applied(universe& uv, schedule const& sched) {
<< uv.rt_update_ctx_.group_routes_affected_by_last_update_.size()
<< " passenger group routes";

uv.rt_update_ctx_.group_routes_affected_by_last_update_.clear();
uv.rt_update_ctx_.reset();
LOG(info) << "passenger group routes: " << uv.tick_stats_.ok_group_routes_
<< " ok, " << uv.tick_stats_.broken_group_routes_ << " broken";
<< " ok, " << uv.tick_stats_.broken_group_routes_ << " broken, "
<< uv.tick_stats_.reactivated_group_routes_ << " reactivated";

MOTIS_STOP_TIMING(total);
uv.tick_stats_.t_rt_updates_applied_total_ =
Expand Down
27 changes: 25 additions & 2 deletions modules/paxmon/src/rt_updates.cc
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,17 @@ namespace motis::paxmon {
void check_broken_interchanges(
universe& uv, schedule const& sched,
std::vector<edge_index> const& updated_interchange_edges) {
std::set<edge*> broken_interchanges;

auto broken_interchanges = std::set<edge*>{};

auto const update_previous_broken_status = [&](auto const& pgwr,
auto const& gr) {
if (uv.rt_update_ctx_.previous_broken_status_.find(pgwr) ==
end(uv.rt_update_ctx_.previous_broken_status_)) {
uv.rt_update_ctx_.previous_broken_status_[pgwr] = gr.broken_;
}
};

for (auto& icei : updated_interchange_edges) {
auto* ice = icei.get(uv);
if (ice->type_ != edge_type::INTERCHANGE) {
Expand Down Expand Up @@ -59,6 +69,7 @@ void check_broken_interchanges(
}
for (auto const& pgwr : uv.pax_connection_info_.group_routes(ice->pci_)) {
auto& gr = uv.passenger_groups_.route(pgwr);
update_previous_broken_status(pgwr, gr);
gr.broken_ = true;
if (gr.probability_ == 0) {
continue;
Expand All @@ -71,10 +82,12 @@ void check_broken_interchanges(
ice->broken_ = false;
for (auto const& pgwr :
uv.pax_connection_info_.group_routes(ice->pci_)) {
update_previous_broken_status(pgwr, uv.passenger_groups_.route(pgwr));
uv.rt_update_ctx_.group_routes_affected_by_last_update_.insert(pgwr);
}
for (auto const& pgwr :
uv.pax_connection_info_.broken_group_routes(ice->pci_)) {
update_previous_broken_status(pgwr, uv.passenger_groups_.route(pgwr));
uv.rt_update_ctx_.group_routes_affected_by_last_update_.insert(pgwr);
}
}
Expand Down Expand Up @@ -192,10 +205,17 @@ void handle_rt_update(universe& uv, schedule const& sched,
}

monitoring_event_type get_monitoring_event_type(
universe const& uv, passenger_group_with_route const& pgwr,
group_route const& gr, reachability_info const& reachability,
int const arrival_delay_threshold) {
if (!reachability.ok_) {
return monitoring_event_type::BROKEN_TRANSFER;
} else if (auto const it =
uv.rt_update_ctx_.previous_broken_status_.find(pgwr);
it != end(uv.rt_update_ctx_.previous_broken_status_) &&
it->second) {
// route was broken before
return monitoring_event_type::REACTIVATED;
} else if (arrival_delay_threshold >= 0 &&
gr.planned_arrival_time_ != INVALID_TIME &&
gr.estimated_delay_ >= arrival_delay_threshold) {
Expand Down Expand Up @@ -286,7 +306,7 @@ std::vector<msg_ptr> update_affected_groups(universe& uv,
MOTIS_STOP_TIMING(localization);

auto const event_type = get_monitoring_event_type(
gr, reachability, uv.arrival_delay_threshold_);
uv, pgwr, gr, reachability, uv.arrival_delay_threshold_);
auto const expected_arrival_time =
event_type == monitoring_event_type::BROKEN_TRANSFER
? INVALID_TIME
Expand Down Expand Up @@ -326,6 +346,9 @@ std::vector<msg_ptr> update_affected_groups(universe& uv,
case monitoring_event_type::MAJOR_DELAY_EXPECTED:
++uv.tick_stats_.major_delay_group_routes_;
break;
case monitoring_event_type::REACTIVATED:
++uv.tick_stats_.reactivated_group_routes_;
break;
}
}

Expand Down
5 changes: 3 additions & 2 deletions modules/paxmon/src/stats_writer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ void stats_writer::write_header() {
<< "ok_group_routes"
<< "broken_group_routes"
<< "major_delay_group_routes"
<< "reactivated_group_routes"
//
<< "t_reachability"
<< "t_localization"
Expand All @@ -53,8 +54,8 @@ void stats_writer::write_tick(const tick_statistics& ts) {
<< ts.rt_delay_schedule_updates_
//
<< ts.affected_group_routes_ << ts.ok_group_routes_
<< ts.broken_group_routes_
<< ts.major_delay_group_routes_
<< ts.broken_group_routes_ << ts.major_delay_group_routes_
<< ts.reactivated_group_routes_
//
<< ts.t_reachability_ << ts.t_localization_ << ts.t_update_load_
<< ts.t_fbs_events_ << ts.t_publish_
Expand Down
1 change: 1 addition & 0 deletions protocol/paxmon/PaxMonMetricsResponse.fbs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ table PaxMonMetrics {
ok_group_routes: [ulong];
broken_group_routes: [ulong];
major_delay_group_routes: [ulong];
reactivated_group_routes: [ulong];

total_timing: [ulong]; // ms
}
Expand Down
1 change: 1 addition & 0 deletions protocol/paxmon/PaxMonUpdate.fbs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ enum PaxMonEventType : byte {
NO_PROBLEM,
BROKEN_TRANSFER,
MAJOR_DELAY_EXPECTED,
REACTIVATED,
}

table PaxMonEvent {
Expand Down
4 changes: 3 additions & 1 deletion ui/rsl/src/api/protocol/motis/paxmon.ts
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,8 @@ export interface PaxMonReachability {
export type PaxMonEventType =
| "NO_PROBLEM"
| "BROKEN_TRANSFER"
| "MAJOR_DELAY_EXPECTED";
| "MAJOR_DELAY_EXPECTED"
| "REACTIVATED";

// paxmon/PaxMonUpdate.fbs
export interface PaxMonEvent {
Expand Down Expand Up @@ -1079,6 +1080,7 @@ export interface PaxMonMetrics {
ok_group_routes: number[];
broken_group_routes: number[];
major_delay_group_routes: number[];
reactivated_group_routes: number[];
total_timing: number[];
}

Expand Down
11 changes: 8 additions & 3 deletions ui/rsl/src/components/transfers/TransferDetails.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,12 @@ function TransferDetails({ transferId }: TransferDetailsProps): ReactNode {
? (departure.current_time - arrival.current_time) / 60
: null;

const missingTransferTime =
availableTransferTime !== null &&
availableTransferTime < data.info.transfer_time
? data.info.transfer_time - availableTransferTime
: null;

const groupedByDestination = data.groups.reduce(
(result, group) => {
const destinationStationId = getDestinationStation(group).id;
Expand Down Expand Up @@ -192,10 +198,9 @@ function TransferDetails({ transferId }: TransferDetailsProps): ReactNode {
)}
</div>

{availableTransferTime !== null && (
{missingTransferTime !== null && (
<div className="mb-2">
Fehlende Umstiegszeit:{" "}
{formatShortDuration(data.info.transfer_time - availableTransferTime)}
Fehlende Umstiegszeit: {formatShortDuration(missingTransferTime)}
</div>
)}

Expand Down

0 comments on commit 6bb2d3d

Please sign in to comment.