Skip to content

Commit

Permalink
fix fen editor
Browse files Browse the repository at this point in the history
  • Loading branch information
franciscoBSalgueiro committed Oct 1, 2023
1 parent aa3fce6 commit a351ff1
Show file tree
Hide file tree
Showing 4 changed files with 107 additions and 54 deletions.
3 changes: 2 additions & 1 deletion src-tauri/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ use crate::{
chess::get_best_moves,
db::{edit_db_info, get_db_info, get_games, get_players},
fs::download_file,
opening::get_opening_from_fen,
opening::{get_opening_from_fen, search_opening_name},
};
use tokio::sync::{RwLock, Semaphore};

Expand Down Expand Up @@ -204,6 +204,7 @@ fn main() {
download_file,
get_best_moves,
get_opening_from_fen,
search_opening_name,
get_puzzle,
get_games,
get_players,
Expand Down
39 changes: 38 additions & 1 deletion src-tauri/src/opening.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,15 @@ use shakmaty::{
};

use lazy_static::lazy_static;
use strsim::jaro_winkler;

#[derive(Serialize, Debug)]
use crate::error::Error;

#[derive(Serialize, Debug, Clone)]
pub struct Opening {
eco: String,
name: String,
fen: String,
}

#[derive(Deserialize)]
Expand Down Expand Up @@ -45,6 +49,37 @@ pub fn get_opening_from_fen(fen: &str) -> Result<&str, &str> {
.ok_or("No opening found")
}

#[tauri::command]
pub async fn search_opening_name(query: String) -> Result<Vec<Opening>, Error> {
let mut best_matches: Vec<(Opening, f64)> = Vec::new();

for opening in OPENINGS.values() {
if best_matches.iter().any(|(m, _)| m.name == opening.name) {
continue;
}

let score = jaro_winkler(&query, &opening.name);

if best_matches.len() < 15 {
best_matches.push((opening.clone(), score));
best_matches.sort_by(|a, b| b.1.partial_cmp(&a.1).unwrap());
} else if let Some(min_score) = best_matches.last().map(|(_, s)| *s) {
if score > min_score {
best_matches.pop();
best_matches.push((opening.clone(), score));
best_matches.sort_by(|a, b| b.1.partial_cmp(&a.1).unwrap());
}
}
}

if !best_matches.is_empty() {
let best_matches_names = best_matches.iter().map(|(o, _)| o.clone()).collect();
Ok(best_matches_names)
} else {
Err(Error::NoMatchFound)
}
}

pub fn get_opening_from_eco(eco: &str) -> Result<&str, &str> {
OPENINGS
.values()
Expand All @@ -67,11 +102,13 @@ lazy_static! {
pos.play_unchecked(&san.to_move(&pos).expect("legal move"));
}
}
let fen = Fen::from_position(pos.clone(), EnPassantMode::Legal);
map.insert(
pos.zobrist_hash(EnPassantMode::Legal),
Opening {
eco: record.eco,
name: record.name,
fen: fen.to_string(),
},
);
}
Expand Down
116 changes: 67 additions & 49 deletions src/components/panels/info/FenInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,21 +13,6 @@ type ItemProps = {
group?: string;
};

const POSITIONS: ItemProps[] = [
{
label: "Empty position",
value: "8/8/8/8/8/8/8/8 w - - 0 1",
},
{
label: "Starting position",
value: "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1",
},
{
label: "Ruy Lopez",
value: "r1bqkbnr/pppp1ppp/2n5/4p3/2B1P3/5N2/PPPP1PPP/RNBQK2R w KQkq - 0 1",
},
];

const SelectItem = forwardRef<HTMLDivElement, ItemProps>(function SelectItem(
{ label, value: fen, ...others }: ItemProps,
ref
Expand All @@ -53,12 +38,7 @@ type Castlingrights = {

function FenInput({ currentFen }: { currentFen: string }) {
const dispatch = useContext(TreeDispatchContext);
const [error, setError] = useState<string | undefined>(undefined);

let positions = POSITIONS;
if (!positions.find((p) => p.value === currentFen)) {
positions = [...positions, { label: currentFen, value: currentFen }];
}
let chess: Chess | null;
let whiteCastling: Castlingrights;
let blackCastling: Castlingrights;
Expand Down Expand Up @@ -90,40 +70,12 @@ function FenInput({ currentFen }: { currentFen: string }) {
}
}

function addFen(fen: string) {
if (fen) {
invoke<{ valid: boolean; error?: string }>("validate_fen", {
fen,
}).then((v) => {
if (v.valid) {
dispatch({ type: "SET_FEN", payload: fen });
setError(undefined);
} else if (v.error) {
setError(capitalize(v.error));
}
});
}
return fen;
}

return (
<Stack spacing="sm">
<Group>
<Stack sx={{ flexGrow: 1 }}>
<Text fw="bold">FEN</Text>
<Select
placeholder="Enter FEN"
value={currentFen}
data={positions}
error={error}
itemComponent={SelectItem}
dropdownPosition="bottom"
onChange={addFen}
onCreate={addFen}
getCreateLabel={(fen) => fen}
searchable
creatable
/>
<FenSearch currentFen={currentFen} />
<Select
data={[
{ label: "White to move", value: "w" },
Expand Down Expand Up @@ -186,4 +138,70 @@ function FenInput({ currentFen }: { currentFen: string }) {
);
}

function FenSearch({ currentFen }: { currentFen: string }) {
const [data, setData] = useState<ItemProps[]>([
{ label: currentFen, value: currentFen },
]);
const [error, setError] = useState<string | undefined>(undefined);
const dispatch = useContext(TreeDispatchContext);

function addFen(fen: string) {
if (fen) {
invoke<{ valid: boolean; error?: string }>("validate_fen", {
fen,
}).then((v) => {
if (v.valid) {
dispatch({ type: "SET_FEN", payload: fen });
setError(undefined);
} else if (v.error) {
setError(capitalize(v.error));
}
});
}
return fen;
}

async function searchOpening(name: string) {
const results = await invoke<
{
eco: string;
name: string;
fen: string;
}[]
>("search_opening_name", {
query: name,
});
setData([
{
label: name,
value: name,
},
...results.map((p) => ({
label: p.name,
value: p.fen,
})),
]);
}

return (
<Select
placeholder="Enter FEN"
value={currentFen}
data={data}
error={error}
itemComponent={SelectItem}
dropdownPosition="bottom"
onChange={addFen}
onCreate={addFen}
filter={() => true}
getCreateLabel={(fen) => {
searchOpening(fen);
return null;
}}
searchable
creatable
/>
);
}

export default memo(FenInput);
3 changes: 0 additions & 3 deletions src/utils/chess.ts
Original file line number Diff line number Diff line change
Expand Up @@ -343,9 +343,6 @@ export async function getOpening(
root: TreeNode,
position: number[]
): Promise<string> {
if (position.length === 0) {
return "";
}
const tree = getNodeAtPath(root, position);
if (tree === null) {
return "";
Expand Down

0 comments on commit a351ff1

Please sign in to comment.