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

3
4
5
import { SENSORTHINGS_API_BASE_URL } from "./config.mjs";

import { QUERY_PARAMS_COMBINED } from "./src_modules/baseUrlPlusQueryParams.mjs";
6

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

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

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

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

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

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

import {
34
35
36
37
38
39
  splitMultipleOptionsTextDelimitedBySlash,
  getSelectedOptionsFromAllDropDownLists,
  checkIfSelectedOptionsContainTemperatureDifference,
  deleteTemperatureDifferenceOptions,
  extractTemperatureDifferenceOptions,
  extractBuildingPlusSamplingRate,
40
41
  checkIfSelectedBuildingDataPointsOptionsAreValid,
  checkIfSelectedAggregationOptionsAreValid,
42
  getAbbreviationsForSelectedOptionsFromAllDropDownLists,
43
  createErrorPopupMessage,
44
} 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
59
import {
  nonDetailedBuilding225Tileset,
  resetStylingForAllBuildings,
  highlightSelectedBuildings,
} from "./appCesium.js";

60
/**
61
62
63
64
 * Callback function that wraps the logic of populating the linked drop down lists.
 * Will run on `DOMContentLoaded` event
 *
 * @returns {undefined}
65
 */
66
const afterDocumentLoads = function () {
67
  styleAllDropDownLists();
68
69
};

70
/**
71
72
73
74
75
76
 * 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
77
 */
