95 lines
2.8 KiB
Rust
95 lines
2.8 KiB
Rust
use std::{io::Read, path::PathBuf};
|
|
|
|
use sgf::{parse_sgf, GameRecord};
|
|
use thiserror::Error;
|
|
|
|
#[derive(Error, Debug)]
|
|
pub enum Error {
|
|
/*
|
|
#[error("Database permission denied")]
|
|
PermissionDenied,
|
|
*/
|
|
#[error("An IO error occurred: {0}")]
|
|
IOError(std::io::Error),
|
|
}
|
|
|
|
impl From<std::io::Error> for Error {
|
|
fn from(err: std::io::Error) -> Self {
|
|
Error::IOError(err)
|
|
}
|
|
}
|
|
|
|
#[derive(Debug)]
|
|
pub struct Database {
|
|
games: Vec<GameRecord>,
|
|
}
|
|
|
|
impl Database {
|
|
pub fn open_path(path: PathBuf) -> Result<Database, Error> {
|
|
let mut games: Vec<GameRecord> = Vec::new();
|
|
|
|
let extension = PathBuf::from("sgf").into_os_string();
|
|
|
|
let path_iter = std::fs::read_dir(path.clone())?;
|
|
for entry in path_iter {
|
|
match entry {
|
|
Ok(entry) => {
|
|
if entry.path().extension() == Some(&extension) {
|
|
let mut buffer = String::new();
|
|
std::fs::File::open(entry.path())
|
|
.unwrap()
|
|
.read_to_string(&mut buffer)
|
|
.unwrap();
|
|
match parse_sgf(&buffer) {
|
|
Ok(sgfs) => {
|
|
let mut sgfs =
|
|
sgfs.into_iter().flatten().collect::<Vec<sgf::GameRecord>>();
|
|
games.append(&mut sgfs);
|
|
}
|
|
Err(err) => println!("Error parsing {:?}: {:?}", entry.path(), err),
|
|
}
|
|
}
|
|
}
|
|
Err(err) => println!("failed entry: {:?}", err),
|
|
}
|
|
}
|
|
|
|
Ok(Database { games })
|
|
}
|
|
|
|
pub fn all_games(&self) -> impl Iterator<Item = &GameRecord> {
|
|
self.games.iter()
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod test {
|
|
use super::*;
|
|
use cool_asserts::assert_matches;
|
|
use sgf::Date;
|
|
|
|
#[test]
|
|
fn it_reads_empty_database() {
|
|
let db = Database::open_path(PathBuf::from("fixtures/empty_database/"))
|
|
.expect("database to open");
|
|
assert_eq!(db.all_games().count(), 0);
|
|
}
|
|
|
|
#[ignore]
|
|
#[test]
|
|
fn it_reads_five_games_from_database() {
|
|
let db =
|
|
Database::open_path(PathBuf::from("fixtures/five_games/")).expect("database to open");
|
|
assert_eq!(db.all_games().count(), 5);
|
|
|
|
assert_matches!(db.all_games().find(|g| g.black_player.name == Some("Steve".to_owned())),
|
|
Some(game) => {
|
|
assert_eq!(game.black_player.name, Some("Steve".to_owned()));
|
|
assert_eq!(game.white_player.name, Some("Savanni".to_owned()));
|
|
assert_eq!(game.dates, vec![Date::Date(chrono::NaiveDate::from_ymd_opt(2023, 4, 19).unwrap())]);
|
|
// assert_eq!(game.info.komi, Some(6.5));
|
|
}
|
|
);
|
|
}
|
|
}
|