"use strict"; /** * Format the response from SensorThings API to make it suitable for use in a line chart * @param {Array} obsArray Array of observations (timestamp + value) that is response from SensorThings API * @returns {Array} Array of formatted observations suitable for use in a line chart */ const formatSensorThingsApiResponseForLineChart = function (obsArray) { if (!obsArray) return; const dataSTAFormatted = obsArray.map((result) => { const timestampObs = new Date(result[0].slice(0, -1)).getTime(); // slice() removes trailing "Z" character in timestamp const valueObs = result[1]; return [timestampObs, valueObs]; }); return dataSTAFormatted; }; /** * Extract the properties that make up the formatted datastream metadata object(s) * @param {Array} formattedDatastreamsMetadataArr An array of formatted metadata object(s) from one or more datastreams * @returns {Object} An object that contains array(s) of formatted datastream metadata properties */ const extractPropertiesFromDatastreamMetadata = function ( formattedDatastreamsMetadataArr ) { // Create arrays from the properties of the formatted datastream metadata const datastreamDescriptionsArr = formattedDatastreamsMetadataArr.map( (datastreamMetadata) => datastreamMetadata.datastreamDescription ); const datastreamNamesArr = formattedDatastreamsMetadataArr.map( (datastreamMetadata) => datastreamMetadata.datastreamName ); const phenomenonNamesArr = formattedDatastreamsMetadataArr.map( (datastreamMetadata) => datastreamMetadata.phenomenonName ); const unitOfMeasurementSymbolsArr = formattedDatastreamsMetadataArr.map( (datastreamMetadata) => datastreamMetadata.unitOfMeasurementSymbol ); return { datastreamDescriptionsArr, datastreamNamesArr, phenomenonNamesArr, unitOfMeasurementSymbolsArr, }; }; /** * Extracts the sampling rate substring from a datastream name string * @param {Array} datastreamNamesArr An array of datastream name(s) * @returns {Array} An array containing the sampling rate substring(s) */ const extractSamplingRateFromDatastreamName = function (datastreamNamesArr) { // The sampling rate string is the last word in the Datastream name string return datastreamNamesArr.map((datastreamName) => datastreamName.split(" ").pop() ); }; /** * Concatenates metadata properties to create a string for either the title or subtitle of a line chart * @param {Array} datastreamMetadataPropArr An array of metadata property strings * @returns {String} A string of comma separated metadata property strings */ const createCombinedTextForLineChartTitles = function ( datastreamMetadataPropArr ) { return datastreamMetadataPropArr.join(", "); }; /** * Creates an options object for each series drawn in the line chart * @param {Array} formattedObsArraysForLineChart An array of formatted observation array(s) from one or more datastreams * @param {Array} phenomenonNamesArr An array of phenomenon name(s) * @param {Array} phenomenonSymbolsArr An array of phenomenon symbol(s) * @returns {Array} An array made up of series options object(s) */ const createSeriesOptionsForLineChart = function ( formattedObsArraysForLineChart, phenomenonNamesArr, phenomenonSymbolsArr ) { // An array of colors provided by the Highcharts object const seriesColors = Highcharts.getOptions().colors; // Create an array of seriesOptions objects // Assumes that the observation array of arrays, phenomenon names array and phenomenon symbols array are of equal length // Use one of the arrays for looping return formattedObsArraysForLineChart.map((formattedObsArray, i) => { return { name: `${phenomenonNamesArr[i]} (${phenomenonSymbolsArr[i]})`, data: formattedObsArray, color: seriesColors[i], turboThreshold: Number.MAX_VALUE, // #3404, remove after 4.0.5 release }; }); }; /** * Draw a line chart using Highcharts library * @param {Array} formattedObsArraysForLineChart An array made up of formatted observation array(s) suitable for use in a line chart * @param {Object} formattedDatastreamMetadataArr An array made up of object(s) containing Datastream metadata * @returns {undefined} undefined */ const drawLineChartHighcharts = function ( formattedObsArraysForLineChart, formattedDatastreamMetadataArr ) { // Arrays of datastream properties const { datastreamNamesArr, phenomenonNamesArr, unitOfMeasurementSymbolsArr, } = extractPropertiesFromDatastreamMetadata(formattedDatastreamMetadataArr); // Create the array of series options object(s) const seriesOptionsArr = createSeriesOptionsForLineChart( formattedObsArraysForLineChart, phenomenonNamesArr, unitOfMeasurementSymbolsArr ); Highcharts.stockChart("chart-line", { chart: { zoomType: "x", }, rangeSelector: { selected: 5, }, title: { text: createCombinedTextForLineChartTitles(phenomenonNamesArr), "align": "left", }, subtitle: { text: `Sampling rate(s): ${createCombinedTextForLineChartTitles( extractSamplingRateFromDatastreamName(datastreamNamesArr) )}`, align: "left", }, tooltip: { pointFormat: '<span style="color:{series.color}">{series.name}</span>: <b>{point.y}</b> <br/>', valueDecimals: 2, }, series: seriesOptionsArr, }); }; export { formatSensorThingsApiResponseForLineChart, drawLineChartHighcharts };