"use strict"; import { BASE_URL, QUERY_PARAMS_COMBINED, } from "./src_modules/baseUrlPlusQueryParams.mjs"; import { calculateVorlaufMinusRuecklaufTemperature } from "./src_modules/calculateTemperatureDiff.mjs"; import { getMetadataPlusObservationsFromSingleOrMultipleDatastreams, isFetchingRawMetadataPlusObservationsSuccessful, } from "./src_modules/fetchData.mjs"; import { formatDatastreamMetadataForChart, extractPropertiesFromFormattedDatastreamMetadata, } from "./src_modules/fetchedDataProcessing.mjs"; import { showLoadingSpinner, hideLoadingSpinner, disableDrawChartButton, enableDrawChartButton, } from "./src_modules/loadingIndicator.mjs"; import { styleAllDropDownLists } from "./src_modules/dropDownListStyling.mjs"; import { extractObservationsWithinDatesInterval, extractUniqueCalendarDatesFromTimestamp, } from "./src_modules/aggregateHelpers.mjs"; import { splitMultipleOptionsTextDelimitedBySlash, getSelectedOptionsFromAllDropDownLists, checkIfSelectedOptionsContainTemperatureDifference, deleteTemperatureDifferenceOptions, extractTemperatureDifferenceOptions, extractBuildingPlusSamplingRate, checkIfSelectedBuildingDataPointsOptionsAreValid, checkIfSelectedAggregationOptionsAreValid, getAbbreviationsForSelectedOptionsFromAllDropDownLists, } from "./src_modules/dropDownListHelpers.mjs"; import { drawColumnChartBasedOnSelectedOptions } from "./src_modules/dropDownListChartColumn.mjs"; import { drawHeatmapBasedOnSelectedOptions } from "./src_modules/dropDownListChartHeatmap.mjs"; import { drawLineChartBasedOnSelectedOptions } from "./src_modules/dropDownListChartLine.mjs"; import { drawScatterPlotBasedOnSelectedOptions } from "./src_modules/dropDownListChartScatterPlot.mjs"; /** * Callback function that wraps the logic of populating the linked drop down lists. * Will run on `DOMContentLoaded` event * * @returns {undefined} */ const afterDocumentLoads = function () { styleAllDropDownLists(); }; /** * 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 { // Note: The chart type amd aggregation type + duration are the first and // third elements respectively, we have ignored the second and fourth elements const [selectedChartTypeArr, , selectedAggregationTypeDurationArr] = getSelectedOptionsFromAllDropDownLists(); // Note: the resulting array is nested, it only has one sub-array // Separate the aggregation type and the aggregation duration strings const [[selectedAggregationType, selectedAggregationDuration]] = splitMultipleOptionsTextDelimitedBySlash( selectedAggregationTypeDurationArr ); // Array of building(s) + data point(s) + sampling rate const selectedBuildingsDataPointsSamplingRateAbbrevNestedArr = getAbbreviationsForSelectedOptionsFromAllDropDownLists( getSelectedOptionsFromAllDropDownLists() ); // The formatted abbreviations array is nested, we are interested in the first sub-array // We assume that all the phenomena have the same sampling rate // Extract the formatted sampling rate string - used by ALL chart types const [[, , selectedSamplingRateAbbrev]] = selectedBuildingsDataPointsSamplingRateAbbrevNestedArr; // User-specified start date and end date for aggregation - used by MULTIPLE chart types const AGGREGATION_START_DATE = "2020-01-01"; const AGGREGATION_STOP_DATE = "2020-12-31"; // The values of these references is either equal to `true` or an error will be thrown // We would like the errors to be thrown at this point before we begin performing any asynchronous tasks const selectedAggregationOptionsAreValid = checkIfSelectedAggregationOptionsAreValid( selectedChartTypeArr, selectedAggregationType, selectedAggregationDuration ); const selectedBuildingDataPointsOptionsAreValid = checkIfSelectedBuildingDataPointsOptionsAreValid( selectedChartTypeArr, selectedBuildingsDataPointsSamplingRateAbbrevNestedArr ); // Check whether we have dT (temperature difference), if so, delete these options, // then compute abbreviations for raw observations const selectedBuildingsDataPointsSamplingRateAbbrevRawObsArr = checkIfSelectedOptionsContainTemperatureDifference( selectedBuildingsDataPointsSamplingRateAbbrevNestedArr ) ? deleteTemperatureDifferenceOptions( selectedBuildingsDataPointsSamplingRateAbbrevNestedArr ) : selectedBuildingsDataPointsSamplingRateAbbrevNestedArr; // Check if we have dT (temperature difference), if so, extract these options const selectedBuildingsDataPointsSamplingRateAbbrevTempDiffArr = checkIfSelectedOptionsContainTemperatureDifference( selectedBuildingsDataPointsSamplingRateAbbrevNestedArr ) ? extractTemperatureDifferenceOptions( selectedBuildingsDataPointsSamplingRateAbbrevNestedArr ) : []; // Display the loading indicator showLoadingSpinner(); // Disable the 'draw chart' button disableDrawChartButton(); // Fetch and extract the observations + metadata / raw observations const [observationsRawNestedArr, metadataRawNestedArr] = selectedBuildingsDataPointsSamplingRateAbbrevRawObsArr.length === 0 ? [[], []] : await getMetadataPlusObservationsFromSingleOrMultipleDatastreams( BASE_URL, QUERY_PARAMS_COMBINED, selectedBuildingsDataPointsSamplingRateAbbrevRawObsArr ); // Fetch and extract the observations + metadata / temperature difference (dT) const [observationsTempDiffNestedArr, metadataTempDiffNestedArr] = selectedBuildingsDataPointsSamplingRateAbbrevTempDiffArr.length === 0 ? [[], []] : await calculateVorlaufMinusRuecklaufTemperature( BASE_URL, QUERY_PARAMS_COMBINED, extractBuildingPlusSamplingRate( selectedBuildingsDataPointsSamplingRateAbbrevTempDiffArr ) ); // Create and extract the combined observations and metadata const [observationsCombinedNestedArr, metadataCombinedNestedArr] = [ [...observationsRawNestedArr, ...observationsTempDiffNestedArr], [...metadataRawNestedArr, ...metadataTempDiffNestedArr], ]; // Create formatted array(s) for metadata - used by ALL chart types const formattedMetadataNestedArr = metadataCombinedNestedArr.map( (metadataObj) => formatDatastreamMetadataForChart(metadataObj) ); // Extract the formatted metadata properties for the raw observations - used by ALL chart types const rawObsExtractedFormattedDatastreamProperties = extractPropertiesFromFormattedDatastreamMetadata( formattedMetadataNestedArr, false ); // Create final array of observations- used by MULTIPLE chart types // If we are performing aggregation, it was envisioned that the user would // select observations that fall within a start and end date const observationsComboNestedFinalArr = selectedAggregationType === "None (raw data)" ? observationsCombinedNestedArr : observationsCombinedNestedArr.map((observationsArr) => extractObservationsWithinDatesInterval( observationsArr, selectedSamplingRateAbbrev, AGGREGATION_START_DATE, AGGREGATION_STOP_DATE ) ); // Unique calendar dates - used by MULTIPLE chart types const uniqueCalendarDatesNestedArr = observationsComboNestedFinalArr.map( (observationsArr) => extractUniqueCalendarDatesFromTimestamp(observationsArr) ); for (const selectedChartType of selectedChartTypeArr) { switch (selectedChartType) { case "Heatmap": if ( selectedAggregationOptionsAreValid && selectedBuildingDataPointsOptionsAreValid ) { drawHeatmapBasedOnSelectedOptions( observationsComboNestedFinalArr, rawObsExtractedFormattedDatastreamProperties ); } break; case "Scatter Plot": if ( selectedAggregationOptionsAreValid && selectedBuildingDataPointsOptionsAreValid ) { drawScatterPlotBasedOnSelectedOptions( observationsComboNestedFinalArr, rawObsExtractedFormattedDatastreamProperties ); } break; case "Line": drawLineChartBasedOnSelectedOptions( selectedAggregationType, selectedAggregationDuration, observationsComboNestedFinalArr, selectedSamplingRateAbbrev, uniqueCalendarDatesNestedArr, formattedMetadataNestedArr ); break; case "Column": drawColumnChartBasedOnSelectedOptions( selectedAggregationType, selectedAggregationDuration, observationsComboNestedFinalArr, selectedSamplingRateAbbrev, uniqueCalendarDatesNestedArr, formattedMetadataNestedArr ); break; default: throw new Error("None of the chart type options were selected"); } } } catch (err) { console.error(err); // Display a dialog window with the error message alert(err); } finally { // Enable the 'draw chart' button enableDrawChartButton(); // Hide the loading indicator hideLoadingSpinner(); } }; document.addEventListener("DOMContentLoaded", afterDocumentLoads); document .querySelector("#btn-draw-chart") .addEventListener("click", drawChartUsingSelectedOptions);