node-red-contrib-prib-functions 0.19.2 → 0.21.0

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 (82) hide show
  1. package/.github/workflows/codeql-analysis.yml +3 -3
  2. package/.github/workflows/npmpublish.yml +6 -6
  3. package/.vs/VSWorkspaceState.json +7 -0
  4. package/.vs/node-red-contrib-prib-functions/v17/.wsuo +0 -0
  5. package/README.md +84 -70
  6. package/dataAnalysis/arrayAllRowsSwap.js +15 -0
  7. package/dataAnalysis/arrayCompareToPrecision.js +34 -0
  8. package/dataAnalysis/arrayDifference.js +14 -0
  9. package/dataAnalysis/arrayDifferenceSeasonal.js +15 -0
  10. package/dataAnalysis/arrayDifferenceSeasonalSecondOrder.js +20 -0
  11. package/dataAnalysis/arrayDifferenceSecondOrder.js +14 -0
  12. package/dataAnalysis/arrayForEachRange.js +38 -0
  13. package/dataAnalysis/arrayOverlay.js +13 -0
  14. package/dataAnalysis/arrayProduct.js +11 -0
  15. package/dataAnalysis/arrayRandom.js +14 -0
  16. package/dataAnalysis/arrayReduceRange.js +11 -0
  17. package/dataAnalysis/arrayScale.js +11 -0
  18. package/dataAnalysis/arraySum.js +11 -0
  19. package/dataAnalysis/arraySumSquared.js +11 -0
  20. package/dataAnalysis/arraySwap.js +11 -0
  21. package/dataAnalysis/dataAnalysis.html +52 -21
  22. package/dataAnalysis/dataAnalysis.js +73 -44
  23. package/dataAnalysis/generateMatrixFunction.js +89 -0
  24. package/dataAnalysis/generateVectorFunction.js +25 -0
  25. package/dataAnalysis/pca.js +472 -325
  26. package/dataAnalysis/svd.js +239 -0
  27. package/documentation/DataAnalysisRealtime.JPG +0 -0
  28. package/documentation/monitorSystem.JPG +0 -0
  29. package/documentation/monitorSystemTest.JPG +0 -0
  30. package/echart/echart.html +68 -0
  31. package/echart/echart.js +85 -0
  32. package/echart/icons/chart-671.png +0 -0
  33. package/echart/lib/echarts.js +95886 -0
  34. package/lib/Chart.js +177 -0
  35. package/lib/Column.js +99 -0
  36. package/lib/GraphDB.js +14 -0
  37. package/lib/Table.js +185 -0
  38. package/lib/objectExtensions.js +361 -0
  39. package/matrix/matrix.js +95 -56
  40. package/matrix/matrixNode.html +88 -55
  41. package/matrix/matrixNode.js +12 -5
  42. package/monitor/BarGauge.js +8 -0
  43. package/monitor/Dataset.js +29 -0
  44. package/monitor/DialGauge.js +109 -0
  45. package/monitor/DialNeedle.js +36 -0
  46. package/monitor/Format.js +74 -0
  47. package/monitor/centerElement.js +14 -0
  48. package/monitor/compareElements.js +95 -0
  49. package/monitor/defs.js +23 -0
  50. package/monitor/extensions.js +906 -0
  51. package/monitor/functions.js +36 -0
  52. package/monitor/json2xml.js +103 -0
  53. package/monitor/monitorSystem.html +199 -0
  54. package/monitor/monitorSystem.js +322 -0
  55. package/monitor/svgHTML.js +179 -0
  56. package/monitor/svgObjects.js +64 -0
  57. package/package.json +20 -6
  58. package/test/00-objectExtensions.js +94 -0
  59. package/test/04-tables.js +33 -0
  60. package/test/data/.config.nodes.json +608 -0
  61. package/test/data/.config.nodes.json.backup +608 -0
  62. package/test/data/.config.runtime.json +4 -0
  63. package/test/data/.config.runtime.json.backup +3 -0
  64. package/test/data/.config.users.json +21 -0
  65. package/test/data/.config.users.json.backup +21 -0
  66. package/test/data/.flow.json.backup +2820 -2003
  67. package/test/data/float32vector10.npy +0 -0
  68. package/test/data/flow.json +2830 -2033
  69. package/test/data/int2matrix2x3.npy +0 -0
  70. package/test/data/package-lock.json +158 -0
  71. package/test/data/package.json +11 -0
  72. package/test/dataAnalysisExtensions.js +471 -0
  73. package/test/dataAnalysisPCA.js +54 -0
  74. package/test/dataAnalysisSVD.js +31 -0
  75. package/test/euclideanDistance.js +2 -2
  76. package/test/transformConfluence.js +1 -1
  77. package/test/transformNumPy.js +132 -0
  78. package/testing/test.html +1 -1
  79. package/testing/test.js +78 -53
  80. package/transform/NumPy.js +303 -0
  81. package/transform/transform.html +12 -0
  82. package/transform/transform.js +34 -2
@@ -7,18 +7,20 @@
7
7
  name: {value:null},
8
8
  action: {value: "create",required:true},
9
9
  args: {value:[]},
10
- arg: {value:null},"arg-type": {value:"msg"},
11
10
  call:{value:null},
12
- column: {value:null},"column-type": {value:"num"},
13
- columns: {value:null},"columns-type": {value:"num"},
11
+ column: {value:2},"column-type": {value:"num"},
12
+ columns: {value:2},"columns-type": {value:"num"},
13
+ dataType: {value:"Float32Array"},"columns-type": {value:"Float32Array"},
14
14
  end: {value:null},"end-type": {value:"num"},
