@peter.prib/renderengine 0.15.3 → 0.16.0

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.
@@ -65391,7 +65391,73 @@ ${theirs}` : theirs;
65391
65391
  }
65392
65392
  }
65393
65393
 
65394
- const WORKBENCH_VIEWS = Object.freeze([ExecutiveView, ArchitectureView, ExploreView, DeliveryView, PortfolioView, ReplayView]);
65394
+ /** Architecture-driven predictions: cost ranges, confidence, and basin layer spend. */
65395
+ class EstimationView extends WorkbenchView {
65396
+ static id = 'estimation';
65397
+ static title = 'Estimation';
65398
+
65399
+ available() { return Boolean(this.workbench.report?.estimation); }
65400
+
65401
+ charts() {
65402
+ const est = this.workbench.report?.estimation;
65403
+ const entries = est?.entries ?? [];
65404
+ if (!entries.length) return [];
65405
+
65406
+ const charts = [
65407
+ {
65408
+ title: `Predicted cost range (${est.totals?.cost?.currency ?? 'AUD'}): minimum → maximum`,
65409
+ chartType: 'dumbbell',
65410
+ data: entries.map((e) => ({
65411
+ label: e.name,
65412
+ start: e.cost.minimum,
65413
+ end: e.cost.maximum,
65414
+ })),
65415
+ },
65416
+ {
65417
+ title: 'Confidence score (0–100%)',
65418
+ chartType: 'bar',
65419
+ data: entries.map((e) => ({
65420
+ label: e.name,
65421
+ value: e.confidence,
65422
+ })),
65423
+ },
65424
+ ];
65425
+
65426
+ const byBasin = {};
65427
+ for (const e of entries) {
65428
+ const label = `L${e.basin?.level ?? 1} ${e.basin?.name ?? 'Basin'}`;
65429
+ byBasin[label] = (byBasin[label] ?? 0) + e.cost.expected;
65430
+ }
65431
+ charts.push({
65432
+ title: 'Predicted spend by basin layer',
65433
+ chartType: 'pie',
65434
+ data: Object.entries(byBasin).map(([label, value]) => ({ label, value })),
65435
+ });
65436
+
65437
+ return charts;
65438
+ }
65439
+
65440
+ notes() {
65441
+ const est = this.workbench.report?.estimation;
65442
+ if (!est) return [];
65443
+ const tot = est.totals;
65444
+ const fmt = (n) => `$${Number(n).toLocaleString('en-US')}`;
65445
+ const notes = [
65446
+ `Total predicted spend: ${fmt(tot.cost.expected)} ${tot.cost.currency} (${fmt(tot.cost.minimum)} – ${fmt(tot.cost.maximum)}) across ${tot.initiativesCount} initiatives`,
65447
+ `Total effort: ${tot.effort.days} days (${tot.effort.storyPoints} story points, ${tot.effort.hours} hours) · ${tot.duration.workingDays} working days`,
65448
+ ];
65449
+
65450
+ const recs = (est.entries ?? []).flatMap((e) => e.recommendations ?? []);
65451
+ const uniqueRecs = [...new Set(recs)];
65452
+ for (const r of uniqueRecs) {
65453
+ notes.push(`Optimisation advice: ${r}`);
65454
+ }
65455
+
65456
+ return notes;
65457
+ }
65458
+ }
65459
+
65460
+ const WORKBENCH_VIEWS = Object.freeze([ExecutiveView, ArchitectureView, ExploreView, DeliveryView, PortfolioView, EstimationView, ReplayView]);
65395
65461
 
65396
65462
  class DecisionWorkbench {
65397
65463
  static KIND = KIND;
@@ -75531,6 +75597,7 @@ ${cells.map(c => ` <Cell${isHeader ? ' ss:StyleID="Header"' : ''}><Data ss:T
75531
75597
  exports.EmphasisRule = EmphasisRule;
75532
75598
  exports.EntityRole = EntityRole;
75533
75599
  exports.EnumerationType = EnumerationType;
