Set up SGF reading and start on the game database #47
|
@ -45,6 +45,7 @@ dependencies = [
|
|||
"js-sys",
|
||||
"num-integer",
|
||||
"num-traits",
|
||||
"time",
|
||||
"wasm-bindgen",
|
||||
"winapi",
|
||||
]
|
||||
|
@ -109,6 +110,15 @@ dependencies = [
|
|||
"syn 2.0.12",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "go-sgf"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"chrono",
|
||||
"nom",
|
||||
"thiserror",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "grid"
|
||||
version = "0.9.0"
|
||||
|
@ -161,6 +171,7 @@ dependencies = [
|
|||
name = "kifu-core"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"go-sgf",
|
||||
"grid",
|
||||
"serde",
|
||||
"serde_json",
|
||||
|
@ -192,12 +203,34 @@ dependencies = [
|
|||
"cfg-if",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
version = "2.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
|
||||
|
||||
[[package]]
|
||||
name = "minimal-lexical"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
|
||||
|
||||
[[package]]
|
||||
name = "no-std-compat"
|
||||
version = "0.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b93853da6d84c2e3c7d730d6473e8817692dd89be387eb01b94d7f108ecb5b8c"
|
||||
|
||||
[[package]]
|
||||
name = "nom"
|
||||
version = "7.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
"minimal-lexical",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-integer"
|
||||
version = "0.1.45"
|
||||
|
@ -335,6 +368,17 @@ dependencies = [
|
|||
"syn 2.0.12",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "time"
|
||||
version = "0.1.45"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1b797afad3f312d1c66a56d11d0316f916356d11bd158fbc6ca6389ff6bf805a"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"wasi",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "typeshare"
|
||||
version = "1.0.1"
|
||||
|
@ -369,6 +413,12 @@ version = "0.1.10"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b"
|
||||
|
||||
[[package]]
|
||||
name = "wasi"
|
||||
version = "0.10.0+wasi-snapshot-preview1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f"
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen"
|
||||
version = "0.2.84"
|
||||
|
|
|
@ -6,8 +6,9 @@ edition = "2021"
|
|||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
go-sgf = { path = "../../go-sgf" }
|
||||
grid = { version = "0.9" }
|
||||
serde = { version = "1", features = [ "derive" ] }
|
||||
serde_json = { version = "1" }
|
||||
serde = { version = "1", features = [ "derive" ] }
|
||||
thiserror = { version = "1" }
|
||||
typeshare = { version = "1" }
|
||||
|
|
|
@ -0,0 +1,77 @@
|
|||
use std::{ffi::OsStr, io::Read, os::unix::ffi::OsStrExt, path::PathBuf};
|
||||
|
||||
use go_sgf::go::{parse_sgf, GameTree, GameType};
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Database {
|
||||
path: PathBuf,
|
||||
games: Vec<GameTree>,
|
||||
}
|
||||
|
||||
impl Database {
|
||||
pub fn open_path(path: PathBuf) -> Result<Database, Error> {
|
||||
let mut games: Vec<GameTree> = 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();
|
||||
let sgf = parse_sgf(&buffer).unwrap();
|
||||
games.extend(sgf);
|
||||
}
|
||||
}
|
||||
Err(err) => println!("failed entry: {:?}", err),
|
||||
}
|
||||
}
|
||||
|
||||
Ok(Database { path, games })
|
||||
}
|
||||
|
||||
pub fn all_games(&self) -> impl Iterator<Item = &GameTree> {
|
||||
self.games.iter()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
|
||||
#[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);
|
||||
}
|
||||
|
||||
#[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);
|
||||
for game in db.all_games() {
|
||||
assert_eq!(game.game_type, GameType::Go);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -3,12 +3,14 @@ pub use api::{
|
|||
CoreApp, CoreRequest, CoreResponse, CreateGameRequest, HotseatPlayerRequest, PlayerInfoRequest,
|
||||
};
|
||||
|
||||
mod types;
|
||||
pub use types::{BoardError, Color, Rank, Size};
|
||||
pub mod ui;
|
||||
|
||||
mod board;
|
||||
pub use board::*;
|
||||
|
||||
mod config;
|
||||
pub use config::*;
|
||||
|
||||
mod database;
|
||||
|
||||
mod types;
|
||||
pub use types::{BoardError, Color, Rank, Size};
|
||||
pub mod ui;
|
||||
|
|
Loading…
Reference in New Issue