mirror of
https://github.com/a-b-street/abstreet.git
synced 2024-12-01 10:44:56 +03:00
more easy WizardState conversion
This commit is contained in:
parent
136ca2d7ab
commit
f26ab131e6
@ -1,52 +1,71 @@
|
||||
use crate::abtest::{ABTestMode, ABTestSavestate};
|
||||
use crate::edit::apply_map_edits;
|
||||
use crate::game::{State, Transition};
|
||||
use crate::game::{State, Transition, WizardState};
|
||||
use crate::render::DrawMap;
|
||||
use crate::ui::{Flags, PerMapUI, UI};
|
||||
use ezgui::{hotkey, EventCtx, GfxCtx, Key, LogScroller, ModalMenu, Wizard, WrappedWizard};
|
||||
use geom::Duration;
|
||||
use map_model::{Map, MapEdits};
|
||||
use map_model::MapEdits;
|
||||
use sim::{ABTest, Scenario, SimFlags};
|
||||
use std::path::PathBuf;
|
||||
|
||||
pub struct PickABTest {
|
||||
wizard: Wizard,
|
||||
}
|
||||
|
||||
pub struct PickABTest;
|
||||
impl PickABTest {
|
||||
pub fn new() -> PickABTest {
|
||||
PickABTest {
|
||||
wizard: Wizard::new(),
|
||||
}
|
||||
pub fn new() -> Box<State> {
|
||||
WizardState::new(Box::new(pick_ab_test))
|
||||
}
|
||||
}
|
||||
|
||||
impl State for PickABTest {
|
||||
fn event(&mut self, ctx: &mut EventCtx, ui: &mut UI) -> Transition {
|
||||
if let Some(ab_test) = pick_ab_test(&ui.primary.map, self.wizard.wrap(ctx)) {
|
||||
let scroller = LogScroller::new(ab_test.test_name.clone(), ab_test.describe());
|
||||
return Transition::Replace(Box::new(ABTestSetup {
|
||||
menu: ModalMenu::new(
|
||||
&format!("A/B Test Editor for {}", ab_test.test_name),
|
||||
vec![vec![
|
||||
(hotkey(Key::Escape), "quit"),
|
||||
(hotkey(Key::R), "run A/B test"),
|
||||
(hotkey(Key::L), "load savestate"),
|
||||
]],
|
||||
ctx,
|
||||
),
|
||||
ab_test,
|
||||
scroller,
|
||||
}));
|
||||
} else if self.wizard.aborted() {
|
||||
return Transition::Pop;
|
||||
}
|
||||
Transition::Keep
|
||||
}
|
||||
fn pick_ab_test(wiz: &mut Wizard, ctx: &mut EventCtx, ui: &mut UI) -> Option<Transition> {
|
||||
let mut wizard = wiz.wrap(ctx);
|
||||
let load_existing = "Load existing A/B test";
|
||||
let create_new = "Create new A/B test";
|
||||
let map_name = ui.primary.map.get_name().to_string();
|
||||
let ab_test = if wizard
|
||||
.choose_string("What A/B test to manage?", vec![load_existing, create_new])?
|
||||
== load_existing
|
||||
{
|
||||
wizard
|
||||
.choose_something_no_keys::<ABTest>(
|
||||
"Load which A/B test?",
|
||||
Box::new(move || abstutil::load_all_objects(abstutil::AB_TESTS, &map_name)),
|
||||
)?
|
||||
.1
|
||||
} else {
|
||||
let test_name = wizard.input_string("Name the A/B test")?;
|
||||
let t = ABTest {
|
||||
test_name,
|
||||
map_name: map_name.clone(),
|
||||
scenario_name: choose_scenario(map_name.clone(), &mut wizard, "What scenario to run?")?,
|
||||
edits1_name: choose_edits(
|
||||
map_name.clone(),
|
||||
&mut wizard,
|
||||
"For the 1st run, what map edits to use?",
|
||||
)?,
|
||||
edits2_name: choose_edits(
|
||||
map_name.clone(),
|
||||
&mut wizard,
|
||||
"For the 2nd run, what map edits to use?",
|
||||
)?,
|
||||
};
|
||||
t.save();
|
||||
t
|
||||
};
|
||||
|
||||
fn draw(&self, g: &mut GfxCtx, _: &UI) {
|
||||
self.wizard.draw(g);
|
||||
}
|
||||
let scroller = LogScroller::new(ab_test.test_name.clone(), ab_test.describe());
|
||||
Some(Transition::Replace(Box::new(ABTestSetup {
|
||||
menu: ModalMenu::new(
|
||||
&format!("A/B Test Editor for {}", ab_test.test_name),
|
||||
vec![vec![
|
||||
(hotkey(Key::Escape), "quit"),
|
||||
(hotkey(Key::R), "run A/B test"),
|
||||
(hotkey(Key::L), "load savestate"),
|
||||
]],
|
||||
ctx,
|
||||
),
|
||||
ab_test,
|
||||
scroller,
|
||||
})))
|
||||
}
|
||||
|
||||
struct ABTestSetup {
|
||||
@ -98,27 +117,6 @@ impl State for LoadSavestate {
|
||||
}
|
||||
}
|
||||
|
||||
fn pick_ab_test(map: &Map, mut wizard: WrappedWizard) -> Option<ABTest> {
|
||||
let load_existing = "Load existing A/B test";
|
||||
let create_new = "Create new A/B test";
|
||||
if wizard.choose_string("What A/B test to manage?", vec![load_existing, create_new])?
|
||||
== load_existing
|
||||
{
|
||||
load_ab_test(map, &mut wizard, "Load which A/B test?")
|
||||
} else {
|
||||
let test_name = wizard.input_string("Name the A/B test")?;
|
||||
let ab_test = ABTest {
|
||||
test_name,
|
||||
map_name: map.get_name().to_string(),
|
||||
scenario_name: choose_scenario(map, &mut wizard, "What scenario to run?")?,
|
||||
edits1_name: choose_edits(map, &mut wizard, "For the 1st run, what map edits to use?")?,
|
||||
edits2_name: choose_edits(map, &mut wizard, "For the 2nd run, what map edits to use?")?,
|
||||
};
|
||||
ab_test.save();
|
||||
Some(ab_test)
|
||||
}
|
||||
}
|
||||
|
||||
fn launch_test(test: &ABTest, ui: &mut UI, ctx: &mut EventCtx) -> ABTestMode {
|
||||
let secondary = ctx.loading_screen(
|
||||
&format!("Launching A/B test {}", test.test_name),
|
||||
@ -234,8 +232,7 @@ fn launch_savestate(test: &ABTest, ss_path: String, ui: &mut UI, ctx: &mut Event
|
||||
)
|
||||
}
|
||||
|
||||
fn choose_scenario(map: &Map, wizard: &mut WrappedWizard, query: &str) -> Option<String> {
|
||||
let map_name = map.get_name().to_string();
|
||||
fn choose_scenario(map_name: String, wizard: &mut WrappedWizard, query: &str) -> Option<String> {
|
||||
wizard
|
||||
.choose_something_no_keys::<String>(
|
||||
query,
|
||||
@ -244,8 +241,7 @@ fn choose_scenario(map: &Map, wizard: &mut WrappedWizard, query: &str) -> Option
|
||||
.map(|(n, _)| n)
|
||||
}
|
||||
|
||||
fn choose_edits(map: &Map, wizard: &mut WrappedWizard, query: &str) -> Option<String> {
|
||||
let map_name = map.get_name().to_string();
|
||||
fn choose_edits(map_name: String, wizard: &mut WrappedWizard, query: &str) -> Option<String> {
|
||||
wizard
|
||||
.choose_something_no_keys::<String>(
|
||||
query,
|
||||
@ -258,16 +254,6 @@ fn choose_edits(map: &Map, wizard: &mut WrappedWizard, query: &str) -> Option<St
|
||||
.map(|(n, _)| n)
|
||||
}
|
||||
|
||||
fn load_ab_test(map: &Map, wizard: &mut WrappedWizard, query: &str) -> Option<ABTest> {
|
||||
let map_name = map.get_name().to_string();
|
||||
wizard
|
||||
.choose_something_no_keys::<ABTest>(
|
||||
query,
|
||||
Box::new(move || abstutil::load_all_objects(abstutil::AB_TESTS, &map_name)),
|
||||
)
|
||||
.map(|(_, t)| t)
|
||||
}
|
||||
|
||||
fn pick_savestate(test: &ABTest, wizard: &mut WrappedWizard) -> Option<String> {
|
||||
let path = abstutil::path1(&test.map_name, abstutil::AB_TEST_SAVES, &test.test_name);
|
||||
wizard
|
||||
|
@ -1,6 +1,6 @@
|
||||
use crate::game::{State, Transition};
|
||||
use crate::game::{Transition, WizardState};
|
||||
use crate::ui::UI;
|
||||
use ezgui::{EventCtx, GfxCtx, ModalMenu, Wizard};
|
||||
use ezgui::{EventCtx, ModalMenu, Wizard};
|
||||
use geom::Duration;
|
||||
|
||||
pub fn time_controls(ctx: &mut EventCtx, ui: &mut UI, menu: &mut ModalMenu) -> Option<Transition> {
|
||||
@ -21,41 +21,23 @@ pub fn time_controls(ctx: &mut EventCtx, ui: &mut UI, menu: &mut ModalMenu) -> O
|
||||
});
|
||||
ui.recalculate_current_selection(ctx);
|
||||
} else if menu.action("jump to specific time") {
|
||||
return Some(Transition::Push(Box::new(JumpingToTime {
|
||||
wizard: Wizard::new(),
|
||||
})));
|
||||
return Some(Transition::Push(WizardState::new(Box::new(jump_to_time))));
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
struct JumpingToTime {
|
||||
wizard: Wizard,
|
||||
}
|
||||
|
||||
impl State for JumpingToTime {
|
||||
fn event(&mut self, ctx: &mut EventCtx, ui: &mut UI) -> Transition {
|
||||
let mut wiz = self.wizard.wrap(ctx);
|
||||
|
||||
if let Some(t) = wiz.input_time_slider(
|
||||
"Jump to what time?",
|
||||
ui.primary.sim.time(),
|
||||
Duration::END_OF_DAY,
|
||||
) {
|
||||
let dt = t - ui.primary.sim.time();
|
||||
ctx.loading_screen(&format!("step forwards {}", dt), |_, mut timer| {
|
||||
ui.primary.sim.timed_step(&ui.primary.map, dt, &mut timer);
|
||||
if let Some(ref mut s) = ui.secondary {
|
||||
s.sim.timed_step(&s.map, dt, &mut timer);
|
||||
}
|
||||
});
|
||||
return Transition::Pop;
|
||||
} else if self.wizard.aborted() {
|
||||
return Transition::Pop;
|
||||
fn jump_to_time(wiz: &mut Wizard, ctx: &mut EventCtx, ui: &mut UI) -> Option<Transition> {
|
||||
let t = wiz.wrap(ctx).input_time_slider(
|
||||
"Jump to what time?",
|
||||
ui.primary.sim.time(),
|
||||
Duration::END_OF_DAY,
|
||||
)?;
|
||||
let dt = t - ui.primary.sim.time();
|
||||
ctx.loading_screen(&format!("step forwards {}", dt), |_, mut timer| {
|
||||
ui.primary.sim.timed_step(&ui.primary.map, dt, &mut timer);
|
||||
if let Some(ref mut s) = ui.secondary {
|
||||
s.sim.timed_step(&s.map, dt, &mut timer);
|
||||
}
|
||||
Transition::Keep
|
||||
}
|
||||
|
||||
fn draw(&self, g: &mut GfxCtx, _: &UI) {
|
||||
self.wizard.draw(g);
|
||||
}
|
||||
});
|
||||
Some(Transition::Pop)
|
||||
}
|
||||
|
@ -4,13 +4,12 @@ mod individ_trips;
|
||||
mod neighborhood;
|
||||
mod scenario;
|
||||
|
||||
use crate::game::{State, Transition};
|
||||
use crate::game::{State, Transition, WizardState};
|
||||
use crate::sandbox::SandboxMode;
|
||||
use crate::ui::UI;
|
||||
use abstutil::Timer;
|
||||
use ezgui::{hotkey, EventCtx, GfxCtx, Key, ModalMenu, Wizard, WrappedWizard};
|
||||
use geom::Duration;
|
||||
use map_model::Map;
|
||||
use popdat::trips_to_scenario;
|
||||
use sim::Scenario;
|
||||
|
||||
@ -80,19 +79,13 @@ impl State for MissionEditMode {
|
||||
});
|
||||
return Transition::Replace(Box::new(SandboxMode::new(ctx)));
|
||||
} else if self.menu.action("create scenario from PSRC trips") {
|
||||
return Transition::Push(Box::new(TripsToScenario {
|
||||
wizard: Wizard::new(),
|
||||
}));
|
||||
return Transition::Push(WizardState::new(Box::new(convert_trips_to_scenario)));
|
||||
} else if self.menu.action("manage neighborhoods") {
|
||||
return Transition::Push(Box::new(neighborhood::NeighborhoodPicker::new()));
|
||||
} else if self.menu.action("load scenario") {
|
||||
return Transition::Push(Box::new(LoadScenario {
|
||||
wizard: Wizard::new(),
|
||||
}));
|
||||
return Transition::Push(WizardState::new(Box::new(load_scenario)));
|
||||
} else if self.menu.action("create new scenario") {
|
||||
return Transition::Push(Box::new(CreateNewScenario {
|
||||
wizard: Wizard::new(),
|
||||
}));
|
||||
return Transition::Push(WizardState::new(Box::new(create_new_scenario)));
|
||||
}
|
||||
Transition::Keep
|
||||
}
|
||||
@ -102,79 +95,53 @@ impl State for MissionEditMode {
|
||||
}
|
||||
}
|
||||
|
||||
struct TripsToScenario {
|
||||
wizard: Wizard,
|
||||
fn convert_trips_to_scenario(
|
||||
wiz: &mut Wizard,
|
||||
ctx: &mut EventCtx,
|
||||
ui: &mut UI,
|
||||
) -> Option<Transition> {
|
||||
let (t1, t2) = pick_time_range(
|
||||
&mut wiz.wrap(ctx),
|
||||
"Include trips departing AFTER when?",
|
||||
"Include trips departing BEFORE when?",
|
||||
)?;
|
||||
ctx.loading_screen("extract PSRC scenario", |_, mut timer| {
|
||||
trips_to_scenario(&ui.primary.map, t1, t2, &mut timer).save();
|
||||
});
|
||||
Some(Transition::Pop)
|
||||
}
|
||||
|
||||
impl State for TripsToScenario {
|
||||
fn event(&mut self, ctx: &mut EventCtx, ui: &mut UI) -> Transition {
|
||||
if let Some((t1, t2)) = pick_time_range(
|
||||
&mut self.wizard.wrap(ctx),
|
||||
"Include trips departing AFTER when?",
|
||||
"Include trips departing BEFORE when?",
|
||||
) {
|
||||
ctx.loading_screen("extract PSRC scenario", |_, mut timer| {
|
||||
trips_to_scenario(&ui.primary.map, t1, t2, &mut timer).save();
|
||||
});
|
||||
return Transition::Pop;
|
||||
} else if self.wizard.aborted() {
|
||||
return Transition::Pop;
|
||||
}
|
||||
Transition::Keep
|
||||
}
|
||||
|
||||
fn draw(&self, g: &mut GfxCtx, _: &UI) {
|
||||
self.wizard.draw(g);
|
||||
}
|
||||
fn load_scenario(wiz: &mut Wizard, ctx: &mut EventCtx, ui: &mut UI) -> Option<Transition> {
|
||||
let map_name = ui.primary.map.get_name().to_string();
|
||||
let (_, s) = wiz.wrap(ctx).choose_something_no_keys::<String>(
|
||||
"Load which scenario?",
|
||||
Box::new(move || abstutil::list_all_objects(abstutil::SCENARIOS, &map_name)),
|
||||
)?;
|
||||
let scenario = abstutil::read_binary(
|
||||
&abstutil::path1_bin(ui.primary.map.get_name(), abstutil::SCENARIOS, &s),
|
||||
&mut Timer::throwaway(),
|
||||
)
|
||||
.unwrap();
|
||||
Some(Transition::Replace(Box::new(
|
||||
scenario::ScenarioManager::new(scenario, ctx),
|
||||
)))
|
||||
}
|
||||
|
||||
struct LoadScenario {
|
||||
wizard: Wizard,
|
||||
}
|
||||
|
||||
impl State for LoadScenario {
|
||||
fn event(&mut self, ctx: &mut EventCtx, ui: &mut UI) -> Transition {
|
||||
if let Some(scenario) = load_scenario(&ui.primary.map, &mut self.wizard.wrap(ctx)) {
|
||||
return Transition::Replace(Box::new(scenario::ScenarioManager::new(scenario, ctx)));
|
||||
} else if self.wizard.aborted() {
|
||||
return Transition::Pop;
|
||||
}
|
||||
Transition::Keep
|
||||
}
|
||||
|
||||
fn draw(&self, g: &mut GfxCtx, _: &UI) {
|
||||
self.wizard.draw(g);
|
||||
}
|
||||
}
|
||||
|
||||
struct CreateNewScenario {
|
||||
wizard: Wizard,
|
||||
}
|
||||
|
||||
impl State for CreateNewScenario {
|
||||
fn event(&mut self, ctx: &mut EventCtx, ui: &mut UI) -> Transition {
|
||||
let mut wrapped = self.wizard.wrap(ctx);
|
||||
if let Some(name) = wrapped.input_string("Name the scenario") {
|
||||
return Transition::Replace(Box::new(scenario::ScenarioManager::new(
|
||||
Scenario {
|
||||
scenario_name: name,
|
||||
map_name: ui.primary.map.get_name().to_string(),
|
||||
seed_parked_cars: Vec::new(),
|
||||
spawn_over_time: Vec::new(),
|
||||
border_spawn_over_time: Vec::new(),
|
||||
individ_trips: Vec::new(),
|
||||
},
|
||||
ctx,
|
||||
)));
|
||||
} else if self.wizard.aborted() {
|
||||
return Transition::Pop;
|
||||
}
|
||||
Transition::Keep
|
||||
}
|
||||
|
||||
fn draw(&self, g: &mut GfxCtx, _: &UI) {
|
||||
self.wizard.draw(g);
|
||||
}
|
||||
fn create_new_scenario(wiz: &mut Wizard, ctx: &mut EventCtx, ui: &mut UI) -> Option<Transition> {
|
||||
let name = wiz.wrap(ctx).input_string("Name the scenario")?;
|
||||
Some(Transition::Replace(Box::new(
|
||||
scenario::ScenarioManager::new(
|
||||
Scenario {
|
||||
scenario_name: name,
|
||||
map_name: ui.primary.map.get_name().to_string(),
|
||||
seed_parked_cars: Vec::new(),
|
||||
spawn_over_time: Vec::new(),
|
||||
border_spawn_over_time: Vec::new(),
|
||||
individ_trips: Vec::new(),
|
||||
},
|
||||
ctx,
|
||||
),
|
||||
)))
|
||||
}
|
||||
|
||||
pub fn pick_time_range(
|
||||
@ -186,19 +153,3 @@ pub fn pick_time_range(
|
||||
let t2 = wizard.input_time_slider(high_query, t1, Duration::END_OF_DAY)?;
|
||||
Some((t1, t2))
|
||||
}
|
||||
|
||||
fn load_scenario(map: &Map, wizard: &mut WrappedWizard) -> Option<Scenario> {
|
||||
let map_name = map.get_name().to_string();
|
||||
wizard
|
||||
.choose_something_no_keys::<String>(
|
||||
"Load which scenario?",
|
||||
Box::new(move || abstutil::list_all_objects(abstutil::SCENARIOS, &map_name)),
|
||||
)
|
||||
.map(|(_, s)| {
|
||||
abstutil::read_binary(
|
||||
&abstutil::path1_bin(map.get_name(), abstutil::SCENARIOS, &s),
|
||||
&mut Timer::throwaway(),
|
||||
)
|
||||
.unwrap()
|
||||
})
|
||||
}
|
||||
|
@ -6,6 +6,7 @@ use map_model::{Map, NeighborhoodBuilder};
|
||||
|
||||
const POINT_RADIUS: Distance = Distance::const_meters(10.0);
|
||||
|
||||
// This shouldn't get subsumed by WizardState, since it has such an interesting draw().
|
||||
pub struct NeighborhoodPicker {
|
||||
wizard: Wizard,
|
||||
}
|
||||
|
@ -192,7 +192,7 @@ fn splash_screen(
|
||||
x if x == tutorial => Some(Transition::Push(Box::new(TutorialMode::new(ctx, ui)))),
|
||||
x if x == debug => Some(Transition::Push(Box::new(DebugMode::new(ctx, ui)))),
|
||||
x if x == mission => Some(Transition::Push(Box::new(MissionEditMode::new(ctx, ui)))),
|
||||
x if x == abtest => Some(Transition::Push(Box::new(PickABTest::new()))),
|
||||
x if x == abtest => Some(Transition::Push(PickABTest::new())),
|
||||
x if x == about => {
|
||||
if wizard.acknowledge(
|
||||
"About A/B Street",
|
||||
|
Loading…
Reference in New Issue
Block a user