Skip to content
Snippets Groups Projects
Commit 8d598373 authored by Tor-Einar Skog's avatar Tor-Einar Skog
Browse files

Merge branch 'feature/vipsutv-737-map-module' of...

Merge branch 'feature/vipsutv-737-map-module' of gitlab.nibio.no:VIPS/VIPSLogic into feature/vipsutv-737-map-module
parents e5e17d7e 81dda06d
Branches
No related tags found
1 merge request!191Add map module and Open-Meteo support
......@@ -19,11 +19,8 @@
package no.nibio.vips.logic.modules.barleynetblotch;
import com.webcohesion.enunciate.metadata.Facet;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.TimeZone;
import java.util.*;
import javax.ejb.EJB;
import javax.persistence.EntityManager;
import javax.persistence.NoResultException;
......@@ -38,10 +35,7 @@ import no.nibio.vips.entity.ModelConfiguration;
import no.nibio.vips.entity.Result;
import no.nibio.vips.entity.WeatherObservation;
import no.nibio.vips.logic.controller.session.ForecastBean;
import no.nibio.vips.logic.entity.Organism;
import no.nibio.vips.logic.entity.Organization;
import no.nibio.vips.logic.entity.PointOfInterestWeatherStation;
import no.nibio.vips.logic.entity.Preparation;
import no.nibio.vips.logic.entity.*;
import no.nibio.vips.logic.util.RunModelException;
import no.nibio.vips.logic.util.SystemTime;
import no.nibio.vips.observation.ObservationImpl;
......@@ -140,6 +134,9 @@ public class BarleyNetBlotchModelService {
public Response runModel(
@PathParam("organizationId") Integer organizationId,
@QueryParam("timeZone") String timeZoneStr,
@QueryParam("weatherdataType") String weatherdataType,
@QueryParam("latitude") Double latitude,
@QueryParam("longitude") Double longitude,
@QueryParam("weatherStationId") Integer weatherStationId,
@QueryParam("sowingDate") String sowingDateStr,
@QueryParam("cropId") Integer cropOrganismId,
......@@ -173,47 +170,57 @@ public class BarleyNetBlotchModelService {
ModelConfiguration config = new ModelConfiguration();
config.setModelId("BARLEYNETB");
// Get weather data from weather station
PointOfInterestWeatherStation weatherStation = em.find(PointOfInterestWeatherStation.class, weatherStationId);
WeatherDataSourceUtil wsdUtil = new WeatherDataSourceUtil();
// End date for weather data depends on season
// We try to add 5 months to the sowing date. If thats in the future,
// We add 10 days to today
Date dateOfLastWeatherData;
Calendar cal = Calendar.getInstance(timeZone);
cal.setTime(sowingDate);
cal.add(Calendar.MONTH, 5);
Date fiveMonthsAfterSowingDate = cal.getTime();
if(fiveMonthsAfterSowingDate.after(SystemTime.getSystemTime()))
{
cal.setTime(SystemTime.getSystemTime());
cal.add(Calendar.DATE, 10);
dateOfLastWeatherData = cal.getTime();
}
else
{
dateOfLastWeatherData = fiveMonthsAfterSowingDate;
}
WeatherDataSourceUtil wsdUtil = new WeatherDataSourceUtil();
Date endDateForWeatherData = calculateEndDateForWeatherData(timeZone, sowingDate);
List<WeatherObservation> observations;
try {
observations = wsdUtil.getWeatherObservations(
if("weatherstation".equals(weatherdataType)) {
PointOfInterestWeatherStation weatherStation =
em.find(PointOfInterestWeatherStation.class, weatherStationId);
try {
observations = wsdUtil.getWeatherObservations(
weatherStation,
WeatherObservation.LOG_INTERVAL_ID_1H,
new String[]{
new String[] {
WeatherElements.TEMPERATURE_MEAN,
WeatherElements.PRECIPITATION
},
sowingDate,
dateOfLastWeatherData
);
} catch (WeatherDataSourceException ex) {
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(ex.getMessage()).build();
}
if(observations == null || observations.isEmpty())
{
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity("Could not find weather data for weather station with id=" + weatherStationId).build();
sowingDate,
endDateForWeatherData
);
} catch (WeatherDataSourceException ex) {
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(ex.getMessage()).build();
}
if (observations == null || observations.isEmpty()) {
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity("Could not find weather data for weather station with id=" + weatherStationId).build();
}
} else {
PointOfInterest coordinates = new PointOfInterest();
coordinates.setLatitude(latitude);
coordinates.setLongitude(longitude);
try {
observations = wsdUtil.getWeatherObservations(
"https://weather.vips.nibio.no/rest/grid/openmeteo/" + coordinates.getLongitude() + "_" + coordinates.getLatitude(),
WeatherObservation.LOG_INTERVAL_ID_1H,
new String[] {
WeatherElements.TEMPERATURE_MEAN,
WeatherElements.PRECIPITATION
},
sowingDate,
endDateForWeatherData,
timeZone,
Boolean.FALSE,
new HashSet<>(Collections.singletonList(WeatherObservation.LOG_INTERVAL_ID_1H))
);
} catch (WeatherDataSourceException ex) {
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(ex.getMessage()).build();
}
if (observations == null || observations.isEmpty()) {
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity("Could not find weather data for weather station with id=" + weatherStationId).build();
}
}
// Mandatory parameters
......@@ -257,6 +264,32 @@ public class BarleyNetBlotchModelService {
}
return Response.ok().entity(results).build();
}
/**
* End date for weather data depends on season. We try to add 5 months to the sowing date.
* If the resulting date is in the future, we add 10 days to today.
*
* @param timeZone The current timezone
* @param sowingDate The sowing date
* @return The end date for weather data
*/
private static Date calculateEndDateForWeatherData(TimeZone timeZone, Date sowingDate) {
Date dateOfLastWeatherData;
Calendar cal = Calendar.getInstance(timeZone);
cal.setTime(sowingDate);
cal.add(Calendar.MONTH, 5);
Date fiveMonthsAfterSowingDate = cal.getTime();
if(fiveMonthsAfterSowingDate.after(SystemTime.getSystemTime()))
{
cal.setTime(SystemTime.getSystemTime());
cal.add(Calendar.DATE, 10);
dateOfLastWeatherData = cal.getTime();
}
else
{
dateOfLastWeatherData = fiveMonthsAfterSowingDate;
}
return dateOfLastWeatherData;
}
}
......@@ -35,7 +35,9 @@ class MapModal {
static TRANSLATIONS = {
nb: {
selectLocation: 'Velg sted',
selectCoordinates: 'Velg punkt',
createNewLocation: 'Opprett nytt sted',
selectNewCoordinates: 'Velg nytt punkt',
name: 'Navn',
latitude: 'Breddegrad',
longitude: 'Lengdegrad',
......@@ -54,7 +56,9 @@ class MapModal {
},
en: {
selectLocation: 'Select location',
selectCoordinates: 'Select point',
createNewLocation: 'Create New Location',
selectNewCoordinates: 'Select new point',
name: 'Name',
latitude: 'Latitude',
longitude: 'Longitude',
......@@ -86,11 +90,10 @@ class MapModal {
this.mapContainerId = mapModalId + "-container";
this.mapContainerElement = this.addMapContainer(this.mapModalElement, this.mapContainerId);
// The variable below should instead be: this.selectPoi or this.selectCoordinates
// this.includeTypeInformation = Object.keys(typeNameMap).length === 7;
this.includeTypeInformation = true;
this.geoJsonData = geoJsonData && geoJsonData !== "{}" ? geoJsonData : { features: []};
// Filter out invalid features
this.geoJsonData.features = this.geoJsonData.features.filter(feature => feature.geometry.type === "Point" && !isNaN(feature.geometry.coordinates[0]) && !isNaN(feature.geometry.coordinates[1]));
this.geoJsonData = geoJsonData;
if (language in MapModal.TRANSLATIONS) {
this.translations = MapModal.TRANSLATIONS[language];
} else {
......@@ -182,9 +185,8 @@ class MapModal {
this.map.addControl(this.closeMapControl);
// Add points to the map if given
if (this.geoJsonData.features) {
if (this.geoJsonData && this.geoJsonData.features) {
geoJSON(this.geoJsonData, {
filter: (feature) => feature.geometry.type === "Point",
pointToLayer: (feature, latlng) => {
return circleMarker(latlng, this.styleOfPointMarker(feature.properties.pointOfInterestTypeId));
},
......@@ -218,7 +220,7 @@ class MapModal {
}
// Function called when point is hidden (by deselecting its location type in legend box)
// If point is already selected, the popup and info panel is removed.
// If point is already selected, the popup is removed.
unbindActionToPoint(layer) {
if (this.selectedExistingPointMarker === layer) {
layer.closePopup();
......@@ -238,6 +240,10 @@ class MapModal {
selectPointById(pointOfInterestId) {
const selectedFeature = this.getFeatureById(pointOfInterestId);
const selectedLayer = this.getLayerById(pointOfInterestId);
if(!selectedFeature || !selectedLayer) {
console.error("Unable to display selected point " + pointOfInterestId, this.geoJsonData.features)
return
}
this.displaySelectedPoint(selectedFeature, selectedLayer, true);
selectedLayer.openPopup();
}
......@@ -394,12 +400,19 @@ class MapModal {
const type = this.translations['poiType' + feature.properties.pointOfInterestTypeId];
const latitude = feature.geometry.coordinates[1].toFixed(this.coordinatePrecision);
const longitude = feature.geometry.coordinates[0].toFixed(this.coordinatePrecision);
const buttonLabel = this.translations.selectLocation;
popupElement.innerHTML = `<h4>${name}</h4>
<b>${this.translations.latitude}</b> ${latitude}<br>
<b>${this.translations.longitude}</b> ${longitude}<br>
<b>${this.translations.type}</b> ${type}<br><br>
<button id="submit-button" class="btn btn-primary">${buttonLabel}</button>`
const buttonLabel = this.isPoiMap ? this.translations.selectLocation : this.translations.selectCoordinates;
if(this.isPoiMap) {
popupElement.innerHTML = `<h4>${name}</h4>
<b>${this.translations.latitude}</b> ${latitude}<br>
<b>${this.translations.longitude}</b> ${longitude}<br>
<b>${this.translations.type}</b> ${type}<br><br>
<button id="submit-button" class="btn btn-primary">${buttonLabel}</button>`
} else {
popupElement.innerHTML = `<b>${this.translations.latitude}</b> ${latitude}<br>
<b>${this.translations.longitude}</b> ${longitude}<br><br>
<button id="submit-button" class="btn btn-primary">${buttonLabel}</button>`
}
const buttonElement = popupElement.querySelector("#submit-button");
buttonElement.addEventListener('click', () => {
this.confirmSelection(feature);
......@@ -438,7 +451,7 @@ class MapModal {
form.innerHTML = `
<div class="panel-heading">
<h4 class="panel-title">${this.translations.createNewLocation}</h4>
<h4 class="panel-title">${this.isPoiMap ? this.translations.createNewLocation : this.translations.selectNewCoordinates}</h4>
<span id="map-poi-close-button" style="position: absolute; top: 5px; right: 10px; cursor: pointer; font-size: 18px;">&times;</span>
</div>
<div class="panel-body">
......@@ -463,7 +476,7 @@ class MapModal {
</select>
</div>
<div class="form-group text-right">
<button id="map-poi-submit-button" class="btn btn-primary">${this.translations.selectLocation}</button>
<button id="map-poi-submit-button" class="btn btn-primary">${this.isPoiMap ? this.translations.selectLocation : this.translations.selectCoordinates}</button>
</div>
</div>`;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment