use std::collections::HashMap;
use crate::{CLASSIC_RULESET, Game, GameResult, Metadata::*, PlayerColor, San};
use super::Pgn;
static REQUIRED_TAGS: [&str; 6] = [
METADATA_KEY_BLACK,
METADATA_KEY_WHITE,
METADATA_KEY_DATE,
METADATA_KEY_ROUND,
METADATA_KEY_EVENT,
METADATA_KEY_SITE,
];
impl Pgn {
#[must_use]
pub fn export(game: &Game) -> String {
let mut metadata = game.get_metadata_map().clone();
let game_result = game.get_game_result();
Self::add_seven_tag_roster(&mut metadata, game_result);
let metadata = Self::format_metadata(&metadata);
let turndata = Self::format_turndata(game);
format!("{}\n{}", metadata, turndata)
}
fn format_turndata(game: &Game) -> String {
let mut result = String::new();
let mut first_fullmove_indicator: bool = true;
let position_history = game.get_all_positions();
let turn_history = game.get_all_turns();
for (position_index, position) in position_history.iter().enumerate() {
if position_index == position_history.len() - 1 {
let game_result =
GameResult::to_string(CLASSIC_RULESET.game_over_check(position).as_ref());
result.push_str(&game_result);
break;
}
match position.get_active_color() {
PlayerColor::Black => {
if first_fullmove_indicator {
result.push_str(&position.get_fullmove_counter().to_string());
result.push_str(".. ");
first_fullmove_indicator = false;
}
}
PlayerColor::White => {
result.push_str(&position.get_fullmove_counter().to_string());
result.push_str(". ");
first_fullmove_indicator = false;
}
}
let turn = turn_history.get(position_index).unwrap();
result.push_str(&San::export(turn, position));
result.push(' ');
}
result
}
fn format_metadata(metadata: &HashMap<String, String>) -> String {
metadata
.iter()
.map(|(key, value)| format!("[{} \"{}\"]\n", key, value))
.collect::<Vec<String>>()
.join("")
}
fn add_seven_tag_roster(
metadata_map: &mut HashMap<String, String>,
game_result: Option<GameResult>,
) {
for tag in REQUIRED_TAGS {
if metadata_map.get(tag).is_none() {
metadata_map.insert(tag.to_string(), "".to_string());
}
}
if metadata_map.get(METADATA_KEY_RESULT).is_some() {
return;
}
let result = GameResult::to_string(game_result.as_ref());
metadata_map.insert(METADATA_KEY_RESULT.to_string(), result);
}
}