75600
+ exports.EstimationView = EstimationView;
75534
75601
  exports.ExchangeFileFormat = ExchangeFileFormat;
75535
75602
  exports.ExecutiveView = ExecutiveView;
75536
75603
  exports.ExploreView = ExploreView;
@@ -61341,7 +61341,73 @@ ${theirs}` : theirs;
61341
61341
  }
61342
61342
  }
61343
61343
 
61344
- const WORKBENCH_VIEWS = Object.freeze([ExecutiveView, ArchitectureView, ExploreView, DeliveryView, PortfolioView, ReplayView]);
61344
+ /** Architecture-driven predictions: cost ranges, confidence, and basin layer spend. */
61345
+ class EstimationView extends WorkbenchView {
61346
+ static id = 'estimation';
61347
+ static title = 'Estimation';
61348
+
61349
+ available() { return Boolean(this.workbench.report?.estimation); }
61350
+
61351
+ charts() {
61352
+ const est = this.workbench.report?.estimation;
61353
+ const entries = est?.entries ?? [];
61354
+ if (!entries.length) return [];
61355
+
61356
+ const charts = [
61357
+ {
61358
+ title: `Predicted cost range (${est.totals?.cost?.currency ?? 'AUD'}): minimum → maximum`,
61359
+ chartType: 'dumbbell',
61360
+ data: entries.map((e) => ({
61361
+ label: e.name,
61362
+ start: e.cost.minimum,
61363
+ end: e.cost.maximum,
61364
+ })),
61365
+ },
61366
+ {
61367
+ title: 'Confidence score (0–100%)',
61368
+ chartType: 'bar',
61369
+ data: entries.map((e) => ({
61370
+ label: e.name,
61371
+ value: e.confidence,
61372
+ })),
61373
+ },
61374
+ ];
61375
+
61376
+ const byBasin = {};
61377
+ for (const e of entries) {
61378
+ const label = `L${e.basin?.level ?? 1} ${e.basin?.name ?? 'Basin'}`;
61379
+ byBasin[label] = (byBasin[label] ?? 0) + e.cost.expected;
61380
+ }
61381
+ charts.push({
61382
+ title: 'Predicted spend by basin layer',
61383
+ chartType: 'pie',
61384
+ data: Object.entries(byBasin).map(([label, value]) => ({ label, value })),
61385
+ });
61386
+
61387
+ return charts;
61388
+ }
61389
+
61390
+ notes() {
61391
+ const est = this.workbench.report?.estimation;
61392
+ if (!est) return [];
61393
+ const tot = est.totals;
61394
+ const fmt = (n) => `$${Number(n).toLocaleString('en-US')}`;
61395
+ const notes = [
61396
+ `Total predicted spend: ${fmt(tot.cost.expected)} ${tot.cost.currency} (${fmt(tot.cost.minimum)} – ${fmt(tot.cost.maximum)}) across ${tot.initiativesCount} initiatives`,
61397
+ `Total effort: ${tot.effort.days} days (${tot.effort.storyPoints} story points, ${tot.effort.hours} hours) · ${tot.duration.workingDays} working days`,
61398
+ ];
61399
+
61400
+ const recs = (est.entries ?? []).flatMap((e) => e.recommendations ?? []);
61401
+ const uniqueRecs = [...new Set(recs)];
61402
+ for (const r of uniqueRecs) {
61403
+ notes.push(`Optimisation advice: ${r}`);
61404
+ }
61405
+
61406
+ return notes;
61407
+ }
61408
+ }
61409
+
61410
+ const WORKBENCH_VIEWS = Object.freeze([ExecutiveView, ArchitectureView, ExploreView, DeliveryView, PortfolioView, EstimationView, ReplayView]);
61345
61411
 
61346
61412
  class DecisionWorkbench {
61347
61413
  static KIND = KIND;
@@ -67822,6 +67888,7 @@ ${cells.map(c => ` <Cell${isHeader ? ' ss:StyleID="Header"' : ''}><Data ss:T
67822
67888
  exports.EmphasisRule = EmphasisRule;
