From 9eb031e912bad745b5d52d9802f0d53eff61a592 Mon Sep 17 00:00:00 2001 From: juggledad Date: Sun, 13 Dec 2020 07:58:13 -0500 Subject: [PATCH] Update node-red-random to add option to dynamically pass in 'To' and 'From' (#707) * Add option to dynamically pass in 'From' and 'To' - fixed bug when 'From' was greater than 'To' by flipping the two * Set initial values of 'From' and 'To to "" to allow dynamic overriding them --- function/random/README.md | 2 + function/random/locales/en-US/random.html | 9 +- function/random/random.html | 4 +- function/random/random.js | 74 +++++- test/function/random/random_spec.js | 273 ++++++++++++++++++---- 5 files changed, 303 insertions(+), 59 deletions(-) diff --git a/function/random/README.md b/function/random/README.md index 0713d08a..91710a84 100644 --- a/function/random/README.md +++ b/function/random/README.md @@ -19,4 +19,6 @@ If set to return an integer it can include both the low and high values. If set to return a floating point value it will be from the low value, up to, but **not** including the high value. `min <= n < max` - so selecting 1 to 6 will return values 1 <= n < 6 . +You can dynamically pass in the 'From' and 'To' values to the node using msg.to and/or msg.from. **NOTE:** hard coded values in the node **always take precedence**. + **Note:** This returns numbers - objects of type **number**. diff --git a/function/random/locales/en-US/random.html b/function/random/locales/en-US/random.html index dbf239b4..0bc93b13 100644 --- a/function/random/locales/en-US/random.html +++ b/function/random/locales/en-US/random.html @@ -1,7 +1,14 @@ diff --git a/function/random/random.html b/function/random/random.html index bf1ae44a..7443615f 100644 --- a/function/random/random.html +++ b/function/random/random.html @@ -31,8 +31,8 @@ color:"#E2D96E", defaults: { name: {value:""}, - low: {value:"1"}, - high: {value:"10"}, + low: {value: 1,validate:function(v) { return !isNaN(v) || v.length === 0;} }, + high: {value: 10,validate:function(v) { return !isNaN(v) || v.length === 0;} }, inte: {value:"true"}, property: {value:"payload",required:true} }, diff --git a/function/random/random.js b/function/random/random.js index dac7b0b9..2140717d 100644 --- a/function/random/random.js +++ b/function/random/random.js @@ -3,21 +3,73 @@ module.exports = function(RED) { "use strict"; function RandomNode(n) { RED.nodes.createNode(this,n); - this.low = Number(n.low || 1); - this.high = Number(n.high || 10); + + this.low = n.low + this.high = n.high this.inte = n.inte || false; this.property = n.property||"payload"; var node = this; + var tmp = {}; + this.on("input", function(msg) { - var value; - if (node.inte == "true" || node.inte === true) { - value = Math.round(Math.random() * (node.high - node.low + 1) + node.low - 0.5); - } - else { - value = Math.random() * (node.high - node.low) + node.low; - } - RED.util.setMessageProperty(msg,node.property,value); - node.send(msg); + + tmp.low = 1 // set this as the default low value + tmp.low_e = "" + if (node.low) { // if the the node has a value use it + tmp.low = node.low + } else if ('from' in msg) { // else see if a 'from' is in the msg + if (Number(msg.from)) { // if it is, and is a number, use it + tmp.low = Number(msg.from); + } else { // otherwise setup NaN error + tmp.low = NaN; + tmp.low_e = " From: " + msg.from; // setup to show bad incoming msg.from + } + } + + tmp.high = 10 // set this as the default high value + tmp.high_e = ""; + if (node.high) { // if the the node has a value use it + tmp.high = node.high + } else if ('to' in msg) { // else see if a 'to' is in the msg + if (Number(msg.to)) { // if it is, and is a number, use it + tmp.high = Number(msg.to); + } else { // otherwise setup NaN error + tmp.high = NaN + tmp.high_e = " To: " + msg.to // setup to show bad incoming msg.to + } + } + + // if tmp.low or high are not numbers, send an error msg with bad values + if ( (isNaN(tmp.low)) || (isNaN(tmp.high)) ) { + this.error("Random: one of the input values is not a number. " + tmp.low_e + tmp.high_e); + } else { + // at this point we have valid values so now to generate the random number! + + // flip the values if low > high so random will work + var value = 0; + if (tmp.low > tmp.high) { + value = tmp.low + tmp.low = tmp.high + tmp.high = value + } + + // if returning an integer, do a math.ceil() on the low value and a + // Math.floor()high value before generate the random number. This must be + // done to insure the rounding doesn't round up if using something like 4.7 + // which would end up with 5 + if ( (node.inte == "true") || (node.inte === true) ) { + tmp.low = Math.ceil(tmp.low); + tmp.high = Math.floor(tmp.high); + // use this to round integers + value = Math.round(Math.random() * (tmp.high - tmp.low + 1) + tmp.low - 0.5); + } else { + // use this to round floats + value = (Math.random() * (tmp.high - tmp.low)) + tmp.low; + } + + RED.util.setMessageProperty(msg,node.property,value); + node.send(msg); + } }); } RED.nodes.registerType("random",RandomNode); diff --git a/test/function/random/random_spec.js b/test/function/random/random_spec.js index ffd119f2..d352c12a 100644 --- a/test/function/random/random_spec.js +++ b/test/function/random/random_spec.js @@ -15,74 +15,257 @@ describe('random node', function() { helper.stopServer(done); }); }); + +// ============================================================ - it("should be loaded with correct defaults", function(done) { - var flow = [{"id":"n1", "type":"random", "name":"random1", "wires":[[]]}]; - helper.load(testNode, flow, function() { - var n1 = helper.getNode("n1"); - //console.log(n1); - n1.should.have.property("low", 1); - n1.should.have.property("high", 10); - n1.should.have.property("inte", false); - done(); - }); - }); - - it('should output an integer between -3 and 3', function(done) { - var flow = [{"id":"n1", "type":"random", low:-3, high:3, inte:true, wires:[["n2"]] }, + it ("Test i1 (integer) - DEFAULT no overrides defaults to 1 and 10", function(done) { + var flow = [{id:"n1", type:"random", low: "" , high:"" , inte:true, wires:[["n2"]] }, {id:"n2", type:"helper"} ]; - helper.load(testNode, flow, function() { + helper.load(testNode, flow, function() { var n1 = helper.getNode("n1"); var n2 = helper.getNode("n2"); - var c = 0; - n2.on("input", function(msg) { - if (c === 0) { - msg.should.have.a.property("payload"); - msg.payload.should.be.approximately(0,3); - msg.payload.toString().indexOf(".").should.equal(-1); - done(); + n2.on("input", function(msg) { + try { + //console.log(msg); + msg.should.have.a.property("payload"); + msg.payload.should.be.within(1,10); + msg.payload.toString().indexOf(".").should.equal(-1); // see if it's really an integer and not a float... + done(); } + catch(err) { done(err); } }); - n1.emit("input", {payload:"a"}); + n1.emit("input", {"test":"Test i1"}); }); }); - it('should output an float between 20 and 30', function(done) { - var flow = [{"id":"n1", "type":"random", low:20, high:30, inte:false, wires:[["n2"]] }, + it ("Test f1 (float) - DEFAULT no overrides defaults to 1 and 10", function(done) { + var flow = [{id:"n1", type:"random", low:"" , high:"" , inte:false, wires:[["n2"]] }, {id:"n2", type:"helper"} ]; - helper.load(testNode, flow, function() { + helper.load(testNode, flow, function() { var n1 = helper.getNode("n1"); var n2 = helper.getNode("n2"); - var c = 0; - n2.on("input", function(msg) { - if (c === 0) { - msg.should.have.a.property("payload"); - msg.payload.should.be.approximately(25,5); - msg.payload.toString().indexOf(".").should.not.equal(-1); - done(); + n2.on("input", function(msg) { + try { + //console.log(msg); + msg.should.have.a.property("payload"); + msg.payload.should.be.within(1.0,9.999); + //msg.payload.toString().indexOf(".").should.not.equal(-1); + done(); } + catch(err) { done(err); } }); - n1.emit("input", {payload:"a"}); + n1.emit("input", {"test":"Test f-1"}); }); }); - it('should output an integer between -3 and 3 on chosen property - foo', function(done) { - var flow = [{"id":"n1", "type":"random", property:"foo", low:-3, high:3, inte:true, wires:[["n2"]] }, +// ============================================================ + + it ("Test i2 (integer) - FLIP node From = 3 To = -3", function(done) { + var flow = [{id:"n1", type:"random", low: 3, high: -3, inte:true, wires:[["n2"]] }, {id:"n2", type:"helper"} ]; - helper.load(testNode, flow, function() { + helper.load(testNode, flow, function() { var n1 = helper.getNode("n1"); var n2 = helper.getNode("n2"); - var c = 0; - n2.on("input", function(msg) { - if (c === 0) { - msg.should.have.a.property("foo"); - msg.foo.should.be.approximately(0,3); - msg.foo.toString().indexOf(".").should.equal(-1); - done(); + n2.on("input", function(msg) { + try { + //console.log(msg); + msg.should.have.a.property("payload"); + msg.payload.should.be.within(-3,3); + msg.payload.toString().indexOf(".").should.equal(-1); // slightly dumb test to see if it really is an integer and not a float... + done(); } + catch(err) { done(err); } }); - n1.emit("input", {payload:"a"}); + n1.emit("input", {"test":"Test i2"}); }); }); + it ("Test f2 (float) - FLIP node From = 3 To = -3", function(done) { + var flow = [{id:"n1", type:"random", low: 3, high: -3, inte:false, wires:[["n2"]] }, + {id:"n2", type:"helper"} ]; + helper.load(testNode, flow, function() { + var n1 = helper.getNode("n1"); + var n2 = helper.getNode("n2"); + n2.on("input", function(msg) { + try { + //console.log(msg); + msg.should.have.a.property("payload"); + msg.payload.should.be.within(-3.0,3.0); + done(); + } + catch(err) { done(err); } + }); + n1.emit("input", {"test":"Test f2"}); + }); + }); + +// ============================================================ + + it ("Test i3 (integer) - values in msg From = 2 To = '5', node no entries", function(done) { + var flow = [{id:"n1", type:"random", low: "", high: "", inte:true, wires:[["n2"]] }, + {id:"n2", type:"helper"} ]; + helper.load(testNode, flow, function() { + var n1 = helper.getNode("n1"); + var n2 = helper.getNode("n2"); + n2.on("input", function(msg) { + try { + //console.log(msg); + msg.should.have.a.property("payload"); + msg.payload.should.be.within(2,5); + msg.payload.toString().indexOf(".").should.equal(-1); // slightly dumb test to see if it really is an integer and not a float... + done(); + } + catch(err) { done(err); } + }); + n1.emit("input", {"test":"Test i3", "from":2, "to":'5'}); + }); + }); + + it ("Test f3 (float) - values in msg From = 2 To = '5', node no entries", function(done) { + var flow = [{id:"n1", type:"random", low: "", high: "", inte:false, wires:[["n2"]] }, + {id:"n2", type:"helper"} ]; + helper.load(testNode, flow, function() { + var n1 = helper.getNode("n1"); + var n2 = helper.getNode("n2"); + n2.on("input", function(msg) { + try { + //console.log(msg); + msg.should.have.a.property("payload"); + msg.payload.should.be.within(2.0,5.0); + done(); + } + catch(err) { done(err); } + }); + n1.emit("input", {"test":"Test f3", "from":2, "to":'5'}); + }); + }); + + + // ============================================================ + + it ("Test i4 (integer) - value in msg From = 2, node From = 5 To = '' - node overides From = 5 To defaults to 10", function(done) { + var flow = [{id:"n1", type:"random", low: 5, high:"", inte:true, wires:[["n2"]] }, + {id:"n2", type:"helper"} ]; + helper.load(testNode, flow, function() { + var n1 = helper.getNode("n1"); + var n2 = helper.getNode("n2"); + n2.on("input", function(msg) { + try { + //console.log(msg); + msg.should.have.a.property("payload"); + msg.payload.should.be.within(5,10); + msg.payload.toString().indexOf(".").should.equal(-1); + done(); + } + catch(err) { done(err); } + }); + n1.emit("input", {"test":"Test i4", "from": 2}); + }); + }); + + it ("Test f4 (float) - value in msg From = 2, node From = 5 To = '' - node wins 'To' defaults to 10", function(done) { + var flow = [{id:"n1", type:"random", low: 5, high:"", inte:false, wires:[["n2"]] }, + {id:"n2", type:"helper"} ]; + helper.load(testNode, flow, function() { + var n1 = helper.getNode("n1"); + var n2 = helper.getNode("n2"); + n2.on("input", function(msg) { + try { + //console.log(msg); + msg.should.have.a.property("payload"); + msg.payload.should.be.within(5.0,10.0); + done(); + } + catch(err) { done(err); } + }); + n1.emit("input", {"test":"Test f4", "from": 2}); + }); + }); + +// ============================================================ + + it ("Test i5 (integer) - msg From = '6' To = '9' node no entries", function(done) { + var flow = [{id:"n1", type:"random", low: "", high: "", inte:true, wires:[["n2"]] }, + {id:"n2", type:"helper"} ]; + helper.load(testNode, flow, function() { + var n1 = helper.getNode("n1"); + var n2 = helper.getNode("n2"); + n2.on("input", function(msg) { + try { + //console.log(msg); + msg.should.have.a.property("payload"); + msg.payload.should.be.within(6,9); + msg.payload.toString().indexOf(".").should.equal(-1); // slightly dumb test to see if it really is an integer and not a float... + done(); + } + catch(err) { done(err); } + }); + n1.emit("input", {"test":"Test i5", "from": '6', "to": '9'}); + }); + }); + + it ("Test f5 (float) - msg From = '6' To = '9' node no entries", function(done) { + var flow = [{id:"n1", type:"random", low: "", high: "", inte:false, wires:[["n2"]] }, + {id:"n2", type:"helper"} ]; + helper.load(testNode, flow, function() { + var n1 = helper.getNode("n1"); + var n2 = helper.getNode("n2"); + n2.on("input", function(msg) { + try { + //console.log(msg); + msg.should.have.a.property("payload"); + msg.payload.should.be.within(6.0,9.0); + done(); + } + catch(err) { done(err); } + }); + n1.emit("input", {"test":"Test f5", "from": '6', "to": '9'}); + }); + }); + +// ============================================================ + + it ("Test i6 (integer) - msg From = 2.4 To = '7.3' node no entries", function(done) { + var flow = [{id:"n1", type:"random", low: "", high: "", inte:true, wires:[["n2"]] }, + {id:"n2", type:"helper"} ]; + helper.load(testNode, flow, function() { + var n1 = helper.getNode("n1"); + var n2 = helper.getNode("n2"); + n2.on("input", function(msg) { + try { + //console.log(msg); + msg.should.have.a.property("payload"); + msg.payload.should.be.within(2,7); + msg.payload.toString().indexOf(".").should.equal(-1); // slightly dumb test to see if it really is an integer and not a float... + done(); + } + catch(err) { done(err); } + }); + n1.emit("input", {"test":"Test i6", "from": 2.4, "to": '7.3'}); + }); + }); + + it ("Test f6 (float) - msg From = 2.4 To = '7.3' node no entries", function(done) { + var flow = [{id:"n1", type:"random", low: "", high: "", inte:false, wires:[["n2"]] }, + {id:"n2", type:"helper"} ]; + helper.load(testNode, flow, function() { + var n1 = helper.getNode("n1"); + var n2 = helper.getNode("n2"); + n2.on("input", function(msg) { + try { + //console.log(msg); + msg.should.have.a.property("payload"); + msg.payload.should.be.within(2.4,7.3); + done(); + } + catch(err) { done(err); } + }); + n1.emit("input", {"test":"Test f6", "from": 2.4, "to": '7.3'}); + }); + }); + +// ============================================================ + + + });