diff --git a/ts/src/stats/AddedGraph.svelte b/ts/src/stats/AddedGraph.svelte
index 9b8b222c3..2b061ce26 100644
--- a/ts/src/stats/AddedGraph.svelte
+++ b/ts/src/stats/AddedGraph.svelte
@@ -1,6 +1,6 @@
diff --git a/ts/src/stats/FutureDue.svelte b/ts/src/stats/FutureDue.svelte
new file mode 100644
index 000000000..aa3744475
--- /dev/null
+++ b/ts/src/stats/FutureDue.svelte
@@ -0,0 +1,62 @@
+
+
+{#if histogramData}
+
+
+{/if}
diff --git a/ts/src/stats/GraphsPage.svelte b/ts/src/stats/GraphsPage.svelte
index e935fe545..ed6379bda 100644
--- a/ts/src/stats/GraphsPage.svelte
+++ b/ts/src/stats/GraphsPage.svelte
@@ -15,6 +15,7 @@
import ButtonsGraph from "./ButtonsGraph.svelte";
import CardCounts from "./CardCounts.svelte";
import HourGraph from "./HourGraph.svelte";
+ import FutureDue from "./FutureDue.svelte";
let sourceData: pb.BackendProto.GraphsOut | null = null;
@@ -121,10 +122,11 @@
+
-
+
diff --git a/ts/src/stats/IntervalsGraph.svelte b/ts/src/stats/IntervalsGraph.svelte
index e6ef075d2..40b39893c 100644
--- a/ts/src/stats/IntervalsGraph.svelte
+++ b/ts/src/stats/IntervalsGraph.svelte
@@ -11,11 +11,12 @@
export let sourceData: pb.BackendProto.GraphsOut | null = null;
- let svg = null as HTMLElement | SVGElement | null;
- let range = IntervalRange.Percentile95;
+ let intervalData: IntervalGraphData | null = null;
let histogramData = null as HistogramData | null;
- let intervalData: IntervalGraphData | null = null;
+ let svg = null as HTMLElement | SVGElement | null;
+ let range = IntervalRange.Percentile95;
+
$: if (sourceData) {
console.log("gathering data");
intervalData = gatherIntervalData(sourceData);
diff --git a/ts/src/stats/added.ts b/ts/src/stats/added.ts
index 2dc2e54cb..111b56b65 100644
--- a/ts/src/stats/added.ts
+++ b/ts/src/stats/added.ts
@@ -44,7 +44,10 @@ function hoverText(
);
}
-export function prepareData(data: GraphData, range: AddedRange): HistogramData | null {
+export function buildHistogram(
+ data: GraphData,
+ range: AddedRange
+): HistogramData | null {
// get min/max
const total = data.daysAdded.length;
if (!total) {
diff --git a/ts/src/stats/future-due.ts b/ts/src/stats/future-due.ts
new file mode 100644
index 000000000..0ea76177f
--- /dev/null
+++ b/ts/src/stats/future-due.ts
@@ -0,0 +1,114 @@
+// Copyright: Ankitects Pty Ltd and contributors
+// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
+
+/* eslint
+@typescript-eslint/no-non-null-assertion: "off",
+@typescript-eslint/no-explicit-any: "off",
+ */
+
+import pb from "../backend/proto";
+import { extent, histogram, rollup, max, sum, Bin } from "d3-array";
+import { scaleLinear, scaleSequential } from "d3-scale";
+import { CardQueue } from "../cards";
+import { HistogramData } from "./histogram-graph";
+import { interpolateGreens } from "d3-scale-chromatic";
+
+export interface GraphData {
+ dueCounts: Map;
+}
+
+export enum FutureDueRange {
+ Month = 0,
+ Quarter = 1,
+ Year = 2,
+ AllTime = 3,
+}
+
+export function gatherData(data: pb.BackendProto.GraphsOut): GraphData {
+ const due = (data.cards as pb.BackendProto.Card[])
+ .filter((c) => c.queue == CardQueue.Review) // && c.due >= data.daysElapsed)
+ .map((c) => c.due - data.daysElapsed);
+ const dueCounts = rollup(
+ due,
+ (v) => v.length,
+ (d) => d
+ );
+ return { dueCounts };
+}
+
+function binValue(d: Bin