Skip to content

Commit

Permalink
Merge pull request #101 from gtorodelvalle/feature/support-integer-ti…
Browse files Browse the repository at this point in the history
…me-random-and-not-random-linear-interpolator

Time linear interpolators  support returning float and integer values
  • Loading branch information
gtorodelvalle authored Sep 28, 2016
2 parents 68e3289 + ed0b107 commit 5fbf7b8
Show file tree
Hide file tree
Showing 17 changed files with 196 additions and 80 deletions.
1 change: 1 addition & 0 deletions CHANGES_NEXT_RELEASE
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
- [FEATURE] time-linear-interpolator and time-random-linear-interpolator support returning float and integer values
73 changes: 43 additions & 30 deletions README.md

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion lib/interpolators/dateIncrementInterpolator.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ module.exports = function(interpolationObjectOrSpec) {

/**
* The date increment interpolator function
* @return {[type]} [description]
* @return {Date} The interpolated new Date
*/
function dateIncrementInterpolator() {
var originDate;
Expand Down
69 changes: 58 additions & 11 deletions lib/interpolators/linearInterpolator.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,6 @@ var ROOT_PATH = require('app-root-path');
var fdsErrors = require(ROOT_PATH + '/lib/errors/fdsErrors');
var linearInterpolator = require('linear-interpolator');

var interpolationArray;

/**
* Validates the entries of an interpolation array
* @param {Array} entry The entry to Validates
Expand Down Expand Up @@ -59,16 +57,65 @@ function sortInterpolationArray(entryA, entryB) {
return entryA[0] - entryB[0];
}

module.exports = function(interpolationArrayOrSpec) {
if (Array.isArray(interpolationArrayOrSpec) && isValidInterpolationArray(interpolationArrayOrSpec)) {
interpolationArray = interpolationArrayOrSpec;
/**
* Checks if the provided interpolation object is a valid once
* @param {Object} interpolationObject The interpolation object
* @return {Boolean} True if the interpolation object is valid, false otherwise
*/
function isValidInterpolationObject(interpolationObject) {
return (interpolationObject.spec && isValidInterpolationArray(interpolationObject.spec) &&
interpolationObject.return && (interpolationObject.return.type === 'float' ||
interpolationObject.return.type === 'integer') &&
((interpolationObject.return.type === 'integer') ?
['ceil', 'floor', 'round'].indexOf(interpolationObject.return.rounding) !== -1 :
true));
}

module.exports = function(interpolationObjectOrSpec) {
var interpolationObject, interpolationArray, originalLinearInterpolator;

/**
* Final linear interpolator
* @param {Number} input A float number between 0 and 24 corresponding to the decimal hours
* @return {Number} Float or integer number according to the specification
*/
function finalLinearInterpolator(input) {
var output = originalLinearInterpolator(input);
if (interpolationObject.return.type === 'float') {
return output;
} else {
// In this case: interpolationObject.return.type === 'integer'
switch (interpolationObject.return.rounding) {
case 'ceil':
return Math.ceil(output);
case 'floor':
return Math.floor(output);
case 'round':
return Math.round(output);
}
}
}

if ((typeof interpolationObjectOrSpec === 'object')) {
if (isValidInterpolationObject(interpolationObjectOrSpec)) {
interpolationObject = interpolationObjectOrSpec;
} else {
throw new fdsErrors.InvalidInterpolationSpec('The provided interpolation object or spec (' +
interpolationObjectOrSpec + ') is not valid (it should be an object including the "spec" and ' +
'"return" properties, where the "return" property is an object including the "type" property and, ' +
'in case "type" is equal to "integer" a "rounding" property)');
}
} else {
interpolationArray = JSON.parse(interpolationArrayOrSpec);
if (!isValidInterpolationArray(interpolationArray)) {
throw new fdsErrors.InvalidInterpolationSpec('The provided interpolation array or specification (' +
interpolationArrayOrSpec + ') is not valid (it should be an array of arrays of 2 number elements)');
interpolationObject = JSON.parse(interpolationObjectOrSpec);
if (!isValidInterpolationObject(interpolationObject)) {
throw new fdsErrors.InvalidInterpolationSpec('The provided interpolation object or spec (' +
interpolationObjectOrSpec + ') is not valid (it should be an object including the "spec" and ' +
'"return" properties, where the "return" property is an object including the "type" property and, ' +
'in case "type" is equal to "integer" a "rounding" property)');
}
}
interpolationArray.sort(sortInterpolationArray);
return linearInterpolator(interpolationArray);
interpolationObject = interpolationObject || interpolationObjectOrSpec;
interpolationArray = interpolationObject.spec.sort(sortInterpolationArray);
originalLinearInterpolator = linearInterpolator(interpolationArray);
return finalLinearInterpolator;
};
81 changes: 68 additions & 13 deletions lib/interpolators/randomLinearInterpolator.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,6 @@ var ROOT_PATH = require('app-root-path');
var fdsErrors = require(ROOT_PATH + '/lib/errors/fdsErrors');
var linearInterpolator = require('linear-interpolator');

var interpolationArray;

/**
* Validates the entries of an interpolation array
* @param {Array} entry The entry to Validates
Expand Down Expand Up @@ -59,23 +57,80 @@ function sortInterpolationArray(entryA, entryB) {
return entryA[0] - entryB[0];
}

module.exports = function(interpolationArrayOrSpec) {
if (typeof interpolationArrayOrSpec === 'string') {
interpolationArrayOrSpec = interpolationArrayOrSpec.replace(/random\(\d+\.?\d*,\d+\.?\d*\)/g, function(match) {
/**
* Checks if the provided interpolation object is a valid once
* @param {Object} interpolationObject The interpolation object
* @return {Boolean} True if the interpolation object is valid, false otherwise
*/
function isValidInterpolationObject(interpolationObject) {
return (interpolationObject.spec && isValidInterpolationArray(interpolationObject.spec) &&
interpolationObject.return && (interpolationObject.return.type === 'float' ||
interpolationObject.return.type === 'integer') &&
((interpolationObject.return.type === 'integer') ?
['ceil', 'floor', 'round'].indexOf(interpolationObject.return.rounding) !== -1 :
true));
}

module.exports = function(interpolationObjectOrSpec) {
var interpolationObject, interpolationArray, originalLinearInterpolator;

/**
* Final linear interpolator
* @param {Number} input A float number between 0 and 24 corresponding to the decimal hours
* @return {Number} Float or integer number according to the specification
*/
function finalLinearInterpolator(input) {
var output = originalLinearInterpolator(input);
if (interpolationObject.return.type === 'float') {
return output;
} else {
// In this case: interpolationObject.return.type === 'integer'
switch (interpolationObject.return.rounding) {
case 'ceil':
return Math.ceil(output);
case 'floor':
return Math.floor(output);
case 'round':
return Math.round(output);
}
}
}

if (typeof interpolationObjectOrSpec === 'string') {
interpolationObjectOrSpec = interpolationObjectOrSpec.replace(/random\(\d+\.?\d*,\d+\.?\d*\)/g, function(match) {
var minMaxArray = match.substring(7, match.length - 1).split(',');
return Math.random() * (parseFloat(minMaxArray[1]) - parseFloat(minMaxArray[0])) + parseFloat(minMaxArray[0]);
});
} else {
interpolationObjectOrSpec.spec = interpolationObjectOrSpec.spec &&
interpolationObjectOrSpec.spec.replace(/random\(\d+\.?\d*,\d+\.?\d*\)/g,
function(match) {
var minMaxArray = match.substring(7, match.length - 1).split(',');
return Math.random() * (parseFloat(minMaxArray[1]) - parseFloat(minMaxArray[0])) + parseFloat(minMaxArray[0]);
}
);
}

if (Array.isArray(interpolationArrayOrSpec) && isValidInterpolationArray(interpolationArrayOrSpec)) {
interpolationArray = interpolationArrayOrSpec;
if ((typeof interpolationObjectOrSpec === 'object')) {
if (isValidInterpolationObject(interpolationObjectOrSpec)) {
interpolationObject = interpolationObjectOrSpec;
} else {
throw new fdsErrors.InvalidInterpolationSpec('The provided interpolation object or spec (' +
interpolationObjectOrSpec + ') is not valid (it should be an object including the "spec" and ' +
'"return" properties, where the "return" property is an object including the "type" property and, ' +
'in case "type" is equal to "integer" a "rounding" property)');
}
} else {
interpolationArray = JSON.parse(interpolationArrayOrSpec);
if (!isValidInterpolationArray(interpolationArray)) {
throw new fdsErrors.InvalidInterpolationSpec('The provided interpolation array or specification (' +
interpolationArrayOrSpec + ') is not valid (it should be an array of arrays of 2 number elements)');
interpolationObject = JSON.parse(interpolationObjectOrSpec);
if (!isValidInterpolationObject(interpolationObject)) {
throw new fdsErrors.InvalidInterpolationSpec('The provided interpolation object or spec (' +
interpolationObjectOrSpec + ') is not valid (it should be an object including the "spec" and ' +
'"return" properties, where the "return" property is an object including the "type" property and, ' +
'in case "type" is equal to "integer" a "rounding" property)');
}
}
interpolationArray.sort(sortInterpolationArray);
return linearInterpolator(interpolationArray);
interpolationObject = interpolationObject || interpolationObjectOrSpec;
interpolationArray = interpolationObject.spec.sort(sortInterpolationArray);
originalLinearInterpolator = linearInterpolator(interpolationArray);
return finalLinearInterpolator;
};
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
"api_key": "the-api-key",
"attributes": [{
"object_id": "attribute1",
"value": "time-linear-interpolator([[0,0],[20,0.25],[21,0.50],[22,0.75],[23,1],[24,1]])"
"value": "time-linear-interpolator({\"spec\": [[0,0],[20,0.25],[21,0.50],[22,0.75],[23,1],[24,1]], \"return\": {\"type\": \"integer\", \"rounding\": \"ceil\"}})"
}]
}]
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
"api_key": "the-api-key",
"attributes": [{
"object_id": "attribute1",
"value": "time-random-linear-interpolator([[0,0],[12,random(0.5,0.75)],[24,0]])"
"value": "time-random-linear-interpolator({\"spec\": [[0,0],[20,random(25,45)],[21,random(50,75)],[22,100],[24,0]], \"return\": {\"type\": \"integer\", \"rounding\": \"ceil\"}})"
}]
}]
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
"api_key": "the-api-key",
"attributes": [{
"object_id": "attribute1",
"value": "time-linear-interpolator([[0,0],[20,0.25],[21,0.50],[22,0.75],[23,1],[24,1]])"
"value": "time-linear-interpolator({\"spec\": [[0,0],[20,0.25],[21,0.50],[22,0.75],[23,1],[24,1]], \"return\": {\"type\": \"integer\", \"rounding\": \"floor\"}})"
}]
}]
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
"api_key": "the-api-key",
"attributes": [{
"object_id": "attribute1",
"value": "time-random-linear-interpolator([[0,0],[12,random(0.5,0.75)],[24,0]])"
"value": "time-random-linear-interpolator({\"spec\": [[0,0],[20,random(25,45)],[21,random(50,75)],[22,100],[24,0]], \"return\": {\"type\": \"integer\", \"rounding\": \"floor\"}})"
}]
}]
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
"api_key": "the-api-key",
"attributes": [{
"object_id": "attribute1",
"value": "time-linear-interpolator([[0,0],[20,0.25],[21,0.50],[22,0.75],[23,1],[24,1]])"
"value": "time-linear-interpolator({\"spec\": [[0,0],[20,0.25],[21,0.50],[22,0.75],[23,1],[24,1]], \"return\": {\"type\": \"integer\", \"rounding\": \"round\"}})"
}]
}]
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
"api_key": "the-api-key",
"attributes": [{
"object_id": "attribute1",
"value": "time-random-linear-interpolator([[0,0],[12,random(0.5,0.75)],[24,0]])"
"value": "time-random-linear-interpolator({\"spec\": [[0,0],[20,random(25,45)],[21,random(50,75)],[22,100],[24,0]], \"return\": {\"type\": \"integer\", \"rounding\": \"round\"}})"
}]
}]
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
"api_key": "the-api-key",
"attributes": [{
"object_id": "attribute1",
"value": "time-linear-interpolator([[0,0],[20,0.25],[21,0.50],[22,0.75],[23,1],[24,1]])"
"value": "time-linear-interpolator({\"spec\": [[0,0],[20,0.25],[21,0.50],[22,0.75],[23,1],[24,1]], \"return\": {\"type\": \"integer\", \"rounding\": \"ceil\"}})"
}]
}]
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
"api_key": "the-api-key",
"attributes": [{
"object_id": "attribute1",
"value": "time-random-linear-interpolator([[0,0],[12,random(0.5,0.75)],[24,0]])"
"value": "time-random-linear-interpolator({\"spec\": [[0,0],[20,random(25,45)],[21,random(50,75)],[22,100],[24,0]], \"return\": {\"type\": \"integer\", \"rounding\": \"ceil\"}})"
}]
}]
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
"active": [{
"name": "active1",
"type": "number",
"value": "time-linear-interpolator([[0,0],[20,0.25],[21,0.50],[22,0.75],[23,1],[24,1]])"
"value": "time-linear-interpolator({\"spec\": [[0,0],[20,0.25],[21,0.50],[22,0.75],[23,1],[24,1]], \"return\": {\"type\": \"float\"}})"
}],
"staticAttributes": [{
"name": "static1",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
"active": [{
"name": "active1",
"type": "number",
"value": "time-random-linear-interpolator([[0,0],[12,random(0.5,0.75)],[24,0]])"
"value": "time-random-linear-interpolator({\"spec\": [[0,0],[20,random(25,45)],[21,random(50,75)],[22,100],[24,0]], \"return\": {\"type\": \"float\"}})"
}],
"staticAttributes": [{
"name": "static1",
Expand Down
18 changes: 9 additions & 9 deletions test/unit/configurations/simulation-configuration.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
"active": [{
"name": "active1",
"type": "number",
"value": "time-linear-interpolator([[0,0],[20,0.25],[21,0.50],[22,0.75],[23,1],[24,1]])"
"value": "time-linear-interpolator({\"spec\": [[0,0],[20,0.25],[21,0.50],[22,0.75],[23,1],[24,1]], \"return\": {\"type\": \"integer\", \"rounding\": \"ceil\"}})"
}],
"staticAttributes": [{
"name": "static1",
Expand All @@ -53,7 +53,7 @@
"active": [{
"name": "active1",
"type": "number",
"value": "time-linear-interpolator([[0,0],[20,0.25],[21,0.50],[22,0.75],[23,1],[24,1]])"
"value": "time-linear-interpolator({\"spec\": [[0,0],[20,0.25],[21,0.50],[22,0.75],[23,1],[24,1]], \"return\": {\"type\": \"integer\", \"rounding\": \"floor\"}})"
}, {
"schedule": "*/1 * * * * *",
"name": "active2",
Expand All @@ -72,18 +72,18 @@
"active": [{
"name": "active1",
"type": "percentage",
"value": "time-random-linear-interpolator([[0,0],[20,random(25,45)],[21,random(50,75)],[22,100],[24,0]])"
"value": "time-random-linear-interpolator({\"spec\": [[0,0],[20,random(25,45)],[21,random(50,75)],[22,100],[24,0]], \"return\": {\"type\": \"integer\", \"rounding\": \"ceil\"}})"
}, {
"schedule": "*/5 * * * * *",
"object_id": "a2",
"name": "active2",
"type": "percentage",
"value": "time-random-linear-interpolator([[0,0],[20,random(25,45)],[21,random(50,75)],[22,100],[24,0]])"
"value": "time-random-linear-interpolator({\"spec\": [[0,0],[20,random(25,45)],[21,random(50,75)],[22,100],[24,0]], \"return\": {\"type\": \"integer\", \"rounding\": \"floor\"}})"
}],
"staticAttributes": [{
"name": "static1",
"type": "percentage",
"value": "time-random-linear-interpolator([[0,0],[20,random(25,45)],[21,random(50,75)],[22,100],[24,0]])"
"value": "time-random-linear-interpolator({\"spec\": [[0,0],[20,random(25,45)],[21,random(50,75)],[22,100],[24,0]], \"return\": {\"type\": \"integer\", \"rounding\": \"round\"}})"
}]
}],
"devices": [{
Expand All @@ -93,7 +93,7 @@
"api_key": "the-api-key",
"attributes": [{
"object_id": "a1",
"value": "time-linear-interpolator([[0,0],[20,0.25],[21,0.50],[22,0.75],[23,1],[24,1]])"
"value": "time-linear-interpolator({\"spec\": [[0,0],[20,0.25],[21,0.50],[22,0.75],[23,1],[24,1]], \"return\": {\"type\": \"integer\", \"rounding\": \"round\"}})"
}]
}, {
"schedule": "*/5 * * * * *",
Expand All @@ -102,7 +102,7 @@
"api_key": "the-api-key",
"attributes": [{
"object_id": "a1",
"value": "time-linear-interpolator([[0,0],[20,0.25],[21,0.50],[22,0.75],[23,1],[24,1]])"
"value": "time-linear-interpolator({\"spec\": [[0,0],[20,0.25],[21,0.50],[22,0.75],[23,1],[24,1]], \"return\": {\"type\": \"integer\", \"rounding\": \"ceil\"}})"
}, {
"schedule": "*/1 * * * * *",
"object_id": "a2",
Expand All @@ -116,11 +116,11 @@
"schedule": "*/1 * * * * *",
"attributes": [{
"object_id": "a1",
"value": "time-random-linear-interpolator([[0,0],[20,random(25,45)],[21,random(50,75)],[22,100],[24,0]])"
"value": "time-random-linear-interpolator({\"spec\": [[0,0],[20,random(25,45)],[21,random(50,75)],[22,100],[24,0]], \"return\": {\"type\": \"integer\", \"rounding\": \"ceil\"}})"
}, {
"schedule": "*/5 * * * * *",
"object_id": "a2",
"value": "time-random-linear-interpolator([[0,0],[20,random(25,45)],[21,random(50,75)],[22,100],[24,0]])"
"value": "time-random-linear-interpolator({\"spec\": [[0,0],[20,random(25,45)],[21,random(50,75)],[22,100],[24,0]], \"return\": {\"type\": \"integer\", \"rounding\": \"ceil\"}})"
}]
}]
}
12 changes: 6 additions & 6 deletions test/unit/fiwareDeviceSimulator_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -5129,19 +5129,19 @@ describe('fiwareDeviceSimulator tests', function() {
if (type === 'entities') {
if (options.ngsiVersion === '1.0') {
should(getAttributeValue(ev.request.body.contextElements, 'EntityName1', 'active1')).
lessThanOrEqual(0.75);
lessThanOrEqual(75);
} else if (options.ngsiVersion === '2.0') {
should(ev.request.body.entities[0].active1.value).lessThanOrEqual(0.75);
should(ev.request.body.entities[0].active1.value).lessThanOrEqual(75);
}
} else {
if (options.protocol === 'UltraLight::HTTP') {
should(ev.request.body.split('|')[1]).lessThanOrEqual(0.75);
should(ev.request.body.split('|')[1]).lessThanOrEqual(75);
} else if (options.protocol === 'UltraLight::MQTT') {
should(ev.request.payload.split('|')[1]).lessThanOrEqual(0.75);
should(ev.request.payload.split('|')[1]).lessThanOrEqual(75);
} else if (options.protocol === 'JSON::HTTP') {
should(ev.request.body.attribute1).lessThanOrEqual(0.75);
should(ev.request.body.attribute1).lessThanOrEqual(75);
} else if (options.protocol === 'JSON::MQTT') {
should(JSON.parse(ev.request.payload).attribute1).lessThanOrEqual(0.75);
should(JSON.parse(ev.request.payload).attribute1).lessThanOrEqual(75);
}
}
});
Expand Down

0 comments on commit 5fbf7b8

Please sign in to comment.