Skip to main content

example/
example.rs

1use std::{
2    collections::HashMap,
3    fs::File,
4    io::{self, BufRead, BufReader, Write},
5    process::ExitCode,
6    str::FromStr,
7};
8
9use pns::{Net, State, Tid};
10
11fn main() -> ExitCode {
12    let mut save = false;
13    let mut load = false;
14
15    let mut args = std::env::args();
16    args.next();
17    for arg in args {
18        match arg.as_ref() {
19            "save" => save = true,
20            "load" => load = true,
21            _ => eprintln!("Ignore invalid argument '{arg}'"),
22        }
23    }
24
25    let Ok(net) = Net::load("pns/examples/example.pn".as_ref()) else {
26        eprintln!("Failed to load example net");
27        return ExitCode::FAILURE;
28    };
29
30    let mut names = HashMap::new();
31    let Ok(file) = File::open("pns/examples/example.pnk") else {
32        eprintln!("Failed to load example keys");
33        return ExitCode::FAILURE;
34    };
35    for (tid, line) in net.transition_ids().zip(BufReader::new(file).lines()) {
36        let Ok(line) = line else {
37            eprintln!("Failed to read key");
38            return ExitCode::FAILURE;
39        };
40        names.insert(tid, line);
41    }
42
43    if save && net.save("examples/example_copy.pns".as_ref()).is_err() {
44        eprintln!("Failed to save example net");
45    }
46
47    let mut state = if load {
48        let Ok(state) = State::load(&net, "examples/example.pns".as_ref()) else {
49            eprintln!("Loading state failed");
50            return ExitCode::FAILURE;
51        };
52        state
53    } else {
54        State::new(&net)
55    };
56
57    let mut forward = true;
58
59    loop {
60        let fireable = if forward {
61            state.fireable()
62        } else {
63            state.unfireable()
64        };
65
66        if fireable.is_empty() {
67            println!("Reverse play direction!");
68            println!();
69            forward = !forward;
70            continue;
71        }
72
73        println!("Choose a transition:");
74        let fireable: Vec<Tid> = fireable.collect();
75        for (i, tid) in fireable.iter().enumerate() {
76            println!("{}: {}", i + 1, names[tid]);
77        }
78        print!("> ");
79        let _ = io::stdout().flush();
80        let stdin = io::stdin();
81        let mut string = String::new();
82        let Ok(size) = stdin.read_line(&mut string) else {
83            eprintln!("Input error");
84            continue;
85        };
86        println!();
87        if size <= 1 {
88            continue;
89        }
90        match unsafe { string.chars().next().unwrap_unchecked() } {
91            'r' => {
92                println!("Reverse play direction!");
93                println!();
94                forward = !forward;
95                continue;
96            }
97            'q' => break,
98            's' => {
99                let result = if unsafe { state.save(&net, "examples/example.pns".as_ref()).is_ok() }
100                {
101                    "successful"
102                } else {
103                    "failed"
104                };
105
106                println!("Saving state {result}",);
107                println!();
108
109                continue;
110            }
111            _ => (),
112        }
113        match usize::from_str(&string[..(string.len() - 1)]) {
114            Ok(num) if num != 0 && num <= fireable.len() => {
115                let tid = fireable[num - 1];
116                if forward {
117                    unsafe { state.fire_unchecked(&net, tid) }
118                } else {
119                    unsafe { state.unfire_unchecked(&net, tid) }
120                }
121            }
122            _ => {
123                println!(
124                    "You have to input a valid number from 1 to {}",
125                    fireable.len()
126                );
127                println!();
128                println!("Other options:");
129                println!("q: Quit");
130                println!("r: Reverse play direction");
131                println!("s: Save");
132                println!();
133            }
134        }
135    }
136
137    ExitCode::SUCCESS
138}