Set up the game review page along with #229

Merged
savanni merged 24 commits from otg/game-review into main 2024-03-31 23:37:51 +00:00
2 changed files with 27 additions and 17 deletions
Showing only changes of commit 3aac3b8393 - Show all commits

View File

@ -49,11 +49,11 @@ pub struct Player {
/// level, the interpreter will reject any games that have setup properties and move properties
/// mixed in a single node. If there are other semantic problems, the interpreter will reject
/// those, as well. Where the function of the parser is to understand and correct fundamental
/// syntax issues, the result of the Game is to have a fully-understood game. However, this doesn't
/// (yet?) go quite to the level of apply the game type (i.e., this is Go, Chess, Yinsh, or
/// syntax issues, the result of the GameRecord is to have a fully-understood game. However, this
/// doesn't (yet?) go quite to the level of apply the game type (i.e., this is Go, Chess, Yinsh, or
/// whatever).
#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
pub struct Game {
pub struct GameRecord {
pub game_type: GameType,
// TODO: board size is not necessary in all games. Hive has no defined board size.
@ -81,7 +81,7 @@ pub struct Game {
pub children: Vec<GameNode>,
}
impl Game {
impl GameRecord {
pub fn new(
game_type: GameType,
board_size: Size,
@ -116,7 +116,7 @@ impl Game {
}
}
impl Node for Game {
impl Node for GameRecord {
fn children<'a>(&'a self) -> Vec<&'a GameNode> {
self.children.iter().collect::<Vec<&'a GameNode>>()
}
@ -127,7 +127,7 @@ impl Node for Game {
}
}
impl TryFrom<&parser::Tree> for Game {
impl TryFrom<&parser::Tree> for GameRecord {
type Error = GameError;
fn try_from(tree: &parser::Tree) -> Result<Self, Self::Error> {
@ -503,7 +503,7 @@ mod test {
#[test]
fn it_can_create_an_empty_game_tree() {
let tree = Game::new(
let tree = GameRecord::new(
GameType::Go,
Size {
width: 19,
@ -517,7 +517,7 @@ mod test {
#[test]
fn it_can_add_moves_to_a_game() {
let mut game = Game::new(
let mut game = GameRecord::new(
GameType::Go,
Size {
width: 19,
@ -693,16 +693,16 @@ mod file_test {
use parser::parse_collection;
use std::{fs::File, io::Read};
fn with_text(text: &str, f: impl FnOnce(Vec<Game>)) {
fn with_text(text: &str, f: impl FnOnce(Vec<GameRecord>)) {
let (_, games) = parse_collection::<nom::error::VerboseError<&str>>(text).unwrap();
let games = games
.into_iter()
.map(|game| Game::try_from(&game).expect("game to parse"))
.collect::<Vec<Game>>();
.map(|game| GameRecord::try_from(&game).expect("game to parse"))
.collect::<Vec<GameRecord>>();
f(games);
}
fn with_file(path: &std::path::Path, f: impl FnOnce(Vec<Game>)) {
fn with_file(path: &std::path::Path, f: impl FnOnce(Vec<GameRecord>)) {
let mut file = File::open(path).unwrap();
let mut text = String::new();
let _ = file.read_to_string(&mut text);

View File

@ -5,7 +5,7 @@ mod types;
use std::{fs::File, io::Read};
pub use date::Date;
pub use game::Game;
pub use game::GameRecord;
pub use parser::parse_collection;
use thiserror::Error;
pub use types::*;
@ -58,16 +58,26 @@ impl From<nom::error::Error<&str>> for ParseError {
}
}
pub fn parse_sgf(input: &str) -> Result<Vec<Result<Game, game::GameError>>, Error> {
/// Given raw text of an SGF file, parse all of the games within that file.
///
/// The outermost Result is for any errors that happen in opening and reading the file, or if hte
/// outermost part of the file format is invalid.
///
/// The inner Result is for errors in each individual game in the file. All of the other games can
/// still be kept as valid.
pub fn parse_sgf(input: &str) -> Result<Vec<Result<GameRecord, game::GameError>>, Error> {
let (_, games) = parse_collection::<nom::error::VerboseError<&str>>(&input)?;
let games = games.into_iter()
.map(|game| Game::try_from(&game))
.collect::<Vec<Result<Game, game::GameError>>>();
.map(|game| GameRecord::try_from(&game))
.collect::<Vec<Result<GameRecord, game::GameError>>>();
Ok(games)
}
pub fn parse_sgf_file(path: &std::path::Path) -> Result<Vec<Result<Game, game::GameError>>, Error> {
/// Given a path, parse all of the games stored in that file.
///
/// See also `parse_sgf`
pub fn parse_sgf_file(path: &std::path::Path) -> Result<Vec<Result<GameRecord, game::GameError>>, Error> {
let mut file = File::open(path).unwrap();
let mut text = String::new();
let _ = file.read_to_string(&mut text);