game/devtools/
scenario.rs

1use abstutil::prettyprint_usize;
2use map_gui::tools::ColorDiscrete;
3use sim::count_parked_cars_per_bldg;
4use synthpop::Scenario;
5use widgetry::mapspace::ToggleZoomed;
6use widgetry::{
7    Color, EventCtx, GfxCtx, HorizontalAlignment, Key, Line, Outcome, Panel, State, Text,
8    VerticalAlignment, Widget,
9};
10
11use crate::app::{App, Transition};
12use crate::common::CommonState;
13use crate::devtools::destinations::PopularDestinations;
14
15pub struct ScenarioManager {
16    panel: Panel,
17    scenario: Scenario,
18    draw: ToggleZoomed,
19}
20
21impl ScenarioManager {
22    pub fn new_state(scenario: Scenario, ctx: &mut EventCtx, app: &App) -> Box<dyn State<App>> {
23        let mut colorer = ColorDiscrete::new(
24            app,
25            vec![
26                ("1-2", Color::BLUE),
27                ("3-4", Color::RED),
28                ("more", Color::BLACK),
29            ],
30        );
31        let mut total_cars_needed = 0;
32        for (b, count) in count_parked_cars_per_bldg(&scenario).consume() {
33            total_cars_needed += count;
34            let color = if count == 0 {
35                continue;
36            } else if count == 1 || count == 2 {
37                "1-2"
38            } else if count == 3 || count == 4 {
39                "3-4"
40            } else {
41                "more"
42            };
43            colorer.add_b(b, color);
44        }
45
46        let (filled_spots, free_parking_spots) = app.primary.sim.get_all_parking_spots();
47        assert!(filled_spots.is_empty());
48
49        let (draw, legend) = colorer.build(ctx);
50        Box::new(ScenarioManager {
51            panel: Panel::new_builder(Widget::col(vec![
52                Widget::row(vec![
53                    Line(format!("Scenario {}", scenario.scenario_name))
54                        .small_heading()
55                        .into_widget(ctx),
56                    ctx.style().btn_close_widget(ctx),
57                ]),
58                ctx.style()
59                    .btn_outline
60                    .text("popular destinations")
61                    .hotkey(Key::D)
62                    .build_def(ctx),
63                Text::from_multiline(vec![
64                    Line(format!(
65                        "{} people",
66                        prettyprint_usize(scenario.people.len())
67                    )),
68                    Line(format!(
69                        "seed {} parked cars",
70                        prettyprint_usize(total_cars_needed)
71                    )),
72                    Line(format!(
73                        "{} parking spots",
74                        prettyprint_usize(free_parking_spots.len()),
75                    )),
76                    Line(""),
77                    Line("Parked cars per building"),
78                ])
79                .into_widget(ctx),
80                legend,
81            ]))
82            .aligned(HorizontalAlignment::Right, VerticalAlignment::Top)
83            .build(ctx),
84            draw,
85            scenario,
86        })
87    }
88}
89
90impl State<App> for ScenarioManager {
91    fn event(&mut self, ctx: &mut EventCtx, app: &mut App) -> Transition {
92        if let Outcome::Clicked(x) = self.panel.event(ctx) {
93            match x.as_ref() {
94                "close" => {
95                    return Transition::Pop;
96                }
97                "popular destinations" => {
98                    return Transition::Push(PopularDestinations::new_state(
99                        ctx,
100                        app,
101                        &self.scenario,
102                    ));
103                }
104                _ => unreachable!(),
105            }
106        }
107
108        ctx.canvas_movement();
109        if ctx.redo_mouseover() {
110            app.recalculate_current_selection(ctx);
111        }
112
113        Transition::Keep
114    }
115
116    fn draw(&self, g: &mut GfxCtx, app: &App) {
117        self.draw.draw(g);
118        self.panel.draw(g);
119        CommonState::draw_osd(g, app);
120    }
121}