1use crate::commands::{step, Command, CommandError};
7use crate::event::Event;
8use crate::observer::EventObserver;
9use crate::state::GameState;
10use std::io::{BufRead, Write};
11use std::path::Path;
12
13pub struct Session {
14 pub state: GameState,
15 pub log: Vec<Event>,
16}
17
18impl Session {
19 pub fn from_events(log: Vec<Event>, observers: &mut [&mut dyn EventObserver]) -> Session {
23 let state = GameState::replay(&log);
24 for event in &log {
25 for obs in observers.iter_mut() {
26 obs.on_event(event);
27 }
28 }
29 Session { state, log }
30 }
31
32 pub fn execute(
35 &mut self,
36 command: Command,
37 observers: &mut [&mut dyn EventObserver],
38 ) -> Result<&[Event], CommandError> {
39 let events = step(&self.state, command)?;
40 let start = self.log.len();
41 for event in events {
42 self.state.apply(&event);
43 for obs in observers.iter_mut() {
44 obs.on_event(&event);
45 }
46 self.log.push(event);
47 }
48 Ok(&self.log[start..])
49 }
50}
51
52pub fn save_log(path: &Path, log: &[Event]) -> std::io::Result<()> {
57 let file = std::fs::File::create(path)?;
58 let mut writer = std::io::BufWriter::new(file);
59 for event in log {
60 let line = serde_json::to_string(event)
61 .map_err(|e| std::io::Error::new(std::io::ErrorKind::InvalidData, e))?;
62 writeln!(writer, "{line}")?;
63 }
64 writer.flush()
65}
66
67pub fn load_log(path: &Path) -> std::io::Result<Vec<Event>> {
68 let file = std::fs::File::open(path)?;
69 let reader = std::io::BufReader::new(file);
70 let mut log = Vec::new();
71 for line in reader.lines() {
72 let line = line?;
73 if line.trim().is_empty() {
74 continue;
75 }
76 let event: Event = serde_json::from_str(&line)
77 .map_err(|e| std::io::Error::new(std::io::ErrorKind::InvalidData, e))?;
78 log.push(event);
79 }
80 Ok(log)
81}