15
15
  factor: {value:null},"factor-type": {value:"num"},
16
+ initialState:{value:"setZero"},
16
17
  matrix: {value:"payload"},"matrix-type": {value:"msg"},
17
18
  precision: {value:3},"precision-type": {value:"num"},
18
19
  row: {value:3},"row-type": {value:"num"},
19
20
  rows: {value:3},"rows-type": {value:"num"},
20
21
  rowTarget: {value:null},"rowTarget-type": {value:"num"},
21
22
  source: {value:"_matrix"},"source-type": {value:"msg"},
23
+ sourceArray: {value:"payload"},"sourceArray-type": {value:"msg,json,flow,global"},
22
24
  start: {value:null},"start-type": {value:"num"},
23
25
  target: {value:"_matrix"},"target-type": {value:"msg"},
24
26
  value: {value:"payload"},"value-type": {value:"msg"},
@@ -35,70 +37,70 @@
35
37
  return this.name || ("Matrix "+this.action||"*** new ***");
36
38
  },
37
39
  oneditprepare: function() {
40
+ console.log("+++")
38
41
  const node=this;
39
42
  node.properties=[];
40
43
  node.editors=[];
41
44
  const actions={
42
- define:{label:"Define",show:["target"],args:["rows","columns"]},
43
- defineEmpty:{label:"Define Empty",show:["target"],args:["rows","columns"]},
44
- create:{label:"Create",show:["target"],args:[]},
45
- createLike:{label:"Create Like",show:["source","target"],args:[]},
46
- clone:{label:"Clone",show:["source","target"],args:[]},
47
45
  add:{label:"Add",show:["source"],args:["matrix"]},
48
46
  addRow:{label:"Add Row",show:["source"],args:["row","vector"]},
49
47
  addRow2Row:{label:"Add Row to Row",show:["source"],args:["row","target","factor","start","end"]},
50
48
  addCell:{label:"Add to Cell",show:["source"],args:["row","column","value"]},
51
- subtractCell:{label:"Subtract Cell",show:["source","target"],args:["row","column","value"]},
52
- multiple:{label:"Multiple",show:["source","target"],args:[]},
53
- multipleCell:{label:"Multiple Cell",show:["source","target"],args:["rows","columns","value"]},
54
- divideCell:{label:"Divide Cell",show:["source"],args:["rows","columns","value"]},
55
- divideRow:{label:"Divide Row",show:["source"],args:["row","factor","start","end"]},
56
- transpose:{label:"Transpose",show:["source","target"],args:[]},
57
- getAdjoint:{label:"Adjoint",show:["source","target"],args:[]},
58
- getCofactor:{label:"Cofactor",show:["source","target"],args:[]},
59
- getComplementMinor:{label:"Complement Minor",show:["source","target"],args:[]},
60
- getIdentity:{label:"Identity",show:["source","target"],args:[]},
61
- getInverse:{label:"Inverse",show:["source","target"],args:[]},
62
- getInverseAdjointMethod:{label:"Inverse (Adjoint Method)",show:["source","target"],args:[]},
63
- getInverseGaussJordan:{label:"Inverse (Gauss Jordan Method)",show:["source","target"],args:[]},
64
- norm:{label:"Norm",show:["source","target"],args:[]},
65
- getDeterminant:{label:"Determinant",show:["source","target"],args:[]},
66
- getDeterminantUsingCofactor:{label:"Determinant (Cofactor)",show:["source","target"],args:[]},
67
- getDeterminantUsingCofactor:{label:"Determinant (Row Echelon Form)",show:["source","target"],args:[]},
68
49
  backwardSubstitution:{label:"Backward Substitution",show:["source"],args:[]},
69
- forwardElimination:{label:"Forward Elimination",show:["source"],args:[]},
70
- gaussianElimination:{label:"Gaussian Elimination",show:["source"],args:[]},
71
- reducedRowEchelonForm:{label:"Reduced Row EchelonForm",show:["source"],args:[]},
72
- rowEchelonForm:{label:"Row Echelon Form",show:["source"],args:[]},
73
- equalsNearly:{label:"Nearly Equals",show:["source"],args:[]},
74
- testIsSquare:{label:"Is Square",show:["source"],args:[]},
75
- get:{label:"Get Cell",show:["source","target"],args:[]},
76
- sumRow:{label:"Sum Row",show:["source","target"],args:[]},
77
- swapRows:{label:"Swap Rows",show:["source"],args:[]},
78
- toArray:{label:"To Array Object",show:["source","target"],args:[]},
79
- runningSum:{label:"Running Sum",show:["source","target"],args:[]},
80
- getVandermonde:{label:"Vandermonde",show:["target"],args:["vector","columns"]},
81
- create:{label:"Create",show:[,"target"],args:["rows","columns"]},
50
+ create:{label:"Create", show:["target"],args:["initialState","rows","columns","dataType"]},
51
+ createLike:{label:"Create Like",show:["source","target"],args:[]},
52
+ clone:{label:"Clone",show:["source","target"],args:[]},
82
53
  createForEachCellPairSet:{label:"Create Pair Set Cells",show:["source","target"],args:["matrix","call"],default:{call:"(baseCellValue,matrixCellValue)=>{}"}},
54
+ define:{label:"Define",show:["target"],args:["rows","columns","dataType"]},
55
+ defineEmpty:{label:"Define Empty",show:["target"],args:["rows","columns","dataType"]},
56
+ divideCell:{label:"Divide Cell",show:["source"],args:["rows","columns","value"]},
57
+ divideRow:{label:"Divide Row",show:["source"],args:["row","factor","start","end"]},
58
+ equalsNearly:{label:"Nearly Equals",show:["source"],args:[]},
59
+ fillArray:{label:"Fill",show:["source"],args:["matrix"]},
60
+ findColumnRow:{label:"Find in Column",show:["source"],args:["column","call","start","end"],default:{call:"()=>{}"}},
83
61
  findRowColumn:{label:"Find in Row",show:["source"],args:["row","call","start","end"],default:{call:"(value,row,column,offset,vector)=>true"}},
84
62
  forRowCells:{label:"Row Cells",show:["source"],args:["row","call","start","end"],default:{call:"()=>{}"}},
85
- fillArray:{label:"fill",show:["source"],args:["matrix"]},
86
- findColumnRow:{label:"Find in Column",show:["source"],args:["column","call","start","end"],default:{call:"()=>{}"}},
87
63
  forColumnCells:{label:"Column Cells",show:["source"],args:["column","call","start","end"],default:{call:"()=>{}"}},
88
64
  forEachCell:{label:"For Each Cell",show:["source"],args:["call"],default:{call:"()=>{}"}},
89
65
  forEachRow:{label:"For Each Row",show:["source"],args:["call"],default:{call:"()=>{}"}},
90
66
  forEachCellPairSet:{label:"For Each Cell Pair Set",show:["source"],args:["matrix","call"],default:{call:"()=>{}"}},
67
+ forwardElimination:{label:"Forward Elimination",show:["source"],args:[]},
68
+ gaussianElimination:{label:"Gaussian Elimination",show:["source"],args:[]},
69
+ get:{label:"Get Cell",show:["source","target"],args:[]},
70
+ getAdjoint:{label:"Adjoint",show:["source","target"],args:[]},
71
+ getCofactor:{label:"Cofactor",show:["source","target"],args:[]},
72
+ getComplementMinor:{label:"Complement Minor",show:["source","target"],args:[]},
73
+ getDeterminant:{label:"Determinant",show:["source","target"],args:[]},
74
+ getDeterminantUsingCofactor:{label:"Determinant (Cofactor)",show:["source","target"],args:[]},
75
+ getDeterminantUsingCofactor:{label:"Determinant (Row Echelon Form)",show:["source","target"],args:[]},
76
+ getIdentity:{label:"Identity",show:["source","target"],args:[]},
77
+ getInverse:{label:"Inverse",show:["source","target"],args:[]},
78
+ getInverseAdjointMethod:{label:"Inverse (Adjoint Method)",show:["source","target"],args:[]},
79
+ getInverseGaussJordan:{label:"Inverse (Gauss Jordan Method)",show:["source","target"],args:[]},
91
80
  getIndex:{label:"Get Vector Offset",show:["source","target"],args:["row","column"]},
92
- getZeroed:{label:"Get Zeroed",show:["source","target"],args:["row","column"]},
93
- getMatrix:{label:"get Sub Matrix",show:["source","target"],args:["row","column","rows","columns"]},
81
+ getMatrix:{label:"Get Sub Matrix",show:["source","target"],args:["row","column","rows","columns"]},
94
82
  getRow:{label:"Get Row",show:["source","target"],args:["row"]},
83
+ getVandermonde:{label:"Vandermonde",show:["target"],args:["vector","columns"]},
84
+ getZeroed:{label:"Get Zeroed",show:["source","target"],args:["row","column"]},
95
85
  maxAbsColumn:{label:"Column Maximum Absolute",show:["source","target"],args:["column","start"]},
96
86
  maxColumn:{label:"Column Max",show:["source","target"],args:["column","start"]},
87
+ multiple:{label:"Multiple",show:["source","target"],args:[]},
88
+ multipleCell:{label:"Multiple Cell",show:["source","target"],args:["rows","columns","value"]},
97
89
  multiplyRow:{label:"Multiply Row",show:["source"],args:["row","factor"]},
90
+ norm:{label:"Norm",show:["source","target"],args:[]},
98
91
  reduceRow:{label:"Reduce Row",show:["source","target"],args:["row","call","value"],default:{call:"(agregatevalue,cellValue,row,column)=>agregatevalue+cellValue"}},
92
+ reduce:{label:"Reduce Cells",show:["source","target"],args:["call","value"],default:{call:"()=>{}"}},
93
+ reducedRowEchelonForm:{label:"Reduced Row EchelonForm",show:["source"],args:[]},
94
+ rowEchelonForm:{label:"Row Echelon Form",show:["source"],args:[]},
95
+ runningSum:{label:"Running Sum",show:["source","target"],args:[]},
99
96
  set:{label:"Set Cell",show:["source"],args:["row","column","value"]},
100
97
  setRow:{label:"Set Row",show:["source"],args:["vector","row"]},
101
- reduce:{label:"Reduce Cells",show:["source","target"],args:["call","value"],default:{call:"()=>{}"}}
98
+ subtractCell:{label:"Subtract Cell",show:["source","target"],args:["row","column","value"]},
99
+ sumRow:{label:"Sum Row",show:["source","target"],args:[]},
100
+ swapRows:{label:"Swap Rows",show:["source"],args:[]},
101
+ testIsSquare:{label:"Is Square",show:["source"],args:[]},
102
+ toArray:{label:"To Array Object",show:["source","target"],args:[]},
103
+ transpose:{label:"Transpose",show:["source","target"],args:[]}
102
104
  };
103
105
  const baseDiv=$("#node-inputDynamicBase");
104
106
  function defineProperty(property,...types) {
@@ -118,16 +120,46 @@
118
120
  const inputNode=$('<input type="text" id="node-input-'+property.name+'"/>').val(node[property.name]);
119
121
  const typeNode=$('<input type="hidden" id="node-input-'+property.name+'-type"/>');
120
122
  element.append([inputNode,typeNode]);
121
- const typeValue=node[property.name+"-type"];
122
- if(typeValue) typeNode.val(typeValue);
123
- $("#node-input-"+property.name).typedInput({
124
- type:typeValue||types[0],
125
- types:types,
126
- typeField: "#node-input-"+property.name+"-type"
127
- });
123
+ if(types[0] instanceof Array) {
124
+ $("#node-input-"+property.name).typedInput({
125
+ type:property.name,
126
+ types:[{value: property.name,
127
+ options: types[0]
128
+ }]})
129
+ } else {
130
+ const typeValue=node[property.name+"-type"];
131
+ if(typeValue) typeNode.val(typeValue);
132
+ $("#node-input-"+property.name).typedInput({
133
+ type:typeValue||types[0],
134
+ types:types,
135
+ typeField: "#node-input-"+property.name+"-type"
136
+ });
137
+ }
128
138
  }
129
139
  }
