@sdeverywhere/check-core 0.1.1 → 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 +425 -190
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1272 -0
- package/dist/index.d.ts +75 -51
- package/dist/index.js +425 -191
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -1,10 +1,54 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __defProps = Object.defineProperties;
|
|
3
|
+
var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
|
|
4
|
+
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __propIsEnum = Object.prototype.propertyIsEnumerable;
|
|
7
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
8
|
+
var __spreadValues = (a, b) => {
|
|
9
|
+
for (var prop in b || (b = {}))
|
|
10
|
+
if (__hasOwnProp.call(b, prop))
|
|
11
|
+
__defNormalProp(a, prop, b[prop]);
|
|
12
|
+
if (__getOwnPropSymbols)
|
|
13
|
+
for (var prop of __getOwnPropSymbols(b)) {
|
|
14
|
+
if (__propIsEnum.call(b, prop))
|
|
15
|
+
__defNormalProp(a, prop, b[prop]);
|
|
16
|
+
}
|
|
17
|
+
return a;
|
|
18
|
+
};
|
|
19
|
+
var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
|
|
20
|
+
var __async = (__this, __arguments, generator) => {
|
|
21
|
+
return new Promise((resolve, reject) => {
|
|
22
|
+
var fulfilled = (value) => {
|
|
23
|
+
try {
|
|
24
|
+
step(generator.next(value));
|
|
25
|
+
} catch (e) {
|
|
26
|
+
reject(e);
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
var rejected = (value) => {
|
|
30
|
+
try {
|
|
31
|
+
step(generator.throw(value));
|
|
32
|
+
} catch (e) {
|
|
33
|
+
reject(e);
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
|
|
37
|
+
step((generator = generator.apply(__this, __arguments)).next());
|
|
38
|
+
});
|
|
39
|
+
};
|
|
40
|
+
|
|
1
41
|
// src/_shared/task-queue.ts
|
|
2
42
|
var TaskQueue = class {
|
|
3
43
|
constructor(processor) {
|
|
4
44
|
this.processor = processor;
|
|
45
|
+
/** The queue of task keys, most recent at front. */
|
|
5
46
|
this.taskKeyQueue = [];
|
|
47
|
+
/** The map of tasks. */
|
|
6
48
|
this.taskMap = /* @__PURE__ */ new Map();
|
|
49
|
+
/** Whether tasks are being processed. */
|
|
7
50
|
this.processing = false;
|
|
51
|
+
/** Whether `shutdown` has been called. */
|
|
8
52
|
this.stopped = false;
|
|
9
53
|
}
|
|
10
54
|
addTask(key, input, onComplete) {
|
|
@@ -42,39 +86,41 @@ var TaskQueue = class {
|
|
|
42
86
|
});
|
|
43
87
|
}
|
|
44
88
|
}
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
const task = this.taskMap.get(taskKey);
|
|
52
|
-
if (task) {
|
|
53
|
-
this.taskMap.delete(taskKey);
|
|
54
|
-
} else {
|
|
55
|
-
return;
|
|
56
|
-
}
|
|
57
|
-
let output;
|
|
58
|
-
try {
|
|
59
|
-
output = await this.processor.process(task.input);
|
|
60
|
-
} catch (e) {
|
|
61
|
-
if (!this.stopped) {
|
|
62
|
-
this.shutdown();
|
|
63
|
-
(_a = this.onIdle) == null ? void 0 : _a.call(this, e);
|
|
89
|
+
processNextTask() {
|
|
90
|
+
return __async(this, null, function* () {
|
|
91
|
+
var _a, _b;
|
|
92
|
+
const taskKey = this.taskKeyQueue.shift();
|
|
93
|
+
if (!taskKey) {
|
|
94
|
+
return;
|
|
64
95
|
}
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
this.processNextTask();
|
|
71
|
-
});
|
|
72
|
-
} else {
|
|
73
|
-
this.processing = false;
|
|
74
|
-
if (!this.stopped) {
|
|
75
|
-
(_b = this.onIdle) == null ? void 0 : _b.call(this);
|
|
96
|
+
const task = this.taskMap.get(taskKey);
|
|
97
|
+
if (task) {
|
|
98
|
+
this.taskMap.delete(taskKey);
|
|
99
|
+
} else {
|
|
100
|
+
return;
|
|
76
101
|
}
|
|
77
|
-
|
|
102
|
+
let output;
|
|
103
|
+
try {
|
|
104
|
+
output = yield this.processor.process(task.input);
|
|
105
|
+
} catch (e) {
|
|
106
|
+
if (!this.stopped) {
|
|
107
|
+
this.shutdown();
|
|
108
|
+
(_a = this.onIdle) == null ? void 0 : _a.call(this, e);
|
|
109
|
+
}
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
task.onComplete(output);
|
|
113
|
+
if (this.taskKeyQueue.length > 0) {
|
|
114
|
+
setTimeout(() => {
|
|
115
|
+
this.processNextTask();
|
|
116
|
+
});
|
|
117
|
+
} else {
|
|
118
|
+
this.processing = false;
|
|
119
|
+
if (!this.stopped) {
|
|
120
|
+
(_b = this.onIdle) == null ? void 0 : _b.call(this);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
});
|
|
78
124
|
}
|
|
79
125
|
};
|
|
80
126
|
|
|
@@ -83,13 +129,13 @@ var CheckDataCoordinator = class {
|
|
|
83
129
|
constructor(bundleModel) {
|
|
84
130
|
this.bundleModel = bundleModel;
|
|
85
131
|
this.taskQueue = new TaskQueue({
|
|
86
|
-
process:
|
|
87
|
-
const result =
|
|
132
|
+
process: (request) => __async(this, null, function* () {
|
|
133
|
+
const result = yield this.bundleModel.getDatasetsForScenario(request.scenarioSpec, [request.datasetKey]);
|
|
88
134
|
const dataset = result.datasetMap.get(request.datasetKey);
|
|
89
135
|
return {
|
|
90
136
|
dataset
|
|
91
137
|
};
|
|
92
|
-
}
|
|
138
|
+
})
|
|
93
139
|
});
|
|
94
140
|
}
|
|
95
141
|
requestDataset(requestKey, scenarioSpec, datasetKey, onResponse) {
|
|
@@ -1642,6 +1688,24 @@ var CheckPlanner = class {
|
|
|
1642
1688
|
dataRefs: this.dataRefs
|
|
1643
1689
|
};
|
|
1644
1690
|
}
|
|
1691
|
+
/**
|
|
1692
|
+
* Record any references to additional datasets contained in the given predicate.
|
|
1693
|
+
* For example, if the predicate is:
|
|
1694
|
+
* ```
|
|
1695
|
+
* gt:
|
|
1696
|
+
* dataset:
|
|
1697
|
+
* name: 'XYZ'
|
|
1698
|
+
* scenario:
|
|
1699
|
+
* inputs: all
|
|
1700
|
+
* at: default
|
|
1701
|
+
* ```
|
|
1702
|
+
* this will add a reference to the scenario/dataset pair so that the data can
|
|
1703
|
+
* be fetched in a later stage.
|
|
1704
|
+
*
|
|
1705
|
+
* @param predicateSpec The predicate spec.
|
|
1706
|
+
* @param checkScenario The scenario in which the dataset is being checked.
|
|
1707
|
+
* @param checkDataset The dataset that is being checked.
|
|
1708
|
+
*/
|
|
1645
1709
|
addDataRefs(predicateSpec, checkScenario, checkDataset) {
|
|
1646
1710
|
let dataRefs;
|
|
1647
1711
|
const addDataRef = (op) => {
|
|
@@ -1770,7 +1834,7 @@ var ComparisonDataCoordinator = class {
|
|
|
1770
1834
|
this.bundleModelL = bundleModelL;
|
|
1771
1835
|
this.bundleModelR = bundleModelR;
|
|
1772
1836
|
this.taskQueue = new TaskQueue({
|
|
1773
|
-
process:
|
|
1837
|
+
process: (request) => __async(this, null, function* () {
|
|
1774
1838
|
switch (request.kind) {
|
|
1775
1839
|
case "dataset":
|
|
1776
1840
|
return this.processDatasetRequest(request);
|
|
@@ -1779,44 +1843,52 @@ var ComparisonDataCoordinator = class {
|
|
|
1779
1843
|
default:
|
|
1780
1844
|
assertNever7(request);
|
|
1781
1845
|
}
|
|
1782
|
-
}
|
|
1846
|
+
})
|
|
1783
1847
|
});
|
|
1784
1848
|
}
|
|
1785
|
-
|
|
1786
|
-
|
|
1787
|
-
|
|
1788
|
-
return
|
|
1789
|
-
|
|
1790
|
-
|
|
1849
|
+
processDatasetRequest(request) {
|
|
1850
|
+
return __async(this, null, function* () {
|
|
1851
|
+
function fetchDatasets(bundleModel, scenarioSpec) {
|
|
1852
|
+
return __async(this, null, function* () {
|
|
1853
|
+
if (scenarioSpec) {
|
|
1854
|
+
return bundleModel.getDatasetsForScenario(scenarioSpec, request.datasetKeys);
|
|
1855
|
+
} else {
|
|
1856
|
+
return void 0;
|
|
1857
|
+
}
|
|
1858
|
+
});
|
|
1791
1859
|
}
|
|
1792
|
-
|
|
1793
|
-
|
|
1794
|
-
|
|
1795
|
-
|
|
1796
|
-
|
|
1797
|
-
|
|
1798
|
-
|
|
1799
|
-
|
|
1800
|
-
|
|
1801
|
-
};
|
|
1860
|
+
const [resultL, resultR] = yield Promise.all([
|
|
1861
|
+
fetchDatasets(this.bundleModelL, request.scenarioSpecL),
|
|
1862
|
+
fetchDatasets(this.bundleModelR, request.scenarioSpecR)
|
|
1863
|
+
]);
|
|
1864
|
+
return {
|
|
1865
|
+
kind: "dataset",
|
|
1866
|
+
datasetMapL: resultL == null ? void 0 : resultL.datasetMap,
|
|
1867
|
+
datasetMapR: resultR == null ? void 0 : resultR.datasetMap
|
|
1868
|
+
};
|
|
1869
|
+
});
|
|
1802
1870
|
}
|
|
1803
|
-
|
|
1804
|
-
|
|
1805
|
-
|
|
1806
|
-
return
|
|
1807
|
-
|
|
1808
|
-
|
|
1871
|
+
processGraphDataRequest(request) {
|
|
1872
|
+
return __async(this, null, function* () {
|
|
1873
|
+
function fetchGraphData(bundleModel, scenarioSpec) {
|
|
1874
|
+
return __async(this, null, function* () {
|
|
1875
|
+
if (scenarioSpec) {
|
|
1876
|
+
return bundleModel.getGraphDataForScenario(scenarioSpec, request.graphId);
|
|
1877
|
+
} else {
|
|
1878
|
+
return void 0;
|
|
1879
|
+
}
|
|
1880
|
+
});
|
|
1809
1881
|
}
|
|
1810
|
-
|
|
1811
|
-
|
|
1812
|
-
|
|
1813
|
-
|
|
1814
|
-
|
|
1815
|
-
|
|
1816
|
-
|
|
1817
|
-
|
|
1818
|
-
|
|
1819
|
-
};
|
|
1882
|
+
const [graphDataL, graphDataR] = yield Promise.all([
|
|
1883
|
+
fetchGraphData(this.bundleModelL, request.scenarioSpecL),
|
|
1884
|
+
fetchGraphData(this.bundleModelR, request.scenarioSpecR)
|
|
1885
|
+
]);
|
|
1886
|
+
return {
|
|
1887
|
+
kind: "graph-data",
|
|
1888
|
+
graphDataL,
|
|
1889
|
+
graphDataR
|
|
1890
|
+
};
|
|
1891
|
+
});
|
|
1820
1892
|
}
|
|
1821
1893
|
requestDatasetMaps(requestKey, scenarioSpecL, scenarioSpecR, datasetKeys, onResponse) {
|
|
1822
1894
|
const request = {
|
|
@@ -2252,7 +2324,9 @@ function compareScores(a, b) {
|
|
|
2252
2324
|
// src/bundle/model-inputs.ts
|
|
2253
2325
|
var ModelInputs = class {
|
|
2254
2326
|
constructor(modelSpec) {
|
|
2327
|
+
/** All inputs keyed by lookup name (lowercase variable name or alias). */
|
|
2255
2328
|
this.inputsByLookupName = /* @__PURE__ */ new Map();
|
|
2329
|
+
/** All input ID aliases. */
|
|
2256
2330
|
this.inputIdAliases = /* @__PURE__ */ new Set();
|
|
2257
2331
|
for (const inputVar of modelSpec.inputVars.values()) {
|
|
2258
2332
|
const varNameKey = inputVar.varName.toLowerCase();
|
|
@@ -2282,9 +2356,17 @@ var ModelInputs = class {
|
|
|
2282
2356
|
}
|
|
2283
2357
|
}
|
|
2284
2358
|
}
|
|
2359
|
+
/**
|
|
2360
|
+
* Return the set of `id XYZ` aliases for all input variables.
|
|
2361
|
+
*/
|
|
2285
2362
|
getAllInputIdAliases() {
|
|
2286
2363
|
return [...this.inputIdAliases];
|
|
2287
2364
|
}
|
|
2365
|
+
/**
|
|
2366
|
+
* Return the `InputVar` that matches the requested name (either by variable name or alias).
|
|
2367
|
+
*
|
|
2368
|
+
* @param name The variable name or alias to match.
|
|
2369
|
+
*/
|
|
2288
2370
|
getInputVarForName(name) {
|
|
2289
2371
|
return this.inputsByLookupName.get(name.toLowerCase());
|
|
2290
2372
|
}
|
|
@@ -2306,6 +2388,9 @@ var comparison_schema_default = {
|
|
|
2306
2388
|
$ref: "#/$defs/top_level_array_item"
|
|
2307
2389
|
},
|
|
2308
2390
|
$defs: {
|
|
2391
|
+
//
|
|
2392
|
+
// TOP-LEVEL
|
|
2393
|
+
//
|
|
2309
2394
|
top_level_array_item: {
|
|
2310
2395
|
oneOf: [
|
|
2311
2396
|
{ $ref: "#/$defs/scenario_array_item" },
|
|
@@ -2313,6 +2398,9 @@ var comparison_schema_default = {
|
|
|
2313
2398
|
{ $ref: "#/$defs/view_group_array_item" }
|
|
2314
2399
|
]
|
|
2315
2400
|
},
|
|
2401
|
+
//
|
|
2402
|
+
// SCENARIOS
|
|
2403
|
+
//
|
|
2316
2404
|
scenario_array_item: {
|
|
2317
2405
|
type: "object",
|
|
2318
2406
|
additionalProperties: false,
|
|
@@ -2329,7 +2417,9 @@ var comparison_schema_default = {
|
|
|
2329
2417
|
{ $ref: "#/$defs/scenario_with_input_at_value" },
|
|
2330
2418
|
{ $ref: "#/$defs/scenario_with_multiple_input_settings" },
|
|
2331
2419
|
{ $ref: "#/$defs/scenario_with_inputs_in_preset_at_position" },
|
|
2420
|
+
// { $ref: '#/$defs/scenario_with_inputs_in_group_at_position' }
|
|
2332
2421
|
{ $ref: "#/$defs/scenario_preset" }
|
|
2422
|
+
// { $ref: '#/$defs/scenario_expand_for_each_input_in_group' }
|
|
2333
2423
|
]
|
|
2334
2424
|
},
|
|
2335
2425
|
scenario_position: {
|
|
@@ -2469,6 +2559,9 @@ var comparison_schema_default = {
|
|
|
2469
2559
|
},
|
|
2470
2560
|
required: ["preset"]
|
|
2471
2561
|
},
|
|
2562
|
+
//
|
|
2563
|
+
// SCENARIO GROUPS
|
|
2564
|
+
//
|
|
2472
2565
|
scenario_group_array_item: {
|
|
2473
2566
|
type: "object",
|
|
2474
2567
|
additionalProperties: false,
|
|
@@ -2544,6 +2637,9 @@ var comparison_schema_default = {
|
|
|
2544
2637
|
},
|
|
2545
2638
|
required: ["scenario_group_ref"]
|
|
2546
2639
|
},
|
|
2640
|
+
//
|
|
2641
|
+
// VIEWS
|
|
2642
|
+
//
|
|
2547
2643
|
view: {
|
|
2548
2644
|
type: "object",
|
|
2549
2645
|
additionalProperties: false,
|
|
@@ -2577,6 +2673,9 @@ var comparison_schema_default = {
|
|
|
2577
2673
|
},
|
|
2578
2674
|
minItems: 1
|
|
2579
2675
|
},
|
|
2676
|
+
//
|
|
2677
|
+
// VIEW GROUPS
|
|
2678
|
+
//
|
|
2580
2679
|
view_group_array_item: {
|
|
2581
2680
|
type: "object",
|
|
2582
2681
|
additionalProperties: false,
|
|
@@ -2860,15 +2959,18 @@ function scenarioSpecFromInputs(inputs, side) {
|
|
|
2860
2959
|
if (state.inputVar === void 0) {
|
|
2861
2960
|
return void 0;
|
|
2862
2961
|
}
|
|
2863
|
-
|
|
2864
|
-
if (state.position) {
|
|
2865
|
-
settings.push(positionSetting(varId, state.position));
|
|
2866
|
-
} else {
|
|
2867
|
-
settings.push(valueSetting(varId, state.value));
|
|
2868
|
-
}
|
|
2962
|
+
settings.push(inputSettingFromResolvedInputState(state));
|
|
2869
2963
|
}
|
|
2870
2964
|
return inputSettingsSpec(settings);
|
|
2871
2965
|
}
|
|
2966
|
+
function inputSettingFromResolvedInputState(state) {
|
|
2967
|
+
const varId = state.inputVar.varId;
|
|
2968
|
+
if (state.position) {
|
|
2969
|
+
return positionSetting(varId, state.position);
|
|
2970
|
+
} else {
|
|
2971
|
+
return valueSetting(varId, state.value);
|
|
2972
|
+
}
|
|
2973
|
+
}
|
|
2872
2974
|
|
|
2873
2975
|
// src/comparison/config/resolve/comparison-resolver.ts
|
|
2874
2976
|
function resolveComparisonSpecs(modelInputsL, modelInputsR, specs) {
|
|
@@ -2904,7 +3006,7 @@ function resolveComparisonSpecs(modelInputsL, modelInputsR, specs) {
|
|
|
2904
3006
|
if (scenarioItem.kind === "scenario-ref") {
|
|
2905
3007
|
const referencedScenario = resolvedScenarios.getScenarioForId(scenarioItem.scenarioId);
|
|
2906
3008
|
if (referencedScenario) {
|
|
2907
|
-
const resolvedScenario = {
|
|
3009
|
+
const resolvedScenario = __spreadValues({}, referencedScenario);
|
|
2908
3010
|
if (scenarioItem.title) {
|
|
2909
3011
|
resolvedScenario.title = scenarioItem.title;
|
|
2910
3012
|
}
|
|
@@ -2942,7 +3044,9 @@ function resolveComparisonSpecs(modelInputsL, modelInputsR, specs) {
|
|
|
2942
3044
|
}
|
|
2943
3045
|
var ResolvedScenarios = class {
|
|
2944
3046
|
constructor() {
|
|
3047
|
+
/** The array of all resolved scenarios. */
|
|
2945
3048
|
this.resolvedScenarios = [];
|
|
3049
|
+
/** The set of resolved scenarios that include an ID, keyed by ID. */
|
|
2946
3050
|
this.resolvedScenariosById = /* @__PURE__ */ new Map();
|
|
2947
3051
|
}
|
|
2948
3052
|
add(scenarios) {
|
|
@@ -2992,6 +3096,20 @@ function resolveScenariosFromSpec(modelInputsL, modelInputsR, scenarioSpec, genK
|
|
|
2992
3096
|
)
|
|
2993
3097
|
];
|
|
2994
3098
|
}
|
|
3099
|
+
case "scenario-with-distinct-inputs": {
|
|
3100
|
+
return [
|
|
3101
|
+
resolveScenarioForDistinctInputSpecs(
|
|
3102
|
+
modelInputsL,
|
|
3103
|
+
modelInputsR,
|
|
3104
|
+
genKey(),
|
|
3105
|
+
scenarioSpec.id,
|
|
3106
|
+
scenarioSpec.title,
|
|
3107
|
+
scenarioSpec.subtitle,
|
|
3108
|
+
scenarioSpec.inputsL,
|
|
3109
|
+
scenarioSpec.inputsR
|
|
3110
|
+
)
|
|
3111
|
+
];
|
|
3112
|
+
}
|
|
2995
3113
|
default:
|
|
2996
3114
|
assertNever11(scenarioSpec);
|
|
2997
3115
|
}
|
|
@@ -3068,6 +3186,59 @@ function resolveScenarioForInputSpecs(modelInputsL, modelInputsR, key, id, title
|
|
|
3068
3186
|
specR
|
|
3069
3187
|
};
|
|
3070
3188
|
}
|
|
3189
|
+
function resolveScenarioForDistinctInputSpecs(modelInputsL, modelInputsR, key, id, title, subtitle, inputSpecsL, inputSpecsR) {
|
|
3190
|
+
const inputsWithErrors = [];
|
|
3191
|
+
const settingsL = [];
|
|
3192
|
+
const settingsR = [];
|
|
3193
|
+
function resolveInputSpec(side, modelInputs, inputSpec) {
|
|
3194
|
+
let inputState;
|
|
3195
|
+
switch (inputSpec.kind) {
|
|
3196
|
+
case "input-at-position":
|
|
3197
|
+
inputState = resolveInputForNameInModel(modelInputs, inputSpec.inputName, inputSpec.position);
|
|
3198
|
+
break;
|
|
3199
|
+
case "input-at-value":
|
|
3200
|
+
inputState = resolveInputForNameInModel(modelInputs, inputSpec.inputName, inputSpec.value);
|
|
3201
|
+
break;
|
|
3202
|
+
default:
|
|
3203
|
+
assertNever11(inputSpec);
|
|
3204
|
+
}
|
|
3205
|
+
if (inputState.error !== void 0) {
|
|
3206
|
+
inputsWithErrors.push({
|
|
3207
|
+
requestedName: inputSpec.inputName,
|
|
3208
|
+
stateL: side === "left" ? inputState : {},
|
|
3209
|
+
stateR: side === "right" ? inputState : {}
|
|
3210
|
+
});
|
|
3211
|
+
} else {
|
|
3212
|
+
const inputSetting = inputSettingFromResolvedInputState(inputState);
|
|
3213
|
+
if (side === "left") {
|
|
3214
|
+
settingsL.push(inputSetting);
|
|
3215
|
+
} else {
|
|
3216
|
+
settingsR.push(inputSetting);
|
|
3217
|
+
}
|
|
3218
|
+
}
|
|
3219
|
+
}
|
|
3220
|
+
inputSpecsL.forEach((inputSpec) => resolveInputSpec("left", modelInputsL, inputSpec));
|
|
3221
|
+
inputSpecsR.forEach((inputSpec) => resolveInputSpec("right", modelInputsR, inputSpec));
|
|
3222
|
+
let specL;
|
|
3223
|
+
let specR;
|
|
3224
|
+
if (inputsWithErrors.length === 0) {
|
|
3225
|
+
specL = inputSettingsSpec(settingsL);
|
|
3226
|
+
specR = inputSettingsSpec(settingsR);
|
|
3227
|
+
}
|
|
3228
|
+
return {
|
|
3229
|
+
kind: "scenario",
|
|
3230
|
+
key,
|
|
3231
|
+
id,
|
|
3232
|
+
title,
|
|
3233
|
+
subtitle,
|
|
3234
|
+
settings: {
|
|
3235
|
+
kind: "input-settings",
|
|
3236
|
+
inputs: inputsWithErrors
|
|
3237
|
+
},
|
|
3238
|
+
specL,
|
|
3239
|
+
specR
|
|
3240
|
+
};
|
|
3241
|
+
}
|
|
3071
3242
|
function resolveInputForName(modelInputsL, modelInputsR, inputName, at) {
|
|
3072
3243
|
return {
|
|
3073
3244
|
requestedName: inputName,
|
|
@@ -3143,7 +3314,9 @@ function inputValueAtPosition2(inputVar, position) {
|
|
|
3143
3314
|
}
|
|
3144
3315
|
var ResolvedScenarioGroups = class {
|
|
3145
3316
|
constructor() {
|
|
3317
|
+
/** The array of all resolved scenario groups. */
|
|
3146
3318
|
this.resolvedGroups = [];
|
|
3319
|
+
/** The set of resolved scenario groups that include an ID, keyed by ID. */
|
|
3147
3320
|
this.resolvedGroupsById = /* @__PURE__ */ new Map();
|
|
3148
3321
|
}
|
|
3149
3322
|
add(group) {
|
|
@@ -3315,6 +3488,11 @@ function getComparisonDatasets(modelSpecL, modelSpecR, datasetOptions) {
|
|
|
3315
3488
|
return new ComparisonDatasetsImpl(modelSpecL, modelSpecR, datasetOptions);
|
|
3316
3489
|
}
|
|
3317
3490
|
var ComparisonDatasetsImpl = class {
|
|
3491
|
+
/**
|
|
3492
|
+
* @param modelSpecL The model spec for the "left" bundle being compared.
|
|
3493
|
+
* @param modelSpecR The model spec for the "right" bundle being compared.
|
|
3494
|
+
* @param datasetOptions The custom configuration for the datasets to be compared.
|
|
3495
|
+
*/
|
|
3318
3496
|
constructor(modelSpecL, modelSpecR, datasetOptions) {
|
|
3319
3497
|
this.datasetOptions = datasetOptions;
|
|
3320
3498
|
const renamedDatasetKeys = datasetOptions == null ? void 0 : datasetOptions.renamedDatasetKeys;
|
|
@@ -3353,12 +3531,15 @@ var ComparisonDatasetsImpl = class {
|
|
|
3353
3531
|
});
|
|
3354
3532
|
}
|
|
3355
3533
|
}
|
|
3534
|
+
// from ComparisonDatasets interface
|
|
3356
3535
|
getAllDatasets() {
|
|
3357
3536
|
return this.allDatasets.values();
|
|
3358
3537
|
}
|
|
3538
|
+
// from ComparisonDatasets interface
|
|
3359
3539
|
getDataset(datasetKey) {
|
|
3360
3540
|
return this.allDatasets.get(datasetKey);
|
|
3361
3541
|
}
|
|
3542
|
+
// from ComparisonDatasets interface
|
|
3362
3543
|
getDatasetKeysForScenario(scenario) {
|
|
3363
3544
|
var _a;
|
|
3364
3545
|
if (((_a = this.datasetOptions) == null ? void 0 : _a.datasetKeysForScenario) !== void 0) {
|
|
@@ -3384,9 +3565,17 @@ var ComparisonScenariosImpl = class {
|
|
|
3384
3565
|
this.scenarioDefs.set(scenario.key, scenario);
|
|
3385
3566
|
}
|
|
3386
3567
|
}
|
|
3568
|
+
/**
|
|
3569
|
+
* Return all `ComparisonScenario` instances that are available for comparisons.
|
|
3570
|
+
*/
|
|
3387
3571
|
getAllScenarios() {
|
|
3388
3572
|
return this.scenarioDefs.values();
|
|
3389
3573
|
}
|
|
3574
|
+
/**
|
|
3575
|
+
* Return the scenario definition for the given key.
|
|
3576
|
+
*
|
|
3577
|
+
* @param key The key for the scenario.
|
|
3578
|
+
*/
|
|
3390
3579
|
getScenario(key) {
|
|
3391
3580
|
return this.scenarioDefs.get(key);
|
|
3392
3581
|
}
|
|
@@ -3413,11 +3602,11 @@ var PromiseQueue = class {
|
|
|
3413
3602
|
}
|
|
3414
3603
|
add(f) {
|
|
3415
3604
|
return new Promise((resolve, reject) => {
|
|
3416
|
-
const run =
|
|
3605
|
+
const run = () => __async(this, null, function* () {
|
|
3417
3606
|
this.runningCount++;
|
|
3418
3607
|
const promise = f();
|
|
3419
3608
|
try {
|
|
3420
|
-
const result =
|
|
3609
|
+
const result = yield promise;
|
|
3421
3610
|
resolve(result);
|
|
3422
3611
|
} catch (e) {
|
|
3423
3612
|
reject(e);
|
|
@@ -3425,7 +3614,7 @@ var PromiseQueue = class {
|
|
|
3425
3614
|
this.runningCount--;
|
|
3426
3615
|
this.runNext();
|
|
3427
3616
|
}
|
|
3428
|
-
};
|
|
3617
|
+
});
|
|
3429
3618
|
if (this.runningCount < 1) {
|
|
3430
3619
|
run();
|
|
3431
3620
|
} else {
|
|
@@ -3444,81 +3633,84 @@ var PromiseQueue = class {
|
|
|
3444
3633
|
};
|
|
3445
3634
|
|
|
3446
3635
|
// src/config/config.ts
|
|
3447
|
-
|
|
3448
|
-
|
|
3449
|
-
|
|
3450
|
-
|
|
3451
|
-
|
|
3452
|
-
|
|
3453
|
-
|
|
3454
|
-
|
|
3455
|
-
|
|
3456
|
-
|
|
3457
|
-
|
|
3458
|
-
|
|
3459
|
-
|
|
3460
|
-
|
|
3461
|
-
|
|
3462
|
-
|
|
3463
|
-
|
|
3464
|
-
|
|
3465
|
-
|
|
3466
|
-
|
|
3467
|
-
|
|
3468
|
-
|
|
3469
|
-
|
|
3470
|
-
|
|
3471
|
-
|
|
3472
|
-
|
|
3473
|
-
|
|
3474
|
-
|
|
3475
|
-
|
|
3476
|
-
const
|
|
3477
|
-
|
|
3478
|
-
|
|
3479
|
-
|
|
3480
|
-
|
|
3481
|
-
|
|
3482
|
-
|
|
3483
|
-
|
|
3484
|
-
|
|
3485
|
-
|
|
3486
|
-
|
|
3487
|
-
|
|
3488
|
-
|
|
3489
|
-
|
|
3636
|
+
function createConfig(options) {
|
|
3637
|
+
return __async(this, null, function* () {
|
|
3638
|
+
var _a;
|
|
3639
|
+
const origCurrentBundle = yield loadSynchronized(options.current);
|
|
3640
|
+
let currentBundle;
|
|
3641
|
+
let comparisonConfig;
|
|
3642
|
+
if (options.comparison === void 0) {
|
|
3643
|
+
currentBundle = origCurrentBundle;
|
|
3644
|
+
} else {
|
|
3645
|
+
const baselineBundle = yield loadSynchronized(options.comparison.baseline);
|
|
3646
|
+
const renamedDatasetKeys = (_a = options.comparison.datasets) == null ? void 0 : _a.renamedDatasetKeys;
|
|
3647
|
+
const invertedRenamedKeys = /* @__PURE__ */ new Map();
|
|
3648
|
+
renamedDatasetKeys == null ? void 0 : renamedDatasetKeys.forEach((newKey, oldKey) => {
|
|
3649
|
+
invertedRenamedKeys.set(newKey, oldKey);
|
|
3650
|
+
});
|
|
3651
|
+
const rightKeyForLeftKey = (leftKey) => {
|
|
3652
|
+
return (renamedDatasetKeys == null ? void 0 : renamedDatasetKeys.get(leftKey)) || leftKey;
|
|
3653
|
+
};
|
|
3654
|
+
const leftKeyForRightKey = (rightKey) => {
|
|
3655
|
+
return invertedRenamedKeys.get(rightKey) || rightKey;
|
|
3656
|
+
};
|
|
3657
|
+
const origBundleModelR = origCurrentBundle.model;
|
|
3658
|
+
const adjBundleModelR = {
|
|
3659
|
+
modelSpec: origBundleModelR.modelSpec,
|
|
3660
|
+
getDatasetsForScenario: (scenarioSpec, datasetKeys) => __async(this, null, function* () {
|
|
3661
|
+
const rightKeys = datasetKeys.map(rightKeyForLeftKey);
|
|
3662
|
+
const result = yield origBundleModelR.getDatasetsForScenario(scenarioSpec, rightKeys);
|
|
3663
|
+
const mapWithRightKeys = result.datasetMap;
|
|
3664
|
+
const mapWithLeftKeys = /* @__PURE__ */ new Map();
|
|
3665
|
+
for (const [rightKey, dataset] of mapWithRightKeys.entries()) {
|
|
3666
|
+
const leftKey = leftKeyForRightKey(rightKey);
|
|
3667
|
+
mapWithLeftKeys.set(leftKey, dataset);
|
|
3668
|
+
}
|
|
3669
|
+
return {
|
|
3670
|
+
datasetMap: mapWithLeftKeys,
|
|
3671
|
+
modelRunTime: result.modelRunTime
|
|
3672
|
+
};
|
|
3673
|
+
}),
|
|
3674
|
+
getGraphDataForScenario: origBundleModelR.getGraphDataForScenario.bind(origBundleModelR),
|
|
3675
|
+
getGraphLinksForScenario: origBundleModelR.getGraphLinksForScenario.bind(origBundleModelR)
|
|
3676
|
+
};
|
|
3677
|
+
currentBundle = __spreadProps(__spreadValues({}, origCurrentBundle), {
|
|
3678
|
+
model: adjBundleModelR
|
|
3679
|
+
});
|
|
3680
|
+
const modelSpecL = baselineBundle.model.modelSpec;
|
|
3681
|
+
const modelSpecR = currentBundle.model.modelSpec;
|
|
3682
|
+
const modelInputsL = new ModelInputs(modelSpecL);
|
|
3683
|
+
const modelInputsR = new ModelInputs(modelSpecR);
|
|
3684
|
+
const comparisonDefs = resolveComparisonSpecsFromSources(modelInputsL, modelInputsR, options.comparison.specs);
|
|
3685
|
+
comparisonConfig = {
|
|
3686
|
+
bundleL: baselineBundle,
|
|
3687
|
+
bundleR: currentBundle,
|
|
3688
|
+
thresholds: options.comparison.thresholds,
|
|
3689
|
+
scenarios: getComparisonScenarios(comparisonDefs.scenarios),
|
|
3690
|
+
datasets: getComparisonDatasets(modelSpecL, modelSpecR, options.comparison.datasets),
|
|
3691
|
+
viewGroups: comparisonDefs.viewGroups
|
|
3692
|
+
};
|
|
3693
|
+
}
|
|
3694
|
+
const checkConfig = {
|
|
3695
|
+
bundle: currentBundle,
|
|
3696
|
+
tests: options.check.tests
|
|
3490
3697
|
};
|
|
3491
|
-
|
|
3492
|
-
|
|
3493
|
-
|
|
3494
|
-
const modelInputsR = new ModelInputs(modelSpecR);
|
|
3495
|
-
const comparisonDefs = resolveComparisonSpecsFromSources(modelInputsL, modelInputsR, options.comparison.specs);
|
|
3496
|
-
comparisonConfig = {
|
|
3497
|
-
bundleL: baselineBundle,
|
|
3498
|
-
bundleR: currentBundle,
|
|
3499
|
-
thresholds: options.comparison.thresholds,
|
|
3500
|
-
scenarios: getComparisonScenarios(comparisonDefs.scenarios),
|
|
3501
|
-
datasets: getComparisonDatasets(modelSpecL, modelSpecR, options.comparison.datasets),
|
|
3502
|
-
viewGroups: comparisonDefs.viewGroups
|
|
3698
|
+
return {
|
|
3699
|
+
check: checkConfig,
|
|
3700
|
+
comparison: comparisonConfig
|
|
3503
3701
|
};
|
|
3504
|
-
}
|
|
3505
|
-
const checkConfig = {
|
|
3506
|
-
bundle: currentBundle,
|
|
3507
|
-
tests: options.check.tests
|
|
3508
|
-
};
|
|
3509
|
-
return {
|
|
3510
|
-
check: checkConfig,
|
|
3511
|
-
comparison: comparisonConfig
|
|
3512
|
-
};
|
|
3702
|
+
});
|
|
3513
3703
|
}
|
|
3514
|
-
|
|
3515
|
-
|
|
3516
|
-
|
|
3517
|
-
|
|
3518
|
-
|
|
3519
|
-
|
|
3520
|
-
|
|
3521
|
-
|
|
3704
|
+
function loadSynchronized(sourceBundle) {
|
|
3705
|
+
return __async(this, null, function* () {
|
|
3706
|
+
const sourceModel = yield sourceBundle.bundle.initModel();
|
|
3707
|
+
const synchronizedModel = synchronizedBundleModel(sourceModel);
|
|
3708
|
+
return {
|
|
3709
|
+
name: sourceBundle.name,
|
|
3710
|
+
version: sourceBundle.bundle.version,
|
|
3711
|
+
model: synchronizedModel
|
|
3712
|
+
};
|
|
3713
|
+
});
|
|
3522
3714
|
}
|
|
3523
3715
|
|
|
3524
3716
|
// src/perf/perf-runner.ts
|
|
@@ -3568,22 +3760,22 @@ var PerfRunner = class {
|
|
|
3568
3760
|
this.mode = mode;
|
|
3569
3761
|
const scenarioSpec = allInputsAtPositionSpec("at-default");
|
|
3570
3762
|
this.taskQueue = new TaskQueue({
|
|
3571
|
-
process:
|
|
3763
|
+
process: (request) => __async(this, null, function* () {
|
|
3572
3764
|
switch (request.kind) {
|
|
3573
3765
|
case "left": {
|
|
3574
|
-
const result =
|
|
3766
|
+
const result = yield bundleModelL.getDatasetsForScenario(scenarioSpec, []);
|
|
3575
3767
|
return {
|
|
3576
3768
|
runTimeL: result.modelRunTime
|
|
3577
3769
|
};
|
|
3578
3770
|
}
|
|
3579
3771
|
case "right": {
|
|
3580
|
-
const result =
|
|
3772
|
+
const result = yield bundleModelR.getDatasetsForScenario(scenarioSpec, []);
|
|
3581
3773
|
return {
|
|
3582
3774
|
runTimeR: result.modelRunTime
|
|
3583
3775
|
};
|
|
3584
3776
|
}
|
|
3585
3777
|
case "both": {
|
|
3586
|
-
const [resultL, resultR] =
|
|
3778
|
+
const [resultL, resultR] = yield Promise.all([
|
|
3587
3779
|
bundleModelL.getDatasetsForScenario(scenarioSpec, []),
|
|
3588
3780
|
bundleModelR.getDatasetsForScenario(scenarioSpec, [])
|
|
3589
3781
|
]);
|
|
@@ -3595,7 +3787,7 @@ var PerfRunner = class {
|
|
|
3595
3787
|
default:
|
|
3596
3788
|
assertNever12(request.kind);
|
|
3597
3789
|
}
|
|
3598
|
-
}
|
|
3790
|
+
})
|
|
3599
3791
|
});
|
|
3600
3792
|
}
|
|
3601
3793
|
start() {
|
|
@@ -3643,13 +3835,31 @@ var PerfRunner = class {
|
|
|
3643
3835
|
|
|
3644
3836
|
// src/data/data-planner.ts
|
|
3645
3837
|
var DataPlanner = class {
|
|
3838
|
+
/**
|
|
3839
|
+
* @param batchSize The maximum number of impl vars that can be fetched
|
|
3840
|
+
* with a single request; this is usually the same as the number of
|
|
3841
|
+
* normal model outputs.
|
|
3842
|
+
*/
|
|
3646
3843
|
constructor(batchSize) {
|
|
3647
3844
|
this.batchSize = batchSize;
|
|
3845
|
+
/** Tasks that need to access both "left" and "right" models in parallel. */
|
|
3648
3846
|
this.taskSetsLR = /* @__PURE__ */ new Map();
|
|
3847
|
+
/** Tasks that only need to access the "left" model. */
|
|
3649
3848
|
this.taskSetsL = /* @__PURE__ */ new Map();
|
|
3849
|
+
/** Tasks that only need to access the "right" model. */
|
|
3650
3850
|
this.taskSetsR = /* @__PURE__ */ new Map();
|
|
3651
3851
|
this.complete = false;
|
|
3652
3852
|
}
|
|
3853
|
+
/**
|
|
3854
|
+
* Add a request to the plan for the given scenario(s) and data task.
|
|
3855
|
+
*
|
|
3856
|
+
* @param scenarioSpecL The input scenario used to configure the "left" model, or undefined if no data
|
|
3857
|
+
* is needed from the left model.
|
|
3858
|
+
* @param scenarioSpecR The input scenario used to configure the "right" model, or undefined if no data
|
|
3859
|
+
* is needed from the right model.
|
|
3860
|
+
* @param datasetKey The key for the dataset to be fetched from each model for the given scenario.
|
|
3861
|
+
* @param dataAction The action to be performed with the fetched datasets.
|
|
3862
|
+
*/
|
|
3653
3863
|
addRequest(scenarioSpecL, scenarioSpecR, datasetKey, dataAction) {
|
|
3654
3864
|
if (scenarioSpecL === void 0 && scenarioSpecR === void 0) {
|
|
3655
3865
|
console.warn("WARNING: Both scenario specs are undefined for DataPlanner request, skipping");
|
|
@@ -3677,6 +3887,9 @@ var DataPlanner = class {
|
|
|
3677
3887
|
dataAction
|
|
3678
3888
|
});
|
|
3679
3889
|
}
|
|
3890
|
+
/**
|
|
3891
|
+
* Build a plan that minimizes the number of data fetches needed.
|
|
3892
|
+
*/
|
|
3680
3893
|
buildPlan() {
|
|
3681
3894
|
if (this.complete) {
|
|
3682
3895
|
throw new Error("DataPlanner.buildPlan() can only be called once");
|
|
@@ -3727,6 +3940,12 @@ var DataTaskSet = class {
|
|
|
3727
3940
|
this.modelTasks = /* @__PURE__ */ new Map();
|
|
3728
3941
|
this.modelImplTasks = /* @__PURE__ */ new Map();
|
|
3729
3942
|
}
|
|
3943
|
+
/**
|
|
3944
|
+
* Add a task that will be performed when the data is fetched for the scenario(s)
|
|
3945
|
+
* associated with this task set.
|
|
3946
|
+
*
|
|
3947
|
+
* @param dataTask A task that performs an action using the fetched dataset(s).
|
|
3948
|
+
*/
|
|
3730
3949
|
addTask(dataTask) {
|
|
3731
3950
|
let taskMap;
|
|
3732
3951
|
if (dataTask.datasetKey.startsWith("ModelImpl")) {
|
|
@@ -3741,6 +3960,11 @@ var DataTaskSet = class {
|
|
|
3741
3960
|
}
|
|
3742
3961
|
tasks.push(dataTask);
|
|
3743
3962
|
}
|
|
3963
|
+
/**
|
|
3964
|
+
* Add all tasks from the given set into this set.
|
|
3965
|
+
*
|
|
3966
|
+
* @param otherTaskSet The other task set that will be merged into this one.
|
|
3967
|
+
*/
|
|
3744
3968
|
merge(otherTaskSet) {
|
|
3745
3969
|
for (const tasks of otherTaskSet.modelTasks.values()) {
|
|
3746
3970
|
for (const task of tasks) {
|
|
@@ -3753,6 +3977,12 @@ var DataTaskSet = class {
|
|
|
3753
3977
|
}
|
|
3754
3978
|
}
|
|
3755
3979
|
}
|
|
3980
|
+
/**
|
|
3981
|
+
* Create one or more data requests that can be used to fetch data for the configured scenario(s).
|
|
3982
|
+
*
|
|
3983
|
+
* @param batchSize The maximum number of impl vars that can be fetched with a single request.
|
|
3984
|
+
* This is usually the same as the number of normal model outputs.
|
|
3985
|
+
*/
|
|
3756
3986
|
buildRequests(batchSize) {
|
|
3757
3987
|
const dataRequests = [];
|
|
3758
3988
|
if (this.modelTasks.size > 0) {
|
|
@@ -3988,42 +4218,46 @@ var SuiteRunner = class {
|
|
|
3988
4218
|
});
|
|
3989
4219
|
}
|
|
3990
4220
|
}
|
|
3991
|
-
|
|
3992
|
-
|
|
3993
|
-
|
|
3994
|
-
|
|
3995
|
-
|
|
3996
|
-
|
|
3997
|
-
|
|
3998
|
-
|
|
3999
|
-
|
|
4000
|
-
return
|
|
4001
|
-
|
|
4002
|
-
|
|
4003
|
-
|
|
4004
|
-
|
|
4005
|
-
|
|
4006
|
-
|
|
4007
|
-
|
|
4008
|
-
|
|
4009
|
-
|
|
4010
|
-
|
|
4011
|
-
|
|
4012
|
-
|
|
4013
|
-
|
|
4014
|
-
|
|
4015
|
-
|
|
4016
|
-
|
|
4017
|
-
|
|
4018
|
-
|
|
4019
|
-
|
|
4020
|
-
const
|
|
4021
|
-
const
|
|
4022
|
-
dataTask.
|
|
4023
|
-
datasetL
|
|
4024
|
-
datasetR
|
|
4025
|
-
|
|
4026
|
-
|
|
4221
|
+
processRequest(request) {
|
|
4222
|
+
return __async(this, null, function* () {
|
|
4223
|
+
var _a, _b;
|
|
4224
|
+
const datasetKeySet = /* @__PURE__ */ new Set();
|
|
4225
|
+
for (const dataTask of request.dataTasks) {
|
|
4226
|
+
datasetKeySet.add(dataTask.datasetKey);
|
|
4227
|
+
}
|
|
4228
|
+
const datasetKeys = [...datasetKeySet];
|
|
4229
|
+
function getDatasets(bundleModel, scenarioSpec) {
|
|
4230
|
+
return __async(this, null, function* () {
|
|
4231
|
+
if (bundleModel && scenarioSpec) {
|
|
4232
|
+
return bundleModel.getDatasetsForScenario(scenarioSpec, datasetKeys);
|
|
4233
|
+
} else {
|
|
4234
|
+
return void 0;
|
|
4235
|
+
}
|
|
4236
|
+
});
|
|
4237
|
+
}
|
|
4238
|
+
const bundleModelL = (_a = this.config.comparison) == null ? void 0 : _a.bundleL.model;
|
|
4239
|
+
const bundleModelR = ((_b = this.config.comparison) == null ? void 0 : _b.bundleR.model) || this.config.check.bundle.model;
|
|
4240
|
+
const [datasetsResultL, datasetsResultR] = yield Promise.all([
|
|
4241
|
+
getDatasets(bundleModelL, request.scenarioSpecL),
|
|
4242
|
+
getDatasets(bundleModelR, request.scenarioSpecR)
|
|
4243
|
+
]);
|
|
4244
|
+
if (datasetsResultL == null ? void 0 : datasetsResultL.modelRunTime) {
|
|
4245
|
+
this.perfStatsL.addRun(datasetsResultL == null ? void 0 : datasetsResultL.modelRunTime);
|
|
4246
|
+
}
|
|
4247
|
+
if (datasetsResultR == null ? void 0 : datasetsResultR.modelRunTime) {
|
|
4248
|
+
this.perfStatsR.addRun(datasetsResultR == null ? void 0 : datasetsResultR.modelRunTime);
|
|
4249
|
+
}
|
|
4250
|
+
const datasetMapL = datasetsResultL == null ? void 0 : datasetsResultL.datasetMap;
|
|
4251
|
+
const datasetMapR = datasetsResultR == null ? void 0 : datasetsResultR.datasetMap;
|
|
4252
|
+
for (const dataTask of request.dataTasks) {
|
|
4253
|
+
const datasetL = datasetMapL == null ? void 0 : datasetMapL.get(dataTask.datasetKey);
|
|
4254
|
+
const datasetR = datasetMapR == null ? void 0 : datasetMapR.get(dataTask.datasetKey);
|
|
4255
|
+
dataTask.dataAction({
|
|
4256
|
+
datasetL,
|
|
4257
|
+
datasetR
|
|
4258
|
+
});
|
|
4259
|
+
}
|
|
4260
|
+
});
|
|
4027
4261
|
}
|
|
4028
4262
|
};
|
|
4029
4263
|
function runSuite(config, callbacks, options) {
|