appChart.js 9.77 KB
Newer Older
Pithon Kabiro's avatar
Pithon Kabiro committed
1
"use strict";
Pithon Kabiro's avatar
Pithon Kabiro committed
2

3
4
5
6
import {
  BASE_URL,
  QUERY_PARAMS_COMBINED,
} from "./src_modules/baseUrlPlusQueryParams.mjs";
7

8
import { calculateVorlaufMinusRuecklaufTemperature } from "./src_modules/calculateTemperatureDiff.mjs";
Pithon Kabiro's avatar
Pithon Kabiro committed
9

10
11
12
13
import {
  getMetadataPlusObservationsFromSingleOrMultipleDatastreams,
  isFetchingRawMetadataPlusObservationsSuccessful,
} from "./src_modules/fetchData.mjs";
Pithon Kabiro's avatar
Pithon Kabiro committed
14

15
import {
16
17
18
  formatDatastreamMetadataForChart,
  extractPropertiesFromFormattedDatastreamMetadata,
} from "./src_modules/fetchedDataProcessing.mjs";
Pithon Kabiro's avatar
Pithon Kabiro committed
19

20
import {
21
22
  showLoadingSpinner,
  hideLoadingSpinner,
23
24
  disableDrawChartButton,
  enableDrawChartButton,
25
} from "./src_modules/loadingIndicator.mjs";
26

27
import { styleAllDropDownLists } from "./src_modules/dropDownListStyling.mjs";
Pithon Kabiro's avatar
Pithon Kabiro committed
28

29
import {
30
  extractObservationsWithinDatesInterval,
31
  extractUniqueCalendarDatesFromTimestamp,
32
33
34
} from "./src_modules/aggregateHelpers.mjs";

import {
35
36
37
38
39
40
  splitMultipleOptionsTextDelimitedBySlash,
  getSelectedOptionsFromAllDropDownLists,
  checkIfSelectedOptionsContainTemperatureDifference,
  deleteTemperatureDifferenceOptions,
  extractTemperatureDifferenceOptions,
  extractBuildingPlusSamplingRate,
41
42
  checkIfSelectedBuildingDataPointsOptionsAreValid,
  checkIfSelectedAggregationOptionsAreValid,
43
44
  getAbbreviationsForSelectedOptionsFromAllDropDownLists,
} from "./src_modules/dropDownListHelpers.mjs";
45

46
import { drawColumnChartBasedOnSelectedOptions } from "./src_modules/dropDownListChartColumn.mjs";
47
48
49

import { drawHeatmapBasedOnSelectedOptions } from "./src_modules/dropDownListChartHeatmap.mjs";

50
import { drawLineChartBasedOnSelectedOptions } from "./src_modules/dropDownListChartLine.mjs";
51

52
import { drawScatterPlotBasedOnSelectedOptions } from "./src_modules/dropDownListChartScatterPlot.mjs";
Pithon Kabiro's avatar
Pithon Kabiro committed
53

54
/**
55
56
57
58
 * Callback function that wraps the logic of populating the linked drop down lists.
 * Will run on `DOMContentLoaded` event
 *
 * @returns {undefined}
59
 */
60
const afterDocumentLoads = function () {
61
  styleAllDropDownLists();
62
63
};

64
/**
65
66
67
68
69
70
 * 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
71
 */
