diff --git a/ipmd/static/ipmd/js/ipmdlib.js b/ipmd/static/ipmd/js/ipmdlib.js index 3c40f2cafd9af7e864f0004fe15736e37c631148..2d58da10a8f31eb42ae7ac2a3700b0249a320357 100644 --- a/ipmd/static/ipmd/js/ipmdlib.js +++ b/ipmd/static/ipmd/js/ipmdlib.js @@ -220,7 +220,7 @@ function getDateArray(timestart, interval, length) /** * - * @param {Integer} weatherParameterId the parameter di + * @param {Integer} weatherParameterId the parameter id * @returns {Json} parameter metadata (name, description, unit, aggregation type (MIN/MAX/AVG)) */ function getWeatherParameter(weatherParameterId){ @@ -272,13 +272,59 @@ function getWeatherStationCoordinate(weatherDatasource, weatherStationId) * @returns */ function getPragmaticWeatherParameterList(requestedParameters, availableParameters) +{ + return getParametersWithFallbacks(requestedParameters).filter(param => availableParameters.includes(param)); +} + +function getParametersWithFallbacks(parameterList) { let completeList = []; - for(let i=0;i<requestedParameters.length;i++) + for(let i=0;i<parameterList.length;i++) { - completeList = completeList.concat(requestedParameters[i], fallbackParams[requestedParameters[i]]); + completeList = completeList.concat(parameterList[i], fallbackParams[parameterList[i]]); } - return completeList.filter(param => availableParameters.includes(param)); + return completeList; +} + +function arePragmaticWeatherParametersInList(requestedParameters, availableParameters) +{ + for(let i=0; i<requestedParameters.length;i++) + { + let requestedParameter = requestedParameters[i]; + // 1. Is the requested parameter in the availableParameters list? + if(! availableParameters.includes(requestedParameter)) + { + if(isEmpty(fallbackParams[requestedParameter])) + { + return false; + } + // If no, check if any fallback parameters are available + let match = false; + + for(let j=0;j<fallbackParams[requestedParameter].length; j++) + { + if(availableParameters.includes(fallbackParams[requestedParameter][j])) + { + match = true; + } + } + if(!match) + { + return false; + } + } + } + + return true; +} + +function getRequiredParameters(modelMetaData) +{ + let parameterList = [] + modelMetaData.input.weather_parameters.forEach(function(weatherParameter){ + parameterList.push(weatherParameter.parameter_code) + }) + return parameterList; } /** diff --git a/ipmd/templates/ipmd/saddlegallmidgeform.html b/ipmd/templates/ipmd/saddlegallmidgeform.html index 932fc31c562eef6592c90c74171f5a4fd22584b2..bb256703ff09ef2857048584351075343b218c38 100644 --- a/ipmd/templates/ipmd/saddlegallmidgeform.html +++ b/ipmd/templates/ipmd/saddlegallmidgeform.html @@ -31,6 +31,7 @@ <h2>Weather data</h2> <div class="row"> <div class="col-md-6"> + <div id="parameterInfo" style="display: none;"></div> <fieldset id="historicDatasourceFields"> <legend>Weather datasource (historic)</legend> <select class="form-control" name="weatherDatasourceId" id="weatherDatasourceList" onchange="handleWeatherDatasourceSelected(this);"></select> @@ -91,7 +92,7 @@ <script type="text/javascript" src="{% static "ipmd/js/ipmdlib.js" %}"></script> <script type="text/javascript"> // Page globals - var modelMetaData = undefined; + var currentModelMetaData = undefined; var currentWeatherDatasource = undefined; var currentForecastWeatherDatasource = undefined; var weatherDatasources = undefined; @@ -101,11 +102,10 @@ var weatherData = undefined; async function initPage() { - modelMetaData = await getModelMetadata("adas.dss","HAPDMA"); - document.getElementById("modelDescription").innerHTML= await modelMetaData["description"]; + currentModelMetaData = await getModelMetadata("adas.dss","HAPDMA"); + document.getElementById("modelDescription").innerHTML= await currentModelMetaData["description"]; inputFormSchema = await getModelInputSchema("adas.dss","HAPDMA") inputFormSchema.title ="Model input data"; - //console.info(inputFormSchema); const element = document.getElementById('inputForm'); // See https://github.com/json-editor/json-editor#options @@ -118,9 +118,22 @@ disable_edit_json: true, disable_properties: true }); - let fullSchema = JSON.parse(modelMetaData["execution"]["input_schema"]); + let fullSchema = JSON.parse(currentModelMetaData["execution"]["input_schema"]); if(fullSchema["properties"]["weatherData"] !== undefined) { + // Display the required weather parameters + let requiredParameters = getRequiredParameters(currentModelMetaData); + let paramHTML = "<h4>Parameters required by the model</h4><ul>"; + for(let i=0;i<requiredParameters.length;i++) + { + let param = getWeatherParameter(requiredParameters[i]); + paramHTML += "<li>" + param.name + "</li>"; + } + paramHTML += "</ul>" + + let parameterInfo = document.getElementById("parameterInfo"); + parameterInfo.innerHTML = paramHTML; + parameterInfo.style.display = "block"; // Pull weather data sources from web service, render lists (historic and forecast sources, some are both) weatherDatasources = await getWeatherDatasources(); @@ -193,7 +206,25 @@ ); let sourceInfo = document.getElementById("historicSourceInfo"); - sourceInfo.innerHTML = currentWeatherDatasource.description; + let sourceHTML = currentWeatherDatasource.description; + sourceHTML += "<h4>Provided weather parameters</h4><ul>"; + for(let i=0;i<currentWeatherDatasource.parameters.common.length;i++) + { + sourceHTML += "<li>" + getWeatherParameter(currentWeatherDatasource.parameters.common[i]).name + "</li>"; + } + sourceHTML += "</ul>"; + + if(!isEmpty(currentWeatherDatasource.parameters.optional) && currentWeatherDatasource.parameters.optional.length > 0) + { + sourceHTML += "<h5>Optional parameters (some weather stations)</h5><ul>"; + for(let i=0;i<currentWeatherDatasource.parameters.optional.length;i++) + { + sourceHTML += "<li>" + getWeatherParameter(currentWeatherDatasource.parameters.optional[i]).name + "</li>"; + } + sourceHTML += "</ul>"; + } + + sourceInfo.innerHTML = sourceHTML; sourceInfoPanel.style.display="block"; if(currentWeatherDatasource.access_type == "stations") { @@ -207,6 +238,12 @@ // Display lat/lon input fields document.getElementById("stationFields").style.display = "none"; } + + // Check that this datasource can deliver the model's requested parameters + if(!arePragmaticWeatherParametersInList(getRequiredParameters(currentModelMetaData), currentWeatherDatasource.parameters.common)) + { + alert("WARNING: The selected datasource can't deliver all weather parameters required by the DSS"); + } } /** @@ -245,7 +282,7 @@ */ async function handleForecastSourceSelected(forecastSourceSelectList) { - currentForecastWeatherDatasource = getWeatherDatasource( + currentForecastWeatherDatasource = await getWeatherDatasource( weatherDatasources, forecastWeatherDatasourceList.options[forecastWeatherDatasourceList.selectedIndex].value ); @@ -270,14 +307,26 @@ ); let sourceInfo = document.getElementById("forecastSourceInfo"); - sourceInfo.innerHTML = currentForecastWeatherDatasource.description; + let sourceHTML = currentForecastWeatherDatasource.description; + sourceHTML += "<h4>Provided weather parameters</h4><ul>"; + for(let i=0;i<currentForecastWeatherDatasource.parameters.common.length;i++) + { + sourceHTML += "<li>" + getWeatherParameter(currentForecastWeatherDatasource.parameters.common[i]).name + "</li>"; + } + sourceHTML += "</ul>"; + + sourceInfo.innerHTML = sourceHTML; sourceInfoPanel.style.display="block"; // Does the forecast data source cover the point in question? if(! await isPointCoveredByDatasource(getLatLon(), currentForecastWeatherDatasource)) { alert("The selected forecast datasource does not cover the selected location."); } - + // Check that this datasource can deliver the model's requested parameters + if(!arePragmaticWeatherParametersInList(getRequiredParameters(currentModelMetaData), currentForecastWeatherDatasource.parameters.common)) + { + alert("WARNING: The selected forecast datasource can't deliver all weather parameters required by the DSS"); + } } /** @@ -315,8 +364,8 @@ async function submitData(){ let inputData = editor.getValue(); // Add hidden parameters - let fullSchema = JSON.parse(modelMetaData["execution"]["input_schema"]); - const hiddenParameters = modelMetaData["execution"]["input_schema_categories"]["hidden"]; + let fullSchema = JSON.parse(currentModelMetaData["execution"]["input_schema"]); + const hiddenParameters = currentModelMetaData["execution"]["input_schema_categories"]["hidden"]; for(let i=0;i<hiddenParameters.length;i++) { let hiddenParameter = hiddenParameters[i]; @@ -339,7 +388,7 @@ getPragmaticWeatherParameterList( function (){ let parameterList = [] - modelMetaData.input.weather_parameters.forEach(function(weatherParameter){ + currentModelMetaData.input.weather_parameters.forEach(function(weatherParameter){ parameterList.push(weatherParameter.parameter_code) }) return parameterList; @@ -368,7 +417,7 @@ getPragmaticWeatherParameterList( function (){ let parameterList = [] - modelMetaData.input.weather_parameters.forEach(function(weatherParameter){ + currentModelMetaData.input.weather_parameters.forEach(function(weatherParameter){ parameterList.push(weatherParameter.parameter_code) }) return parameterList; @@ -398,7 +447,7 @@ getPragmaticWeatherParameterList( function (){ let parameterList = [] - modelMetaData.input.weather_parameters.forEach(function(weatherParameter){ + currentModelMetaData.input.weather_parameters.forEach(function(weatherParameter){ parameterList.push(weatherParameter.parameter_code) }) return parameterList;