feat: add value ± standard deviation to RaceChart
This commit is contained in:
parent
a52dae5605
commit
de79970987
@ -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;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user