use std::{ collections::HashMap, fs::File, io::{self, BufRead, BufReader}, process::ExitCode, str::FromStr, }; use pns::{Net, State, Tid}; fn main() -> ExitCode { let mut save = false; let mut load = false; let mut args = std::env::args(); args.next(); for arg in args { match arg.as_ref() { "save" => save = true, "load" => load = true, _ => eprintln!("Ignore invalid argument '{arg}'"), } } let Ok(net) = Net::load("pns/examples/example.pn".as_ref()) else { eprintln!("Failed to load example net"); return ExitCode::FAILURE; }; let mut names = HashMap::new(); let Ok(file) = File::open("pns/examples/example.pnk") else { eprintln!("Failed to load example keys"); return ExitCode::FAILURE; }; for (tid, line) in net.transition_ids().zip(BufReader::new(file).lines()) { let Ok(line) = line else { eprintln!("Failed to read key"); return ExitCode::FAILURE; }; names.insert(tid, line); } if save && net.save("examples/example_copy.pns".as_ref()).is_err() { eprintln!("Failed to save example net"); } let mut state = if load { let Ok(state) = State::load(&net, "examples/example.pns".as_ref()) else { eprintln!("Loading state failed"); return ExitCode::FAILURE; }; state } else { State::new(&net) }; let mut forward = true; loop { let fireable = if forward { state.fireable() } else { state.unfireable() }; if fireable.is_empty() { println!("Reverse play direction!"); forward = !forward; continue; } let fireable: Vec = fireable.collect(); for (i, tid) in fireable.iter().enumerate() { println!("{}: {}", i + 1, names[tid]); } let stdin = io::stdin(); let mut string = String::new(); let Ok(size) = stdin.read_line(&mut string) else { eprintln!("Input error"); continue; }; if size == 0 { continue; } match unsafe { string.chars().next().unwrap_unchecked() } { 'r' => { println!("Reverse play direction!"); forward = !forward; continue; } 'q' => break, 's' => { println!( "{}", if unsafe { state.save(&net, "examples/example.pns".as_ref()).is_ok() } { "Saving successful" } else { "Saving failed" } ); continue; } _ => (), } match usize::from_str(&string[..(string.len() - 1)]) { Ok(num) if num != 0 && num <= fireable.len() => { let tid = fireable[num - 1]; if forward { unsafe { state.fire_unchecked(&net, tid) } } else { unsafe { state.unfire_unchecked(&net, tid) } }; } _ => { println!( "You have to input a valid number from 1 to {}", fireable.len() ); println!("You can also quit by writing \"q\", save the current state by writing \"s\" or reverse by writing \"r\""); continue; } } } ExitCode::SUCCESS }