"use strict"; import { extractObservationValuesWithinDatesInterval, extractObservationValuesWithinMonthInterval, } from "./aggregateHelpers.mjs"; /** * Remove `null` observation values from an array of observation values * * @param {Array} obsValuesArr An array of observation values * @returns {Array} An array with `null` observation values removed */ const filterOutNullObservationValues = function (obsValuesArr) { return obsValuesArr.filter((obs) => obs !== null); }; /** * Calculate the minimum observation values that fall within a time interval delimited by a start date and end date * @param {Array} obsValuesForDaysIntervalArr An array of observation values that fall within our time interval * @returns {Number} A floating-point number representing the minimum of observation values */ const calculateMinimumObservationValuesWithinDatesInterval = function ( obsValuesForDaysIntervalArr ) { // If the observation value is `null`, skip the calculation return obsValuesForDaysIntervalArr.reduce((previousValue, obsValue) => obsValue === null ? null : Math.min(previousValue, obsValue) ); }; /** * Calculate the maximum observation values that fall within a time interval delimited by a start date and end date * @param {Array} obsValuesForDaysIntervalArr An array of observation values that fall within our time interval * @returns {Number} A floating-point number representing the maximum of observation values */ const calculateMaximumObservationValuesWithinDatesInterval = function ( obsValuesForDaysIntervalArr ) { // If the observation value is `null`, skip the calculation return obsValuesForDaysIntervalArr.reduce((previousValue, obsValue) => obsValue === null ? null : Math.max(previousValue, obsValue) ); }; /** * Calculate the sum of observation values that fall within a time interval delimited by a start date and end date * @param {Array} obsValuesForDaysIntervalArr An array of observation values that fall within our time interval * @returns {Number} A floating-point number representing the sum of observation values */ const calculateSumOfObservationValuesWithinDatesInterval = function ( obsValuesForDaysIntervalArr ) { // Remove the `null` observation values before calculating the sum return filterOutNullObservationValues(obsValuesForDaysIntervalArr).reduce( (previousValue, obsValue) => previousValue + obsValue, 0 ); }; /** * Calculate the average (arithmetic mean) of observation values that fall within a time interval delimited by a start date and end date * @param {Array} obsValuesForDaysIntervalArr An array of observation values that fall within our time interval * @returns {Number} A floating-point number representing the average (arithmetic mean) of observation values */ const calculateAverageOfObservationValuesWithinDatesInterval = function ( obsValuesForDaysIntervalArr ) { // The observation values array should only include non-`null` values return ( calculateSumOfObservationValuesWithinDatesInterval( obsValuesForDaysIntervalArr ) / filterOutNullObservationValues(obsValuesForDaysIntervalArr).length ); }; /** * Calculate the minimum of observation values that fall within a time interval delimited by the first day and last day of a calendar month * @param {Array} obsValuesForMonthIntervalArr An array of observation values that fall within one calendar month * @returns {Number} A floating-point number representing the minimum of observation values within one calendar month */ const calculateMinimumObservationValuesWithinMonthInterval = function ( obsValuesForMonthIntervalArr ) { // If the observation value is `null`, skip the calculation return obsValuesForMonthIntervalArr.reduce((previousValue, obsValue) => obsValue === null ? null : Math.min(previousValue, obsValue) ); }; /** * Calculate the maximum of observation values that fall within a time interval delimited by the first day and last day of a calendar month * @param {Array} obsValuesForMonthIntervalArr An array of observation values that fall within one calendar month * @returns {Number} A floating-point number representing the maximum of observation values within one calendar month */ const calculateMaximumObservationValuesWithinMonthInterval = function ( obsValuesForMonthIntervalArr ) { // If the observation value is `null`, skip the calculation return obsValuesForMonthIntervalArr.reduce((previousValue, obsValue) => obsValue === null ? null : Math.max(previousValue, obsValue) ); }; /** * Calculate the sum of observation values that fall within a time interval delimited by the first day and last day of a calendar month * @param {Array} obsValuesForMonthIntervalArr An array of observation values that fall within one calendar month * @returns {Number} A floating-point number representing the sum of observation values within one calendar month */ const calculateSumOfObservationValuesWithinMonthInterval = function ( obsValuesForMonthIntervalArr ) { // Remove the `null` observation values before calculating the sum return filterOutNullObservationValues(obsValuesForMonthIntervalArr).reduce( (previousValue, obsValue) => previousValue + obsValue, 0 ); }; /** * Calculate the average (arithmetic mean) of observation values that fall within a time interval delimited by the first day and last day of a calendar month * @param {Array} obsValuesForMonthIntervalArr An array of observation values that fall within one calendar month * @returns {Number} A floating-point number representing the average (arithmetic mean) of observation values within one calendar month */ const calculateAverageOfObservationValuesWithinMonthInterval = function ( obsValuesForMonthIntervalArr ) { // The observation values array should only include non-`null` values return ( calculateSumOfObservationValuesWithinMonthInterval( obsValuesForMonthIntervalArr ) / filterOutNullObservationValues(obsValuesForMonthIntervalArr).length ); }; /** * Calculate the minimum of observation values within a time interval delimited by a start date and end date. The time interval may be daily or monthly * @param {Array} obsNestedArr A 1*N array that contains N nested arrays of observations (timestamp + value) * @param {String} samplingRate The sampling rate of observations as a string, e.g. "15min", "60min" * @param {Array} uniqueCalendarDatesOrMonthsArr A 1*N array of unique calendar dates or calendar months strings * @param {String} aggregationInterval The aggregation interval as a string e.g. "daily", "monthly" * @returns {Array} A 1*N array that contains N nested arrays of minimum values */ const calculateMinimumObservationValuesWithinInterval = function ( obsNestedArr, samplingRate, uniqueCalendarDatesOrMonthsArr, aggregationInterval ) { // Calculate minimum values of observations - daily // Note the use of the two nested `map` methods if (aggregationInterval === "daily") { return uniqueCalendarDatesOrMonthsArr.map((uniqueCalendarDatesArr, i) => uniqueCalendarDatesArr.map((uniqueCalendarDate) => calculateMinimumObservationValuesWithinDatesInterval( extractObservationValuesWithinDatesInterval( obsNestedArr[i], samplingRate, uniqueCalendarDate, uniqueCalendarDate ) ) ) ); } // Calculate minimum values of observations - monthly // Note the use of the two nested `map` methods else if (aggregationInterval === "monthly") { return uniqueCalendarDatesOrMonthsArr.map((uniqueCalendarMonthsArr, i) => uniqueCalendarMonthsArr.map((uniqueCalendarMonth) => calculateMinimumObservationValuesWithinMonthInterval( extractObservationValuesWithinMonthInterval( obsNestedArr[i], samplingRate, uniqueCalendarMonth ) ) ) ); } }; /** * Calculate the maximum of observation values within a time interval delimited by a start date and end date. The time interval may be daily or monthly * @param {Array} obsNestedArr A 1*N array that contains N nested arrays of observations (timestamp + value) * @param {String} samplingRate The sampling rate of observations as a string, e.g. "15min", "60min" * @param {Array} uniqueCalendarDatesOrMonthsArr A 1*N array of unique calendar dates or calendar months strings * @param {String} aggregationInterval The aggregation interval as a string e.g. "daily", "monthly" * @returns {Array} A 1*N array that contains N nested arrays of maximum values */ const calculateMaximumObservationValuesWithinInterval = function ( obsNestedArr, samplingRate, uniqueCalendarDatesOrMonthsArr, aggregationInterval ) { // Calculate maximum values of observations - daily // Note the use of the two nested `map` methods if (aggregationInterval === "daily") { return uniqueCalendarDatesOrMonthsArr.map((uniqueCalendarDatesArr, i) => uniqueCalendarDatesArr.map((uniqueCalendarDate) => calculateMaximumObservationValuesWithinDatesInterval( extractObservationValuesWithinDatesInterval( obsNestedArr[i], samplingRate, uniqueCalendarDate, uniqueCalendarDate ) ) ) ); } // Calculate maximum values of observations - monthly // Note the use of the two nested `map` methods else if (aggregationInterval === "monthly") { return uniqueCalendarDatesOrMonthsArr.map((uniqueCalendarMonthsArr, i) => uniqueCalendarMonthsArr.map((uniqueCalendarMonth) => calculateMaximumObservationValuesWithinMonthInterval( extractObservationValuesWithinMonthInterval( obsNestedArr[i], samplingRate, uniqueCalendarMonth ) ) ) ); } }; /** * Calculate the sum of observation values within a time interval delimited by a start date and end date. The time interval may be daily or monthly * @param {Array} obsNestedArr A 1*N array that contains N nested arrays of observations (timestamp + value) * @param {String} samplingRate The sampling rate of observations as a string, e.g. "15min", "60min" * @param {Array} uniqueCalendarDatesOrMonthsArr A 1*N array of unique calendar dates or calendar months strings * @param {String} aggregationInterval The aggregation interval as a string e.g. "daily", "monthly" * @returns {Array} A 1*N array that contains N nested arrays of sum values */ const calculateSumOfObservationValuesWithinInterval = function ( obsNestedArr, samplingRate, uniqueCalendarDatesOrMonthsArr, aggregationInterval ) { // Calculate sum of values of observations - daily // Note the use of the two nested `map` methods if (aggregationInterval === "daily") { return uniqueCalendarDatesOrMonthsArr.map((uniqueCalendarDatesArr, i) => uniqueCalendarDatesArr.map((uniqueCalendarDate) => calculateSumOfObservationValuesWithinDatesInterval( extractObservationValuesWithinDatesInterval( obsNestedArr[i], samplingRate, uniqueCalendarDate, uniqueCalendarDate ) ) ) ); } // Calculate sum of values of observations - monthly // Note the use of the two nested `map` methods else if (aggregationInterval === "monthly") { return uniqueCalendarDatesOrMonthsArr.map((uniqueCalendarMonthsArr, i) => uniqueCalendarMonthsArr.map((uniqueCalendarMonth) => calculateSumOfObservationValuesWithinMonthInterval( extractObservationValuesWithinMonthInterval( obsNestedArr[i], samplingRate, uniqueCalendarMonth ) ) ) ); } }; /** * Calculate the average (arithmetic mean) of observation values within a time interval delimited by a start date and end date. The time interval may be daily or monthly * @param {Array} obsNestedArr A 1*N array that contains N nested arrays of observations (timestamp + value) * @param {String} samplingRate The sampling rate of observations as a string, e.g. "15min", "60min" * @param {Array} uniqueCalendarDatesOrMonthsArr A 1*N array of unique calendar dates or calendar months strings * @param {String} aggregationInterval The aggregation interval as a string e.g. "daily", "monthly" * @returns {Array} A 1*N array that contains N nested arrays of average (arithmetic mean) values */ const calculateAverageOfObservationValuesWithinInterval = function ( obsNestedArr, samplingRate, uniqueCalendarDatesOrMonthsArr, aggregationInterval ) { // Calculate average of values of observations - daily // Note the use of the two nested `map` methods if (aggregationInterval === "daily") { return uniqueCalendarDatesOrMonthsArr.map((uniqueCalendarDatesArr, i) => uniqueCalendarDatesArr.map((uniqueCalendarDate) => calculateAverageOfObservationValuesWithinDatesInterval( extractObservationValuesWithinDatesInterval( obsNestedArr[i], samplingRate, uniqueCalendarDate, uniqueCalendarDate ) ) ) ); } // Calculate average of values of observations - monthly // Note the use of the two nested `map` methods else if (aggregationInterval === "monthly") { return uniqueCalendarDatesOrMonthsArr.map((uniqueCalendarMonthsArr, i) => uniqueCalendarMonthsArr.map((uniqueCalendarMonth) => calculateAverageOfObservationValuesWithinMonthInterval( extractObservationValuesWithinMonthInterval( obsNestedArr[i], samplingRate, uniqueCalendarMonth ) ) ) ); } }; export { calculateMinimumObservationValuesWithinInterval, calculateMaximumObservationValuesWithinInterval, calculateSumOfObservationValuesWithinInterval, calculateAverageOfObservationValuesWithinInterval, };