Improve benchmark case details and score chart scaling (#146)

Co-authored-by: Yaowei Zheng <hiyouga@buaa.edu.cn>
This commit is contained in:
Jingzhe XuandYaowei Zheng authored and GitHub committed 2026-07-31 20:42:32 +08:00
1 parent 5308002d72
commit 740f101242
19 files changed
+519 -212

No files matched your search

+44 -14
View File
@@ -1,12 +1,12 @@
/**
* Unit tests for the Evaluation center's Score-only chart helpers: Score extraction,
* gap segmentation across runtime series, y-axis max, and runtime grouping.
* dynamic y-axis range, gap segmentation across runtime series, and runtime grouping.
*/
import { describe, expect, it } from "vitest";
import {
lineSegments,
metricMax,
modelSeries,
scoreScale,
scoreValues,
seriesValues,
} from "../src/features/benchmark/benchmark-metrics";
@@ -14,12 +14,53 @@ import {
const evaluations = [{ score: 60 }, { score: 75.25 }, { score: 85.5 }];
describe("scoreValues", () => {
it("extracts stored Scores and treats non-finite malformed input as a gap", () => {
it("extracts stored Scores and treats non-finite input as a gap", () => {
expect(scoreValues(evaluations)).toEqual([60, 75.25, 85.5]);
expect(scoreValues([{ score: Number.NaN }, { score: Infinity }])).toEqual([null, null]);
});
});
describe("scoreScale (dynamic padded Score axis)", () => {
it("pads observed scores, clamps to 0..100, and rounds outward to friendly ticks", () => {
expect(scoreScale([71, 83.67, 88.33])).toEqual({
min: 60,
max: 100,
ticks: [60, 70, 80, 90, 100],
});
});
it("keeps a dynamic range for a single or repeated score", () => {
expect(scoreScale([88])).toEqual({
min: 75,
max: 100,
ticks: [75, 80, 85, 90, 95, 100],
});
expect(scoreScale([50, 50])).toEqual({
min: 40,
max: 60,
ticks: [40, 45, 50, 55, 60],
});
});
it("clamps boundary scores and falls back safely when every value is missing", () => {
expect(scoreScale([100])).toEqual({
min: 90,
max: 100,
ticks: [90, 92, 94, 96, 98, 100],
});
expect(scoreScale([0])).toEqual({
min: 0,
max: 10,
ticks: [0, 2, 4, 6, 8, 10],
});
expect(scoreScale([null, null])).toEqual({
min: 0,
max: 100,
ticks: [0, 20, 40, 60, 80, 100],
});
});
});
describe("lineSegments (gap segmentation)", () => {
it("no gaps: one segment with everything (consecutive indexes)", () => {
expect(lineSegments([60, 75.25, 85.5])).toEqual([
@@ -51,17 +92,6 @@ describe("lineSegments (gap segmentation)", () => {
});
});
describe("metricMax (y-axis upper bound)", () => {
it("takes the maximum of present points (ignoring null)", () => {
expect(metricMax([0.12, null, 0.2])).toBe(0.2);
});
it("all missing / all zero yields a tiny positive number (no division by zero in the coordinate system)", () => {
expect(metricMax([null, null])).toBe(1e-9);
expect(metricMax([0, 0])).toBe(1e-9);
});
});
describe("modelSeries / seriesValues (curves split by model ID and thinking level)", () => {
const mixed = [
{
+10
View File
@@ -15,6 +15,7 @@
import { describe, expect, it } from "vitest";
import {
makeGeom,
makeRangeGeom,
linePath,
areaPath,
sparseLabelIdx,
@@ -56,6 +57,15 @@ describe("makeGeom", () => {
it("step falls back to the whole inner width when n=0 (no division by zero)", () => {
expect(makeGeom(0, 1, 640).step).toBe(586);
});
it("an explicit non-zero range maps its min to the baseline and max to the top", () => {
const g = makeRangeGeom(2, 60, 100, 640);
expect(g.min).toBe(60);
expect(g.max).toBe(100);
expect(g.y(60)).toBe(178);
expect(g.y(100)).toBe(10);
expect(g.y(80)).toBe(94);
});
});
describe("linePath / areaPath", () => {