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

RSL: Fix revert forecast for routes with major delays #410

Merged
merged 2 commits into from
Nov 23, 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
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