Skip to content

Commit

Permalink
feat: adjust axis formatting based on selected scale [fixes #22]
Browse files Browse the repository at this point in the history
todo: same but for tooltips
  • Loading branch information
gregdan3 committed Aug 28, 2024
1 parent 34bb251 commit b4d7c42
Show file tree
Hide file tree
Showing 5 changed files with 92 additions and 8 deletions.
4 changes: 2 additions & 2 deletions src/pages/index.astro
Original file line number Diff line number Diff line change
Expand Up @@ -209,9 +209,9 @@ const frontmatter = { title: "ilo Muni" };
});
}

const axis = SCALES[scale].axis;
const scaleData = SCALES[scale];

await reloadUsageChart(usageCanvas, results, axis);
await reloadUsageChart(usageCanvas, results, scaleData);
return { queries, errors };
}

Expand Down
18 changes: 12 additions & 6 deletions src/utils/chart.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { htmlLegendPlugin, crossHairPlugin } from "@utils/plugins";
import type { Axis } from "@utils/types";
import { FORMATTERS } from "@utils/ui.ts";
import type { ScaleData } from "@utils/types";
import type { Result, Row } from "@utils/sqlite";
import type { ChartTypeRegistry, TooltipItem } from "chart.js/auto";
import Chart from "chart.js/auto";
Expand All @@ -22,7 +23,7 @@ function roundForGraph(num: number): number {
async function initUsageChart(
canvas: HTMLCanvasElement,
data: Result[],
axis: Axis,
scale: ScaleData,
) {
const chart = new Chart(canvas, {
type: "line",
Expand Down Expand Up @@ -83,7 +84,7 @@ async function initUsageChart(
// },
},
y: {
type: axis,
type: scale.axis,
axis: "y",
suggestedMin: 0,
grid: {
Expand All @@ -95,6 +96,9 @@ async function initUsageChart(
border: {
display: false,
},
ticks: {
callback: FORMATTERS[scale.axisNums],
},
},
},
elements: {
Expand Down Expand Up @@ -163,16 +167,18 @@ async function initUsageChart(
export async function reloadUsageChart(
canvas: HTMLCanvasElement,
data: Result[],
axis: Axis,
scale: ScaleData,
) {
if (!existingChart) {
existingChart = await initUsageChart(canvas, data, axis);
existingChart = await initUsageChart(canvas, data, scale);
} else {
existingChart.data.datasets = data.map((result: Result) => ({
label: result.term,
data: result.data,
}));
existingChart.options.scales!.y!.type = axis;
existingChart.options.scales!.y!.type = scale.axis;
existingChart.options.scales!.y!.ticks!.callback =
FORMATTERS[scale.axisNums];
existingChart.update();
}
}
34 changes: 34 additions & 0 deletions src/utils/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -112,94 +112,128 @@ export const SCALES = {
category: "simple",
smoothable: false,
axis: "linear",
axisNums: "int", // truncated by thousands
tooltipNums: "raw",
},
rel: {
label: "Relative",
category: "simple",
smoothable: true,
axis: "linear",
axisNums: "percent", // truncated to 2 significant digits
tooltipNums: "rawPercent", // truncated to 5 significant digits
},
cmsum: {
label: "Cumulative",
category: "simple",
smoothable: false,
axis: "linear",
axisNums: "int",
tooltipNums: "raw",
},
logabs: {
label: "Absolute Log",
category: "useful",
smoothable: false,
axis: "logarithmic",
axisNums: "int",
tooltipNums: "raw",
},
logrel: {
label: "Relative Log",
category: "useful",
smoothable: true,
axis: "logarithmic",
axisNums: "percent",
tooltipNums: "rawPercent",
},
logcm: {
label: "Cumulative Log",
category: "useful",
smoothable: false,
axis: "logarithmic",
axisNums: "int",
tooltipNums: "raw",
},
normabs: {
label: "Absolute Minmax",
category: "useful",
smoothable: false,
axis: "linear",
axisNums: "raw",
tooltipNums: "raw",
},
normrel: {
label: "Relative Minmax",
category: "useful",
smoothable: true,
axis: "linear",
axisNums: "raw",
tooltipNums: "raw",
},
normcm: {
label: "Cumulative Minmax",
category: "useful",
smoothable: false,
axis: "linear",
axisNums: "raw",
tooltipNums: "raw",
},
entropy: {
label: "Absolute Entropy",
category: "weird",
smoothable: true,
axis: "linear",
axisNums: "raw",
tooltipNums: "raw",
},
relentropy: {
label: "Relative Entropy",
category: "weird",
smoothable: true,
axis: "linear",
axisNums: "raw",
tooltipNums: "raw",
},
deriv1: {
label: "Absolute 1st Deriv",
category: "weird",
smoothable: false,
axis: "linear",
axisNums: "int",
tooltipNums: "raw",
},
// deriv2: {
// label: "2nd Deriv Absolute",
// category: "weird",
// smoothable: false,
// axis: "linear",
// axisNums: "int",
// tooltipNums: "raw",
// },
relderiv1: {
label: "Relative 1st Deriv",
category: "weird",
smoothable: false,
axis: "linear",
axisNums: "percent",
tooltipNums: "rawPercent",
},
// relderiv2: {
// label: "2nd Deriv Relative",
// category: "weird",
// smoothable: false,
// axis: "linear",
// axisNums: "percent",
// tooltipNums: "rawPercent",
// },
zscore: {
label: "Relative Z-Score",
category: "weird",
smoothable: true,
axis: "linear",
axisNums: "raw",
tooltipNums: "raw",
},
} as const;

Expand Down
4 changes: 4 additions & 0 deletions src/utils/types.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,18 @@
// URL params
import { SCALES, SMOOTHERS, LENGTHS, SMOOTHINGS } from "@utils/constants";

import { FORMATTERS } from "@utils/ui.ts";

export const lengths = LENGTHS.map((n: string): number => {
return parseInt(n, 10);
});
export const smoothings = SMOOTHINGS.map((n: string): number => {
return parseInt(n, 10);
});

export type Formatter = keyof typeof FORMATTERS;
export type Scale = keyof typeof SCALES;
export type ScaleData = (typeof SCALES)[Scale];
export type LengthParam = (typeof LENGTHS)[number];
export type Smoother = keyof typeof SMOOTHERS;
export type SmoothingParam = (typeof SMOOTHINGS)[number];
Expand Down
40 changes: 40 additions & 0 deletions src/utils/ui.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,43 @@ export async function copyUrlToClipboard() {
}
}
}

export function formatInteger(n: number): string {
const suffixes = ["", "K", "M", "B", "T"];
const tier = (Math.log10(Math.abs(n)) / 3) | 0;

if (tier <= 0) return n.toString();

const suffix = suffixes[tier];
const scale = Math.pow(10, tier * 3);
const scaled = n / scale;

return scaled.toFixed(1).replace(/\.0$/, "") + suffix;
}

export function formatRaw(n: number): string {
return n.toString();
}

export function formatPercentage(n: number, sigDigits: number = 2): string {
if (n === 0) return "0%";

n *= 100;

const absValue = Math.abs(n);
const magnitude = Math.floor(Math.log10(absValue));
const scale = Math.pow(10, magnitude - sigDigits + 1);

const rounded = Math.round(n / scale) * scale;

const formatted = rounded.toPrecision(sigDigits);

return parseFloat(formatted).toString() + "%";
}

export const FORMATTERS = {
raw: formatRaw,
percent: (n: number) => formatPercentage(n, 2),
rawPercent: (n: number) => formatPercentage(n, 5),
int: formatInteger,
} as const;

0 comments on commit b4d7c42

Please sign in to comment.