start structuring the UI for selecting and running a challenge

This commit is contained in:
Dustin Carlino 2019-10-30 20:44:27 -07:00
parent d35d0c1b41
commit 53bd77332e
3 changed files with 96 additions and 0 deletions

91
game/src/challenges.rs Normal file
View File

@ -0,0 +1,91 @@
use crate::game::{State, Transition, WizardState};
use crate::ui::UI;
use ezgui::{
hotkey, Choice, EventCtx, GfxCtx, HorizontalAlignment, Key, Line, ModalMenu, Text,
VerticalAlignment,
};
// TODO Also have some kind of screenshot to display for each challenge
#[derive(Clone)]
struct Challenge {
title: String,
description: String,
map_name: String,
scenario_name: String,
}
impl abstutil::Cloneable for Challenge {}
fn all_challenges() -> Vec<Challenge> {
vec![
Challenge {
title: "Speed up route 980".to_string(),
description:
"Decrease the average waiting time between all of 980's stops by at least 30s"
.to_string(),
map_name: "montlake".to_string(),
scenario_name: "weekday_typical_traffic_from_psrc".to_string(),
},
Challenge {
title: "Speed up route 27 along Yesler".to_string(),
description:
"Decrease the average waiting time between all of 27's stops by at least 30s"
.to_string(),
map_name: "23rd".to_string(),
scenario_name: "weekday_typical_traffic_from_psrc".to_string(),
},
]
}
pub fn challenges_picker() -> Box<dyn State> {
WizardState::new(Box::new(move |wiz, ctx, _| {
let (_, challenge) = wiz.wrap(ctx).choose("Play which challenge?", || {
all_challenges()
.into_iter()
.map(|c| Choice::new(c.title.clone(), c))
.collect()
})?;
let mut summary = Text::from(Line(&challenge.description));
summary.add(Line(""));
summary.add(Line("Proposals:"));
summary.add(Line(""));
summary.add(Line("- bus lane fix (untested)"));
summary.add(Line("- signal retiming (score 500)"));
Some(Transition::Replace(Box::new(ChallengeSplash {
summary,
menu: ModalMenu::new(
&challenge.title,
vec![
(hotkey(Key::Escape), "back to challenges"),
(hotkey(Key::S), "start challenge"),
(hotkey(Key::L), "load existing proposal"),
],
ctx,
),
})))
}))
}
struct ChallengeSplash {
menu: ModalMenu,
summary: Text,
}
impl State for ChallengeSplash {
fn event(&mut self, ctx: &mut EventCtx, _: &mut UI) -> Transition {
self.menu.event(ctx);
if self.menu.action("back to challenges") {
return Transition::Replace(challenges_picker());
}
Transition::Keep
}
fn draw(&self, g: &mut GfxCtx, _: &UI) {
g.draw_blocking_text(
&self.summary,
(HorizontalAlignment::Center, VerticalAlignment::Center),
);
self.menu.draw(g);
}
}

View File

@ -1,4 +1,5 @@
mod abtest; mod abtest;
mod challenges;
mod common; mod common;
mod debug; mod debug;
mod edit; mod edit;

View File

@ -1,4 +1,5 @@
use crate::abtest::setup::PickABTest; use crate::abtest::setup::PickABTest;
use crate::challenges::challenges_picker;
use crate::debug::DebugMode; use crate::debug::DebugMode;
use crate::edit::EditMode; use crate::edit::EditMode;
use crate::game::{State, Transition}; use crate::game::{State, Transition};
@ -123,6 +124,7 @@ fn splash_screen(
) -> Option<Transition> { ) -> Option<Transition> {
let mut wizard = raw_wizard.wrap(ctx); let mut wizard = raw_wizard.wrap(ctx);
let sandbox = "Sandbox mode"; let sandbox = "Sandbox mode";
let challenge = "Challenge mode";
let load_map = "Load another map"; let load_map = "Load another map";
let edit = "Edit map"; let edit = "Edit map";
let abtest = "A/B Test Mode"; let abtest = "A/B Test Mode";
@ -142,6 +144,7 @@ fn splash_screen(
.choose("Welcome to A/B Street!", || { .choose("Welcome to A/B Street!", || {
vec![ vec![
Choice::new(sandbox, ()).key(Key::S), Choice::new(sandbox, ()).key(Key::S),
Choice::new(challenge, ()).key(Key::C),
Choice::new(load_map, ()).key(Key::L), Choice::new(load_map, ()).key(Key::L),
Choice::new(edit, ()).key(Key::E), Choice::new(edit, ()).key(Key::E),
Choice::new(abtest, ()).key(Key::A), Choice::new(abtest, ()).key(Key::A),
@ -156,6 +159,7 @@ fn splash_screen(
.as_str() .as_str()
{ {
x if x == sandbox => Some(Transition::Push(Box::new(SandboxMode::new(ctx, ui)))), x if x == sandbox => Some(Transition::Push(Box::new(SandboxMode::new(ctx, ui)))),
x if x == challenge => Some(Transition::Push(challenges_picker())),
x if x == load_map => { x if x == load_map => {
if let Some(name) = wizard.choose_string("Load which map?", || { if let Some(name) = wizard.choose_string("Load which map?", || {
let current_map = ui.primary.map.get_name(); let current_map = ui.primary.map.get_name();