1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
//! Rolling per-stop arrival log.
//!
//! Carries a `CurrentTick` sibling resource that mirrors
//! [`Simulation::current_tick`](crate::sim::Simulation::current_tick)
//! so strategies reading the log from phases without direct access to
//! `PhaseContext` (e.g. [`RepositionStrategy`](crate::dispatch::RepositionStrategy))
//! can still compute windowed queries.
//!
//!
//! Commercial group controllers sample per-stop arrival rates to pick
//! traffic modes (up-peak, down-peak) and to pre-position idle cars
//! ahead of expected demand (Otis Compass Infinity's *predictive
//! parking*, KONE Polaris's pattern-driven mode switch). This log is
//! the signal source: dispatch strategies read it via
//! [`DispatchManifest::arrivals_at`](crate::dispatch::DispatchManifest::arrivals_at),
//! reposition strategies read it directly from `World` resources.
//!
//! The log is append-only during a tick and pruned at the start of each
//! tick to keep memory bounded under long runs. Stored entries are
//! `(tick, stop)` pairs; queries are by stop and time window only.
use crateEntityId;
use ;
/// World resource mirroring the current simulation tick.
///
/// Kept in sync by [`Simulation::step`](crate::sim::Simulation::step).
/// Lets phases that don't receive a `PhaseContext` (reposition
/// strategies, custom `World` consumers) compute rolling-window queries
/// against [`ArrivalLog`] without plumbing tick through their
/// signatures.
` entry.
pub u64,
);
/// Default rolling window (in ticks).
///
/// Used by [`DispatchManifest::arrivals_at`](crate::dispatch::DispatchManifest::arrivals_at)
/// when the sim doesn't override it. Five minutes of real time at the
/// default 60 Hz tick rate, matching the window commercial controllers
/// use to detect up-peak / down-peak transitions.
pub const DEFAULT_ARRIVAL_WINDOW_TICKS: u64 = 18_000;
/// World resource controlling how far back the [`ArrivalLog`] retains
/// entries before `Simulation::advance_tick` prunes them.
///
/// Defaults to [`DEFAULT_ARRIVAL_WINDOW_TICKS`]. Strategies that query
/// a longer window (e.g.
/// [`PredictiveParking::with_window_ticks`](crate::dispatch::reposition::PredictiveParking::with_window_ticks)
/// with a value greater than the default) will silently see only the
/// last `DEFAULT_ARRIVAL_WINDOW_TICKS` unless this retention is
/// widened via [`Simulation::set_arrival_log_retention_ticks`](crate::sim::Simulation::set_arrival_log_retention_ticks).
;
/// Append-only log of per-stop arrival events used to compute rolling
/// arrival-rate signals.
///
/// Stored as a `Vec<(tick, stop)>` sorted by tick (records are appended
/// in tick order during normal sim execution). Queries are `O(n)` worst
/// case but typically `O(window_size)`; `prune_before` keeps the tail
/// short enough that this is a non-issue for practical window sizes.