import Plotly from 'plotly.js-dist';
import { displayMessage } from '../../../utils.js';
import { PlotlyVefPlot } from '../../../../plot/templates/PlotlyVefPlot.js';
// static plot container
let vefPlotly = null;
let plotInterval = null;
let plotTimeout = null;
function clearTimers() {
if (plotInterval) clearInterval(plotInterval);
if (plotTimeout) clearTimeout(plotTimeout);
plotInterval = null;
plotTimeout = null;
}
function plotInSidebar(data, layout) {
const target = document.createElement("div");
target.style.width = "100%";
target.classList.add("vef-plot");
clearTimers();
const createPlot = () => {
clearTimers();
if (vefPlotly) Plotly.purge(vefPlotly.graphDiv);
vefPlotly = new PlotlyVefPlot(target, data, layout);
Plotly.newPlot(vefPlotly.graphDiv, vefPlotly.data, vefPlotly.layout, vefPlotly.config);
vefPlotly.extensions.apply({ 'redirectNotification': { 'callback': displayMessage } });
};
// only init plot if the target is visible in DOM (offsetParent == null if not displayed)
// use timeout to push to end of eventloop. If not in DOM check repeatedly
plotTimeout = setTimeout(() => {
if (target.offsetParent) {
createPlot()
} else {
plotInterval = setInterval(() => {
if (target.offsetParent) createPlot();
}, 700);
}
}, 50);
return target;
}
export function getDateTimeFromWMSResponse(str) {
if (!str) return str
//'{"2020-02-20 00:00:00","2020-02-20 23:59:00"}' -> ISO format only in future
return str.match(/\d{4}-\d{2}-\d{2}[\sT]\d{2}:\d{2}:\d{2}(?:\.\d+)?/g)
}
export function getNumbersFromWMSResponse(arg) {
if (!arg) return arg
//"{27.009,27.008,27.007,27.000,27.001,26.997}"
const sqlString = arg.toString();
const stringNumbers = sqlString.match(/(?:[+-])?\d+(?:\.\d+)?/g);
const floatNumbers = stringNumbers.map(item => parseFloat(item));
return floatNumbers
}
/**
* Creates an elementary plot
*
*
* @param {*} valueX
* @param {*} valueY
* @param {string} labelX
* @param {string} labelY
* @returns {HTMLElement} span placeholder
*/
export function plot(valueX, valueY, labelX, labelY) {
if (valueX == null || valueY == null)
return undefined
const data = [{ x: valueX, y: valueY }];
const layout = {
xaxis: { title: { text: labelX } },
yaxis: { title: { text: labelY } }
};
return plotInSidebar(data, layout);
}
/**
* Creates an overview plot for the measurements layers
*
* @param {object} properties
* @param {object} data response
* @returns {string} span placeholder
*
*/
export function marehubOverviewPlot(properties) {
if (properties.ov_type && (properties.value_cnt > 1)) {
const times = getDateTimeFromWMSResponse(properties.times);
const depths = getNumbersFromWMSResponse(properties.depths);
const values = getNumbersFromWMSResponse(properties.values);
if (values) {
// create regular plots
switch (properties.ov_type) {
case "depth profile, stationary":
if (depths && (depths.length > 0)) {
const data = [{ x: values, y: depths }];
const labelX = properties.parameter_name + ((properties.parameter_unit) ? ` [${properties.parameter_unit}]` : '');
const labelY = (properties.depth_type || "depth") + " [m]";
const layout = {
hovermode: "y",
xaxis: { title: { text: labelX } },
yaxis: { title: { text: labelY }, autorange: "reversed" }
}
return plotInSidebar(data, layout);
}
break;
case "time series, stationary":
case "time series, moving":
if (times && (times.length > 0)) {
const data = [{ x: times, y: values }];
const labelX = "Time of Day";
const labelY = properties.parameter_name + ((properties.parameter_unit) ? ` [${properties.parameter_unit}]` : '');
const layout = {
xaxis: { title: { text: labelX } },
yaxis: { title: { text: labelY } }
}
return plotInSidebar(data, layout);
}
break;
}
} else {
// special case for current
const values_vc = getNumbersFromWMSResponse(properties.values_vc);
const values_uc = getNumbersFromWMSResponse(properties.values_uc);
if (!values_vc || !values_uc) return undefined;
switch (properties.ov_type) {
case "depth profile, stationary":
if (depths && (depths.length > 0)) {
const data = [
{ x: values_vc, y: depths, name: "VC" },
{ x: values_uc, y: depths, name: "UC" }
]
const labelX = "Current Velocity" + ((properties.parameter_unit) ? ` [${properties.parameter_unit}]` : '');
const labelY = (properties.depth_type || "depth") + " [m]";
const layout = {
hovermode: "y",
xaxis: { title: { text: labelX } },
yaxis: { title: { text: labelY }, autorange: "reversed" }
}
return plotInSidebar(data, layout);
}
break;
case "time series, stationary":
case "time series, moving":
if (times && (times.length > 0)) {
const data = [
{ y: values_vc, x: times, name: "VC" },
{ y: values_uc, x: times, name: "UC" }
]
const labelX = "Time of Day";
const labelY = "Current Velocity" + ((properties.parameter_unit) ? ` [${properties.parameter_unit}]` : '');
const layout = {
xaxis: { title: { text: labelX } },
yaxis: { title: { text: labelY } }
}
return plotInSidebar(data, layout);
}
break;
}
}
}
return undefined;
}
/**
* Prints the value with unit if only one value exists
*
* @param {*} properties
* @param {*} column
* @param {*} unit
* @returns {string} value
*/
export function getMarehubOverviewValue(properties, column, unit) {
column = column || "values";
unit = unit || properties.parameter_unit;
if (properties.value_cnt == 1) {
const values = getNumbersFromWMSResponse(properties[column]);
if (values?.length == 1) {
let value = values[0];
if (unit) value += " " + unit;
return value
}
}
return undefined;
}