UNPKG

qrt

Version:
186 lines (159 loc) 4.37 kB
'use strict'; const { deg2rad, rad2deg } = require('./utils.js'); const { parseRaw, parseAvgKey } = require('./vendor/qart'); module.exports = { /** * @param {Array} [directions] - array of directions in degrees * @param {Array} [input] - array of arrays containing * wind direction and speed * @param {Array} [speed] - array of speeds in m/s * @return {number} * * @example * * avgWind([360, 45, 90]); * avgWind([[360, 1.48], [45, 1.78], [90, 3.44]]); * avgWind([360, 45, 90], [1.48, 1.78, 3.44]); */ windDirectionMean: (...args) => { let sinSum = 0; let cosSum = 0; if (args.length === 1) { if (!Array.isArray(args[0])) { throw new TypeError(`Expected a array, got ${typeof args[0]}`); } // The argument is an array of arrays if (Array.isArray(args[0][0])) { args[0].forEach(([direction, speed]) => { sinSum += speed * Math.sin(deg2rad(direction)); cosSum += speed * Math.cos(deg2rad(direction)); }); } else { // Only an array of directions was passed args[0].forEach((direction) => { sinSum += Math.sin(deg2rad(direction)); cosSum += Math.cos(deg2rad(direction)); }); } } // Expect first argument to be an array of directions // and the second to be of speed if (args.length === 2) { if (!Array.isArray(args[1])) { throw new TypeError(`Expected a array, got ${typeof args[0]}`); } const directions = args[0]; const speeds = args[1]; directions.forEach((direction, index) => { const speed = speeds[index]; sinSum += speed * Math.sin(deg2rad(direction)); cosSum += speed * Math.cos(deg2rad(direction)); }); } return (rad2deg(Math.atan2(sinSum, cosSum)) + 360) % 360; }, /** * Air Quality Index */ airQualityIndex(med_PM10, med_PM25, med_NO2, med_O3, med_SO2) { function calcSensorAqi(aqiRules, sensorValue) { return Object.entries(aqiRules).reduce( (accumulator, [aqi, range]) => { const [min, max] = range; if (sensorValue > min && sensorValue < max) { accumulator = Number(aqi); } return accumulator; }, 5 ); } // AQI: [min, max] const rules = { PM10: { 5: [0, 21], 4: [21, 36], 3: [36, 51], 2: [51, 101], 1: [101, Infinity], }, PM25: { 5: [0, 11], 4: [11, 21], 3: [21, 26], 2: [26, 51], 1: [51, Infinity], }, NO2: { 5: [0, 40], 4: [40, 101], 3: [101, 201], 2: [201, 401], 1: [401, Infinity], }, SO2: { 5: [0, 100], 4: [101, 201], 3: [201, 351], 2: [351, 501], 1: [501, Infinity], }, }; const aqi = { PM10: calcSensorAqi(rules.PM10, med_PM10), PM25: calcSensorAqi(rules.PM25, med_PM25), NO2: calcSensorAqi(rules.NO2, med_NO2), SO2: calcSensorAqi(rules.SO2, med_SO2), }; const [AQI_POL, AQI_GLOBAL] = Object.entries(aqi).reduce( (accumulator, current) => { const [accSensor, accValue] = accumulator; const [currSensor, currValue] = current; if (accValue > currValue) { accumulator = current; } return accumulator; }, ['PM10', aqi.PM10] ); return { AQI_POL, AQI_GLOBAL }; }, noiseMean(samples) { // Create a new array dividing each value by 10 // and anti-log the value 10^x and them add together all the values const total = samples .map((sample) => sample / 10) .map((sample) => Math.pow(10, sample)) .reduce((acc, curr) => (acc += curr), 0); // Divide the total by the number of samples // base 10 log this number and multiply it by 10 return 10 * Math.log10(total / samples.length); }, /* * Takes a set of coordinates and return a bounding box * * @name bbox * @param {Array} coordinates - Two-dimensional array with latitude and longitudes * @return {Array} A array containing min Latitude, min Longitude, max Latitude, max Longitude */ bbox(coordinates) { const latitudes = coordinates.reduce((acc, curr) => { acc.push(curr[0]); return acc; }, []); const longitudes = coordinates.reduce((acc, curr) => { acc.push(curr[1]); return acc; }, []); const minLat = Math.min(...latitudes); const maxLat = Math.max(...latitudes); const minLong = Math.min(...longitudes); const maxLong = Math.max(...longitudes); return [minLat, minLong, maxLat, maxLong]; }, // QART tools qart: { parseRaw, parseAvgKey, }, };