appChart.js 9.85 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
43
  getAbbreviationsForSelectedOptionsFromAllDropDownLists,
} from "./src_modules/dropDownListHelpers.mjs";
44

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

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

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

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

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

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

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

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

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

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

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

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

    // Display the loading indicator
    showLoadingSpinner();

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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