@things-factory/figure-ui 10.1.147 → 10.1.150

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.
Files changed (210) hide show
  1. package/client/bootstrap.ts +10 -2
  2. package/client/graphql/index.ts +20 -0
  3. package/client/modeller/canvas.ts +6 -2
  4. package/client/modeller/carrier-declaration.ts +63 -0
  5. package/client/modeller/editor.ts +62 -27
  6. package/client/modeller/figure-carrier.ts +117 -0
  7. package/client/modeller/figure-cavity-drawing.ts +3 -9
  8. package/client/modeller/figure-first-save.ts +4 -7
  9. package/client/modeller/figure-history-panel.ts +2 -3
  10. package/client/modeller/figure-links.ts +46 -60
  11. package/client/modeller/figure-material-panel.ts +4 -14
  12. package/client/modeller/figure-mesh-choice.ts +68 -0
  13. package/client/modeller/figure-parts.ts +23 -1
  14. package/client/modeller/figure-preview.ts +2 -2
  15. package/client/modeller/figure-properties.ts +5 -3
  16. package/client/modeller/figure-section-editor.ts +12 -33
  17. package/client/modeller/figure-section-panel.ts +6 -7
  18. package/client/modeller/figure-slot-layout-panel.ts +208 -0
  19. package/client/modeller/figure-verdict.ts +21 -31
  20. package/client/modeller/first-save.ts +23 -0
  21. package/client/modeller/links.ts +52 -1
  22. package/client/modeller/material-edit.ts +38 -0
  23. package/client/modeller/maturity.ts +28 -0
  24. package/client/modeller/mesh-import.ts +77 -0
  25. package/client/modeller/modeller-route.ts +9 -0
  26. package/client/modeller/mounting-part.ts +15 -0
  27. package/client/modeller/newest-answer.ts +21 -0
  28. package/client/modeller/preview-model.ts +5 -0
  29. package/client/modeller/refusals.ts +168 -82
  30. package/client/modeller/section-controls.ts +25 -1
  31. package/client/modeller/section-drawing.ts +43 -1
  32. package/client/modeller/slot-layout-host.ts +140 -0
  33. package/client/pages/figure-modeller-page.ts +6 -5
  34. package/client/viewparts/detail-route.ts +7 -0
  35. package/client/viewparts/figure-detail-dock.ts +1 -3
  36. package/dist-client/bootstrap.d.ts +1 -1
  37. package/dist-client/bootstrap.js +9 -2
  38. package/dist-client/bootstrap.js.map +1 -1
  39. package/dist-client/graphql/index.d.ts +5 -0
  40. package/dist-client/graphql/index.js +19 -0
  41. package/dist-client/graphql/index.js.map +1 -1
  42. package/dist-client/modeller/canvas.d.ts +2 -0
  43. package/dist-client/modeller/canvas.js +10 -2
  44. package/dist-client/modeller/canvas.js.map +1 -1
  45. package/dist-client/modeller/carrier-declaration.d.ts +31 -0
  46. package/dist-client/modeller/carrier-declaration.js +53 -0
  47. package/dist-client/modeller/carrier-declaration.js.map +1 -0
  48. package/dist-client/modeller/editor.d.ts +13 -0
  49. package/dist-client/modeller/editor.js +62 -27
  50. package/dist-client/modeller/editor.js.map +1 -1
  51. package/dist-client/modeller/figure-carrier.d.ts +26 -0
  52. package/dist-client/modeller/figure-carrier.js +123 -0
  53. package/dist-client/modeller/figure-carrier.js.map +1 -0
  54. package/dist-client/modeller/figure-cavity-drawing.js +3 -11
  55. package/dist-client/modeller/figure-cavity-drawing.js.map +1 -1
  56. package/dist-client/modeller/figure-first-save.d.ts +4 -0
  57. package/dist-client/modeller/figure-first-save.js +5 -8
  58. package/dist-client/modeller/figure-first-save.js.map +1 -1
  59. package/dist-client/modeller/figure-history-panel.js +2 -4
  60. package/dist-client/modeller/figure-history-panel.js.map +1 -1
  61. package/dist-client/modeller/figure-links.d.ts +4 -1
  62. package/dist-client/modeller/figure-links.js +47 -57
  63. package/dist-client/modeller/figure-links.js.map +1 -1
  64. package/dist-client/modeller/figure-material-panel.d.ts +0 -1
  65. package/dist-client/modeller/figure-material-panel.js +4 -14
  66. package/dist-client/modeller/figure-material-panel.js.map +1 -1
  67. package/dist-client/modeller/figure-mesh-choice.d.ts +16 -0
  68. package/dist-client/modeller/figure-mesh-choice.js +75 -0
  69. package/dist-client/modeller/figure-mesh-choice.js.map +1 -0
  70. package/dist-client/modeller/figure-parts.d.ts +1 -1
  71. package/dist-client/modeller/figure-parts.js +22 -0
  72. package/dist-client/modeller/figure-parts.js.map +1 -1
  73. package/dist-client/modeller/figure-preview.js +2 -2
  74. package/dist-client/modeller/figure-preview.js.map +1 -1
  75. package/dist-client/modeller/figure-properties.d.ts +2 -1
  76. package/dist-client/modeller/figure-properties.js +5 -3
  77. package/dist-client/modeller/figure-properties.js.map +1 -1
  78. package/dist-client/modeller/figure-section-editor.d.ts +2 -2
  79. package/dist-client/modeller/figure-section-editor.js +12 -33
  80. package/dist-client/modeller/figure-section-editor.js.map +1 -1
  81. package/dist-client/modeller/figure-section-panel.js +6 -7
  82. package/dist-client/modeller/figure-section-panel.js.map +1 -1
  83. package/dist-client/modeller/figure-slot-layout-panel.d.ts +36 -0
  84. package/dist-client/modeller/figure-slot-layout-panel.js +198 -0
  85. package/dist-client/modeller/figure-slot-layout-panel.js.map +1 -0
  86. package/dist-client/modeller/figure-verdict.d.ts +1 -1
  87. package/dist-client/modeller/figure-verdict.js +19 -37
  88. package/dist-client/modeller/figure-verdict.js.map +1 -1
  89. package/dist-client/modeller/first-save.d.ts +10 -0
  90. package/dist-client/modeller/first-save.js +16 -0
  91. package/dist-client/modeller/first-save.js.map +1 -1
  92. package/dist-client/modeller/links.d.ts +26 -1
  93. package/dist-client/modeller/links.js +43 -0
  94. package/dist-client/modeller/links.js.map +1 -1
  95. package/dist-client/modeller/material-edit.d.ts +11 -0
  96. package/dist-client/modeller/material-edit.js +28 -0
  97. package/dist-client/modeller/material-edit.js.map +1 -0
  98. package/dist-client/modeller/maturity.d.ts +15 -0
  99. package/dist-client/modeller/maturity.js +23 -0
  100. package/dist-client/modeller/maturity.js.map +1 -1
  101. package/dist-client/modeller/mesh-import.d.ts +47 -0
  102. package/dist-client/modeller/mesh-import.js +47 -0
  103. package/dist-client/modeller/mesh-import.js.map +1 -0
  104. package/dist-client/modeller/modeller-route.d.ts +5 -0
  105. package/dist-client/modeller/modeller-route.js +9 -0
  106. package/dist-client/modeller/modeller-route.js.map +1 -1
  107. package/dist-client/modeller/mounting-part.d.ts +14 -0
  108. package/dist-client/modeller/mounting-part.js +10 -0
  109. package/dist-client/modeller/mounting-part.js.map +1 -0
  110. package/dist-client/modeller/newest-answer.d.ts +12 -0
  111. package/dist-client/modeller/newest-answer.js +21 -0
  112. package/dist-client/modeller/newest-answer.js.map +1 -0
  113. package/dist-client/modeller/preview-model.d.ts +2 -0
  114. package/dist-client/modeller/preview-model.js +4 -0
  115. package/dist-client/modeller/preview-model.js.map +1 -1
  116. package/dist-client/modeller/refusals.d.ts +26 -5
  117. package/dist-client/modeller/refusals.js +184 -86
  118. package/dist-client/modeller/refusals.js.map +1 -1
  119. package/dist-client/modeller/section-controls.d.ts +17 -1
  120. package/dist-client/modeller/section-controls.js +18 -0
  121. package/dist-client/modeller/section-controls.js.map +1 -1
  122. package/dist-client/modeller/section-drawing.d.ts +24 -1
  123. package/dist-client/modeller/section-drawing.js +42 -0
  124. package/dist-client/modeller/section-drawing.js.map +1 -1
  125. package/dist-client/modeller/slot-layout-host.d.ts +81 -0
  126. package/dist-client/modeller/slot-layout-host.js +105 -0
  127. package/dist-client/modeller/slot-layout-host.js.map +1 -0
  128. package/dist-client/pages/figure-modeller-page.js +5 -4
  129. package/dist-client/pages/figure-modeller-page.js.map +1 -1
  130. package/dist-client/tsconfig.tsbuildinfo +1 -1
  131. package/dist-client/viewparts/detail-route.d.ts +5 -0
  132. package/dist-client/viewparts/detail-route.js +8 -0
  133. package/dist-client/viewparts/detail-route.js.map +1 -0
  134. package/dist-client/viewparts/figure-detail-dock.d.ts +0 -1
  135. package/dist-client/viewparts/figure-detail-dock.js +1 -3
  136. package/dist-client/viewparts/figure-detail-dock.js.map +1 -1
  137. package/package.json +9 -8
  138. package/test/align.test.ts +0 -9
  139. package/test/browser/assistant-stand-in.js +32 -0
  140. package/test/browser/build.check.mjs +77 -0
  141. package/test/browser/build.mjs +31 -6
  142. package/test/browser/editing-page.js +224 -0
  143. package/test/browser/editing.check.mjs +550 -0
  144. package/test/browser/links-page.js +113 -0
  145. package/test/browser/links.check.mjs +568 -0
  146. package/test/browser/modeller.check.mjs +21 -0
  147. package/test/browser/parts-page.js +120 -0
  148. package/test/browser/parts.check.mjs +328 -0
  149. package/test/browser/places-mesh-page.js +36 -0
  150. package/test/browser/places-mesh.check.mjs +239 -0
  151. package/test/browser/product-page.check.mjs +682 -0
  152. package/test/browser/product-page.js +276 -0
  153. package/test/browser/screen-page.js +112 -0
  154. package/test/browser/screen-product-page.js +62 -0
  155. package/test/browser/screen.check.mjs +1003 -0
  156. package/test/browser/section-page.js +256 -0
  157. package/test/browser/section.check.mjs +719 -0
  158. package/test/browser/serve.mjs +20 -12
  159. package/test/carrier-declaration.test.ts +69 -0
  160. package/test/cavity-drawing.test.ts +2 -18
  161. package/test/clip-ai-proposal.test.ts +1 -5
  162. package/test/clip-consent.test.ts +0 -5
  163. package/test/clips.test.ts +0 -7
  164. package/test/command-preview.test.ts +0 -68
  165. package/test/controls.test.ts +0 -9
  166. package/test/detail-dock.test.ts +6 -25
  167. package/test/face-mapping.test.ts +1 -20
  168. package/test/fasten-drawing.test.ts +0 -23
  169. package/test/fields.test.ts +6 -33
  170. package/test/figure-assistant-surface.test.ts +32 -38
  171. package/test/first-minute.test.ts +3 -55
  172. package/test/first-save-suggest.test.ts +11 -8
  173. package/test/first-save.test.ts +4 -26
  174. package/test/gizmo.test.ts +0 -25
  175. package/test/joint-fan.test.ts +0 -10
  176. package/test/keys.test.ts +0 -7
  177. package/test/layout.test.ts +4 -73
  178. package/test/links.test.ts +48 -67
  179. package/test/live.test.ts +0 -34
  180. package/test/material.test.ts +17 -26
  181. package/test/maturity.test.ts +13 -16
  182. package/test/mesh-import.test.ts +76 -0
  183. package/test/modeller-route.test.ts +3 -19
  184. package/test/package-download.test.ts +6 -7
  185. package/test/parts-wiring.test.ts +9 -51
  186. package/test/preview.test.ts +5 -46
  187. package/test/properties.test.ts +11 -26
  188. package/test/proposal-record.test.ts +2 -19
  189. package/test/recipes.test.ts +0 -15
  190. package/test/refusals.test.ts +257 -151
  191. package/test/release-entry.test.ts +1 -9
  192. package/test/release-panel.test.ts +1 -22
  193. package/test/resize-with-placement.test.ts +0 -32
  194. package/test/revert-choice.test.ts +1 -22
  195. package/test/revert-keeping.test.ts +1 -12
  196. package/test/save-landed.test.ts +16 -14
  197. package/test/scene-canvas.test.ts +2 -13
  198. package/test/section-editor.test.ts +30 -83
  199. package/test/section-panel.test.ts +22 -17
  200. package/test/slot-layout-host.test.ts +117 -0
  201. package/test/theme.test.ts +5 -9
  202. package/test/verdict.test.ts +44 -41
  203. package/test/view.test.ts +5 -12
  204. package/translations/en.json +61 -1
  205. package/translations/es.json +61 -1
  206. package/translations/ja.json +61 -1
  207. package/translations/ko.json +61 -1
  208. package/translations/ms.json +61 -1
  209. package/translations/zh.json +61 -1
  210. package/test/thumbnail.test.ts +0 -29
