feat: add value ± standard deviation to RaceChart

This commit is contained in:
julius 2025-03-02 20:09:54 +01:00
parent a52dae5605
commit de79970987
Signed by: julius
GPG Key ID: C80A63E6A5FD7092

View File

@ -1,5 +1,5 @@
import { FC, useEffect, useState } from 'react'; import { FC, useEffect, useState } from "react";
import { PlayerRanking } from './types'; import { PlayerRanking } from "./types";
interface RaceChartProps { interface RaceChartProps {
players: PlayerRanking[]; players: PlayerRanking[];
@ -8,38 +8,35 @@ interface RaceChartProps {
const determineNiceWidth = (width: number) => { const determineNiceWidth = (width: number) => {
const max = 1080; const max = 1080;
if (width >= max) if (width >= max) return max;
return max else if (width > 768) return width * 0.8;
else if (width > 768) else return width * 0.96;
return width * 0.8 };
else
return width * 0.96
}
const RaceChart: FC<RaceChartProps> = ({ players, std }) => { const RaceChart: FC<RaceChartProps> = ({ players, std }) => {
// State to store window's width and height // State to store window's width and height
const [width, setWidth] = useState(determineNiceWidth(window.innerWidth)); const [width, setWidth] = useState(determineNiceWidth(window.innerWidth));
const [height, setHeight] = useState(window.innerHeight); //const [height, setHeight] = useState(window.innerHeight);
const height = players.length * 40;
// Update state on resize // Update state on resize
useEffect(() => { useEffect(() => {
const handleResize = () => { const handleResize = () => {
setWidth(determineNiceWidth(window.innerWidth)); setWidth(determineNiceWidth(window.innerWidth));
setHeight(window.innerHeight); //setHeight(window.innerHeight);
}; };
window.addEventListener('resize', handleResize); window.addEventListener("resize", handleResize);
return () => { return () => {
window.removeEventListener('resize', handleResize); window.removeEventListener("resize", handleResize);
}; };
}, []); }, []);
const padding = 24; const padding = 24;
const gap = 8 const gap = 8;
const maxValue = Math.max(...players.map((player) => player.rank)) + 1; const maxValue = Math.max(...players.map((player) => player.rank)) + 1;
const barHeight = (height - 2 * padding) / players.length; const barHeight = (height - 2 * padding) / players.length;
return ( return (
<svg width={width} height={height}> <svg width={width} height={height}>
{players.map((player, index) => ( {players.map((player, index) => (
<rect <rect
key={index} key={index}
@ -48,9 +45,11 @@ const RaceChart: FC<RaceChartProps> = ({ players, std }) => {
width={(1 - player.rank / maxValue) * width} width={(1 - player.rank / maxValue) * width}
height={barHeight - gap} // subtract 2 for some spacing between bars height={barHeight - gap} // subtract 2 for some spacing between bars
fill="#36c" fill="#36c"
/>))} />
))}
{players.map((player, index) => ( {players.map((player, index) => (
<g>
<text <text
key={index} key={index}
x={4} x={4}
@ -59,14 +58,37 @@ const RaceChart: FC<RaceChartProps> = ({ players, std }) => {
height={barHeight - 8} // subtract 2 for some spacing between bars height={barHeight - 8} // subtract 2 for some spacing between bars
fontSize={`${barHeight - 1.5 * gap}px`} fontSize={`${barHeight - 1.5 * gap}px`}
fill="aliceblue" fill="aliceblue"
stroke='#36c' stroke="#36c"
strokeWidth={1.6} strokeWidth={4}
fontWeight={"bold"} fontWeight={"bold"}
paintOrder={"stroke fill"} paintOrder={"stroke fill"}
>{player.name}</text> fontFamily="monospace"
))} >
{player.name}
</svg> </text>
) <text
key={index}
x={
4 +
Math.max(...players.map((p, _) => p.name.length)) *
(barHeight - 1.5 * gap) *
0.66
} }
y={index * barHeight + barHeight / 2 + padding + gap / 2}
width={(1 - player.rank / maxValue) * width}
height={barHeight - 8} // subtract 2 for some spacing between bars
fontSize={`${0.75 * (barHeight - 1.5 * gap)}px`}
fill="aliceblue"
stroke="#36c"
fontWeight={"bold"}
strokeWidth={4}
paintOrder={"stroke fill"}
>
{`${player.rank} ± ${player.std}`}
</text>
</g>
))}
</svg>
);
};
export default RaceChart; export default RaceChart;