78
const drawChartUsingSelectedOptions = async function () {
79
  try {
80
81
82
    // Reset the styling of the 3D tileset, in case building(s) were highlighted
    resetStylingForAllBuildings(nonDetailedBuilding225Tileset);

83
    // Note: The chart type amd aggregation type + duration are the first and
84
85
    // third elements respectively, we have ignored the second and fourth elements
    const [selectedChartTypeArr, , selectedAggregationTypeDurationArr] =
86
      getSelectedOptionsFromAllDropDownLists();
87

88
89
90
    // Note: the resulting array is nested, it only has one sub-array
    // Separate the aggregation type and the aggregation duration strings
    const [[selectedAggregationType, selectedAggregationDuration]] =
91
92
      splitMultipleOptionsTextDelimitedBySlash(
        selectedAggregationTypeDurationArr
93
94
      );

95
    // Array of building(s) + data point(s) + sampling rate
96
    const selectedBuildingsDataPointsSamplingRateAbbrevNestedArr =
97
      getAbbreviationsForSelectedOptionsFromAllDropDownLists(
98
        getSelectedOptionsFromAllDropDownLists()
99
100
      );

101
102
103
104
105
106
    // 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;

107
108
109
110
111
    // Highlight the selected buildings
    highlightSelectedBuildings(
      selectedBuildingsDataPointsSamplingRateAbbrevNestedArr
    );

112
113
114
115
    // 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";

116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
    // 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
      );

131
132
    // Check whether we have dT (temperature difference), if so, delete these options,
    // then compute abbreviations for raw observations
133
    const selectedBuildingsDataPointsSamplingRateAbbrevRawObsArr =
134
      checkIfSelectedOptionsContainTemperatureDifference(
135
        selectedBuildingsDataPointsSamplingRateAbbrevNestedArr
136
      )
137
        ? deleteTemperatureDifferenceOptions(
138
            selectedBuildingsDataPointsSamplingRateAbbrevNestedArr
139
          )
140
        : selectedBuildingsDataPointsSamplingRateAbbrevNestedArr;
141

142
    // Check if we have dT (temperature difference), if so, extract these options
143
    const selectedBuildingsDataPointsSamplingRateAbbrevTempDiffArr =
144
      checkIfSelectedOptionsContainTemperatureDifference(
145
        selectedBuildingsDataPointsSamplingRateAbbrevNestedArr
146
147
      )
        ? extractTemperatureDifferenceOptions(
148
            selectedBuildingsDataPointsSamplingRateAbbrevNestedArr
149
150
151
152
153
154
          )
        : [];

    // Display the loading indicator
    showLoadingSpinner();

155
156
157
    // Disable the 'draw chart' button
    disableDrawChartButton();

158
159
    // Fetch and extract the observations + metadata / raw observations
    const [observationsRawNestedArr, metadataRawNestedArr] =
160
      selectedBuildingsDataPointsSamplingRateAbbrevRawObsArr.length === 0
161
162
        ? [[], []]
        : await getMetadataPlusObservationsFromSingleOrMultipleDatastreams(
163
            SENSORTHINGS_API_BASE_URL,
164
            QUERY_PARAMS_COMBINED,
165
            selectedBuildingsDataPointsSamplingRateAbbrevRawObsArr
166
167
          );

168
169
    // Fetch and extract the observations + metadata / temperature difference (dT)
    const [observationsTempDiffNestedArr, metadataTempDiffNestedArr] =
170
      selectedBuildingsDataPointsSamplingRateAbbrevTempDiffArr.length === 0
171
172
        ? [[], []]
        : await calculateVorlaufMinusRuecklaufTemperature(
173
            SENSORTHINGS_API_BASE_URL,
174
175
            QUERY_PARAMS_COMBINED,
            extractBuildingPlusSamplingRate(
176
              selectedBuildingsDataPointsSamplingRateAbbrevTempDiffArr
177
178
179
            )
          );

180
181
    // Create and extract the combined observations and metadata
    const [observationsCombinedNestedArr, metadataCombinedNestedArr] = [
182
183
      [...observationsRawNestedArr, ...observationsTempDiffNestedArr],
      [...metadataRawNestedArr, ...metadataTempDiffNestedArr],
184
    ];
185

186
    // Create formatted array(s) for metadata - used by ALL chart types
187
    const formattedMetadataNestedArr = metadataCombinedNestedArr.map(
188
      (metadataObj) => formatDatastreamMetadataForChart(metadataObj)
189
190
    );

191
    // Extract the formatted metadata properties for the raw observations - used by ALL chart types
192
    const rawObsExtractedFormattedDatastreamProperties =
193
194
      extractPropertiesFromFormattedDatastreamMetadata(
        formattedMetadataNestedArr,
195
        false
196
197
      );

198
199
200
201
202
    // 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)"
203
204
        ? observationsCombinedNestedArr
        : observationsCombinedNestedArr.map((observationsArr) =>
205
206
207
            extractObservationsWithinDatesInterval(
              observationsArr,
              selectedSamplingRateAbbrev,
208
209
              AGGREGATION_START_DATE,
              AGGREGATION_STOP_DATE
210
211
            )
          );
212

213
    // Unique calendar dates - used by MULTIPLE chart types
214
    const uniqueCalendarDatesNestedArr = observationsComboNestedFinalArr.map(
215
216
217
218
      (observationsArr) =>
        extractUniqueCalendarDatesFromTimestamp(observationsArr)
    );

219
    for (const selectedChartType of selectedChartTypeArr) {
220
221
222
223
224
225
226
227
      switch (selectedChartType) {
        case "Heatmap":
          if (
            selectedAggregationOptionsAreValid &&
            selectedBuildingDataPointsOptionsAreValid
          ) {
            drawHeatmapBasedOnSelectedOptions(
              observationsComboNestedFinalArr,
228
              rawObsExtractedFormattedDatastreamProperties
229
            );
230
231
232
233
234
235
236
237
          }
          break;

        case "Scatter Plot":
          if (
            selectedAggregationOptionsAreValid &&
            selectedBuildingDataPointsOptionsAreValid
          ) {
238
            drawScatterPlotBasedOnSelectedOptions(
239
              observationsComboNestedFinalArr,
240
              rawObsExtractedFormattedDatastreamProperties
241
242
243
244
245
            );
          }
          break;

        case "Line":
246
247
248
249
250
251
252
253
          drawLineChartBasedOnSelectedOptions(
            selectedAggregationType,
            selectedAggregationDuration,
            observationsComboNestedFinalArr,
            selectedSamplingRateAbbrev,
            uniqueCalendarDatesNestedArr,
            formattedMetadataNestedArr
          );
254
255
256
          break;

        case "Column":
257
258
259
260
261
262
263
264
          drawColumnChartBasedOnSelectedOptions(
            selectedAggregationType,
            selectedAggregationDuration,
            observationsComboNestedFinalArr,
            selectedSamplingRateAbbrev,
            uniqueCalendarDatesNestedArr,
            formattedMetadataNestedArr
          );
265
          break;
266

267
268
        default:
          throw new Error("None of the chart type options were selected");
269
      }
270
    }
271
272
  } catch (err) {
    console.error(err);
273

274
275
    // Display a popup that displays the error message
    createErrorPopupMessage(err);
276
  } finally {
277
278
279
    // Enable the 'draw chart' button
    enableDrawChartButton();

280
281
    // Hide the loading indicator
    hideLoadingSpinner();
282
283
284
  }
};

285
286
287
288
289
document.addEventListener("DOMContentLoaded", afterDocumentLoads);

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