@sis-cc/dotstatsuite-components 9.1.2 → 9.2.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.
Files changed (77) hide show
  1. package/lib/rules/src/preparators/enhanceObservations.js +155 -0
  2. package/lib/rules/src/preparators/formatValue.js +77 -0
  3. package/lib/rules/src/preparators/getDimensions.js +55 -0
  4. package/lib/rules/src/preparators/getDisplay.js +32 -0
  5. package/lib/rules/src/preparators/getObservations.js +27 -0
  6. package/lib/rules/src/table/factories/getCells.js +1 -3
  7. package/lib/rules/src/table/factories/getLayoutData.js +118 -159
  8. package/lib/rules/src/table/factories/getSortedLayoutIndexes.js +118 -0
  9. package/lib/rules/src/table/factories/getTableData.js +12 -10
  10. package/lib/rules/src/table/factories/refineLayoutSize.js +210 -0
  11. package/lib/rules/src/table/preparators/prepareData.js +23 -23
  12. package/lib/rules/src/table/units/getAttachmentSeriesIndexes.js +1 -1
  13. package/lib/rules/src/table/units/getUnitsSeries.js +31 -0
  14. package/lib/rules/src/v8-transformer.js +2 -1
  15. package/package.json +2 -2
  16. package/src/rules/src/preparators/enhanceObservations.js +163 -0
  17. package/src/rules/src/preparators/formatValue.js +73 -0
  18. package/src/rules/src/preparators/getDimensions.js +49 -0
  19. package/src/rules/src/preparators/getDisplay.js +20 -0
  20. package/src/rules/src/preparators/getObservations.js +19 -0
  21. package/src/rules/src/table/factories/getCells.js +3 -7
  22. package/src/rules/src/table/factories/getLayoutData.js +150 -184
  23. package/src/rules/src/table/factories/getSortedLayoutIndexes.js +108 -0
  24. package/src/rules/src/table/factories/getTableData.js +10 -10
  25. package/src/rules/src/table/factories/refineLayoutSize.js +224 -0
  26. package/src/rules/src/table/preparators/prepareData.js +23 -32
  27. package/src/rules/src/table/units/getAttachmentSeriesIndexes.js +2 -1
  28. package/src/rules/src/table/units/getUnitsSeries.js +20 -0
  29. package/src/rules/src/v8-transformer.js +2 -1
  30. package/test/appendUnitsInLayoutDataEntry.test.js +3 -3
  31. package/test/enhanceObservations.test.js +270 -0
  32. package/test/getAttachmentSeriesIndexes.test.js +1 -1
  33. package/test/getCells.test.js +4 -39
  34. package/test/getLayoutData.test.js +193 -298
  35. package/test/getOneValueDimensions.test.js +1 -1
  36. package/test/getSortedLayoutIndexes.test.js +80 -0
  37. package/test/getUnitsArtefacts.test.js +1 -1
  38. package/test/getUnitsSeries.test.js +64 -0
  39. package/test/mocks/table-layout-multi-hierarchies--layout.json +621 -0
  40. package/test/mocks/table-layout-multi-hierarchies--layoutData.json +32410 -0
  41. package/test/mocks/table-layout-multi-hierarchies--layoutIndexes.json +2760 -0
  42. package/test/mocks/table-layout-multi-hierarchies--observations.json +30688 -0
  43. package/test/mocks/table-layout-multi-hierarchies--sizedIndexes.json +2761 -0
  44. package/test/mocks/table-layout-truncation1--layout.json +27469 -0
  45. package/test/mocks/table-layout-truncation1--layoutData.json +20357 -0
  46. package/test/mocks/table-layout-truncation1--layoutIndexes.json +7512 -0
  47. package/test/mocks/table-layout-truncation1--observations.json +70002 -0
  48. package/test/mocks/table-layout-truncation1--sizedIndexes.json +3010 -0
  49. package/test/mocks/table-prep-multi-hierarchies--attributes.json +44 -0
  50. package/test/mocks/table-prep-multi-hierarchies--dimensions.json +688 -0
  51. package/test/mocks/table-prep-multi-hierarchies--enhancedObservations.json +19696 -0
  52. package/test/mocks/table-prep-multi-hierarchies--observations.json +8246 -0
  53. package/test/mocks/table-prep-multi-hierarchies--sdmxJson.json +2985 -0
  54. package/test/mocks/table-prep-truncation1--dimensions.json +35057 -0
  55. package/test/mocks/table-prep-truncation1--enhancedObservations.json +70002 -0
  56. package/test/mocks/table-prep-truncation1--observations.json +27502 -0
  57. package/test/mocks/table-prep-truncation1--sdmxJson.json +55103 -0
  58. package/test/mocks/table-prep-units--observations.json +284286 -0
  59. package/test/mocks/table-prep-units--unitsSeries.json +41042 -0
  60. package/test/parseAttributes.test.js +1 -1
  61. package/test/refineLayoutSize.test.js +415 -0
  62. package/test/table-layout-perf.test.js +74 -0
  63. package/test/table-prep-perf.test.js +65 -0
  64. package/lib/rules/src/table/factories/getSortedLayoutData.js +0 -145
  65. package/lib/rules/src/table/factories/refineLayoutHierarchy.js +0 -61
  66. package/lib/rules/src/table/preparators/parseObservations.js +0 -76
  67. package/lib/rules/src/table/units/getUnitsSeriesOccurences.js +0 -39
  68. package/src/rules/src/table/factories/getSortedLayoutData.js +0 -133
  69. package/src/rules/src/table/factories/refineLayoutHierarchy.js +0 -64
  70. package/src/rules/src/table/preparators/parseObservations.js +0 -81
  71. package/src/rules/src/table/units/getUnitsSeriesOccurences.js +0 -51
  72. package/test/appendUnitsInLayoutData.test.js +0 -248
  73. package/test/getSortedLayoutData.test.js +0 -382
  74. package/test/getUnitsSeriesOccurences.test.js +0 -133
  75. package/test/parseObservations.test.js +0 -116
  76. package/test/refineDimSeriesUnits.test.js +0 -24
  77. package/test/refineLayoutHierarchy.test.js +0 -79
