@sdeverywhere/check-core 0.1.0 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +28 -2
- package/dist/index.cjs +2071 -710
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1272 -0
- package/dist/index.d.ts +672 -307
- package/dist/index.js +2059 -696
- package/dist/index.js.map +1 -1
- package/package.json +6 -5
- package/schema/comparison.schema.json +456 -0
package/dist/index.cjs
CHANGED
|
@@ -33,117 +33,69 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
33
33
|
}
|
|
34
34
|
return to;
|
|
35
35
|
};
|
|
36
|
-
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
36
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
37
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
38
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
39
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
40
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
41
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
42
|
+
mod
|
|
43
|
+
));
|
|
37
44
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
45
|
+
var __async = (__this, __arguments, generator) => {
|
|
46
|
+
return new Promise((resolve, reject) => {
|
|
47
|
+
var fulfilled = (value) => {
|
|
48
|
+
try {
|
|
49
|
+
step(generator.next(value));
|
|
50
|
+
} catch (e) {
|
|
51
|
+
reject(e);
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
var rejected = (value) => {
|
|
55
|
+
try {
|
|
56
|
+
step(generator.throw(value));
|
|
57
|
+
} catch (e) {
|
|
58
|
+
reject(e);
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
|
|
62
|
+
step((generator = generator.apply(__this, __arguments)).next());
|
|
63
|
+
});
|
|
64
|
+
};
|
|
38
65
|
|
|
39
66
|
// src/index.ts
|
|
40
67
|
var src_exports = {};
|
|
41
68
|
__export(src_exports, {
|
|
42
69
|
CheckDataCoordinator: () => CheckDataCoordinator,
|
|
43
|
-
|
|
44
|
-
DatasetManager: () => DatasetManager,
|
|
70
|
+
ComparisonDataCoordinator: () => ComparisonDataCoordinator,
|
|
45
71
|
PerfRunner: () => PerfRunner,
|
|
46
72
|
PerfStats: () => PerfStats,
|
|
47
|
-
|
|
48
|
-
allInputsAtPositionScenario: () => allInputsAtPositionScenario,
|
|
73
|
+
categorizeComparisonTestSummaries: () => categorizeComparisonTestSummaries,
|
|
49
74
|
checkReportFromSummary: () => checkReportFromSummary,
|
|
50
75
|
checkSummaryFromReport: () => checkSummaryFromReport,
|
|
51
|
-
|
|
52
|
-
compareSummaryFromReport: () => compareSummaryFromReport,
|
|
76
|
+
comparisonSummaryFromReport: () => comparisonSummaryFromReport,
|
|
53
77
|
createConfig: () => createConfig,
|
|
54
78
|
datasetMessage: () => datasetMessage,
|
|
55
79
|
diffDatasets: () => diffDatasets,
|
|
56
80
|
diffGraphs: () => diffGraphs,
|
|
57
|
-
inputAtPositionScenario: () => inputAtPositionScenario,
|
|
58
|
-
inputAtValueScenario: () => inputAtValueScenario,
|
|
59
|
-
matrixScenarios: () => matrixScenarios,
|
|
60
|
-
positionSetting: () => positionSetting,
|
|
61
81
|
predicateMessage: () => predicateMessage,
|
|
62
82
|
runSuite: () => runSuite,
|
|
63
83
|
scenarioMessage: () => scenarioMessage,
|
|
64
|
-
|
|
65
|
-
suiteSummaryFromReport: () => suiteSummaryFromReport,
|
|
66
|
-
valueSetting: () => valueSetting
|
|
84
|
+
suiteSummaryFromReport: () => suiteSummaryFromReport
|
|
67
85
|
});
|
|
68
86
|
module.exports = __toCommonJS(src_exports);
|
|
69
87
|
|
|
70
|
-
// src/_shared/scenario.ts
|
|
71
|
-
var import_assert_never = require("assert-never");
|
|
72
|
-
function positionSetting(inputVarId, position) {
|
|
73
|
-
return {
|
|
74
|
-
kind: "position",
|
|
75
|
-
inputVarId,
|
|
76
|
-
position
|
|
77
|
-
};
|
|
78
|
-
}
|
|
79
|
-
function valueSetting(inputVarId, value) {
|
|
80
|
-
return {
|
|
81
|
-
kind: "value",
|
|
82
|
-
inputVarId,
|
|
83
|
-
value
|
|
84
|
-
};
|
|
85
|
-
}
|
|
86
|
-
function settingsScenario(key, groupKey, settings) {
|
|
87
|
-
return {
|
|
88
|
-
kind: "settings",
|
|
89
|
-
key,
|
|
90
|
-
groupKey,
|
|
91
|
-
settings
|
|
92
|
-
};
|
|
93
|
-
}
|
|
94
|
-
function inputAtPositionScenario(inputVarId, groupKey, position) {
|
|
95
|
-
const key = keyForInputAtPosition(`input${inputVarId}`, position);
|
|
96
|
-
return settingsScenario(key, groupKey, [positionSetting(inputVarId, position)]);
|
|
97
|
-
}
|
|
98
|
-
function inputAtValueScenario(inputVarId, groupKey, value) {
|
|
99
|
-
const key = keyForInputAtValue(`input${inputVarId}`, value);
|
|
100
|
-
return settingsScenario(key, groupKey, [valueSetting(inputVarId, value)]);
|
|
101
|
-
}
|
|
102
|
-
function allInputsAtPositionScenario(position) {
|
|
103
|
-
return {
|
|
104
|
-
kind: "all-inputs",
|
|
105
|
-
key: keyForInputAtPosition("all_inputs", position),
|
|
106
|
-
groupKey: "all_inputs",
|
|
107
|
-
position
|
|
108
|
-
};
|
|
109
|
-
}
|
|
110
|
-
function matrixScenarios(inputVarIds) {
|
|
111
|
-
const scenarios = [];
|
|
112
|
-
scenarios.push(allInputsAtPositionScenario("at-default"));
|
|
113
|
-
scenarios.push(allInputsAtPositionScenario("at-minimum"));
|
|
114
|
-
scenarios.push(allInputsAtPositionScenario("at-maximum"));
|
|
115
|
-
for (const inputVarId of inputVarIds) {
|
|
116
|
-
scenarios.push(inputAtPositionScenario(inputVarId, inputVarId, "at-minimum"));
|
|
117
|
-
scenarios.push(inputAtPositionScenario(inputVarId, inputVarId, "at-maximum"));
|
|
118
|
-
}
|
|
119
|
-
return scenarios;
|
|
120
|
-
}
|
|
121
|
-
function keyForInputPosition(position) {
|
|
122
|
-
switch (position) {
|
|
123
|
-
case "at-default":
|
|
124
|
-
return "default";
|
|
125
|
-
case "at-minimum":
|
|
126
|
-
return "min";
|
|
127
|
-
case "at-maximum":
|
|
128
|
-
return "max";
|
|
129
|
-
default:
|
|
130
|
-
(0, import_assert_never.assertNever)(position);
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
function keyForInputAtPosition(inputKey, position) {
|
|
134
|
-
return `${inputKey}_at_${keyForInputPosition(position)}`;
|
|
135
|
-
}
|
|
136
|
-
function keyForInputAtValue(inputKey, value) {
|
|
137
|
-
return `${inputKey}_at_${value}`;
|
|
138
|
-
}
|
|
139
|
-
|
|
140
88
|
// src/_shared/task-queue.ts
|
|
141
89
|
var TaskQueue = class {
|
|
142
90
|
constructor(processor) {
|
|
143
91
|
this.processor = processor;
|
|
92
|
+
/** The queue of task keys, most recent at front. */
|
|
144
93
|
this.taskKeyQueue = [];
|
|
94
|
+
/** The map of tasks. */
|
|
145
95
|
this.taskMap = /* @__PURE__ */ new Map();
|
|
96
|
+
/** Whether tasks are being processed. */
|
|
146
97
|
this.processing = false;
|
|
98
|
+
/** Whether `shutdown` has been called. */
|
|
147
99
|
this.stopped = false;
|
|
148
100
|
}
|
|
149
101
|
addTask(key, input, onComplete) {
|
|
@@ -181,39 +133,41 @@ var TaskQueue = class {
|
|
|
181
133
|
});
|
|
182
134
|
}
|
|
183
135
|
}
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
const task = this.taskMap.get(taskKey);
|
|
191
|
-
if (task) {
|
|
192
|
-
this.taskMap.delete(taskKey);
|
|
193
|
-
} else {
|
|
194
|
-
return;
|
|
195
|
-
}
|
|
196
|
-
let output;
|
|
197
|
-
try {
|
|
198
|
-
output = await this.processor.process(task.input);
|
|
199
|
-
} catch (e) {
|
|
200
|
-
if (!this.stopped) {
|
|
201
|
-
this.shutdown();
|
|
202
|
-
(_a = this.onIdle) == null ? void 0 : _a.call(this, e);
|
|
136
|
+
processNextTask() {
|
|
137
|
+
return __async(this, null, function* () {
|
|
138
|
+
var _a, _b;
|
|
139
|
+
const taskKey = this.taskKeyQueue.shift();
|
|
140
|
+
if (!taskKey) {
|
|
141
|
+
return;
|
|
203
142
|
}
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
this.processNextTask();
|
|
210
|
-
});
|
|
211
|
-
} else {
|
|
212
|
-
this.processing = false;
|
|
213
|
-
if (!this.stopped) {
|
|
214
|
-
(_b = this.onIdle) == null ? void 0 : _b.call(this);
|
|
143
|
+
const task = this.taskMap.get(taskKey);
|
|
144
|
+
if (task) {
|
|
145
|
+
this.taskMap.delete(taskKey);
|
|
146
|
+
} else {
|
|
147
|
+
return;
|
|
215
148
|
}
|
|
216
|
-
|
|
149
|
+
let output;
|
|
150
|
+
try {
|
|
151
|
+
output = yield this.processor.process(task.input);
|
|
152
|
+
} catch (e) {
|
|
153
|
+
if (!this.stopped) {
|
|
154
|
+
this.shutdown();
|
|
155
|
+
(_a = this.onIdle) == null ? void 0 : _a.call(this, e);
|
|
156
|
+
}
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
159
|
+
task.onComplete(output);
|
|
160
|
+
if (this.taskKeyQueue.length > 0) {
|
|
161
|
+
setTimeout(() => {
|
|
162
|
+
this.processNextTask();
|
|
163
|
+
});
|
|
164
|
+
} else {
|
|
165
|
+
this.processing = false;
|
|
166
|
+
if (!this.stopped) {
|
|
167
|
+
(_b = this.onIdle) == null ? void 0 : _b.call(this);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
});
|
|
217
171
|
}
|
|
218
172
|
};
|
|
219
173
|
|
|
@@ -222,18 +176,18 @@ var CheckDataCoordinator = class {
|
|
|
222
176
|
constructor(bundleModel) {
|
|
223
177
|
this.bundleModel = bundleModel;
|
|
224
178
|
this.taskQueue = new TaskQueue({
|
|
225
|
-
process:
|
|
226
|
-
const result =
|
|
179
|
+
process: (request) => __async(this, null, function* () {
|
|
180
|
+
const result = yield this.bundleModel.getDatasetsForScenario(request.scenarioSpec, [request.datasetKey]);
|
|
227
181
|
const dataset = result.datasetMap.get(request.datasetKey);
|
|
228
182
|
return {
|
|
229
183
|
dataset
|
|
230
184
|
};
|
|
231
|
-
}
|
|
185
|
+
})
|
|
232
186
|
});
|
|
233
187
|
}
|
|
234
|
-
requestDataset(requestKey,
|
|
188
|
+
requestDataset(requestKey, scenarioSpec, datasetKey, onResponse) {
|
|
235
189
|
const request = {
|
|
236
|
-
|
|
190
|
+
scenarioSpec,
|
|
237
191
|
datasetKey
|
|
238
192
|
};
|
|
239
193
|
this.taskQueue.addTask(requestKey, request, (response) => {
|
|
@@ -246,10 +200,10 @@ var CheckDataCoordinator = class {
|
|
|
246
200
|
};
|
|
247
201
|
|
|
248
202
|
// src/check/check-report.ts
|
|
249
|
-
var
|
|
203
|
+
var import_assert_never2 = __toESM(require("assert-never"), 1);
|
|
250
204
|
|
|
251
205
|
// src/check/check-predicate.ts
|
|
252
|
-
var
|
|
206
|
+
var import_assert_never = __toESM(require("assert-never"), 1);
|
|
253
207
|
function symbolForPredicateOp(op) {
|
|
254
208
|
switch (op) {
|
|
255
209
|
case "gt":
|
|
@@ -265,7 +219,7 @@ function symbolForPredicateOp(op) {
|
|
|
265
219
|
case "approx":
|
|
266
220
|
return "\u2248";
|
|
267
221
|
default:
|
|
268
|
-
(0,
|
|
222
|
+
(0, import_assert_never.default)(op);
|
|
269
223
|
}
|
|
270
224
|
}
|
|
271
225
|
|
|
@@ -279,7 +233,7 @@ function buildCheckReport(checkPlan, checkResults) {
|
|
|
279
233
|
const scenarioReports = [];
|
|
280
234
|
for (const scenarioPlan of testPlan.scenarios) {
|
|
281
235
|
let scenarioStatus = "passed";
|
|
282
|
-
if (scenarioPlan.checkScenario.
|
|
236
|
+
if (scenarioPlan.checkScenario.spec === void 0) {
|
|
283
237
|
testStatus = "error";
|
|
284
238
|
scenarioStatus = "error";
|
|
285
239
|
}
|
|
@@ -376,14 +330,14 @@ function predicateReport(predicatePlan, checkKey, result) {
|
|
|
376
330
|
};
|
|
377
331
|
opRef = opDataRef;
|
|
378
332
|
opValue = `${sym} '${dataRef.dataset.name}'`;
|
|
379
|
-
const
|
|
380
|
-
if (!
|
|
333
|
+
const refScenarioSpec = (_b = dataRef.scenario) == null ? void 0 : _b.spec;
|
|
334
|
+
if (!refScenarioSpec) {
|
|
381
335
|
return;
|
|
382
336
|
}
|
|
383
337
|
if (predOp.scenario === "inherit") {
|
|
384
338
|
opValue += ` (w/ same scenario)`;
|
|
385
339
|
} else {
|
|
386
|
-
if (
|
|
340
|
+
if (refScenarioSpec.kind === "all-inputs" && refScenarioSpec.position === "at-default") {
|
|
387
341
|
opValue += ` (w/ default scenario)`;
|
|
388
342
|
} else {
|
|
389
343
|
opValue += ` (w/ configured scenario)`;
|
|
@@ -418,7 +372,7 @@ function predicateReport(predicatePlan, checkKey, result) {
|
|
|
418
372
|
}
|
|
419
373
|
function scenarioMessage(scenario, bold) {
|
|
420
374
|
const checkScenario = scenario.checkScenario;
|
|
421
|
-
if (checkScenario.
|
|
375
|
+
if (checkScenario.spec === void 0) {
|
|
422
376
|
if (checkScenario.error) {
|
|
423
377
|
switch (checkScenario.error.kind) {
|
|
424
378
|
case "unknown-input-group":
|
|
@@ -426,7 +380,7 @@ function scenarioMessage(scenario, bold) {
|
|
|
426
380
|
case "empty-input-group":
|
|
427
381
|
return `error: input group ${bold(checkScenario.error.name)} is empty`;
|
|
428
382
|
default:
|
|
429
|
-
(0,
|
|
383
|
+
(0, import_assert_never2.default)(checkScenario.error.kind);
|
|
430
384
|
}
|
|
431
385
|
} else {
|
|
432
386
|
const badInputNames = checkScenario.inputDescs.filter((d) => d.inputVar === void 0).map((d) => bold(d.name));
|
|
@@ -443,7 +397,7 @@ function scenarioMessage(scenario, bold) {
|
|
|
443
397
|
case "at-maximum":
|
|
444
398
|
return "maximum";
|
|
445
399
|
default:
|
|
446
|
-
(0,
|
|
400
|
+
(0, import_assert_never2.default)(position);
|
|
447
401
|
}
|
|
448
402
|
}
|
|
449
403
|
function inputMessage(inputDesc) {
|
|
@@ -458,13 +412,13 @@ function scenarioMessage(scenario, bold) {
|
|
|
458
412
|
}
|
|
459
413
|
return msg;
|
|
460
414
|
}
|
|
461
|
-
if (checkScenario.
|
|
462
|
-
const position = checkScenario.
|
|
415
|
+
if (checkScenario.spec.kind === "all-inputs") {
|
|
416
|
+
const position = checkScenario.spec.position;
|
|
463
417
|
return `when ${bold("all inputs")} are at ${bold(positionName(position))}...`;
|
|
464
418
|
} else if (checkScenario.inputGroupName) {
|
|
465
419
|
let position = "at-default";
|
|
466
|
-
if (checkScenario.
|
|
467
|
-
position = checkScenario.
|
|
420
|
+
if (checkScenario.spec.settings[0].kind === "position") {
|
|
421
|
+
position = checkScenario.spec.settings[0].position;
|
|
468
422
|
}
|
|
469
423
|
const groupName = checkScenario.inputGroupName;
|
|
470
424
|
return `when all inputs in ${bold(groupName)} are at ${bold(positionName(position))}...`;
|
|
@@ -497,7 +451,7 @@ function predicateMessage(predicate, bold) {
|
|
|
497
451
|
case "empty-input-group":
|
|
498
452
|
return `error: referenced input group ${bold(result.errorInfo.name)} is empty`;
|
|
499
453
|
default:
|
|
500
|
-
(0,
|
|
454
|
+
(0, import_assert_never2.default)(result.errorInfo.kind);
|
|
501
455
|
}
|
|
502
456
|
} else {
|
|
503
457
|
return `unknown error`;
|
|
@@ -1068,7 +1022,7 @@ function parseTestYaml(yamlStrings) {
|
|
|
1068
1022
|
groups.push(group);
|
|
1069
1023
|
}
|
|
1070
1024
|
} else {
|
|
1071
|
-
let msg = "Failed to parse YAML
|
|
1025
|
+
let msg = "Failed to parse YAML check definitions";
|
|
1072
1026
|
for (const error of validate.errors || []) {
|
|
1073
1027
|
if (error.message) {
|
|
1074
1028
|
msg += `
|
|
@@ -1242,9 +1196,12 @@ function actionForPredicate(predicateSpec) {
|
|
|
1242
1196
|
|
|
1243
1197
|
// src/_shared/combo.ts
|
|
1244
1198
|
function cartesianProductOf(arr) {
|
|
1245
|
-
return arr.reduce(
|
|
1246
|
-
|
|
1247
|
-
|
|
1199
|
+
return arr.reduce(
|
|
1200
|
+
(a, b) => {
|
|
1201
|
+
return a.map((x) => b.map((y) => x.concat([y]))).reduce((v, w) => v.concat(w), []);
|
|
1202
|
+
},
|
|
1203
|
+
[[]]
|
|
1204
|
+
);
|
|
1248
1205
|
}
|
|
1249
1206
|
|
|
1250
1207
|
// src/check/check-dataset.ts
|
|
@@ -1335,14 +1292,16 @@ function matchByName(modelSpec, datasetName, datasetSource) {
|
|
|
1335
1292
|
};
|
|
1336
1293
|
}
|
|
1337
1294
|
function matchByGroup(modelSpec, groupName) {
|
|
1338
|
-
const groupToMatch = groupName.toLowerCase();
|
|
1339
1295
|
let matchedGroupName;
|
|
1340
1296
|
let matchedGroupDatasetKeys;
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1297
|
+
if (modelSpec.datasetGroups) {
|
|
1298
|
+
const groupToMatch = groupName.toLowerCase();
|
|
1299
|
+
for (const [group, datasetKeys] of modelSpec.datasetGroups) {
|
|
1300
|
+
if (group.toLowerCase() === groupToMatch) {
|
|
1301
|
+
matchedGroupName = group;
|
|
1302
|
+
matchedGroupDatasetKeys = datasetKeys;
|
|
1303
|
+
break;
|
|
1304
|
+
}
|
|
1346
1305
|
}
|
|
1347
1306
|
}
|
|
1348
1307
|
if (matchedGroupName === void 0) {
|
|
@@ -1419,6 +1378,65 @@ function matchByType(modelSpec, varTypeToMatch) {
|
|
|
1419
1378
|
|
|
1420
1379
|
// src/check/check-scenario.ts
|
|
1421
1380
|
var import_assert_never4 = __toESM(require("assert-never"), 1);
|
|
1381
|
+
|
|
1382
|
+
// src/_shared/scenario-specs.ts
|
|
1383
|
+
var import_assert_never3 = require("assert-never");
|
|
1384
|
+
function positionSetting(inputVarId, position) {
|
|
1385
|
+
return {
|
|
1386
|
+
kind: "position",
|
|
1387
|
+
inputVarId,
|
|
1388
|
+
position
|
|
1389
|
+
};
|
|
1390
|
+
}
|
|
1391
|
+
function valueSetting(inputVarId, value) {
|
|
1392
|
+
return {
|
|
1393
|
+
kind: "value",
|
|
1394
|
+
inputVarId,
|
|
1395
|
+
value
|
|
1396
|
+
};
|
|
1397
|
+
}
|
|
1398
|
+
function inputSettingsSpec(settings) {
|
|
1399
|
+
const uidParts = settings.map((setting) => {
|
|
1400
|
+
switch (setting.kind) {
|
|
1401
|
+
case "position":
|
|
1402
|
+
return `${setting.inputVarId}_at_${keyForInputPosition(setting.position)}`;
|
|
1403
|
+
case "value":
|
|
1404
|
+
return `${setting.inputVarId}_at_${setting.value}`;
|
|
1405
|
+
default:
|
|
1406
|
+
(0, import_assert_never3.assertNever)(setting);
|
|
1407
|
+
}
|
|
1408
|
+
});
|
|
1409
|
+
const uid = `inputs_${uidParts.sort().join("_")}`;
|
|
1410
|
+
return {
|
|
1411
|
+
kind: "input-settings",
|
|
1412
|
+
uid,
|
|
1413
|
+
settings
|
|
1414
|
+
};
|
|
1415
|
+
}
|
|
1416
|
+
function inputAtPositionSpec(inputVarId, position) {
|
|
1417
|
+
return inputSettingsSpec([positionSetting(inputVarId, position)]);
|
|
1418
|
+
}
|
|
1419
|
+
function allInputsAtPositionSpec(position) {
|
|
1420
|
+
return {
|
|
1421
|
+
kind: "all-inputs",
|
|
1422
|
+
uid: `all_inputs_at_${keyForInputPosition(position)}`,
|
|
1423
|
+
position
|
|
1424
|
+
};
|
|
1425
|
+
}
|
|
1426
|
+
function keyForInputPosition(position) {
|
|
1427
|
+
switch (position) {
|
|
1428
|
+
case "at-default":
|
|
1429
|
+
return "default";
|
|
1430
|
+
case "at-minimum":
|
|
1431
|
+
return "min";
|
|
1432
|
+
case "at-maximum":
|
|
1433
|
+
return "max";
|
|
1434
|
+
default:
|
|
1435
|
+
(0, import_assert_never3.assertNever)(position);
|
|
1436
|
+
}
|
|
1437
|
+
}
|
|
1438
|
+
|
|
1439
|
+
// src/check/check-scenario.ts
|
|
1422
1440
|
function expandScenarios(modelSpec, scenarioSpecs, simplify) {
|
|
1423
1441
|
if (scenarioSpecs.length === 0) {
|
|
1424
1442
|
const scenarioSpec = {
|
|
@@ -1495,10 +1513,12 @@ function inputDescForName(modelSpec, inputName, at) {
|
|
|
1495
1513
|
}
|
|
1496
1514
|
}
|
|
1497
1515
|
function groupForName(modelSpec, groupName) {
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
|
|
1516
|
+
if (modelSpec.inputGroups) {
|
|
1517
|
+
const groupToMatch = groupName.toLowerCase();
|
|
1518
|
+
for (const [group, inputVars] of modelSpec.inputGroups) {
|
|
1519
|
+
if (group.toLowerCase() === groupToMatch) {
|
|
1520
|
+
return [group, inputVars];
|
|
1521
|
+
}
|
|
1502
1522
|
}
|
|
1503
1523
|
}
|
|
1504
1524
|
return void 0;
|
|
@@ -1513,56 +1533,35 @@ function errorScenarioForInputGroup(kind, groupName) {
|
|
|
1513
1533
|
};
|
|
1514
1534
|
}
|
|
1515
1535
|
function checkScenarioWithAllInputsAtPosition(position) {
|
|
1516
|
-
const scenario = allInputsAtPositionScenario(position);
|
|
1517
1536
|
return {
|
|
1518
|
-
|
|
1537
|
+
spec: allInputsAtPositionSpec(position),
|
|
1519
1538
|
inputDescs: []
|
|
1520
1539
|
};
|
|
1521
1540
|
}
|
|
1522
1541
|
function checkScenarioWithInputAtPosition(inputVar, position) {
|
|
1523
1542
|
const varId = inputVar.varId;
|
|
1524
|
-
const scenario = inputAtPositionScenario(varId, varId, position);
|
|
1525
1543
|
return {
|
|
1526
|
-
|
|
1544
|
+
spec: inputAtPositionSpec(varId, position),
|
|
1527
1545
|
inputDescs: [inputDescAtPosition(inputVar, position)]
|
|
1528
1546
|
};
|
|
1529
1547
|
}
|
|
1530
1548
|
function checkScenarioForInputDescs(groupName, inputDescs) {
|
|
1531
|
-
let
|
|
1549
|
+
let spec;
|
|
1532
1550
|
if (inputDescs.every((desc) => desc.inputVar !== void 0)) {
|
|
1533
|
-
const settings =
|
|
1534
|
-
const keyParts = [];
|
|
1535
|
-
for (const inputDesc of inputDescs) {
|
|
1551
|
+
const settings = inputDescs.map((inputDesc) => {
|
|
1536
1552
|
const varId = inputDesc.inputVar.varId;
|
|
1537
1553
|
if (inputDesc.position) {
|
|
1538
|
-
|
|
1539
|
-
keyParts.push(keyForInputAtPosition(varId, inputDesc.position));
|
|
1540
|
-
} else {
|
|
1541
|
-
settings.push(valueSetting(varId, inputDesc.value));
|
|
1542
|
-
keyParts.push(keyForInputAtValue(varId, inputDesc.value));
|
|
1543
|
-
}
|
|
1544
|
-
}
|
|
1545
|
-
if (settings.length === 1) {
|
|
1546
|
-
const scenarioKey = `input${keyParts[0]}`;
|
|
1547
|
-
const groupKey = settings[0].inputVarId;
|
|
1548
|
-
scenario = settingsScenario(scenarioKey, groupKey, settings);
|
|
1549
|
-
} else if (settings.length > 1) {
|
|
1550
|
-
let scenarioKey;
|
|
1551
|
-
let groupKey;
|
|
1552
|
-
if (groupName) {
|
|
1553
|
-
scenarioKey = `group_${groupName.toLowerCase().replace(/ /g, "_")}`;
|
|
1554
|
-
groupKey = scenarioKey;
|
|
1554
|
+
return positionSetting(varId, inputDesc.position);
|
|
1555
1555
|
} else {
|
|
1556
|
-
|
|
1557
|
-
groupKey = scenarioKey;
|
|
1556
|
+
return valueSetting(varId, inputDesc.value);
|
|
1558
1557
|
}
|
|
1559
|
-
|
|
1560
|
-
|
|
1558
|
+
});
|
|
1559
|
+
spec = inputSettingsSpec(settings);
|
|
1561
1560
|
} else {
|
|
1562
|
-
|
|
1561
|
+
spec = void 0;
|
|
1563
1562
|
}
|
|
1564
1563
|
return {
|
|
1565
|
-
|
|
1564
|
+
spec,
|
|
1566
1565
|
inputGroupName: groupName,
|
|
1567
1566
|
inputDescs
|
|
1568
1567
|
};
|
|
@@ -1676,7 +1675,7 @@ var CheckPlanner = class {
|
|
|
1676
1675
|
}
|
|
1677
1676
|
const planScenarios = [];
|
|
1678
1677
|
for (const checkScenario of checkScenarios) {
|
|
1679
|
-
if (checkScenario.
|
|
1678
|
+
if (checkScenario.spec === void 0) {
|
|
1680
1679
|
planScenarios.push({
|
|
1681
1680
|
checkScenario,
|
|
1682
1681
|
datasets: []
|
|
@@ -1736,6 +1735,24 @@ var CheckPlanner = class {
|
|
|
1736
1735
|
dataRefs: this.dataRefs
|
|
1737
1736
|
};
|
|
1738
1737
|
}
|
|
1738
|
+
/**
|
|
1739
|
+
* Record any references to additional datasets contained in the given predicate.
|
|
1740
|
+
* For example, if the predicate is:
|
|
1741
|
+
* ```
|
|
1742
|
+
* gt:
|
|
1743
|
+
* dataset:
|
|
1744
|
+
* name: 'XYZ'
|
|
1745
|
+
* scenario:
|
|
1746
|
+
* inputs: all
|
|
1747
|
+
* at: default
|
|
1748
|
+
* ```
|
|
1749
|
+
* this will add a reference to the scenario/dataset pair so that the data can
|
|
1750
|
+
* be fetched in a later stage.
|
|
1751
|
+
*
|
|
1752
|
+
* @param predicateSpec The predicate spec.
|
|
1753
|
+
* @param checkScenario The scenario in which the dataset is being checked.
|
|
1754
|
+
* @param checkDataset The dataset that is being checked.
|
|
1755
|
+
*/
|
|
1739
1756
|
addDataRefs(predicateSpec, checkScenario, checkDataset) {
|
|
1740
1757
|
let dataRefs;
|
|
1741
1758
|
const addDataRef = (op) => {
|
|
@@ -1785,8 +1802,8 @@ var CheckPlanner = class {
|
|
|
1785
1802
|
}
|
|
1786
1803
|
}
|
|
1787
1804
|
let dataRefKey;
|
|
1788
|
-
if (refScenario.
|
|
1789
|
-
dataRefKey = `${refScenario.
|
|
1805
|
+
if (refScenario.spec && refDataset.datasetKey) {
|
|
1806
|
+
dataRefKey = `${refScenario.spec.uid}::${refDataset.datasetKey}`;
|
|
1790
1807
|
}
|
|
1791
1808
|
const dataRef = {
|
|
1792
1809
|
key: dataRefKey,
|
|
@@ -1841,14 +1858,14 @@ function checkSummaryFromReport(checkReport) {
|
|
|
1841
1858
|
predicateSummaries
|
|
1842
1859
|
};
|
|
1843
1860
|
}
|
|
1844
|
-
function checkReportFromSummary(checkConfig, checkSummary
|
|
1861
|
+
function checkReportFromSummary(checkConfig, checkSummary) {
|
|
1845
1862
|
const checkSpecResult = parseTestYaml(checkConfig.tests);
|
|
1846
1863
|
if (checkSpecResult.isErr()) {
|
|
1847
1864
|
return void 0;
|
|
1848
1865
|
}
|
|
1849
1866
|
const checkSpec = checkSpecResult.value;
|
|
1850
1867
|
const checkPlanner = new CheckPlanner(checkConfig.bundle.model.modelSpec);
|
|
1851
|
-
checkPlanner.addAllChecks(checkSpec,
|
|
1868
|
+
checkPlanner.addAllChecks(checkSpec, false);
|
|
1852
1869
|
const checkPlan = checkPlanner.buildPlan();
|
|
1853
1870
|
const checkResults = /* @__PURE__ */ new Map();
|
|
1854
1871
|
for (const predicateSummary of checkSummary.predicateSummaries) {
|
|
@@ -1857,44 +1874,74 @@ function checkReportFromSummary(checkConfig, checkSummary, simplifyScenarios) {
|
|
|
1857
1874
|
return buildCheckReport(checkPlan, checkResults);
|
|
1858
1875
|
}
|
|
1859
1876
|
|
|
1860
|
-
// src/
|
|
1877
|
+
// src/comparison/run/comparison-data-coordinator.ts
|
|
1861
1878
|
var import_assert_never7 = require("assert-never");
|
|
1862
|
-
var
|
|
1879
|
+
var ComparisonDataCoordinator = class {
|
|
1863
1880
|
constructor(bundleModelL, bundleModelR) {
|
|
1864
1881
|
this.bundleModelL = bundleModelL;
|
|
1865
1882
|
this.bundleModelR = bundleModelR;
|
|
1866
1883
|
this.taskQueue = new TaskQueue({
|
|
1867
|
-
process:
|
|
1884
|
+
process: (request) => __async(this, null, function* () {
|
|
1868
1885
|
switch (request.kind) {
|
|
1869
|
-
case "dataset":
|
|
1870
|
-
|
|
1871
|
-
|
|
1872
|
-
|
|
1873
|
-
]);
|
|
1874
|
-
return {
|
|
1875
|
-
kind: "dataset",
|
|
1876
|
-
datasetMapL: resultL.datasetMap,
|
|
1877
|
-
datasetMapR: resultR.datasetMap
|
|
1878
|
-
};
|
|
1879
|
-
}
|
|
1880
|
-
case "graph-data": {
|
|
1881
|
-
const bundleModel = request.bundle === "right" ? this.bundleModelR : this.bundleModelL;
|
|
1882
|
-
const graphData = await bundleModel.getGraphDataForScenario(request.scenario, request.graphId);
|
|
1883
|
-
return {
|
|
1884
|
-
kind: "graph-data",
|
|
1885
|
-
graphData
|
|
1886
|
-
};
|
|
1887
|
-
}
|
|
1886
|
+
case "dataset":
|
|
1887
|
+
return this.processDatasetRequest(request);
|
|
1888
|
+
case "graph-data":
|
|
1889
|
+
return this.processGraphDataRequest(request);
|
|
1888
1890
|
default:
|
|
1889
1891
|
(0, import_assert_never7.assertNever)(request);
|
|
1890
1892
|
}
|
|
1893
|
+
})
|
|
1894
|
+
});
|
|
1895
|
+
}
|
|
1896
|
+
processDatasetRequest(request) {
|
|
1897
|
+
return __async(this, null, function* () {
|
|
1898
|
+
function fetchDatasets(bundleModel, scenarioSpec) {
|
|
1899
|
+
return __async(this, null, function* () {
|
|
1900
|
+
if (scenarioSpec) {
|
|
1901
|
+
return bundleModel.getDatasetsForScenario(scenarioSpec, request.datasetKeys);
|
|
1902
|
+
} else {
|
|
1903
|
+
return void 0;
|
|
1904
|
+
}
|
|
1905
|
+
});
|
|
1906
|
+
}
|
|
1907
|
+
const [resultL, resultR] = yield Promise.all([
|
|
1908
|
+
fetchDatasets(this.bundleModelL, request.scenarioSpecL),
|
|
1909
|
+
fetchDatasets(this.bundleModelR, request.scenarioSpecR)
|
|
1910
|
+
]);
|
|
1911
|
+
return {
|
|
1912
|
+
kind: "dataset",
|
|
1913
|
+
datasetMapL: resultL == null ? void 0 : resultL.datasetMap,
|
|
1914
|
+
datasetMapR: resultR == null ? void 0 : resultR.datasetMap
|
|
1915
|
+
};
|
|
1916
|
+
});
|
|
1917
|
+
}
|
|
1918
|
+
processGraphDataRequest(request) {
|
|
1919
|
+
return __async(this, null, function* () {
|
|
1920
|
+
function fetchGraphData(bundleModel, scenarioSpec) {
|
|
1921
|
+
return __async(this, null, function* () {
|
|
1922
|
+
if (scenarioSpec) {
|
|
1923
|
+
return bundleModel.getGraphDataForScenario(scenarioSpec, request.graphId);
|
|
1924
|
+
} else {
|
|
1925
|
+
return void 0;
|
|
1926
|
+
}
|
|
1927
|
+
});
|
|
1891
1928
|
}
|
|
1929
|
+
const [graphDataL, graphDataR] = yield Promise.all([
|
|
1930
|
+
fetchGraphData(this.bundleModelL, request.scenarioSpecL),
|
|
1931
|
+
fetchGraphData(this.bundleModelR, request.scenarioSpecR)
|
|
1932
|
+
]);
|
|
1933
|
+
return {
|
|
1934
|
+
kind: "graph-data",
|
|
1935
|
+
graphDataL,
|
|
1936
|
+
graphDataR
|
|
1937
|
+
};
|
|
1892
1938
|
});
|
|
1893
1939
|
}
|
|
1894
|
-
requestDatasetMaps(requestKey,
|
|
1940
|
+
requestDatasetMaps(requestKey, scenarioSpecL, scenarioSpecR, datasetKeys, onResponse) {
|
|
1895
1941
|
const request = {
|
|
1896
1942
|
kind: "dataset",
|
|
1897
|
-
|
|
1943
|
+
scenarioSpecL,
|
|
1944
|
+
scenarioSpecR,
|
|
1898
1945
|
datasetKeys
|
|
1899
1946
|
};
|
|
1900
1947
|
this.taskQueue.addTask(requestKey, request, (response) => {
|
|
@@ -1903,16 +1950,16 @@ var CompareDataCoordinator = class {
|
|
|
1903
1950
|
}
|
|
1904
1951
|
});
|
|
1905
1952
|
}
|
|
1906
|
-
requestGraphData(requestKey,
|
|
1953
|
+
requestGraphData(requestKey, scenarioSpecL, scenarioSpecR, graphId, onResponse) {
|
|
1907
1954
|
const request = {
|
|
1908
1955
|
kind: "graph-data",
|
|
1909
|
-
|
|
1910
|
-
|
|
1956
|
+
scenarioSpecL,
|
|
1957
|
+
scenarioSpecR,
|
|
1911
1958
|
graphId
|
|
1912
1959
|
};
|
|
1913
1960
|
this.taskQueue.addTask(requestKey, request, (response) => {
|
|
1914
1961
|
if (response.kind === "graph-data") {
|
|
1915
|
-
onResponse(response.
|
|
1962
|
+
onResponse(response.graphDataL, response.graphDataR);
|
|
1916
1963
|
}
|
|
1917
1964
|
});
|
|
1918
1965
|
}
|
|
@@ -1921,7 +1968,7 @@ var CompareDataCoordinator = class {
|
|
|
1921
1968
|
}
|
|
1922
1969
|
};
|
|
1923
1970
|
|
|
1924
|
-
// src/
|
|
1971
|
+
// src/comparison/diff-datasets/diff-datasets.ts
|
|
1925
1972
|
function diffDatasets(datasetL, datasetR) {
|
|
1926
1973
|
let minValueL = Number.MAX_VALUE;
|
|
1927
1974
|
let maxValueL = Number.MIN_VALUE;
|
|
@@ -2016,19 +2063,9 @@ function diffDatasets(datasetL, datasetR) {
|
|
|
2016
2063
|
maxDiffPoint
|
|
2017
2064
|
};
|
|
2018
2065
|
}
|
|
2019
|
-
function compareDatasets(scenarioKey, datasetKey, datasetMapL, datasetMapR) {
|
|
2020
|
-
const datasetL = datasetMapL.get(datasetKey);
|
|
2021
|
-
const datasetR = datasetMapR.get(datasetKey);
|
|
2022
|
-
const diffReport = diffDatasets(datasetL, datasetR);
|
|
2023
|
-
return {
|
|
2024
|
-
scenarioKey,
|
|
2025
|
-
datasetKey,
|
|
2026
|
-
diffReport
|
|
2027
|
-
};
|
|
2028
|
-
}
|
|
2029
2066
|
|
|
2030
|
-
// src/
|
|
2031
|
-
function diffGraphs(graphL, graphR, scenarioKey,
|
|
2067
|
+
// src/comparison/diff-graphs/diff-graphs.ts
|
|
2068
|
+
function diffGraphs(graphL, graphR, scenarioKey, testSummaries) {
|
|
2032
2069
|
let inclusion;
|
|
2033
2070
|
if (graphL && graphR) {
|
|
2034
2071
|
inclusion = "both";
|
|
@@ -2070,8 +2107,8 @@ function diffGraphs(graphL, graphR, scenarioKey, datasetSummaries) {
|
|
|
2070
2107
|
datasetKeys.add(dataset.datasetKey);
|
|
2071
2108
|
}
|
|
2072
2109
|
for (const datasetKey of datasetKeys) {
|
|
2073
|
-
const
|
|
2074
|
-
const maxDiff =
|
|
2110
|
+
const testSummary = testSummaries.find((summary) => summary.d === datasetKey && summary.s === scenarioKey);
|
|
2111
|
+
const maxDiff = testSummary == null ? void 0 : testSummary.md;
|
|
2075
2112
|
datasetReports.push({
|
|
2076
2113
|
datasetKey,
|
|
2077
2114
|
maxDiff
|
|
@@ -2085,12 +2122,12 @@ function diffGraphs(graphL, graphR, scenarioKey, datasetSummaries) {
|
|
|
2085
2122
|
};
|
|
2086
2123
|
}
|
|
2087
2124
|
|
|
2088
|
-
// src/
|
|
2089
|
-
function
|
|
2090
|
-
const
|
|
2091
|
-
for (const r of
|
|
2125
|
+
// src/comparison/report/comparison-reporting.ts
|
|
2126
|
+
function comparisonSummaryFromReport(comparisonReport) {
|
|
2127
|
+
const terseSummaries = [];
|
|
2128
|
+
for (const r of comparisonReport.testReports) {
|
|
2092
2129
|
if (r.diffReport.validity === "both" && r.diffReport.maxDiff > 0) {
|
|
2093
|
-
|
|
2130
|
+
terseSummaries.push({
|
|
2094
2131
|
s: r.scenarioKey,
|
|
2095
2132
|
d: r.datasetKey,
|
|
2096
2133
|
md: r.diffReport.maxDiff
|
|
@@ -2098,394 +2135,1633 @@ function compareSummaryFromReport(compareReport) {
|
|
|
2098
2135
|
}
|
|
2099
2136
|
}
|
|
2100
2137
|
return {
|
|
2101
|
-
|
|
2102
|
-
perfReportL:
|
|
2103
|
-
perfReportR:
|
|
2138
|
+
testSummaries: terseSummaries,
|
|
2139
|
+
perfReportL: comparisonReport.perfReportL,
|
|
2140
|
+
perfReportR: comparisonReport.perfReportR
|
|
2104
2141
|
};
|
|
2105
2142
|
}
|
|
2143
|
+
function restoreFromTerseSummaries(comparisonConfig, terseSummaries) {
|
|
2144
|
+
const existingSummaries = /* @__PURE__ */ new Map();
|
|
2145
|
+
for (const summary of terseSummaries) {
|
|
2146
|
+
const key = `${summary.s}::${summary.d}`;
|
|
2147
|
+
existingSummaries.set(key, summary);
|
|
2148
|
+
}
|
|
2149
|
+
const allTestSummaries = [];
|
|
2150
|
+
for (const scenario of comparisonConfig.scenarios.getAllScenarios()) {
|
|
2151
|
+
const datasetKeys = comparisonConfig.datasets.getDatasetKeysForScenario(scenario);
|
|
2152
|
+
for (const datasetKey of datasetKeys) {
|
|
2153
|
+
const key = `${scenario.key}::${datasetKey}`;
|
|
2154
|
+
const existingSummary = existingSummaries.get(key);
|
|
2155
|
+
const maxDiff = (existingSummary == null ? void 0 : existingSummary.md) || 0;
|
|
2156
|
+
allTestSummaries.push({
|
|
2157
|
+
s: scenario.key,
|
|
2158
|
+
d: datasetKey,
|
|
2159
|
+
md: maxDiff
|
|
2160
|
+
});
|
|
2161
|
+
}
|
|
2162
|
+
}
|
|
2163
|
+
return allTestSummaries;
|
|
2164
|
+
}
|
|
2106
2165
|
|
|
2107
|
-
// src/
|
|
2108
|
-
|
|
2109
|
-
|
|
2110
|
-
|
|
2166
|
+
// src/comparison/report/comparison-grouping.ts
|
|
2167
|
+
var import_assert_never8 = require("assert-never");
|
|
2168
|
+
|
|
2169
|
+
// src/comparison/report/buckets.ts
|
|
2170
|
+
function getBucketIndex(diffPct, thresholds) {
|
|
2171
|
+
if (diffPct === 0) {
|
|
2172
|
+
return 0;
|
|
2173
|
+
}
|
|
2174
|
+
for (let i = 0; i < thresholds.length; i++) {
|
|
2175
|
+
if (diffPct < thresholds[i]) {
|
|
2176
|
+
return i + 1;
|
|
2177
|
+
}
|
|
2178
|
+
}
|
|
2179
|
+
return thresholds.length + 1;
|
|
2180
|
+
}
|
|
2181
|
+
|
|
2182
|
+
// src/comparison/report/comparison-grouping.ts
|
|
2183
|
+
function categorizeComparisonTestSummaries(comparisonConfig, terseSummaries) {
|
|
2184
|
+
const allTestSummaries = restoreFromTerseSummaries(comparisonConfig, terseSummaries);
|
|
2185
|
+
const groupsByScenario = groupComparisonTestSummaries(allTestSummaries, "by-scenario");
|
|
2186
|
+
const byScenario = categorizeComparisonGroups(comparisonConfig, [...groupsByScenario.values()]);
|
|
2187
|
+
const groupsByDataset = groupComparisonTestSummaries(allTestSummaries, "by-dataset");
|
|
2188
|
+
const byDataset = categorizeComparisonGroups(comparisonConfig, [...groupsByDataset.values()]);
|
|
2111
2189
|
return {
|
|
2112
|
-
|
|
2113
|
-
|
|
2114
|
-
return promiseQueue.add(() => sourceModel.getDatasetsForScenario(scenario, datasetKeys));
|
|
2115
|
-
},
|
|
2116
|
-
getGraphsForDataset: (_a = sourceModel.getGraphsForDataset) == null ? void 0 : _a.bind(sourceModel),
|
|
2117
|
-
getGraphDataForScenario: (scenario, graphId) => {
|
|
2118
|
-
return promiseQueue.add(() => sourceModel.getGraphDataForScenario(scenario, graphId));
|
|
2119
|
-
},
|
|
2120
|
-
getGraphLinksForScenario: sourceModel.getGraphLinksForScenario.bind(sourceModel)
|
|
2190
|
+
byScenario,
|
|
2191
|
+
byDataset
|
|
2121
2192
|
};
|
|
2122
2193
|
}
|
|
2123
|
-
|
|
2124
|
-
|
|
2125
|
-
|
|
2126
|
-
|
|
2194
|
+
function groupComparisonTestSummaries(testSummaries, groupKind) {
|
|
2195
|
+
const groups = /* @__PURE__ */ new Map();
|
|
2196
|
+
for (const testSummary of testSummaries) {
|
|
2197
|
+
let groupKey;
|
|
2198
|
+
switch (groupKind) {
|
|
2199
|
+
case "by-dataset":
|
|
2200
|
+
groupKey = testSummary.d;
|
|
2201
|
+
break;
|
|
2202
|
+
case "by-scenario":
|
|
2203
|
+
groupKey = testSummary.s;
|
|
2204
|
+
break;
|
|
2205
|
+
default:
|
|
2206
|
+
(0, import_assert_never8.assertNever)(groupKind);
|
|
2207
|
+
}
|
|
2208
|
+
const group = groups.get(groupKey);
|
|
2209
|
+
if (group) {
|
|
2210
|
+
group.testSummaries.push(testSummary);
|
|
2211
|
+
} else {
|
|
2212
|
+
groups.set(groupKey, {
|
|
2213
|
+
kind: groupKind,
|
|
2214
|
+
key: groupKey,
|
|
2215
|
+
testSummaries: [testSummary]
|
|
2216
|
+
});
|
|
2217
|
+
}
|
|
2127
2218
|
}
|
|
2128
|
-
|
|
2129
|
-
|
|
2130
|
-
|
|
2131
|
-
|
|
2132
|
-
|
|
2133
|
-
|
|
2134
|
-
|
|
2135
|
-
|
|
2136
|
-
|
|
2137
|
-
|
|
2138
|
-
|
|
2139
|
-
|
|
2140
|
-
|
|
2141
|
-
|
|
2142
|
-
|
|
2143
|
-
|
|
2144
|
-
|
|
2219
|
+
return groups;
|
|
2220
|
+
}
|
|
2221
|
+
function categorizeComparisonGroups(comparisonConfig, allGroups) {
|
|
2222
|
+
const allGroupSummaries = /* @__PURE__ */ new Map();
|
|
2223
|
+
const withErrors = [];
|
|
2224
|
+
const onlyInLeft = [];
|
|
2225
|
+
const onlyInRight = [];
|
|
2226
|
+
let withDiffs = [];
|
|
2227
|
+
const withoutDiffs = [];
|
|
2228
|
+
function addSummaryForGroup(group, root, validInL, validInR) {
|
|
2229
|
+
let scores;
|
|
2230
|
+
if (validInL && validInR) {
|
|
2231
|
+
scores = getScoresForGroup(group, comparisonConfig.thresholds);
|
|
2232
|
+
}
|
|
2233
|
+
const groupSummary = {
|
|
2234
|
+
root,
|
|
2235
|
+
group,
|
|
2236
|
+
scores
|
|
2237
|
+
};
|
|
2238
|
+
allGroupSummaries.set(group.key, groupSummary);
|
|
2239
|
+
if (validInL && validInR) {
|
|
2240
|
+
if (scores.totalDiffCount !== scores.diffCountByBucket[0]) {
|
|
2241
|
+
withDiffs.push(groupSummary);
|
|
2145
2242
|
} else {
|
|
2146
|
-
|
|
2243
|
+
withoutDiffs.push(groupSummary);
|
|
2147
2244
|
}
|
|
2148
|
-
})
|
|
2245
|
+
} else if (validInL) {
|
|
2246
|
+
onlyInLeft.push(groupSummary);
|
|
2247
|
+
} else if (validInR) {
|
|
2248
|
+
onlyInRight.push(groupSummary);
|
|
2249
|
+
} else {
|
|
2250
|
+
withErrors.push(groupSummary);
|
|
2251
|
+
}
|
|
2149
2252
|
}
|
|
2150
|
-
|
|
2151
|
-
|
|
2152
|
-
|
|
2153
|
-
|
|
2154
|
-
|
|
2253
|
+
for (const group of allGroups.values()) {
|
|
2254
|
+
switch (group.kind) {
|
|
2255
|
+
case "by-dataset": {
|
|
2256
|
+
const dataset = comparisonConfig.datasets.getDataset(group.key);
|
|
2257
|
+
const validInL = (dataset == null ? void 0 : dataset.outputVarL) !== void 0;
|
|
2258
|
+
const validInR = (dataset == null ? void 0 : dataset.outputVarR) !== void 0;
|
|
2259
|
+
addSummaryForGroup(group, dataset, validInL, validInR);
|
|
2260
|
+
break;
|
|
2155
2261
|
}
|
|
2262
|
+
case "by-scenario": {
|
|
2263
|
+
const scenario = comparisonConfig.scenarios.getScenario(group.key);
|
|
2264
|
+
const validInL = (scenario == null ? void 0 : scenario.specL) !== void 0;
|
|
2265
|
+
const validInR = (scenario == null ? void 0 : scenario.specR) !== void 0;
|
|
2266
|
+
addSummaryForGroup(group, scenario, validInL, validInR);
|
|
2267
|
+
break;
|
|
2268
|
+
}
|
|
2269
|
+
default:
|
|
2270
|
+
(0, import_assert_never8.assertNever)(group.kind);
|
|
2156
2271
|
}
|
|
2157
2272
|
}
|
|
2158
|
-
|
|
2159
|
-
|
|
2160
|
-
|
|
2161
|
-
|
|
2162
|
-
|
|
2163
|
-
|
|
2164
|
-
let currentBundle;
|
|
2165
|
-
let compareConfig;
|
|
2166
|
-
if (options.compare === void 0) {
|
|
2167
|
-
currentBundle = origCurrentBundle;
|
|
2168
|
-
} else {
|
|
2169
|
-
const baselineBundle = await loadSynchronized(options.compare.baseline);
|
|
2170
|
-
const renamedDatasetKeys = options.compare.datasets.renamedDatasetKeys;
|
|
2171
|
-
const invertedRenamedKeys = /* @__PURE__ */ new Map();
|
|
2172
|
-
renamedDatasetKeys == null ? void 0 : renamedDatasetKeys.forEach((newKey, oldKey) => {
|
|
2173
|
-
invertedRenamedKeys.set(newKey, oldKey);
|
|
2174
|
-
});
|
|
2175
|
-
const rightKeyForLeftKey = (leftKey) => {
|
|
2176
|
-
return (renamedDatasetKeys == null ? void 0 : renamedDatasetKeys.get(leftKey)) || leftKey;
|
|
2177
|
-
};
|
|
2178
|
-
const leftKeyForRightKey = (rightKey) => {
|
|
2179
|
-
return invertedRenamedKeys.get(rightKey) || rightKey;
|
|
2180
|
-
};
|
|
2181
|
-
const origBundleModelR = origCurrentBundle.model;
|
|
2182
|
-
const adjBundleModelR = {
|
|
2183
|
-
modelSpec: origBundleModelR.modelSpec,
|
|
2184
|
-
getDatasetsForScenario: async (scenario, datasetKeys) => {
|
|
2185
|
-
const rightKeys = datasetKeys.map(rightKeyForLeftKey);
|
|
2186
|
-
const result = await origBundleModelR.getDatasetsForScenario(scenario, rightKeys);
|
|
2187
|
-
const mapWithRightKeys = result.datasetMap;
|
|
2188
|
-
const mapWithLeftKeys = /* @__PURE__ */ new Map();
|
|
2189
|
-
for (const [rightKey, dataset] of mapWithRightKeys.entries()) {
|
|
2190
|
-
const leftKey = leftKeyForRightKey(rightKey);
|
|
2191
|
-
mapWithLeftKeys.set(leftKey, dataset);
|
|
2192
|
-
}
|
|
2193
|
-
return {
|
|
2194
|
-
datasetMap: mapWithLeftKeys,
|
|
2195
|
-
modelRunTime: result.modelRunTime
|
|
2196
|
-
};
|
|
2197
|
-
},
|
|
2198
|
-
getGraphsForDataset: (_a = origBundleModelR.getGraphsForDataset) == null ? void 0 : _a.bind(origBundleModelR),
|
|
2199
|
-
getGraphDataForScenario: origBundleModelR.getGraphDataForScenario.bind(origBundleModelR),
|
|
2200
|
-
getGraphLinksForScenario: origBundleModelR.getGraphLinksForScenario.bind(origBundleModelR)
|
|
2201
|
-
};
|
|
2202
|
-
currentBundle = __spreadProps(__spreadValues({}, origCurrentBundle), {
|
|
2203
|
-
model: adjBundleModelR
|
|
2204
|
-
});
|
|
2205
|
-
compareConfig = {
|
|
2206
|
-
bundleL: baselineBundle,
|
|
2207
|
-
bundleR: currentBundle,
|
|
2208
|
-
thresholds: options.compare.thresholds,
|
|
2209
|
-
scenarios: options.compare.scenarios,
|
|
2210
|
-
datasets: options.compare.datasets
|
|
2211
|
-
};
|
|
2273
|
+
if (withDiffs.length > 1) {
|
|
2274
|
+
if (withDiffs[0].group.kind === "by-dataset") {
|
|
2275
|
+
withDiffs = sortDatasetGroupSummaries(withDiffs);
|
|
2276
|
+
} else if (withDiffs[0].group.kind === "by-scenario") {
|
|
2277
|
+
withDiffs = sortScenarioGroupSummaries(withDiffs);
|
|
2278
|
+
}
|
|
2212
2279
|
}
|
|
2213
|
-
const checkConfig = {
|
|
2214
|
-
bundle: currentBundle,
|
|
2215
|
-
tests: options.check.tests
|
|
2216
|
-
};
|
|
2217
2280
|
return {
|
|
2218
|
-
|
|
2219
|
-
|
|
2281
|
+
allGroupSummaries,
|
|
2282
|
+
withErrors,
|
|
2283
|
+
onlyInLeft,
|
|
2284
|
+
onlyInRight,
|
|
2285
|
+
withDiffs,
|
|
2286
|
+
withoutDiffs
|
|
2220
2287
|
};
|
|
2221
2288
|
}
|
|
2222
|
-
|
|
2223
|
-
const
|
|
2224
|
-
const
|
|
2289
|
+
function getScoresForGroup(group, thresholds) {
|
|
2290
|
+
const diffCountByBucket = Array(thresholds.length + 2).fill(0);
|
|
2291
|
+
const totalMaxDiffByBucket = Array(thresholds.length + 2).fill(0);
|
|
2292
|
+
let totalDiffCount = 0;
|
|
2293
|
+
for (const testSummary of group.testSummaries) {
|
|
2294
|
+
const bucketIndex = getBucketIndex(testSummary.md, thresholds);
|
|
2295
|
+
diffCountByBucket[bucketIndex]++;
|
|
2296
|
+
totalMaxDiffByBucket[bucketIndex] += testSummary.md;
|
|
2297
|
+
totalDiffCount++;
|
|
2298
|
+
}
|
|
2299
|
+
let diffPercentByBucket;
|
|
2300
|
+
if (totalDiffCount > 0) {
|
|
2301
|
+
diffPercentByBucket = diffCountByBucket.map((count) => count / totalDiffCount * 100);
|
|
2302
|
+
} else {
|
|
2303
|
+
diffPercentByBucket = [];
|
|
2304
|
+
}
|
|
2225
2305
|
return {
|
|
2226
|
-
|
|
2227
|
-
|
|
2228
|
-
|
|
2306
|
+
totalDiffCount,
|
|
2307
|
+
totalMaxDiffByBucket,
|
|
2308
|
+
diffCountByBucket,
|
|
2309
|
+
diffPercentByBucket
|
|
2229
2310
|
};
|
|
2230
2311
|
}
|
|
2231
|
-
|
|
2232
|
-
|
|
2233
|
-
var
|
|
2234
|
-
|
|
2235
|
-
|
|
2236
|
-
|
|
2237
|
-
|
|
2238
|
-
|
|
2239
|
-
|
|
2240
|
-
|
|
2241
|
-
|
|
2242
|
-
|
|
2243
|
-
|
|
2312
|
+
function sortDatasetGroupSummaries(summaries) {
|
|
2313
|
+
return summaries.sort((a, b) => {
|
|
2314
|
+
var _a, _b;
|
|
2315
|
+
const scoreResult = compareScores(a.scores, b.scores);
|
|
2316
|
+
if (scoreResult !== 0) {
|
|
2317
|
+
return -scoreResult;
|
|
2318
|
+
} else {
|
|
2319
|
+
const aVar = a.root.outputVarL;
|
|
2320
|
+
const bVar = b.root.outputVarR;
|
|
2321
|
+
const aSource = ((_a = aVar.sourceName) == null ? void 0 : _a.toLowerCase()) || "";
|
|
2322
|
+
const bSource = ((_b = bVar.sourceName) == null ? void 0 : _b.toLowerCase()) || "";
|
|
2323
|
+
if (aSource !== bSource) {
|
|
2324
|
+
return aSource.localeCompare(bSource);
|
|
2325
|
+
} else {
|
|
2326
|
+
const aName = aVar.varName.toLowerCase();
|
|
2327
|
+
const bName = bVar.varName.toLowerCase();
|
|
2328
|
+
return aName.localeCompare(bName);
|
|
2329
|
+
}
|
|
2244
2330
|
}
|
|
2245
|
-
|
|
2246
|
-
|
|
2247
|
-
|
|
2248
|
-
|
|
2249
|
-
|
|
2250
|
-
|
|
2331
|
+
});
|
|
2332
|
+
}
|
|
2333
|
+
function sortScenarioGroupSummaries(summaries) {
|
|
2334
|
+
return summaries.sort((a, b) => {
|
|
2335
|
+
var _a, _b;
|
|
2336
|
+
const scoreResult = compareScores(a.scores, b.scores);
|
|
2337
|
+
if (scoreResult !== 0) {
|
|
2338
|
+
return -scoreResult;
|
|
2339
|
+
} else {
|
|
2340
|
+
const aScenario = a.root;
|
|
2341
|
+
const bScenario = b.root;
|
|
2342
|
+
const aTitle = aScenario.title.toLowerCase();
|
|
2343
|
+
const bTitle = bScenario.title.toLowerCase();
|
|
2344
|
+
if (aTitle !== bTitle) {
|
|
2345
|
+
return aTitle.localeCompare(bTitle);
|
|
2346
|
+
} else {
|
|
2347
|
+
const aSubtitle = ((_a = aScenario.subtitle) == null ? void 0 : _a.toLowerCase()) || "";
|
|
2348
|
+
const bSubtitle = ((_b = bScenario.subtitle) == null ? void 0 : _b.toLowerCase()) || "";
|
|
2349
|
+
return aSubtitle.localeCompare(bSubtitle);
|
|
2350
|
+
}
|
|
2351
|
+
}
|
|
2352
|
+
});
|
|
2353
|
+
}
|
|
2354
|
+
function compareScores(a, b) {
|
|
2355
|
+
if (a.totalMaxDiffByBucket.length !== b.totalMaxDiffByBucket.length) {
|
|
2356
|
+
return 0;
|
|
2357
|
+
}
|
|
2358
|
+
const len = a.totalMaxDiffByBucket.length;
|
|
2359
|
+
for (let i = len - 1; i >= 0; i--) {
|
|
2360
|
+
const aTotal = a.totalMaxDiffByBucket[i];
|
|
2361
|
+
const bTotal = b.totalMaxDiffByBucket[i];
|
|
2362
|
+
if (aTotal > bTotal) {
|
|
2363
|
+
return 1;
|
|
2364
|
+
} else if (aTotal < bTotal) {
|
|
2365
|
+
return -1;
|
|
2366
|
+
}
|
|
2367
|
+
}
|
|
2368
|
+
return 0;
|
|
2369
|
+
}
|
|
2370
|
+
|
|
2371
|
+
// src/bundle/model-inputs.ts
|
|
2372
|
+
var ModelInputs = class {
|
|
2373
|
+
constructor(modelSpec) {
|
|
2374
|
+
/** All inputs keyed by lookup name (lowercase variable name or alias). */
|
|
2375
|
+
this.inputsByLookupName = /* @__PURE__ */ new Map();
|
|
2376
|
+
/** All input ID aliases. */
|
|
2377
|
+
this.inputIdAliases = /* @__PURE__ */ new Set();
|
|
2378
|
+
for (const inputVar of modelSpec.inputVars.values()) {
|
|
2379
|
+
const varNameKey = inputVar.varName.toLowerCase();
|
|
2380
|
+
this.inputsByLookupName.set(varNameKey, inputVar);
|
|
2381
|
+
if (inputVar.inputId) {
|
|
2382
|
+
const idAlias = `id ${inputVar.inputId}`;
|
|
2383
|
+
this.inputIdAliases.add(idAlias);
|
|
2384
|
+
const idKey = idAlias.toLowerCase();
|
|
2385
|
+
this.inputsByLookupName.set(idKey, inputVar);
|
|
2386
|
+
}
|
|
2387
|
+
}
|
|
2388
|
+
if (modelSpec.inputAliases) {
|
|
2389
|
+
for (const [alias, varId] of modelSpec.inputAliases.entries()) {
|
|
2390
|
+
const aliasKey = alias.toLowerCase();
|
|
2391
|
+
if (this.inputsByLookupName.has(aliasKey)) {
|
|
2392
|
+
console.warn(
|
|
2393
|
+
`WARNING: Input variable already defined with a name that collides with alias '${alias}', skipping`
|
|
2394
|
+
);
|
|
2395
|
+
continue;
|
|
2396
|
+
}
|
|
2397
|
+
const inputVar = modelSpec.inputVars.get(varId);
|
|
2398
|
+
if (inputVar === void 0) {
|
|
2399
|
+
console.warn(`WARNING: No input variable found for '${varId}' associated with alias '${alias}', skipping`);
|
|
2400
|
+
continue;
|
|
2401
|
+
}
|
|
2402
|
+
this.inputsByLookupName.set(aliasKey, inputVar);
|
|
2403
|
+
}
|
|
2404
|
+
}
|
|
2405
|
+
}
|
|
2406
|
+
/**
|
|
2407
|
+
* Return the set of `id XYZ` aliases for all input variables.
|
|
2408
|
+
*/
|
|
2409
|
+
getAllInputIdAliases() {
|
|
2410
|
+
return [...this.inputIdAliases];
|
|
2411
|
+
}
|
|
2412
|
+
/**
|
|
2413
|
+
* Return the `InputVar` that matches the requested name (either by variable name or alias).
|
|
2414
|
+
*
|
|
2415
|
+
* @param name The variable name or alias to match.
|
|
2416
|
+
*/
|
|
2417
|
+
getInputVarForName(name) {
|
|
2418
|
+
return this.inputsByLookupName.get(name.toLowerCase());
|
|
2419
|
+
}
|
|
2420
|
+
};
|
|
2421
|
+
|
|
2422
|
+
// src/comparison/config/parse/comparison-parser.ts
|
|
2423
|
+
var import_ajv2 = __toESM(require("ajv"), 1);
|
|
2424
|
+
var import_assert_never9 = __toESM(require("assert-never"), 1);
|
|
2425
|
+
var import_neverthrow2 = require("neverthrow");
|
|
2426
|
+
var import_yaml2 = __toESM(require("yaml"), 1);
|
|
2427
|
+
|
|
2428
|
+
// src/comparison/config/parse/comparison.schema.js
|
|
2429
|
+
var comparison_schema_default = {
|
|
2430
|
+
$schema: "http://json-schema.org/draft-07/schema#",
|
|
2431
|
+
title: "Model Comparison Test",
|
|
2432
|
+
type: "array",
|
|
2433
|
+
description: "A group of model comparison scenarios and views.",
|
|
2434
|
+
items: {
|
|
2435
|
+
$ref: "#/$defs/top_level_array_item"
|
|
2436
|
+
},
|
|
2437
|
+
$defs: {
|
|
2438
|
+
//
|
|
2439
|
+
// TOP-LEVEL
|
|
2440
|
+
//
|
|
2441
|
+
top_level_array_item: {
|
|
2442
|
+
oneOf: [
|
|
2443
|
+
{ $ref: "#/$defs/scenario_array_item" },
|
|
2444
|
+
{ $ref: "#/$defs/scenario_group_array_item" },
|
|
2445
|
+
{ $ref: "#/$defs/view_group_array_item" }
|
|
2446
|
+
]
|
|
2447
|
+
},
|
|
2448
|
+
//
|
|
2449
|
+
// SCENARIOS
|
|
2450
|
+
//
|
|
2451
|
+
scenario_array_item: {
|
|
2452
|
+
type: "object",
|
|
2453
|
+
additionalProperties: false,
|
|
2454
|
+
properties: {
|
|
2455
|
+
scenario: {
|
|
2456
|
+
$ref: "#/$defs/scenario"
|
|
2457
|
+
}
|
|
2458
|
+
},
|
|
2459
|
+
required: ["scenario"]
|
|
2460
|
+
},
|
|
2461
|
+
scenario: {
|
|
2462
|
+
oneOf: [
|
|
2463
|
+
{ $ref: "#/$defs/scenario_with_input_at_position" },
|
|
2464
|
+
{ $ref: "#/$defs/scenario_with_input_at_value" },
|
|
2465
|
+
{ $ref: "#/$defs/scenario_with_multiple_input_settings" },
|
|
2466
|
+
{ $ref: "#/$defs/scenario_with_inputs_in_preset_at_position" },
|
|
2467
|
+
// { $ref: '#/$defs/scenario_with_inputs_in_group_at_position' }
|
|
2468
|
+
{ $ref: "#/$defs/scenario_preset" }
|
|
2469
|
+
// { $ref: '#/$defs/scenario_expand_for_each_input_in_group' }
|
|
2470
|
+
]
|
|
2471
|
+
},
|
|
2472
|
+
scenario_position: {
|
|
2473
|
+
type: "string",
|
|
2474
|
+
enum: ["min", "max", "default"]
|
|
2475
|
+
},
|
|
2476
|
+
scenario_with_input_at_position: {
|
|
2477
|
+
type: "object",
|
|
2478
|
+
additionalProperties: false,
|
|
2479
|
+
properties: {
|
|
2480
|
+
id: {
|
|
2481
|
+
type: "string"
|
|
2482
|
+
},
|
|
2483
|
+
title: {
|
|
2484
|
+
type: "string"
|
|
2485
|
+
},
|
|
2486
|
+
subtitle: {
|
|
2487
|
+
type: "string"
|
|
2488
|
+
},
|
|
2489
|
+
with: {
|
|
2490
|
+
type: "string"
|
|
2491
|
+
},
|
|
2492
|
+
at: {
|
|
2493
|
+
$ref: "#/$defs/scenario_position"
|
|
2494
|
+
}
|
|
2495
|
+
},
|
|
2496
|
+
required: ["with", "at"]
|
|
2497
|
+
},
|
|
2498
|
+
scenario_with_input_at_value: {
|
|
2499
|
+
type: "object",
|
|
2500
|
+
additionalProperties: false,
|
|
2501
|
+
properties: {
|
|
2502
|
+
id: {
|
|
2503
|
+
type: "string"
|
|
2504
|
+
},
|
|
2505
|
+
title: {
|
|
2506
|
+
type: "string"
|
|
2507
|
+
},
|
|
2508
|
+
subtitle: {
|
|
2509
|
+
type: "string"
|
|
2510
|
+
},
|
|
2511
|
+
with: {
|
|
2512
|
+
type: "string"
|
|
2513
|
+
},
|
|
2514
|
+
at: {
|
|
2515
|
+
type: "number"
|
|
2516
|
+
}
|
|
2517
|
+
},
|
|
2518
|
+
required: ["with", "at"]
|
|
2519
|
+
},
|
|
2520
|
+
scenario_input_at_position: {
|
|
2521
|
+
type: "object",
|
|
2522
|
+
additionalProperties: false,
|
|
2523
|
+
properties: {
|
|
2524
|
+
input: {
|
|
2525
|
+
type: "string"
|
|
2526
|
+
},
|
|
2527
|
+
at: {
|
|
2528
|
+
$ref: "#/$defs/scenario_position"
|
|
2529
|
+
}
|
|
2530
|
+
},
|
|
2531
|
+
required: ["input", "at"]
|
|
2532
|
+
},
|
|
2533
|
+
scenario_input_at_value: {
|
|
2534
|
+
type: "object",
|
|
2535
|
+
additionalProperties: false,
|
|
2536
|
+
properties: {
|
|
2537
|
+
input: {
|
|
2538
|
+
type: "string"
|
|
2539
|
+
},
|
|
2540
|
+
at: {
|
|
2541
|
+
type: "number"
|
|
2542
|
+
}
|
|
2543
|
+
},
|
|
2544
|
+
required: ["input", "at"]
|
|
2545
|
+
},
|
|
2546
|
+
scenario_input_setting: {
|
|
2547
|
+
oneOf: [{ $ref: "#/$defs/scenario_input_at_position" }, { $ref: "#/$defs/scenario_input_at_value" }]
|
|
2548
|
+
},
|
|
2549
|
+
scenario_input_setting_array: {
|
|
2550
|
+
type: "array",
|
|
2551
|
+
items: {
|
|
2552
|
+
$ref: "#/$defs/scenario_input_setting"
|
|
2553
|
+
},
|
|
2554
|
+
minItems: 1
|
|
2555
|
+
},
|
|
2556
|
+
scenario_with_multiple_input_settings: {
|
|
2557
|
+
type: "object",
|
|
2558
|
+
additionalProperties: false,
|
|
2559
|
+
properties: {
|
|
2560
|
+
id: {
|
|
2561
|
+
type: "string"
|
|
2562
|
+
},
|
|
2563
|
+
title: {
|
|
2564
|
+
type: "string"
|
|
2565
|
+
},
|
|
2566
|
+
subtitle: {
|
|
2567
|
+
type: "string"
|
|
2568
|
+
},
|
|
2569
|
+
with: {
|
|
2570
|
+
$ref: "#/$defs/scenario_input_setting_array"
|
|
2571
|
+
}
|
|
2572
|
+
},
|
|
2573
|
+
required: ["with"]
|
|
2574
|
+
},
|
|
2575
|
+
scenario_with_inputs_in_preset_at_position: {
|
|
2576
|
+
type: "object",
|
|
2577
|
+
additionalProperties: false,
|
|
2578
|
+
properties: {
|
|
2579
|
+
id: {
|
|
2580
|
+
type: "string"
|
|
2581
|
+
},
|
|
2582
|
+
title: {
|
|
2583
|
+
type: "string"
|
|
2584
|
+
},
|
|
2585
|
+
subtitle: {
|
|
2586
|
+
type: "string"
|
|
2587
|
+
},
|
|
2588
|
+
with_inputs: {
|
|
2589
|
+
type: "string",
|
|
2590
|
+
enum: ["all"]
|
|
2591
|
+
},
|
|
2592
|
+
at: {
|
|
2593
|
+
$ref: "#/$defs/scenario_position"
|
|
2594
|
+
}
|
|
2595
|
+
},
|
|
2596
|
+
required: ["with_inputs", "at"]
|
|
2597
|
+
},
|
|
2598
|
+
scenario_preset: {
|
|
2599
|
+
type: "object",
|
|
2600
|
+
additionalProperties: false,
|
|
2601
|
+
properties: {
|
|
2602
|
+
preset: {
|
|
2603
|
+
type: "string",
|
|
2604
|
+
enum: ["matrix"]
|
|
2605
|
+
}
|
|
2606
|
+
},
|
|
2607
|
+
required: ["preset"]
|
|
2608
|
+
},
|
|
2609
|
+
//
|
|
2610
|
+
// SCENARIO GROUPS
|
|
2611
|
+
//
|
|
2612
|
+
scenario_group_array_item: {
|
|
2613
|
+
type: "object",
|
|
2614
|
+
additionalProperties: false,
|
|
2615
|
+
properties: {
|
|
2616
|
+
scenario_group: {
|
|
2617
|
+
$ref: "#/$defs/scenario_group"
|
|
2618
|
+
}
|
|
2619
|
+
},
|
|
2620
|
+
required: ["scenario_group"]
|
|
2621
|
+
},
|
|
2622
|
+
scenario_group: {
|
|
2623
|
+
type: "object",
|
|
2624
|
+
additionalProperties: false,
|
|
2625
|
+
properties: {
|
|
2626
|
+
id: {
|
|
2627
|
+
type: "string"
|
|
2628
|
+
},
|
|
2629
|
+
title: {
|
|
2630
|
+
type: "string"
|
|
2631
|
+
},
|
|
2632
|
+
scenarios: {
|
|
2633
|
+
type: "array",
|
|
2634
|
+
items: {
|
|
2635
|
+
$ref: "#/$defs/scenario_group_scenarios_array_item"
|
|
2636
|
+
},
|
|
2637
|
+
minItems: 1
|
|
2638
|
+
}
|
|
2639
|
+
},
|
|
2640
|
+
required: ["title", "scenarios"]
|
|
2641
|
+
},
|
|
2642
|
+
scenario_group_scenarios_array_item: {
|
|
2643
|
+
oneOf: [{ $ref: "#/$defs/scenario_array_item" }, { $ref: "#/$defs/scenario_ref_array_item" }]
|
|
2644
|
+
},
|
|
2645
|
+
scenario_ref_id: {
|
|
2646
|
+
type: "string"
|
|
2647
|
+
},
|
|
2648
|
+
scenario_ref_object: {
|
|
2649
|
+
type: "object",
|
|
2650
|
+
additionalProperties: false,
|
|
2651
|
+
properties: {
|
|
2652
|
+
id: {
|
|
2653
|
+
type: "string"
|
|
2654
|
+
},
|
|
2655
|
+
title: {
|
|
2656
|
+
type: "string"
|
|
2657
|
+
},
|
|
2658
|
+
subtitle: {
|
|
2659
|
+
type: "string"
|
|
2660
|
+
}
|
|
2661
|
+
},
|
|
2662
|
+
required: ["id"]
|
|
2663
|
+
},
|
|
2664
|
+
scenario_ref: {
|
|
2665
|
+
oneOf: [{ $ref: "#/$defs/scenario_ref_id" }, { $ref: "#/$defs/scenario_ref_object" }]
|
|
2666
|
+
},
|
|
2667
|
+
scenario_ref_array_item: {
|
|
2668
|
+
type: "object",
|
|
2669
|
+
additionalProperties: false,
|
|
2670
|
+
properties: {
|
|
2671
|
+
scenario_ref: {
|
|
2672
|
+
$ref: "#/$defs/scenario_ref"
|
|
2673
|
+
}
|
|
2674
|
+
},
|
|
2675
|
+
required: ["scenario_ref"]
|
|
2676
|
+
},
|
|
2677
|
+
scenario_group_ref: {
|
|
2678
|
+
type: "object",
|
|
2679
|
+
additionalProperties: false,
|
|
2680
|
+
properties: {
|
|
2681
|
+
scenario_group_ref: {
|
|
2682
|
+
type: "string"
|
|
2683
|
+
}
|
|
2684
|
+
},
|
|
2685
|
+
required: ["scenario_group_ref"]
|
|
2686
|
+
},
|
|
2687
|
+
//
|
|
2688
|
+
// VIEWS
|
|
2689
|
+
//
|
|
2690
|
+
view: {
|
|
2691
|
+
type: "object",
|
|
2692
|
+
additionalProperties: false,
|
|
2693
|
+
properties: {
|
|
2694
|
+
title: {
|
|
2695
|
+
type: "string"
|
|
2696
|
+
},
|
|
2697
|
+
subtitle: {
|
|
2698
|
+
type: "string"
|
|
2699
|
+
},
|
|
2700
|
+
scenario_ref: {
|
|
2701
|
+
type: "string"
|
|
2702
|
+
},
|
|
2703
|
+
graphs: {
|
|
2704
|
+
$ref: "#/$defs/view_graphs"
|
|
2705
|
+
}
|
|
2706
|
+
},
|
|
2707
|
+
required: ["scenario_ref", "graphs"]
|
|
2708
|
+
},
|
|
2709
|
+
view_graphs: {
|
|
2710
|
+
oneOf: [{ $ref: "#/$defs/view_graphs_preset" }, { $ref: "#/$defs/view_graphs_array" }]
|
|
2711
|
+
},
|
|
2712
|
+
view_graphs_preset: {
|
|
2713
|
+
type: "string",
|
|
2714
|
+
enum: ["all"]
|
|
2715
|
+
},
|
|
2716
|
+
view_graphs_array: {
|
|
2717
|
+
type: "array",
|
|
2718
|
+
items: {
|
|
2719
|
+
type: "string"
|
|
2720
|
+
},
|
|
2721
|
+
minItems: 1
|
|
2722
|
+
},
|
|
2723
|
+
//
|
|
2724
|
+
// VIEW GROUPS
|
|
2725
|
+
//
|
|
2726
|
+
view_group_array_item: {
|
|
2727
|
+
type: "object",
|
|
2728
|
+
additionalProperties: false,
|
|
2729
|
+
properties: {
|
|
2730
|
+
view_group: {
|
|
2731
|
+
$ref: "#/$defs/view_group"
|
|
2732
|
+
}
|
|
2733
|
+
},
|
|
2734
|
+
required: ["view_group"]
|
|
2735
|
+
},
|
|
2736
|
+
view_group: {
|
|
2737
|
+
oneOf: [
|
|
2738
|
+
{ $ref: "#/$defs/view_group_with_views_array" },
|
|
2739
|
+
{ $ref: "#/$defs/view_group_shorthand_with_scenarios_array" }
|
|
2740
|
+
]
|
|
2741
|
+
},
|
|
2742
|
+
view_group_with_views_array: {
|
|
2743
|
+
type: "object",
|
|
2744
|
+
additionalProperties: false,
|
|
2745
|
+
properties: {
|
|
2746
|
+
title: {
|
|
2747
|
+
type: "string"
|
|
2748
|
+
},
|
|
2749
|
+
views: {
|
|
2750
|
+
type: "array",
|
|
2751
|
+
items: {
|
|
2752
|
+
$ref: "#/$defs/view_group_views_array_item"
|
|
2753
|
+
},
|
|
2754
|
+
minItems: 1
|
|
2755
|
+
}
|
|
2756
|
+
},
|
|
2757
|
+
required: ["title", "views"]
|
|
2758
|
+
},
|
|
2759
|
+
view_group_views_array_item: {
|
|
2760
|
+
type: "object",
|
|
2761
|
+
additionalProperties: false,
|
|
2762
|
+
properties: {
|
|
2763
|
+
view: {
|
|
2764
|
+
$ref: "#/$defs/view"
|
|
2765
|
+
}
|
|
2766
|
+
}
|
|
2767
|
+
},
|
|
2768
|
+
view_group_shorthand_with_scenarios_array: {
|
|
2769
|
+
type: "object",
|
|
2770
|
+
additionalProperties: false,
|
|
2771
|
+
properties: {
|
|
2772
|
+
title: {
|
|
2773
|
+
type: "string"
|
|
2774
|
+
},
|
|
2775
|
+
scenarios: {
|
|
2776
|
+
type: "array",
|
|
2777
|
+
items: {
|
|
2778
|
+
$ref: "#/$defs/view_group_scenarios_array_item"
|
|
2779
|
+
},
|
|
2780
|
+
minItems: 1
|
|
2781
|
+
},
|
|
2782
|
+
graphs: {
|
|
2783
|
+
$ref: "#/$defs/view_graphs"
|
|
2784
|
+
}
|
|
2785
|
+
},
|
|
2786
|
+
required: ["title", "scenarios", "graphs"]
|
|
2787
|
+
},
|
|
2788
|
+
view_group_scenarios_array_item: {
|
|
2789
|
+
oneOf: [{ $ref: "#/$defs/scenario_ref_array_item" }, { $ref: "#/$defs/scenario_group_ref" }]
|
|
2790
|
+
}
|
|
2791
|
+
}
|
|
2792
|
+
};
|
|
2793
|
+
|
|
2794
|
+
// src/comparison/config/parse/comparison-parser.ts
|
|
2795
|
+
function parseComparisonSpecs(specSource) {
|
|
2796
|
+
const scenarios = [];
|
|
2797
|
+
const scenarioGroups = [];
|
|
2798
|
+
const viewGroups = [];
|
|
2799
|
+
const ajv = new import_ajv2.default();
|
|
2800
|
+
const validate = ajv.compile(comparison_schema_default);
|
|
2801
|
+
let parsed;
|
|
2802
|
+
switch (specSource.kind) {
|
|
2803
|
+
case "json":
|
|
2804
|
+
parsed = JSON.parse(specSource.content);
|
|
2805
|
+
break;
|
|
2806
|
+
case "yaml":
|
|
2807
|
+
parsed = import_yaml2.default.parse(specSource.content);
|
|
2808
|
+
break;
|
|
2809
|
+
default:
|
|
2810
|
+
(0, import_assert_never9.default)(specSource.kind);
|
|
2811
|
+
}
|
|
2812
|
+
if (validate(parsed)) {
|
|
2813
|
+
for (const specItem of parsed) {
|
|
2814
|
+
if ("scenario" in specItem) {
|
|
2815
|
+
scenarios.push(scenarioSpecFromParsed(specItem.scenario));
|
|
2816
|
+
} else if ("scenario_group" in specItem) {
|
|
2817
|
+
scenarioGroups.push(scenarioGroupSpecFromParsed(specItem.scenario_group));
|
|
2818
|
+
} else if ("view_group" in specItem) {
|
|
2819
|
+
viewGroups.push(viewGroupSpecFromParsed(specItem.view_group));
|
|
2820
|
+
}
|
|
2821
|
+
}
|
|
2822
|
+
} else {
|
|
2823
|
+
let msg = "Failed to parse YAML comparison definitions";
|
|
2824
|
+
for (const error of validate.errors || []) {
|
|
2825
|
+
if (error.message) {
|
|
2826
|
+
msg += `
|
|
2827
|
+
${error.message}`;
|
|
2828
|
+
}
|
|
2829
|
+
}
|
|
2830
|
+
return (0, import_neverthrow2.err)(new Error(msg));
|
|
2831
|
+
}
|
|
2832
|
+
return (0, import_neverthrow2.ok)({
|
|
2833
|
+
scenarios,
|
|
2834
|
+
scenarioGroups,
|
|
2835
|
+
viewGroups
|
|
2836
|
+
});
|
|
2837
|
+
}
|
|
2838
|
+
function scenarioSpecFromParsed(parsedScenario) {
|
|
2839
|
+
if (parsedScenario.preset === "matrix") {
|
|
2840
|
+
return {
|
|
2841
|
+
kind: "scenario-matrix"
|
|
2842
|
+
};
|
|
2843
|
+
}
|
|
2844
|
+
if (parsedScenario.with !== void 0) {
|
|
2845
|
+
let inputSpecs;
|
|
2846
|
+
if (Array.isArray(parsedScenario.with)) {
|
|
2847
|
+
const parsedInputs = parsedScenario.with;
|
|
2848
|
+
inputSpecs = parsedInputs.map(inputSpecFromParsed);
|
|
2849
|
+
} else {
|
|
2850
|
+
inputSpecs = [
|
|
2851
|
+
inputSpecFromParsed({
|
|
2852
|
+
input: parsedScenario.with,
|
|
2853
|
+
at: parsedScenario.at
|
|
2854
|
+
})
|
|
2855
|
+
];
|
|
2856
|
+
}
|
|
2857
|
+
return {
|
|
2858
|
+
kind: "scenario-with-inputs",
|
|
2859
|
+
id: parsedScenario.id,
|
|
2860
|
+
title: parsedScenario.title,
|
|
2861
|
+
subtitle: parsedScenario.subtitle,
|
|
2862
|
+
inputs: inputSpecs
|
|
2863
|
+
};
|
|
2864
|
+
}
|
|
2865
|
+
if (parsedScenario.with_inputs === "all") {
|
|
2866
|
+
return {
|
|
2867
|
+
kind: "scenario-with-all-inputs",
|
|
2868
|
+
id: parsedScenario.id,
|
|
2869
|
+
title: parsedScenario.title,
|
|
2870
|
+
subtitle: parsedScenario.subtitle,
|
|
2871
|
+
position: parsedScenario.at
|
|
2872
|
+
};
|
|
2873
|
+
}
|
|
2874
|
+
throw new Error(`Unable to convert parsed scenario: ${JSON.stringify(parsedScenario)}`);
|
|
2875
|
+
}
|
|
2876
|
+
function inputSpecFromParsed(parsedInput) {
|
|
2877
|
+
if (typeof parsedInput.at === "number") {
|
|
2878
|
+
const value = parsedInput.at;
|
|
2879
|
+
return {
|
|
2880
|
+
kind: "input-at-value",
|
|
2881
|
+
inputName: parsedInput.input,
|
|
2882
|
+
value
|
|
2883
|
+
};
|
|
2884
|
+
} else {
|
|
2885
|
+
return {
|
|
2886
|
+
kind: "input-at-position",
|
|
2887
|
+
inputName: parsedInput.input,
|
|
2888
|
+
position: parsedInput.at
|
|
2889
|
+
};
|
|
2890
|
+
}
|
|
2891
|
+
}
|
|
2892
|
+
function scenarioGroupSpecFromParsed(parsedScenarioGroup) {
|
|
2893
|
+
const scenarioSpecs = parsedScenarioGroup.scenarios.map(
|
|
2894
|
+
(parsedScenarioOrRef) => {
|
|
2895
|
+
if ("scenario_ref" in parsedScenarioOrRef) {
|
|
2896
|
+
return scenarioRefSpecFromParsed(parsedScenarioOrRef);
|
|
2897
|
+
} else {
|
|
2898
|
+
return scenarioSpecFromParsed(parsedScenarioOrRef.scenario);
|
|
2899
|
+
}
|
|
2900
|
+
}
|
|
2901
|
+
);
|
|
2902
|
+
return {
|
|
2903
|
+
kind: "scenario-group",
|
|
2904
|
+
id: parsedScenarioGroup.id,
|
|
2905
|
+
title: parsedScenarioGroup.title,
|
|
2906
|
+
scenarios: scenarioSpecs
|
|
2907
|
+
};
|
|
2908
|
+
}
|
|
2909
|
+
function scenarioRefSpecFromParsed(parsedScenarioRef) {
|
|
2910
|
+
if (typeof parsedScenarioRef.scenario_ref === "string") {
|
|
2911
|
+
return {
|
|
2912
|
+
kind: "scenario-ref",
|
|
2913
|
+
scenarioId: parsedScenarioRef.scenario_ref
|
|
2914
|
+
};
|
|
2915
|
+
} else {
|
|
2916
|
+
return {
|
|
2917
|
+
kind: "scenario-ref",
|
|
2918
|
+
scenarioId: parsedScenarioRef.scenario_ref.id,
|
|
2919
|
+
title: parsedScenarioRef.scenario_ref.title,
|
|
2920
|
+
subtitle: parsedScenarioRef.scenario_ref.subtitle
|
|
2921
|
+
};
|
|
2922
|
+
}
|
|
2923
|
+
}
|
|
2924
|
+
function scenarioGroupRefSpecFromParsed(parsedGroupRef) {
|
|
2925
|
+
return {
|
|
2926
|
+
kind: "scenario-group-ref",
|
|
2927
|
+
groupId: parsedGroupRef.scenario_group_ref
|
|
2928
|
+
};
|
|
2929
|
+
}
|
|
2930
|
+
function viewSpecFromParsed(parsedView) {
|
|
2931
|
+
return {
|
|
2932
|
+
kind: "view",
|
|
2933
|
+
title: parsedView.title,
|
|
2934
|
+
subtitle: parsedView.subtitle,
|
|
2935
|
+
scenarioId: parsedView.scenario_ref,
|
|
2936
|
+
graphs: viewGraphsSpecFromParsed(parsedView.graphs)
|
|
2937
|
+
};
|
|
2938
|
+
}
|
|
2939
|
+
function viewGraphsSpecFromParsed(parsedGraphs) {
|
|
2940
|
+
if (parsedGraphs === "all") {
|
|
2941
|
+
return {
|
|
2942
|
+
kind: "graphs-preset",
|
|
2943
|
+
preset: "all"
|
|
2944
|
+
};
|
|
2945
|
+
} else {
|
|
2946
|
+
return {
|
|
2947
|
+
kind: "graphs-array",
|
|
2948
|
+
graphIds: parsedGraphs
|
|
2949
|
+
};
|
|
2950
|
+
}
|
|
2951
|
+
}
|
|
2952
|
+
function viewGroupSpecFromParsed(parsedViewGroup) {
|
|
2953
|
+
if (parsedViewGroup.views !== void 0) {
|
|
2954
|
+
return {
|
|
2955
|
+
kind: "view-group-with-views",
|
|
2956
|
+
title: parsedViewGroup.title,
|
|
2957
|
+
views: parsedViewGroup.views.map((item) => viewSpecFromParsed(item.view))
|
|
2958
|
+
};
|
|
2959
|
+
} else if (parsedViewGroup.scenarios !== void 0) {
|
|
2960
|
+
const scenarios = parsedViewGroup.scenarios.map(
|
|
2961
|
+
(parsedScenarioOrGroupRef) => {
|
|
2962
|
+
if ("scenario_ref" in parsedScenarioOrGroupRef) {
|
|
2963
|
+
return scenarioRefSpecFromParsed(parsedScenarioOrGroupRef);
|
|
2964
|
+
} else if ("scenario_group_ref" in parsedScenarioOrGroupRef) {
|
|
2965
|
+
return scenarioGroupRefSpecFromParsed(parsedScenarioOrGroupRef);
|
|
2966
|
+
} else {
|
|
2967
|
+
throw new Error("Invalid view group");
|
|
2968
|
+
}
|
|
2969
|
+
}
|
|
2970
|
+
);
|
|
2971
|
+
return {
|
|
2972
|
+
kind: "view-group-with-scenarios",
|
|
2973
|
+
title: parsedViewGroup.title,
|
|
2974
|
+
scenarios,
|
|
2975
|
+
graphs: viewGraphsSpecFromParsed(parsedViewGroup.graphs)
|
|
2976
|
+
};
|
|
2977
|
+
} else {
|
|
2978
|
+
throw new Error("Invalid view group");
|
|
2979
|
+
}
|
|
2980
|
+
}
|
|
2981
|
+
|
|
2982
|
+
// src/comparison/config/resolve/comparison-resolver.ts
|
|
2983
|
+
var import_assert_never11 = require("assert-never");
|
|
2984
|
+
|
|
2985
|
+
// src/comparison/config/resolve/comparison-scenario-specs.ts
|
|
2986
|
+
var import_assert_never10 = require("assert-never");
|
|
2987
|
+
function scenarioSpecsFromSettings(settings) {
|
|
2988
|
+
switch (settings.kind) {
|
|
2989
|
+
case "all-inputs-settings": {
|
|
2990
|
+
const scenario = allInputsAtPositionSpec(settings.position);
|
|
2991
|
+
return [scenario, scenario];
|
|
2992
|
+
}
|
|
2993
|
+
case "input-settings": {
|
|
2994
|
+
const specL = scenarioSpecFromInputs(settings.inputs, "left");
|
|
2995
|
+
const specR = scenarioSpecFromInputs(settings.inputs, "right");
|
|
2996
|
+
return [specL, specR];
|
|
2997
|
+
}
|
|
2998
|
+
default:
|
|
2999
|
+
(0, import_assert_never10.assertNever)(settings);
|
|
3000
|
+
}
|
|
3001
|
+
}
|
|
3002
|
+
function scenarioSpecFromInputs(inputs, side) {
|
|
3003
|
+
const settings = [];
|
|
3004
|
+
for (const input of inputs) {
|
|
3005
|
+
const state = side === "left" ? input.stateL : input.stateR;
|
|
3006
|
+
if (state.inputVar === void 0) {
|
|
3007
|
+
return void 0;
|
|
3008
|
+
}
|
|
3009
|
+
settings.push(inputSettingFromResolvedInputState(state));
|
|
3010
|
+
}
|
|
3011
|
+
return inputSettingsSpec(settings);
|
|
3012
|
+
}
|
|
3013
|
+
function inputSettingFromResolvedInputState(state) {
|
|
3014
|
+
const varId = state.inputVar.varId;
|
|
3015
|
+
if (state.position) {
|
|
3016
|
+
return positionSetting(varId, state.position);
|
|
3017
|
+
} else {
|
|
3018
|
+
return valueSetting(varId, state.value);
|
|
3019
|
+
}
|
|
3020
|
+
}
|
|
3021
|
+
|
|
3022
|
+
// src/comparison/config/resolve/comparison-resolver.ts
|
|
3023
|
+
function resolveComparisonSpecs(modelInputsL, modelInputsR, specs) {
|
|
3024
|
+
let key = 1;
|
|
3025
|
+
const genKey = () => {
|
|
3026
|
+
return `${key++}`;
|
|
3027
|
+
};
|
|
3028
|
+
const resolvedScenarios = new ResolvedScenarios();
|
|
3029
|
+
for (const scenarioSpec of specs.scenarios) {
|
|
3030
|
+
resolvedScenarios.add(resolveScenariosFromSpec(modelInputsL, modelInputsR, scenarioSpec, genKey));
|
|
3031
|
+
}
|
|
3032
|
+
const partiallyResolvedScenarioGroups = [];
|
|
3033
|
+
for (const scenarioGroupSpec of specs.scenarioGroups) {
|
|
3034
|
+
const scenariosForGroup = [];
|
|
3035
|
+
for (const scenarioItem of scenarioGroupSpec.scenarios) {
|
|
3036
|
+
if (scenarioItem.kind === "scenario-ref") {
|
|
3037
|
+
scenariosForGroup.push(scenarioItem);
|
|
3038
|
+
} else {
|
|
3039
|
+
const scenarios = resolveScenariosFromSpec(modelInputsL, modelInputsR, scenarioItem, genKey);
|
|
3040
|
+
resolvedScenarios.add(scenarios);
|
|
3041
|
+
scenariosForGroup.push(...scenarios);
|
|
3042
|
+
}
|
|
3043
|
+
}
|
|
3044
|
+
partiallyResolvedScenarioGroups.push({
|
|
3045
|
+
spec: scenarioGroupSpec,
|
|
3046
|
+
scenarios: scenariosForGroup
|
|
3047
|
+
});
|
|
3048
|
+
}
|
|
3049
|
+
const resolvedScenarioGroups = new ResolvedScenarioGroups();
|
|
3050
|
+
for (const partiallyResolvedGroup of partiallyResolvedScenarioGroups) {
|
|
3051
|
+
const scenariosForGroup = [];
|
|
3052
|
+
for (const scenarioItem of partiallyResolvedGroup.scenarios) {
|
|
3053
|
+
if (scenarioItem.kind === "scenario-ref") {
|
|
3054
|
+
const referencedScenario = resolvedScenarios.getScenarioForId(scenarioItem.scenarioId);
|
|
3055
|
+
if (referencedScenario) {
|
|
3056
|
+
const resolvedScenario = __spreadValues({}, referencedScenario);
|
|
3057
|
+
if (scenarioItem.title) {
|
|
3058
|
+
resolvedScenario.title = scenarioItem.title;
|
|
3059
|
+
}
|
|
3060
|
+
if (scenarioItem.subtitle) {
|
|
3061
|
+
resolvedScenario.subtitle = scenarioItem.subtitle;
|
|
3062
|
+
}
|
|
3063
|
+
scenariosForGroup.push(resolvedScenario);
|
|
3064
|
+
} else {
|
|
3065
|
+
scenariosForGroup.push({
|
|
3066
|
+
kind: "unresolved-scenario-ref",
|
|
3067
|
+
scenarioId: scenarioItem.scenarioId
|
|
3068
|
+
});
|
|
3069
|
+
}
|
|
3070
|
+
} else {
|
|
3071
|
+
scenariosForGroup.push(scenarioItem);
|
|
3072
|
+
}
|
|
3073
|
+
}
|
|
3074
|
+
resolvedScenarioGroups.add({
|
|
3075
|
+
kind: "scenario-group",
|
|
3076
|
+
id: partiallyResolvedGroup.spec.id,
|
|
3077
|
+
title: partiallyResolvedGroup.spec.title,
|
|
3078
|
+
scenarios: scenariosForGroup
|
|
3079
|
+
});
|
|
3080
|
+
}
|
|
3081
|
+
const resolvedViewGroups = [];
|
|
3082
|
+
for (const viewGroupSpec of specs.viewGroups) {
|
|
3083
|
+
const resolvedViewGroup = resolveViewGroupFromSpec(resolvedScenarios, resolvedScenarioGroups, viewGroupSpec);
|
|
3084
|
+
resolvedViewGroups.push(resolvedViewGroup);
|
|
3085
|
+
}
|
|
3086
|
+
return {
|
|
3087
|
+
scenarios: resolvedScenarios.getAll(),
|
|
3088
|
+
scenarioGroups: resolvedScenarioGroups.getAll(),
|
|
3089
|
+
viewGroups: resolvedViewGroups
|
|
3090
|
+
};
|
|
3091
|
+
}
|
|
3092
|
+
var ResolvedScenarios = class {
|
|
3093
|
+
constructor() {
|
|
3094
|
+
/** The array of all resolved scenarios. */
|
|
3095
|
+
this.resolvedScenarios = [];
|
|
3096
|
+
/** The set of resolved scenarios that include an ID, keyed by ID. */
|
|
3097
|
+
this.resolvedScenariosById = /* @__PURE__ */ new Map();
|
|
3098
|
+
}
|
|
3099
|
+
add(scenarios) {
|
|
3100
|
+
for (const resolvedScenario of scenarios) {
|
|
3101
|
+
this.resolvedScenarios.push(resolvedScenario);
|
|
3102
|
+
if (resolvedScenario.id !== void 0) {
|
|
3103
|
+
if (this.resolvedScenariosById.has(resolvedScenario.id)) {
|
|
3104
|
+
throw new Error(`Multiple scenarios defined with the same id (${resolvedScenario.id})`);
|
|
3105
|
+
}
|
|
3106
|
+
this.resolvedScenariosById.set(resolvedScenario.id, resolvedScenario);
|
|
3107
|
+
}
|
|
3108
|
+
}
|
|
3109
|
+
}
|
|
3110
|
+
getAll() {
|
|
3111
|
+
return this.resolvedScenarios;
|
|
3112
|
+
}
|
|
3113
|
+
getScenarioForId(id) {
|
|
3114
|
+
return this.resolvedScenariosById.get(id);
|
|
3115
|
+
}
|
|
3116
|
+
};
|
|
3117
|
+
function resolveScenariosFromSpec(modelInputsL, modelInputsR, scenarioSpec, genKey) {
|
|
3118
|
+
switch (scenarioSpec.kind) {
|
|
3119
|
+
case "scenario-matrix":
|
|
3120
|
+
return resolveScenarioMatrix(modelInputsL, modelInputsR, genKey);
|
|
3121
|
+
case "scenario-with-all-inputs": {
|
|
3122
|
+
const position = inputPosition2(scenarioSpec.position);
|
|
3123
|
+
return [
|
|
3124
|
+
resolveScenarioWithAllInputsAtPosition(
|
|
3125
|
+
genKey(),
|
|
3126
|
+
scenarioSpec.id,
|
|
3127
|
+
scenarioSpec.title,
|
|
3128
|
+
scenarioSpec.subtitle,
|
|
3129
|
+
position
|
|
3130
|
+
)
|
|
3131
|
+
];
|
|
3132
|
+
}
|
|
3133
|
+
case "scenario-with-inputs": {
|
|
3134
|
+
return [
|
|
3135
|
+
resolveScenarioForInputSpecs(
|
|
3136
|
+
modelInputsL,
|
|
3137
|
+
modelInputsR,
|
|
3138
|
+
genKey(),
|
|
3139
|
+
scenarioSpec.id,
|
|
3140
|
+
scenarioSpec.title,
|
|
3141
|
+
scenarioSpec.subtitle,
|
|
3142
|
+
scenarioSpec.inputs
|
|
3143
|
+
)
|
|
3144
|
+
];
|
|
3145
|
+
}
|
|
3146
|
+
case "scenario-with-distinct-inputs": {
|
|
3147
|
+
return [
|
|
3148
|
+
resolveScenarioForDistinctInputSpecs(
|
|
3149
|
+
modelInputsL,
|
|
3150
|
+
modelInputsR,
|
|
3151
|
+
genKey(),
|
|
3152
|
+
scenarioSpec.id,
|
|
3153
|
+
scenarioSpec.title,
|
|
3154
|
+
scenarioSpec.subtitle,
|
|
3155
|
+
scenarioSpec.inputsL,
|
|
3156
|
+
scenarioSpec.inputsR
|
|
3157
|
+
)
|
|
3158
|
+
];
|
|
3159
|
+
}
|
|
3160
|
+
default:
|
|
3161
|
+
(0, import_assert_never11.assertNever)(scenarioSpec);
|
|
3162
|
+
}
|
|
3163
|
+
}
|
|
3164
|
+
function resolveScenarioMatrix(modelInputsL, modelInputsR, genKey) {
|
|
3165
|
+
const resolvedScenarios = [];
|
|
3166
|
+
resolvedScenarios.push(
|
|
3167
|
+
resolveScenarioWithAllInputsAtPosition(genKey(), void 0, void 0, void 0, "at-default")
|
|
3168
|
+
);
|
|
3169
|
+
const inputIdAliases = /* @__PURE__ */ new Set();
|
|
3170
|
+
modelInputsL.getAllInputIdAliases().forEach((alias) => inputIdAliases.add(alias));
|
|
3171
|
+
modelInputsR.getAllInputIdAliases().forEach((alias) => inputIdAliases.add(alias));
|
|
3172
|
+
for (const inputIdAlias of inputIdAliases) {
|
|
3173
|
+
const inputAtMin = {
|
|
3174
|
+
kind: "input-at-position",
|
|
3175
|
+
inputName: inputIdAlias,
|
|
3176
|
+
position: "min"
|
|
3177
|
+
};
|
|
3178
|
+
const inputAtMax = {
|
|
3179
|
+
kind: "input-at-position",
|
|
3180
|
+
inputName: inputIdAlias,
|
|
3181
|
+
position: "max"
|
|
3182
|
+
};
|
|
3183
|
+
resolvedScenarios.push(
|
|
3184
|
+
resolveScenarioForInputSpecs(modelInputsL, modelInputsR, genKey(), void 0, void 0, void 0, [inputAtMin])
|
|
3185
|
+
);
|
|
3186
|
+
resolvedScenarios.push(
|
|
3187
|
+
resolveScenarioForInputSpecs(modelInputsL, modelInputsR, genKey(), void 0, void 0, void 0, [inputAtMax])
|
|
3188
|
+
);
|
|
3189
|
+
}
|
|
3190
|
+
return resolvedScenarios;
|
|
3191
|
+
}
|
|
3192
|
+
function resolveScenarioWithAllInputsAtPosition(key, id, title, subtitle, position) {
|
|
3193
|
+
const settings = {
|
|
3194
|
+
kind: "all-inputs-settings",
|
|
3195
|
+
position
|
|
3196
|
+
};
|
|
3197
|
+
const [specL, specR] = scenarioSpecsFromSettings(settings);
|
|
3198
|
+
return {
|
|
3199
|
+
kind: "scenario",
|
|
3200
|
+
key,
|
|
3201
|
+
id,
|
|
3202
|
+
title,
|
|
3203
|
+
subtitle,
|
|
3204
|
+
settings,
|
|
3205
|
+
specL,
|
|
3206
|
+
specR
|
|
3207
|
+
};
|
|
3208
|
+
}
|
|
3209
|
+
function resolveScenarioForInputSpecs(modelInputsL, modelInputsR, key, id, title, subtitle, inputSpecs) {
|
|
3210
|
+
const resolvedInputs = inputSpecs.map((inputSpec) => {
|
|
3211
|
+
switch (inputSpec.kind) {
|
|
3212
|
+
case "input-at-position":
|
|
3213
|
+
return resolveInputForName(modelInputsL, modelInputsR, inputSpec.inputName, inputSpec.position);
|
|
3214
|
+
case "input-at-value":
|
|
3215
|
+
return resolveInputForName(modelInputsL, modelInputsR, inputSpec.inputName, inputSpec.value);
|
|
3216
|
+
default:
|
|
3217
|
+
(0, import_assert_never11.assertNever)(inputSpec);
|
|
3218
|
+
}
|
|
3219
|
+
});
|
|
3220
|
+
const settings = {
|
|
3221
|
+
kind: "input-settings",
|
|
3222
|
+
inputs: resolvedInputs
|
|
3223
|
+
};
|
|
3224
|
+
const [specL, specR] = scenarioSpecsFromSettings(settings);
|
|
3225
|
+
return {
|
|
3226
|
+
kind: "scenario",
|
|
3227
|
+
key,
|
|
3228
|
+
id,
|
|
3229
|
+
title,
|
|
3230
|
+
subtitle,
|
|
3231
|
+
settings,
|
|
3232
|
+
specL,
|
|
3233
|
+
specR
|
|
3234
|
+
};
|
|
3235
|
+
}
|
|
3236
|
+
function resolveScenarioForDistinctInputSpecs(modelInputsL, modelInputsR, key, id, title, subtitle, inputSpecsL, inputSpecsR) {
|
|
3237
|
+
const inputsWithErrors = [];
|
|
3238
|
+
const settingsL = [];
|
|
3239
|
+
const settingsR = [];
|
|
3240
|
+
function resolveInputSpec(side, modelInputs, inputSpec) {
|
|
3241
|
+
let inputState;
|
|
3242
|
+
switch (inputSpec.kind) {
|
|
3243
|
+
case "input-at-position":
|
|
3244
|
+
inputState = resolveInputForNameInModel(modelInputs, inputSpec.inputName, inputSpec.position);
|
|
3245
|
+
break;
|
|
3246
|
+
case "input-at-value":
|
|
3247
|
+
inputState = resolveInputForNameInModel(modelInputs, inputSpec.inputName, inputSpec.value);
|
|
3248
|
+
break;
|
|
3249
|
+
default:
|
|
3250
|
+
(0, import_assert_never11.assertNever)(inputSpec);
|
|
3251
|
+
}
|
|
3252
|
+
if (inputState.error !== void 0) {
|
|
3253
|
+
inputsWithErrors.push({
|
|
3254
|
+
requestedName: inputSpec.inputName,
|
|
3255
|
+
stateL: side === "left" ? inputState : {},
|
|
3256
|
+
stateR: side === "right" ? inputState : {}
|
|
3257
|
+
});
|
|
3258
|
+
} else {
|
|
3259
|
+
const inputSetting = inputSettingFromResolvedInputState(inputState);
|
|
3260
|
+
if (side === "left") {
|
|
3261
|
+
settingsL.push(inputSetting);
|
|
3262
|
+
} else {
|
|
3263
|
+
settingsR.push(inputSetting);
|
|
3264
|
+
}
|
|
3265
|
+
}
|
|
3266
|
+
}
|
|
3267
|
+
inputSpecsL.forEach((inputSpec) => resolveInputSpec("left", modelInputsL, inputSpec));
|
|
3268
|
+
inputSpecsR.forEach((inputSpec) => resolveInputSpec("right", modelInputsR, inputSpec));
|
|
3269
|
+
let specL;
|
|
3270
|
+
let specR;
|
|
3271
|
+
if (inputsWithErrors.length === 0) {
|
|
3272
|
+
specL = inputSettingsSpec(settingsL);
|
|
3273
|
+
specR = inputSettingsSpec(settingsR);
|
|
3274
|
+
}
|
|
3275
|
+
return {
|
|
3276
|
+
kind: "scenario",
|
|
3277
|
+
key,
|
|
3278
|
+
id,
|
|
3279
|
+
title,
|
|
3280
|
+
subtitle,
|
|
3281
|
+
settings: {
|
|
3282
|
+
kind: "input-settings",
|
|
3283
|
+
inputs: inputsWithErrors
|
|
3284
|
+
},
|
|
3285
|
+
specL,
|
|
3286
|
+
specR
|
|
3287
|
+
};
|
|
3288
|
+
}
|
|
3289
|
+
function resolveInputForName(modelInputsL, modelInputsR, inputName, at) {
|
|
3290
|
+
return {
|
|
3291
|
+
requestedName: inputName,
|
|
3292
|
+
stateL: resolveInputForNameInModel(modelInputsL, inputName, at),
|
|
3293
|
+
stateR: resolveInputForNameInModel(modelInputsR, inputName, at)
|
|
3294
|
+
};
|
|
3295
|
+
}
|
|
3296
|
+
function resolveInputForNameInModel(modelInputs, inputName, at) {
|
|
3297
|
+
const inputVar = modelInputs.getInputVarForName(inputName);
|
|
3298
|
+
if (inputVar) {
|
|
3299
|
+
return resolveInputVar(inputVar, at);
|
|
3300
|
+
} else {
|
|
3301
|
+
return {
|
|
3302
|
+
error: {
|
|
3303
|
+
kind: "unknown-input"
|
|
3304
|
+
}
|
|
3305
|
+
};
|
|
3306
|
+
}
|
|
3307
|
+
}
|
|
3308
|
+
function resolveInputVar(inputVar, at) {
|
|
3309
|
+
if (typeof at === "number") {
|
|
3310
|
+
const value = at;
|
|
3311
|
+
return resolveInputVarAtValue(inputVar, value);
|
|
3312
|
+
} else {
|
|
3313
|
+
const position = inputPosition2(at);
|
|
3314
|
+
return resolveInputVarAtPosition(inputVar, position);
|
|
3315
|
+
}
|
|
3316
|
+
}
|
|
3317
|
+
function resolveInputVarAtPosition(inputVar, position) {
|
|
3318
|
+
return {
|
|
3319
|
+
inputVar,
|
|
3320
|
+
position,
|
|
3321
|
+
value: inputValueAtPosition2(inputVar, position)
|
|
3322
|
+
};
|
|
3323
|
+
}
|
|
3324
|
+
function resolveInputVarAtValue(inputVar, value) {
|
|
3325
|
+
if (value >= inputVar.minValue && value <= inputVar.maxValue) {
|
|
3326
|
+
return {
|
|
3327
|
+
inputVar,
|
|
3328
|
+
value
|
|
3329
|
+
};
|
|
3330
|
+
} else {
|
|
3331
|
+
return {
|
|
3332
|
+
error: {
|
|
3333
|
+
kind: "invalid-value"
|
|
3334
|
+
}
|
|
3335
|
+
};
|
|
3336
|
+
}
|
|
3337
|
+
}
|
|
3338
|
+
function inputPosition2(position) {
|
|
3339
|
+
switch (position) {
|
|
3340
|
+
case "default":
|
|
3341
|
+
return "at-default";
|
|
3342
|
+
case "min":
|
|
3343
|
+
return "at-minimum";
|
|
3344
|
+
case "max":
|
|
3345
|
+
return "at-maximum";
|
|
3346
|
+
default:
|
|
3347
|
+
return void 0;
|
|
3348
|
+
}
|
|
3349
|
+
}
|
|
3350
|
+
function inputValueAtPosition2(inputVar, position) {
|
|
3351
|
+
switch (position) {
|
|
3352
|
+
case "at-default":
|
|
3353
|
+
return inputVar.defaultValue;
|
|
3354
|
+
case "at-minimum":
|
|
3355
|
+
return inputVar.minValue;
|
|
3356
|
+
case "at-maximum":
|
|
3357
|
+
return inputVar.maxValue;
|
|
3358
|
+
default:
|
|
3359
|
+
(0, import_assert_never11.assertNever)(position);
|
|
3360
|
+
}
|
|
3361
|
+
}
|
|
3362
|
+
var ResolvedScenarioGroups = class {
|
|
3363
|
+
constructor() {
|
|
3364
|
+
/** The array of all resolved scenario groups. */
|
|
3365
|
+
this.resolvedGroups = [];
|
|
3366
|
+
/** The set of resolved scenario groups that include an ID, keyed by ID. */
|
|
3367
|
+
this.resolvedGroupsById = /* @__PURE__ */ new Map();
|
|
3368
|
+
}
|
|
3369
|
+
add(group) {
|
|
3370
|
+
this.resolvedGroups.push(group);
|
|
3371
|
+
if (group.id !== void 0) {
|
|
3372
|
+
if (this.resolvedGroupsById.has(group.id)) {
|
|
3373
|
+
throw new Error(`Multiple scenario groups defined with the same id (${group.id})`);
|
|
3374
|
+
}
|
|
3375
|
+
this.resolvedGroupsById.set(group.id, group);
|
|
3376
|
+
}
|
|
3377
|
+
}
|
|
3378
|
+
getAll() {
|
|
3379
|
+
return this.resolvedGroups;
|
|
3380
|
+
}
|
|
3381
|
+
getGroupForId(id) {
|
|
3382
|
+
return this.resolvedGroupsById.get(id);
|
|
3383
|
+
}
|
|
3384
|
+
};
|
|
3385
|
+
function resolveGraphsFromSpec(graphsSpec) {
|
|
3386
|
+
switch (graphsSpec.kind) {
|
|
3387
|
+
case "graphs-preset":
|
|
3388
|
+
return "all";
|
|
3389
|
+
case "graphs-array":
|
|
3390
|
+
return graphsSpec.graphIds;
|
|
3391
|
+
default:
|
|
3392
|
+
(0, import_assert_never11.assertNever)(graphsSpec);
|
|
3393
|
+
}
|
|
3394
|
+
}
|
|
3395
|
+
function resolveViewForScenarioId(resolvedScenarios, viewTitle, viewSubtitle, scenarioId, graphs) {
|
|
3396
|
+
const resolvedScenario = resolvedScenarios.getScenarioForId(scenarioId);
|
|
3397
|
+
if (resolvedScenario) {
|
|
3398
|
+
return resolveViewForScenario(viewTitle, viewSubtitle, resolvedScenario, graphs);
|
|
3399
|
+
} else {
|
|
3400
|
+
return unresolvedViewForScenarioId(viewTitle, viewSubtitle, scenarioId);
|
|
3401
|
+
}
|
|
3402
|
+
}
|
|
3403
|
+
function resolveViewForScenarioRefSpec(resolvedScenarios, refSpec, graphs) {
|
|
3404
|
+
const resolvedScenario = resolvedScenarios.getScenarioForId(refSpec.scenarioId);
|
|
3405
|
+
if (resolvedScenario) {
|
|
3406
|
+
return resolveViewForScenario(refSpec.title, refSpec.subtitle, resolvedScenario, graphs);
|
|
3407
|
+
} else {
|
|
3408
|
+
return unresolvedViewForScenarioId(void 0, void 0, refSpec.scenarioId);
|
|
3409
|
+
}
|
|
3410
|
+
}
|
|
3411
|
+
function resolveViewForScenario(viewTitle, viewSubtitle, resolvedScenario, graphs) {
|
|
3412
|
+
if (viewTitle === void 0) {
|
|
3413
|
+
viewTitle = resolvedScenario.title;
|
|
3414
|
+
if (viewTitle === void 0) {
|
|
3415
|
+
viewTitle = "Untitled view";
|
|
3416
|
+
}
|
|
3417
|
+
if (viewSubtitle === void 0) {
|
|
3418
|
+
viewSubtitle = resolvedScenario.subtitle;
|
|
3419
|
+
}
|
|
3420
|
+
}
|
|
3421
|
+
return {
|
|
3422
|
+
kind: "view",
|
|
3423
|
+
title: viewTitle,
|
|
3424
|
+
subtitle: viewSubtitle,
|
|
3425
|
+
scenario: resolvedScenario,
|
|
3426
|
+
graphs
|
|
3427
|
+
};
|
|
3428
|
+
}
|
|
3429
|
+
function unresolvedViewForScenarioId(viewTitle, viewSubtitle, scenarioId) {
|
|
3430
|
+
return {
|
|
3431
|
+
kind: "unresolved-view",
|
|
3432
|
+
title: viewTitle,
|
|
3433
|
+
subtitle: viewSubtitle,
|
|
3434
|
+
scenarioId
|
|
3435
|
+
};
|
|
3436
|
+
}
|
|
3437
|
+
function unresolvedViewForScenarioGroupId(viewTitle, viewSubtitle, scenarioGroupId) {
|
|
3438
|
+
return {
|
|
3439
|
+
kind: "unresolved-view",
|
|
3440
|
+
title: viewTitle,
|
|
3441
|
+
subtitle: viewSubtitle,
|
|
3442
|
+
scenarioGroupId
|
|
3443
|
+
};
|
|
3444
|
+
}
|
|
3445
|
+
function resolveViewGroupFromSpec(resolvedScenarios, resolvedScenarioGroups, viewGroupSpec) {
|
|
3446
|
+
let views;
|
|
3447
|
+
switch (viewGroupSpec.kind) {
|
|
3448
|
+
case "view-group-with-views": {
|
|
3449
|
+
views = viewGroupSpec.views.map((viewSpec) => {
|
|
3450
|
+
const graphs = resolveGraphsFromSpec(viewSpec.graphs);
|
|
3451
|
+
return resolveViewForScenarioId(
|
|
3452
|
+
resolvedScenarios,
|
|
3453
|
+
viewSpec.title,
|
|
3454
|
+
viewSpec.subtitle,
|
|
3455
|
+
viewSpec.scenarioId,
|
|
3456
|
+
graphs
|
|
3457
|
+
);
|
|
3458
|
+
});
|
|
3459
|
+
break;
|
|
3460
|
+
}
|
|
3461
|
+
case "view-group-with-scenarios": {
|
|
3462
|
+
const graphs = resolveGraphsFromSpec(viewGroupSpec.graphs);
|
|
3463
|
+
views = [];
|
|
3464
|
+
for (const refSpec of viewGroupSpec.scenarios) {
|
|
3465
|
+
switch (refSpec.kind) {
|
|
3466
|
+
case "scenario-ref":
|
|
3467
|
+
views.push(resolveViewForScenarioRefSpec(resolvedScenarios, refSpec, graphs));
|
|
3468
|
+
break;
|
|
3469
|
+
case "scenario-group-ref": {
|
|
3470
|
+
const resolvedGroup = resolvedScenarioGroups.getGroupForId(refSpec.groupId);
|
|
3471
|
+
if (resolvedGroup) {
|
|
3472
|
+
for (const scenario of resolvedGroup.scenarios) {
|
|
3473
|
+
switch (scenario.kind) {
|
|
3474
|
+
case "unresolved-scenario-ref":
|
|
3475
|
+
views.push(unresolvedViewForScenarioId(void 0, void 0, scenario.scenarioId));
|
|
3476
|
+
break;
|
|
3477
|
+
case "scenario":
|
|
3478
|
+
views.push(resolveViewForScenario(void 0, void 0, scenario, graphs));
|
|
3479
|
+
break;
|
|
3480
|
+
default:
|
|
3481
|
+
(0, import_assert_never11.assertNever)(scenario);
|
|
3482
|
+
}
|
|
3483
|
+
}
|
|
3484
|
+
} else {
|
|
3485
|
+
views.push(unresolvedViewForScenarioGroupId(void 0, void 0, refSpec.groupId));
|
|
3486
|
+
}
|
|
3487
|
+
break;
|
|
3488
|
+
}
|
|
3489
|
+
default:
|
|
3490
|
+
(0, import_assert_never11.assertNever)(refSpec);
|
|
3491
|
+
}
|
|
3492
|
+
}
|
|
3493
|
+
break;
|
|
3494
|
+
}
|
|
3495
|
+
default:
|
|
3496
|
+
(0, import_assert_never11.assertNever)(viewGroupSpec);
|
|
3497
|
+
}
|
|
3498
|
+
return {
|
|
3499
|
+
kind: "view-group",
|
|
3500
|
+
title: viewGroupSpec.title,
|
|
3501
|
+
views
|
|
3502
|
+
};
|
|
3503
|
+
}
|
|
3504
|
+
|
|
3505
|
+
// src/comparison/config/comparison-config.ts
|
|
3506
|
+
function resolveComparisonSpecsFromSources(modelInputsL, modelInputsR, specSources) {
|
|
3507
|
+
const combinedSpecs = {
|
|
3508
|
+
scenarios: [],
|
|
3509
|
+
scenarioGroups: [],
|
|
3510
|
+
viewGroups: []
|
|
3511
|
+
};
|
|
3512
|
+
for (const specSource of specSources) {
|
|
3513
|
+
let specs;
|
|
3514
|
+
if ("kind" in specSource) {
|
|
3515
|
+
const parseResult = parseComparisonSpecs(specSource);
|
|
3516
|
+
if (parseResult.isOk()) {
|
|
3517
|
+
specs = parseResult.value;
|
|
3518
|
+
} else {
|
|
3519
|
+
const filenamePart = specSource.filename ? ` in ${specSource.filename}` : "";
|
|
3520
|
+
console.error(`ERROR: Failed to parse comparison spec${filenamePart}, skipping`);
|
|
3521
|
+
continue;
|
|
3522
|
+
}
|
|
3523
|
+
} else {
|
|
3524
|
+
specs = specSource;
|
|
3525
|
+
}
|
|
3526
|
+
combinedSpecs.scenarios.push(...specs.scenarios);
|
|
3527
|
+
combinedSpecs.scenarioGroups.push(...specs.scenarioGroups);
|
|
3528
|
+
combinedSpecs.viewGroups.push(...specs.viewGroups);
|
|
3529
|
+
}
|
|
3530
|
+
return resolveComparisonSpecs(modelInputsL, modelInputsR, combinedSpecs);
|
|
3531
|
+
}
|
|
3532
|
+
|
|
3533
|
+
// src/comparison/config/comparison-datasets.ts
|
|
3534
|
+
function getComparisonDatasets(modelSpecL, modelSpecR, datasetOptions) {
|
|
3535
|
+
return new ComparisonDatasetsImpl(modelSpecL, modelSpecR, datasetOptions);
|
|
3536
|
+
}
|
|
3537
|
+
var ComparisonDatasetsImpl = class {
|
|
3538
|
+
/**
|
|
3539
|
+
* @param modelSpecL The model spec for the "left" bundle being compared.
|
|
3540
|
+
* @param modelSpecR The model spec for the "right" bundle being compared.
|
|
3541
|
+
* @param datasetOptions The custom configuration for the datasets to be compared.
|
|
3542
|
+
*/
|
|
3543
|
+
constructor(modelSpecL, modelSpecR, datasetOptions) {
|
|
3544
|
+
this.datasetOptions = datasetOptions;
|
|
3545
|
+
const renamedDatasetKeys = datasetOptions == null ? void 0 : datasetOptions.renamedDatasetKeys;
|
|
3546
|
+
const invertedRenamedKeys = /* @__PURE__ */ new Map();
|
|
3547
|
+
renamedDatasetKeys == null ? void 0 : renamedDatasetKeys.forEach((newKey, oldKey) => {
|
|
3548
|
+
invertedRenamedKeys.set(newKey, oldKey);
|
|
3549
|
+
});
|
|
3550
|
+
function leftKeyForRightKey(rightKey) {
|
|
3551
|
+
return invertedRenamedKeys.get(rightKey) || rightKey;
|
|
3552
|
+
}
|
|
3553
|
+
const allOutputVarKeysSet = /* @__PURE__ */ new Set();
|
|
3554
|
+
const modelOutputVarKeysSet = /* @__PURE__ */ new Set();
|
|
3555
|
+
function addOutputVars(outputVars, handleRenames) {
|
|
3556
|
+
outputVars.forEach((outputVar, key) => {
|
|
3557
|
+
const remappedKey = handleRenames ? leftKeyForRightKey(key) : key;
|
|
3558
|
+
allOutputVarKeysSet.add(remappedKey);
|
|
2251
3559
|
if (outputVar.sourceName === void 0) {
|
|
2252
3560
|
modelOutputVarKeysSet.add(remappedKey);
|
|
2253
3561
|
}
|
|
2254
3562
|
});
|
|
2255
3563
|
}
|
|
2256
|
-
addOutputVars(
|
|
2257
|
-
addOutputVars(
|
|
3564
|
+
addOutputVars(modelSpecL.outputVars, false);
|
|
3565
|
+
addOutputVars(modelSpecR.outputVars, true);
|
|
2258
3566
|
this.allOutputVarKeys = Array.from(allOutputVarKeysSet);
|
|
2259
3567
|
this.modelOutputVarKeys = Array.from(modelOutputVarKeysSet);
|
|
2260
|
-
|
|
2261
|
-
|
|
2262
|
-
|
|
2263
|
-
|
|
2264
|
-
|
|
2265
|
-
|
|
3568
|
+
this.allDatasets = /* @__PURE__ */ new Map();
|
|
3569
|
+
for (const datasetKeyL of this.allOutputVarKeys) {
|
|
3570
|
+
const datasetKeyR = (renamedDatasetKeys == null ? void 0 : renamedDatasetKeys.get(datasetKeyL)) || datasetKeyL;
|
|
3571
|
+
const outputVarL = modelSpecL.outputVars.get(datasetKeyL);
|
|
3572
|
+
const outputVarR = modelSpecR.outputVars.get(datasetKeyR);
|
|
3573
|
+
this.allDatasets.set(datasetKeyL, {
|
|
3574
|
+
kind: "dataset",
|
|
3575
|
+
key: datasetKeyL,
|
|
3576
|
+
outputVarL,
|
|
3577
|
+
outputVarR
|
|
3578
|
+
});
|
|
2266
3579
|
}
|
|
2267
3580
|
}
|
|
2268
|
-
|
|
3581
|
+
// from ComparisonDatasets interface
|
|
3582
|
+
getAllDatasets() {
|
|
3583
|
+
return this.allDatasets.values();
|
|
3584
|
+
}
|
|
3585
|
+
// from ComparisonDatasets interface
|
|
3586
|
+
getDataset(datasetKey) {
|
|
3587
|
+
return this.allDatasets.get(datasetKey);
|
|
3588
|
+
}
|
|
3589
|
+
// from ComparisonDatasets interface
|
|
3590
|
+
getDatasetKeysForScenario(scenario) {
|
|
2269
3591
|
var _a;
|
|
2270
|
-
|
|
2271
|
-
|
|
2272
|
-
const datasetKeyL = datasetKey;
|
|
2273
|
-
const datasetKeyR = ((_a = this.renamedDatasetKeys) == null ? void 0 : _a.get(datasetKeyL)) || datasetKeyL;
|
|
2274
|
-
const outputVarL = modelSpecL.outputVars.get(datasetKeyL);
|
|
2275
|
-
const outputVarR = modelSpecR.outputVars.get(datasetKeyR);
|
|
2276
|
-
let varName;
|
|
2277
|
-
let newVarName;
|
|
2278
|
-
let sourceName;
|
|
2279
|
-
let newSourceName;
|
|
2280
|
-
if (outputVarL && outputVarR && outputVarL.varName != outputVarR.varName) {
|
|
2281
|
-
varName = outputVarL.varName;
|
|
2282
|
-
newVarName = outputVarR.varName;
|
|
2283
|
-
} else {
|
|
2284
|
-
const outputVar = outputVarR || outputVarL;
|
|
2285
|
-
varName = (outputVar == null ? void 0 : outputVar.varName) || "Unknown";
|
|
2286
|
-
}
|
|
2287
|
-
if (outputVarL && outputVarR && outputVarL.sourceName != outputVarR.sourceName) {
|
|
2288
|
-
sourceName = outputVarL.sourceName;
|
|
2289
|
-
newSourceName = outputVarR.sourceName;
|
|
3592
|
+
if (((_a = this.datasetOptions) == null ? void 0 : _a.datasetKeysForScenario) !== void 0) {
|
|
3593
|
+
return this.datasetOptions.datasetKeysForScenario(this.allOutputVarKeys, scenario);
|
|
2290
3594
|
} else {
|
|
2291
|
-
|
|
2292
|
-
|
|
3595
|
+
if (scenario.settings.kind === "all-inputs-settings" && scenario.settings.position === "at-default") {
|
|
3596
|
+
return this.allOutputVarKeys;
|
|
3597
|
+
} else {
|
|
3598
|
+
return this.modelOutputVarKeys;
|
|
3599
|
+
}
|
|
2293
3600
|
}
|
|
2294
|
-
return {
|
|
2295
|
-
varName,
|
|
2296
|
-
newVarName,
|
|
2297
|
-
sourceName,
|
|
2298
|
-
newSourceName,
|
|
2299
|
-
relatedItems: (outputVarR == null ? void 0 : outputVarR.relatedItems) || []
|
|
2300
|
-
};
|
|
2301
3601
|
}
|
|
2302
3602
|
};
|
|
2303
3603
|
|
|
2304
|
-
// src/config/
|
|
2305
|
-
|
|
2306
|
-
|
|
2307
|
-
|
|
2308
|
-
|
|
2309
|
-
|
|
2310
|
-
this.
|
|
2311
|
-
|
|
2312
|
-
|
|
2313
|
-
this.groupInfo = /* @__PURE__ */ new Map();
|
|
2314
|
-
}
|
|
2315
|
-
getScenarios() {
|
|
2316
|
-
return [...this.scenarios.values()];
|
|
2317
|
-
}
|
|
2318
|
-
getScenario(scenarioKey) {
|
|
2319
|
-
return this.scenarios.get(scenarioKey);
|
|
2320
|
-
}
|
|
2321
|
-
getScenarioGroupInfo(groupKey) {
|
|
2322
|
-
return this.groupInfo.get(groupKey);
|
|
2323
|
-
}
|
|
2324
|
-
getScenarioInfo(scenario, groupKey) {
|
|
2325
|
-
if (scenario.key === "all_inputs_at_default") {
|
|
2326
|
-
const defaultInfo = this.defaultInfoForGroup.get(groupKey);
|
|
2327
|
-
if (defaultInfo) {
|
|
2328
|
-
return defaultInfo;
|
|
2329
|
-
}
|
|
2330
|
-
}
|
|
2331
|
-
return this.scenarioInfo.get(scenario.key);
|
|
2332
|
-
}
|
|
2333
|
-
setDefaultScenarioInfoForGroup(groupKey, scenarioInfo) {
|
|
2334
|
-
this.defaultInfoForGroup.set(groupKey, scenarioInfo);
|
|
2335
|
-
}
|
|
2336
|
-
addScenario(scenario, scenarioInfo, groupInfo) {
|
|
2337
|
-
this.scenarios.set(scenario.key, scenario);
|
|
2338
|
-
if (!scenarioInfo) {
|
|
2339
|
-
scenarioInfo = this.getInfoForScenario(scenario);
|
|
2340
|
-
}
|
|
2341
|
-
this.scenarioInfo.set(scenario.key, scenarioInfo);
|
|
2342
|
-
if (!groupInfo) {
|
|
2343
|
-
groupInfo = this.getGroupInfoForScenario(scenario);
|
|
2344
|
-
}
|
|
2345
|
-
this.groupInfo.set(scenario.groupKey, groupInfo);
|
|
2346
|
-
}
|
|
2347
|
-
addScenarioMatrix() {
|
|
2348
|
-
const inputVarIdsL = Array.from(this.bundleL.modelSpec.inputVars.keys());
|
|
2349
|
-
const inputVarIdsR = Array.from(this.bundleR.modelSpec.inputVars.keys());
|
|
2350
|
-
const inputVarIds = /* @__PURE__ */ new Set([...inputVarIdsL, ...inputVarIdsR]);
|
|
2351
|
-
this.addScenario(allInputsAtPositionScenario("at-default"));
|
|
2352
|
-
this.addScenario(allInputsAtPositionScenario("at-minimum"));
|
|
2353
|
-
this.addScenario(allInputsAtPositionScenario("at-maximum"));
|
|
2354
|
-
for (const inputVarId of inputVarIds) {
|
|
2355
|
-
this.addScenario(inputAtPositionScenario(inputVarId, inputVarId, "at-minimum"));
|
|
2356
|
-
this.addScenario(inputAtPositionScenario(inputVarId, inputVarId, "at-maximum"));
|
|
2357
|
-
}
|
|
2358
|
-
}
|
|
2359
|
-
getGroupInfoForScenario(scenario) {
|
|
2360
|
-
switch (scenario.kind) {
|
|
2361
|
-
case "all-inputs":
|
|
2362
|
-
return {
|
|
2363
|
-
title: "All Inputs",
|
|
2364
|
-
relatedItems: []
|
|
2365
|
-
};
|
|
2366
|
-
case "settings":
|
|
2367
|
-
if (scenario.settings.length === 1) {
|
|
2368
|
-
const inputVar = this.getInputVarForSetting(scenario.settings[0]);
|
|
2369
|
-
let relatedItems;
|
|
2370
|
-
let subtitle;
|
|
2371
|
-
if (inputVar == null ? void 0 : inputVar.relatedItem) {
|
|
2372
|
-
relatedItems = [inputVar.relatedItem];
|
|
2373
|
-
subtitle = inputVar.relatedItem.locationPath.join(' <span class="related-sep">></span> ');
|
|
2374
|
-
} else {
|
|
2375
|
-
relatedItems = [];
|
|
2376
|
-
subtitle = void 0;
|
|
2377
|
-
}
|
|
2378
|
-
return {
|
|
2379
|
-
title: (inputVar == null ? void 0 : inputVar.varName) || "Unknown Input",
|
|
2380
|
-
subtitle,
|
|
2381
|
-
relatedItems
|
|
2382
|
-
};
|
|
2383
|
-
} else {
|
|
2384
|
-
return {
|
|
2385
|
-
title: "Multiple Inputs",
|
|
2386
|
-
relatedItems: this.getRelatedItemsForSettings(scenario.settings)
|
|
2387
|
-
};
|
|
2388
|
-
}
|
|
2389
|
-
default:
|
|
2390
|
-
(0, import_assert_never8.assertNever)(scenario);
|
|
3604
|
+
// src/comparison/config/comparison-scenarios.ts
|
|
3605
|
+
function getComparisonScenarios(scenarios) {
|
|
3606
|
+
return new ComparisonScenariosImpl(scenarios);
|
|
3607
|
+
}
|
|
3608
|
+
var ComparisonScenariosImpl = class {
|
|
3609
|
+
constructor(scenarios) {
|
|
3610
|
+
this.scenarioDefs = /* @__PURE__ */ new Map();
|
|
3611
|
+
for (const scenario of scenarios) {
|
|
3612
|
+
this.scenarioDefs.set(scenario.key, scenario);
|
|
2391
3613
|
}
|
|
2392
3614
|
}
|
|
2393
|
-
|
|
2394
|
-
|
|
2395
|
-
|
|
2396
|
-
|
|
2397
|
-
|
|
2398
|
-
if (scenario.settings.length === 1 && scenario.settings[0].kind === "position") {
|
|
2399
|
-
const setting = scenario.settings[0];
|
|
2400
|
-
return this.getInfoForPositionSetting(setting.inputVarId, setting.position);
|
|
2401
|
-
} else {
|
|
2402
|
-
return {
|
|
2403
|
-
title: `PLACEHOLDER (scenario info not provided)`,
|
|
2404
|
-
position: 1
|
|
2405
|
-
};
|
|
2406
|
-
}
|
|
2407
|
-
default:
|
|
2408
|
-
(0, import_assert_never8.assertNever)(scenario);
|
|
2409
|
-
}
|
|
3615
|
+
/**
|
|
3616
|
+
* Return all `ComparisonScenario` instances that are available for comparisons.
|
|
3617
|
+
*/
|
|
3618
|
+
getAllScenarios() {
|
|
3619
|
+
return this.scenarioDefs.values();
|
|
2410
3620
|
}
|
|
2411
|
-
|
|
2412
|
-
|
|
2413
|
-
|
|
2414
|
-
|
|
2415
|
-
|
|
2416
|
-
|
|
2417
|
-
|
|
2418
|
-
|
|
2419
|
-
|
|
2420
|
-
|
|
2421
|
-
|
|
2422
|
-
|
|
2423
|
-
|
|
2424
|
-
|
|
2425
|
-
|
|
2426
|
-
|
|
3621
|
+
/**
|
|
3622
|
+
* Return the scenario definition for the given key.
|
|
3623
|
+
*
|
|
3624
|
+
* @param key The key for the scenario.
|
|
3625
|
+
*/
|
|
3626
|
+
getScenario(key) {
|
|
3627
|
+
return this.scenarioDefs.get(key);
|
|
3628
|
+
}
|
|
3629
|
+
};
|
|
3630
|
+
|
|
3631
|
+
// src/config/synchronized-model.ts
|
|
3632
|
+
function synchronizedBundleModel(sourceModel) {
|
|
3633
|
+
const promiseQueue = new PromiseQueue();
|
|
3634
|
+
return {
|
|
3635
|
+
modelSpec: sourceModel.modelSpec,
|
|
3636
|
+
getDatasetsForScenario: (scenarioSpec, datasetKeys) => {
|
|
3637
|
+
return promiseQueue.add(() => sourceModel.getDatasetsForScenario(scenarioSpec, datasetKeys));
|
|
3638
|
+
},
|
|
3639
|
+
getGraphDataForScenario: (scenarioSpec, graphId) => {
|
|
3640
|
+
return promiseQueue.add(() => sourceModel.getGraphDataForScenario(scenarioSpec, graphId));
|
|
3641
|
+
},
|
|
3642
|
+
getGraphLinksForScenario: sourceModel.getGraphLinksForScenario.bind(sourceModel)
|
|
3643
|
+
};
|
|
3644
|
+
}
|
|
3645
|
+
var PromiseQueue = class {
|
|
3646
|
+
constructor() {
|
|
3647
|
+
this.tasks = [];
|
|
3648
|
+
this.runningCount = 0;
|
|
3649
|
+
}
|
|
3650
|
+
add(f) {
|
|
3651
|
+
return new Promise((resolve, reject) => {
|
|
3652
|
+
const run = () => __async(this, null, function* () {
|
|
3653
|
+
this.runningCount++;
|
|
3654
|
+
const promise = f();
|
|
3655
|
+
try {
|
|
3656
|
+
const result = yield promise;
|
|
3657
|
+
resolve(result);
|
|
3658
|
+
} catch (e) {
|
|
3659
|
+
reject(e);
|
|
3660
|
+
} finally {
|
|
3661
|
+
this.runningCount--;
|
|
3662
|
+
this.runNext();
|
|
3663
|
+
}
|
|
3664
|
+
});
|
|
3665
|
+
if (this.runningCount < 1) {
|
|
3666
|
+
run();
|
|
2427
3667
|
} else {
|
|
2428
|
-
|
|
3668
|
+
this.tasks.push(run);
|
|
2429
3669
|
}
|
|
2430
|
-
}
|
|
2431
|
-
subtitle = void 0;
|
|
2432
|
-
}
|
|
2433
|
-
let position;
|
|
2434
|
-
switch (inputPosition2) {
|
|
2435
|
-
case "at-default":
|
|
2436
|
-
position = 0;
|
|
2437
|
-
break;
|
|
2438
|
-
case "at-minimum":
|
|
2439
|
-
position = 1;
|
|
2440
|
-
break;
|
|
2441
|
-
case "at-maximum":
|
|
2442
|
-
position = 2;
|
|
2443
|
-
break;
|
|
2444
|
-
default:
|
|
2445
|
-
(0, import_assert_never8.assertNever)(inputPosition2);
|
|
2446
|
-
}
|
|
2447
|
-
return {
|
|
2448
|
-
title,
|
|
2449
|
-
subtitle,
|
|
2450
|
-
position
|
|
2451
|
-
};
|
|
3670
|
+
});
|
|
2452
3671
|
}
|
|
2453
|
-
|
|
2454
|
-
|
|
2455
|
-
|
|
2456
|
-
|
|
2457
|
-
|
|
2458
|
-
relatedItems.push(inputVar.relatedItem);
|
|
3672
|
+
runNext() {
|
|
3673
|
+
if (this.tasks.length > 0) {
|
|
3674
|
+
const task = this.tasks.shift();
|
|
3675
|
+
if (task) {
|
|
3676
|
+
task();
|
|
2459
3677
|
}
|
|
2460
3678
|
}
|
|
2461
|
-
return relatedItems;
|
|
2462
|
-
}
|
|
2463
|
-
getInputVarForSetting(setting) {
|
|
2464
|
-
const inputVarId = setting.inputVarId;
|
|
2465
|
-
const inputVarL = this.bundleL.modelSpec.inputVars.get(inputVarId);
|
|
2466
|
-
const inputVarR = this.bundleR.modelSpec.inputVars.get(inputVarId);
|
|
2467
|
-
return inputVarR || inputVarL;
|
|
2468
3679
|
}
|
|
2469
3680
|
};
|
|
2470
|
-
|
|
2471
|
-
|
|
2472
|
-
|
|
2473
|
-
|
|
2474
|
-
|
|
2475
|
-
|
|
2476
|
-
|
|
2477
|
-
|
|
2478
|
-
|
|
2479
|
-
|
|
2480
|
-
|
|
3681
|
+
|
|
3682
|
+
// src/config/config.ts
|
|
3683
|
+
function createConfig(options) {
|
|
3684
|
+
return __async(this, null, function* () {
|
|
3685
|
+
var _a;
|
|
3686
|
+
const origCurrentBundle = yield loadSynchronized(options.current);
|
|
3687
|
+
let currentBundle;
|
|
3688
|
+
let comparisonConfig;
|
|
3689
|
+
if (options.comparison === void 0) {
|
|
3690
|
+
currentBundle = origCurrentBundle;
|
|
3691
|
+
} else {
|
|
3692
|
+
const baselineBundle = yield loadSynchronized(options.comparison.baseline);
|
|
3693
|
+
const renamedDatasetKeys = (_a = options.comparison.datasets) == null ? void 0 : _a.renamedDatasetKeys;
|
|
3694
|
+
const invertedRenamedKeys = /* @__PURE__ */ new Map();
|
|
3695
|
+
renamedDatasetKeys == null ? void 0 : renamedDatasetKeys.forEach((newKey, oldKey) => {
|
|
3696
|
+
invertedRenamedKeys.set(newKey, oldKey);
|
|
3697
|
+
});
|
|
3698
|
+
const rightKeyForLeftKey = (leftKey) => {
|
|
3699
|
+
return (renamedDatasetKeys == null ? void 0 : renamedDatasetKeys.get(leftKey)) || leftKey;
|
|
3700
|
+
};
|
|
3701
|
+
const leftKeyForRightKey = (rightKey) => {
|
|
3702
|
+
return invertedRenamedKeys.get(rightKey) || rightKey;
|
|
3703
|
+
};
|
|
3704
|
+
const origBundleModelR = origCurrentBundle.model;
|
|
3705
|
+
const adjBundleModelR = {
|
|
3706
|
+
modelSpec: origBundleModelR.modelSpec,
|
|
3707
|
+
getDatasetsForScenario: (scenarioSpec, datasetKeys) => __async(this, null, function* () {
|
|
3708
|
+
const rightKeys = datasetKeys.map(rightKeyForLeftKey);
|
|
3709
|
+
const result = yield origBundleModelR.getDatasetsForScenario(scenarioSpec, rightKeys);
|
|
3710
|
+
const mapWithRightKeys = result.datasetMap;
|
|
3711
|
+
const mapWithLeftKeys = /* @__PURE__ */ new Map();
|
|
3712
|
+
for (const [rightKey, dataset] of mapWithRightKeys.entries()) {
|
|
3713
|
+
const leftKey = leftKeyForRightKey(rightKey);
|
|
3714
|
+
mapWithLeftKeys.set(leftKey, dataset);
|
|
3715
|
+
}
|
|
3716
|
+
return {
|
|
3717
|
+
datasetMap: mapWithLeftKeys,
|
|
3718
|
+
modelRunTime: result.modelRunTime
|
|
3719
|
+
};
|
|
3720
|
+
}),
|
|
3721
|
+
getGraphDataForScenario: origBundleModelR.getGraphDataForScenario.bind(origBundleModelR),
|
|
3722
|
+
getGraphLinksForScenario: origBundleModelR.getGraphLinksForScenario.bind(origBundleModelR)
|
|
3723
|
+
};
|
|
3724
|
+
currentBundle = __spreadProps(__spreadValues({}, origCurrentBundle), {
|
|
3725
|
+
model: adjBundleModelR
|
|
3726
|
+
});
|
|
3727
|
+
const modelSpecL = baselineBundle.model.modelSpec;
|
|
3728
|
+
const modelSpecR = currentBundle.model.modelSpec;
|
|
3729
|
+
const modelInputsL = new ModelInputs(modelSpecL);
|
|
3730
|
+
const modelInputsR = new ModelInputs(modelSpecR);
|
|
3731
|
+
const comparisonDefs = resolveComparisonSpecsFromSources(modelInputsL, modelInputsR, options.comparison.specs);
|
|
3732
|
+
comparisonConfig = {
|
|
3733
|
+
bundleL: baselineBundle,
|
|
3734
|
+
bundleR: currentBundle,
|
|
3735
|
+
thresholds: options.comparison.thresholds,
|
|
3736
|
+
scenarios: getComparisonScenarios(comparisonDefs.scenarios),
|
|
3737
|
+
datasets: getComparisonDatasets(modelSpecL, modelSpecR, options.comparison.datasets),
|
|
3738
|
+
viewGroups: comparisonDefs.viewGroups
|
|
3739
|
+
};
|
|
2481
3740
|
}
|
|
2482
|
-
|
|
2483
|
-
|
|
2484
|
-
|
|
3741
|
+
const checkConfig = {
|
|
3742
|
+
bundle: currentBundle,
|
|
3743
|
+
tests: options.check.tests
|
|
3744
|
+
};
|
|
3745
|
+
return {
|
|
3746
|
+
check: checkConfig,
|
|
3747
|
+
comparison: comparisonConfig
|
|
3748
|
+
};
|
|
3749
|
+
});
|
|
3750
|
+
}
|
|
3751
|
+
function loadSynchronized(sourceBundle) {
|
|
3752
|
+
return __async(this, null, function* () {
|
|
3753
|
+
const sourceModel = yield sourceBundle.bundle.initModel();
|
|
3754
|
+
const synchronizedModel = synchronizedBundleModel(sourceModel);
|
|
3755
|
+
return {
|
|
3756
|
+
name: sourceBundle.name,
|
|
3757
|
+
version: sourceBundle.bundle.version,
|
|
3758
|
+
model: synchronizedModel
|
|
3759
|
+
};
|
|
3760
|
+
});
|
|
2485
3761
|
}
|
|
2486
3762
|
|
|
2487
3763
|
// src/perf/perf-runner.ts
|
|
2488
|
-
var
|
|
3764
|
+
var import_assert_never12 = require("assert-never");
|
|
2489
3765
|
|
|
2490
3766
|
// src/perf/perf-stats.ts
|
|
2491
3767
|
var PerfStats = class {
|
|
@@ -2529,26 +3805,26 @@ var PerfRunner = class {
|
|
|
2529
3805
|
this.bundleModelL = bundleModelL;
|
|
2530
3806
|
this.bundleModelR = bundleModelR;
|
|
2531
3807
|
this.mode = mode;
|
|
2532
|
-
const
|
|
3808
|
+
const scenarioSpec = allInputsAtPositionSpec("at-default");
|
|
2533
3809
|
this.taskQueue = new TaskQueue({
|
|
2534
|
-
process:
|
|
3810
|
+
process: (request) => __async(this, null, function* () {
|
|
2535
3811
|
switch (request.kind) {
|
|
2536
3812
|
case "left": {
|
|
2537
|
-
const result =
|
|
3813
|
+
const result = yield bundleModelL.getDatasetsForScenario(scenarioSpec, []);
|
|
2538
3814
|
return {
|
|
2539
3815
|
runTimeL: result.modelRunTime
|
|
2540
3816
|
};
|
|
2541
3817
|
}
|
|
2542
3818
|
case "right": {
|
|
2543
|
-
const result =
|
|
3819
|
+
const result = yield bundleModelR.getDatasetsForScenario(scenarioSpec, []);
|
|
2544
3820
|
return {
|
|
2545
3821
|
runTimeR: result.modelRunTime
|
|
2546
3822
|
};
|
|
2547
3823
|
}
|
|
2548
3824
|
case "both": {
|
|
2549
|
-
const [resultL, resultR] =
|
|
2550
|
-
bundleModelL.getDatasetsForScenario(
|
|
2551
|
-
bundleModelR.getDatasetsForScenario(
|
|
3825
|
+
const [resultL, resultR] = yield Promise.all([
|
|
3826
|
+
bundleModelL.getDatasetsForScenario(scenarioSpec, []),
|
|
3827
|
+
bundleModelR.getDatasetsForScenario(scenarioSpec, [])
|
|
2552
3828
|
]);
|
|
2553
3829
|
return {
|
|
2554
3830
|
runTimeL: resultL.modelRunTime,
|
|
@@ -2556,9 +3832,9 @@ var PerfRunner = class {
|
|
|
2556
3832
|
};
|
|
2557
3833
|
}
|
|
2558
3834
|
default:
|
|
2559
|
-
(0,
|
|
3835
|
+
(0, import_assert_never12.assertNever)(request.kind);
|
|
2560
3836
|
}
|
|
2561
|
-
}
|
|
3837
|
+
})
|
|
2562
3838
|
});
|
|
2563
3839
|
}
|
|
2564
3840
|
start() {
|
|
@@ -2604,46 +3880,164 @@ var PerfRunner = class {
|
|
|
2604
3880
|
}
|
|
2605
3881
|
};
|
|
2606
3882
|
|
|
2607
|
-
// src/suite/suite-runner.ts
|
|
2608
|
-
var import_assert_never10 = __toESM(require("assert-never"), 1);
|
|
2609
|
-
|
|
2610
3883
|
// src/data/data-planner.ts
|
|
2611
|
-
var
|
|
2612
|
-
|
|
2613
|
-
|
|
2614
|
-
|
|
2615
|
-
|
|
2616
|
-
|
|
3884
|
+
var DataPlanner = class {
|
|
3885
|
+
/**
|
|
3886
|
+
* @param batchSize The maximum number of impl vars that can be fetched
|
|
3887
|
+
* with a single request; this is usually the same as the number of
|
|
3888
|
+
* normal model outputs.
|
|
3889
|
+
*/
|
|
3890
|
+
constructor(batchSize) {
|
|
3891
|
+
this.batchSize = batchSize;
|
|
3892
|
+
/** Tasks that need to access both "left" and "right" models in parallel. */
|
|
3893
|
+
this.taskSetsLR = /* @__PURE__ */ new Map();
|
|
3894
|
+
/** Tasks that only need to access the "left" model. */
|
|
3895
|
+
this.taskSetsL = /* @__PURE__ */ new Map();
|
|
3896
|
+
/** Tasks that only need to access the "right" model. */
|
|
3897
|
+
this.taskSetsR = /* @__PURE__ */ new Map();
|
|
3898
|
+
this.complete = false;
|
|
2617
3899
|
}
|
|
2618
|
-
|
|
2619
|
-
|
|
2620
|
-
|
|
3900
|
+
/**
|
|
3901
|
+
* Add a request to the plan for the given scenario(s) and data task.
|
|
3902
|
+
*
|
|
3903
|
+
* @param scenarioSpecL The input scenario used to configure the "left" model, or undefined if no data
|
|
3904
|
+
* is needed from the left model.
|
|
3905
|
+
* @param scenarioSpecR The input scenario used to configure the "right" model, or undefined if no data
|
|
3906
|
+
* is needed from the right model.
|
|
3907
|
+
* @param datasetKey The key for the dataset to be fetched from each model for the given scenario.
|
|
3908
|
+
* @param dataAction The action to be performed with the fetched datasets.
|
|
3909
|
+
*/
|
|
3910
|
+
addRequest(scenarioSpecL, scenarioSpecR, datasetKey, dataAction) {
|
|
3911
|
+
if (scenarioSpecL === void 0 && scenarioSpecR === void 0) {
|
|
3912
|
+
console.warn("WARNING: Both scenario specs are undefined for DataPlanner request, skipping");
|
|
3913
|
+
return;
|
|
3914
|
+
}
|
|
3915
|
+
let taskSetsMap;
|
|
3916
|
+
let uid;
|
|
3917
|
+
if (scenarioSpecL && scenarioSpecR) {
|
|
3918
|
+
taskSetsMap = this.taskSetsLR;
|
|
3919
|
+
uid = scenarioPairUid(scenarioSpecL, scenarioSpecR);
|
|
3920
|
+
} else if (scenarioSpecR) {
|
|
3921
|
+
taskSetsMap = this.taskSetsR;
|
|
3922
|
+
uid = scenarioSpecR.uid;
|
|
3923
|
+
} else {
|
|
3924
|
+
taskSetsMap = this.taskSetsL;
|
|
3925
|
+
uid = scenarioSpecL.uid;
|
|
2621
3926
|
}
|
|
2622
|
-
|
|
3927
|
+
let taskSet = taskSetsMap.get(uid);
|
|
3928
|
+
if (!taskSet) {
|
|
3929
|
+
taskSet = new DataTaskSet(scenarioSpecL, scenarioSpecR);
|
|
3930
|
+
taskSetsMap.set(uid, taskSet);
|
|
3931
|
+
}
|
|
3932
|
+
taskSet.addTask({
|
|
2623
3933
|
datasetKey,
|
|
2624
|
-
|
|
3934
|
+
dataAction
|
|
3935
|
+
});
|
|
3936
|
+
}
|
|
3937
|
+
/**
|
|
3938
|
+
* Build a plan that minimizes the number of data fetches needed.
|
|
3939
|
+
*/
|
|
3940
|
+
buildPlan() {
|
|
3941
|
+
if (this.complete) {
|
|
3942
|
+
throw new Error("DataPlanner.buildPlan() can only be called once");
|
|
3943
|
+
}
|
|
3944
|
+
this.complete = true;
|
|
3945
|
+
const lKeyMappings = /* @__PURE__ */ new Map();
|
|
3946
|
+
const rKeyMappings = /* @__PURE__ */ new Map();
|
|
3947
|
+
for (const lrUid of this.taskSetsLR.keys()) {
|
|
3948
|
+
const [lUid, rUid] = lrUid.split("::");
|
|
3949
|
+
if (!lKeyMappings.has(lUid)) {
|
|
3950
|
+
lKeyMappings.set(lUid, lrUid);
|
|
3951
|
+
}
|
|
3952
|
+
if (!rKeyMappings.has(rUid)) {
|
|
3953
|
+
rKeyMappings.set(rUid, lrUid);
|
|
3954
|
+
}
|
|
3955
|
+
}
|
|
3956
|
+
function merge(taskSetsLR, taskSetsForSide, keyMappingsForSide) {
|
|
3957
|
+
for (const [keyForSide, taskSetForSide] of taskSetsForSide.entries()) {
|
|
3958
|
+
const lrKey = keyMappingsForSide.get(keyForSide);
|
|
3959
|
+
if (lrKey) {
|
|
3960
|
+
const taskSetLR = taskSetsLR.get(lrKey);
|
|
3961
|
+
taskSetLR.merge(taskSetForSide);
|
|
3962
|
+
taskSetsForSide.delete(keyForSide);
|
|
3963
|
+
}
|
|
3964
|
+
}
|
|
3965
|
+
}
|
|
3966
|
+
merge(this.taskSetsLR, this.taskSetsL, lKeyMappings);
|
|
3967
|
+
merge(this.taskSetsLR, this.taskSetsR, rKeyMappings);
|
|
3968
|
+
const requests = [];
|
|
3969
|
+
const batchSize = this.batchSize;
|
|
3970
|
+
function addRequests(taskSets) {
|
|
3971
|
+
for (const taskSet of taskSets) {
|
|
3972
|
+
requests.push(...taskSet.buildRequests(batchSize));
|
|
3973
|
+
}
|
|
3974
|
+
}
|
|
3975
|
+
addRequests(this.taskSetsLR.values());
|
|
3976
|
+
addRequests(this.taskSetsL.values());
|
|
3977
|
+
addRequests(this.taskSetsR.values());
|
|
3978
|
+
return {
|
|
3979
|
+
requests
|
|
2625
3980
|
};
|
|
3981
|
+
}
|
|
3982
|
+
};
|
|
3983
|
+
var DataTaskSet = class {
|
|
3984
|
+
constructor(scenarioSpecL, scenarioSpecR) {
|
|
3985
|
+
this.scenarioSpecL = scenarioSpecL;
|
|
3986
|
+
this.scenarioSpecR = scenarioSpecR;
|
|
3987
|
+
this.modelTasks = /* @__PURE__ */ new Map();
|
|
3988
|
+
this.modelImplTasks = /* @__PURE__ */ new Map();
|
|
3989
|
+
}
|
|
3990
|
+
/**
|
|
3991
|
+
* Add a task that will be performed when the data is fetched for the scenario(s)
|
|
3992
|
+
* associated with this task set.
|
|
3993
|
+
*
|
|
3994
|
+
* @param dataTask A task that performs an action using the fetched dataset(s).
|
|
3995
|
+
*/
|
|
3996
|
+
addTask(dataTask) {
|
|
2626
3997
|
let taskMap;
|
|
2627
|
-
if (datasetKey.startsWith("ModelImpl")) {
|
|
3998
|
+
if (dataTask.datasetKey.startsWith("ModelImpl")) {
|
|
2628
3999
|
taskMap = this.modelImplTasks;
|
|
2629
4000
|
} else {
|
|
2630
4001
|
taskMap = this.modelTasks;
|
|
2631
4002
|
}
|
|
2632
|
-
let tasks = taskMap.get(datasetKey);
|
|
4003
|
+
let tasks = taskMap.get(dataTask.datasetKey);
|
|
2633
4004
|
if (!tasks) {
|
|
2634
4005
|
tasks = [];
|
|
2635
|
-
taskMap.set(datasetKey, tasks);
|
|
4006
|
+
taskMap.set(dataTask.datasetKey, tasks);
|
|
2636
4007
|
}
|
|
2637
4008
|
tasks.push(dataTask);
|
|
2638
4009
|
}
|
|
4010
|
+
/**
|
|
4011
|
+
* Add all tasks from the given set into this set.
|
|
4012
|
+
*
|
|
4013
|
+
* @param otherTaskSet The other task set that will be merged into this one.
|
|
4014
|
+
*/
|
|
4015
|
+
merge(otherTaskSet) {
|
|
4016
|
+
for (const tasks of otherTaskSet.modelTasks.values()) {
|
|
4017
|
+
for (const task of tasks) {
|
|
4018
|
+
this.addTask(task);
|
|
4019
|
+
}
|
|
4020
|
+
}
|
|
4021
|
+
for (const tasks of otherTaskSet.modelImplTasks.values()) {
|
|
4022
|
+
for (const task of tasks) {
|
|
4023
|
+
this.addTask(task);
|
|
4024
|
+
}
|
|
4025
|
+
}
|
|
4026
|
+
}
|
|
4027
|
+
/**
|
|
4028
|
+
* Create one or more data requests that can be used to fetch data for the configured scenario(s).
|
|
4029
|
+
*
|
|
4030
|
+
* @param batchSize The maximum number of impl vars that can be fetched with a single request.
|
|
4031
|
+
* This is usually the same as the number of normal model outputs.
|
|
4032
|
+
*/
|
|
2639
4033
|
buildRequests(batchSize) {
|
|
2640
4034
|
const dataRequests = [];
|
|
2641
4035
|
if (this.modelTasks.size > 0) {
|
|
2642
4036
|
const dataTasks = [];
|
|
2643
4037
|
this.modelTasks.forEach((tasks) => dataTasks.push(...tasks));
|
|
2644
4038
|
dataRequests.push({
|
|
2645
|
-
|
|
2646
|
-
|
|
4039
|
+
scenarioSpecL: this.scenarioSpecL,
|
|
4040
|
+
scenarioSpecR: this.scenarioSpecR,
|
|
2647
4041
|
dataTasks
|
|
2648
4042
|
});
|
|
2649
4043
|
}
|
|
@@ -2656,8 +4050,8 @@ var ScenarioTaskSet = class {
|
|
|
2656
4050
|
dataTasks.push(...this.modelImplTasks.get(datasetKey));
|
|
2657
4051
|
}
|
|
2658
4052
|
dataRequests.push({
|
|
2659
|
-
|
|
2660
|
-
|
|
4053
|
+
scenarioSpecL: this.scenarioSpecL,
|
|
4054
|
+
scenarioSpecR: this.scenarioSpecR,
|
|
2661
4055
|
dataTasks
|
|
2662
4056
|
});
|
|
2663
4057
|
}
|
|
@@ -2665,29 +4059,11 @@ var ScenarioTaskSet = class {
|
|
|
2665
4059
|
return dataRequests;
|
|
2666
4060
|
}
|
|
2667
4061
|
};
|
|
2668
|
-
|
|
2669
|
-
|
|
2670
|
-
|
|
2671
|
-
|
|
2672
|
-
|
|
2673
|
-
addRequest(kind, scenario, datasetKey, dataFunc) {
|
|
2674
|
-
let scenarioTaskSet = this.scenarioTaskSets.get(scenario.key);
|
|
2675
|
-
if (!scenarioTaskSet) {
|
|
2676
|
-
scenarioTaskSet = new ScenarioTaskSet(scenario);
|
|
2677
|
-
this.scenarioTaskSets.set(scenario.key, scenarioTaskSet);
|
|
2678
|
-
}
|
|
2679
|
-
scenarioTaskSet.addTask(kind, datasetKey, dataFunc);
|
|
2680
|
-
}
|
|
2681
|
-
buildPlan() {
|
|
2682
|
-
const requests = [];
|
|
2683
|
-
for (const taskSet of this.scenarioTaskSets.values()) {
|
|
2684
|
-
requests.push(...taskSet.buildRequests(this.batchSize));
|
|
2685
|
-
}
|
|
2686
|
-
return {
|
|
2687
|
-
requests
|
|
2688
|
-
};
|
|
2689
|
-
}
|
|
2690
|
-
};
|
|
4062
|
+
function scenarioPairUid(scenarioSpecL, scenarioSpecR) {
|
|
4063
|
+
const uidL = (scenarioSpecL == null ? void 0 : scenarioSpecL.uid) || "";
|
|
4064
|
+
const uidR = (scenarioSpecR == null ? void 0 : scenarioSpecR.uid) || "";
|
|
4065
|
+
return `${uidL}::${uidR}`;
|
|
4066
|
+
}
|
|
2691
4067
|
|
|
2692
4068
|
// src/check/check-runner.ts
|
|
2693
4069
|
function runChecks(checkConfig, checkSpec, dataPlanner, refDataPlanner, simplifyScenarios) {
|
|
@@ -2697,7 +4073,7 @@ function runChecks(checkConfig, checkSpec, dataPlanner, refDataPlanner, simplify
|
|
|
2697
4073
|
const checkPlan = checkPlanner.buildPlan();
|
|
2698
4074
|
const refDatasets = /* @__PURE__ */ new Map();
|
|
2699
4075
|
for (const [dataRefKey, dataRef] of checkPlan.dataRefs.entries()) {
|
|
2700
|
-
refDataPlanner.addRequest(
|
|
4076
|
+
refDataPlanner.addRequest(void 0, dataRef.scenario.spec, dataRef.dataset.datasetKey, (datasets) => {
|
|
2701
4077
|
const dataset = datasets.datasetR;
|
|
2702
4078
|
if (dataset) {
|
|
2703
4079
|
refDatasets.set(dataRefKey, dataset);
|
|
@@ -2706,7 +4082,7 @@ function runChecks(checkConfig, checkSpec, dataPlanner, refDataPlanner, simplify
|
|
|
2706
4082
|
}
|
|
2707
4083
|
const checkResults = /* @__PURE__ */ new Map();
|
|
2708
4084
|
for (const [checkKey, checkTask] of checkPlan.tasks.entries()) {
|
|
2709
|
-
dataPlanner.addRequest(
|
|
4085
|
+
dataPlanner.addRequest(void 0, checkTask.scenario.spec, checkTask.dataset.datasetKey, (datasets) => {
|
|
2710
4086
|
const dataset = datasets.datasetR;
|
|
2711
4087
|
const checkResult = runCheck(checkTask, dataset, refDatasets);
|
|
2712
4088
|
checkResults.set(checkKey, checkResult);
|
|
@@ -2737,7 +4113,7 @@ function runCheck(checkTask, dataset, refDatasets) {
|
|
|
2737
4113
|
name: dataRef.dataset.name
|
|
2738
4114
|
}
|
|
2739
4115
|
};
|
|
2740
|
-
} else if (dataRef.scenario.
|
|
4116
|
+
} else if (dataRef.scenario.spec === void 0) {
|
|
2741
4117
|
if (dataRef.scenario.error) {
|
|
2742
4118
|
return {
|
|
2743
4119
|
status: "error",
|
|
@@ -2774,16 +4150,15 @@ function runCheck(checkTask, dataset, refDatasets) {
|
|
|
2774
4150
|
return checkTask.action.run(dataset, opRefDatasets);
|
|
2775
4151
|
}
|
|
2776
4152
|
|
|
2777
|
-
// src/
|
|
2778
|
-
function
|
|
2779
|
-
const
|
|
2780
|
-
const
|
|
2781
|
-
|
|
2782
|
-
const datasetKeys = compareConfig.datasets.getDatasetKeysForScenario(scenario);
|
|
4153
|
+
// src/comparison/run/comparison-runner.ts
|
|
4154
|
+
function runComparisons(comparisonConfig, dataPlanner) {
|
|
4155
|
+
const testReports = [];
|
|
4156
|
+
for (const scenario of comparisonConfig.scenarios.getAllScenarios()) {
|
|
4157
|
+
const datasetKeys = comparisonConfig.datasets.getDatasetKeysForScenario(scenario);
|
|
2783
4158
|
for (const datasetKey of datasetKeys) {
|
|
2784
|
-
dataPlanner.addRequest(
|
|
4159
|
+
dataPlanner.addRequest(scenario.specL, scenario.specR, datasetKey, (datasets) => {
|
|
2785
4160
|
const diffReport = diffDatasets(datasets.datasetL, datasets.datasetR);
|
|
2786
|
-
|
|
4161
|
+
testReports.push({
|
|
2787
4162
|
scenarioKey: scenario.key,
|
|
2788
4163
|
datasetKey,
|
|
2789
4164
|
diffReport
|
|
@@ -2792,7 +4167,7 @@ function runCompare(compareConfig, dataPlanner, simplifyScenarios) {
|
|
|
2792
4167
|
}
|
|
2793
4168
|
}
|
|
2794
4169
|
return () => {
|
|
2795
|
-
return
|
|
4170
|
+
return testReports;
|
|
2796
4171
|
};
|
|
2797
4172
|
}
|
|
2798
4173
|
|
|
@@ -2830,9 +4205,9 @@ var SuiteRunner = class {
|
|
|
2830
4205
|
const checkSpec = checkSpecResult.value;
|
|
2831
4206
|
const simplifyScenarios = (options == null ? void 0 : options.simplifyScenarios) === true;
|
|
2832
4207
|
const buildCheckReport2 = runChecks(this.config.check, checkSpec, dataPlanner, refDataPlanner, simplifyScenarios);
|
|
2833
|
-
let
|
|
2834
|
-
if (this.config.
|
|
2835
|
-
|
|
4208
|
+
let buildComparisonTestReports;
|
|
4209
|
+
if (this.config.comparison) {
|
|
4210
|
+
buildComparisonTestReports = runComparisons(this.config.comparison, dataPlanner);
|
|
2836
4211
|
}
|
|
2837
4212
|
this.taskQueue.onIdle = (error) => {
|
|
2838
4213
|
var _a2, _b2, _c2, _d2;
|
|
@@ -2843,17 +4218,17 @@ var SuiteRunner = class {
|
|
|
2843
4218
|
(_b2 = (_a2 = this.callbacks).onError) == null ? void 0 : _b2.call(_a2, error);
|
|
2844
4219
|
} else {
|
|
2845
4220
|
const checkReport = buildCheckReport2();
|
|
2846
|
-
let
|
|
2847
|
-
if (this.config.
|
|
2848
|
-
|
|
2849
|
-
|
|
4221
|
+
let comparisonReport;
|
|
4222
|
+
if (this.config.comparison) {
|
|
4223
|
+
comparisonReport = {
|
|
4224
|
+
testReports: buildComparisonTestReports(),
|
|
2850
4225
|
perfReportL: this.perfStatsL.toReport(),
|
|
2851
4226
|
perfReportR: this.perfStatsR.toReport()
|
|
2852
4227
|
};
|
|
2853
4228
|
}
|
|
2854
4229
|
(_d2 = (_c2 = this.callbacks).onComplete) == null ? void 0 : _d2.call(_c2, {
|
|
2855
4230
|
checkReport,
|
|
2856
|
-
|
|
4231
|
+
comparisonReport
|
|
2857
4232
|
});
|
|
2858
4233
|
}
|
|
2859
4234
|
};
|
|
@@ -2862,10 +4237,10 @@ var SuiteRunner = class {
|
|
|
2862
4237
|
const dataRequests = [...refDataPlan.requests, ...dataPlan.requests];
|
|
2863
4238
|
const taskCount = dataRequests.length;
|
|
2864
4239
|
if (taskCount === 0) {
|
|
2865
|
-
let
|
|
2866
|
-
if (this.config.
|
|
2867
|
-
|
|
2868
|
-
|
|
4240
|
+
let comparisonReport;
|
|
4241
|
+
if (this.config.comparison) {
|
|
4242
|
+
comparisonReport = {
|
|
4243
|
+
testReports: [],
|
|
2869
4244
|
perfReportL: this.perfStatsL.toReport(),
|
|
2870
4245
|
perfReportR: this.perfStatsR.toReport()
|
|
2871
4246
|
};
|
|
@@ -2876,7 +4251,7 @@ var SuiteRunner = class {
|
|
|
2876
4251
|
checkReport: {
|
|
2877
4252
|
groups: []
|
|
2878
4253
|
},
|
|
2879
|
-
|
|
4254
|
+
comparisonReport
|
|
2880
4255
|
});
|
|
2881
4256
|
return;
|
|
2882
4257
|
}
|
|
@@ -2890,51 +4265,46 @@ var SuiteRunner = class {
|
|
|
2890
4265
|
});
|
|
2891
4266
|
}
|
|
2892
4267
|
}
|
|
2893
|
-
|
|
2894
|
-
|
|
2895
|
-
|
|
2896
|
-
datasetKeySet
|
|
2897
|
-
|
|
2898
|
-
|
|
2899
|
-
const scenario = request.scenario;
|
|
2900
|
-
let datasetsResultL;
|
|
2901
|
-
let datasetsResultR;
|
|
2902
|
-
switch (request.kind) {
|
|
2903
|
-
case "check": {
|
|
2904
|
-
const bundleModel = this.config.check.bundle.model;
|
|
2905
|
-
datasetsResultR = await bundleModel.getDatasetsForScenario(scenario, datasetKeys);
|
|
2906
|
-
break;
|
|
4268
|
+
processRequest(request) {
|
|
4269
|
+
return __async(this, null, function* () {
|
|
4270
|
+
var _a, _b;
|
|
4271
|
+
const datasetKeySet = /* @__PURE__ */ new Set();
|
|
4272
|
+
for (const dataTask of request.dataTasks) {
|
|
4273
|
+
datasetKeySet.add(dataTask.datasetKey);
|
|
2907
4274
|
}
|
|
2908
|
-
|
|
2909
|
-
|
|
2910
|
-
|
|
2911
|
-
|
|
2912
|
-
|
|
2913
|
-
|
|
2914
|
-
|
|
2915
|
-
|
|
2916
|
-
|
|
2917
|
-
break;
|
|
4275
|
+
const datasetKeys = [...datasetKeySet];
|
|
4276
|
+
function getDatasets(bundleModel, scenarioSpec) {
|
|
4277
|
+
return __async(this, null, function* () {
|
|
4278
|
+
if (bundleModel && scenarioSpec) {
|
|
4279
|
+
return bundleModel.getDatasetsForScenario(scenarioSpec, datasetKeys);
|
|
4280
|
+
} else {
|
|
4281
|
+
return void 0;
|
|
4282
|
+
}
|
|
4283
|
+
});
|
|
2918
4284
|
}
|
|
2919
|
-
|
|
2920
|
-
|
|
2921
|
-
|
|
2922
|
-
|
|
2923
|
-
|
|
2924
|
-
|
|
2925
|
-
|
|
2926
|
-
|
|
2927
|
-
|
|
2928
|
-
|
|
2929
|
-
|
|
2930
|
-
|
|
2931
|
-
const
|
|
2932
|
-
const
|
|
2933
|
-
dataTask.
|
|
2934
|
-
datasetL
|
|
2935
|
-
datasetR
|
|
2936
|
-
|
|
2937
|
-
|
|
4285
|
+
const bundleModelL = (_a = this.config.comparison) == null ? void 0 : _a.bundleL.model;
|
|
4286
|
+
const bundleModelR = ((_b = this.config.comparison) == null ? void 0 : _b.bundleR.model) || this.config.check.bundle.model;
|
|
4287
|
+
const [datasetsResultL, datasetsResultR] = yield Promise.all([
|
|
4288
|
+
getDatasets(bundleModelL, request.scenarioSpecL),
|
|
4289
|
+
getDatasets(bundleModelR, request.scenarioSpecR)
|
|
4290
|
+
]);
|
|
4291
|
+
if (datasetsResultL == null ? void 0 : datasetsResultL.modelRunTime) {
|
|
4292
|
+
this.perfStatsL.addRun(datasetsResultL == null ? void 0 : datasetsResultL.modelRunTime);
|
|
4293
|
+
}
|
|
4294
|
+
if (datasetsResultR == null ? void 0 : datasetsResultR.modelRunTime) {
|
|
4295
|
+
this.perfStatsR.addRun(datasetsResultR == null ? void 0 : datasetsResultR.modelRunTime);
|
|
4296
|
+
}
|
|
4297
|
+
const datasetMapL = datasetsResultL == null ? void 0 : datasetsResultL.datasetMap;
|
|
4298
|
+
const datasetMapR = datasetsResultR == null ? void 0 : datasetsResultR.datasetMap;
|
|
4299
|
+
for (const dataTask of request.dataTasks) {
|
|
4300
|
+
const datasetL = datasetMapL == null ? void 0 : datasetMapL.get(dataTask.datasetKey);
|
|
4301
|
+
const datasetR = datasetMapR == null ? void 0 : datasetMapR.get(dataTask.datasetKey);
|
|
4302
|
+
dataTask.dataAction({
|
|
4303
|
+
datasetL,
|
|
4304
|
+
datasetR
|
|
4305
|
+
});
|
|
4306
|
+
}
|
|
4307
|
+
});
|
|
2938
4308
|
}
|
|
2939
4309
|
};
|
|
2940
4310
|
function runSuite(config, callbacks, options) {
|
|
@@ -2945,44 +4315,35 @@ function runSuite(config, callbacks, options) {
|
|
|
2945
4315
|
};
|
|
2946
4316
|
}
|
|
2947
4317
|
|
|
2948
|
-
// src/suite/suite-
|
|
4318
|
+
// src/suite/suite-reporting.ts
|
|
2949
4319
|
function suiteSummaryFromReport(suiteReport) {
|
|
2950
4320
|
const checkSummary = checkSummaryFromReport(suiteReport.checkReport);
|
|
2951
|
-
let
|
|
2952
|
-
if (suiteReport.
|
|
2953
|
-
|
|
4321
|
+
let comparisonSummary;
|
|
4322
|
+
if (suiteReport.comparisonReport) {
|
|
4323
|
+
comparisonSummary = comparisonSummaryFromReport(suiteReport.comparisonReport);
|
|
2954
4324
|
}
|
|
2955
4325
|
return {
|
|
2956
4326
|
checkSummary,
|
|
2957
|
-
|
|
4327
|
+
comparisonSummary
|
|
2958
4328
|
};
|
|
2959
4329
|
}
|
|
2960
4330
|
// Annotate the CommonJS export names for ESM import in node:
|
|
2961
4331
|
0 && (module.exports = {
|
|
2962
4332
|
CheckDataCoordinator,
|
|
2963
|
-
|
|
2964
|
-
DatasetManager,
|
|
4333
|
+
ComparisonDataCoordinator,
|
|
2965
4334
|
PerfRunner,
|
|
2966
4335
|
PerfStats,
|
|
2967
|
-
|
|
2968
|
-
allInputsAtPositionScenario,
|
|
4336
|
+
categorizeComparisonTestSummaries,
|
|
2969
4337
|
checkReportFromSummary,
|
|
2970
4338
|
checkSummaryFromReport,
|
|
2971
|
-
|
|
2972
|
-
compareSummaryFromReport,
|
|
4339
|
+
comparisonSummaryFromReport,
|
|
2973
4340
|
createConfig,
|
|
2974
4341
|
datasetMessage,
|
|
2975
4342
|
diffDatasets,
|
|
2976
4343
|
diffGraphs,
|
|
2977
|
-
inputAtPositionScenario,
|
|
2978
|
-
inputAtValueScenario,
|
|
2979
|
-
matrixScenarios,
|
|
2980
|
-
positionSetting,
|
|
2981
4344
|
predicateMessage,
|
|
2982
4345
|
runSuite,
|
|
2983
4346
|
scenarioMessage,
|
|
2984
|
-
|
|
2985
|
-
suiteSummaryFromReport,
|
|
2986
|
-
valueSetting
|
|
4347
|
+
suiteSummaryFromReport
|
|
2987
4348
|
});
|
|
2988
4349
|
//# sourceMappingURL=index.cjs.map
|