metaforecast/src/web/display/HistoryChart.tsx

156 lines
3.8 KiB
TypeScript

import React from "react";
import { FrontendForecast } from "../platforms";
import * as V from "victory";
import { HistoryChartFlyout } from "./HistoryChartFlyout";
import {
VictoryBar,
VictoryLabel,
VictoryTooltip,
VictoryLine,
VictoryScatter,
VictoryChart,
VictoryTheme,
VictoryAxis,
VictoryGroup,
VictoryVoronoiContainer,
} from "victory";
interface Props {
question: FrontendForecast;
history: number[];
}
const data0 = [
{ date: 1, probability: 0.1 },
{ date: 2, probability: 0.2 },
{ date: 3, probability: 0.4 },
{ date: 4, probability: 0.6 },
{ date: 5, probability: 0.6 },
{ date: 6, probability: 0.65 },
{ date: 7, probability: 0.65 },
{ date: 8, probability: 0.65 },
{ date: 9, probability: 0.7 },
];
let l = 5;
const data = Array.from(Array(l).keys()).map((x) => ({
date: x,
probability: x / l,
}));
let getDate = (x) => {
let date = new Date(x);
return date.toISOString().slice(5, 10).replaceAll("-", "/");
};
let dataAsXy = data.map((datum) => ({
x: getDate(datum.date * (1000 * 60 * 60 * 24)),
y: datum.probability,
}));
export const HistoryChart: React.FC<Props> = ({ question, history }) => {
return (
<VictoryChart
domainPadding={20}
theme={VictoryTheme.material}
height={300}
containerComponent={<VictoryVoronoiContainer />}
domain={{
y: [0, 1],
}}
>
<VictoryGroup
color="darkblue"
data={dataAsXy}
labels={({ datum }) => `${datum.x}: ${Math.round(datum.y * 100)}%`}
labelComponent={
<VictoryTooltip
pointerLength={0}
dy={-12}
style={{
fontSize: 9,
fill: "black",
strokeWidth: 0.05,
}}
flyoutStyle={{
stroke: "black",
fill: "white",
}}
flyoutWidth={60}
cornerRadius={0}
flyoutPadding={7}
/>
}
>
<VictoryLine />
<VictoryScatter size={({ active }) => (active ? 3.75 : 3)} />
</VictoryGroup>
<VictoryAxis
// tickValues specifies both the number of ticks and where
// they are placed on the axis
tickValues={data.map((datum) => datum.date)}
tickCount={10}
tickFormat={dataAsXy.map((datum) => datum.x)}
style={{
grid: { stroke: null, strokeWidth: 0.5 },
}}
tickLabelComponent={
<VictoryLabel
dy={0}
angle={-30}
style={{ fontSize: 7, fill: "gray" }}
/>
}
/>
<VictoryAxis
dependentAxis
// tickFormat specifies how ticks should be displayed
tickFormat={(x) => `${x * 100}%`}
style={{
grid: { stroke: "#D3D3D3", strokeWidth: 0.5 },
}}
/>
</VictoryChart>
);
};
/*
<VictoryChart
// domainPadding will add space to each side of VictoryBar to
// prevent it from overlapping the axis
domainPadding={20}
theme={VictoryTheme.material}
height={300}
title={"Blah"}
containerComponent={<VictoryVoronoiContainer />}
>
<VictoryGroup
data={data.map((datum) => ({ x: datum.date, y: datum.probability }))}
labels={data.map((datum) => `1%`)}
style={{ labels: { fill: "black", fontSize: 10 } }}
labelComponent={
<VictoryTooltip style={{ fontSize: 10, fill: "black" }} dy={-15} />
}
>
<VictoryLine
height={300}
width={300}
style={{
data: { stroke: "#000080" },
parent: { border: "1px solid #ccc" },
}}
domain={{
y: [0, 1],
}}
></VictoryLine>
<VictoryScatter
style={{
data: { fill: "#000080" },
}}
size={3}
/>
</VictoryGroup>
</VictoryChart>
*/