signalk-server
Version:
An implementation of a [Signal K](http://signalk.org) server for boats.
95 lines (94 loc) • 3.81 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.getToPreferredDelta = void 0;
const debug_1 = require("./debug");
const debug = (0, debug_1.createDebug)('signalk-server:sourcepriorities');
const toPrecedences = (sourcePrioritiesMap) => Object.keys(sourcePrioritiesMap).reduce((acc, path) => {
const priorityIndices = sourcePrioritiesMap[path].reduce((acc2, { sourceRef, timeout }, i) => {
acc2.set(sourceRef, {
precedence: i,
timeout
});
return acc2;
}, new Map());
acc.set(path, priorityIndices);
return acc;
}, new Map());
const getToPreferredDelta = (sourcePrioritiesData, unknownSourceTimeout = 10000) => {
if (!sourcePrioritiesData) {
debug('No priorities data');
return (delta, _now, _selfContext) => delta;
}
const precedences = toPrecedences(sourcePrioritiesData);
const contextPathTimestamps = new Map();
const setLatest = (context, path, sourceRef, millis) => {
let pathLatestTimestamps = contextPathTimestamps.get(context);
if (!pathLatestTimestamps) {
pathLatestTimestamps = new Map();
contextPathTimestamps.set(context, pathLatestTimestamps);
}
pathLatestTimestamps.set(path, { sourceRef, timestamp: millis });
};
const getLatest = (context, path) => {
const pathLatestTimestamps = contextPathTimestamps.get(context);
if (!pathLatestTimestamps) {
return {
sourceRef: '',
timestamp: 0
};
}
const latestTimestamp = pathLatestTimestamps.get(path);
if (!latestTimestamp) {
return {
sourceRef: '',
timestamp: 0
};
}
return latestTimestamp;
};
const HIGHESTPRECEDENCE = {
precedence: 0,
timeout: 0
};
const LOWESTPRECEDENCE = {
precedence: Number.POSITIVE_INFINITY,
timeout: unknownSourceTimeout
};
const isPreferredValue = (path, latest, sourceRef, millis) => {
const pathPrecedences = precedences.get(path);
if (!pathPrecedences) {
return true;
}
const latestPrecedence = pathPrecedences.get(latest.sourceRef) || HIGHESTPRECEDENCE;
const incomingPrecedence = pathPrecedences.get(sourceRef) || LOWESTPRECEDENCE;
const latestIsFromHigherPrecedence = latestPrecedence.precedence < incomingPrecedence.precedence;
const isPreferred = !latestIsFromHigherPrecedence ||
millis - latest.timestamp > incomingPrecedence.timeout;
if (debug.enabled) {
debug(`${path}:${sourceRef}:${isPreferred}:${millis - latest.timestamp}`);
}
return isPreferred;
};
return (delta, now, selfContext) => {
if (delta.context === selfContext) {
const millis = now.getTime();
delta.updates &&
delta.updates.forEach((update) => {
if ('values' in update) {
update.values = update.values.reduce((acc, pathValue) => {
const latest = getLatest(delta.context, pathValue.path);
const isPreferred = isPreferredValue(pathValue.path, latest, update.$source, millis);
if (isPreferred) {
setLatest(delta.context, pathValue.path, update.$source, millis);
acc.push(pathValue);
return acc;
}
return acc;
}, []);
}
});
}
return delta;
};
};
exports.getToPreferredDelta = getToPreferredDelta;