67823
67889
  exports.EntityRole = EntityRole;
67824
67890
  exports.EnumerationType = EnumerationType;
67891
+ exports.EstimationView = EstimationView;
67825
67892
  exports.ExchangeFileFormat = ExchangeFileFormat;
67826
67893
  exports.ExecutiveView = ExecutiveView;
67827
67894
  exports.ExploreView = ExploreView;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@peter.prib/renderengine",
3
- "version": "0.15.3",
3
+ "version": "0.16.0",
4
4
  "description": "ArchiMate modeller, data modeller, diagram editor, OLAP cube & pivot chart studio, and 50+ type chart library for the browser, with no runtime dependencies.",
5
5
  "type": "module",
6
6
  "main": "src/index.js",
@@ -308,7 +308,73 @@ export class ReplayView extends WorkbenchView {
308
308
  }
309
309
  }
310
310
 
311
- export const WORKBENCH_VIEWS = Object.freeze([ExecutiveView, ArchitectureView, ExploreView, DeliveryView, PortfolioView, ReplayView]);
311
+ /** Architecture-driven predictions: cost ranges, confidence, and basin layer spend. */
312
+ export class EstimationView extends WorkbenchView {
313
+ static id = 'estimation';
314
+ static title = 'Estimation';
315
+
316
+ available() { return Boolean(this.workbench.report?.estimation); }
317
+
318
+ charts() {
319
+ const est = this.workbench.report?.estimation;
320
+ const entries = est?.entries ?? [];
321
+ if (!entries.length) return [];
322
+
323
+ const charts = [
324
+ {
325
+ title: `Predicted cost range (${est.totals?.cost?.currency ?? 'AUD'}): minimum → maximum`,
326
+ chartType: 'dumbbell',
327
+ data: entries.map((e) => ({
328
+ label: e.name,
329
+ start: e.cost.minimum,
330
+ end: e.cost.maximum,
331
+ })),
332
+ },
333
+ {
334
+ title: 'Confidence score (0–100%)',
335
+ chartType: 'bar',
336
+ data: entries.map((e) => ({
337
+ label: e.name,
338
+ value: e.confidence,
339
+ })),
340
+ },
341
+ ];
342
+
343
+ const byBasin = {};
344
+ for (const e of entries) {
345
+ const label = `L${e.basin?.level ?? 1} ${e.basin?.name ?? 'Basin'}`;
346
+ byBasin[label] = (byBasin[label] ?? 0) + e.cost.expected;
347
+ }
348
+ charts.push({
349
+ title: 'Predicted spend by basin layer',
350
+ chartType: 'pie',
351
+ data: Object.entries(byBasin).map(([label, value]) => ({ label, value })),
352
+ });
353
+
354
+ return charts;
355
+ }
356
+
357
+ notes() {
358
+ const est = this.workbench.report?.estimation;
359
+ if (!est) return [];
360
+ const tot = est.totals;
361
+ const fmt = (n) => `$${Number(n).toLocaleString('en-US')}`;
362
+ const notes = [
363
+ `Total predicted spend: ${fmt(tot.cost.expected)} ${tot.cost.currency} (${fmt(tot.cost.minimum)} – ${fmt(tot.cost.maximum)}) across ${tot.initiativesCount} initiatives`,
364
+ `Total effort: ${tot.effort.days} days (${tot.effort.storyPoints} story points, ${tot.effort.hours} hours) · ${tot.duration.workingDays} working days`,
365
+ ];
366
+
367
+ const recs = (est.entries ?? []).flatMap((e) => e.recommendations ?? []);
368
+ const uniqueRecs = [...new Set(recs)];
369
+ for (const r of uniqueRecs) {
370
+ notes.push(`Optimisation advice: ${r}`);
371
+ }
372
+
373
+ return notes;
374
+ }
375
+ }
376
+
377
+ export const WORKBENCH_VIEWS = Object.freeze([ExecutiveView, ArchitectureView, ExploreView, DeliveryView, PortfolioView, EstimationView, ReplayView]);
312
378
 
