async function readFile(path, callback) { function reading() { fs.readFile(path, 'utf8', function(err, rawData) { if (err) { console.error(err); return; }else{ if(callback) { callback(rawData); } } }); } if(fs.existsSync(path)) { reading(); }else{ console.error('File does not exist: ' + path); } } function loadDataFromFile(path, callback) { var rawData, parsedData; async function parseData(rawData) { return new Promise((resolve, reject) => { parsedData = JSON.parse(rawData); if(callback) { callback(parsedData); } resolve(); }); } return readFile(path, parseData); } const findClosest = (arr, num) => { const creds = arr.reduce((acc, val, ind) => { let { diff, index } = acc; const difference = Math.abs(val["A"] - num); if(difference < diff){ diff = difference; index = ind; }; return { diff, index }; }, { diff: Infinity, index: -1 }); return arr[creds.index]; }; var makeObjective = function(targetFunc,xlist,ylist) { var objective = function(params) { var total = 0.0; for(var i=0; i < xlist.length; ++i) { var resultThisDatum = targetFunc(params, xlist[i]); var delta = resultThisDatum - ylist[i]; total += (delta*delta); } return total; }; return objective; }; var cubic = function(params,x) { return params[0] * x*x*x + params[1] * x*x + params[2] * x + params[3]; }; var linear = function(params, x) { return params[0]*x + params[1]; }; function SquareFitter() { this.count = 0; this.sumX = 0; this.sumX2 = 0; this.sumX3 = 0; this.sumX4 = 0; this.sumY = 0; this.sumXY = 0; this.sumX2Y = 0; } SquareFitter.prototype = { 'add': function(x, y) { this.count++; this.sumX += x; this.sumX2 += x*x; this.sumX3 += x*x*x; this.sumX4 += x*x*x*x; this.sumY += y; this.sumXY += x*y; this.sumX2Y += x*x*y; }, 'project': function(x) { var det = this.count*this.sumX2*this.sumX4 - this.count*this.sumX3*this.sumX3 - this.sumX*this.sumX*this.sumX4 + 2*this.sumX*this.sumX2*this.sumX3 - this.sumX2*this.sumX2*this.sumX2; var offset = this.sumX*this.sumX2Y*this.sumX3 - this.sumX*this.sumX4*this.sumXY - this.sumX2*this.sumX2*this.sumX2Y + this.sumX2*this.sumX3*this.sumXY + this.sumX2*this.sumX4*this.sumY - this.sumX3*this.sumX3*this.sumY; var scale = -this.count*this.sumX2Y*this.sumX3 + this.count*this.sumX4*this.sumXY + this.sumX*this.sumX2*this.sumX2Y - this.sumX*this.sumX4*this.sumY - this.sumX2*this.sumX2*this.sumXY + this.sumX2*this.sumX3*this.sumY; var accel = this.sumY*this.sumX*this.sumX3 - this.sumY*this.sumX2*this.sumX2 - this.sumXY*this.count*this.sumX3 + this.sumXY*this.sumX2*this.sumX - this.sumX2Y*this.sumX*this.sumX + this.sumX2Y*this.count*this.sumX2; return (offset + x*scale + x*x*accel) / det; } }; function squareProject(data) { var fitter = new SquareFitter(); for(var i = 0; i < data.length; i++) { console.log(i, data[i]); fitter.add(i, data[i]); } return fitter; } var getDateFromDayNum = function(dayNum, year){ var date = new Date(); if(year) { date.setFullYear(year); } date.setMonth(0); date.setDate(0); var timeOfFirst = date.getTime(); // this is the time in milliseconds of 1/1/YYYY var dayMilli = 1000 * 60 * 60 * 24; var dayNumMilli = dayNum * dayMilli; date.setTime(timeOfFirst + dayNumMilli); return date; } function degToRad(degrees) { let pi = Math.PI; return degrees * (pi / 180); } function radToDeg(radians) { var pi = Math.PI; return radians * (180 / pi); } function getTextWidth(text, font) { // re-use canvas object for better performance text = text.replace("&sup", ""); text = text.replace("·", ""); var canvas = getTextWidth.canvas || (getTextWidth.canvas = document.createElement("canvas")); var context = canvas.getContext("2d"); context.font = font; var metrics = context.measureText(text); return metrics.width; } function daysInMonth(month, year) { return new Date(year, month, 0).getDate(); } function colorLuminance(color, luminosity) { // validate hex string color = new String(color).replace(/[^0-9a-f]/gi, ''); if (color.length < 6) { color = color[0]+ color[0]+ color[1]+ color[1]+ color[2]+ color[2]; } luminosity = luminosity || 0; // convert to decimal and change luminosity var newColor = "#", c, i, black = 0, white = 255; for (i = 0; i < 3; i++) { c = parseInt(color.substr(i*2,2), 16); c = Math.round(Math.min(Math.max(black, c + (luminosity * white)), white)).toString(16); newColor += ("00"+c).substr(c.length); } return newColor; /*if (color.length >6) { color= color.substring(1,color.length)} var rgb = parseInt(color, 16); var r = Math.abs(((rgb >> 16) & 0xFF)+v); if (r>255) r=r-(r-255); var g = Math.abs(((rgb >> 8) & 0xFF)+v); if (g>255) g=g-(g-255); var b = Math.abs((rgb & 0xFF)+v); if (b>255) b=b-(b-255); r = Number(r < 0 || isNaN(r)) ? 0 : ((r > 255) ? 255 : r).toString(16); if (r.length == 1) r = '0' + r; g = Number(g < 0 || isNaN(g)) ? 0 : ((g > 255) ? 255 : g).toString(16); if (g.length == 1) g = '0' + g; b = Number(b < 0 || isNaN(b)) ? 0 : ((b > 255) ? 255 : b).toString(16); if (b.length == 1) b = '0' + b; return "#" + r + g + b;*/ /* // validate hex string hex = String(hex).replace(/[^0-9a-f]/gi, ''); if (hex.length < 6) { hex = hex[0]+hex[0]+hex[1]+hex[1]+hex[2]+hex[2]; } lum = lum || 0; // convert to decimal and change luminosity var rgb = "#", c, i; for (i = 0; i < 3; i++) { c = parseInt(hex.substr(i*2,2), 16); c = Math.round(Math.min(Math.max(0, c + (c * lum)), 255)).toString(16); rgb += ("00"+c).substr(c.length); } return rgb; */ } function parseHTML(html) { var t = document.createElement('template'); t.innerHTML = html; return t.content.cloneNode(true); } function parseSVG(svg) { var parser = new DOMParser(); var doc = parser.parseFromString(svg, "image/svg+xml"); return doc; }