@@ -1 +1 @@
1
- {"version":3,"file":"maturity.js","sourceRoot":"","sources":["../../client/modeller/maturity.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n compileFigureAsset,\n compileFigureDocument,\n LIMITS,\n SEGMENT_PRESETS,\n FIGURE_BUDGET_KEYS,\n FIGURE_GRADE_SCALE,\n figureCostOf,\n figureGradeOf,\n figureMaterialKeyOf,\n figureScoreOf,\n figureWorldBoxesOf,\n figureWritersOf\n} from '@hatiolab/figure-model'\nimport type { FigureAsset, FigureAssetGeometry, FigureBudgetKey, FigureBudgetUse, FigureCost, FigureGeometry, FigureScore } from '@hatiolab/figure-model'\n\nimport { capacityFrom } from './scene-budget.js'\nimport type { FigureCapacity } from './scene-budget.js'\n\n/*\n * The modeller's maturity report, read off the evaluated asset (user, 2026-09-24: the tab showed a count and nothing\n * else — 「왜 이렇게 너프되었는지」):\n *\n * grade A–D and its scale figure-model's `figureScoreOf`: one screen's target shared per instance (groups,\n * triangles) and the declared rule limits (independent, transparent)\n * radar · axes six axes; reactive is not measured, and detail has no field\n * drawing cost triangles, distinct shapes, distinct materials\n * trend what grows with the instance count and what the instances share\n *\n * Kept apart from the element so it can be tested without a browser.\n *\n * ## What the renderer shares, which is what the numbers count\n *\n * things-scene draws one mesh per drawn body (`figure-rig.ts`) — no merging by material — so a body is\n * a draw call. It shares geometry by provider, dimensions, segments and profile (`figure-geometry.ts`, `keyOf`)\n * and materials by token, preset, transparency and light (`materialFor`). The keys below are those keys; a\n * distinct-shape count that used another key would describe a renderer that does not exist.\n *\n * ## Budgets does not have\n *\n * Two budgets are not measured here, and are not shown as zero:\n * - off-palette surfaces: the material has no surface field, so there is nothing to count;\n * - part count by detail level: does not carry the detail level (chief architect, 2026-09-24, ADR-0087).\n */\n\n/*\n The grade, its budgets and its bounds are figure-model's (`figureScoreOf`), so the catalogue grades a figure as this tab\n does. The grade is the headroom against one screen's target (`LIMITS.screenInstances`), not a draw-call limit.\n*/\nexport { FIGURE_BUDGET_KEYS, FIGURE_GRADE_SCALE as GRADE_SCALE, figureGradeOf as gradeOf }\nexport type { FigureBudgetKey, FigureBudgetUse, FigureScore }\n\nexport type FigureAxisKey = 'scale' | 'consistency' | 'reuse' | 'detail' | 'reactive' | 'readable'\n\n/** One maturity axis. */\nexport interface FigureMaturityAxis {\n key: FigureAxisKey\n /** 0–1. Absent when the axis cannot be measured. */\n ratio?: number\n reading?: string\n /** A reading that is words, not a number. */\n readingKey?: string\n because?: string\n /** Why the axis is not measured. When present there is no ratio — an unmeasured axis is not a zero. */\n blocked?: string\n}\n\n/** Instances on one screen, and what each series costs at that count. */\nexport interface FigureCurvePoint {\n instances: number\n triangles: number\n drawCalls: number\n /** Vertex buffers: one per distinct shape, shared by every instance of the same size. */\n geometries: number\n materials: number\n}\n\nexport interface FigureReport {\n cost: FigureCost\n capacity: FigureCapacity\n score: FigureScore\n /** Distinct shapes and materials among the drawn bodies — the 「그리는 비용」 rows. */\n distinctShapes: number\n distinctMaterials: number\n reuse: { distinct: number; parts: number; saved: number }\n axes: FigureMaturityAxis[]\n curve: FigureCurvePoint[]\n}\n\n/** The board target for the scale axis: 500 assets on one drawing (design document §4.15). */\nexport const BOARD_ASSETS = 500\n\n/**\n * The report for one asset, or nothing when no body is drawn — then there is nothing to measure, and the screen\n * says so rather than drawing zeros.\n *\n * Evaluated at the asset's own design and state defaults, as `figureCostOf` is.\n */\nexport function figureReportOf(asset: FigureAsset): FigureReport | undefined {\n const cost = figureCostOf(asset)\n const capacity = capacityFrom(cost.groups, cost.triangles)\n if (!capacity) return undefined\n\n const drawn = compileFigureAsset(asset)\n .evaluate()\n .geometry.filter(body => body.visible !== false)\n const plan = compileFigureDocument(asset.document)\n const writers = figureWritersOf(asset)\n\n const shapes = new Set(drawn.map(shapeKeyOf))\n const materials = new Set(drawn.map(materialKeyOf))\n\n const score = figureScoreOf(asset)!\n\n const reuse = { distinct: shapes.size, parts: drawn.length, saved: drawn.length - shapes.size }\n\n const axes: FigureMaturityAxis[] = [\n {\n key: 'scale',\n // The board target filled is 1; room beyond it is better spent on the other axes, so it does not count more.\n ratio: Math.min(1, capacity.instances / BOARD_ASSETS),\n reading: String(capacity.instances),\n because: 'figure.text.maturity-scale-because'\n },\n consistency(asset, materials.size),\n {\n key: 'reuse',\n // A low distinct-to-parts ratio is much reuse; turned over so that more is higher.\n ratio: reuse.parts === 0 ? 0 : 1 - reuse.distinct / reuse.parts,\n reading: String(reuse.saved),\n because: 'figure.text.maturity-reuse-because'\n },\n { key: 'detail', blocked: 'figure.text.maturity-blocked-no-detail-level' },\n { key: 'reactive', blocked: 'figure.text.maturity-blocked-no-binding' },\n readable(asset, plan, drawn, writers)\n ]\n\n return {\n cost,\n capacity,\n score,\n distinctShapes: shapes.size,\n distinctMaterials: materials.size,\n reuse,\n axes,\n curve: decadeSteps(1, 10000).map(instances => ({\n instances,\n triangles: cost.triangles * instances,\n drawCalls: cost.groups * instances,\n geometries: shapes.size,\n materials: materials.size\n }))\n }\n}\n\n/**\n * The key things-scene shares a body's geometry by (`figure-geometry.ts` `keyOf`): the operation, what is not in its\n * numbers (the axis, the kind of section, which ends of an inside are open), its numbers to a micrometre, and segments\n * (12 when unset).\n */\nexport function shapeKeyOf(body: FigureAssetGeometry | FigureGeometry): string {\n if (!('shape' in body)) {\n // A scalar body has no mesh of its own; it is still one drawn body, told apart by what it declares.\n const dims = Object.keys(body.dimensions).sort().map(k => `${k}=${body.dimensions[k]}`).join(',')\n return `${body.provider}|${dims}`\n }\n const shape = body.shape\n const round = (v: number) => Math.round(v * 1e6) / 1e6\n const dims = Object.keys(shape.dimensions)\n .sort()\n .map(k => `${k}=${round(shape.dimensions[k]!)}`)\n .join(',')\n const e = shape.extrusion,\n c = shape.cavity,\n r = shape.revolution\n const l = shape.loft\n const meaning = e\n ? `${e.axis}:${e.section.kind}:${c ? `${c.start === 'open' ? 'o' : 'c'}${c.end === 'open' ? 'o' : 'c'}` : '-'}`\n : r\n ? `${r.axis}:${r.profile.kind}`\n : l\n ? `${l.axis}:point`\n : ''\n const segments = (body as { segments?: number }).segments ?? 12\n return `${shape.provider}|${meaning}|${dims}|s${segments}`\n}\n\n/**\n * The key things-scene shares a material by (`figure-rig.ts` `materialFor`), within one asset: token, preset,\n * transparency, and the light when it is on. The colour follows from the token, so it is not a second key.\n */\nexport function materialKeyOf(body: FigureAssetGeometry): string {\n return figureMaterialKeyOf(body)\n}\n\n/**\n * Does it look like one set — baselines 3 and 4, three checks.\n *\n * Two of them hold by construction: the material has no surface field, so there is no texture, and the\n * format refuses a segment count outside the presets (`compileFigureAsset`, `QUALITY`). They are still counted, so\n * the ratio stays one fault in three.\n */\nfunction consistency(asset: FigureAsset, distinctMaterials: number): FigureMaturityAxis {\n const textures = 0\n const offPreset = asset.appearance.filter(look => look.segments !== undefined && !SEGMENT_PRESETS.includes(look.segments)).length\n const faults = (textures > 0 ? 1 : 0) + (offPreset > 0 ? 1 : 0) + (distinctMaterials > LIMITS.distinctMaterials ? 1 : 0)\n return {\n key: 'consistency',\n ratio: (3 - faults) / 3,\n readingKey: faults === 0 ? 'figure.text.maturity-consistency-clean' : 'figure.text.maturity-consistency-faults',\n because: 'figure.text.maturity-consistency-because'\n }\n}\n\n/** Seen from above, these do not fill their footprint box, by provider name. */\n/** Round seen from above: a circle or an ellipse pushed along Y, anything turned about Y. */\nconst roundFootprint = (shape: { extrusion?: { axis: string; section: { kind: string } }; revolution?: { axis: string } }) =>\n (shape.extrusion?.axis === 'y' && shape.extrusion.section.kind === 'ellipse') || shape.revolution?.axis === 'y'\n\n/**\n * Can it be told apart from above — baseline 1.\n *\n * Viewpoint entropy (Vázquez et al.) over the top view, counted by colour region rather than by face so that a\n * finer segment count does not raise it: H = −Σ p·log p over each material's share of the footprint plus the\n * background, divided by log(`LIMITS.distinctMaterials` + 1), the most this measure can reach.\n *\n * The footprint is the base box: the space the asset declares when it declares one (ADR-0044's box is the model's\n * occupancy), otherwise the drawn bodies' own extent. Bodies are their axis-aligned world boxes\n * (`figureWorldBoxesOf`, the gate's reading); the higher one covers the lower.\n */\nfunction readable(\n asset: FigureAsset,\n plan: ReturnType<typeof compileFigureDocument>,\n drawn: FigureAssetGeometry[],\n writers: Map<string, string>\n): FigureMaturityAxis {\n const placed = drawn\n .filter(body => 'pose' in body)\n // One placed, drawn body gives exactly one box; boxes are taken one by one to keep each with its material.\n .map(body => ({ body, box: figureWorldBoxesOf([body], writers)[0]! }))\n if (placed.length === 0) return { key: 'readable', blocked: 'figure.text.maturity-blocked-no-parts' }\n\n let frame: { x0: number; x1: number; z0: number; z1: number }\n if (asset.occupancy) {\n const values = plan.evaluate({ ...asset.designInputs, ...asset.stateDefaults }).values\n const at = (ref: string) => values[ref] as number\n const b = asset.occupancy.bounds\n frame = { x0: at(b.x.min), x1: at(b.x.max), z0: at(b.z.min), z1: at(b.z.max) }\n } else {\n frame = { x0: Infinity, x1: -Infinity, z0: Infinity, z1: -Infinity }\n for (const { box } of placed) {\n frame.x0 = Math.min(frame.x0, box.centre.x - box.extent.x / 2)\n frame.x1 = Math.max(frame.x1, box.centre.x + box.extent.x / 2)\n frame.z0 = Math.min(frame.z0, box.centre.z - box.extent.z / 2)\n frame.z1 = Math.max(frame.z1, box.centre.z + box.extent.z / 2)\n }\n }\n\n const regions = topViewRegions(placed, frame)\n if (regions.total === 0) return { key: 'readable', blocked: 'figure.text.maturity-blocked-no-parts' }\n\n const shares = [...regions.byMaterial.values(), regions.background].map(area => area / regions.footprint).filter(share => share > 0)\n const entropy = -shares.reduce((sum, p) => sum + p * Math.log(p), 0)\n const ceiling = Math.log(LIMITS.distinctMaterials + 1)\n return {\n key: 'readable',\n // Clamped both ways: one region alone gives −0, which is not a reading anyone should see.\n ratio: Math.max(0, Math.min(1, entropy / ceiling)),\n reading: String(regions.byMaterial.size),\n because: 'figure.text.maturity-readable-because'\n }\n}\n\n/** Which material shows from above, on a 64 × 64 grid over the footprint, over world boxes. */\nfunction topViewRegions(\n placed: { body: FigureAssetGeometry; box: ReturnType<typeof figureWorldBoxesOf>[number] }[],\n frame: { x0: number; x1: number; z0: number; z1: number }\n) {\n const GRID = 64\n const cells = new Array<string | null>(GRID * GRID).fill(null)\n const height = new Float64Array(GRID * GRID)\n const sx = GRID / Math.max(frame.x1 - frame.x0, 1e-6)\n const sz = GRID / Math.max(frame.z1 - frame.z0, 1e-6)\n\n for (const { body, box } of placed) {\n const top = box.centre.y + box.extent.y / 2\n const key = materialKeyOf(body)\n const x0 = Math.max(0, Math.floor((box.centre.x - box.extent.x / 2 - frame.x0) * sx))\n const x1 = Math.min(GRID, Math.ceil((box.centre.x + box.extent.x / 2 - frame.x0) * sx))\n const y0 = Math.max(0, Math.floor((box.centre.z - box.extent.z / 2 - frame.z0) * sz))\n const y1 = Math.min(GRID, Math.ceil((box.centre.z + box.extent.z / 2 - frame.z0) * sz))\n const round = 'shape' in body && roundFootprint(body.shape as never)\n\n for (let y = y0; y < y1; y++) {\n for (let x = x0; x < x1; x++) {\n // A round body does not fill its box; the corners are cut.\n if (round) {\n const cx = (x + 0.5 - (x0 + x1) / 2) / ((x1 - x0) / 2 || 1)\n const cy = (y + 0.5 - (y0 + y1) / 2) / ((y1 - y0) / 2 || 1)\n if (cx * cx + cy * cy > 1) continue\n }\n const i = y * GRID + x\n if (cells[i] === null || top > height[i]!) {\n cells[i] = key\n height[i] = top\n }\n }\n }\n }\n\n const byMaterial = new Map<string, number>()\n let covered = 0\n for (const key of cells) {\n if (key === null) continue\n covered++\n byMaterial.set(key, (byMaterial.get(key) ?? 0) + 1)\n }\n return { byMaterial, total: covered, background: GRID * GRID - covered, footprint: GRID * GRID }\n}\n\n/** 1 · 2 · 5 per decade: even steps on a log axis. */\nexport function decadeSteps(from: number, to: number): number[] {\n const out: number[] = []\n for (let decade = 1; decade <= to; decade *= 10) {\n for (const m of [1, 2, 5]) {\n const v = decade * m\n if (v >= from && v <= to) out.push(v)\n }\n }\n if (out.length === 0 || out[out.length - 1] !== to) out.push(to)\n return [...new Set(out)].sort((a, b) => a - b)\n}\n\n// ─── The trend chart ─────────────────────────────────────────────────────────\n\nexport type FigureCurveSeries = 'triangles' | 'drawCalls' | 'geometries' | 'materials'\n\n/**\n * The four lines: two that grow with the instance count and two that stay flat — the flat ones are what the\n * instances share. Materials are dashed and drawn last, so a line under them still shows where the two meet.\n */\nexport const CURVE_SERIES: readonly { key: FigureCurveSeries; flat: boolean; dashed?: boolean }[] = [\n { key: 'triangles', flat: false },\n { key: 'drawCalls', flat: false },\n { key: 'geometries', flat: true },\n { key: 'materials', flat: true, dashed: true }\n]\n\n/** The chart's size. The chart is shown at this size in a sheet; shrunk into the side, its words are unreadable. */\nexport const CURVE_SIZE = { width: 680, height: 380, pad: { top: 52, right: 208, bottom: 44, left: 62 } } as const\n\nexport interface FigureCurveLayout {\n xTicks: { x: number; label: string }[]\n yTicks: { y: number; label: string }[]\n lines: { key: FigureCurveSeries; d: string; flat: boolean; dashed: boolean; last: number }[]\n /** The value the flat lines share when they lie on one another, so the screen can say why one line is missing. */\n overlap?: number\n}\n\nconst log10 = (v: number) => Math.log(Math.max(v, 1)) / Math.LN10\n\n/** 1, 10, 100 … written short. */\nexport function shortNumber(v: number): string {\n if (v >= 1_000_000) return `${v / 1_000_000}M`\n if (v >= 1_000) return `${v / 1_000}k`\n return String(v)\n}\n\n/** Where the chart puts each line and tick. Both axes are logarithmic. */\nexport function curveLayout(points: FigureCurvePoint[]): FigureCurveLayout | undefined {\n if (points.length === 0) return undefined\n const { width, height, pad } = CURVE_SIZE\n const minX = points[0]!.instances\n const maxX = points[points.length - 1]!.instances\n let maxY = 1\n for (const p of points) for (const s of CURVE_SERIES) maxY = Math.max(maxY, p[s.key])\n\n const plotW = width - pad.left - pad.right\n const plotH = height - pad.top - pad.bottom\n const spanX = Math.max(log10(maxX) - log10(minX), 1e-9)\n const spanY = Math.max(log10(maxY), 1e-9)\n const px = (v: number) => pad.left + ((log10(v) - log10(minX)) / spanX) * plotW\n const py = (v: number) => pad.top + plotH - (log10(v) / spanY) * plotH\n\n const yTicks: FigureCurveLayout['yTicks'] = []\n for (let e = 0; Math.pow(10, e) <= maxY * 1.001; e++) yTicks.push({ y: py(Math.pow(10, e)), label: shortNumber(Math.pow(10, e)) })\n const xTicks: FigureCurveLayout['xTicks'] = []\n for (let e = 0; Math.pow(10, e) <= maxX * 1.001; e++) {\n const v = Math.pow(10, e)\n if (v >= minX) xTicks.push({ x: px(v), label: shortNumber(v) })\n }\n\n const last = points[points.length - 1]!\n const lines = CURVE_SERIES.map(s => ({\n key: s.key,\n d: points.map((p, i) => `${i === 0 ? 'M' : 'L'}${px(p.instances).toFixed(1)},${py(p[s.key]).toFixed(1)}`).join(' '),\n flat: s.flat,\n dashed: !!s.dashed,\n last: last[s.key]\n }))\n const flat = new Set(CURVE_SERIES.filter(s => s.flat).map(s => last[s.key]))\n return { xTicks, yTicks, lines, overlap: flat.size === 1 ? [...flat][0] : undefined }\n}\n\n/** What the parts list shows under its title: the cost, how many fit, the grade and what decides it. */\nexport interface FigureBudgetLine {\n triangles: number\n groups: number\n instances: number\n grade: string\n tightest: { key: string; used: number; limit: number }\n}\n\nexport function budgetOf(report: FigureReport | undefined): FigureBudgetLine | undefined {\n if (!report) return undefined\n const { tightest } = report.score\n return {\n triangles: report.cost.triangles,\n groups: report.cost.groups,\n instances: report.capacity.instances,\n grade: report.score.grade,\n tightest: { key: tightest.key, used: tightest.used, limit: Math.floor(tightest.limit) }\n }\n}\n"]}
1
+ {"version":3,"file":"maturity.js","sourceRoot":"","sources":["../../client/modeller/maturity.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n compileFigureAsset,\n compileFigureDocument,\n LIMITS,\n SEGMENT_PRESETS,\n FIGURE_BUDGET_KEYS,\n FIGURE_GRADE_SCALE,\n figureCostOf,\n figureGradeOf,\n figureMaterialKeyOf,\n figureScoreOf,\n figureWorldBoxesOf,\n figureWritersOf\n} from '@hatiolab/figure-model'\nimport type { FigureAsset, FigureAssetGeometry, FigureBudgetKey, FigureBudgetUse, FigureCost, FigureGeometry, FigureScore } from '@hatiolab/figure-model'\n\nimport { capacityFrom } from './scene-budget.js'\nimport type { FigureCapacity } from './scene-budget.js'\n\n/*\n * The modeller's maturity report, read off the evaluated asset (user, 2026-09-24: the tab showed a count and nothing\n * else — 「왜 이렇게 너프되었는지」):\n *\n * grade A–D and its scale figure-model's `figureScoreOf`: one screen's target shared per instance (groups,\n * triangles) and the declared rule limits (independent, transparent)\n * radar · axes six axes; reactive is not measured, and detail has no field\n * drawing cost triangles, distinct shapes, distinct materials\n * trend what grows with the instance count and what the instances share\n *\n * Kept apart from the element so it can be tested without a browser.\n *\n * ## What the renderer shares, which is what the numbers count\n *\n * things-scene draws one mesh per drawn body (`figure-rig.ts`) — no merging by material — so a body is\n * a draw call. It shares geometry by provider, dimensions, segments and profile (`figure-geometry.ts`, `keyOf`)\n * and materials by token, preset, transparency and light (`materialFor`). The keys below are those keys; a\n * distinct-shape count that used another key would describe a renderer that does not exist.\n *\n * ## Budgets does not have\n *\n * Two budgets are not measured here, and are not shown as zero:\n * - off-palette surfaces: the material has no surface field, so there is nothing to count;\n * - part count by detail level: does not carry the detail level (chief architect, 2026-09-24, ADR-0087).\n */\n\n/*\n The grade, its budgets and its bounds are figure-model's (`figureScoreOf`), so the catalogue grades a figure as this tab\n does. The grade is the headroom against one screen's target (`LIMITS.screenInstances`), not a draw-call limit.\n*/\nexport { FIGURE_BUDGET_KEYS, FIGURE_GRADE_SCALE as GRADE_SCALE, figureGradeOf as gradeOf }\nexport type { FigureBudgetKey, FigureBudgetUse, FigureScore }\n\n/** A · B · C · D as the tab draws its scale: each grade with the bound it is computed with, and D past the last. */\nexport function gradeBoundsOf(): [string, string][] {\n return [...FIGURE_GRADE_SCALE.map(([grade, bound]): [string, string] => [grade, `≤ ${bound * 100}%`]), ['D', '> 100%']]\n}\n\nexport type FigureAxisKey = 'scale' | 'consistency' | 'reuse' | 'detail' | 'reactive' | 'readable'\n\n/** One maturity axis. */\nexport interface FigureMaturityAxis {\n key: FigureAxisKey\n /** 0–1. Absent when the axis cannot be measured. */\n ratio?: number\n reading?: string\n /** A reading that is words, not a number. */\n readingKey?: string\n because?: string\n /** Why the axis is not measured. When present there is no ratio — an unmeasured axis is not a zero. */\n blocked?: string\n}\n\n/** Instances on one screen, and what each series costs at that count. */\nexport interface FigureCurvePoint {\n instances: number\n triangles: number\n drawCalls: number\n /** Vertex buffers: one per distinct shape, shared by every instance of the same size. */\n geometries: number\n materials: number\n}\n\nexport interface FigureReport {\n cost: FigureCost\n capacity: FigureCapacity\n score: FigureScore\n /** Distinct shapes and materials among the drawn bodies — the 「그리는 비용」 rows. */\n distinctShapes: number\n distinctMaterials: number\n reuse: { distinct: number; parts: number; saved: number }\n axes: FigureMaturityAxis[]\n curve: FigureCurvePoint[]\n}\n\n/** The board target for the scale axis: 500 assets on one drawing (design document §4.15). */\nexport const BOARD_ASSETS = 500\n\n/**\n * The report for one asset, or nothing when no body is drawn — then there is nothing to measure, and the screen\n * says so rather than drawing zeros.\n *\n * Evaluated at the asset's own design and state defaults, as `figureCostOf` is.\n */\nexport function figureReportOf(asset: FigureAsset): FigureReport | undefined {\n const cost = figureCostOf(asset)\n const capacity = capacityFrom(cost.groups, cost.triangles)\n if (!capacity) return undefined\n\n const drawn = compileFigureAsset(asset)\n .evaluate()\n .geometry.filter(body => body.visible !== false)\n const plan = compileFigureDocument(asset.document)\n const writers = figureWritersOf(asset)\n\n const shapes = new Set(drawn.map(shapeKeyOf))\n const materials = new Set(drawn.map(materialKeyOf))\n\n const score = figureScoreOf(asset)!\n\n const reuse = { distinct: shapes.size, parts: drawn.length, saved: drawn.length - shapes.size }\n\n const axes: FigureMaturityAxis[] = [\n {\n key: 'scale',\n // The board target filled is 1; room beyond it is better spent on the other axes, so it does not count more.\n ratio: Math.min(1, capacity.instances / BOARD_ASSETS),\n reading: String(capacity.instances),\n because: 'figure.text.maturity-scale-because'\n },\n consistency(asset, materials.size),\n {\n key: 'reuse',\n // A low distinct-to-parts ratio is much reuse; turned over so that more is higher.\n ratio: reuse.parts === 0 ? 0 : 1 - reuse.distinct / reuse.parts,\n reading: String(reuse.saved),\n because: 'figure.text.maturity-reuse-because'\n },\n { key: 'detail', blocked: 'figure.text.maturity-blocked-no-detail-level' },\n { key: 'reactive', blocked: 'figure.text.maturity-blocked-no-binding' },\n readable(asset, plan, drawn, writers)\n ]\n\n return {\n cost,\n capacity,\n score,\n distinctShapes: shapes.size,\n distinctMaterials: materials.size,\n reuse,\n axes,\n curve: decadeSteps(1, 10000).map(instances => ({\n instances,\n triangles: cost.triangles * instances,\n drawCalls: cost.groups * instances,\n geometries: shapes.size,\n materials: materials.size\n }))\n }\n}\n\n/**\n * The key things-scene shares a body's geometry by (`figure-geometry.ts` `keyOf`): the operation, what is not in its\n * numbers (the axis, the kind of section, which ends of an inside are open), its numbers to a micrometre, and segments\n * (12 when unset).\n */\nexport function shapeKeyOf(body: FigureAssetGeometry | FigureGeometry): string {\n if (!('shape' in body)) {\n // A scalar body has no mesh of its own; it is still one drawn body, told apart by what it declares.\n const dims = Object.keys(body.dimensions).sort().map(k => `${k}=${body.dimensions[k]}`).join(',')\n return `${body.provider}|${dims}`\n }\n const shape = body.shape\n const round = (v: number) => Math.round(v * 1e6) / 1e6\n const dims = Object.keys(shape.dimensions)\n .sort()\n .map(k => `${k}=${round(shape.dimensions[k]!)}`)\n .join(',')\n const e = shape.extrusion,\n c = shape.cavity,\n r = shape.revolution\n const l = shape.loft\n const meaning = e\n ? `${e.axis}:${e.section.kind}:${c ? `${c.start === 'open' ? 'o' : 'c'}${c.end === 'open' ? 'o' : 'c'}` : '-'}`\n : r\n ? `${r.axis}:${r.profile.kind}`\n : l\n ? `${l.axis}:point`\n : ''\n const segments = (body as { segments?: number }).segments ?? 12\n return `${shape.provider}|${meaning}|${dims}|s${segments}`\n}\n\n/**\n * The key things-scene shares a material by (`figure-rig.ts` `materialFor`), within one asset: token, preset,\n * transparency, and the light when it is on. The colour follows from the token, so it is not a second key.\n */\nexport function materialKeyOf(body: FigureAssetGeometry): string {\n return figureMaterialKeyOf(body)\n}\n\n/**\n * Does it look like one set — baselines 3 and 4, three checks.\n *\n * Two of them hold by construction: the material has no surface field, so there is no texture, and the\n * format refuses a segment count outside the presets (`compileFigureAsset`, `QUALITY`). They are still counted, so\n * the ratio stays one fault in three.\n */\nfunction consistency(asset: FigureAsset, distinctMaterials: number): FigureMaturityAxis {\n const textures = 0\n const offPreset = asset.appearance.filter(look => look.segments !== undefined && !SEGMENT_PRESETS.includes(look.segments)).length\n const faults = (textures > 0 ? 1 : 0) + (offPreset > 0 ? 1 : 0) + (distinctMaterials > LIMITS.distinctMaterials ? 1 : 0)\n return {\n key: 'consistency',\n ratio: (3 - faults) / 3,\n readingKey: faults === 0 ? 'figure.text.maturity-consistency-clean' : 'figure.text.maturity-consistency-faults',\n because: 'figure.text.maturity-consistency-because'\n }\n}\n\n/** Seen from above, these do not fill their footprint box, by provider name. */\n/** Round seen from above: a circle or an ellipse pushed along Y, anything turned about Y. */\nconst roundFootprint = (shape: { extrusion?: { axis: string; section: { kind: string } }; revolution?: { axis: string } }) =>\n (shape.extrusion?.axis === 'y' && shape.extrusion.section.kind === 'ellipse') || shape.revolution?.axis === 'y'\n\n/**\n * Can it be told apart from above — baseline 1.\n *\n * Viewpoint entropy (Vázquez et al.) over the top view, counted by colour region rather than by face so that a\n * finer segment count does not raise it: H = −Σ p·log p over each material's share of the footprint plus the\n * background, divided by log(`LIMITS.distinctMaterials` + 1), the most this measure can reach.\n *\n * The footprint is the base box: the space the asset declares when it declares one (ADR-0044's box is the model's\n * occupancy), otherwise the drawn bodies' own extent. Bodies are their axis-aligned world boxes\n * (`figureWorldBoxesOf`, the gate's reading); the higher one covers the lower.\n */\nfunction readable(\n asset: FigureAsset,\n plan: ReturnType<typeof compileFigureDocument>,\n drawn: FigureAssetGeometry[],\n writers: Map<string, string>\n): FigureMaturityAxis {\n const placed = drawn\n .filter(body => 'pose' in body)\n // One placed, drawn body gives exactly one box; boxes are taken one by one to keep each with its material.\n .map(body => ({ body, box: figureWorldBoxesOf([body], writers)[0]! }))\n if (placed.length === 0) return { key: 'readable', blocked: 'figure.text.maturity-blocked-no-parts' }\n\n let frame: { x0: number; x1: number; z0: number; z1: number }\n if (asset.occupancy) {\n const values = plan.evaluate({ ...asset.designInputs, ...asset.stateDefaults }).values\n const at = (ref: string) => values[ref] as number\n const b = asset.occupancy.bounds\n frame = { x0: at(b.x.min), x1: at(b.x.max), z0: at(b.z.min), z1: at(b.z.max) }\n } else {\n frame = { x0: Infinity, x1: -Infinity, z0: Infinity, z1: -Infinity }\n for (const { box } of placed) {\n frame.x0 = Math.min(frame.x0, box.centre.x - box.extent.x / 2)\n frame.x1 = Math.max(frame.x1, box.centre.x + box.extent.x / 2)\n frame.z0 = Math.min(frame.z0, box.centre.z - box.extent.z / 2)\n frame.z1 = Math.max(frame.z1, box.centre.z + box.extent.z / 2)\n }\n }\n\n const regions = topViewRegions(placed, frame)\n if (regions.total === 0) return { key: 'readable', blocked: 'figure.text.maturity-blocked-no-parts' }\n\n const shares = [...regions.byMaterial.values(), regions.background].map(area => area / regions.footprint).filter(share => share > 0)\n const entropy = -shares.reduce((sum, p) => sum + p * Math.log(p), 0)\n const ceiling = Math.log(LIMITS.distinctMaterials + 1)\n return {\n key: 'readable',\n // Clamped both ways: one region alone gives −0, which is not a reading anyone should see.\n ratio: Math.max(0, Math.min(1, entropy / ceiling)),\n reading: String(regions.byMaterial.size),\n because: 'figure.text.maturity-readable-because'\n }\n}\n\n/** Which material shows from above, on a 64 × 64 grid over the footprint, over world boxes. */\nfunction topViewRegions(\n placed: { body: FigureAssetGeometry; box: ReturnType<typeof figureWorldBoxesOf>[number] }[],\n frame: { x0: number; x1: number; z0: number; z1: number }\n) {\n const GRID = 64\n const cells = new Array<string | null>(GRID * GRID).fill(null)\n const height = new Float64Array(GRID * GRID)\n const sx = GRID / Math.max(frame.x1 - frame.x0, 1e-6)\n const sz = GRID / Math.max(frame.z1 - frame.z0, 1e-6)\n\n for (const { body, box } of placed) {\n const top = box.centre.y + box.extent.y / 2\n const key = materialKeyOf(body)\n const x0 = Math.max(0, Math.floor((box.centre.x - box.extent.x / 2 - frame.x0) * sx))\n const x1 = Math.min(GRID, Math.ceil((box.centre.x + box.extent.x / 2 - frame.x0) * sx))\n const y0 = Math.max(0, Math.floor((box.centre.z - box.extent.z / 2 - frame.z0) * sz))\n const y1 = Math.min(GRID, Math.ceil((box.centre.z + box.extent.z / 2 - frame.z0) * sz))\n const round = 'shape' in body && roundFootprint(body.shape as never)\n\n for (let y = y0; y < y1; y++) {\n for (let x = x0; x < x1; x++) {\n // A round body does not fill its box; the corners are cut.\n if (round) {\n const cx = (x + 0.5 - (x0 + x1) / 2) / ((x1 - x0) / 2 || 1)\n const cy = (y + 0.5 - (y0 + y1) / 2) / ((y1 - y0) / 2 || 1)\n if (cx * cx + cy * cy > 1) continue\n }\n const i = y * GRID + x\n if (cells[i] === null || top > height[i]!) {\n cells[i] = key\n height[i] = top\n }\n }\n }\n }\n\n const byMaterial = new Map<string, number>()\n let covered = 0\n for (const key of cells) {\n if (key === null) continue\n covered++\n byMaterial.set(key, (byMaterial.get(key) ?? 0) + 1)\n }\n return { byMaterial, total: covered, background: GRID * GRID - covered, footprint: GRID * GRID }\n}\n\n/** 1 · 2 · 5 per decade: even steps on a log axis. */\nexport function decadeSteps(from: number, to: number): number[] {\n const out: number[] = []\n for (let decade = 1; decade <= to; decade *= 10) {\n for (const m of [1, 2, 5]) {\n const v = decade * m\n if (v >= from && v <= to) out.push(v)\n }\n }\n if (out.length === 0 || out[out.length - 1] !== to) out.push(to)\n return [...new Set(out)].sort((a, b) => a - b)\n}\n\n// ─── The trend chart ─────────────────────────────────────────────────────────\n\nexport type FigureCurveSeries = 'triangles' | 'drawCalls' | 'geometries' | 'materials'\n\n/**\n * The four lines: two that grow with the instance count and two that stay flat — the flat ones are what the\n * instances share. Materials are dashed and drawn last, so a line under them still shows where the two meet.\n */\nexport const CURVE_SERIES: readonly { key: FigureCurveSeries; flat: boolean; dashed?: boolean }[] = [\n { key: 'triangles', flat: false },\n { key: 'drawCalls', flat: false },\n { key: 'geometries', flat: true },\n { key: 'materials', flat: true, dashed: true }\n]\n\n/** The chart's size. The chart is shown at this size in a sheet; shrunk into the side, its words are unreadable. */\nexport const CURVE_SIZE = { width: 680, height: 380, pad: { top: 52, right: 208, bottom: 44, left: 62 } } as const\n\nexport interface FigureCurveLayout {\n xTicks: { x: number; label: string }[]\n yTicks: { y: number; label: string }[]\n lines: { key: FigureCurveSeries; d: string; flat: boolean; dashed: boolean; last: number }[]\n /** The value the flat lines share when they lie on one another, so the screen can say why one line is missing. */\n overlap?: number\n}\n\nconst log10 = (v: number) => Math.log(Math.max(v, 1)) / Math.LN10\n\n/** 1, 10, 100 … written short. */\nexport function shortNumber(v: number): string {\n if (v >= 1_000_000) return `${v / 1_000_000}M`\n if (v >= 1_000) return `${v / 1_000}k`\n return String(v)\n}\n\n/** Where the chart puts each line and tick. Both axes are logarithmic. */\nexport function curveLayout(points: FigureCurvePoint[]): FigureCurveLayout | undefined {\n if (points.length === 0) return undefined\n const { width, height, pad } = CURVE_SIZE\n const minX = points[0]!.instances\n const maxX = points[points.length - 1]!.instances\n let maxY = 1\n for (const p of points) for (const s of CURVE_SERIES) maxY = Math.max(maxY, p[s.key])\n\n const plotW = width - pad.left - pad.right\n const plotH = height - pad.top - pad.bottom\n const spanX = Math.max(log10(maxX) - log10(minX), 1e-9)\n const spanY = Math.max(log10(maxY), 1e-9)\n const px = (v: number) => pad.left + ((log10(v) - log10(minX)) / spanX) * plotW\n const py = (v: number) => pad.top + plotH - (log10(v) / spanY) * plotH\n\n const yTicks: FigureCurveLayout['yTicks'] = []\n for (let e = 0; Math.pow(10, e) <= maxY * 1.001; e++) yTicks.push({ y: py(Math.pow(10, e)), label: shortNumber(Math.pow(10, e)) })\n const xTicks: FigureCurveLayout['xTicks'] = []\n for (let e = 0; Math.pow(10, e) <= maxX * 1.001; e++) {\n const v = Math.pow(10, e)\n if (v >= minX) xTicks.push({ x: px(v), label: shortNumber(v) })\n }\n\n const last = points[points.length - 1]!\n const lines = CURVE_SERIES.map(s => ({\n key: s.key,\n d: points.map((p, i) => `${i === 0 ? 'M' : 'L'}${px(p.instances).toFixed(1)},${py(p[s.key]).toFixed(1)}`).join(' '),\n flat: s.flat,\n dashed: !!s.dashed,\n last: last[s.key]\n }))\n const flat = new Set(CURVE_SERIES.filter(s => s.flat).map(s => last[s.key]))\n return { xTicks, yTicks, lines, overlap: flat.size === 1 ? [...flat][0] : undefined }\n}\n\n/** What the parts list shows under its title: the cost, how many fit, the grade and what decides it. */\nexport interface FigureBudgetLine {\n triangles: number\n groups: number\n instances: number\n grade: string\n tightest: { key: string; used: number; limit: number }\n}\n\n/**\n * What the verdict tab measures of the figure on screen once it settles: the report, the bodies there are to fit the\n * space to (drawn or hidden -- a hidden part is still a part to measure), and what it tells the page: the count for its\n * tab and the parts list's line, from the same report. A source the format refuses has no report.\n */\nexport function verdictMeasureOf(asset: FigureAsset | undefined): {\n report?: FigureReport\n bodies: number\n told: { instances?: number; budget?: FigureBudgetLine }\n} {\n let report: FigureReport | undefined\n let bodies = 0\n try {\n const cost = asset ? figureCostOf(asset) : undefined\n bodies = cost ? cost.groups + cost.hidden : 0\n report = asset ? figureReportOf(asset) : undefined\n } catch {\n /* A source the format refuses has no report; the server's finding says why. */\n report = undefined\n }\n return { report, bodies, told: { instances: report?.capacity.instances, budget: budgetOf(report) } }\n}\n\nexport function budgetOf(report: FigureReport | undefined): FigureBudgetLine | undefined {\n if (!report) return undefined\n const { tightest } = report.score\n return {\n triangles: report.cost.triangles,\n groups: report.cost.groups,\n instances: report.capacity.instances,\n grade: report.score.grade,\n tightest: { key: tightest.key, used: tightest.used, limit: Math.floor(tightest.limit) }\n }\n}\n"]}
@@ -0,0 +1,47 @@
1
+ import type { FigurePrimitiveCreation } from '@hatiolab/figure-model';
2
+ type Vec = {
3
+ x: number;
4
+ y: number;
5
+ z: number;
6
+ };
7
+ type Box = {
8
+ min: Vec;
9
+ max: Vec;
10
+ };
11
+ /** What `uploadFigureMesh` answers: the file's hash and what the server read of it. */
12
+ export interface MeshUpload {
13
+ hash: string;
14
+ summary: {
15
+ bounds: Box;
16
+ triangles: number;
17
+ primitives: number;
18
+ unit: 'm';
19
+ nodes: Array<{
20
+ index: number;
21
+ name: string;
22
+ parent: number | null;
23
+ bounds: Box | null;
24
+ triangles: number;
25
+ primitives: number;
26
+ position: Vec;
27
+ rotation: Vec;
28
+ refused?: 'no-mesh' | 'sheared';
29
+ }>;
30
+ };
31
+ }
32
+ /** What the author can make a part of: the whole file first, then each node that holds a mesh and has a frame. */
33
+ export declare function meshChoicesOf(upload: MeshUpload): Array<{
34
+ node?: number;
35
+ name: string;
36
+ triangles: number;
37
+ }>;
38
+ /** A part id from a node's name: letter-led, letters, digits, `_` and `-`; another number when it is taken. */
39
+ export declare function meshPartIdOf(name: string, taken: ReadonlySet<string>): string;
40
+ /**
41
+ * The part: its bounds and counts as the server read them, its size the reach along its longest axis (so it is 1:1),
42
+ * and -- for a node -- standing where the node stood in the file, so a crane taken apart node by node stands as it did.
43
+ */
44
+ export declare function meshPartOf(upload: MeshUpload, choice: {
45
+ node?: number;
46
+ }, id: string): FigurePrimitiveCreation;
47
+ export {};
@@ -0,0 +1,47 @@
1
+ /** What the author can make a part of: the whole file first, then each node that holds a mesh and has a frame. */
2
+ export function meshChoicesOf(upload) {
3
+ return [
4
+ { name: '', triangles: upload.summary.triangles },
5
+ ...upload.summary.nodes.filter(n => n.bounds && !n.refused).map(n => ({ node: n.index, name: n.name, triangles: n.triangles }))
6
+ ];
7
+ }
8
+ /** A part id from a node's name: letter-led, letters, digits, `_` and `-`; another number when it is taken. */
9
+ export function meshPartIdOf(name, taken) {
10
+ const cleaned = name.replace(/[^a-zA-Z0-9_-]+/g, '-').replace(/^[^a-zA-Z]+/, '').replace(/-+$/, '');
11
+ const base = cleaned || 'mesh';
12
+ if (!taken.has(base))
13
+ return base;
14
+ let n = 2;
15
+ while (taken.has(`${base}-${n}`))
16
+ n++;
17
+ return `${base}-${n}`;
18
+ }
19
+ /**
20
+ * The part: its bounds and counts as the server read them, its size the reach along its longest axis (so it is 1:1),
21
+ * and -- for a node -- standing where the node stood in the file, so a crane taken apart node by node stands as it did.
22
+ */
23
+ export function meshPartOf(upload, choice, id) {
24
+ const node = choice.node === undefined ? undefined : upload.summary.nodes.find(n => n.index === choice.node);
25
+ if (choice.node !== undefined && (!node?.bounds || node.refused))
26
+ throw new Error(`node ${choice.node} of the file cannot be a part`);
27
+ const bounds = node ? node.bounds : upload.summary.bounds;
28
+ const size = Math.max(bounds.max.x - bounds.min.x, bounds.max.y - bounds.min.y, bounds.max.z - bounds.min.z);
29
+ const turned = node && (node.rotation.x || node.rotation.y || node.rotation.z);
30
+ return {
31
+ kind: 'mesh',
32
+ id,
33
+ dimensions: { size },
34
+ mesh: {
35
+ asset: upload.hash,
36
+ format: 'glb',
37
+ unit: upload.summary.unit,
38
+ ...(node ? { node: node.index } : {}),
39
+ bounds,
40
+ triangles: node ? node.triangles : upload.summary.triangles,
41
+ primitives: node ? node.primitives : upload.summary.primitives
42
+ },
43
+ position: node ? { ...node.position } : { x: 0, y: 0, z: 0 },
44
+ ...(turned ? { rotation: { ...node.rotation } } : {})
45
+ };
46
+ }
47
+ //# sourceMappingURL=mesh-import.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mesh-import.js","sourceRoot":"","sources":["../../client/modeller/mesh-import.ts"],"names":[],"mappings":"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","sourcesContent":["/*\n * A GLB made into a mesh part (ADR-0129, figure-model contract §13). The server reads the file when it is uploaded and\n * answers its hash and what it holds; this turns that answer and the author's choice -- the whole file, or one node of it\n * -- into the part figure-model adds. Kept free of Lit and the network so node tests read it directly.\n */\nimport type { FigurePrimitiveCreation } from '@hatiolab/figure-model'\n\ntype Vec = { x: number; y: number; z: number }\ntype Box = { min: Vec; max: Vec }\n\n/** What `uploadFigureMesh` answers: the file's hash and what the server read of it. */\nexport interface MeshUpload {\n hash: string\n summary: {\n bounds: Box\n triangles: number\n primitives: number\n unit: 'm'\n nodes: Array<{\n index: number\n name: string\n parent: number | null\n bounds: Box | null\n triangles: number\n primitives: number\n position: Vec\n rotation: Vec\n refused?: 'no-mesh' | 'sheared'\n }>\n }\n}\n\n/** What the author can make a part of: the whole file first, then each node that holds a mesh and has a frame. */\nexport function meshChoicesOf(upload: MeshUpload): Array<{ node?: number; name: string; triangles: number }> {\n return [\n { name: '', triangles: upload.summary.triangles },\n ...upload.summary.nodes.filter(n => n.bounds && !n.refused).map(n => ({ node: n.index, name: n.name, triangles: n.triangles }))\n ]\n}\n\n/** A part id from a node's name: letter-led, letters, digits, `_` and `-`; another number when it is taken. */\nexport function meshPartIdOf(name: string, taken: ReadonlySet<string>): string {\n const cleaned = name.replace(/[^a-zA-Z0-9_-]+/g, '-').replace(/^[^a-zA-Z]+/, '').replace(/-+$/, '')\n const base = cleaned || 'mesh'\n if (!taken.has(base)) return base\n let n = 2\n while (taken.has(`${base}-${n}`)) n++\n return `${base}-${n}`\n}\n\n/**\n * The part: its bounds and counts as the server read them, its size the reach along its longest axis (so it is 1:1),\n * and -- for a node -- standing where the node stood in the file, so a crane taken apart node by node stands as it did.\n */\nexport function meshPartOf(upload: MeshUpload, choice: { node?: number }, id: string): FigurePrimitiveCreation {\n const node = choice.node === undefined ? undefined : upload.summary.nodes.find(n => n.index === choice.node)\n if (choice.node !== undefined && (!node?.bounds || node.refused)) throw new Error(`node ${choice.node} of the file cannot be a part`)\n const bounds = node ? node.bounds! : upload.summary.bounds\n const size = Math.max(bounds.max.x - bounds.min.x, bounds.max.y - bounds.min.y, bounds.max.z - bounds.min.z)\n const turned = node && (node.rotation.x || node.rotation.y || node.rotation.z)\n return {\n kind: 'mesh',\n id,\n dimensions: { size },\n mesh: {\n asset: upload.hash,\n format: 'glb',\n unit: upload.summary.unit,\n ...(node ? { node: node.index } : {}),\n bounds,\n triangles: node ? node.triangles : upload.summary.triangles,\n primitives: node ? node.primitives : upload.summary.primitives\n },\n position: node ? { ...node.position } : { x: 0, y: 0, z: 0 },\n ...(turned ? { rotation: { ...node!.rotation } } : {})\n }\n}\n"]}
@@ -6,3 +6,8 @@ export declare const MODELLER = "figure-modeller";
6
6
  export declare function modellerPathOf(figure?: {
7
7
  id?: string;
8
8
  }): string;