@@ -0,0 +1,224 @@
1
+ import * as R from 'ramda';
2
+
3
+ const getPivotKey = indexes => R.pipe(
4
+ R.props(indexes),
5
+ R.join(':')
6
+ );
7
+
8
+ const getPivots = (layout, shape) => R.pipe(
9
+ R.props(shape),
10
+ R.map(R.pipe(R.pluck('__index'), getPivotKey))
11
+ )(layout);
12
+
13
+ const indexWithPivots = (pivots, observations) => R.pipe(
14
+ R.values,
15
+ R.reduce(
16
+ (acc, obs) => {
17
+ const path = R.map(
18
+ pivot => pivot(obs.orderedDimIndexes),
19
+ pivots
20
+ );
21
+ return R.over(
22
+ R.lensPath(path),
23
+ R.ifElse(R.isNil, R.always([obs]), R.append(obs))
24
+ )(acc);
25
+ },
26
+ {}
27
+ )
28
+ )(observations);
29
+
30
+ export const getCuratedCells = ({ layout, observations, shape }) => {
31
+ const pivots = getPivots(layout, shape);
32
+ return indexWithPivots(pivots, observations);
33
+ };
34
+
35
+ export const refineSections = (sections, extractedKeys, curatedObs) => R.pipe(
36
+ R.map(
37
+ (section) => {
38
+ const sectionKey = R.join(':', R.head(section) || []);
39
+ return R.over(
40
+ R.lensIndex(1),
41
+ R.filter(
42
+ rowData => {
43
+ const rowKey = R.join(':', rowData);
44
+ return R.pipe(
45
+ R.path([sectionKey, rowKey]),
46
+ R.omit(extractedKeys),
47
+ R.isEmpty,
48
+ R.not
49
+ )(curatedObs);
50
+ }
51
+ )
52
+ )(section);
53
+ }
54
+ ),
55
+ R.filter(
56
+ R.pipe(R.nth(1), R.isEmpty, R.not)
57
+ )
58
+ )(sections);
59
+
60
+ export const refineHeader = (header, extractedKeys, curatedObs) => R.filter( // extracted : { [sectionKey]: [...rowKeys] }
61
+ (header) => {
62
+ const headerKey = R.join(':', header);
63
+ return R.pipe(
64
+ R.prop(headerKey),
65
+ (sections) => {
66
+ return R.pickBy(
67
+ (rows, section) => R.pipe(
68
+ R.omit(R.propOr([], section, extractedKeys)),
69
+ R.isEmpty,
70
+ R.not
71
+ )(rows),
72
+ sections
73
+ );
74
+ },
75
+ R.isEmpty,
76
+ R.not
77
+ )(curatedObs);
78
+ }
79
+ )(header);
80
+
81
+ export const truncateSectionRows = (n, sectionsData) => {
82
+ const [rest, extracted] = R.pipe(
83
+ R.last, // last section
84
+ R.nth(1), // rows
85
+ R.splitAt(R.negate(n)) // truncate from the end
86
+ )(sectionsData);
87
+
88
+ const truncatedData = R.isEmpty(rest)
89
+ ? R.dropLast(1, sectionsData) // remove section if no more rows
90
+ : R.adjust(-1, R.adjust(1, R.always(rest)), sectionsData)
91
+
92
+ const sectionKey = R.join(':', R.pipe(R.last, R.head)(sectionsData) || []);
93
+ const rowKeys = R.map(R.join(':'), extracted);
94
+
95
+ const extractedLength = R.length(extracted);
96
+ if (extractedLength < n) {
97
+ const { truncated, extractedKeys } = truncateSectionRows(
98
+ n - extractedLength,
99
+ truncatedData
100
+ );
101
+ return ({ truncated, extractedKeys: { ...extractedKeys, [sectionKey]: rowKeys } });
102
+ }
103
+
104
+ return ({ truncated: truncatedData, extractedKeys: { [sectionKey]: rowKeys } });
105
+ };
106
+
107
+ export const truncateHeader = (n, headerData) => {
108
+ const [truncated, extracted] = R.splitAt(R.negate(n))(headerData);
109
+ return ({ truncated, extractedKeys: R.map(R.join(':'), extracted) });
110
+ };
111
+
112
+ const refineLength = length => length === 0 ? 1 : length;
113
+
114
+ const truncateLayout = (isVertical) => R.ifElse(
115
+ R.always(isVertical),
116
+ truncateSectionRows,
117
+ truncateHeader,
118
+ );
119
+
120
+ const refineLayout = (isVertical) => R.ifElse(
121
+ R.always(isVertical),
122
+ refineHeader,
123
+ refineSections
124
+ )
125
+
126
+ const getShape = isVertical => isVertical ? ['header', 'sections', 'rows'] : ['sections', 'rows', 'header'];
127
+
128
+ const getRefinedLayout = (isVertical, truncated, refined) => R.ifElse(
129
+ R.always(isVertical),
130
+ R.pipe(R.assoc('sections', truncated), R.assoc('header', refined)),
131
+ R.pipe(R.assoc('header', truncated), R.assoc('sections', refined)),
132
+ )({});
133
+
134
+ const segregateLayout = (isVertical) => R.ifElse(
135
+ R.always(isVertical),
136
+ R.props(['sections', 'header']),
137
+ R.props(['header', 'sections'])
138
+ );
139
+
140
+ export const refineLayoutSize = ({ layout, observations, limit }) => layoutIndexes => {
141
+ const { header, sections } = layoutIndexes;
142
+ if (R.isNil(limit) || limit === 0 || R.all(R.isEmpty, [header, sections])) {
143
+ return R.assoc('truncated', false, layoutIndexes);
144
+ }
145
+
146
+ //number of dimensions in header
147
+ const headerDimCount = R.pipe(
148
+ R.head, // first column
149
+ R.when(R.isNil, R.always([])),
150
+ R.length // number of dims
151
+ )(header);
152
+
153
+ //number of columns for values
154
+ const headerValuesCount = R.pipe(
155
+ R.length,
156
+ R.when(R.equals(0), R.always(1))
157
+ )(header);
158
+
159
+ //total of cells in header
160
+ const headerCellsCount = headerDimCount * (headerValuesCount + 1);
161
+
162
+ // number of dimensions in a row
163
+ const rowDimCount = R.pipe(
164
+ R.head, // firstSection
165
+ R.last, // rows,
166
+ R.head, // first row
167
+ R.length
168
+ )(sections);
169
+
170
+ // number of cells in a row
171
+ const rowCellsCount = rowDimCount + headerValuesCount + 1;
172
+
173
+ // number of rows
174
+ const rowsCount = R.pipe(
175
+ R.map(R.last),
176
+ R.unnest,
177
+ R.length,
178
+ R.add(1)
179
+ )(sections);
180
+
181
+ // total of cells in all rows
182
+ const rowsCellsCount = rowCellsCount * rowsCount;
183
+
184
+ // number of sections cells
185
+ const sectionsCellsCount = R.ifElse(
186
+ R.pipe(R.head, R.head, R.length, R.equals(0)),
187
+ R.always(0),
188
+ R.length
189
+ )(sections);
190
+
191
+ const total = rowsCellsCount + sectionsCellsCount + headerCellsCount;
192
+
193
+ const excess = total - limit;
194
+ if (excess <= 0) {
195
+ return R.assoc('truncated', false, layoutIndexes);
196
+ }
197
+
198
+ // total of cells in one column
199
+ const columnCellsCount = headerDimCount + rowsCount;
200
+
201
+ const isVertical = columnCellsCount > rowCellsCount
202
+
203
+ const [toTruncate, toRefine] = segregateLayout(isVertical)(layoutIndexes);
204
+
205
+
206
+ const cutLength = R.pipe(
207
+ R.ifElse(R.identity, R.always(rowCellsCount), R.always(columnCellsCount)),
208
+ R.divide(excess),
209
+ Math.ceil
210
+ )(isVertical);
211
+
212
+ const { truncated, extractedKeys } = truncateLayout(isVertical)(cutLength, toTruncate);
213
+
214
+ const curatedObs = R.pipe(
215
+ getShape,
216
+ (shape) => getCuratedCells({ layout, observations, shape })
217
+ )(isVertical);
218
+
219
+ const refined = refineLayout(isVertical)(toRefine, extractedKeys, curatedObs);
220
+
221
+ const result = getRefinedLayout(isVertical, truncated, refined);
222
+
223
+ return R.assoc('truncated', true, result);
224
+ };
@@ -3,11 +3,9 @@ import { getObservationsType } from '../../properties/getObservationsType';
3
3
  import { parseDimensionsIds } from './parseDimensionsIds';
