diff --git a/src/main/java/net/ipmdecisions/model/entity/LocationResult.java b/src/main/java/net/ipmdecisions/model/entity/LocationResult.java new file mode 100644 index 0000000000000000000000000000000000000000..ef2ed6cb86e5de509f45cc912c721c693b76f5bc --- /dev/null +++ b/src/main/java/net/ipmdecisions/model/entity/LocationResult.java @@ -0,0 +1,153 @@ +/* + * Copyright (c) 2020 NIBIO <http://www.nibio.no/>. + * + * This file is part of VIPSCommon. + * VIPSCommon is free software: you can redistribute it and/or modify + * it under the terms of the NIBIO Open Source License as published by + * NIBIO, either version 1 of the License, or (at your option) any + * later version. + * + * VIPSCommon is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * NIBIO Open Source License for more details. + * + * You should have received a copy of the NIBIO Open Source License + * along with VIPSCommon. If not, see <http://www.nibio.no/licenses/>. + * + */ + +package net.ipmdecisions.model.entity; + +/** + * @copyright 2020 <a href="http://www.nibio.no/">NIBIO</a> + * @author Tor-Einar Skog <tor-einar.skog@nibio.no> + */ +public class LocationResult { + private Double longitude; + private Double latitude; + private Double altitude; + private Double[][] data; + + public LocationResult(Double longitude, Double latitude, Double altitude, int rows, int columns){ + this.longitude = longitude; + this.latitude = latitude; + this.altitude = altitude; + this.data = new Double[rows][columns]; + } + + public LocationResult(){ + + } + + /** + * + * @return The number of rows in the dataset + */ + public Integer getLength() + { + return this.data.length; + } + + /** + * + * @return The number of parameters per rows in the dataset + */ + public Integer getWidth() + { + return this.data[0].length; + } + + public Double[][] getData() + { + return this.data; + } + + public void setData(Double[][] data) + { + this.data = data; + } + + public void setValue(Integer row, Integer column, Double value) + { + this.data[row][column] = value; + } + + public Double getValue(Integer row, Integer column) + { + return this.data[row][column]; + } + + public Double[] getRow(Integer row) + { + return this.data[row]; + } + + public Double[] getColumn(Integer column) + { + Double[] columnValues = new Double[this.data.length]; + for(Integer i=0; i < this.data.length; i++) + { + columnValues[i] = this.data[i][column]; + } + return columnValues; + } + + @Override + public String toString() + { + String retVal = ""; + for(Integer i=0;i<this.data.length;i++) + { + retVal += i + ""; + for(Integer j = 0; j < this.data[i].length; j++) + { + retVal += "\t" + this.data[i][j]; + } + retVal += "\n"; + } + return retVal; + } + + /** + * @return the longitude + */ + public Double getLongitude() { + return longitude; + } + + /** + * @param longitude the longitude to set + */ + public void setLongitude(Double longitude) { + this.longitude = longitude; + } + + /** + * @return the latitude + */ + public Double getLatitude() { + return latitude; + } + + /** + * @param latitude the latitude to set + */ + public void setLatitude(Double latitude) { + this.latitude = latitude; + } + + /** + * @return the altitude + */ + public Double getAltitude() { + return altitude; + } + + /** + * @param altitude the altitude to set + */ + public void setAltitude(Double altitude) { + this.altitude = altitude; + } +} diff --git a/src/main/java/net/ipmdecisions/model/entity/ModelOutput.java b/src/main/java/net/ipmdecisions/model/entity/ModelOutput.java new file mode 100644 index 0000000000000000000000000000000000000000..ef76c25d08ca8c365d506b4299ff5cb53bee3d58 --- /dev/null +++ b/src/main/java/net/ipmdecisions/model/entity/ModelOutput.java @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2020 NIBIO <http://www.nibio.no/>. + * + * This file is part of VIPSCommon. + * VIPSCommon is free software: you can redistribute it and/or modify + * it under the terms of the NIBIO Open Source License as published by + * NIBIO, either version 1 of the License, or (at your option) any + * later version. + * + * VIPSCommon is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * NIBIO Open Source License for more details. + * + * You should have received a copy of the NIBIO Open Source License + * along with VIPSCommon. If not, see <http://www.nibio.no/licenses/>. + * + */ + +package net.ipmdecisions.model.entity; + +import java.time.Instant; +import java.util.ArrayList; +import java.util.List; + +/** + * + * @copyright 2020 <a href="http://www.nibio.no/">NIBIO</a> + * @author Tor-Einar Skog <tor-einar.skog@nibio.no> + */ +public class ModelOutput { + private Instant timeStart; + private Instant timeEnd; + private Integer interval; + private String[] resultParameters; + private List<LocationResult> locationResult; + + /** + * @return the timeStart + */ + public Instant getTimeStart() { + return timeStart; + } + + + /** + * @param timeStart the timeStart to set + */ + public void setTimeStart(Instant timeStart) { + this.timeStart = timeStart; + } + + /** + * @return the timeEnd + */ + public Instant getTimeEnd() { + return timeEnd; + } + + + /** + * @param timeEnd the timeEnd to set + */ + public void setTimeEnd(Instant timeEnd) { + this.timeEnd = timeEnd; + } + + /** + * @return the interval + */ + public Integer getInterval() { + return interval; + } + + /** + * @param interval the interval to set + */ + public void setInterval(Integer interval) { + this.interval = interval; + } + + /** + * @return the resultParameters + */ + public String[] getResultParameters() { + return resultParameters; + } + + /** + * @param resultParameters the resultParameters to set + */ + public void setResultParameters(String[] resultParameters) { + this.resultParameters = resultParameters; + } + + /** + * @return the locationResult + */ + public List<LocationResult> getLocationResult() { + return locationResult; + } + + /** + * @param locationResult the locationResult to set + */ + public void setLocationResult(List<LocationResult> locationResult) { + this.locationResult = locationResult; + } + + public void addLocationResult(LocationResult locationResult) { + if (this.locationResult == null) + { + this.locationResult = new ArrayList<>(); + } + this.locationResult.add(locationResult); + } +} diff --git a/src/main/java/no/nibio/vips/ipmdecisions/DataTransformer.java b/src/main/java/no/nibio/vips/ipmdecisions/DataTransformer.java index c4dceed1e594ef10cb8b177065258912215d8a45..189cfae0fe2a981ae82fd32b5c1bfed10a5fe034 100644 --- a/src/main/java/no/nibio/vips/ipmdecisions/DataTransformer.java +++ b/src/main/java/no/nibio/vips/ipmdecisions/DataTransformer.java @@ -21,10 +21,17 @@ package no.nibio.vips.ipmdecisions; import java.time.Instant; import java.util.ArrayList; +import java.util.Collections; import java.util.Date; +import java.util.HashSet; import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; +import net.ipmdecisions.model.entity.LocationResult; +import net.ipmdecisions.model.entity.ModelOutput; import net.ipmdecisions.weather.entity.LocationWeatherData; import net.ipmdecisions.weather.entity.WeatherData; +import no.nibio.vips.entity.Result; import no.nibio.vips.entity.WeatherObservation; /** @@ -60,4 +67,64 @@ public class DataTransformer { return retVal; } + /** + * Convert VIPS Result list to a IPM Decisions model output object + * @param VIPSResults + * @return + */ + public ModelOutput getIPMDecisionsModelOutput(List<Result> VIPSResults){ + // Loop through once first to + // a) Detect the max frequency between results and + // b) check all possible result parameters + Collections.sort(VIPSResults); + Set<String> resultParameters = new HashSet<>(); + resultParameters.add("WARNING_STATUS"); + Long minSecondsBetween = null; + Long lastTime = null; + for(Result r:VIPSResults) + { + resultParameters.addAll(r.getKeys()); + if(lastTime != null) + { + minSecondsBetween = minSecondsBetween != null ? Math.min(minSecondsBetween, (r.getValidTimeStart().getTime() - lastTime)/1000) + :(r.getValidTimeStart().getTime() - lastTime)/1000; + } + lastTime = r.getValidTimeStart().getTime(); + } + + String[] VIPSResultParameters = resultParameters.stream().toArray(String[] ::new); + String[] IPMResultParameters = new String[VIPSResultParameters.length]; + for(int i=0;i<VIPSResultParameters.length;i++) + { + String[] parts = VIPSResultParameters[i].split("\\."); + IPMResultParameters[i] = parts[parts.length-1]; + } + + // Build the result + ModelOutput retVal = new ModelOutput(); + retVal.setInterval(minSecondsBetween.intValue()); + retVal.setResultParameters(IPMResultParameters); + retVal.setTimeStart(VIPSResults.get(0).getValidTimeStart().toInstant()); + retVal.setTimeEnd(VIPSResults.get(VIPSResults.size()-1).getValidTimeStart().toInstant()); + LocationResult locationResult = new LocationResult(); + Long rows = 1 + (retVal.getTimeEnd().getEpochSecond() - retVal.getTimeStart().getEpochSecond()) / retVal.getInterval(); + Double[][] data = new Double[rows.intValue()][retVal.getResultParameters().length]; // TODO Set correct dimensions + for(Result r:VIPSResults) + { + // Calculate which row, based on + Long row = (r.getValidTimeStart().getTime()/1000 - retVal.getTimeStart().getEpochSecond()) / retVal.getInterval(); + // Using the ordering in the resultParameters + for(int i=0;i<retVal.getResultParameters().length;i++) + { + data[row.intValue()][i] = VIPSResultParameters[i].equals("WARNING_STATUS") ? + r.getWarningStatus() + : VIPSResultParameters[i] != null ? + Double.valueOf(r.getAllValues().get(VIPSResultParameters[i])) + : null; + } + } + locationResult.setData(data); + retVal.addLocationResult(locationResult); + return retVal; + } }