File size: 4,052 Bytes
f0c8ada | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 | import { Chess } from "../../../libs/chess.js";
import { Classification } from "../../classification/MoveClassifier.js";
export const IgnoredSuggestionTypes = [
Classification.BRILLIANT.type,
Classification.GREAT.type,
Classification.PERFECT.type,
Classification.THEORY.type,
Classification.FORCED.type
];
export class MoveInformation {
constructor() {}
/**
* Converts a UCI string to a SAN string.
* @param {string} uci - The UCI string to convert.
* @param {string} fen - The FEN string to use for the conversion.
* @returns {string} The SAN string.
*/
static convertUCIToSAN(uci, fen) {
const tempChess = new Chess(fen);
const from = uci.substring(0, 2);
const to = uci.substring(2, 4);
const promotion = uci.length > 4 ? uci.substring(4, 5) : undefined;
const moveObj = tempChess.move({ from, to, promotion });
return moveObj.san;
}
/**
* Updates the move information display.
* @param {Object} node - The current move node.
* @param {Object} prevNode - The previous move node.
*/
static updateMoveInfo(node, prevNode) {
const $moveInfo = $(".move-info").empty();
// Show placeholder when at the root node or have no move data
if (!node || node.id === 'root' || !node.move) {
$("<div>").addClass("move-info-placeholder")
.text("Select a move to see its classification.")
.appendTo($moveInfo);
return;
}
// Create container for move classification info
const $moveInfoContainer = $("<div>").addClass("move-classification-info");
// Add the current move classification if available
if (node.classification) {
const $moveInfoLine = $("<div>").addClass("classification-line");
// Left side - classification and move
const $moveLeftSide = $("<div>").addClass("move-left-side");
// Are the icons cached yet?
const trueClassification = Classification[node.classification.toUpperCase()];
if (trueClassification?.cachedImg) {
const originalImg = trueClassification.cachedImg;
const clone = originalImg.cloneNode(true);
$moveLeftSide.append(clone);
} else {
$("<img>").addClass("move-icon")
.attr("src", trueClassification.src)
.attr("alt", node.classification)
.appendTo($moveLeftSide);
}
$("<span>").addClass("move")
.addClass(trueClassification.class)
.text(node.move.san + " " + trueClassification.comment)
.appendTo($moveLeftSide);
$moveInfoLine.append($moveLeftSide);
// Right side - best move alternative
if (node.evaluatedMove?.lines?.length > 0 && !IgnoredSuggestionTypes.includes(node.classification)) {
// Get the previous position's best move
if (prevNode?.evaluatedMove?.lines) {
const bestLine = prevNode.evaluatedMove.lines.find(line => line.id === 1);
if (bestLine) {
// Get best move UCI string - either from uciMove or first element of pv array
const bestMoveUci = bestLine.uciMove || (bestLine.pv && bestLine.pv.length > 0 ? bestLine.pv[0] : null);
if (bestMoveUci) {
const san = MoveInformation.convertUCIToSAN(bestMoveUci, prevNode.fen);
$("<div>").addClass("perfect-move-alternative")
.text("Best was " + san)
.appendTo($moveInfoLine);
}
}
}
}
$moveInfoContainer.append($moveInfoLine);
}
// Add the container to the move-info div
$moveInfo.append($moveInfoContainer);
}
} |