4
4
  import { getNoDisplayAnnotationsIndexes } from './getNoDisplayAnnotationsIndexes';
5
5
  import { getNoDisplayCodes } from './getNoDisplayCodes';
6
- import { getDisplay } from './getDisplay';
7
6
  import { parseAttributes } from './parseAttributes';
8
7
  import { getDimensionsAttributesRegisters } from './getDimensionsAttributesRegisters';
9
8
  import { parseAttributesValuesFromObservations } from './parseAttributesValuesFromObservations';
10
- import { parseObservations } from './parseObservations';
11
9
  import { getOneValueDimensions } from './getOneValueDimensions';
12
10
  import { getManyValuesDimensions } from './getManyValuesDimensions';
13
11
  import { getAttributeValue } from './getAttributeValue';
@@ -17,8 +15,11 @@ import { getUnitsDefinition } from '../units/getUnitsDefinition';
17
15
  import { getUnitsArtefacts } from '../units/getUnitsArtefacts';
18
16
  import { getHeaderUnits } from '../units/getHeaderUnits';
19
17
  import { getAttachmentSeriesIndexes } from '../units/getAttachmentSeriesIndexes';
20
- import { getUnitsSeriesOccurences } from '../units/getUnitsSeriesOccurences';
21
- import { refineDimSeriesUnits } from '../units/refineDimSeriesUnits';
18
+ import { getUnitsSeries } from '../units/getUnitsSeries';
19
+
20
+ import { getDisplay } from '../../preparators/getDisplay';
21
+ import { getObservations } from '../../preparators/getObservations';
22
+ import { enhanceObservations } from '../../preparators/enhanceObservations';
22
23
 