9
+ /**
10
+ * Where one released version downloads as a package file, by its release reference {namespace}/{type}@{version}
11
+ * (ADR-0114) -- or undefined before the figure has a full name.
12
+ */
13
+ export declare function packageHrefOf(contextPath: string, namespace: string | null | undefined, type: string | null | undefined, version: number): string | undefined;
@@ -6,4 +6,13 @@ export const MODELLER = 'figure-modeller';
6
6
  export function modellerPathOf(figure) {
7
7
  return figure?.id ? `${MODELLER}/${figure.id}` : MODELLER;
8
8
  }
9
+ /**
10
+ * Where one released version downloads as a package file, by its release reference {namespace}/{type}@{version}
11
+ * (ADR-0114) -- or undefined before the figure has a full name.
12
+ */
13
+ export function packageHrefOf(contextPath, namespace, type, version) {
14
+ if (!namespace || !type)
15
+ return undefined;
16
+ return `${contextPath}/figure-package?refs=${encodeURIComponent(`${namespace}/${type}@${version}`)}`;
17
+ }
9
18
  //# sourceMappingURL=modeller-route.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"modeller-route.js","sourceRoot":"","sources":["../../client/modeller/modeller-route.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,CAAC,MAAM,QAAQ,GAAG,iBAAiB,CAAA;AAEzC,MAAM,UAAU,cAAc,CAAC,MAAwB;IACrD,OAAO,MAAM,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,QAAQ,IAAI,MAAM,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAA;AAC3D,CAAC","sourcesContent":["/**\n * The one modeller. The catalogue, a new figure and an old address all open the same page. `figure-modeller`\n * stays as an alias so a link written under that name still lands.\n */\nexport const MODELLER = 'figure-modeller'\n\nexport function modellerPathOf(figure?: { id?: string }): string {\n return figure?.id ? `${MODELLER}/${figure.id}` : MODELLER\n}\n"]}
