@hestia-earth/engine-models 0.81.1 → 0.81.4
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 +144 -0
- package/cjs/version.d.ts +1 -0
- package/{dist → cjs}/version.js +1 -1
- package/config/Cycle.json +8 -0
- package/esm/config.d.ts +31 -0
- package/esm/config.js +39 -0
- package/esm/index.js +5 -0
- package/esm/models.d.ts +41 -0
- package/esm/models.js +2 -0
- package/esm/utils.d.ts +6 -0
- package/esm/utils.js +33 -0
- package/esm/validate-config.d.ts +19 -0
- package/esm/validate-config.js +65 -0
- package/esm/version.d.ts +1 -0
- package/esm/version.js +1 -0
- package/model-links.json +424 -14
- package/package.json +25 -5
- package/LICENSE +0 -21
- package/dist/version.d.ts +0 -1
- package/search-results.json +0 -1
- package/src/config.spec.ts +0 -88
- package/src/config.ts +0 -101
- package/src/models.spec.ts +0 -11
- package/src/models.ts +0 -49
- package/src/utils.spec.ts +0 -118
- package/src/utils.ts +0 -67
- package/src/validate-config.spec.ts +0 -31
- package/src/validate-config.ts +0 -103
- package/src/version.ts +0 -1
- /package/{dist → cjs}/config.d.ts +0 -0
- /package/{dist → cjs}/config.js +0 -0
- /package/{dist → cjs}/index.d.ts +0 -0
- /package/{dist → cjs}/index.js +0 -0
- /package/{dist → cjs}/models.d.ts +0 -0
- /package/{dist → cjs}/models.js +0 -0
- /package/{dist → cjs}/utils.d.ts +0 -0
- /package/{dist → cjs}/utils.js +0 -0
- /package/{dist → cjs}/validate-config.d.ts +0 -0
- /package/{dist → cjs}/validate-config.js +0 -0
- /package/{src/index.ts → esm/index.d.ts} +0 -0
package/README.md
ADDED
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
# HESTIA Engine Models
|
|
2
|
+
|
|
3
|
+
[](https://gitlab.com/hestia-earth/hestia-engine-models/commits/master)
|
|
4
|
+
[](https://gitlab.com/hestia-earth/hestia-engine-models/commits/master)
|
|
5
|
+
|
|
6
|
+
HESTIA's set of models for running calculations or retrieving data using external datasets and internal lookups.
|
|
7
|
+
|
|
8
|
+
## Documentation
|
|
9
|
+
|
|
10
|
+
Documentation for every model can be found in the [HESTIA Guide](https://hestia.earth/guide/models).
|
|
11
|
+
|
|
12
|
+
## Install
|
|
13
|
+
|
|
14
|
+
1. Install python `3.12` minimum
|
|
15
|
+
2. Install the module:
|
|
16
|
+
```bash
|
|
17
|
+
pip install hestia_earth.models
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
### Usage
|
|
21
|
+
|
|
22
|
+
```python
|
|
23
|
+
from hestia_earth.models.pooreNemecek2018 import run
|
|
24
|
+
|
|
25
|
+
cycle_data = {"@type": "Cycle", ...}
|
|
26
|
+
# cycle is a JSONLD node Cycle
|
|
27
|
+
result = run('no3ToGroundwaterSoilFlux', cycle_data)
|
|
28
|
+
print(result)
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
This will display only the result of the `no3ToGroundwaterSoilFlux` model (Emission).
|
|
32
|
+
|
|
33
|
+
Additionally, to reduce the number of queries to the HESTIA API and run the models faster, prefetching can be enabled:
|
|
34
|
+
```python
|
|
35
|
+
from hestia_earth.models.preload_requests import enable_preload
|
|
36
|
+
|
|
37
|
+
enable_preload()
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
#### Using the orchestrator
|
|
41
|
+
|
|
42
|
+
The models come with an "orchestrator", which allows you to run a pre-configured set of models instead of a single one.
|
|
43
|
+
|
|
44
|
+
The configuration for each Node (Cycle, Site or ImpactAssessment) can be found in the [config](./config) folder.
|
|
45
|
+
|
|
46
|
+
Usage:
|
|
47
|
+
```python
|
|
48
|
+
from hestia_earth.orchestrator import run
|
|
49
|
+
from hestia_earth.models.config import load_config
|
|
50
|
+
|
|
51
|
+
cycle = {"@type": "Cycle", ...}
|
|
52
|
+
result = run(cycle, load_config(cycle))
|
|
53
|
+
print(result)
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
This will display the Cycle recalculated with all HESTIA default models running.
|
|
57
|
+
|
|
58
|
+
#### Using Spatial Models
|
|
59
|
+
|
|
60
|
+
We have models that can gap-fill geographical information on a `Site`. If you want to use these models:
|
|
61
|
+
1. Install the library: `pip install hestia-earth-earth-engine`
|
|
62
|
+
2. Follow the [Getting Started instructions](https://gitlab.com/hestia-earth/hestia-earth-engine#getting-started).
|
|
63
|
+
|
|
64
|
+
### Collecting logs in JSON format
|
|
65
|
+
|
|
66
|
+
:info: This is an experimental feature and is not yet integrated in all the HESTIA tools.
|
|
67
|
+
|
|
68
|
+
To collect logs in JSON format:
|
|
69
|
+
1. Set the env variable `LOG_JSON_ENABLED` to `true`
|
|
70
|
+
1. Use the following code to collect contribution logs:
|
|
71
|
+
```python
|
|
72
|
+
from hestia_earth.orchestrator import run
|
|
73
|
+
from hestia_earth.models.config import load_config
|
|
74
|
+
from hestia_earth.models.jlog import reset_collected_logs, get_collected_logs
|
|
75
|
+
|
|
76
|
+
# make sure the logs are reset before each run
|
|
77
|
+
reset_collected_logs()
|
|
78
|
+
|
|
79
|
+
# run the models as usual
|
|
80
|
+
impact = {"@type": "ImpactAssessment", ...}
|
|
81
|
+
result = run(impact, load_config(impact))
|
|
82
|
+
print(result)
|
|
83
|
+
|
|
84
|
+
# write the logs to a JSON file
|
|
85
|
+
logs = get_collected_logs()
|
|
86
|
+
with open("logs.json", "w") as f:
|
|
87
|
+
f.write(to_string(logs, indent=2))
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
When a node is recalculated in separate passes (e.g. stage 1 then stage 2 in different
|
|
91
|
+
processes), seed the later pass with the earlier one's logs so stage-1-only placements
|
|
92
|
+
are not lost:
|
|
93
|
+
```python
|
|
94
|
+
from hestia_earth.models.jlog import load_collected_logs, get_collected_logs
|
|
95
|
+
|
|
96
|
+
# stage 2: load the logs collected during stage 1, then run stage 2 as usual
|
|
97
|
+
load_collected_logs(stage1_logs)
|
|
98
|
+
result = run(impact, load_config(impact), stage=2)
|
|
99
|
+
logs = get_collected_logs() # contains both stage 1 and stage 2
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
### Collecting contribution data
|
|
103
|
+
|
|
104
|
+
:info: This is an experimental feature and is not yet integrated in all the HESTIA tools.
|
|
105
|
+
|
|
106
|
+
To collect contribution data of impacts/endpoints on ImpactAssessment:
|
|
107
|
+
1. Set the env variable `LOG_CONTRIBUTION_ENABLED` to `true`
|
|
108
|
+
1. Use the following code to collect contribution logs:
|
|
109
|
+
```python
|
|
110
|
+
from hestia_earth.orchestrator import run
|
|
111
|
+
from hestia_earth.models.config import load_config
|
|
112
|
+
from hestia_earth.models.log_contribution import reset_contributions, get_contributions
|
|
113
|
+
|
|
114
|
+
# make sure the contributions are reset before each run
|
|
115
|
+
reset_contributions()
|
|
116
|
+
|
|
117
|
+
# run the models as usual
|
|
118
|
+
impact = {"@type": "ImpactAssessment", ...}
|
|
119
|
+
result = run(impact, load_config(impact))
|
|
120
|
+
print(result)
|
|
121
|
+
|
|
122
|
+
# write the contributions to a JSON file
|
|
123
|
+
contributions = get_contributions()
|
|
124
|
+
with open("contributions.json", "w") as f:
|
|
125
|
+
f.write(to_string(contributions, indent=2))
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
The contribution data will store the factors used for each `emissionsResourceUse` that contributes to specific `impacts`, and likewise `impacts` that contribute to `endpoints`. The index in the data represents the index of the blank node in the list of contributing blank nodes.
|
|
129
|
+
|
|
130
|
+
#### Using the ecoinventV3 model
|
|
131
|
+
|
|
132
|
+
:warning: This model has been deprecated and no further support will be provided.
|
|
133
|
+
|
|
134
|
+
ecoinvent is a consistent, transparent, and well validated life cycle inventory database.
|
|
135
|
+
We use ecoinvent data to ascertain the environmental impacts of activities that occur outside of our system boundary, for example data on the environmental impacts of extracting oil and producing diesel, or the impacts of manufacturing plastics.
|
|
136
|
+
|
|
137
|
+
The `ecoinventV3` model requires a valid [license](https://ecoinvent.org/offerings/licences/) to run. We are currently working on a way to enable users of this code with a valid ecoinvent licence to run these models themselves, but for now, these models are only available on the public platform.
|
|
138
|
+
|
|
139
|
+
### Amortising Land Use Change Emissions Using Linear Discounting
|
|
140
|
+
|
|
141
|
+
:info: This is an experimental feature and is not yet integrated in all the HESTIA tools. All carbon stock change models (`ipcc2019.aboveGroundBiomass`, _etc._) and their associated emission models (`ipcc2019.co2ToAirAboveGroundBiomassStockChange`, _etc._) have been updated; however, changes to `hestia.landCover` are required to make linear discounting fully functional (see work item [#1623](https://gitlab.com/hestia-earth/hestia-engine-models/-/work_items/1623) for further information).
|
|
142
|
+
|
|
143
|
+
To amortise the impacts of land use change using linear discounting across IPCC (2019) models:
|
|
144
|
+
1. Set the env variable `USE_LINEAR_DISCOUNTING` to `true`
|
package/cjs/version.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const ENGINE_VERSION = "0.81.4";
|
package/{dist → cjs}/version.js
RENAMED
package/config/Cycle.json
CHANGED
|
@@ -2607,6 +2607,14 @@
|
|
|
2607
2607
|
},
|
|
2608
2608
|
"stage": 2
|
|
2609
2609
|
},
|
|
2610
|
+
{
|
|
2611
|
+
"key": "completeness",
|
|
2612
|
+
"model": "cycle",
|
|
2613
|
+
"value": "completeness",
|
|
2614
|
+
"runStrategy": "always",
|
|
2615
|
+
"mergeStrategy": "node",
|
|
2616
|
+
"stage": 2
|
|
2617
|
+
},
|
|
2610
2618
|
{
|
|
2611
2619
|
"key": "emissions",
|
|
2612
2620
|
"model": "cycle",
|
package/esm/config.d.ts
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { NodeType } from '@hestia-earth/schema';
|
|
2
|
+
export interface IOrchestratorModelConfig {
|
|
3
|
+
key: string;
|
|
4
|
+
model: string;
|
|
5
|
+
value: string;
|
|
6
|
+
runStrategy: 'always' | 'add_key_if_missing' | 'add_blank_node_if_missing';
|
|
7
|
+
runArgs?: Record<string, any>;
|
|
8
|
+
mergeStrategy: 'default' | 'append' | 'list' | 'node';
|
|
9
|
+
mergeArgs?: Record<string, any>;
|
|
10
|
+
}
|
|
11
|
+
export interface IOrchestratorConfig {
|
|
12
|
+
models: (IOrchestratorModelConfig | IOrchestratorModelConfig[])[];
|
|
13
|
+
}
|
|
14
|
+
export type allowedType = NodeType.Cycle | NodeType.Site | NodeType.ImpactAssessment;
|
|
15
|
+
export declare const allowedTypes: allowedType[];
|
|
16
|
+
/**
|
|
17
|
+
* Load orchestrator configuration.
|
|
18
|
+
*
|
|
19
|
+
* @param nodeType NodeType associated with configuration.
|
|
20
|
+
* @returns
|
|
21
|
+
*/
|
|
22
|
+
export declare const loadConfig: (nodeType: allowedType) => IOrchestratorConfig;
|
|
23
|
+
interface ICalculationConfigData {
|
|
24
|
+
key: 'related' | 'nested';
|
|
25
|
+
type: allowedType;
|
|
26
|
+
stage: number;
|
|
27
|
+
}
|
|
28
|
+
export declare const loadRunConfig: (nodeType: allowedType, stage: number) => ICalculationConfigData[];
|
|
29
|
+
export declare const loadTriggerConfig: (nodeType: allowedType, stage: number) => ICalculationConfigData[];
|
|
30
|
+
export declare const getMaxStage: (nodeType: allowedType) => any;
|
|
31
|
+
export {};
|
package/esm/config.js
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { NodeType } from '@hestia-earth/schema';
|
|
2
|
+
import * as runConfig from '../config/run-calculations.json';
|
|
3
|
+
import * as triggerConfig from '../config/trigger-calculations.json';
|
|
4
|
+
import * as Cycle from '../config/Cycle.json';
|
|
5
|
+
import * as ImpactAssessment from '../config/ImpactAssessment.json';
|
|
6
|
+
import * as Site from '../config/Site.json';
|
|
7
|
+
export const allowedTypes = [
|
|
8
|
+
NodeType.Cycle,
|
|
9
|
+
NodeType.Site,
|
|
10
|
+
NodeType.ImpactAssessment
|
|
11
|
+
];
|
|
12
|
+
const validateType = (nodeType) => allowedTypes.includes(nodeType) ||
|
|
13
|
+
(() => {
|
|
14
|
+
throw new Error(`Invalid type ${nodeType}. Allowed types: ${allowedTypes.join(', ')}`);
|
|
15
|
+
})();
|
|
16
|
+
const typeToConfig = {
|
|
17
|
+
[NodeType.Cycle]: Cycle,
|
|
18
|
+
[NodeType.ImpactAssessment]: ImpactAssessment,
|
|
19
|
+
[NodeType.Site]: Site
|
|
20
|
+
};
|
|
21
|
+
/**
|
|
22
|
+
* Load orchestrator configuration.
|
|
23
|
+
*
|
|
24
|
+
* @param nodeType NodeType associated with configuration.
|
|
25
|
+
* @returns
|
|
26
|
+
*/
|
|
27
|
+
export const loadConfig = (nodeType) => validateType(nodeType) && typeToConfig[nodeType];
|
|
28
|
+
const validateStage = (config, nodeType, stage) => `stage-${stage}` in config[nodeType]
|
|
29
|
+
? config[nodeType][`stage-${stage}`]
|
|
30
|
+
: (() => {
|
|
31
|
+
throw new Error(`Invalid stage configuration for ${nodeType}: ${stage}`);
|
|
32
|
+
})();
|
|
33
|
+
export const loadRunConfig = (nodeType, stage) => validateType(nodeType) &&
|
|
34
|
+
validateStage(runConfig, nodeType, stage);
|
|
35
|
+
export const loadTriggerConfig = (nodeType, stage) => validateType(nodeType) &&
|
|
36
|
+
validateStage(triggerConfig, nodeType, stage);
|
|
37
|
+
export const getMaxStage = (nodeType) => validateType(nodeType)
|
|
38
|
+
? Math.max.apply(Math.max, Object.keys(runConfig[nodeType]).map((key) => Number(key.replace('stage-', ''))))
|
|
39
|
+
: null;
|
package/esm/index.js
ADDED
package/esm/models.d.ts
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { EmissionMethodTier } from '@hestia-earth/schema';
|
|
2
|
+
export interface IModel {
|
|
3
|
+
/**
|
|
4
|
+
* Path to the implementation (code) of the model.
|
|
5
|
+
*/
|
|
6
|
+
path: string;
|
|
7
|
+
/**
|
|
8
|
+
* Path to the documentation of the model.
|
|
9
|
+
*/
|
|
10
|
+
docPath: string;
|
|
11
|
+
/**
|
|
12
|
+
* Path to the documentation of the model on the guide.
|
|
13
|
+
*/
|
|
14
|
+
guidePath: string;
|
|
15
|
+
/**
|
|
16
|
+
* The name of the model used as `methodModel`.
|
|
17
|
+
*/
|
|
18
|
+
model: string;
|
|
19
|
+
/**
|
|
20
|
+
* The term the model is associated with.
|
|
21
|
+
*/
|
|
22
|
+
term?: string;
|
|
23
|
+
/**
|
|
24
|
+
* The methodTier of the Emission (if applicable).
|
|
25
|
+
*/
|
|
26
|
+
methodTier?: EmissionMethodTier;
|
|
27
|
+
/**
|
|
28
|
+
* A key in the model if term does not exist.
|
|
29
|
+
*/
|
|
30
|
+
modelKey?: string;
|
|
31
|
+
/**
|
|
32
|
+
* List of other models this model needs to run.
|
|
33
|
+
*/
|
|
34
|
+
dependencies?: string[];
|
|
35
|
+
}
|
|
36
|
+
export type modelLookup = Record<string, Pick<IModel, 'model' | 'term' | 'modelKey'>[]>;
|
|
37
|
+
export interface IModelLinks {
|
|
38
|
+
links: IModel[];
|
|
39
|
+
lookups: Record<string, modelLookup>;
|
|
40
|
+
}
|
|
41
|
+
export declare const models: IModelLinks;
|
package/esm/models.js
ADDED
package/esm/utils.d.ts
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { IOrchestratorModelConfig } from './config';
|
|
2
|
+
import { IModel } from './models';
|
|
3
|
+
export declare const findMatchingModel: (model: Partial<IModel>, config?: {
|
|
4
|
+
useDotValues?: boolean;
|
|
5
|
+
}) => IModel;
|
|
6
|
+
export declare const findMatchingModelFromConfig: (model: Pick<IOrchestratorModelConfig, "model" | "value">) => IModel;
|
package/esm/utils.js
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { models } from './models';
|
|
2
|
+
const matchWithDot = (model, key, value) => typeof value === 'string' && value.split('.').pop() === model[key];
|
|
3
|
+
const matchPath = (model, key, value) => key === 'path' && typeof value === 'string' && model[key].startsWith(value);
|
|
4
|
+
export const findMatchingModel = (model, config = {
|
|
5
|
+
useDotValues: false
|
|
6
|
+
}) => Object.keys(model).length > 0
|
|
7
|
+
? models.links.find((m) => Object.entries(model).every(([key, value]) => value === m[key] ||
|
|
8
|
+
(config.useDotValues && matchWithDot(m, key, value)) ||
|
|
9
|
+
matchPath(m, key, value)))
|
|
10
|
+
: null;
|
|
11
|
+
const modelMatchOrder = ({ model, value }) => [
|
|
12
|
+
{ model, term: value },
|
|
13
|
+
{ model, modelKey: value },
|
|
14
|
+
{
|
|
15
|
+
model,
|
|
16
|
+
modelKey: value.split('.').pop()
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
model,
|
|
20
|
+
term: value.split('.').pop()
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
model,
|
|
24
|
+
path: ['hestia_earth', 'models', model, value].join('/')
|
|
25
|
+
},
|
|
26
|
+
!value || value === 'all' ? { model } : null
|
|
27
|
+
].filter(Boolean);
|
|
28
|
+
export const findMatchingModelFromConfig = (model) => {
|
|
29
|
+
var _a, _b;
|
|
30
|
+
return (_b = (_a = modelMatchOrder(model)
|
|
31
|
+
.map((params) => findMatchingModel(params) ||
|
|
32
|
+
findMatchingModel(params, { useDotValues: true }))) === null || _a === void 0 ? void 0 : _a.filter(Boolean)) === null || _b === void 0 ? void 0 : _b.shift();
|
|
33
|
+
};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { allowedType, IOrchestratorModelConfig } from './config';
|
|
2
|
+
/**
|
|
3
|
+
* Use inter-dependencies to detect models that are in the wrong order.
|
|
4
|
+
*
|
|
5
|
+
* @param nodeType Cycle, Site, or ImpactAssessment
|
|
6
|
+
* @returns List of models that have dependencies that could not be found prior to running.
|
|
7
|
+
*/
|
|
8
|
+
export declare const validateConfigOrder: (nodeType: allowedType) => {
|
|
9
|
+
model: IOrchestratorModelConfig;
|
|
10
|
+
existing: string[];
|
|
11
|
+
missing: string[];
|
|
12
|
+
}[];
|
|
13
|
+
/**
|
|
14
|
+
* Detect multiple models running in parallel when they should not.
|
|
15
|
+
* Note: we use the `mergeArgs` to handle special cases when multiple identical models CAN run in parallel
|
|
16
|
+
*
|
|
17
|
+
* @param nodeType Cycle, Site, or ImpactAssessment
|
|
18
|
+
*/
|
|
19
|
+
export declare const validateConfigDuplicates: (nodeType: allowedType) => IOrchestratorModelConfig[];
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { loadConfig } from './config';
|
|
2
|
+
import { findMatchingModelFromConfig } from './utils';
|
|
3
|
+
// models not included in the links
|
|
4
|
+
const skipModels = ['emissions.deleted', 'transformations'];
|
|
5
|
+
const isHestiaResidueCyclicModel = ({ model, value }) => model === 'hestia' && (value === null || value === void 0 ? void 0 : value.startsWith('residue'));
|
|
6
|
+
const isOrganicCarbonCyclicModel = ({ model, value }) => model === 'hestia' && (value === null || value === void 0 ? void 0 : value.startsWith('organicCarbonPer'));
|
|
7
|
+
const includeModel = (model) => [
|
|
8
|
+
!skipModels.includes(model.model),
|
|
9
|
+
// cyclic dependencies
|
|
10
|
+
!isHestiaResidueCyclicModel(model),
|
|
11
|
+
!isOrganicCarbonCyclicModel(model),
|
|
12
|
+
!model.key.startsWith('cache')
|
|
13
|
+
].every(Boolean);
|
|
14
|
+
// dependencies that cannot be validated
|
|
15
|
+
const skipDependencies = [
|
|
16
|
+
// completeness gap-fills after other models run
|
|
17
|
+
'completeness'
|
|
18
|
+
];
|
|
19
|
+
const matchDependencies = (models) => (model) => {
|
|
20
|
+
var _a, _b, _c;
|
|
21
|
+
const { dependencies } = findMatchingModelFromConfig(model);
|
|
22
|
+
const previousModels = models.slice(0, models.indexOf(model));
|
|
23
|
+
const existing = (_a = dependencies === null || dependencies === void 0 ? void 0 : dependencies.filter((value) => previousModels.some((config) => { var _a; return ((_a = config.value) === null || _a === void 0 ? void 0 : _a.split('.').pop()) === value; }))) !== null && _a !== void 0 ? _a : [];
|
|
24
|
+
return {
|
|
25
|
+
model,
|
|
26
|
+
existing,
|
|
27
|
+
missing: (_c = (_b = dependencies === null || dependencies === void 0 ? void 0 : dependencies
|
|
28
|
+
// skip dependencies that dont exist at all
|
|
29
|
+
.filter((value) => models.some((config) => config.value === value))) === null || _b === void 0 ? void 0 : _b.filter((v) => !existing.includes(v) &&
|
|
30
|
+
!skipDependencies.includes(v) &&
|
|
31
|
+
v !== model.value)) !== null && _c !== void 0 ? _c : []
|
|
32
|
+
};
|
|
33
|
+
};
|
|
34
|
+
/**
|
|
35
|
+
* Use inter-dependencies to detect models that are in the wrong order.
|
|
36
|
+
*
|
|
37
|
+
* @param nodeType Cycle, Site, or ImpactAssessment
|
|
38
|
+
* @returns List of models that have dependencies that could not be found prior to running.
|
|
39
|
+
*/
|
|
40
|
+
export const validateConfigOrder = (nodeType) => {
|
|
41
|
+
const config = loadConfig(nodeType);
|
|
42
|
+
// flatten all models to process one by one, starting with the last one
|
|
43
|
+
const models = config.models.flat();
|
|
44
|
+
const results = models.filter(includeModel).map(matchDependencies(models));
|
|
45
|
+
return results.filter((r) => r.missing.length > 0);
|
|
46
|
+
};
|
|
47
|
+
const findDuplicatedConfigs = (models) => {
|
|
48
|
+
const modelsByValue = models.reduce((prev, curr) => (Object.assign(Object.assign({}, prev), { [curr.value]: [...(prev[curr.value] || []), curr] })), {});
|
|
49
|
+
return Object.values(modelsByValue)
|
|
50
|
+
.map((values) => values.filter((v) => { var _a; return !((_a = v.mergeArgs) === null || _a === void 0 ? void 0 : _a.sameMethodModel); }))
|
|
51
|
+
.filter((values) => values.length > 1);
|
|
52
|
+
};
|
|
53
|
+
/**
|
|
54
|
+
* Detect multiple models running in parallel when they should not.
|
|
55
|
+
* Note: we use the `mergeArgs` to handle special cases when multiple identical models CAN run in parallel
|
|
56
|
+
*
|
|
57
|
+
* @param nodeType Cycle, Site, or ImpactAssessment
|
|
58
|
+
*/
|
|
59
|
+
export const validateConfigDuplicates = (nodeType) => {
|
|
60
|
+
const config = loadConfig(nodeType);
|
|
61
|
+
const duplicates = config.models
|
|
62
|
+
.map((value) => (Array.isArray(value) ? findDuplicatedConfigs(value) : []))
|
|
63
|
+
.flat(2);
|
|
64
|
+
return duplicates;
|
|
65
|
+
};
|
package/esm/version.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const ENGINE_VERSION = "0.81.4";
|
package/esm/version.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const ENGINE_VERSION = '0.81.4';
|