1use serde::{Deserialize, Serialize};
2
3use abstio::MapName;
4use abstutil::{prettyprint_usize, Counter, Timer};
5use geom::Distance;
6use map_model::{IntersectionID, Map, PathRequest, PathStepV2, PathV2, Pathfinder, RoadID};
7
8#[derive(Clone, Serialize, Deserialize)]
14pub struct TrafficCounts {
15 pub map: MapName,
16 pub description: String,
19 pub per_road: Counter<RoadID>,
21 pub per_intersection: Counter<IntersectionID>,
22}
23
24impl Default for TrafficCounts {
25 fn default() -> Self {
26 Self {
27 map: MapName::new("zz", "place", "holder"),
28 description: String::new(),
29 per_road: Counter::new(),
30 per_intersection: Counter::new(),
31 }
32 }
33}
34
35impl TrafficCounts {
36 pub fn from_path_requests(
40 map: &Map,
41 description: String,
42 requests: &[(PathRequest, usize)],
43 pathfinder: &Pathfinder,
44 timer: &mut Timer,
45 ) -> Self {
46 let mut counts = Self {
47 map: map.get_name().clone(),
48 description,
49 per_road: Counter::new(),
50 per_intersection: Counter::new(),
51 };
52
53 for r in map.all_roads() {
56 counts.per_road.add(r.id, 0);
57 }
58 for i in map.all_intersections() {
59 counts.per_intersection.add(i.id, 0);
60 }
61
62 timer.start_iter("calculate routes", requests.len());
70 for (req, count) in requests {
71 timer.next();
72 if let Some(path) = pathfinder.pathfind_v2(req.clone(), map) {
73 counts.update_with_path(path, *count, map);
74 }
75 }
76 counts
77 }
78
79 pub fn update_with_path(&mut self, path: PathV2, count: usize, map: &Map) {
80 for step in path.get_steps() {
81 match step {
82 PathStepV2::Along(dr) | PathStepV2::Contraflow(dr) => {
83 self.per_road.add(dr.road, count);
84 }
85 PathStepV2::Movement(m) | PathStepV2::ContraflowMovement(m) => {
86 self.per_intersection.add(m.parent, count);
87 }
88 }
89 }
90
91 let req = path.get_req();
93 if req.start.dist_along() == Distance::ZERO {
94 let i = map.get_l(req.start.lane()).src_i;
96 if map.get_i(i).is_border() {
97 self.per_intersection.add(i, count);
98 }
99 } else {
100 let i = map.get_l(req.end.lane()).dst_i;
101 if map.get_i(i).is_border() {
102 self.per_intersection.add(i, count);
103 }
104 }
105 }
106
107 pub fn quickly_compare(&self, other: &TrafficCounts) {
109 println!("{} vs {}", self.description, other.description);
111 let mut sum = 0.0;
112 let mut n = 0;
113 for (r, cnt1) in self.per_road.borrow() {
114 let cnt1 = *cnt1;
115 let cnt2 = other.per_road.get(*r);
116 println!(
117 "{}: {} vs {}",
118 r,
119 prettyprint_usize(cnt1),
120 prettyprint_usize(cnt2)
121 );
122 sum += (cnt1 as f64 - cnt2 as f64).powi(2);
123 n += 1;
124 }
125 for (i, cnt1) in self.per_intersection.borrow() {
126 let cnt1 = *cnt1;
127 let cnt2 = other.per_intersection.get(*i);
128 println!(
129 "{}: {} vs {}",
130 i,
131 prettyprint_usize(cnt1),
132 prettyprint_usize(cnt2)
133 );
134 sum += (cnt1 as f64 - cnt2 as f64).powi(2);
135 n += 1;
136 }
137 println!("RMSE = {:.2}", (sum / n as f64).sqrt());
138 }
139}