Skip to content

Commit

Permalink
orphan and lost components in SummaryExport
Browse files Browse the repository at this point in the history
  • Loading branch information
Evgeny Metelkin committed Jan 24, 2024
1 parent 0c19a83 commit fa08628
Show file tree
Hide file tree
Showing 4 changed files with 117 additions and 34 deletions.
4 changes: 2 additions & 2 deletions src/summary-export/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,8 @@ class SummaryExport extends AbstractExport {
let image = {
unitDefStorage: this._container.unitDefStorage,
functionDefStorage: this._container.functionDefStorage,
selectedNamespaces: selectedNamespaces,
namespaceStorage: this._container.namespaceStorage
namespaceStorage: this._container.namespaceStorage,
nsImages: selectedNamespaces.map((x) => x[1].getSummaryImage())
};
let content = this.getDotCode(image);

Expand Down
81 changes: 81 additions & 0 deletions src/summary-export/namespace.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
const { Namespace } = require('../namespace');
const { uniqBy, differenceBy } = require('../utils');

Namespace.prototype.getSummaryImage = function() {
let fullComponentIds = [...this.keys()];
let fullConstIds = this.selectByInstanceOf('Const').map((x) => x.id);
let fullRecordIds = this.selectByInstanceOf('Record') // remove processes from here
.filter((x) => !x.instanceOf('Process'))
.map((x) => x.id);
let fullSwitchers = this.selectByInstanceOf('_Switcher');
// for Record assignments
let usedIds1 = this.selectByInstanceOf('Record').reduce((acc, x) => {
// start_
let startSymbols = x.assignments.start_?.dependOn();
startSymbols && (acc = acc.concat(startSymbols));
// ode_
let odeSymbols = x.assignments.ode_?.dependOn();
odeSymbols && (acc = acc.concat(odeSymbols));
// switchers
fullSwitchers.forEach((sw) => {
let contextSymbols_i = x.assignments[sw.id]?.dependOn();
contextSymbols_i && (acc = acc.concat(contextSymbols_i));
});
// context
Object.keys(x.assignments).filter((context) => {
if (context !== 'ode_' && context !== 'start_') {
acc.push(context);
}
});

return acc;
}, []);
// for Switcher trigger
let usedIds2 = fullSwitchers.reduce((acc, x) => {
let triggerSymbols = x.trigger?.dependOn();
triggerSymbols && (acc = acc.concat(triggerSymbols));

return acc;
}, []);
// for Species compartment
let usedIds3 = this.selectByInstanceOf('Species').map((x) => {
return x.compartment;
});
// for Process actors
let usedIds4 = this.selectByInstanceOf('Process').reduce((acc, x) => {
let actorSymbols = x.actors?.map((x) => x.target);
actorSymbols && (acc = acc.concat(actorSymbols));

return acc;
}, []);
// for TimeSwitcher start, period, stop
let usedIds5 = this.selectByInstanceOf('TimeSwitcher').reduce((acc, x) => {
x.start && acc.push(x.start);
x.period && acc.push(x.period);
x.stop && acc.push(x.stop);

return acc;
}, []);
// for Reaction compartment
let usedIds6 = this.selectByInstanceOf('Reaction').filter((x) => !!x.compartment).map((x) => {
return x.compartment;
});

let usedIds = uniqBy([].concat(usedIds1, usedIds2, usedIds3, usedIds4, usedIds5, usedIds6));

let orphanSwitchers = fullSwitchers.filter((sw) => {
let recordWithContext = this.selectByInstanceOf('Record').find((x) => {
return !!x.assignments[sw.id];
});

return !recordWithContext; // true if orphan
}).map((x) => x.id);

return {
ns: this,
orphanConsts: differenceBy(fullConstIds, usedIds),
orphanRecords: differenceBy(fullRecordIds, usedIds),
orphanSwitchers: orphanSwitchers,
lostComponents: differenceBy(usedIds, fullComponentIds)
};
};
53 changes: 21 additions & 32 deletions src/templates/summary.md.njk
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
# Summary for platform

## #defineFunction elements

Total count: {{ functionDefStorage | length }}
## FunctionDef elements ({{ functionDefStorage | length }})

### Core

Expand All @@ -14,9 +12,7 @@ Total count: {{ functionDefStorage | length }}
{{- '-' if not userFunctionDef.length }}
{%- for key, value in userFunctionDef %}{{ value.id }}, {% endfor %}

## #defineUnit elements

Total count: {{ unitDefStorage | length }}
## UnitDef elements ({{ unitDefStorage | length }})

### Core

Expand All @@ -28,47 +24,40 @@ Total count: {{ unitDefStorage | length }}
{{- '-' if not userUnitDef.length }}
{%- for key, value in userUnitDef %}{{ value.id }}, {% endfor %}

## #setNS elements

Totalcount: {{ namespaceStorage | length }}
## Namespace elements ({{ namespaceStorage | length }})

{% for key, value in namespaceStorage %}{{ key }}, {% endfor %}

{% for name, ns in selectedNamespaces %}
## "{{ name }}" namespace ({{ 'abstract' if ns.isAbstract else 'concrete' }})

Total count: {{ ns.size }}
{% for img in nsImages %}{% set ns = img.ns %}
## "{{ ns.spaceName }}" {{ 'abstract' if ns.isAbstract else 'concrete' }} namespace ({{ ns.size }})

## @TimeScale
### By classes

{% for key, value in ns | filter2('1.className', 'TimeScale') %}{{ key }}, {% endfor %}
TimeScale: {% for key, value in ns | filter2('1.className', 'TimeScale') %}{{ key }}, {% endfor %}

## @Const
Const: {% for key, value in ns | filter2('1.className', 'Const') %}{{ key }}, {% endfor %}

{% for key, value in ns | filter2('1.className', 'Const') %}{{ key }}, {% endfor %}
Record: {% for key, value in ns | filter2('1.className', 'Record') %}{{ key }}, {% endfor %}

## @Record
Process: {% for key, value in ns | filter2('1.className', 'Process') %}{{ key }}, {% endfor %}

{% for key, value in ns | filter2('1.className', 'Record') %}{{ key }}, {% endfor %}
Compartment: {% for key, value in ns | filter2('1.className', 'Compartment') %}{{ key }}, {% endfor %}

## @Process
Species: {% for key, value in ns | filter2('1.className', 'Species') %}{{ key }}, {% endfor %}

{% for key, value in ns | filter2('1.className', 'Process') %}{{ key }}, {% endfor %}
Reaction: {% for key, value in ns | filter2('1.className', 'Reaction') %}{{ key }}, {% endfor %}

## @Compartment

{% for key, value in ns | filter2('1.className', 'Compartment') %}{{ key }}, {% endfor %}

## @Species
TimeSwitcher: {% for key, value in ns | filter2('1.className', 'TimeSwitcher') %}{{ key }}, {% endfor %}
{# CSwitcher, DSwitcher, StopSwitcher, Dose, Page, #}
### Orphan (unused) components

{% for key, value in ns | filter2('1.className', 'Species') %}{{ key }}, {% endfor %}
Const: {% for x in img.orphanConsts %}{{ x }}, {% endfor %}{{ '-' if not img.orphanConsts | length }}

## @Reaction
Record: {% for x in img.orphanRecords %}{{ x }}, {% endfor %}{{ '-' if not img.orphanRecords | length }}

{% for key, value in ns | filter2('1.className', 'Reaction') %}{{ key }}, {% endfor %}
Switcher: {% for x in img.orphanSwitchers %}{{ x }}, {% endfor %}{{ '-' if not img.orphanSwitchers | length }}

## @TimeSwitcher
### Lost (absent) components

{% for key, value in ns | filter2('1.className', 'TimeSwitcher') %}{{ key }}, {% endfor %}
{# CSwitcher, DSwitcher, StopSwitcher, Dose, Page, #}
{% for x in img.lostComponents %}{{ x }}, {% endfor %}{{ '-' if not img.lostComponents | length }}
{% endfor %}
13 changes: 13 additions & 0 deletions src/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,18 @@ function intersection(array1, array2) {
return intersect;
}

function differenceBy(array1, array2, selector = (x) => x) {
let result = [];
array1.forEach((x) => {
let selected1 = selector(x);
if (array2.map(selector).indexOf(selected1) === -1) {
result.push(x);
}
});

return result;
}

function flatten(o){
if (typeof o!== 'object')
throw new TypeError('Object required.');
Expand Down Expand Up @@ -94,6 +106,7 @@ module.exports = {
ajv,
uniqBy,
intersection,
differenceBy,
flatten,
cloneDeep
};

0 comments on commit fa08628

Please sign in to comment.