santa/
buildings.rs
1use std::collections::{HashMap, HashSet};
2
3use map_model::{AmenityType, BuildingID, BuildingType};
4use widgetry::{Color, Drawable, EventCtx, GeomBatch, Line, Text};
5
6use crate::App;
7
8pub struct Buildings {
9 pub buildings: HashMap<BuildingID, BldgState>,
11 pub draw_all: Drawable,
14 pub total_housing_units: usize,
15 pub upzones: HashSet<BuildingID>,
16}
17
18#[derive(Clone)]
19pub enum BldgState {
20 Undelivered(usize),
22 Store,
23 Done,
24 Ignore,
26}
27
28impl Buildings {
29 pub fn new(ctx: &mut EventCtx, app: &App, upzones: HashSet<BuildingID>) -> Buildings {
30 let colors = &app.session.colors;
31
32 let mut buildings = HashMap::new();
33 let mut total_housing_units = 0;
34 let mut batch = GeomBatch::new();
35 for b in app.map.all_buildings() {
36 if upzones.contains(&b.id) {
37 buildings.insert(b.id, BldgState::Store);
38 batch.push(colors.store, b.polygon.clone());
39 batch.append(
40 Text::from("Upzoned")
41 .render_autocropped(ctx)
42 .scale(0.1)
43 .centered_on(b.label_center),
44 );
45 continue;
46 }
47
48 if let BuildingType::Residential {
49 num_housing_units, ..
50 } = b.bldg_type
51 {
52 if num_housing_units > 0 {
54 buildings.insert(b.id, BldgState::Undelivered(num_housing_units));
55 total_housing_units += num_housing_units;
56
57 let color = if num_housing_units > 5 {
58 colors.apartment
59 } else {
60 colors.house
61 };
62 batch.push(color, b.polygon.clone());
63 if num_housing_units > 1 {
65 batch.append(
66 Text::from(Line(num_housing_units.to_string()).fg(Color::BLACK))
67 .render_autocropped(ctx)
68 .scale(0.2)
69 .centered_on(b.label_center),
70 );
71 }
72 continue;
73 }
74 } else if let Some(amenity) = b.amenities.iter().find(|a| {
75 if let Some(at) = AmenityType::categorize(&a.amenity_type) {
76 at == AmenityType::Bar
77 || at == AmenityType::ConvenienceStore
78 || at == AmenityType::Food
79 || at == AmenityType::Supermarket
80 } else {
81 false
82 }
83 }) {
84 buildings.insert(b.id, BldgState::Store);
85 batch.push(colors.store, b.polygon.clone());
86 batch.append(
87 Text::from(amenity.names.get(app.opts.language.as_ref()))
88 .render_autocropped(ctx)
89 .scale(0.1)
90 .centered_on(b.label_center),
91 );
92 continue;
93 }
94
95 buildings.insert(b.id, BldgState::Ignore);
97 batch.push(colors.visited, b.polygon.clone());
98 }
99
100 Buildings {
101 buildings,
102 draw_all: ctx.upload(batch),
103 total_housing_units,
104 upzones,
105 }
106 }
107
108 pub fn all_stores(&self) -> Vec<BuildingID> {
109 let mut stores = Vec::new();
110 for (b, state) in &self.buildings {
111 if let BldgState::Store = state {
112 stores.push(*b);
113 }
114 }
115 stores
116 }
117
118 pub fn draw_done_houses(&self, ctx: &mut EventCtx, app: &App) -> Drawable {
119 let mut batch = GeomBatch::new();
120 for (b, state) in &self.buildings {
121 if let BldgState::Done = state {
122 batch.push(
123 app.session.colors.visited,
124 app.map.get_b(*b).polygon.clone(),
125 );
126 }
127 }
128 ctx.upload(batch)
129 }
130}