130
- defineProperty({name:"source" ,label:"Source" ,icon:"crosshairs"},"msg","flow","global");
140
+ defineProperty({name:"initialState",label:"Initially" ,icon:"tag"},[
141
+ { value: "setZero", label: "Zeros"},
142
+ { value: "setRandom", label: "Random Numbers"},
143
+ { value: "setIdentity", label: "Identity"},
144
+ { value: "setOne", label: "all 1"},
145
+ ]);
146
+
147
+ defineProperty({name:"dataType",label:"number Type" ,icon:"tag"},[
148
+ { value: "Float32Array", label: "float32 -3.4e38 to 3.4e38" },
149
+ { value: "Float64Array", label: "double/float64 -1.8e308 to 1.8e308" }, { value: "Int8Array", label: "byte -128 to 122" },
150
+ { value: "Uint8Array", label: "octet 0 to 255" },
151
+ { value: "Uint8ClampedArray", label: "octet clamped 0 to 255" },
152
+ { value: "Int16Array", label: "short -32768 to 32767" },
153
+ { value: "Uint16Array", label: "short unsigned 0 to 65535" },
154
+ { value: "Int32Array", label: " long -2147483648 to 2147483647" },
155
+ { value: "Uint32Array", label: "long unsgined 0 to 4294967295" },
156
+ { value: "BigInt64Array", label: "bigint 2**-263 to 2**263" },
157
+ { value: "BigUint64Array", label: "bigint unsigned 0 to 2**264" },
158
+ ]);
159
+
160
+
161
+
162
+ defineProperty({name:"source" ,label:"Source" ,icon:"crosshairs"},"msg","json","flow","global");
131
163
  defineProperty({name:"arg" ,label:"Argument" ,icon:"tag"},"num","json","msg","flow","global","env");
