"use strict"; import { BASE_URL, QUERY_PARAMS_COMBINED, } from "./src_modules/baseUrlPlusQueryParams.mjs"; import { calculateVorlaufMinusRuecklaufTemperature } from "./src_modules/calculateTemperatureDiff.mjs"; import { getMetadataPlusObservationsFromSingleOrMultipleDatastreams } from "./src_modules/fetchData.mjs"; import { formatDatastreamMetadataForChart, extractPropertiesFromFormattedDatastreamMetadata, } from "./src_modules/fetchedDataProcessing.mjs"; import { formatSensorThingsApiResponseForLineOrColumnChart, drawLineChartHighcharts, } from "./src_modules/chartLine.mjs"; import { drawColumnChartHighcharts } from "./src_modules/chartColumn.mjs"; import { showLoadingSpinner, hideLoadingSpinner, } from "./src_modules/loadingIndicator.mjs"; import { vanillaSelectBox } from "./thirdparty/vanillaSelectBox.mjs"; import { extractObservationsWithinDatesInterval, extractUniqueCalendarDatesFromTimestamp, } from "./src_modules/aggregateHelpers.mjs"; import { splitMultipleOptionsTextDelimitedBySlash, getSelectedOptionsFromAllDropDownLists, checkIfSelectedOptionsContainTemperatureDifference, deleteTemperatureDifferenceOptions, extractTemperatureDifferenceOptions, extractBuildingPlusSamplingRate, checkIfChartRequiresRawObservations, getAbbreviationsForSelectedOptionsFromAllDropDownLists, } from "./src_modules/dropDownListHelpers.mjs"; import { drawHeatmapBasedOnSelectedOptions, drawScatterPlotFromChartSelection, drawLineChartBasedOnSelectedAggregationOptions, drawColumnChartBasedOnSelectedAggregationOptions, } from "./src_modules/dropDownListProcessing.mjs"; /** * Use the `vanillaDropDown` library to style the buildings & data points drop down list * * @returns {undefined} */ const styleBuildingsDataPointsDropDown = function () { // Create our dropdown list using `vanillaSelectBox`; supports the selection of multiple options new vanillaSelectBox("#drop-down--bldg-data-point", { "disableSelectAll": true, "maxSelect": 5, "placeHolder": "--Select--", "search": false, }); }; /** * Use the `vanillaDropDown` library to style the aggregation type drop down list * * @returns {undefined} */ const styleAggregationDropDown = function () { // Create our dropdown list using `vanillaSelectBox` new vanillaSelectBox("#drop-down--aggregation-type", { "disableSelectAll": true, "maxSelect": 1, "placeHolder": "--Select--", "search": false, }); }; /** * Use the `vanillaDropDown` library to style the third sampling rate down list * * @returns {undefined} */ const styleSamplingRateDropDown = function () { // Create our dropdown list using `vanillaSelectBox` new vanillaSelectBox("#drop-down--sampling-rate", { "disableSelectAll": true, "maxSelect": 1, "placeHolder": "--Select--", "search": false, }); }; /** * Use the `vanillaDropDown` library to style the chart type drop down list * * @returns {undefined} */ const styleChartTypeDropDown = function () { // Create our dropdown list using `vanillaSelectBox` new vanillaSelectBox("#drop-down--chart-type", { "disableSelectAll": true, "maxSelect": 1, "placeHolder": "--Select--", "search": false, }); }; /** * Callback function that wraps the logic of populating the linked drop down lists. * Will run on `DOMContentLoaded` event * * @returns {undefined} */ const afterDocumentLoads = function () { styleBuildingsDataPointsDropDown(); styleAggregationDropDown(); styleSamplingRateDropDown(); styleChartTypeDropDown(); }; /** * Callback function that draws a chart using options from the drop-down list that * have been selected by a user. * Will be run when the user clicks a button * * @async * @returns {undefined} undefined */ const drawChartUsingSelectedOptions = async function () { try { const selectedOptionsAllDropDownLists = getSelectedOptionsFromAllDropDownLists(); // Note: The aggregation type + duration and chart type are the second and // fourth elements respectively, we have ignored the first and third elements const [, selectedAggregationTypeDurationArr, , selectedChartTypeArr] = selectedOptionsAllDropDownLists; // Create an array of aggregation type and duration const selectedAggregationTypeDurationSplitNestedArr = splitMultipleOptionsTextDelimitedBySlash( selectedAggregationTypeDurationArr ); // Separate the aggregation type and the aggregation duration strings const [selectedAggregationTypeDurationSplitArr] = selectedAggregationTypeDurationSplitNestedArr; const [selectedAggregationTypeArr, selectedAggregationDuration] = selectedAggregationTypeDurationSplitArr; // Array of building(s) + data point(s) + sampling rate const selectedBuildingsDataPointsSamplingRateAbbrev = getAbbreviationsForSelectedOptionsFromAllDropDownLists( selectedOptionsAllDropDownLists ); // Create copies of the arrays of building(s) + data point(s) + sampling rate const selectedBuildingsDataPointsSamplingRateAbbrevNonComputedCopy = [ ...selectedBuildingsDataPointsSamplingRateAbbrev, ]; const selectedBuildingsDataPointsSamplingRateAbbrevComputedCopy = [ ...selectedBuildingsDataPointsSamplingRateAbbrev, ]; // Check if we have non-computed const selectedBuildingsDataPointsSamplingRateAbbrevNonComputed = checkIfSelectedOptionsContainTemperatureDifference( selectedBuildingsDataPointsSamplingRateAbbrevNonComputedCopy ) ? deleteTemperatureDifferenceOptions( selectedBuildingsDataPointsSamplingRateAbbrevNonComputedCopy ) : selectedBuildingsDataPointsSamplingRateAbbrevNonComputedCopy; // Check if we have computed / dT const selectedBuildingsDataPointsSamplingRateAbbrevComputed = checkIfSelectedOptionsContainTemperatureDifference( selectedBuildingsDataPointsSamplingRateAbbrevComputedCopy ) ? extractTemperatureDifferenceOptions( selectedBuildingsDataPointsSamplingRateAbbrevComputedCopy ) : []; // Display the loading indicator showLoadingSpinner(); // Fetch the observations + metadata / non-computed const observationsPlusMetadataNonComputed = selectedBuildingsDataPointsSamplingRateAbbrevNonComputed.length === 0 ? [[], []] : await getMetadataPlusObservationsFromSingleOrMultipleDatastreams( BASE_URL, QUERY_PARAMS_COMBINED, selectedBuildingsDataPointsSamplingRateAbbrevNonComputed ); // Fetch the observations + metadata / computed (dT) const observationsPlusMetadataComputed = selectedBuildingsDataPointsSamplingRateAbbrevComputed.length === 0 ? [[], []] : await calculateVorlaufMinusRuecklaufTemperature( BASE_URL, QUERY_PARAMS_COMBINED, extractBuildingPlusSamplingRate( selectedBuildingsDataPointsSamplingRateAbbrevComputed ) ); // Extract the combined arrays for observations and metadata / non-computed const [observationsNestedNonComputedArr, metadataNestedNonComputedArr] = observationsPlusMetadataNonComputed; // Extract the combined arrays for observations and metadata / computed (dT) const [observationsNestedComputedArr, metadataNestedComputedArr] = observationsPlusMetadataComputed; // Create a combined array of observations and metadata const observationsPlusMetadataCombined = [ [...observationsNestedNonComputedArr, ...observationsNestedComputedArr], [...metadataNestedNonComputedArr, ...metadataNestedComputedArr], ]; const [observationsComboNestedArr, metadataComboNestedArr] = observationsPlusMetadataCombined; // Create formatted array(s) for metadata - used by ALL chart types const formattedMetadataNestedArr = metadataComboNestedArr.map( (metadataObj) => formatDatastreamMetadataForChart(metadataObj) ); // Extract the formatted metadata properties - used by ALL chart types const extractedFormattedDatastreamProperties = extractPropertiesFromFormattedDatastreamMetadata( formattedMetadataNestedArr, false ); // The formatted abbreviations array is nested const [selectedBuildingsDataPointsSamplingRateAbbrevArr] = selectedBuildingsDataPointsSamplingRateAbbrev; // Extract the formatted sampling rate string - used by ALL chart types const [, , selectedSamplingRateAbbrev] = selectedBuildingsDataPointsSamplingRateAbbrevArr; // User-specified start date and end date for aggregation - used by MULTIPLE chart types const aggregationStartDate = "2020-01-01"; const aggregationEndDate = "2020-12-31"; // Extract observations within the user-specified start and end date - used by MULTIPLE chart types const observationsAggregationNestedArr = observationsComboNestedArr.map( (obsArr) => extractObservationsWithinDatesInterval( obsArr, "60min", aggregationStartDate, aggregationEndDate ) ); // Unique calendar dates - used by MULTIPLE chart types const uniqueCalendarDatesNestedArr = observationsAggregationNestedArr.map( (observationsArr) => extractUniqueCalendarDatesFromTimestamp(observationsArr) ); selectedChartTypeArr.forEach((selectedChartType) => { if (selectedChartType === "Heatmap") { // We are interested in raw observations if ( checkIfChartRequiresRawObservations( selectedAggregationTypeArr, selectedAggregationDuration ) ) { drawHeatmapBasedOnSelectedOptions( selectedBuildingsDataPointsSamplingRateAbbrev, observationsComboNestedArr, extractedFormattedDatastreamProperties ); } else { throw new Error( "This type of chart (Heatmap) does not support aggregated results" ); } } if (selectedChartType === "Scatter Plot") { // We are interested in raw observations if ( checkIfChartRequiresRawObservations( selectedAggregationTypeArr, selectedAggregationDuration ) ) { drawScatterPlotFromChartSelection( selectedBuildingsDataPointsSamplingRateAbbrev, observationsComboNestedArr, extractedFormattedDatastreamProperties ); } else { throw new Error( "This type of chart (Scatter Plot) does not support aggregated results" ); } } if (selectedChartType === "Line") { // We are interested in raw observations or aggregated observations // Raw observations if (selectedAggregationTypeArr === "None (raw data)") { // Create formatted array(s) for observations const formattedRawObservationsLineChartNestedArr = observationsComboNestedArr.map((observationsArr) => formatSensorThingsApiResponseForLineOrColumnChart(observationsArr) ); drawLineChartHighcharts( formattedRawObservationsLineChartNestedArr, extractedFormattedDatastreamProperties ); } // Aggregated observations else { drawLineChartBasedOnSelectedAggregationOptions( selectedAggregationTypeArr, selectedAggregationDuration, observationsAggregationNestedArr, selectedSamplingRateAbbrev, uniqueCalendarDatesNestedArr, formattedMetadataNestedArr ); } } if (selectedChartType === "Column") { // We are interested in raw observations or aggregated observations // Raw observations if (selectedAggregationTypeArr === "None (raw data)") { // Create formatted array(s) for observations const formattedRawObservationsColumnChartNestedArr = observationsComboNestedArr.map((observationsArr) => formatSensorThingsApiResponseForLineOrColumnChart(observationsArr) ); drawColumnChartHighcharts( formattedRawObservationsColumnChartNestedArr, extractedFormattedDatastreamProperties ); } // Aggregated observations else { drawColumnChartBasedOnSelectedAggregationOptions( selectedAggregationTypeArr, selectedAggregationDuration, observationsAggregationNestedArr, selectedSamplingRateAbbrev, uniqueCalendarDatesNestedArr, formattedMetadataNestedArr ); } } }); } catch (err) { console.error(err); } finally { // Hide the loading indicator hideLoadingSpinner(); } }; document.addEventListener("DOMContentLoaded", afterDocumentLoads); document .querySelector("#btn-draw-chart") .addEventListener("click", drawChartUsingSelectedOptions);