jump to previous/next savestate

This commit is contained in:
Dustin Carlino 2018-12-09 17:16:15 -08:00
parent 44d9065123
commit ebc5419f9a
3 changed files with 74 additions and 25 deletions

View File

@ -3,7 +3,7 @@ use crate::plugins::{Plugin, PluginCtx};
use abstutil::elapsed_seconds;
use ezgui::EventLoopMode;
use piston::input::Key;
use sim::{Benchmark, TIMESTEP};
use sim::{Benchmark, Sim, TIMESTEP};
use std::mem;
use std::time::{Duration, Instant};
@ -77,15 +77,51 @@ impl Plugin for SimControls {
}
if ctx
.input
.unimportant_key_pressed(Key::P, SIM, "load sim state")
.unimportant_key_pressed(Key::Y, SIM, "load previous sim state")
{
match ctx.primary.sim.load_most_recent() {
match ctx
.primary
.sim
.find_previous_savestate(ctx.primary.sim.time)
.and_then(|path| Sim::load_savestate(path, None))
{
Ok(new_sim) => {
// TODO From the perspective of other SimMode plugins, does this just
// look like the simulation stepping forwards?
ctx.primary.sim = new_sim;
ctx.primary.recalculate_current_selection = true;
if let Some((s, _)) = ctx.secondary {
s.sim = Sim::load_savestate(
s.sim.find_previous_savestate(s.sim.time).unwrap(),
None,
)
.unwrap();
}
}
Err(e) => error!("Couldn't load savestate: {}", e),
};
}
if ctx
.input
.unimportant_key_pressed(Key::U, SIM, "load next sim state")
{
match ctx
.primary
.sim
.find_next_savestate(ctx.primary.sim.time)
.and_then(|path| Sim::load_savestate(path, None))
{
Ok(new_sim) => {
ctx.primary.sim = new_sim;
ctx.primary.recalculate_current_selection = true;
if let Some((s, _)) = ctx.secondary {
s.sim = s.sim.load_most_recent().unwrap();
s.sim = Sim::load_savestate(
s.sim.find_next_savestate(s.sim.time).unwrap(),
None,
)
.unwrap();
}
}
Err(e) => error!("Couldn't load savestate: {}", e),

View File

@ -88,9 +88,15 @@ impl Sim {
}
}
pub fn load(path: String, new_run_name: String) -> Result<Sim, std::io::Error> {
pub fn load_savestate(
path: String,
new_run_name: Option<String>,
) -> Result<Sim, std::io::Error> {
info!("Loading {}", path);
abstutil::read_json(&path).map(|mut s: Sim| {
s.run_name = new_run_name;
if let Some(name) = new_run_name {
s.run_name = name;
}
s
})
}
@ -135,15 +141,8 @@ impl Sim {
"At {} while processing {:?}",
self.time, self.current_agent_for_debugging
);
if let Ok(mut list) = self.find_all_savestates() {
// Find the most recent one BEFORE the current time
list.reverse();
for (tick, path) in list {
if tick < self.time {
error!("Debug from {}", path);
break;
}
}
if let Ok(path) = self.find_previous_savestate(self.time) {
error!("Debug from {}", path);
}
}
@ -313,15 +312,6 @@ impl Sim {
path
}
// TODO Return a descriptive error again
pub fn load_most_recent(&self) -> Result<Sim, std::io::Error> {
let (_, load) = self
.find_all_savestates()
.and_then(|mut list| list.pop().ok_or_else(|| io_error("empty directory")))?;
info!("Loading {}", load);
abstutil::read_json(&load)
}
// Earliest one is first
fn find_all_savestates(&self) -> Result<Vec<(Tick, String)>, std::io::Error> {
let mut results: Vec<(Tick, String)> = Vec::new();
@ -351,6 +341,28 @@ impl Sim {
Ok(results)
}
pub fn find_previous_savestate(&self, base_time: Tick) -> Result<String, std::io::Error> {
let mut list = self.find_all_savestates()?;
// Find the most recent one BEFORE the current time
list.reverse();
for (tick, path) in list {
if tick < base_time {
return Ok(path);
}
}
Err(io_error(&format!("no savestate before {}", base_time)))
}
pub fn find_next_savestate(&self, base_time: Tick) -> Result<String, std::io::Error> {
let list = self.find_all_savestates()?;
for (tick, path) in list {
if tick > base_time {
return Ok(path);
}
}
Err(io_error(&format!("no savestate after {}", base_time)))
}
pub fn active_agents(&self) -> Vec<AgentID> {
self.trips_state.active_agents()
}

View File

@ -89,7 +89,8 @@ pub fn run(t: &mut TestRunner) {
}
let sim3: sim::Sim =
sim::Sim::load(sim1_save.clone(), "with_savestating_3".to_string()).unwrap();
sim::Sim::load_savestate(sim1_save.clone(), Some("with_savestating_3".to_string()))
.unwrap();
if sim3 != sim2 {
panic!(
"sim state differs between {} and {}",