23
24
  export const prepareData = (sdmxJson, customAttributes, unitsProps={}) => {
24
25
  const {
@@ -30,10 +31,7 @@ export const prepareData = (sdmxJson, customAttributes, unitsProps={}) => {
30
31
  defaultCodes, annotationsDefinitionCodes, data: sdmxJson
31
32
  });
32
33
  const _customAttributes = R.assoc('units', unitsDefinitionCodes, customAttributes);
33
- const dimensions = R.pipe(
34
- R.pathOr([], ['data', 'structure', 'dimensions', 'observation']),
35
- R.addIndex(R.map)((dim, index) => R.assoc('__index', index, dim))
36
- )(sdmxJson);
34
+ const dimensions = R.pathOr([], ['data', 'structure', 'dimensions', 'observation'], sdmxJson);
37
35
 
38
36
  const dimensionsIndexedByIds = R.indexBy(R.prop('id'), dimensions);
39
37
 
@@ -60,40 +58,33 @@ export const prepareData = (sdmxJson, customAttributes, unitsProps={}) => {
60
58
  const attachmentSeriesIndexes = getAttachmentSeriesIndexes({ dimensions: _dimensions, unitsArtefacts });
61
59
  //------------------------------------------------------------------
62
60
 
61
+ const attributes = R.pathOr([], ['data', 'structure', 'attributes', 'observation'], sdmxJson);
62
+
63
63
  const { attributesIndexedByIds, attributesIdsIndexedByTargets } = parseAttributes({
64
64
  attributes: R.concat(
65
- R.pathOr([], ['data', 'structure', 'attributes', 'observation'], sdmxJson),
65
+ attributes,
66
66
  R.pathOr([], ['data', 'structure', 'attributes', 'dataSet'], sdmxJson),
67
67
  ),
68
68
  parsedDimensionsIds,
69
69
  getDisplay: _getDisplay,
70
70
  customAttributes: _customAttributes,
71
71
  });
72
-
72
+
73
73
  const seriesAttributesIds = R.propOr([], 'series', attributesIdsIndexedByTargets);
74
74
  const observationsAttributesIds = R.propOr([], 'observations', attributesIdsIndexedByTargets);
75
- const observations = parseObservations(
76
- R.pathOr({}, ['data', 'dataSets', 0, 'observations'], sdmxJson),
77
- dimensions,
78
- R.pick(R.concat(seriesAttributesIds, observationsAttributesIds), attributesIndexedByIds),
79
- R.pipe(
80
- R.pick(['prefscale', 'decimals']),
81
- R.mapObjIndexed(R.flip(R.prop)(attributesIndexedByIds))
82
- )(attributesIdsIndexedByTargets),
83
- unitsArtefacts,
84
- _getDisplay
85
- );
75
+ const options = {
76
+ attachmentSeriesIndexes,
77
+ customAttributes,
78
+ noDisplayIndexes,
79
+ notDisplayedCodes,
80
+ attributesIds: R.concat(seriesAttributesIds, observationsAttributesIds),
81
+ unitsIds: unitsDefinitionCodes,
82
+ };
83
+
84
+ const _observations = getObservations(sdmxJson);
85
+ const observations = enhanceObservations(dimensions, _observations, attributes, options);
86
86
  //------------------------------------------------------------------
87
- const { rawUnitsSeries, obs } = getUnitsSeriesOccurences({
88
- unitsArtefacts, attachmentSeriesIndexes
89
- })(observations);
90
- const unitsSeries = refineDimSeriesUnits({
91
- unitsArtefacts: R.merge(
92
- R.pathOr({}, ['dimensions', 'series'], unitsArtefacts),
93
- R.pathOr({}, ['attributes', 'series'], unitsArtefacts)
94
- ),
95
- rejectedValueIds
96
- })(rawUnitsSeries);
87
+ const unitsSeries = getUnitsSeries(observations);
97
88
  const unitsAttachmentSeriesIds = R.pipe(
98
89
  R.props(attachmentSeriesIndexes),
99
90
  R.pluck('id')
@@ -153,7 +144,7 @@ export const prepareData = (sdmxJson, customAttributes, unitsProps={}) => {
153
144
  unitsAttachmentSeriesIds,
154
145
  unitsSeries,
155
146
  },
156
- observations: obs,
147
+ observations,
157
148
  observationsType: getObservationsType(sdmxJson.data),
158
149
  dataflowAttributes,
159
150
  dataflowName: R.path(['data', 'structure', 'name'], sdmxJson),
@@ -21,6 +21,7 @@ export const getAttachmentSeriesIndexes = ({
21
21
  R.props(R.concat(unitsDimensionsCodes, targettedDimensionsCodes)),
22
22
  R.filter(dim => !R.isNil(dim)),
23
23
  R.pluck('index'),
24
- R.uniq
24
+ R.uniq,
25
+ R.sortBy(R.identity)
25
26
  )(dimensions);
26
27
  };
@@ -0,0 +1,20 @@
1
+ import * as R from 'ramda';
2
+
3
+ /*
4
+ observations = { [obsKey]: { units: { serieKey: '', [id]: { id, name, value } } } };
5
+ */
6
+
7
+ export const getUnitsSeries = (observations) => {
8
+ let series = {};
9
+ R.map(obs => {
10
+ series = R.over(R.lensProp(obs.units.serieKey), R.ifElse(R.isNil, R.always([obs.units]), R.append(obs.units)))(series);
11
+ }, observations);
12
+
13
+ return R.map(
14
+ serie => R.reduce(
15
+ (acc, units) => R.mergeWith((a, b) => R.path(['value', 'index'], a) === R.path(['value', 'index'], b) ? a : null, acc, units),
16
+ {},
17
+ serie
18
+ )
19
+ )(series);
20
+ };
@@ -112,7 +112,7 @@ export const dataTransformer = (dataNew, options = {}) => {
112
112
  const getDimObservations = R.propOr([], 'observation');
113
113
  const dimObservations = getDimObservations(dimensions);
114
114
 
115
- const getObservations = locale => R.reduce((acc, observation) => {
115
+ const getObservations = locale => R.addIndex(R.reduce)((acc, observation, obsIndex) => {
116
116
  const id = R.prop('id')(observation);
117
117
  const dimAnnotations = getRelationnalAnnotations(R.propOr([],'annotations')(observation))(annotations)
118
118
  const isHidden = R.includes(id)(hiddenIds) ? hiddenFormat : getIsHidden(dimAnnotations);
@@ -147,6 +147,7 @@ export const dataTransformer = (dataNew, options = {}) => {
147
147
  return ({
148
148
  observation: R.append({
149
149
  ...observation,
150
+ __index: obsIndex,
150
151
  name: getLocalisedProp('names', observation),
151
152
  values: sortedValues,
152
153
  role: R.isNil(observation.roles) ? null : R.head(observation.roles),
@@ -29,7 +29,7 @@ describe('appendUnitsInLayoutDataEntry tests', () => {
29
29
  unitsDefinitionCodes: [],
30
30
  unitsIndexes: [],
31
31
  partialUnitSerieIndexes: []
32
- })([])).to.deep.equal([{ dimension: {}, value: { id: 'VAL', unitsLabel: '' } }]);
32
+ })([])).to.deep.equal([{ dimension: {}, value: { id: '', unitsLabel: '' } }]);
33
33
  });
34
34
  it('complete test', () => {
35
35
  expect(appendUnitsInLayoutDataEntry({
@@ -43,7 +43,7 @@ describe('appendUnitsInLayoutDataEntry tests', () => {
43
43
  { dimension: { id: 'D1', __index: 2 }, value: { id: 'V', __index: 0 } },
44
44
  { dimension: { id: 'D2', __index: 0 }, value: { id: 'V', __index: 0 } },
45
45
  { dimension: { id: 'D3', __index: 4 }, value: { id: 'V', __index: 0 } },
46
- { dimension: { id: 'U' }, value: { id: 'VAL', unitsLabel: 'U3V, U1V' } }
46
+ { dimension: { id: 'U' }, value: { id: 'U3V - U1V', unitsLabel: 'U3V, U1V' } }
47
47
  ]);
48
48
  });
49
49
  it('rejectedValues test', () => {
@@ -59,7 +59,7 @@ describe('appendUnitsInLayoutDataEntry tests', () => {
59
59
  { dimension: { id: 'D1', __index: 2 }, value: { id: 'V', __index: 0 } },
60
60
  { dimension: { id: 'D2', __index: 0 }, value: { id: 'V', __index: 0 } },
61
61
  { dimension: { id: 'D3', __index: 4 }, value: { id: 'V', __index: 0 } },
62
- { dimension: { id: 'U' }, value: { id: 'VAL', unitsLabel: 'U1V' } }
62
+ { dimension: { id: 'U' }, value: { id: 'U1V', unitsLabel: 'U1V' } }
63
63
  ]);
64
64
  })
65
65
  });
@@ -0,0 +1,270 @@
1
+ import { expect } from 'chai';
2
+ import { enhanceObservations } from '../src/rules/src/preparators/enhanceObservations';
3
+ import numeral from 'numeral';
4
+
5
+ numeral.register('locale', 'eObs', { delimiters: { thousands: ",", decimal: "." } });
6
+ describe('enhanceObservations tests', () => {
7
+ it('blank test', () => {
8
+ expect(enhanceObservations([], {}, [], {})).to.deep.equal({});
9
+ });
10
+ it('orderedDimIndexes test', () => {
11
+ const dimensions = [
12
+ { id: 'D1', values: [{ id: 'v1', __indexPosition: 2 }, { id: 'v2', __indexPosition: 0 }, { id: 'v3', __indexPosition: 1 }] },
13
+ { id: 'D2', values: [{ id: 'v1', __indexPosition: 1 }, { id: 'v2', __indexPosition: 2 }, { id: 'v3', __indexPosition: 0 }] },
14
+ { id: 'D3', values: [{ id: 'v1', __indexPosition: 0 }] }
15
+ ];
16
+ const observations = {
17
+ a: { dimValuesIndexes: [0, 0, 0], value: '1' },
18
+ b: { dimValuesIndexes: [0, 1, 0], value: '2' },
19
+ c: { dimValuesIndexes: [0, 2, 0], value: '3' },
20
+ d: { dimValuesIndexes: [1, 0, 0], value: '4' },
21
+ e: { dimValuesIndexes: [1, 1, 0], value: '5' },
22
+ f: { dimValuesIndexes: [1, 2, 0], value: '6' },
23
+ g: { dimValuesIndexes: [2, 0, 0], value: '7' },
24
+ h: { dimValuesIndexes: [2, 1, 0], value: '8' },
25
+ i: { dimValuesIndexes: [2, 2, 0], value: '9' }
26
+ };
27
+ expect(enhanceObservations(dimensions, observations, [], {})).to.deep.equal({
28
+ a: { attributes: {}, units: { serieKey: 'x:x:x' }, dimValuesIndexes: [0, 0, 0], orderedDimIndexes: [2, 1, 0], value: '1', formattedValue: '1', indexedDimValIds: { D1: 'v1', D2: 'v1', D3: 'v1' } },
29
+ b: { attributes: {}, units: { serieKey: 'x:x:x' }, dimValuesIndexes: [0, 1, 0], orderedDimIndexes: [2, 2, 0], value: '2', formattedValue: '2', indexedDimValIds: { D1: 'v1', D2: 'v2', D3: 'v1' } },
30
+ c: { attributes: {}, units: { serieKey: 'x:x:x' }, dimValuesIndexes: [0, 2, 0], orderedDimIndexes: [2, 0, 0], value: '3', formattedValue: '3', indexedDimValIds: { D1: 'v1', D2: 'v3', D3: 'v1' } },
31
+ d: { attributes: {}, units: { serieKey: 'x:x:x' }, dimValuesIndexes: [1, 0, 0], orderedDimIndexes: [0, 1, 0], value: '4', formattedValue: '4', indexedDimValIds: { D1: 'v2', D2: 'v1', D3: 'v1' } },
32
+ e: { attributes: {}, units: { serieKey: 'x:x:x' }, dimValuesIndexes: [1, 1, 0], orderedDimIndexes: [0, 2, 0], value: '5', formattedValue: '5', indexedDimValIds: { D1: 'v2', D2: 'v2', D3: 'v1' } },
33
+ f: { attributes: {}, units: { serieKey: 'x:x:x' }, dimValuesIndexes: [1, 2, 0], orderedDimIndexes: [0, 0, 0], value: '6', formattedValue: '6', indexedDimValIds: { D1: 'v2', D2: 'v3', D3: 'v1' } },
34
+ g: { attributes: {}, units: { serieKey: 'x:x:x' }, dimValuesIndexes: [2, 0, 0], orderedDimIndexes: [1, 1, 0], value: '7', formattedValue: '7', indexedDimValIds: { D1: 'v3', D2: 'v1', D3: 'v1' } },
35
+ h: { attributes: {}, units: { serieKey: 'x:x:x' }, dimValuesIndexes: [2, 1, 0], orderedDimIndexes: [1, 2, 0], value: '8', formattedValue: '8', indexedDimValIds: { D1: 'v3', D2: 'v2', D3: 'v1' } },
36
+ i: { attributes: {}, units: { serieKey: 'x:x:x' }, dimValuesIndexes: [2, 2, 0], orderedDimIndexes: [1, 0, 0], value: '9', formattedValue: '9', indexedDimValIds: { D1: 'v3', D2: 'v3', D3: 'v1' } }
37
+ });
38
+ });
39
+
40
+ it('formatValue test', () => {
41
+ numeral.locale('eObs');
42
+ const attributes = [
43
+ { id: 'A1', values: [] },
44
+ { id: 'A2', values: [{ id: '-1' }, { id: '0' }, { id: '1' }, { id: '3' }, { id: 'Z' }] },
45
+ { id: 'A3', values: [{ id: '0' }, { id: '2' }, { id: '3' }, { id: '5' }, { id: 'A' }] }
46
+ ];
47
+
48
+ const customAttributes = { prefscale: 'A2', decimals: 'A3' };
49
+
50
+ const observations = {
51
+ a: { value: 2, attrValuesIndexes: [null, null, null], dimValuesIndexes: [] },
52
+ c: { value: 10, attrValuesIndexes: [null, 4, null], dimValuesIndexes: [] },
53
+ d: { value: 5, attrValuesIndexes: [null, 1, null], dimValuesIndexes: [] },
54
+ e: { value: 8.3, attrValuesIndexes: [null, 0, null], dimValuesIndexes: [] },
55
+ f: { value: 25.62, attrValuesIndexes: [null, 3, null], dimValuesIndexes: [] },
56
+ g: { value: 3.7, attrValuesIndexes: [null, null, 4], dimValuesIndexes: [] },
57
+ h: { value: 21.1234567, attrValuesIndexes: [null, null, 2], dimValuesIndexes: [] },
58
+ i: { value: 20.1, attrValuesIndexes: [null, null, 3], dimValuesIndexes: [] },
59
+ j: { value: 19.9, attrValuesIndexes: [null, null, 0], dimValuesIndexes: [] },
60
+ k: { value: 16.35, attrValuesIndexes: [null, 2, 1], dimValuesIndexes: [] },
61
+ l: { value: 155062.56, attrValuesIndexes: [null, null, 2], dimValuesIndexes: [] },
62
+ m: { value: 155062.56, attrValuesIndexes: [null, null, 0], dimValuesIndexes: [] },
63
+ n: { value: null, attrValuesIndexes: [null, null, 1], dimValuesIndexes: [] },
64
+ };
65
+
66
+ expect(enhanceObservations([], observations, attributes, { customAttributes })).to.deep.equal({
67
+ a: { attributes: {}, units: { serieKey: '' }, value: 2, formattedValue: '2', attrValuesIndexes: [null, null, null], dimValuesIndexes: [], orderedDimIndexes: [], indexedDimValIds: {} },
68
+ c: { attributes: {}, units: { serieKey: '' }, value: 10, formattedValue: '10', attrValuesIndexes: [null, 4, null], dimValuesIndexes: [], orderedDimIndexes: [], indexedDimValIds: {} },
69
+ d: { attributes: {}, units: { serieKey: '' }, value: 5, formattedValue: '5', attrValuesIndexes: [null, 1, null], dimValuesIndexes: [], orderedDimIndexes: [], indexedDimValIds: {} },
70
+ e: { attributes: {}, units: { serieKey: '' }, value: 8.3, formattedValue: '83', attrValuesIndexes: [null, 0, null], dimValuesIndexes: [], orderedDimIndexes: [], indexedDimValIds: {} },
71
+ f: { attributes: {}, units: { serieKey: '' }, value: 25.62, formattedValue: '0.02562', attrValuesIndexes: [null, 3, null], dimValuesIndexes: [], orderedDimIndexes: [], indexedDimValIds: {} },
72
+ g: { attributes: {}, units: { serieKey: '' }, value: 3.7, formattedValue: '3.7', attrValuesIndexes: [null, null, 4], dimValuesIndexes: [], orderedDimIndexes: [], indexedDimValIds: {} },
73
+ h: { attributes: {}, units: { serieKey: '' }, value: 21.1234567, formattedValue: '21.123', attrValuesIndexes: [null, null, 2], dimValuesIndexes: [], orderedDimIndexes: [], indexedDimValIds: {} },
74
+ i: { attributes: {}, units: { serieKey: '' }, value: 20.1, formattedValue: '20.10000', attrValuesIndexes: [null, null, 3], dimValuesIndexes: [], orderedDimIndexes: [], indexedDimValIds: {} },
75
+ j: { attributes: {}, units: { serieKey: '' }, value: 19.9, formattedValue: '20', attrValuesIndexes: [null, null, 0], dimValuesIndexes: [], orderedDimIndexes: [], indexedDimValIds: {} },
76
+ k: { attributes: {}, units: { serieKey: '' }, value: 16.35, formattedValue: '1.64', attrValuesIndexes: [null, 2, 1], dimValuesIndexes: [], orderedDimIndexes: [], indexedDimValIds: {} },
77
+ l: { attributes: {}, units: { serieKey: '' }, value: 155062.56, formattedValue: '155,062.560', attrValuesIndexes: [null, null, 2], dimValuesIndexes: [], orderedDimIndexes: [], indexedDimValIds: {} },
78
+ m: { attributes: {}, units: { serieKey: '' }, value: 155062.56, formattedValue: '155,063', attrValuesIndexes: [null, null, 0], dimValuesIndexes: [], orderedDimIndexes: [], indexedDimValIds: {} },
79
+ n: { attributes: {}, units: { serieKey: '' }, value: null, formattedValue: '..', attrValuesIndexes: [null, null, 1], dimValuesIndexes: [], orderedDimIndexes: [], indexedDimValIds: {} },
80
+ });
81
+ });
82
+
83
+ it('attributes and units test', () => {
84
+ const attributes = [
85
+ {
86
+ id: 'a0',
87
+ values: [{ id: 'v0' }, { id: 'v1' }, { id: 'v2' }],
88
+ },
89
+ {
90
+ id: 'a1',
91
+ values: [{ id: 'v0' }],
92
+ },
93
+ {
94
+ id: 'a2',
95
+ values: [{ id: 'v0' }, { id: 'v1' }],
96
+ },
97
+ {
98
+ id: 'a3',
99
+ values: [{ id: 'v0' }, { id: 'v1' }],
100
+ },
101
+ {
102
+ id: 'a4',
103
+ values: [{ id: 'v0' }, { id: 'v1' }],
104
+ },
105
+ ];
106
+
107
+ const dimensions = [
108
+ {
109
+ id: 'd0',
110
+ __index: 0,
111
+ values: [
112
+ { id: 'v0', __index: 0, __indexPosition: 0 },
113
+ { id: 'v1', __index: 1, __indexPosition: 1 },
114
+ { id: 'v2', __index: 2, __indexPosition: 2 },
115
+ { id: 'v3', __index: 3, __indexPosition: 3 }
116
+ ]
117
+ },
118
+ {
119
+ id: 'd1',
120
+ __index: 1,
121
+ values: [
122
+ { id: 'v0', __index: 0, __indexPosition: 0 }
123
+ ]
124
+ },
125
+ {
126
+ id: 'd2',
127
+ __index: 2,
128
+ values: [
129
+ { id: 'v0', __index: 0, __indexPosition: 0 }
130
+ ]
131
+ },
132
+ {
133
+ id: 'd3',
134
+ __index: 3,
135
+ values: [
136
+ { id: 'v0', __index: 0, __indexPosition: 0 },
137
+ { id: 'v1', __index: 1, __indexPosition: 1 }
138
+ ]
139
+ },
140
+ {
141
+ id: 'd4',
142
+ __index: 4,
143
+ values: [
144
+ { id: 'v0', __index: 0, __indexPosition: 0 }
145
+ ]
146
+ }
147
+ ];
148
+
149
+
150
+ const observations = {
151
+ a: {
152
+ attrValuesIndexes: [0, 0, 0, 0, 0],
153
+ dimValuesIndexes: [0, 0, 0, 0, 0],
154
+ value: 22,
155
+ },
156
+ b: {
157
+ attrValuesIndexes: [1, 0, 1, 1, 0],
158
+ dimValuesIndexes: [0, 0, 0, 1, 0],
159
+ value: 17,
160
+ },
161
+ c: {
162
+ attrValuesIndexes: [2, 0, null, null, 0],
163
+ dimValuesIndexes: [1, 0, 0, 0, 0],
164
+ value: 55,
165
+ },
166
+ d: {
167
+ attrValuesIndexes: [2, 0, null, null, 1],
168
+ dimValuesIndexes: [2, 0, 0, 0, 0],
169
+ value: 35,
170
+ },
171
+ e: {
172
+ attrValuesIndexes: [2, null, null, null, null],
173
+ dimValuesIndexes: [3, 0, 0, 0, 0],
174
+ value: 35,
175
+ }
176
+ };
177
+
178
+ const options = {
179
+ noDisplayIndexes: [],
180
+ notDisplayedCodes: {
181
+ d0: { values: { v3: 'v3' } },
182
+ a4: { values: { v1: 'v1' } }
183
+ },
184
+ attributesIds: ['a0', 'a1'],
185
+ unitsIds: ['d0', 'a4'],
186
+ };
187
+
188
+ expect(enhanceObservations(dimensions, observations, attributes, options)).to.deep.equal({
189
+ a: {
190
+ attrValuesIndexes: [0, 0, 0, 0, 0],
191
+ dimValuesIndexes: [0, 0, 0, 0, 0],
192
+ orderedDimIndexes: [0, 0, 0, 0, 0],
193
+ value: 22,
194
+ formattedValue: '22',
195
+ units: {
196
+ d0: { id: 'd0', __index: 0, value: { id: 'v0', index: 0, __index: 0, __indexPosition: 0 } },
197
+ a4: { id: 'a4', __index: 4, value: { id: 'v0', index: 0 } },
198
+ serieKey: 'x:x:x:x:x'
199
+ },
200
+ attributes: {
201
+ a0: { id: 'a0', value: { id: 'v0' } },
202
+ a1: { id: 'a1', value: { id: 'v0' } }
203
+ },
204
+ indexedDimValIds: { d0: 'v0', d1: 'v0', d2: 'v0', d3: 'v0', d4: 'v0' }
205
+ },
206
+ b: {
207
+ attrValuesIndexes: [1, 0, 1, 1, 0],
208
+ dimValuesIndexes: [0, 0, 0, 1, 0],
209
+ orderedDimIndexes: [0, 0, 0, 1, 0],
210
+ value: 17,
211
+ formattedValue: '17',
212
+ units: {
213
+ d0: { id: 'd0', __index: 0, value: { id: 'v0', index: 0, __index: 0, __indexPosition: 0 } },
214
+ a4: { id: 'a4', __index: 4, value: { id: 'v0', index: 0 } },
215
+ serieKey: 'x:x:x:x:x'
216
+ },
217
+ attributes: {
218
+ a0: { id: 'a0', value: { id: 'v1' } },
219
+ a1: { id: 'a1', value: { id: 'v0' } }
220
+ },
221
+ indexedDimValIds: { d0: 'v0', d1: 'v0', d2: 'v0', d3: 'v1', d4: 'v0' }
222
+ },
223
+ c: {
224
+ attrValuesIndexes: [2, 0, null, null, 0],
225
+ dimValuesIndexes: [1, 0, 0, 0, 0],
226
+ orderedDimIndexes: [1, 0, 0, 0, 0],
227
+ value: 55,
228
+ formattedValue: '55',
229
+ units: {
230
+ d0: { id: 'd0', __index: 0, value: { id: 'v1', index: 1, __index: 1, __indexPosition: 1 } },
231
+ a4: { id: 'a4', __index: 4, value: { id: 'v0', index: 0 } },
232
+ serieKey: 'x:x:x:x:x'
233
+ },
234
+ attributes: {
235
+ a0: { id: 'a0', value: { id: 'v2' } },
236
+ a1: { id: 'a1', value: { id: 'v0' } }
237
+ },
238
+ indexedDimValIds: { d0: 'v1', d1: 'v0', d2: 'v0', d3: 'v0', d4: 'v0' }
239
+ },
240
+ d: {
241
+ attrValuesIndexes: [2, 0, null, null, 1],
242
+ dimValuesIndexes: [2, 0, 0, 0, 0],
243
+ orderedDimIndexes: [2, 0, 0, 0, 0],
244
+ value: 35,
245
+ formattedValue: '35',
246
+ units: {
247
+ d0: { id: 'd0', __index: 0, value: { id: 'v2', index: 2, __index: 2, __indexPosition: 2 } },
248
+ serieKey: 'x:x:x:x:x'
249
+ },
250
+ attributes: {
251
+ a0: { id: 'a0', value: { id: 'v2' } },
252
+ a1: { id: 'a1', value: { id: 'v0' } }
253
+ },
254
+ indexedDimValIds: { d0: 'v2', d1: 'v0', d2: 'v0', d3: 'v0', d4: 'v0' }
255
+ },
256
+ e: {
257
+ attrValuesIndexes: [2, null, null, null, null],
258
+ dimValuesIndexes: [3, 0, 0, 0, 0],
259
+ orderedDimIndexes: [3, 0, 0, 0, 0],
260
+ value: 35,
261
+ formattedValue: '35',
262
+ units: { serieKey: 'x:x:x:x:x' },
263
+ attributes: {
264
+ a0: { id: 'a0', value: { id: 'v2' } }
265
+ },
266
+ indexedDimValIds: { d0: 'v3', d1: 'v0', d2: 'v0', d3: 'v0', d4: 'v0' }
267
+ }
268
+ });
269
+ });
270
+ });
@@ -30,6 +30,6 @@ describe('getAttachmentSeriesIndexes test', () => {
30
30
  });
31
31
  it('basic test', () => {
32
32
  expect(getAttachmentSeriesIndexes({ dimensions, unitsArtefacts }))
33
- .to.deep.equal([0, 3, 2]);
33
+ .to.deep.equal([0, 2, 3]);
34
34
  });
35
35
  });