Disable sgf::go and provide a shim for a game

This commit is contained in:
Savanni D'Gerinel 2023-10-19 02:43:08 -04:00 committed by savanni
parent 48113d6ccb
commit 942e91009e
7 changed files with 84 additions and 98 deletions

View File

@ -1,6 +1,6 @@
use std::{io::Read, path::PathBuf}; use std::{io::Read, path::PathBuf};
use sgf::{go, parse_sgf, Game}; use sgf::{parse_sgf, Game};
use thiserror::Error; use thiserror::Error;
#[derive(Error, Debug)] #[derive(Error, Debug)]
@ -21,12 +21,12 @@ impl From<std::io::Error> for Error {
#[derive(Debug)] #[derive(Debug)]
pub struct Database { pub struct Database {
games: Vec<go::Game>, games: Vec<Game>,
} }
impl Database { impl Database {
pub fn open_path(path: PathBuf) -> Result<Database, Error> { pub fn open_path(path: PathBuf) -> Result<Database, Error> {
let mut games: Vec<go::Game> = Vec::new(); let mut games: Vec<Game> = Vec::new();
let extension = PathBuf::from("sgf").into_os_string(); let extension = PathBuf::from("sgf").into_os_string();
@ -43,10 +43,7 @@ impl Database {
match parse_sgf(&buffer) { match parse_sgf(&buffer) {
Ok(sgfs) => { Ok(sgfs) => {
for sgf in sgfs { for sgf in sgfs {
match sgf { games.push(sgf);
Game::Go(game) => games.push(game),
Game::Unsupported(_) => {}
}
} }
} }
Err(err) => println!("Error parsing {:?}: {:?}", entry.path(), err), Err(err) => println!("Error parsing {:?}: {:?}", entry.path(), err),
@ -60,7 +57,7 @@ impl Database {
Ok(Database { games }) Ok(Database { games })
} }
pub fn all_games(&self) -> impl Iterator<Item = &go::Game> { pub fn all_games(&self) -> impl Iterator<Item = &Game> {
self.games.iter() self.games.iter()
} }
} }
@ -78,6 +75,7 @@ mod test {
assert_eq!(db.all_games().count(), 0); assert_eq!(db.all_games().count(), 0);
} }
#[ignore]
#[test] #[test]
fn it_reads_five_games_from_database() { fn it_reads_five_games_from_database() {
let db = let db =

View File

@ -1,5 +1,5 @@
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use sgf::go::{Game, GameResult, Win}; use sgf::{Game, GameResult, Win};
use typeshare::typeshare; use typeshare::typeshare;
#[derive(Clone, Debug, Deserialize, Serialize)] #[derive(Clone, Debug, Deserialize, Serialize)]
@ -23,13 +23,13 @@ impl GamePreviewElement {
None => "unknown".to_owned(), None => "unknown".to_owned(),
}; };
let black_player = match game.info.black_rank { let black_player = match &game.info.black_rank {
Some(rank) => format!("{} ({})", black_player, rank.to_string()), Some(rank) => format!("{} ({})", black_player, rank),
None => black_player, None => black_player,
}; };
let white_player = match game.info.white_rank { let white_player = match &game.info.white_rank {
Some(rank) => format!("{} ({})", white_player, rank.to_string()), Some(rank) => format!("{} ({})", white_player, rank),
None => white_player, None => white_player,
}; };

View File

@ -1,6 +1,6 @@
use crate::ui::{Action, GamePreviewElement}; use crate::ui::{Action, GamePreviewElement};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use sgf::go::Game; use sgf::Game;
use typeshare::typeshare; use typeshare::typeshare;
fn rank_strings() -> Vec<String> { fn rank_strings() -> Vec<String> {

View File

@ -4,6 +4,7 @@ use std::{fmt, num::ParseIntError};
use thiserror::Error; use thiserror::Error;
use typeshare::typeshare; use typeshare::typeshare;
#[allow(dead_code)]
#[derive(Debug, Error, PartialEq)] #[derive(Debug, Error, PartialEq)]
pub enum Error { pub enum Error {
#[error("Failed to parse integer {0}")] #[error("Failed to parse integer {0}")]
@ -67,12 +68,14 @@ impl TryFrom<&str> for Date {
} }
*/ */
#[allow(dead_code)]
fn parse_numbers(s: &str) -> Result<Vec<i32>, Error> { fn parse_numbers(s: &str) -> Result<Vec<i32>, Error> {
s.split('-') s.split('-')
.map(|s| s.parse::<i32>().map_err(Error::ParseNumberError)) .map(|s| s.parse::<i32>().map_err(Error::ParseNumberError))
.collect::<Result<Vec<i32>, Error>>() .collect::<Result<Vec<i32>, Error>>()
} }
#[allow(dead_code)]
pub fn parse_date_field(s: &str) -> Result<Vec<Date>, Error> { pub fn parse_date_field(s: &str) -> Result<Vec<Date>, Error> {
let date_elements = s.split(','); let date_elements = s.split(',');
let mut dates = Vec::new(); let mut dates = Vec::new();

View File

@ -234,50 +234,6 @@ pub struct GameInfo {
pub result: Option<GameResult>, pub result: Option<GameResult>,
} }
#[derive(Clone, Debug, PartialEq)]
pub enum GameResult {
Annulled,
Draw,
Black(Win),
White(Win),
Unknown(String),
}
impl TryFrom<&str> for GameResult {
type Error = String;
fn try_from(s: &str) -> Result<GameResult, Self::Error> {
if s == "0" {
Ok(GameResult::Draw)
} else if s == "Void" {
Ok(GameResult::Annulled)
} else {
let parts = s.split('+').collect::<Vec<&str>>();
let res = match parts[0].to_ascii_lowercase().as_str() {
"b" => GameResult::Black,
"w" => GameResult::White,
_ => return Ok(GameResult::Unknown(parts[0].to_owned())),
};
match parts[1].to_ascii_lowercase().as_str() {
"r" | "resign" => Ok(res(Win::Resignation)),
"t" | "time" => Ok(res(Win::Time)),
"f" | "forfeit" => Ok(res(Win::Forfeit)),
_ => {
let score = parts[1].parse::<f32>().unwrap();
Ok(res(Win::Score(score)))
}
}
}
}
}
#[derive(Clone, Debug, PartialEq)]
pub enum Win {
Score(f32),
Resignation,
Forfeit,
Time,
}
/* /*
enum PropType { enum PropType {
Move, Move,

View File

@ -1,13 +1,14 @@
mod date; mod date;
pub use date::Date; pub use date::Date;
pub mod go;
mod tree; mod tree;
use tree::parse_collection; pub use tree::parse_collection;
use thiserror::Error; use thiserror::Error;
mod types;
pub use types::*;
#[derive(Debug)] #[derive(Debug)]
pub enum Error { pub enum Error {
InvalidField, InvalidField,
@ -56,41 +57,6 @@ impl From<nom::error::Error<&str>> for ParseError {
} }
} }
pub enum Game { pub fn parse_sgf(_input: &str) -> Result<Vec<Game>, Error> {
Go(go::Game), Ok(vec![Game::default()])
Unsupported(tree::Tree),
} }
pub fn parse_sgf(input: &str) -> Result<Vec<Game>, Error> {
let (_, trees) = parse_collection::<nom::error::VerboseError<&str>>(input)?;
Ok(trees
.into_iter()
.map(|t| match t.root.find_prop("GM") {
Some(prop) if prop.values == vec!["1".to_owned()] => {
Game::Go(go::Game::try_from(t).expect("properly structured game tree"))
}
_ => Game::Unsupported(t),
})
.collect::<Vec<Game>>())
}
/*
impl From<(&str, VerboseErrorKind)> for
impl From<nom::error::VerboseError<&str>> for ParseError {
fn from(err: nom::error::VerboseError<&str>) -> Self {
Self::NomErrors(
err.errors
.into_iter()
.map(|err| ParseError::from(err))
.collect(),
)
/*
Self::NomError(nom::error::Error {
input: err.input.to_owned(),
code: err.code.clone(),
})
*/
}
}
*/

63
sgf/src/types.rs Normal file
View File

@ -0,0 +1,63 @@
use crate::date::Date;
/// This is a placeholder structure. It is not meant to represent a game, only to provide a mock
/// interface for code already written that expects a Game data type to exist.
#[derive(Debug, Default)]
pub struct Game {
pub info: GameInfo,
}
#[derive(Debug, Default)]
pub struct GameInfo {
pub black_player: Option<String>,
pub black_rank: Option<String>,
pub white_player: Option<String>,
pub white_rank: Option<String>,
pub result: Option<GameResult>,
pub game_name: Option<String>,
pub date: Vec<Date>,
}
#[derive(Clone, Debug, PartialEq)]
pub enum GameResult {
Annulled,
Draw,
Black(Win),
White(Win),
Unknown(String),
}
impl TryFrom<&str> for GameResult {
type Error = String;
fn try_from(s: &str) -> Result<GameResult, Self::Error> {
if s == "0" {
Ok(GameResult::Draw)
} else if s == "Void" {
Ok(GameResult::Annulled)
} else {
let parts = s.split('+').collect::<Vec<&str>>();
let res = match parts[0].to_ascii_lowercase().as_str() {
"b" => GameResult::Black,
"w" => GameResult::White,
_ => return Ok(GameResult::Unknown(parts[0].to_owned())),
};
match parts[1].to_ascii_lowercase().as_str() {
"r" | "resign" => Ok(res(Win::Resignation)),
"t" | "time" => Ok(res(Win::Time)),
"f" | "forfeit" => Ok(res(Win::Forfeit)),
_ => {
let score = parts[1].parse::<f32>().unwrap();
Ok(res(Win::Score(score)))
}
}
}
}
}
#[derive(Clone, Debug, PartialEq)]
pub enum Win {
Score(f32),
Resignation,
Forfeit,
Time,
}