import React from "react";
import {
VictoryAxis,
VictoryChart,
VictoryGroup,
VictoryLabel,
VictoryLegend,
VictoryScatter,
VictoryLine,
VictoryTheme,
VictoryTooltip,
VictoryVoronoiContainer,
} from "victory";
import { QuestionWithHistoryFragment } from "../../fragments.generated";
interface Props {
question: QuestionWithHistoryFragment;
}
const buildDataset = (n, fn) => {
return Array.from(Array(n).keys()).map((x) => ({
date: x,
probability: fn(x),
}));
};
let getDate0 = (x) => {
// for fake data
let date = new Date(x);
return date.toISOString().slice(5, 10).replaceAll("-", "/");
};
let formatOptionName = (name) => {
return name.length > 10 ? name.slice(0, 8) + "..." : name;
};
let getLength = (str) => {
let capitalLetterLengthMultiplier = 1.25;
let smallLetterMultiplier = 0.8;
let numUpper = (str.match(/[A-Z]/g) || []).length;
let numSmallLetters = (str.match(/[fijlrt]/g) || []).length;
let numSpaces = (str.match(/[\s]/g) || []).length;
let length =
str.length +
-numUpper -
numSmallLetters +
numUpper * capitalLetterLengthMultiplier +
(numSmallLetters + numSpaces) * smallLetterMultiplier;
return length;
};
let timestampToString = (x) => {
// for real timestamps
console.log(x);
let date = new Date(Date.parse(x));
let dayOfMonth = date.getDate();
let month = date.getMonth() + 1;
let year = date.getFullYear();
let dateString = `${("0" + dayOfMonth).slice(-2)}/${("0" + month).slice(
-2
)}/${year.toString().slice(-2)}`;
console.log(dateString);
return dateString;
};
let dataAsXy = (data) =>
data.map((datum) => ({
x: timestampToString(datum.date), //getDate(datum.date * (1000 * 60 * 60 * 24)),
y: datum.probability,
name: datum.name,
}));
const colors = ["dodgerblue", "crimson", "seagreen", "darkviolet", "turquoise"];
const getVictoryGroup = (data, i) => {
return (
(active ? 3.75 : 3)}
//labels={() => null}
//labelComponent={}
/>
null}
//labelComponent={}
/>
);
};
export const HistoryChart: React.FC = ({ question }) => {
let dataSetsNames = [];
question.history.forEach((item) => {
let optionNames = item.options.map((option) => option.name);
dataSetsNames.push(...optionNames);
});
dataSetsNames = [...new Set(dataSetsNames)].slice(0, 5); // take the first 5
let dataSets = [];
let maxProbability = 0;
let longestNameLength = 0;
for (let name of dataSetsNames) {
let newDataset = [];
let previousDate = -Infinity;
for (let item of question.history) {
let relevantItemsArray = item.options.filter((x) => x.name == name);
let date = new Date(item.timestamp * 1000);
if (
relevantItemsArray.length == 1 &&
item.timestamp - previousDate > 12 * 60 * 60
) {
let relevantItem = relevantItemsArray[0];
// if (relevantItem.type == "PROBABILITY") {
let result = {
date,
probability: relevantItem.probability,
name: relevantItem.name,
};
maxProbability =
relevantItem.probability > maxProbability
? relevantItem.probability
: maxProbability;
let length = getLength(relevantItem.name);
longestNameLength =
length > longestNameLength ? length : longestNameLength;
newDataset.push(result);
// }
previousDate = item.timestamp;
}
}
dataSets.push(newDataset);
}
let letterLength = 7;
let labelLegendStart = 45;
let domainMax =
maxProbability < 0.5 ? Math.round(10 * (maxProbability + 0.05)) / 10 : 1;
let dataSetsLength = dataSets.length;
let goldenRatio = (1 + Math.sqrt(5)) / 2;
let width = 750;
let height = width / goldenRatio;
let padding = {
top: 20,
bottom: 50,
left: 0,
right: labelLegendStart + letterLength * longestNameLength,
};
return (
`Not shown`}
labelComponent={
`${datum.name}: ${Math.round(datum.y * 100)}%`
}
style={{
fontSize: 15,
fill: "black",
strokeWidth: 0.05,
}}
flyoutStyle={{
stroke: "black",
fill: "white",
}}
cornerRadius={0}
flyoutPadding={7}
/>
}
voronoiBlacklist={
["line-0", "line-1", "line-2", "line-3", "line-4"]
//Array.from(Array(5).keys()).map((x, i) => `line${i}`)
// see: https://github.com/FormidableLabs/victory/issues/545
}
/>
}
domain={{
y: [0, domainMax],
}}
>
({
name: dataSetsNames[i],
symbol: { fill: colors[i] },
}))}
/>
{dataSets
.slice(0, 5)
.map((dataset, i) => getVictoryGroup(dataset, i))}
datum.x)}
// tickFormat={dataAsXy.map((datum) => datum.x)}
tickCount={7}
style={{
grid: { stroke: null, strokeWidth: 0.5 },
}}
//axisLabelComponent={
//
//}
// label="Date (dd/mm/yy)"
tickLabelComponent={
}
/>
`${x * 100}%`}
style={{
grid: { stroke: "#D3D3D3", strokeWidth: 0.5 },
}}
tickLabelComponent={
}
/>
);
};