mirror of
https://github.com/ankitects/anki.git
synced 2025-09-25 17:26:36 -04:00
Add zoomed version of graph
This commit is contained in:
parent
000cffc6d6
commit
17d8528afd
2 changed files with 119 additions and 41 deletions
|
@ -13,9 +13,13 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
import TableData from "../graphs/TableData.svelte";
|
import TableData from "../graphs/TableData.svelte";
|
||||||
import InputBox from "../graphs/InputBox.svelte";
|
import InputBox from "../graphs/InputBox.svelte";
|
||||||
import { defaultGraphBounds, type TableDatum } from "../graphs/graph-helpers";
|
import { defaultGraphBounds, type TableDatum } from "../graphs/graph-helpers";
|
||||||
import { SimulateSubgraph, type Point } from "../graphs/simulator";
|
import {
|
||||||
|
SimulateSubgraph,
|
||||||
|
SimulateWorkloadSubgraph,
|
||||||
|
type Point,
|
||||||
|
} from "../graphs/simulator";
|
||||||
import * as tr from "@generated/ftl";
|
import * as tr from "@generated/ftl";
|
||||||
import { renderSimulationChart } from "../graphs/simulator";
|
import { renderSimulationChart, renderWorkloadChart } from "../graphs/simulator";
|
||||||
import {
|
import {
|
||||||
computeOptimalRetention,
|
computeOptimalRetention,
|
||||||
simulateFsrsReview,
|
simulateFsrsReview,
|
||||||
|
@ -48,6 +52,9 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
|
|
||||||
const config = state.currentConfig;
|
const config = state.currentConfig;
|
||||||
let simulateSubgraph: SimulateSubgraph = SimulateSubgraph.count;
|
let simulateSubgraph: SimulateSubgraph = SimulateSubgraph.count;
|
||||||
|
let simulateWorkloadSubgraph: SimulateWorkloadSubgraph =
|
||||||
|
SimulateWorkloadSubgraph.ratio;
|
||||||
|
let workload: boolean = false;
|
||||||
let tableData: TableDatum[] = [];
|
let tableData: TableDatum[] = [];
|
||||||
let simulating: boolean = false;
|
let simulating: boolean = false;
|
||||||
const fsrs = state.fsrs;
|
const fsrs = state.fsrs;
|
||||||
|
@ -196,23 +203,20 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
} finally {
|
} finally {
|
||||||
simulating = false;
|
simulating = false;
|
||||||
if (resp) {
|
if (resp) {
|
||||||
simulationNumber += 1;
|
points = Object.entries(resp.memorized).map(([dr, v]) => ({
|
||||||
|
x: parseInt(dr),
|
||||||
|
timeCost: resp!.cost[dr],
|
||||||
|
memorized: v,
|
||||||
|
count: -1,
|
||||||
|
label: 1,
|
||||||
|
}));
|
||||||
|
|
||||||
points = points.concat(
|
workload = true;
|
||||||
Object.entries(resp.memorized).map(([dr, v]) => ({
|
tableData = renderWorkloadChart(
|
||||||
x: parseInt(dr),
|
|
||||||
timeCost: resp!.cost[dr],
|
|
||||||
count: resp!.cost[dr] / v,
|
|
||||||
memorized: v,
|
|
||||||
label: simulationNumber,
|
|
||||||
})),
|
|
||||||
);
|
|
||||||
|
|
||||||
tableData = renderSimulationChart(
|
|
||||||
svg as SVGElement,
|
svg as SVGElement,
|
||||||
bounds,
|
bounds,
|
||||||
points,
|
points,
|
||||||
simulateSubgraph,
|
simulateWorkloadSubgraph,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -266,11 +270,15 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
tableData = renderSimulationChart(
|
const render_function = workload
|
||||||
|
? renderWorkloadChart
|
||||||
|
: renderSimulationChart;
|
||||||
|
|
||||||
|
tableData = render_function(
|
||||||
svg as SVGElement,
|
svg as SVGElement,
|
||||||
bounds,
|
bounds,
|
||||||
pointsToRender,
|
pointsToRender,
|
||||||
simulateSubgraph,
|
(workload ? simulateWorkloadSubgraph : simulateSubgraph) as any as never,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -519,30 +527,57 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
<Graph>
|
<Graph>
|
||||||
<div class="radio-group">
|
<div class="radio-group">
|
||||||
<InputBox>
|
<InputBox>
|
||||||
<label>
|
{#if !workload}
|
||||||
<input
|
<label>
|
||||||
type="radio"
|
<input
|
||||||
value={SimulateSubgraph.count}
|
type="radio"
|
||||||
bind:group={simulateSubgraph}
|
value={SimulateSubgraph.count}
|
||||||
/>
|
bind:group={simulateSubgraph}
|
||||||
{tr.deckConfigFsrsSimulatorRadioCount()}
|
/>
|
||||||
</label>
|
{tr.deckConfigFsrsSimulatorRadioCount()}
|
||||||
<label>
|
</label>
|
||||||
<input
|
<label>
|
||||||
type="radio"
|
<input
|
||||||
value={SimulateSubgraph.time}
|
type="radio"
|
||||||
bind:group={simulateSubgraph}
|
value={SimulateSubgraph.time}
|
||||||
/>
|
bind:group={simulateSubgraph}
|
||||||
{tr.statisticsReviewsTimeCheckbox()}
|
/>
|
||||||
</label>
|
{tr.statisticsReviewsTimeCheckbox()}
|
||||||
<label>
|
</label>
|
||||||
<input
|
<label>
|
||||||
type="radio"
|
<input
|
||||||
value={SimulateSubgraph.memorized}
|
type="radio"
|
||||||
bind:group={simulateSubgraph}
|
value={SimulateSubgraph.memorized}
|
||||||
/>
|
bind:group={simulateSubgraph}
|
||||||
{tr.deckConfigFsrsSimulatorRadioMemorized()}
|
/>
|
||||||
</label>
|
{tr.deckConfigFsrsSimulatorRadioMemorized()}
|
||||||
|
</label>
|
||||||
|
{:else}
|
||||||
|
<label>
|
||||||
|
<input
|
||||||
|
type="radio"
|
||||||
|
value={SimulateWorkloadSubgraph.ratio}
|
||||||
|
bind:group={simulateWorkloadSubgraph}
|
||||||
|
/>
|
||||||
|
{"Ratio"}
|
||||||
|
</label>
|
||||||
|
<label>
|
||||||
|
<input
|
||||||
|
type="radio"
|
||||||
|
value={SimulateWorkloadSubgraph.memorized}
|
||||||
|
bind:group={simulateWorkloadSubgraph}
|
||||||
|
/>
|
||||||
|
{tr.deckConfigFsrsSimulatorRadioMemorized()}
|
||||||
|
</label>
|
||||||
|
<label>
|
||||||
|
<input
|
||||||
|
type="radio"
|
||||||
|
value={SimulateWorkloadSubgraph.time}
|
||||||
|
bind:group={simulateWorkloadSubgraph}
|
||||||
|
/>
|
||||||
|
{tr.statisticsReviewsTimeCheckbox()}
|
||||||
|
</label>
|
||||||
|
{/if}
|
||||||
</InputBox>
|
</InputBox>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
@ -43,6 +43,49 @@ export enum SimulateWorkloadSubgraph {
|
||||||
memorized,
|
memorized,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function renderWorkloadChart(
|
||||||
|
svgElem: SVGElement,
|
||||||
|
bounds: GraphBounds,
|
||||||
|
data: Point[],
|
||||||
|
subgraph: SimulateWorkloadSubgraph,
|
||||||
|
) {
|
||||||
|
const today = new Date();
|
||||||
|
|
||||||
|
const xMin = 70;
|
||||||
|
const xMax = 99;
|
||||||
|
|
||||||
|
const x = scaleLinear()
|
||||||
|
.domain([xMin, xMax])
|
||||||
|
.range([bounds.marginLeft, bounds.width - bounds.marginRight]);
|
||||||
|
|
||||||
|
const subgraph_data = ({
|
||||||
|
[SimulateWorkloadSubgraph.ratio]: data.map(d => ({ ...d, y: d.timeCost / d.memorized })),
|
||||||
|
[SimulateWorkloadSubgraph.time]: data.map(d => ({ ...d, y: d.timeCost })),
|
||||||
|
[SimulateWorkloadSubgraph.memorized]: data.map(d => ({ ...d, y: d.memorized })),
|
||||||
|
})[subgraph];
|
||||||
|
|
||||||
|
const yTickFormat = (n: number): string => {
|
||||||
|
return subgraph == SimulateWorkloadSubgraph.time ? timeSpan(n, true) : n.toString();
|
||||||
|
};
|
||||||
|
|
||||||
|
const formatY: (value: number) => string = ({
|
||||||
|
[SimulateWorkloadSubgraph.ratio]: (value: number) => `${timeSpan(value)} time per 1 card memorized`,
|
||||||
|
[SimulateWorkloadSubgraph.time]: timeSpan,
|
||||||
|
[SimulateWorkloadSubgraph.memorized]: (value: number) =>
|
||||||
|
tr.statisticsMemorized({ memorized: Math.round(value).toFixed(0) }),
|
||||||
|
})[subgraph];
|
||||||
|
|
||||||
|
return _renderSimulationChart(
|
||||||
|
svgElem,
|
||||||
|
bounds,
|
||||||
|
subgraph_data,
|
||||||
|
x,
|
||||||
|
yTickFormat,
|
||||||
|
formatY,
|
||||||
|
(_e: MouseEvent, _d: number) => undefined,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
export function renderSimulationChart(
|
export function renderSimulationChart(
|
||||||
svgElem: SVGElement,
|
svgElem: SVGElement,
|
||||||
bounds: GraphBounds,
|
bounds: GraphBounds,
|
||||||
|
|
Loading…
Reference in a new issue