313
379
  export class DecisionWorkbench {
314
380
  static KIND = KIND;
package/src/index.js CHANGED
@@ -211,7 +211,7 @@ import { buildTypeCategoryTree, buildPropertyTree } from './charting/modelTree/b
211
211
  import { DiagramTabs } from './charting/modelTree/DiagramTabs.js';
212
212
  import { DataModelNotation, DataModelLevel, AttributedLevel, ConceptualLevel, LogicalLevel, PhysicalLevel, NotationStyle, RelationshipKind, AssociationKind, GeneralizationKind, EntityRole, FactRole, DimensionRole } from './datamodel.js';
213
213
  import { DataModel, DataModelPerspective, DataModelContext, LevelSchema, LevelMapping, ServiceDomain, DataModelFileFormat, ServiceLandscape, BianLandscapeReader, BianSemanticApiReader, DataType, EnumerationType, StructuredType, NamingStandard, NameStyle, ClassificationScheme, ClassificationLens, SqlDdl, SqlDdlFileFormat, ModelScorecard, ScorecardCategory, MeasuredCategory, ModelMapping, DataLineage, ArchimateDataLink } from './charting/datamodel/index.js';
214
- import { DecisionWorkbench, WorkbenchView, ExecutiveView, ArchitectureView, ExploreView, DeliveryView, PortfolioView, ReplayView, WORKBENCH_VIEWS } from './charting/decision/DecisionWorkbench.js';
214
+ import { DecisionWorkbench, WorkbenchView, ExecutiveView, ArchitectureView, ExploreView, DeliveryView, PortfolioView, EstimationView, ReplayView, WORKBENCH_VIEWS } from './charting/decision/DecisionWorkbench.js';
215
215
  import { RequirementsModel, RequirementsChecker, RequirementsFileFormat, TrackerExportFileFormat, StoryboardFileFormat, TrackerExport, TRACKERS, Storyboard, TrackerApi, JiraApi, AzureDevOpsApi, GitLabApi, TRACKER_APIS, trackerApi, trackerConnectionFields } from './charting/requirements/index.js';
216
216
  import { EditableModel } from './charting/model/EditableModel.js';
217
217
  import { ModelEditCommand } from './charting/model/ModelEditCommand.js';
@@ -287,7 +287,7 @@ export {
287
287
  DataModelNotation, DataModelLevel, AttributedLevel, ConceptualLevel, LogicalLevel, PhysicalLevel, NotationStyle, RelationshipKind, AssociationKind, GeneralizationKind, EntityRole, FactRole, DimensionRole,
288
288
  DataModel, DataModelPerspective, DataModelContext, LevelSchema, LevelMapping, ServiceDomain, DataModelFileFormat, ServiceLandscape, BianLandscapeReader, BianSemanticApiReader, DataType, EnumerationType, StructuredType, NamingStandard, NameStyle, ClassificationScheme, ClassificationLens, SqlDdl, SqlDdlFileFormat, ModelScorecard, ScorecardCategory, MeasuredCategory,
289
289
  RequirementsModel, RequirementsChecker, RequirementsFileFormat, TrackerExportFileFormat, StoryboardFileFormat, TrackerExport, TRACKERS, Storyboard,
290
- DecisionWorkbench, WorkbenchView, ExecutiveView, ArchitectureView, ExploreView, DeliveryView, PortfolioView, ReplayView, WORKBENCH_VIEWS,
290
+ DecisionWorkbench, WorkbenchView, ExecutiveView, ArchitectureView, ExploreView, DeliveryView, PortfolioView, EstimationView, ReplayView, WORKBENCH_VIEWS,
291
291
  TrackerApi, JiraApi, AzureDevOpsApi, GitLabApi, TRACKER_APIS, trackerApi, trackerConnectionFields,
292
292
  EditableModel, ModelEditCommand, Benchmark,
293
293
  BianNotation, BianFunctionalPattern, BianActionTerm,