132
164
  defineProperty({name:"matrix" ,label:"Matrix" ,icon:"th"},"msg","flow","global");
133
165
  defineProperty({name:"target" ,label:"Target" ,icon:"save"},"msg","flow","global");
@@ -145,8 +177,10 @@
145
177
  defineProperty({name:"vector" ,label:"Vector" ,icon:"ellipsis-h"},"json","msg","flow","global");
146
178
  defineProperty({name:"call" ,label:"Call" ,icon:"js",mode:"javascript"},"edit");
147
179
 
148
- const options=Object.keys(actions).reduce((previousValue,property)=>previousValue.concat({value:property,label:actions[property].label}),
149
- []);
180
+ const options=Object.keys(actions)
181
+ .sort((a,b) => actions[a].label<actions[b].label?-1:0)
182
+ .reduce((previousValue,property)=>previousValue.concat({value:property,label:actions[property].label}),
183
+ []);
150
184
  const actionNode=$("#node-input-action");
151
185
  actionNode.typedInput({
152
186
  types: [{
@@ -154,7 +188,7 @@
154
188
  options: options
155
189
  }]
156
190
  });
157
- actionNode.change(function() {
191
+ actionNode.change(function() {
158
192
  action=$(this).val();
159
193
  node.args=[];
160
194
  node.properties.forEach(property=>$(".form-row-http-in-"+property).hide());
@@ -162,7 +196,6 @@
162
196
  node.args=actionDef.args;
163
197
  node.args.forEach(property=>$(".form-row-http-in-"+property).show());
164
198
  actionDef.show.forEach(property=>$(".form-row-http-in-"+property).show());
165
-
166
199
  });
167
200
  },
168
201
  oneditsave: function() {
@@ -23,6 +23,7 @@ function evalInFunction(node,propertyName){
23
23
  const property=node[propertyName];
24
24
  if(property==null) throw Error("no value for "+propertyName);
25
25
  const propertyType=propertyName+"-type";
26
+ if(! (propertyType in node)) return evalFunction(propertyName,"()=>node."+property)
26
27
  switch (node[propertyType]){
27
28
  case "num":
28
29
  case "json":
@@ -86,7 +87,11 @@ module.exports = function (RED) {
86
87
  }
87
88
  node.argFunction=[];
88
89
  node.args.forEach(property=>{
89
- node.argFunction.push(evalInFunction(node,property).bind(this));
90
+ try{
91
+ node.argFunction.push(evalInFunction(node,property).bind(this));
92
+ } catch(ex) {
93
+ throw Error("args "+property+" "+ex.message)
94
+ }
90
95
  })
91
96
  function baseProcess(msg){
92
97
  const sourceIn=node.getSource(msg);
@@ -99,14 +104,15 @@ module.exports = function (RED) {
99
104
  node.setData.apply(node,[result,msg]);
100
105
  }
101
106
  function createProcess(msg){
102
- const sourceIn=node.getSource(msg);
103
- if(sourceIn==null) throw Error("source data not found");
104
- const sourceMatrix=(sourceIn instanceof Matrix?sourceIn.clone():new Matrix(sourceIn));
107
+ if(logger.active) logger.sendInfo({label:"create",arg:{rowsMax:node.row,columns:node.column}});
108
+ const sourceMatrix=new Matrix({rowsMax:node.rows,columns:node.columns,dataType:node.dataType});
109
+ if(!(node.initialState in sourceMatrix)) throw Error("Invalid initial state "+node.initialState);
110
+ sourceMatrix[node.initialState]()
105
111
  node.setData.apply(node,[sourceMatrix,msg]);
106
112
  }
107
113
  function defineProcess(msg){
108
114
  if(logger.active) logger.sendInfo({label:"define",arg:{rows:node.row,columns:node.column}});
109
- const sourceMatrix=new Matrix({rows:node.rows,columns:node.columns});
115
+ const sourceMatrix=new Matrix({rows:node.rows,columns:node.columns,dataType:node.dataType});
110
116
  node.setData.apply(node,[sourceMatrix,msg]);
111
117
  }
112
118
  function defineEmptyProcess(msg){
@@ -152,6 +158,7 @@ module.exports = function (RED) {
152
158
  node.msgProcess(msg);
153
159
  node.send(msg);
154
160
  } catch(ex) {
161
+ error(node,ex,"Invalid "+ex.message)
155
162
  msg.error=ex.message;
156
163
  node.send([null,msg]);
157
164
  if(logger.active) logger.send({label:"error",node:node.id,action:node.action,exception:ex.message,stack:ex.stack});
@@ -0,0 +1,8 @@
1
+ const getBarGauge=(max,min)=>{
2
+ return {action:"g",id:"barGauge",children:[
3
+ defs,
4
+ {action:"rect",x:x,y:y,width:width,height:height,children:[
5
+ {action:"animate",attributeName:"transform",values:"0;5;0",dur:"10s",repeatCount:"indefinite"}
6
+ ]},
7
+ ]}
8
+ }
@@ -0,0 +1,29 @@
1
+ function Dataset(settings) {
2
+ Object.assign(this,{values:[]},settings)
3
+ }
4
+ Dataset.prototype.addValue=function(v){
5
+ if(this.min==null) {
6
+ this.max=v
7
+ this.min=v
8
+ this.range=0
9
+ this.average=v
10
+ } else {
11
+ if(this.min>v){
12
+ this.min=v
13
+ this.range=this.max-this.min
14
+ } else if(this.max<v){
15
+ this.max=v
16
+ this.range=this.max-this.min
17
+ }
18
+ this.average+=(v-this.average)/(this.values.length+1)
19
+ }
20
+ this.values.push(v)
21
+ }
22
+ Dataset.prototype.getMax=function(){return this.max}
23
+ Dataset.prototype.getMin=function(){return this.min}
24
+ Dataset.prototype.getAverage=function(){return this.average}
25
+ Dataset.prototype.getFirst=function(){return this.values[0]}
26
+ Dataset.prototype.getRange=function(){return this.range}
27
+ Dataset.prototype.getLast=function(){return this.value.slice(-1)}
28
+
29
+ module.exports=Dataset
@@ -0,0 +1,109 @@
1
+ const defs=require("./defs.js")
2
+ const DialNeedle=require("./DialNeedle.js")
3
+ const boundValue=(v,max=100,min=0)=>Math.min(Math.max(v, min), max)
4
+ const pi2=2 * Math.PI
5
+ const pi2DegreeFactor=180 / Math.PI
6
+ const toRadians=(degrees)=> degrees / pi2DegreeFactor
7
+ const toDegrees=(radians)=> radians * pi2DegreeFactor
8
+ function DialGauge(settings) {
9
+ Object.assign(this,{radius:100,value:0,gapAngle:80,color:"gray",min:0,max:100,title:"%"},settings)
10
+ this.range=this.max-this.min
11
+ if(this.range<=0) throw Error("invalid range, min>=max")
12
+ this.strokeWidth = this.radius * 0.3;
13
+ this.circumference = this.radius * pi2
14
+ this.dashOffset = this.circumference * this.gapAngle/380;
15
+ this.gaugeAngleArea=360-this.gapAngle
16
+ this.angleFactor=this.gaugeAngleArea/this.range
17
+ this.halfStrokeGap=(this.circumference-this.dashOffset)/2
18
+ this.strokeInnerRadius=this.radius - this.strokeWidth / 2
19
+ this.strokeInnerCircumference= this.strokeInnerRadius * pi2
20
+ this.strokeDashOffset = this.strokeInnerCircumference * this.gaugeAngleArea/360;
21
+ this.gauge={action:"circle",fill:"transparent",
22
+ cx:this.radius,cy:this.radius,r:this.strokeInnerRadius,stroke:"lightgray","stroke-width":this.strokeWidth,
23
+ "stroke-dasharray":this.getDashArray(this.max),
24
+ transform:{rotate:{angle:90+parseInt(this.gapAngle/2),x:this.radius,y:this.radius}}}
25
+ this.needle=new DialNeedle({radius:this.radius,startAngle:-this.gaugeAngleArea/2})
26
+ this.svg=this.getSvg()
27
+ }
28
+ DialGauge.prototype.get=function(value){
29
+ return this.svg
30
+ }
31
+ DialGauge.prototype.getSvg=function(){
32
+ const group=[]
33
+ group.push(Object.assign({},this.gauge,{stroke:"red"}))
34
+ group.push(Object.assign({},this.gauge,{stroke:"orange","stroke-dasharray":this.getDashArray(80)}))
35
+ group.push(Object.assign({},this.gauge,{stroke:"yellow","stroke-dasharray":this.getDashArray(60)}))
36
+ group.push(Object.assign({},this.gauge,{stroke:"lightgreen","stroke-dasharray":this.getDashArray(40)}))
37
+ group.push(Object.assign({},this.gauge,{stroke:"green","stroke-dasharray":this.getDashArray(20)}))
38
+ group.push(Object.assign({},this.gauge,{id:"dialColor",stroke:"lightgray","stroke-dasharray":this.getDashArrayReverse(0)}))
39
+ /*
40
+ group.push({action:"clipPath",id:"clipGauge",children:[
41
+ Object.assign({},this.gauge,{id:"dialColor1","stroke-dasharray":this.getDashArray(0),"stroke-miterlimit":"10",stroke:"none",class:"heatGrad"})
42
+ ]})
43
+ group.push({action:"style",children:["circle.heatGrad {background: conic-gradient(red, orange, yellow, green); }"]})
44
+ group.push({action:"use",href:{id:"clipGauge"}})
45
+ */
46
+ group.push(this.getScale())
47
+ group.push({action:"text",x:this.radius,y:this.radius*1.5,"dominant-baseline":"middle","text-anchor":"middle",children:[this.title]})
48
+ group.push(this.needle.get(0))
49
+ return {action:"g",height:2*this.radius,children:[group]}
50
+ /*
51
+ {action:"clipPath",children:[
52
+ Object.assign({},this.gauge,{id:"dialColor","stroke-dasharray":this.getDashArray(0),stroke:"none",class:"grad"})
53
+ ]},
54
+ {action:"style",children:["circle.grad {background: conic-gradient(red, orange, yellow, green); }"]},
55
+ {action:"setConicGradient",id:"clip"},
56
+ */
57
+ }
58
+
59
+ DialGauge.prototype.getUpdate=function(value){
60
+ return [this.needle.getUpdate((value-this.min)*this.angleFactor),{action:"update",id:"dialColor","stroke-dasharray":this.getDashArrayReverse(value)}]
61
+ }
62
+ DialGauge.prototype.setMax=function(value){
63
+ this.max = value
64
+ this.range=this.max-this.min
65
+ if(this.range<=0) throw Error("invalid range, min>=max")
66
+ this.angleFactor=this.gaugeAngleArea/this.range
67
+ return this
68
+ }
69
+ DialGauge.prototype.getDashArray=function(value){
70
+ const ratio=(value-this.min)/this.range
71
+ const dash=this.strokeDashOffset*ratio
72
+ const gap=this.strokeInnerCircumference-dash
73
+ return dash+","+gap
74
+ }
75
+ DialGauge.prototype.getDashArrayReverse=function(value){
76
+ const ratio=(value-this.min)/this.range
77
+ const gap=this.strokeDashOffset*ratio
78
+ const dash=this.strokeDashOffset*(1-ratio)
79
+ return "0,"+gap+","+dash+","+this.strokeDashOffset
80
+ }
81
+
82
+ DialGauge.prototype.getScale=function() {
83
+ const sr1 = this.radius;
84
+ const sr2 = this.radius - this.strokeWidth-5;
85
+ const srT = sr2 - 10;
86
+ const objDef=[]
87
+ let n = 0;
88
+ const increment=toRadians(this.gaugeAngleArea/10)
89
+ for (let sr = toRadians(-this.gaugeAngleArea); sr <= 0; sr += increment) {
90
+ const sra=sr + toRadians(90 - this.gapAngle/2)
91
+ const saCos=Math.cos(sra)
92
+ const saSin=Math.sin(sra)
93
+ objDef.push({action:"line",
94
+ x1:this.radius + sr1 * saCos,
95
+ y1:this.radius + sr1 * saSin,
96
+ x2:this.radius + sr2 * saCos,
97
+ y2:this.radius + sr2 * saSin}
98
+ )
99
+ objDef.push({action:"text",
100
+ x:this.radius + srT * saCos,
101
+ y:this.radius + srT * saSin,
102
+ children:[String(n*10)]
103
+ })
104
+ n++
105
+ }
106
+ return objDef;
107
+ }
108
+
109
+ module.exports=DialGauge
@@ -0,0 +1,36 @@
1
+ function DialNeedle(settings) {
2
+ Object.assign(this,{
3
+ radius:100,
4
+ startAngle:0,
5
+ id:"needle",
6
+ baseDialSize:20,
7
+ value:{min:0,max:100}
8
+ },settings)
9
+ Object.assign(this,{
10
+ endAngle:this.endAngle??360-this.startAngle,
11
+ center:this.center??{x:this.radius,y:this.radius}
12
+ })
13
+ this.value.range=this.value.max-this.value.min
14
+ this.ratio=(this.endAngle-this.startAngle)/this.range,
15
+ this.svg=this.getSvg();
16
+ }
17
+ DialNeedle.prototype.get=function(value){
18
+ return this.svg
19
+ }
20
+ DialNeedle.prototype.getSvg=function(id=""){
21
+ return {action:"g",id:id+this.id,children:[
22
+ {action:"path",transform:{rotate:{angle:this.startAngle,x:this.radius,y:this.radius}},d:[
23
+ {action:"moveTo",x:this.radius,y:0},
24
+ {action:"deltaLineTo",x:-this.baseDialSize,y:this.radius},
25
+ {action:"deltaArc",radius:{x:this.baseDialSize,y:this.baseDialSize},x:this.baseDialSize*2,y:0},
26
+ {action:"Z"}
27
+ ],
28
+ fill:this.color,stroke:this.color
29
+ }
30
+ ]}
31
+ }
32
+ DialNeedle.prototype.getUpdate=function(angle){
33
+ if(angle>360 || angle < -360) throw Error("angle > 360 or < -360, angle: "+angle)
34
+ return {action:"update",id:this.id,transform:{rotate:{angle,x:this.radius,y:this.radius}}}
35
+ }
36
+ module.exports=DialNeedle
@@ -0,0 +1,74 @@
1
+ const Format={
2
+ NumberToAbbreviated:(value)=>{
3
+ if(typeof value!='number') value=parseFloat(value);
4
+ if (value>Math.pow(10,16)) return Math.round(value/Math.pow(10,15)).toString()+'P'
5
+ if (value>Math.pow(10,13)) return Math.round(value/Math.pow(10,12)).toString()+'T'
6
+ if (value>Math.pow(10,10)) return Math.round(value/Math.pow(10,9)).toString()+'G'
7
+ if (value>Math.pow(10,7)) return Math.round(value/Math.pow(10,6)).toString()+'M'
8
+ if (value>Math.pow(10,4)) return Math.round(value/Math.pow(10,3)).toString()+'K'
9
+ if (value == Math.round(value)) return value.toString()
10
+ if (value>=10000) return value.toFixed(0).toString()
11
+ if (value>=1000) return value.toFixed(1).toString()
12
+ if (value>=100) return value.toFixed(2).toString()
13
+ if (value>=10) return value.toFixed(3).toString()
14
+ return value.toString()
15
+ },
16
+ HexToString: (value)=>{
17
+ if(value==null) return null;
18
+ let valueString = '';
19
+ for (let i = 0; i < value.length; i += 2)
20
+ valueString += String.fromCharCode(parseInt(value.substr(i, 2), 16));
21
+ return valueString;
22
+ },
23
+ padLeadZero:(value,size)=>"000000000000".substr(0,size-value.toString().length)+value,
24
+ toString:(type,value)=>{
25
+ switch (type) {
26
+ case 'timestamp' :
27
+ case 'datetime' :
28
+ case 'time' :
29
+ case 'date' :
30
+ var ts = new Date();
31
+ ts.setTime(parseInt(value));
32
+ var axisLabel='';
33
+ switch (this.dataType[0]) {
34
+ case 'timestamp' :
35
+ case 'date' :
36
+ case 'datetime' :
37
+ if (this.precision[0] >= 1440) axisLabel+=ts.getFullYear()+'-';
38
+ if (this.precision[0] >= 1440) axisLabel+=Format.padLeadZero(ts.getMonth()+1,2)+'-';
39
+ if (this.precision[0] >= 1440) axisLabel+=Format.padLeadZero(ts.getDate(),2);
40
+ if (this.precision[0] >= 1440) axisLabel+=' ';
41
+ case 'time' :
42
+ if (this.precision[0] >= 360) axisLabel+=Format.padLeadZero(ts.getHours(),2)+':';
43
+ if (this.precision[0] >= 60) axisLabel+=Format.padLeadZero(ts.getMinutes(),2)+':';
44
+ if (this.precision[0] >= 1) axisLabel+=Format.padLeadZero(ts.getSeconds(),2);
45
+ }
46
+ return axisLabel;
47
+ case 'int' :
48
+ case 'real' :
49
+ case 'number' :
50
+ return format.NumberToAbbreviated(value)
51
+ }
52
+ return value.toString();
53
+ },
54
+ StringToHex:(value)=>{
55
+ if(value==null) return null;
56
+ let hex = '';
57
+ for(let i=0;i<value.length;i++)
58
+ hex += ''+value.charCodeAt(i).toString(16);
59
+ return hex;
60
+ },
61
+ xmlEncodeString(value) {
62
+ if(value==null) return null;
63
+ return value.toString().replace(/([\&"<>])/g, function(str, item) {
64
+ return {
65
+ '&': '&amp;',
66
+ '"': '&quot;',
67
+ '<': '&lt;',
68
+ '>': '&gt;'
69
+ }[item];
70
+ });
71
+ }
72
+ }
73
+
74
+ module.exports=Format
@@ -0,0 +1,14 @@
1
+ function centerElement(elementIdToCenter) {
2
+ if(elementIdToCenter == null) return;
3
+ const toCenter = document.getElementById(elementIdToCenter);
4
+ const width = toCenter.getWidth();
5
+ const height = toCenter.getHeight();
6
+ const elementParent = toCenter.ancestors();
7
+ const Pwidth = elementParent[0].getWidth();
8
+ const Pheight = elementParent[0].getHeight();
9
+ width = parseInt(Pwidth/2, 10) - parseInt(width/2, 10);
10
+ height = parseInt(Pheight/2, 10) - parseInt(height/2, 10);
11
+ toCenter.setStyle({'top': height + 'px'});
12
+ toCenter.setStyle({'left': width + 'px'});
13
+ }
14
+ module.exports=centerElement
@@ -0,0 +1,95 @@
1
+ function compareNodes(oldNode, newNode, compare) { // this function under construction
2
+ if( compare==null)
3
+ var compare= {
4
+ attribute: {
5
+ match: function(attribute) {
6
+ }
7
+ ,mismatch: function(oldAttribute,newAttribute) {
8
+ return '<attribute key="'+oldAttribute.nodeName+'" old="'+oldAttribute.nodeValue+'" new="'+newAttribute.nodeValue+'"/>';
9
+ }
10
+ ,missingNew: function(attribute) {
11
+ return '<attribute key="'+attribute.nodeName+'" new="'+attribute.nodeValue+'"/>';
12
+ }
13
+ ,missingOld : function(attribute) {
14
+ return '<attribute key="'+attribute.nodeName+'" old="'+attribute.nodeValue+'"/>';
15
+ }
16
+ }
17
+ ,node: {
18
+ isSameElement: function(oldNode,newNode) {
19
+ if(oldNode.nodeType != newNode.nodeType) return false;
20
+ if(oldNode.nodeType != 1) return true;
21
+ return (oldNode.nodeName = newNode.nodeName);
22
+ }
23
+ ,match: function(node) {
24
+ }
25
+ ,mismatch: function(oldNode,newNode) {
26
+ return '<pair><new th>"'+node.nodeValue+'</new></node>'
27
+ }
28
+ ,missingNew: function(node) {
29
+ return '<node key="'+node.nodeName+'"><new>"'+node.nodeValue+'</new></node>'
30
+ }
31
+ ,missingOld : function(node) {
32
+ return '<node key="'+node.nodeName+'"><old>"'+node.nodeValue+'</old></node>'
33
+ }
34
+ }
35
+ };
36
+ var diff="";
37
+ if(oldNode == null)
38
+ var oldAttributes=[] , oldNodes=[];
39
+ else
40
+ var oldAttributes=oldNode.attributes , oldNodes=oldNode.childNodes;
41
+ if(newNode == null)
42
+ var newAttributes=[] , newNodes=[];
43
+ else
44
+ var newAttributes=newNode.attributes , newNodes=oldNode.childNodes;
45
+ if( !compare.node.isSameElement(oldNode,newNode)
46
+ || oldNode.nodeValue != newNode.nodeValue )
47
+ diff += compare.node.mismatch(oldNode,newNode);
48
+ else
49
+ diff += compare.node.match(oldNode,newNode);
50
+ var o=0;n=0;
51
+ while (o<oldAttributes.length || n<newAttributes.length) {
52
+ var oldAttribute=oldAttributes[o],newAttribute=newAttributes[n];
53
+ if(oldAttributes.nodeName==newAttribute.nodeName) {
54
+ if(oldAttribute.nodeValue==newAttribute.nodeValue)
55
+ diff += compare.attribute.match(oldAttribute);
56
+ else
57
+ diff += compare.attribute.mismatch(oldAttribute,newAttribute);
58
+ o++;n++;
59
+ continue;
60
+ }
61
+ if(oldAttribute.nodeName>newAttribute.nodeName) {
62
+ diff += compare.attribute.missingNew(newAttribute);
63
+ n++;
64
+ continue;
65
+ }
66
+ diff+= compare.attribute.missingOld(oldAttribute);
67
+ o++;
68
+ }
69
+ for (o=o;oldAttributes.length;o++) diff += compare.attribute.missingOld(oldAttributes[o]);
70
+ for (n=n;newAttributes.length;n++) diff += compare.attribute.missingANew(newAttributes[n]);
71
+ o=0;n=0;
72
+ while (o<oldNodes.length || n<newNodes.length) {
73
+ var oldNode=oldNodes[o]; newNode=newNodes[n];
74
+ if(compare.node.isSameElement(oldNode,newNode)) {
75
+ diff+=compareNodes(oldNode,newNode,compare);
76
+ n++;o++;
77
+ continue;
78
+ }
79
+ for (i=o;i<oldNodes.length;i++) // search for same element
80
+ if(compare.node.isSameElement(oldNodes[i],newNode)) break;
81
+ for (j=n;j<newNodes.length;j++) // search for same element
82
+ if(compare.node.isSameElement(oldNode,newNodes[j])) break;
83
+
84
+ if(i>=oldNodes.length) i=9999;
85
+ if(j>=newNodes.length) j=9999;
86
+ if((i-o)>(j-n))
87
+ for (n=n;n<j;n++) compare.node.missingNew(newNodes[n]);
88
+ else
89
+ for (o=o;o<i;o++) compare.node.missingOld(oldNodes[o]);
90
+ continue;
91
+ }
92
+ for (o=o;o<oldNodes.length;o++) compare.node.missingOld(oldNodes[o]);
93
+ for (n=n;n<newNodes.length;n++) compare.node.missingNew(newNodes[n]);
94
+ }
95
+