72
const drawChartUsingSelectedOptions = async function () {
73
  try {
74
    // Note: The chart type amd aggregation type + duration are the first and
75
76
    // third elements respectively, we have ignored the second and fourth elements
    const [selectedChartTypeArr, , selectedAggregationTypeDurationArr] =
77
      getSelectedOptionsFromAllDropDownLists();
78

79
80
81
    // Note: the resulting array is nested, it only has one sub-array
    // Separate the aggregation type and the aggregation duration strings
    const [[selectedAggregationType, selectedAggregationDuration]] =
82
83
      splitMultipleOptionsTextDelimitedBySlash(
        selectedAggregationTypeDurationArr
84
85
      );

86
    // Array of building(s) + data point(s) + sampling rate
87
    const selectedBuildingsDataPointsSamplingRateAbbrevNestedArr =
88
      getAbbreviationsForSelectedOptionsFromAllDropDownLists(
89
        getSelectedOptionsFromAllDropDownLists()
90
91
      );

92
93
94
95
96
97
98
99
100
101
    // 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";

102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
    // 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
      );

117
118
    // Check whether we have dT (temperature difference), if so, delete these options,
    // then compute abbreviations for raw observations
119
    const selectedBuildingsDataPointsSamplingRateAbbrevRawObsArr =
120
      checkIfSelectedOptionsContainTemperatureDifference(
121
        selectedBuildingsDataPointsSamplingRateAbbrevNestedArr
122
      )
123
        ? deleteTemperatureDifferenceOptions(
124
            selectedBuildingsDataPointsSamplingRateAbbrevNestedArr
125
          )
126
        : selectedBuildingsDataPointsSamplingRateAbbrevNestedArr;
127

128
    // Check if we have dT (temperature difference), if so, extract these options
129
    const selectedBuildingsDataPointsSamplingRateAbbrevTempDiffArr =
130
      checkIfSelectedOptionsContainTemperatureDifference(
131
        selectedBuildingsDataPointsSamplingRateAbbrevNestedArr
132
133
      )
        ? extractTemperatureDifferenceOptions(
134
            selectedBuildingsDataPointsSamplingRateAbbrevNestedArr
135
136
137
138
139
140
          )
        : [];

    // Display the loading indicator
    showLoadingSpinner();

141
142
143
    // Disable the 'draw chart' button
    disableDrawChartButton();

144
145
    // Fetch and extract the observations + metadata / raw observations
    const [observationsRawNestedArr, metadataRawNestedArr] =
146
      selectedBuildingsDataPointsSamplingRateAbbrevRawObsArr.length === 0
147
148
149
150
        ? [[], []]
        : await getMetadataPlusObservationsFromSingleOrMultipleDatastreams(
            BASE_URL,
            QUERY_PARAMS_COMBINED,
151
            selectedBuildingsDataPointsSamplingRateAbbrevRawObsArr
152
153
          );

154
155
    // Fetch and extract the observations + metadata / temperature difference (dT)
    const [observationsTempDiffNestedArr, metadataTempDiffNestedArr] =
156
      selectedBuildingsDataPointsSamplingRateAbbrevTempDiffArr.length === 0
157
158
159
160
161
        ? [[], []]
        : await calculateVorlaufMinusRuecklaufTemperature(
            BASE_URL,
            QUERY_PARAMS_COMBINED,
            extractBuildingPlusSamplingRate(
162
              selectedBuildingsDataPointsSamplingRateAbbrevTempDiffArr
163
164
165
            )
          );

166
167
    // Create and extract the combined observations and metadata
    const [observationsCombinedNestedArr, metadataCombinedNestedArr] = [
168
169
      [...observationsRawNestedArr, ...observationsTempDiffNestedArr],
      [...metadataRawNestedArr, ...metadataTempDiffNestedArr],
170
    ];
171

172
    // Create formatted array(s) for metadata - used by ALL chart types
173
    const formattedMetadataNestedArr = metadataCombinedNestedArr.map(
174
      (metadataObj) => formatDatastreamMetadataForChart(metadataObj)
175
176
    );

177
    // Extract the formatted metadata properties for the raw observations - used by ALL chart types
178
    const rawObsExtractedFormattedDatastreamProperties =
179
180
      extractPropertiesFromFormattedDatastreamMetadata(
        formattedMetadataNestedArr,
181
        false
182
183
      );

184
185
186
187
188
    // 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)"
189
190
        ? observationsCombinedNestedArr
        : observationsCombinedNestedArr.map((observationsArr) =>
191
192
193
            extractObservationsWithinDatesInterval(
              observationsArr,
              selectedSamplingRateAbbrev,
194
195
              AGGREGATION_START_DATE,
              AGGREGATION_STOP_DATE
196
197
            )
          );
198

199
    // Unique calendar dates - used by MULTIPLE chart types
200
    const uniqueCalendarDatesNestedArr = observationsComboNestedFinalArr.map(
201
202
203
204
      (observationsArr) =>
        extractUniqueCalendarDatesFromTimestamp(observationsArr)
    );

205
    for (const selectedChartType of selectedChartTypeArr) {
206
207
208
209
210
211
212
213
      switch (selectedChartType) {
        case "Heatmap":
          if (
            selectedAggregationOptionsAreValid &&
            selectedBuildingDataPointsOptionsAreValid
          ) {
            drawHeatmapBasedOnSelectedOptions(
              observationsComboNestedFinalArr,
214
              rawObsExtractedFormattedDatastreamProperties
215
            );
216
217
218
219
220
221
222
223
          }
          break;

        case "Scatter Plot":
          if (
            selectedAggregationOptionsAreValid &&
            selectedBuildingDataPointsOptionsAreValid
          ) {
224
            drawScatterPlotBasedOnSelectedOptions(
225
              observationsComboNestedFinalArr,
226
              rawObsExtractedFormattedDatastreamProperties
227
228
229
230
231
            );
          }
          break;

        case "Line":
232
233
234
235
236
237
238
239
          drawLineChartBasedOnSelectedOptions(
            selectedAggregationType,
            selectedAggregationDuration,
            observationsComboNestedFinalArr,
            selectedSamplingRateAbbrev,
            uniqueCalendarDatesNestedArr,
            formattedMetadataNestedArr
          );
240
241
242
          break;

        case "Column":
243
244
245
246
247
248
249
250
          drawColumnChartBasedOnSelectedOptions(
            selectedAggregationType,
            selectedAggregationDuration,
            observationsComboNestedFinalArr,
            selectedSamplingRateAbbrev,
            uniqueCalendarDatesNestedArr,
            formattedMetadataNestedArr
          );
251
          break;
252

253
254
        default:
          throw new Error("None of the chart type options were selected");
255
      }
256
    }
257
258
  } catch (err) {
    console.error(err);
259
260
261

    // Display a dialog window with the error message
    alert(err);
262
  } finally {
263
264
265
    // Enable the 'draw chart' button
    enableDrawChartButton();

266
267
    // Hide the loading indicator
    hideLoadingSpinner();
268
269
270
  }
};

271
272
273
274
275
document.addEventListener("DOMContentLoaded", afterDocumentLoads);

document
  .querySelector("#btn-draw-chart")
  .addEventListener("click", drawChartUsingSelectedOptions);