sounds + layout
This commit is contained in:
@@ -6,29 +6,30 @@ interface EvaluationBarProps {
|
||||
score?: number | null; // centipawns
|
||||
mate?: number | null; // moves to mate
|
||||
isPlayerWhite: boolean;
|
||||
orientation?: 'vertical' | 'horizontal';
|
||||
}
|
||||
|
||||
export function EvaluationBar({ score, mate, isPlayerWhite }: EvaluationBarProps) {
|
||||
// Calculate white's percentage height
|
||||
export function EvaluationBar({ score, mate, isPlayerWhite, orientation = 'vertical' }: EvaluationBarProps) {
|
||||
// Calculate white's percentage height/width
|
||||
// Using sigmoid-like function for score: P = 1 / (1 + 10^(-score/400))
|
||||
// This is a standard way to visualize CP advantage.
|
||||
let whiteHeightPercent = 50;
|
||||
let whitePercent = 50;
|
||||
let label = "0.0";
|
||||
|
||||
if (mate !== null && mate !== undefined) {
|
||||
// Mate detected
|
||||
if (mate > 0) {
|
||||
whiteHeightPercent = 100;
|
||||
whitePercent = 100;
|
||||
label = `M${Math.abs(mate)}`;
|
||||
} else {
|
||||
whiteHeightPercent = 0;
|
||||
whitePercent = 0;
|
||||
label = `M${Math.abs(mate)}`;
|
||||
}
|
||||
} else if (score !== null && score !== undefined) {
|
||||
// Score is in centipawns. 100 cp = 1 pawn.
|
||||
// We clamp the visual score somewhat to avoid extreme compression
|
||||
const winChance = 1 / (1 + Math.pow(10, -score / 400));
|
||||
whiteHeightPercent = winChance * 100;
|
||||
whitePercent = winChance * 100;
|
||||
|
||||
// Format label: +1.5 or -0.3
|
||||
// If player is NOT white, we invert the score for display (so + means Player advantage)
|
||||
@@ -41,22 +42,37 @@ export function EvaluationBar({ score, mate, isPlayerWhite }: EvaluationBarProps
|
||||
if (score === 0) label = "0.0";
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="w-8 h-full bg-gray-800 border border-gray-400 relative overflow-hidden rounded shadow-inner">
|
||||
{/* Black background is the container (h-full) */}
|
||||
const isVertical = orientation === 'vertical';
|
||||
|
||||
{/* White bar grows from bottom if player is white, from top if player is black */}
|
||||
return (
|
||||
<div className={clsx(
|
||||
"bg-gray-800 border border-gray-400 relative overflow-hidden rounded shadow-inner",
|
||||
isVertical ? "w-8 h-full" : "w-full h-6"
|
||||
)}>
|
||||
{/* Black background is the container */}
|
||||
|
||||
{/* White bar grows from bottom/left if player is white, from top/right if player is black */}
|
||||
<div
|
||||
className={clsx(
|
||||
"absolute w-full bg-white transition-all duration-500 ease-in-out",
|
||||
isPlayerWhite ? "bottom-0" : "top-0"
|
||||
"absolute bg-white transition-all duration-500 ease-in-out",
|
||||
isVertical ? "w-full" : "h-full",
|
||||
// Vertical positioning
|
||||
isVertical && (isPlayerWhite ? "bottom-0" : "top-0"),
|
||||
// Horizontal positioning
|
||||
!isVertical && (isPlayerWhite ? "left-0" : "right-0")
|
||||
)}
|
||||
style={{ height: `${whiteHeightPercent}%` }}
|
||||
style={{
|
||||
height: isVertical ? `${whitePercent}%` : '100%',
|
||||
width: !isVertical ? `${whitePercent}%` : '100%'
|
||||
}}
|
||||
/>
|
||||
|
||||
{/* Score Label */}
|
||||
<div className="absolute inset-0 flex items-center justify-center pointer-events-none">
|
||||
<span className="text-xs font-bold text-white mix-blend-difference select-none">
|
||||
<span className={clsx(
|
||||
"font-bold text-white mix-blend-difference select-none",
|
||||
isVertical ? "text-xs" : "text-sm"
|
||||
)}>
|
||||
{label}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user