Skip to content

Commit

Permalink
allow non-standard starting positions in databases
Browse files Browse the repository at this point in the history
  • Loading branch information
franciscoBSalgueiro committed Dec 4, 2023
1 parent 44174c3 commit d414b9b
Show file tree
Hide file tree
Showing 6 changed files with 47 additions and 43 deletions.
6 changes: 3 additions & 3 deletions src-tauri/src/db/encoding.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::error::Error;
use shakmaty::{san::SanPlus, Chess, Move, Position};
use shakmaty::{fen::Fen, san::SanPlus, CastlingMode, Chess, FromSetup, Move, Position};

pub fn encode_move(m: &Move, chess: &Chess) -> Result<u8, Error> {
let moves = chess.legal_moves();
Expand All @@ -11,8 +11,8 @@ pub fn decode_move(byte: u8, chess: &Chess) -> Option<Move> {
legal_moves.get(byte as usize).cloned()
}

pub fn decode_moves(moves_bytes: Vec<u8>) -> Result<String, Error> {
let mut chess = Chess::default();
pub fn decode_moves(moves_bytes: Vec<u8>, initial_fen: Fen) -> Result<String, Error> {
let mut chess = Chess::from_setup(initial_fen.into(), CastlingMode::Standard).unwrap();
let mut moves = Vec::new();
for byte in moves_bytes {
let m = decode_move(byte, &chess).unwrap();
Expand Down
62 changes: 35 additions & 27 deletions src-tauri/src/db/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ use diesel::{
};
use pgn_reader::{BufferedReader, RawHeader, SanPlus, Skip, Visitor};
use serde::{Deserialize, Serialize};
use shakmaty::{fen::Fen, Board, ByColor, Chess, Piece, Position};
use shakmaty::{fen::Fen, Board, ByColor, Chess, FromSetup, Piece, Position};

use std::{
fs::{remove_file, File},
Expand Down Expand Up @@ -311,9 +311,10 @@ impl Visitor for Importer {
if value.as_bytes() == b"rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1" {
self.game.fen = None;
} else {
// Don't process games that don't start in standard position
self.skip = true;
// self.current.fen = Some(value.decode_utf8_lossy().into_owned());
let fen = Fen::from_ascii(value.as_bytes()).unwrap();
self.game.fen = Some(value.decode_utf8_lossy().into_owned());
self.game.position =
Chess::from_setup(fen.into_setup(), shakmaty::CastlingMode::Standard).unwrap();
}
}
}
Expand Down Expand Up @@ -861,29 +862,36 @@ pub async fn get_games(
fn normalize_games(games: Vec<(Game, Player, Player, Event, Site)>) -> Vec<NormalizedGame> {
games
.into_iter()
.map(|(game, white, black, event, site)| NormalizedGame {
id: game.id,
event: event.name.unwrap_or_default(),
event_id: event.id,
site: site.name.unwrap_or_default(),
site_id: site.id,
date: game.date,
time: game.time,
round: game.round,
white: white.name.unwrap_or_default(),
white_id: game.white_id,
white_elo: game.white_elo,
black: black.name.unwrap_or_default(),
black_id: game.black_id,
black_elo: game.black_elo,
result: game.result,
time_control: game.time_control,
eco: game.eco,
white_material: game.white_material,
black_material: game.black_material,
ply_count: game.ply_count,
fen: game.fen.unwrap_or(Fen::default().to_string()),
moves: decode_moves(game.moves).unwrap_or_default(),
.map(|(game, white, black, event, site)| {
let fen: Fen = game
.fen
.map(|f| Fen::from_ascii(f.as_bytes()).unwrap())
.unwrap_or_default();

NormalizedGame {
id: game.id,
event: event.name.unwrap_or_default(),
event_id: event.id,
site: site.name.unwrap_or_default(),
site_id: site.id,
date: game.date,
time: game.time,
round: game.round,
white: white.name.unwrap_or_default(),
white_id: game.white_id,
white_elo: game.white_elo,
black: black.name.unwrap_or_default(),
black_id: game.black_id,
black_elo: game.black_elo,
result: game.result,
time_control: game.time_control,
eco: game.eco,
white_material: game.white_material,
black_material: game.black_material,
ply_count: game.ply_count,
fen: fen.to_string(),
moves: decode_moves(game.moves, fen).unwrap_or_default(),
}
})
.collect()
}
Expand Down
2 changes: 1 addition & 1 deletion src/components/databases/GameCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ function GameCard({ game }: { game: NormalizedGame }) {
<Stack h="100%">
<GameInfo headers={game} />
<Divider mb="sm" />
<GamePreview pgn={game.moves} />
<GamePreview pgn={game.moves} headers={game} />
</Stack>
</Paper>
);
Expand Down
14 changes: 5 additions & 9 deletions src/components/databases/GamePreview.tsx
Original file line number Diff line number Diff line change
@@ -1,33 +1,33 @@
import { Box, Group, Stack, Text } from "@mantine/core";
import { useHotkeys } from "react-hotkeys-hook";
import { useContext } from "react";
import { Chessground } from "@/chessground/Chessground";
import MoveControls from "../common/MoveControls";
import { useAtomValue, useSetAtom } from "jotai";
import { useSetAtom } from "jotai";
import { activeTabAtom } from "@/atoms/atoms";
import GameNotation from "../boards/GameNotation";
import {
TreeDispatchContext,
TreeStateContext,
} from "../common/TreeStateContext";
import { useImmerReducer } from "use-immer";
import treeReducer, { TreeState, getNodeAtPath } from "@/utils/treeReducer";
import treeReducer, { GameHeaders, TreeState, getNodeAtPath } from "@/utils/treeReducer";
import { useNavigate } from "react-router-dom";
import { parsePGN } from "@/utils/chess";
import useSWR from "swr";
import { keyMapAtom } from "@/atoms/keybinds";

function GamePreviewWrapper({
id,
pgn,
headers,
hideControls,
}: {
id?: string;
pgn: string;
headers?: GameHeaders;
hideControls?: boolean;
}) {
const { data: parsedGame, isLoading } = useSWR(pgn, async (game) => {
return await parsePGN(game);
return await parsePGN(game, headers?.fen);
});

return (
Expand Down Expand Up @@ -62,10 +62,6 @@ function GamePreview({

const [treeState, dispatch] = useImmerReducer(treeReducer, game);

const keyMap = useAtomValue(keyMapAtom);
useHotkeys(keyMap.PREVIOUS_MOVE.keys, () => dispatch({ type: "GO_TO_PREVIOUS" }));
useHotkeys(keyMap.NEXT_MOVE.keys, () => dispatch({ type: "GO_TO_NEXT" }));

return (
<TreeStateContext.Provider value={treeState}>
<TreeDispatchContext.Provider value={dispatch}>
Expand Down
4 changes: 2 additions & 2 deletions src/utils/chess.ts
Original file line number Diff line number Diff line change
Expand Up @@ -403,11 +403,11 @@ function innerParsePGN(
return tree;
}

export async function parsePGN(pgn: string, halfMoves = 0): Promise<TreeState> {
export async function parsePGN(pgn: string, initialFen?: string): Promise<TreeState> {
const tokens = await invoke<Token[]>("lex_pgn", { pgn: pgn });

const headers = getPgnHeaders(tokens);
const tree = innerParsePGN(tokens, headers.fen, halfMoves);
const tree = innerParsePGN(tokens, initialFen || headers.fen, 0);
tree.headers = headers;
tree.position = headers.start ?? [];
return tree;
Expand Down
2 changes: 1 addition & 1 deletion src/utils/tabs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ export async function createTab({
const id = genID();

if (pgn) {
const tree = await parsePGN(pgn);
const tree = await parsePGN(pgn, headers?.fen);
if (headers) {
tree.headers = headers;
}
Expand Down

0 comments on commit d414b9b

Please sign in to comment.