87 lines
2.7 KiB
Rust
87 lines
2.7 KiB
Rust
use std::path::{Path, PathBuf};
|
|
use std::fs::File;
|
|
use std::collections::{HashMap, BinaryHeap};
|
|
use std::cmp::Reverse;
|
|
use std::io::Write;
|
|
|
|
use crate::game::{Game, Coord};
|
|
|
|
/// An error when writing to a file
|
|
#[derive(Debug)]
|
|
pub enum WriterError {
|
|
FileAccessError,
|
|
WriteError,
|
|
}
|
|
|
|
|
|
/// Write the given game to the file at the given path.
|
|
pub fn write_game_at_path(path: PathBuf, game: &Game) -> Result<(), WriterError> {
|
|
let mut file = create_file(path.as_path())?;
|
|
write_game(&mut file, game)
|
|
}
|
|
|
|
/// Write the given game to the writer. Currently only accept `std::io::Write` implementors.
|
|
pub fn write_game(writer: &mut impl Write, game: &Game) -> Result<(), WriterError> {
|
|
//let path = Path::new(path);
|
|
let mut string = String::new();
|
|
let mut values = CellRows::new();
|
|
for i in game.cells() {
|
|
values.insert(i);
|
|
}
|
|
for y in values.smallest_y..values.greatest_y+1 {
|
|
if let Some(row) = values.rows.get_mut(&y) {
|
|
for x in values.smallest_x..values.greatest_x+1 {
|
|
if let Some(ch) = row.peek() {
|
|
if ch.0 == x {
|
|
string.push_str("*");
|
|
row.pop();
|
|
} else {
|
|
string.push_str(".");
|
|
}
|
|
} else {
|
|
string.push_str(".");
|
|
}
|
|
}
|
|
}
|
|
string.push_str("\n");
|
|
}
|
|
match write!(writer, "{}", string) {
|
|
Ok(_) => Ok(()),
|
|
Err(_) => Err(WriterError::WriteError),
|
|
}
|
|
}
|
|
|
|
fn create_file(path: &Path) -> Result<File, WriterError> {
|
|
match File::create(path) {
|
|
Ok(file) => Ok(file),
|
|
Err(_) => Err(WriterError::FileAccessError),
|
|
}
|
|
}
|
|
|
|
#[derive(Default)]
|
|
struct CellRows {
|
|
rows: HashMap<isize, BinaryHeap<Reverse<isize>>>,
|
|
smallest_x: isize,
|
|
greatest_x: isize,
|
|
smallest_y: isize,
|
|
greatest_y: isize,
|
|
smallest_x_set: bool,
|
|
smallest_y_set: bool,
|
|
greatest_x_set: bool,
|
|
greatest_y_set: bool,
|
|
}
|
|
|
|
impl CellRows {
|
|
pub fn new() -> Self {
|
|
Self::default()
|
|
}
|
|
|
|
pub fn insert(&mut self, (x, y): Coord) {
|
|
if x < self.smallest_x || !self.smallest_x_set { self.smallest_x = x; self.smallest_x_set = true };
|
|
if y < self.smallest_y || !self.smallest_y_set { self.smallest_y = y; self.smallest_y_set = true };
|
|
if x > self.greatest_x || !self.greatest_x_set { self.greatest_x = x; self.greatest_x_set = true };
|
|
if y > self.greatest_y || !self.greatest_y_set { self.greatest_y = y; self.greatest_y_set = true };
|
|
self.rows.entry(y).and_modify(|heap| {heap.push(Reverse(x))}).or_insert({let mut heap = BinaryHeap::new(); heap.push(Reverse(x)); heap});
|
|
}
|
|
}
|