Newer
Older
Naab, Daniel James
committed
const { createSelector, defaultMemoize: memoize } = require('reselect');
const { setEquality } = require('../../utils');
const MASK_DESC = {
ice: 'Ice',
fld: 'Flood',
bkw: 'Backwater',
zfl: 'Zeroflow',
dry: 'Dry',
ssn: 'Seasonal',
pr: 'Partial Record',
rat: 'Rating Development',
eqp: 'Equipment Malfunction',
mnt: 'Maintenance',
dis: 'Discontinued',
tst: 'Test',
pmp: 'Pump',
'***': 'Unavailable'
};
/**
* Returns the points for a given timeseries.
* @param {Object} state Redux store
* @param {String} tsDataKey Timeseries key
* @return {Array} Array of points.
*/
const pointsSelector = memoize(tsDataKey => createSelector(
Naab, Daniel James
committed
state => state.tsData,
tsData => tsData[tsDataKey]
));
Naab, Daniel James
committed
* Factory function creates a function that:
* Returns the current show state of a timeseries.
* @param {Object} state Redux store
* @param {String} tsDataKey Timeseries key
* @return {Boolean} Show state of the timeseries
*/
Naab, Daniel James
committed
const isVisibleSelector = memoize(tsDataKey => (state) => {
return state.showSeries[tsDataKey];
});
Naab, Daniel James
committed
* Factory function creates a function that:
Naab, Daniel James
committed
* Returns all points in a timeseries grouped into line segments.
* @param {Object} state Redux store
* @param {String} tsDataKey Timeseries key
* @return {Array} Array of points.
*/
Naab, Daniel James
committed
const lineSegmentsSelector = memoize(tsDataKey => createSelector(
Naab, Daniel James
committed
pointsSelector(tsDataKey),
Naab, Daniel James
committed
(points) => {
// Accumulate data into line groups, splitting on the estimated and
// approval status.
let lines = [];
const masks = new Set(Object.keys(MASK_DESC));
Naab, Daniel James
committed
for (let pt of points) {
// Classes to put on the line with this point.
let lineClasses = {
approved: pt.approved,
estimated: pt.estimated,
dataMask: null
};
Naab, Daniel James
committed
if (pt.value === null) {
let qualifiers = new Set(pt.qualifiers.map(q => q.toLowerCase()));
// current business rules specify that a particular data point
// will only have at most one masking qualifier
let maskIntersection = new Set([...masks].filter(x => qualifiers.has(x)));
lineClasses.dataMask = [...maskIntersection][0]
Naab, Daniel James
committed
}
else if (pt.value !== null) {
// Temporary check to help detect test sites.
if (pt.qualifiers.length > 1) {
/*eslint no-console: "allow"*/
console.error('Point has multiple qualifiers', pt.qualifiers);
}
}
// If this point doesn't have the same classes as the last point,
// create a new line for it.
if (lastClasses.approved !== lineClasses.approved ||
lastClasses.estimated !== lineClasses.estimated ||
lastClasses.dataMask !== lineClasses.dataMask) {
lines.push({
classes: lineClasses,
points: []
});
}
Naab, Daniel James
committed
// Add this point to the current line.
lines[lines.length - 1].points.push(pt);
// Cache the classes for the next loop iteration.
lastClasses = lineClasses;
Naab, Daniel James
committed
}
return lines;
}
Naab, Daniel James
committed
));
module.exports = { pointsSelector, lineSegmentsSelector, isVisibleSelector, MASK_DESC };