textual data for forecast

Also stick to exact xMax, so we match the old graphs.
This commit is contained in:
Damien Elmes 2020-08-04 15:15:57 +10:00
parent 1b62b932fe
commit c9f9ae532e
2 changed files with 48 additions and 19 deletions

View File

@ -1,17 +1,19 @@
<script lang="typescript"> <script lang="typescript">
import { I18n } from "../i18n"; import { I18n } from "../i18n";
import { HistogramData } from "./histogram-graph"; import { HistogramData } from "./histogram-graph";
import { GraphRange, RevlogRange } from "./graphs"; import { GraphRange, RevlogRange, TableDatum } from "./graphs";
import { gatherData, GraphData, buildHistogram } from "./future-due"; import { gatherData, GraphData, buildHistogram } from "./future-due";
import pb from "../backend/proto"; import pb from "../backend/proto";
import HistogramGraph from "./HistogramGraph.svelte"; import HistogramGraph from "./HistogramGraph.svelte";
import GraphRangeRadios from "./GraphRangeRadios.svelte"; import GraphRangeRadios from "./GraphRangeRadios.svelte";
import TableData from "./TableData.svelte";
export let sourceData: pb.BackendProto.GraphsOut | null = null; export let sourceData: pb.BackendProto.GraphsOut | null = null;
export let i18n: I18n; export let i18n: I18n;
let graphData = null as GraphData | null; let graphData = null as GraphData | null;
let histogramData = null as HistogramData | null; let histogramData = null as HistogramData | null;
let tableData: TableDatum[] = [] as any;
let backlog: boolean = true; let backlog: boolean = true;
let graphRange: GraphRange = GraphRange.Month; let graphRange: GraphRange = GraphRange.Month;
@ -20,7 +22,12 @@
} }
$: if (graphData) { $: if (graphData) {
histogramData = buildHistogram(graphData, graphRange, backlog, i18n); [histogramData, tableData] = buildHistogram(
graphData,
graphRange,
backlog,
i18n
);
} }
const title = i18n.tr(i18n.TR.STATISTICS_FUTURE_DUE_TITLE); const title = i18n.tr(i18n.TR.STATISTICS_FUTURE_DUE_TITLE);
@ -44,4 +51,5 @@
<HistogramGraph data={histogramData} {i18n} /> <HistogramGraph data={histogramData} {i18n} />
<TableData {i18n} {tableData} />
</div> </div>

View File

@ -14,7 +14,7 @@ import { HistogramData } from "./histogram-graph";
import { interpolateGreens } from "d3-scale-chromatic"; import { interpolateGreens } from "d3-scale-chromatic";
import { dayLabel } from "../time"; import { dayLabel } from "../time";
import { I18n } from "../i18n"; import { I18n } from "../i18n";
import { GraphRange } from "./graphs"; import { GraphRange, TableDatum } from "./graphs";
export interface GraphData { export interface GraphData {
dueCounts: Map<number, number>; dueCounts: Map<number, number>;
@ -60,11 +60,11 @@ export function buildHistogram(
range: GraphRange, range: GraphRange,
backlog: boolean, backlog: boolean,
i18n: I18n i18n: I18n
): HistogramData | null { ): [HistogramData | null, TableDatum[]] {
// get min/max // get min/max
const data = sourceData.dueCounts; const data = sourceData.dueCounts;
if (!data) { if (!data) {
return null; return [null, []];
} }
const [xMinOrig, origXMax] = extent<number>(data.keys()); const [xMinOrig, origXMax] = extent<number>(data.keys());
@ -88,12 +88,10 @@ export function buildHistogram(
case GraphRange.AllTime: case GraphRange.AllTime:
break; break;
} }
xMax = xMax! + 1;
// cap bars to available range // cap bars to available range
const desiredBars = Math.min(70, xMax! - xMin!); const desiredBars = Math.min(70, xMax! - xMin!);
const x = scaleLinear().domain([xMin!, xMax!]).nice(); const x = scaleLinear().domain([xMin!, xMax!]);
const bins = histogram() const bins = histogram()
.value((m) => { .value((m) => {
return m[0]; return m[0];
@ -103,13 +101,13 @@ export function buildHistogram(
// empty graph? // empty graph?
if (!sum(bins, (bin) => bin.length)) { if (!sum(bins, (bin) => bin.length)) {
return null; return [null, []];
} }
const adjustedRange = scaleLinear().range([0.8, 0.3]); const adjustedRange = scaleLinear().range([0.8, 0.3]);
const colourScale = scaleSequential((n) => const colourScale = scaleSequential((n) =>
interpolateGreens(adjustedRange(n)) interpolateGreens(adjustedRange(n))
).domain([xMin!, xMax]); ).domain([xMin!, xMax!]);
const total = sum(bins as any, binValue); const total = sum(bins as any, binValue);
@ -129,13 +127,36 @@ export function buildHistogram(
return `${days}:<br>${cards}<br>${totalLabel}: ${cumulative}`; return `${days}:<br>${cards}<br>${totalLabel}: ${cumulative}`;
} }
return { const periodDays = xMax! - xMin!;
scale: x, const tableData = [
bins, {
total, label: i18n.tr(i18n.TR.STATISTICS_TOTAL),
hoverText, value: i18n.tr(i18n.TR.STATISTICS_REVIEWS, { reviews: total }),
showArea: true, },
colourScale, {
binValue, label: i18n.tr(i18n.TR.STATISTICS_AVERAGE),
}; value: i18n.tr(i18n.TR.STATISTICS_REVIEWS_PER_DAY, {
count: Math.round(total / periodDays),
}),
},
{
label: i18n.tr(i18n.TR.STATISTICS_DUE_TOMORROW),
value: i18n.tr(i18n.TR.STATISTICS_REVIEWS, {
reviews: sourceData.dueCounts.get(1) ?? 0,
}),
},
];
return [
{
scale: x,
bins,
total,
hoverText,
showArea: true,
colourScale,
binValue,
},
tableData,
];
} }