@tangle-network/charts 0.1.4 → 0.1.6

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 CHANGED
@@ -21,6 +21,8 @@ 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
22
  A matrix preserves an observed zero cost as $0 and omits a null cost.
23
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.
24
26
  Malformed rates, intervals, matrix counts, and breakdown counts return a refusal instead of a misleading mark.
25
27
  Unmeasured and flagged matrix attempts keep distinct marks and table counts, even without tier grades.
26
28
  An interval whisker is omitted when its bounds exclude the row's rate.
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
@@ -999,7 +999,7 @@ function costFrontier(rows, o) {
999
999
  row.label,
1000
1000
  drawable(row.estimate) ? pct(row.rate) : estimateNote(row.estimate, row.attempts),
1001
1001
  kn(row.solved, row.attempts),
1002
- rateIntervalGap(row) === null ? `${pct(row.interval.lower)}–${pct(row.interval.upper)} (${intervalName(row.interval)}, n=${row.attempts})` : `not drawn (${rateIntervalGap(row)})`,
1002
+ rateIntervalGap(row) === null ? `${pct(row.interval.lower)}–${pct(row.interval.upper)} (${intervalName(row.interval)}, ${row.attempts} attempts)` : `not drawn (${rateIntervalGap(row)})`,
1003
1003
  costText(row.cost, row.solved),
1004
1004
  row.cost.basis,
1005
1005
  row.onFront === null ? "not computed" : row.onFront ? "yes" : "no"
@@ -1065,7 +1065,7 @@ function narrowList(rows) {
1065
1065
  const fact = placed ? `${count} · ${costText(row.cost, row.solved)} per pass${row.onFront ? " · on the frontier" : ""}` : `${count} · ${reason}not plotted`;
1066
1066
  const facts = fitLines(fact.split(" · "), 358, 12, "mono");
1067
1067
  marks += textBlock(facts, 0, cy + 12, 16, `class="tgc-ink-muted tgc-num" font-size="12"`);
1068
- const interval = rateIntervalGap(row) === null ? ` · ${intervalName(row.interval)} interval ${pct(row.interval.lower)}–${pct(row.interval.upper)}, n=${row.attempts}` : "";
1068
+ const interval = rateIntervalGap(row) === null ? ` · ${intervalName(row.interval)} interval ${pct(row.interval.lower)}–${pct(row.interval.upper)}, ${row.attempts} attempts` : "";
1069
1069
  out += titled(`${row.label} · ${fact}${interval}`, marks);
1070
1070
  y = cy + 4 + facts.length * 16;
1071
1071
  if (i < rows.length - 1) out += line(0, y + 2, 358, y + 2, "tgc-rule");
@@ -1228,7 +1228,7 @@ function plot(costed, unplaced, drawLine, o) {
1228
1228
  }
1229
1229
  for (const p of placed) {
1230
1230
  const cls = p.row.onFront ? p.estimated ? "tgc-pt-est" : "tgc-pt-front" : "tgc-pt";
1231
- out += titled(`${p.row.label} · ${pct(p.row.rate)} ${o.measure} · ${kn(p.row.solved, p.row.attempts)} passed · ${costText(p.row.cost, p.row.solved)} per pass${rateIntervalGap(p.row) === null ? ` · ${intervalName(p.row.interval)} interval ${pct(p.row.interval.lower)}–${pct(p.row.interval.upper)}, n=${p.row.attempts}` : ""}${p.row.onFront ? " · on the frontier" : ""}`, circle(p.x, p.y, 4, cls));
1231
+ out += titled(`${p.row.label} · ${pct(p.row.rate)} ${o.measure} · ${kn(p.row.solved, p.row.attempts)} passed · ${costText(p.row.cost, p.row.solved)} per pass${rateIntervalGap(p.row) === null ? ` · ${intervalName(p.row.interval)} interval ${pct(p.row.interval.lower)}–${pct(p.row.interval.upper)}, ${p.row.attempts} attempts` : ""}${p.row.onFront ? " · on the frontier" : ""}`, circle(p.x, p.y, 4, cls));
1232
1232
  }
1233
1233
  out += labels.join("");
1234
1234
  let h = 320;
@@ -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))];
@@ -1379,7 +1388,7 @@ function rankedRates(input, o) {
1379
1388
  String(row.solved),
1380
1389
  String(row.attempts),
1381
1390
  drawable(row.estimate) ? pct(row.rate) : estimateNote(row.estimate, row.attempts),
1382
- rateIntervalGap(row) === null ? `${pct(row.interval.lower)}–${pct(row.interval.upper)} (${intervalName(row.interval)}, n=${row.attempts})` : `not drawn (${rateIntervalGap(row)})`,
1391
+ rateIntervalGap(row) === null ? `${pct(row.interval.lower)}–${pct(row.interval.upper)} (${intervalName(row.interval)}, ${row.attempts} attempts)` : `not drawn (${rateIntervalGap(row)})`,
1383
1392
  ...tiered ? [row.tiers ? [tierSummary(row.tiers), offLadder ? `${offLadder} off the ladder` : ""].filter(Boolean).join(" · ") || "none" : "not graded"] : [],
1384
1393
  ...layout.cost ? [costText(row.cost, row.solved), row.cost.basis + (row.cost.receipts !== null ? `, ${row.cost.receipts} receipts` : "")] : [],
1385
1394
  ...layout.median ? [row.medianWallMs === null ? "unknown" : duration(row.medianWallMs)] : []
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tangle-network/charts",
3
- "version": "0.1.4",
3
+ "version": "0.1.6",
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",