1
+ {"version":3,"file":"modeller-route.js","sourceRoot":"","sources":["../../client/modeller/modeller-route.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,CAAC,MAAM,QAAQ,GAAG,iBAAiB,CAAA;AAEzC,MAAM,UAAU,cAAc,CAAC,MAAwB;IACrD,OAAO,MAAM,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,QAAQ,IAAI,MAAM,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAA;AAC3D,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,aAAa,CAAC,WAAmB,EAAE,SAAoC,EAAE,IAA+B,EAAE,OAAe;IACvI,IAAI,CAAC,SAAS,IAAI,CAAC,IAAI;QAAE,OAAO,SAAS,CAAA;IACzC,OAAO,GAAG,WAAW,wBAAwB,kBAAkB,CAAC,GAAG,SAAS,IAAI,IAAI,IAAI,OAAO,EAAE,CAAC,EAAE,CAAA;AACtG,CAAC","sourcesContent":["/**\n * The one modeller. The catalogue, a new figure and an old address all open the same page. `figure-modeller`\n * stays as an alias so a link written under that name still lands.\n */\nexport const MODELLER = 'figure-modeller'\n\nexport function modellerPathOf(figure?: { id?: string }): string {\n return figure?.id ? `${MODELLER}/${figure.id}` : MODELLER\n}\n\n/**\n * Where one released version downloads as a package file, by its release reference {namespace}/{type}@{version}\n * (ADR-0114) -- or undefined before the figure has a full name.\n */\nexport function packageHrefOf(contextPath: string, namespace: string | null | undefined, type: string | null | undefined, version: number): string | undefined {\n if (!namespace || !type) return undefined\n return `${contextPath}/figure-package?refs=${encodeURIComponent(`${namespace}/${type}@${version}`)}`\n}\n"]}
@@ -0,0 +1,14 @@
1
+ import type { FigureFace } from '@hatiolab/figure-model';
2
+ import type { FigureFigureFacts } from './figure-facts.js';
3
+ /**
4
+ * The mounting face the properties tab offers: the part and face picked in its lists, else the one set, else where the
5
+ * figure meets its plane (`suggested`) -- a conveyor's legs, not its bed (walk 1, 2026-09-26) -- else the first part.
6
+ * A part no longer in the figure is passed over.
7
+ */
8
+ export declare function offeredMountingOf(facts: Pick<FigureFigureFacts, 'parts' | 'mounting' | 'suggested'>, picked?: {
9
+ part?: string;
10
+ face?: FigureFace;
11
+ }): {
12
+ part?: string;
13
+ face: FigureFace;
14
+ };
@@ -0,0 +1,10 @@
1
+ /**
2
+ * The mounting face the properties tab offers: the part and face picked in its lists, else the one set, else where the
3
+ * figure meets its plane (`suggested`) -- a conveyor's legs, not its bed (walk 1, 2026-09-26) -- else the first part.
4
+ * A part no longer in the figure is passed over.
5
+ */
6
+ export function offeredMountingOf(facts, picked = {}) {
7
+ const part = [picked.part, facts.mounting?.part, facts.suggested?.part, facts.parts[0]].find(one => one && facts.parts.includes(one));
8
+ return { part, face: picked.face ?? facts.mounting?.face ?? facts.suggested?.face ?? 'bottom' };
9
+ }
10
+ //# sourceMappingURL=mounting-part.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mounting-part.js","sourceRoot":"","sources":["../../client/modeller/mounting-part.ts"],"names":[],"mappings":"AAGA;;;;GAIG;AACH,MAAM,UAAU,iBAAiB,CAC/B,KAAkE,EAClE,SAA+C,EAAE;IAEjD,MAAM,IAAI,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,QAAQ,EAAE,IAAI,EAAE,KAAK,CAAC,SAAS,EAAE,IAAI,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,KAAK,CAAC,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAA;IACrI,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,IAAI,KAAK,CAAC,QAAQ,EAAE,IAAI,IAAI,KAAK,CAAC,SAAS,EAAE,IAAI,IAAI,QAAQ,EAAE,CAAA;AACjG,CAAC","sourcesContent":["import type { FigureFace } from '@hatiolab/figure-model'\nimport type { FigureFigureFacts } from './figure-facts.js'\n\n/**\n * The mounting face the properties tab offers: the part and face picked in its lists, else the one set, else where the\n * figure meets its plane (`suggested`) -- a conveyor's legs, not its bed (walk 1, 2026-09-26) -- else the first part.\n * A part no longer in the figure is passed over.\n */\nexport function offeredMountingOf(\n facts: Pick<FigureFigureFacts, 'parts' | 'mounting' | 'suggested'>,\n picked: { part?: string; face?: FigureFace } = {}\n): { part?: string; face: FigureFace } {\n const part = [picked.part, facts.mounting?.part, facts.suggested?.part, facts.parts[0]].find(one => one && facts.parts.includes(one))\n return { part, face: picked.face ?? facts.mounting?.face ?? facts.suggested?.face ?? 'bottom' }\n}\n"]}
@@ -0,0 +1,12 @@
1
+ /** What came back for a question: its answer, or why there is none. */
2
+ export type FigureOutcome<T> = {
3
+ answer: T;
4
+ } | {
5
+ failure: unknown;
6
+ };
7
+ /**
8
+ * Questions asked again while an earlier one is still out (a figure edited while the server judges it): answers can
9
+ * come back out of order, and only the newest question's lands -- its answer or its failure alike. An older one arriving
10
+ * late is dropped, so it never covers the newer one.
11
+ */
12
+ export declare function newestAnswer<T>(): (question: () => Promise<T>, land: (outcome: FigureOutcome<T>) => void) => Promise<void>;
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Questions asked again while an earlier one is still out (a figure edited while the server judges it): answers can
3
+ * come back out of order, and only the newest question's lands -- its answer or its failure alike. An older one arriving
4
+ * late is dropped, so it never covers the newer one.
5
+ */
6
+ export function newestAnswer() {
7
+ let asked = 0;
8
+ return async (question, land) => {
9
+ const mine = ++asked;
10
+ let outcome;
11
+ try {
12
+ outcome = { answer: await question() };
13
+ }
14
+ catch (failure) {
15
+ outcome = { failure };
16
+ }
17
+ if (mine === asked)
18
+ land(outcome);
19
+ };
20
+ }
21
+ //# sourceMappingURL=newest-answer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"newest-answer.js","sourceRoot":"","sources":["../../client/modeller/newest-answer.ts"],"names":[],"mappings":"AAGA;;;;GAIG;AACH,MAAM,UAAU,YAAY;IAC1B,IAAI,KAAK,GAAG,CAAC,CAAA;IACb,OAAO,KAAK,EAAE,QAA0B,EAAE,IAAyC,EAAiB,EAAE;QACpG,MAAM,IAAI,GAAG,EAAE,KAAK,CAAA;QACpB,IAAI,OAAyB,CAAA;QAC7B,IAAI,CAAC;YACH,OAAO,GAAG,EAAE,MAAM,EAAE,MAAM,QAAQ,EAAE,EAAE,CAAA;QACxC,CAAC;QAAC,OAAO,OAAO,EAAE,CAAC;YACjB,OAAO,GAAG,EAAE,OAAO,EAAE,CAAA;QACvB,CAAC;QACD,IAAI,IAAI,KAAK,KAAK;YAAE,IAAI,CAAC,OAAO,CAAC,CAAA;IACnC,CAAC,CAAA;AACH,CAAC","sourcesContent":["/** What came back for a question: its answer, or why there is none. */\nexport type FigureOutcome<T> = { answer: T } | { failure: unknown }\n\n/**\n * Questions asked again while an earlier one is still out (a figure edited while the server judges it): answers can\n * come back out of order, and only the newest question's lands -- its answer or its failure alike. An older one arriving\n * late is dropped, so it never covers the newer one.\n */\nexport function newestAnswer<T>() {\n let asked = 0\n return async (question: () => Promise<T>, land: (outcome: FigureOutcome<T>) => void): Promise<void> => {\n const mine = ++asked\n let outcome: FigureOutcome<T>\n try {\n outcome = { answer: await question() }\n } catch (failure) {\n outcome = { failure }\n }\n if (mine === asked) land(outcome)\n }\n}\n"]}
@@ -1,5 +1,7 @@
1
1
  import type { FigureAsset } from '@hatiolab/figure-model';
2
2
  export declare const PREVIEW_FACTOR = 2;
3
+ /** The type the preview registers the figure under: this figure's own, never a real type a board uses. */
4
+ export declare function previewTypeOf(context: string): string;
3
5
  export declare const PREVIEW_WAYS: readonly {
4
6
  name: string;
5
7
  axes: readonly ('x' | 'y' | 'z')[];
@@ -1,6 +1,10 @@
1
1
  import { compileFigureAsset, figureOccupiedBoxesOf, figureWritersOf, FIGURE_INSTANCE_SIZE_INPUTS } from '@hatiolab/figure-model';
2
2
  /* The preview's arithmetic, apart from the element so it is tested without a browser (see figure-preview.ts). */
3
3
  export const PREVIEW_FACTOR = 2;
4
+ /** The type the preview registers the figure under: this figure's own, never a real type a board uses. */
5
+ export function previewTypeOf(context) {
6
+ return `figure-preview-${context || 'new'}`;
7
+ }
4
8
  export const PREVIEW_WAYS = [
5
9
  { name: 'base', axes: [] },
6
10
  { name: 'x', axes: ['x'] },
@@ -1 +1 @@
1
- {"version":3,"file":"preview-model.js","sourceRoot":"","sources":["../../client/modeller/preview-model.ts"],"names":[],"mappings":"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","sourcesContent":["import { compileFigureAsset, figureOccupiedBoxesOf, figureWritersOf, FIGURE_INSTANCE_SIZE_INPUTS } from '@hatiolab/figure-model'\nimport type { FigureAsset } from '@hatiolab/figure-model'\n\n/* The preview's arithmetic, apart from the element so it is tested without a browser (see figure-preview.ts). */\n\nexport const PREVIEW_FACTOR = 2\n\nexport const PREVIEW_WAYS: readonly { name: string; axes: readonly ('x' | 'y' | 'z')[] }[] = [\n { name: 'base', axes: [] },\n { name: 'x', axes: ['x'] },\n { name: 'y', axes: ['y'] },\n { name: 'z', axes: ['z'] },\n { name: 'x·y', axes: ['x', 'y'] },\n { name: 'x·z', axes: ['x', 'z'] },\n { name: 'y·z', axes: ['y', 'z'] },\n { name: 'x·y·z', axes: ['x', 'y', 'z'] }\n]\n\n/** The size the figure was made at: its instance size when it declares one, else the room its bodies take. */\nexport function authoredSizeOf(asset: FigureAsset): { x: number; y: number; z: number } {\n const d = asset.designInputs\n const declared = (['x', 'y', 'z'] as const).map(axis => d[FIGURE_INSTANCE_SIZE_INPUTS[axis]])\n if (declared.every(v => typeof v === 'number' && v > 0)) return { x: declared[0]!, y: declared[1]!, z: declared[2]! }\n /* No declared size: the room its bodies take up, so the instance is placed at the size it draws. */\n const boxes = figureOccupiedBoxesOf(compileFigureAsset(asset).evaluate().geometry, figureWritersOf(asset))\n const span = (axis: 'x' | 'y' | 'z') =>\n boxes.length ? Math.max(...boxes.map(b => b.centre[axis] + b.extent[axis] / 2)) - Math.min(...boxes.map(b => b.centre[axis] - b.extent[axis] / 2)) : 0\n return { x: Math.max(1, Math.round(span('x'))), y: Math.max(1, Math.round(span('y'))), z: Math.max(1, Math.round(span('z'))) }\n}\n\n/** The eight instances: where each stands on the board and how large, in the scene's words. */\nexport function previewInstances(type: string, size: { x: number; y: number; z: number }) {\n const COLUMNS = 4\n const cell = { x: size.x * PREVIEW_FACTOR * 1.25, z: size.z * PREVIEW_FACTOR * 1.25 }\n const components = PREVIEW_WAYS.map((way, at) => {\n const grow = (axis: 'x' | 'y' | 'z') => (way.axes.includes(axis) ? PREVIEW_FACTOR : 1)\n const width = Math.round(size.x * grow('x'))\n const height = Math.round(size.z * grow('z'))\n const column = at % COLUMNS\n const row = Math.floor(at / COLUMNS)\n return {\n type,\n id: `at-${way.name}`,\n left: Math.round(column * cell.x + (cell.x - width) / 2),\n top: Math.round(row * cell.z + (cell.z - height) / 2),\n width,\n height,\n /* Always written: without it the height is taken as the plan's mean and \"grow y only\" would not grow it. */\n depth: Math.round(size.y * grow('y'))\n }\n })\n return { components, board: { width: Math.round(cell.x * COLUMNS), height: Math.round(cell.z * Math.ceil(PREVIEW_WAYS.length / COLUMNS)) } }\n}\n\n\n/**\n * Where a variant asks a size the figure does not declare, the size it is drawn at instead -- as the board draws it\n * (things-scene clamps each axis to the declared range; chief architect's ruling 2026-09-25). Per variant, empty when\n * it is drawn as asked. A figure that follows its height only is drawn at its one width in the wider variants, and\n * the preview says so rather than drawing them as though they grew.\n */\nexport function previewClampsOf(asset: FigureAsset, size: { x: number; y: number; z: number }): Record<string, Array<{ axis: 'x' | 'y' | 'z'; asked: number; used: number }>> {\n const inputs = asset.document.model.inputs\n return Object.fromEntries(\n PREVIEW_WAYS.map(way => [\n way.name,\n (['x', 'y', 'z'] as const).flatMap(axis => {\n const input = inputs.find(i => i.id === FIGURE_INSTANCE_SIZE_INPUTS[axis])\n if (!input) return []\n const asked = Math.round(size[axis] * (way.axes.includes(axis) ? PREVIEW_FACTOR : 1))\n const used = Math.round(Math.min(Math.max(asked, input.min ?? -Infinity), input.max ?? Infinity))\n return used === asked ? [] : [{ axis, asked, used }]\n })\n ])\n )\n}\n\n/**\n * The part the preview's size help speaks of: the one picked in the help, else the one chosen in the editor, else the\n * first that has a size rule. A choice that is not among the parts (removed, or a part with no rule) is passed over.\n */\nexport function setupPartOf(picked: string, chosen: string, targets: string[]): string {\n return [picked, chosen].find(id => !!id && targets.includes(id)) ?? targets[0] ?? ''\n}\n"]}
1
+ {"version":3,"file":"preview-model.js","sourceRoot":"","sources":["../../client/modeller/preview-model.ts"],"names":[],"mappings":"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","sourcesContent":["import { compileFigureAsset, figureOccupiedBoxesOf, figureWritersOf, FIGURE_INSTANCE_SIZE_INPUTS } from '@hatiolab/figure-model'\nimport type { FigureAsset } from '@hatiolab/figure-model'\n\n/* The preview's arithmetic, apart from the element so it is tested without a browser (see figure-preview.ts). */\n\nexport const PREVIEW_FACTOR = 2\n\n/** The type the preview registers the figure under: this figure's own, never a real type a board uses. */\nexport function previewTypeOf(context: string): string {\n return `figure-preview-${context || 'new'}`\n}\n\nexport const PREVIEW_WAYS: readonly { name: string; axes: readonly ('x' | 'y' | 'z')[] }[] = [\n { name: 'base', axes: [] },\n { name: 'x', axes: ['x'] },\n { name: 'y', axes: ['y'] },\n { name: 'z', axes: ['z'] },\n { name: 'x·y', axes: ['x', 'y'] },\n { name: 'x·z', axes: ['x', 'z'] },\n { name: 'y·z', axes: ['y', 'z'] },\n { name: 'x·y·z', axes: ['x', 'y', 'z'] }\n]\n\n/** The size the figure was made at: its instance size when it declares one, else the room its bodies take. */\nexport function authoredSizeOf(asset: FigureAsset): { x: number; y: number; z: number } {\n const d = asset.designInputs\n const declared = (['x', 'y', 'z'] as const).map(axis => d[FIGURE_INSTANCE_SIZE_INPUTS[axis]])\n if (declared.every(v => typeof v === 'number' && v > 0)) return { x: declared[0]!, y: declared[1]!, z: declared[2]! }\n /* No declared size: the room its bodies take up, so the instance is placed at the size it draws. */\n const boxes = figureOccupiedBoxesOf(compileFigureAsset(asset).evaluate().geometry, figureWritersOf(asset))\n const span = (axis: 'x' | 'y' | 'z') =>\n boxes.length ? Math.max(...boxes.map(b => b.centre[axis] + b.extent[axis] / 2)) - Math.min(...boxes.map(b => b.centre[axis] - b.extent[axis] / 2)) : 0\n return { x: Math.max(1, Math.round(span('x'))), y: Math.max(1, Math.round(span('y'))), z: Math.max(1, Math.round(span('z'))) }\n}\n\n/** The eight instances: where each stands on the board and how large, in the scene's words. */\nexport function previewInstances(type: string, size: { x: number; y: number; z: number }) {\n const COLUMNS = 4\n const cell = { x: size.x * PREVIEW_FACTOR * 1.25, z: size.z * PREVIEW_FACTOR * 1.25 }\n const components = PREVIEW_WAYS.map((way, at) => {\n const grow = (axis: 'x' | 'y' | 'z') => (way.axes.includes(axis) ? PREVIEW_FACTOR : 1)\n const width = Math.round(size.x * grow('x'))\n const height = Math.round(size.z * grow('z'))\n const column = at % COLUMNS\n const row = Math.floor(at / COLUMNS)\n return {\n type,\n id: `at-${way.name}`,\n left: Math.round(column * cell.x + (cell.x - width) / 2),\n top: Math.round(row * cell.z + (cell.z - height) / 2),\n width,\n height,\n /* Always written: without it the height is taken as the plan's mean and \"grow y only\" would not grow it. */\n depth: Math.round(size.y * grow('y'))\n }\n })\n return { components, board: { width: Math.round(cell.x * COLUMNS), height: Math.round(cell.z * Math.ceil(PREVIEW_WAYS.length / COLUMNS)) } }\n}\n\n\n/**\n * Where a variant asks a size the figure does not declare, the size it is drawn at instead -- as the board draws it\n * (things-scene clamps each axis to the declared range; chief architect's ruling 2026-09-25). Per variant, empty when\n * it is drawn as asked. A figure that follows its height only is drawn at its one width in the wider variants, and\n * the preview says so rather than drawing them as though they grew.\n */\nexport function previewClampsOf(asset: FigureAsset, size: { x: number; y: number; z: number }): Record<string, Array<{ axis: 'x' | 'y' | 'z'; asked: number; used: number }>> {\n const inputs = asset.document.model.inputs\n return Object.fromEntries(\n PREVIEW_WAYS.map(way => [\n way.name,\n (['x', 'y', 'z'] as const).flatMap(axis => {\n const input = inputs.find(i => i.id === FIGURE_INSTANCE_SIZE_INPUTS[axis])\n if (!input) return []\n const asked = Math.round(size[axis] * (way.axes.includes(axis) ? PREVIEW_FACTOR : 1))\n const used = Math.round(Math.min(Math.max(asked, input.min ?? -Infinity), input.max ?? Infinity))\n return used === asked ? [] : [{ axis, asked, used }]\n })\n ])\n )\n}\n\n/**\n * The part the preview's size help speaks of: the one picked in the help, else the one chosen in the editor, else the\n * first that has a size rule. A choice that is not among the parts (removed, or a part with no rule) is passed over.\n */\nexport function setupPartOf(picked: string, chosen: string, targets: string[]): string {\n return [picked, chosen].find(id => !!id && targets.includes(id)) ?? targets[0] ?? ''\n}\n"]}
@@ -1,5 +1,5 @@
1
1
  type Say = (key: string, params: Record<string, string>) => string;
2
- /** The refusal in words, or nothing for any other refusal. */
2
+ /** A size range the figure cannot be drawn over, or one that leaves out its own size, in words; nothing for any other refusal. */
3
3
  export declare function sizeRangeRefusalOf(error: unknown, say: Say): string | null;
4
4
  /**
5
5
  * A link refused because the size range it would leave cannot hold: measuring again cannot help (the link is not there
@@ -27,6 +27,10 @@ export declare function inDeclaredRoom(error: unknown): boolean;
27
27
  * left is the declared space (with a way on: fit it again) and a row -- one laid along the part, or hanging in its row.
28
28
  */
29
29
  export declare function partRefusalOf(error: unknown, part: string, say: Say): string | null;
30
+ /** A part the gizmo cannot move because a joint or a fastening places it, named as the author knows it (`part`). */
31
+ export declare function placedRefusalOf(error: unknown, part: string, say: Say): string | null;
32
+ /** A part name refused: not a name, already used, or another part is named under the part. The rule is the kernel's. */
33
+ export declare function partNameRefusalOf(error: unknown, say: Say): string | null;
30
34
  /** What removing a part let go of (figure-model's `RemovalNotice`), said in one line, or nothing when it let go of nothing. */
31
35
  export declare function removalNoticeOf(notice: {
32
36
  released: Array<{
@@ -50,16 +54,33 @@ export declare function removalNoticeOf(notice: {
50
54
  } | undefined, say: Say): string | null;
51
55
  /**
52
56
  * A recipe refused at one of its steps: which step, and why -- the particular sentence when there is one (a size
53
- * range, a value's range, a placement), otherwise the kernel's code. The kernel says 「steps[2]: attach: …」.
57
+ * range, a value's range, a placement), otherwise the kernel's code. The step is the refusal's path, `steps[2]`: the
58
+ * contract's path grammar, not its English (ADR-0127 decision 6).
54
59
  */
55
60
  export declare function recipeRefusalOf(error: unknown, say: Say): string | null;
61
+ /**
62
+ * A slot layout refused (ADR-0118): the anchor, slot or value it was refused for. The layout's own findings are named
63
+ * by where they are; the editor checks them before Apply, so they rarely reach here.
64
+ */
65
+ export declare function slotLayoutRefusalOf(error: unknown, say: Say): string | null;
66
+ /**
67
+ * A refusal in the author's words when the screen has words for it, otherwise said as a refusal with its code -- never
68
+ * the kernel's English on the screen (the duplicate of a row's part showed 「EDIT_TARGET: … not a repeated template」,
69
+ * 2026-09-27).
70
+ */
56
71
  export declare function editRefusalOf(error: unknown, say: Say): string;
57
72
  /**
58
- * A value outside the range its input declares, with the range and the value given -- the kernel says
59
- * 「size.x: 6021100 outside [300,1200]」. The figure's own size is named by its axis; any other input by its range only.
60
- * The repeat pitch's refusal shares the code and has its own words (`figure.text.repeat-pitch-too-small`).
73
+ * A value outside the range its input declares, with the range and the value given. The figure's own size is named by
74
+ * its axis; any other input by its range only.
61
75
  */
62
76
  export declare function inputRangeRefusalOf(error: unknown, say: Say): string | null;
77
+ /**
78
+ * A row past its limits: a pitch so fine it would hold more copies than a row takes, a row that would expand to more
79
+ * bodies than a figure draws, or a number of copies outside what a row may have.
80
+ */
81
+ export declare function rowLimitRefusalOf(error: unknown, say: Say): string | null;
82
+ /** A row's pitch under which the figure, at the length it is authored, would hold more copies than a row takes. */
83
+ export declare function repeatPitchRefusalOf(error: unknown, say: Say): string | null;
63
84
  /**
64
85
  * Why "follow the size and keep where the figure is placed" was not applied, in the author's words (ADR-0097): the plan
65
86
  * says what it would have had to overwrite, and for a part through the plane how far. A code the screen has no words