/** * * @param {JSON} obj JSON object on which to replace a specific key. * @param {String} oldKey is the old key in the JSON to be renamed to newKey * @param {String} newKey is the key that should replace the oldKey * usage: myjson.forEach((obj) => renameKey(obj, "oldkey", "newkey")); */ function renameKey(obj, oldKey, newKey) { obj[newKey] = obj[oldKey]; delete obj[oldKey]; } /** * * @param {Array} arr is the Array to be converted into a JSON * @returns {JSON} stringToJsonObject */ function convertArray2JSON(arr) { var arrayToString = JSON.stringify(Object.assign({}, arr)); // convert array to string var stringToJsonObject = JSON.parse(arrayToString); // convert string to json object return stringToJsonObject; } /** * * @param {Array} array containing dates of type Date * @param {Date} date date to look for in array * @returns postition of the array where the date was matched */ export const whereIsDateInArray = function(array, date) { const DAY = date.getDate(); const MONTH = date.getMonth(); var pos = -1; for (var i = 0; i < array.length; i++) { var day = array[i].getDate(); var month = array[i].getMonth(); if (day === DAY && MONTH === month) { pos = i; } } return pos; } /** * Converts the date string from DD.MM.YYYY obtained from HTML date picker to -> MM.DD.YYYY * @param {String} selctedDate containing a date string in the format DD.MM.YYYY * @returns {String} of the provided date in the format MM.DD.YYYY */ export const switchDayMonth_inDate = function(selectedDate) { var splitedString = selectedDate.split('.'); var newDate = []; newDate.push(splitedString[1]); newDate.push(splitedString[0]); newDate.push(splitedString[2]); return newDate.join('.');; } /** * Format the response from SensorThings API to make it suitable for heatmap * @param {Array} obsArray Response from SensorThings API as array * @param {Int8} hours Number of hours to aggregate over. If hours=0, * it will be aggregated by date (e.g. all values recorded on 1st of May etc...) * if hours to any number (also hours=24) data will be aggregated over every 24hours, * even if the date changes (e.g. data from 1st of May from 10pm up 9pm on 2nd of May etc.) * @param {String} method Specify how to aggregate date. Use: 'mean' = default, 'sum', 'min' or 'max' * @returns {Array} Aggregated Response */ export const aggregateResponse = function(obsArray, hours, method) { if (!obsArray) return; if (hours < 0) return; // check if we have a defined method or the method specified is accepted, rest is handeled in switch/case below if (method == undefined) method = 'mean'; // convert obsArray to json let jsonFromArr = []; for (var i = 0; i < obsArray.length; i++) { jsonFromArr.push(convertArray2JSON(obsArray[i])); } // rename the keys in the jason jsonFromArr.forEach((obj) => renameKey(obj, "0", "datetime")); let jsonData = jsonFromArr; jsonData.forEach((obj) => renameKey(obj, "1", "temperature")); let newOutput = []; var aggDates = []; var aggregatedVals = []; var vals = []; // store values temporarily to use for processing if (hours == 0) { // i.e. aggregate over one Date / Day var currentDate; var oldDate; for (var d = 0; d < jsonData.length; d++) { let tmpDate = new Date(jsonData[d].datetime); currentDate = tmpDate.getDate(); // gets the day of the month 1...31 if (d === 0) oldDate = currentDate; if (currentDate == oldDate) { vals.push(jsonData[d].temperature); } else { aggDates.push(new Date(tmpDate - 1)); if (vals.length == 0) { aggregatedVals.push(-1); oldDate = currentDate; continue; } switch (method) { case 'mean': aggregatedVals.push(vals.reduce(function(a, b) { return a + b / vals.length; }, -1)); break; case 'sum': aggregatedVals.push(vals.reduce(function(a, b) { return a + b; }, -1)); break; case 'min': aggregatedVals.push(vals.reduce(function(a, b) { return Math.min(a, b); })); break; case 'max': aggregatedVals.push(vals.reduce(function(a, b) { return Math.max(a, b); })); break; default: aggregatedVals.push(vals.reduce(function(a, b) { return a + b / vals.length; }, -1)); } vals = []; // clear the daily value vector vals.push(jsonData[d].temperature); // now push first entry of new day into my temp value vector. } oldDate = currentDate; } // end of for loop // create output to be in the same List format as the original data from obsArray. for (let i = 0; i < aggregatedVals.length; i++) { newOutput.push([aggDates[i].toISOString(), aggregatedVals[i]]); } } else { // i.e. aggregate over X hours, irrespective of the day. let cnt = 0; let cumHours = 0; for (var d = 0; d < jsonData.length; d++) { if (cnt < hours) { vals.push(jsonData[d].temperature); cnt++; } else { cumHours += cnt; cnt = 0; aggDates.push(cumHours); if (vals.length == 0) { aggregatedVals.push(-1); continue; } switch (method) { case 'mean': aggregatedVals.push(vals.reduce(function(a, b) { return a + b / vals.length; }, -1)); break; case 'sum': aggregatedVals.push(vals.reduce(function(a, b) { return a + b; }, -1)); break; case 'min': aggregatedVals.push(vals.reduce(function(a, b) { return Math.min(a, b); }, )); break; case 'max': aggregatedVals.push(vals.reduce(function(a, b) { return Math.max(a, b); }, )); break; default: aggregatedVals.push(vals.reduce(function(a, b) { return a + b / vals.length; }, -1)); } vals = []; // clear the daily value vector vals.push(jsonData[d].temperature); // now push first entry of new day into my temp value vector. cnt++; } oldDate = currentDate; } // end of for loop // create output to be in the same List format as the original data from obsArray. for (let i = 0; i < aggregatedVals.length; i++) { newOutput.push([aggDates[i], aggregatedVals[i]]); } } // end else // return newOutput; return { originalFormat: newOutput, aggDates: aggDates, aggVals: aggregatedVals }; }