@tangle-network/charts 0.1.3 → 0.1.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.js +29 -11
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -18,9 +18,13 @@ A figure function returns a `Refusal` in place of a figure it cannot draw honest
|
|
|
18
18
|
The producer's `estimate` controls rate marks: `descriptive` draws a rate bar and may show a named Wilson score interval when that estimate meets the producer's unit threshold.
|
|
19
19
|
Task-clustered bootstrap intervals require a `bootstrap` estimate.
|
|
20
20
|
Intervals without support are marked as not drawn in the data table and note.
|
|
21
|
-
|
|
21
|
+
Cost-per-pass figures print `unknown` for missing, zero, or unproven cost; zero passes print `no pass`.
|
|
22
|
+
A matrix preserves an observed zero cost as $0 and omits a null cost.
|
|
22
23
|
Rank numbers require every row to carry both a rank and a `bootstrap` estimate.
|
|
24
|
+
For an unranked descriptive report, `rankedRates` accepts `order: "input"` to retain the producer's row order and make no ranking claim.
|
|
25
|
+
The default keeps supported ranks or sorts unranked rows by observed rate.
|
|
23
26
|
Malformed rates, intervals, matrix counts, and breakdown counts return a refusal instead of a misleading mark.
|
|
27
|
+
Unmeasured and flagged matrix attempts keep distinct marks and table counts, even without tier grades.
|
|
24
28
|
An interval whisker is omitted when its bounds exclude the row's rate.
|
|
25
29
|
|
|
26
30
|
It has no runtime dependencies and uses no DOM, so it runs in a Worker, a build step or a browser.
|
package/dist/index.d.ts
CHANGED
|
@@ -180,6 +180,8 @@ export declare function rateOrder<T extends Pick<RateRow, "rank" | "rate" | "est
|
|
|
180
180
|
interface RankedRatesOptions {
|
|
181
181
|
/** What the rate measures, lower case: "solve rate". */
|
|
182
182
|
measure: string;
|
|
183
|
+
/** Preserve unranked input order instead of sorting observed rates. */
|
|
184
|
+
order?: "input";
|
|
183
185
|
/** The App Grade tier a pass needs; marks the tier strip. */
|
|
184
186
|
passTier?: Tier;
|
|
185
187
|
/** Singular, lower-case nouns: what one unit of `attempts` is, and what a row is. */
|
package/dist/index.js
CHANGED
|
@@ -1258,7 +1258,8 @@ const chartTokensCss = ":root{--chart-ink:#2d2d2d;--chart-ink-muted:#686868;--ch
|
|
|
1258
1258
|
* cost per pass and median run. An App Grade grader adds a tier strip under
|
|
1259
1259
|
* the bar with a tick at the pass tier. Bootstrap rows with ranks keep their order;
|
|
1260
1260
|
* unranked rows sort by rate, rows with too few units last, and the finding
|
|
1261
|
-
* says no comparison backs the order.
|
|
1261
|
+
* says no comparison backs the order. Explicit input order keeps unranked rows
|
|
1262
|
+
* where the producer placed them and makes no ranking claim.
|
|
1262
1263
|
*
|
|
1263
1264
|
* Refuses: a bar when the producer labels the estimate `none` or
|
|
1264
1265
|
* `insufficient` (the row prints its count only); a whisker whose interval
|
|
@@ -1282,6 +1283,14 @@ function rankedRates(input, o) {
|
|
|
1282
1283
|
id,
|
|
1283
1284
|
refused: `No ${noun.setup} has an ${noun.attempt}.`
|
|
1284
1285
|
};
|
|
1286
|
+
if (o.order !== void 0 && o.order !== "input") return {
|
|
1287
|
+
id,
|
|
1288
|
+
refused: "Unknown row order."
|
|
1289
|
+
};
|
|
1290
|
+
if (o.order === "input" && input.some((row) => row.rank !== null)) return {
|
|
1291
|
+
id,
|
|
1292
|
+
refused: "Input order requires unranked rows."
|
|
1293
|
+
};
|
|
1285
1294
|
for (const row of input) {
|
|
1286
1295
|
const gap = rateDataGap(row);
|
|
1287
1296
|
if (gap) return {
|
|
@@ -1307,7 +1316,7 @@ function rankedRates(input, o) {
|
|
|
1307
1316
|
}
|
|
1308
1317
|
}
|
|
1309
1318
|
const ranked = input.every((row) => row.rank !== null && row.estimate === "bootstrap");
|
|
1310
|
-
const rows = rateOrder(input);
|
|
1319
|
+
const rows = o.order === "input" ? [...input] : rateOrder(input);
|
|
1311
1320
|
const layout = {
|
|
1312
1321
|
ranked,
|
|
1313
1322
|
cost: rows.some((r) => perPass(r.cost) !== null || r.cost.basis !== "unknown" || r.cost.receipts !== null),
|
|
@@ -1323,8 +1332,8 @@ function rankedRates(input, o) {
|
|
|
1323
1332
|
const setupsN = `${rows.length} ${plural(rows.length, noun.setup)}`;
|
|
1324
1333
|
const top = rows[0];
|
|
1325
1334
|
const uniqueTop = bars.length === 1 || bars.length > 1 && bars[1].rate < top.rate;
|
|
1326
|
-
const finding = ranked ? `${top.label} ranks first, passing ${pct(top.rate)} of ${plural(2, noun.attempt)}.` : bars.length === 0 ? `No ${noun.setup} has enough units to draw a ${o.measure}.` : rows.length === 1 ? `${top.label} passes ${pct(top.rate)} of ${top.attempts} ${plural(top.attempts, noun.attempt)}.` : uniqueTop ? `${top.label} has the highest ${o.measure}, ${pct(top.rate)} of ${top.attempts} ${plural(top.attempts, noun.attempt)}; no comparison backs the order.` : `Sorted by ${o.measure}; no comparison backs the order.`;
|
|
1327
|
-
const lede = `${passed} of ${attempts} ${plural(attempts, noun.attempt)} passed across ${setupsN}.` + (noBar.length && bars.length ? ` ${noBar.length} of ${setupsN} have too few units to draw a rate; they come last
|
|
1335
|
+
const finding = ranked ? `${top.label} ranks first, passing ${pct(top.rate)} of ${plural(2, noun.attempt)}.` : bars.length === 0 ? `No ${noun.setup} has enough units to draw a ${o.measure}.` : o.order === "input" ? `${capitalize(o.measure)} by ${noun.setup}; no ranking is claimed.` : rows.length === 1 ? `${top.label} passes ${pct(top.rate)} of ${top.attempts} ${plural(top.attempts, noun.attempt)}.` : uniqueTop ? `${top.label} has the highest ${o.measure}, ${pct(top.rate)} of ${top.attempts} ${plural(top.attempts, noun.attempt)}; no comparison backs the order.` : `Sorted by ${o.measure}; no comparison backs the order.`;
|
|
1336
|
+
const lede = `${passed} of ${attempts} ${plural(attempts, noun.attempt)} passed across ${setupsN}.` + (noBar.length && bars.length ? ` ${noBar.length} of ${setupsN} have too few units to draw a rate${o.order === "input" ? "." : "; they come last."}` : "");
|
|
1328
1337
|
const intervalNames = [...new Set(whiskers.map((row) => intervalName(row.interval)))];
|
|
1329
1338
|
const read = bars.length ? [`Bars show the share of ${plural(2, noun.attempt)} that passed${whiskers.length ? `; whiskers show the ${intervalNames.join(" or ")} interval` : ""}.`, tiered ? `The strip under a bar splits ${plural(2, noun.attempt)} by App Grade tier${o.passTier ? `, and the tick marks ${o.passTier} or better` : ""}.` : ""].filter(Boolean).join(" ") : `Counts show ${plural(2, noun.attempt)} passed; no ${noun.setup} has enough units to draw a rate.`;
|
|
1330
1339
|
const bases = [...new Set(rows.filter((r) => perPass(r.cost) !== null).map((r) => r.cost.basis))];
|
|
@@ -1596,8 +1605,17 @@ function tilesOf(cell) {
|
|
|
1596
1605
|
while (out.length < attempts) out.push("ungraded");
|
|
1597
1606
|
return out;
|
|
1598
1607
|
}
|
|
1599
|
-
if (cell.solved !== null) return [
|
|
1600
|
-
|
|
1608
|
+
if (cell.solved !== null) return [
|
|
1609
|
+
...Array(cell.solved).fill("solved"),
|
|
1610
|
+
...Array(attempts - cell.solved - (cell.flagged ?? 0) - (cell.unmeasured ?? 0)).fill("open"),
|
|
1611
|
+
...Array(cell.flagged ?? 0).fill("flagged"),
|
|
1612
|
+
...Array(cell.unmeasured ?? 0).fill("unmeasured")
|
|
1613
|
+
];
|
|
1614
|
+
return [
|
|
1615
|
+
...Array(attempts - (cell.flagged ?? 0) - (cell.unmeasured ?? 0)).fill("ungraded"),
|
|
1616
|
+
...Array(cell.flagged ?? 0).fill("flagged"),
|
|
1617
|
+
...Array(cell.unmeasured ?? 0).fill("unmeasured")
|
|
1618
|
+
];
|
|
1601
1619
|
}
|
|
1602
1620
|
function tile(kind, x, y) {
|
|
1603
1621
|
switch (kind) {
|
|
@@ -1619,7 +1637,7 @@ function cellText(cell, means) {
|
|
|
1619
1637
|
if (cell.attempts === 0) return "none counted";
|
|
1620
1638
|
if (cell.solved !== null) return kn(cell.solved, cell.attempts);
|
|
1621
1639
|
if (cell.tiers) return tierSummary(cell.tiers, cell.unmeasured, cell.flagged);
|
|
1622
|
-
return `${cell.attempts}`;
|
|
1640
|
+
return tierSummary(null, cell.unmeasured, cell.flagged) ? `${cell.attempts} · ${tierSummary(null, cell.unmeasured, cell.flagged)}` : `${cell.attempts}`;
|
|
1623
1641
|
}
|
|
1624
1642
|
function describe(task, setup, cell, means) {
|
|
1625
1643
|
if (!cell || (means ? cell.mean === null : cell.attempts === null)) return `${task} · ${setup.label}: not run`;
|
|
@@ -1684,7 +1702,7 @@ function taskMatrix(tasks, setupsIn, cells, o = {}) {
|
|
|
1684
1702
|
refused: `${cell.task} × ${cell.setup}: cost is invalid.`
|
|
1685
1703
|
};
|
|
1686
1704
|
if (!means && cell.attempts !== null) {
|
|
1687
|
-
if (tierTotal(cell.tiers) + (cell.flagged ?? 0) + (cell.unmeasured ?? 0) > cell.attempts || cell.solved !== null && cell.solved > cell.attempts) return {
|
|
1705
|
+
if (tierTotal(cell.tiers) + (cell.flagged ?? 0) + (cell.unmeasured ?? 0) > cell.attempts || cell.solved !== null && cell.solved + (cell.flagged ?? 0) + (cell.unmeasured ?? 0) > cell.attempts) return {
|
|
1688
1706
|
id,
|
|
1689
1707
|
refused: `${cell.task} × ${cell.setup}: grades or passes exceed its ${cell.attempts} attempts.`
|
|
1690
1708
|
};
|
|
@@ -1761,7 +1779,7 @@ function taskMatrix(tasks, setupsIn, cells, o = {}) {
|
|
|
1761
1779
|
const kinds = /* @__PURE__ */ new Set();
|
|
1762
1780
|
if (!means) for (const cell of cells) for (const k of tilesOf(cell)) kinds.add(k);
|
|
1763
1781
|
const tiered = cells.some((c) => c.tiers !== null);
|
|
1764
|
-
const read = means ? `Each cell is one ${noun.setup}'s mean on one ${noun.task}, printed and drawn as a bar on a shared scale; · marks a pair never scored.` : tiered ? `One tile per ${noun.attempt}, best first: tiles fill by App Grade tier and an outline is F${o.passTier ? `; ${o.passTier} or better passes` : ""}. Tile order is not run order.` : `One tile per ${noun.attempt}: a filled tile passed and
|
|
1782
|
+
const read = means ? `Each cell is one ${noun.setup}'s mean on one ${noun.task}, printed and drawn as a bar on a shared scale; · marks a pair never scored.` : tiered ? `One tile per ${noun.attempt}, best first: tiles fill by App Grade tier and an outline is F${o.passTier ? `; ${o.passTier} or better passes` : ""}. Tile order is not run order.` : `One tile per ${noun.attempt}: a filled tile passed and a plain outline did not. Dashed, dotted, and struck tiles keep their separate observation states. Tile order is not run order.`;
|
|
1765
1783
|
const method = means ? `Each cell is the producer's mean score for one ${noun.setup} on one ${noun.task}.` : [
|
|
1766
1784
|
tiered ? `Tiles show the App Grade tier of each ${noun.attempt}${o.passTier ? `, and ${o.passTier} or better counts as a pass` : ""}.` : `Filled tiles are the ${plural(2, noun.attempt)} the producer marks solved.`,
|
|
1767
1785
|
kinds.has("unmeasured") ? `U marks ${noun.attempt === "attempt" ? "an attempt" : `a ${noun.attempt}`} the grader could not measure.` : "",
|
|
@@ -1774,8 +1792,8 @@ function taskMatrix(tasks, setupsIn, cells, o = {}) {
|
|
|
1774
1792
|
}))], tasks.map((task) => [task, ...setups.map((s) => {
|
|
1775
1793
|
const cell = at(task, s);
|
|
1776
1794
|
const main = cellText(cell, means);
|
|
1777
|
-
const extra = !means && cell && cell.solved !== null && cell.tiers ? ` · ${tierSummary(cell.tiers, cell.unmeasured, cell.flagged)}` : "";
|
|
1778
|
-
const cost = cell && cell.costUsd !== null ? ` · ${
|
|
1795
|
+
const extra = !means && cell && cell.solved !== null && (cell.tiers || cell.unmeasured || cell.flagged) ? ` · ${tierSummary(cell.tiers, cell.unmeasured, cell.flagged)}` : "";
|
|
1796
|
+
const cost = cell && cell.costUsd !== null ? ` · ${usd(cell.costUsd)}` : "";
|
|
1779
1797
|
return main === "·" ? "not run" : `${main}${extra}${cost}`;
|
|
1780
1798
|
})]));
|
|
1781
1799
|
const scaleMax = Math.max(1, ...cells.map((c) => c.mean ?? 0));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tangle-network/charts",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.5",
|
|
4
4
|
"description": "Benchmark figures as static SVG and HTML tables: ranked rates, cost frontier, comparison intervals, task matrix and breakdown. Draws from producer data and refuses what it cannot draw honestly.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|