From d3b0f810019bc8b6f82aa24b7c1726b8b59da3b5 Mon Sep 17 00:00:00 2001
From: Tor-Einar Skog <tor-einar.skog@nibio.no>
Date: Mon, 23 Apr 2018 13:41:08 +0200
Subject: [PATCH] Tests are complete. Refatoring name

---
 .gitignore                                    |   1 +
 pom.xml                                       |   3 +-
 .../DataMatrix.java                           |  15 +-
 .../SeptoriaHumidityModel.java                | 504 ++++++++++++++++++
 .../SeptoriaWetHourModel.java                 | 273 ----------
 .../septoriahumiditymodel/texts.properties    |  21 +
 .../septoriahumiditymodel/texts_nb.properties |  22 +
 .../SeptoriaHumidityModelTest.java}           | 181 +++----
 8 files changed, 640 insertions(+), 380 deletions(-)
 mode change 100755 => 100644 .gitignore
 rename src/main/java/no/nibio/vips/model/{septoriawethourmodel => septoriahumiditymodel}/DataMatrix.java (72%)
 create mode 100644 src/main/java/no/nibio/vips/model/septoriahumiditymodel/SeptoriaHumidityModel.java
 delete mode 100644 src/main/java/no/nibio/vips/model/septoriawethourmodel/SeptoriaWetHourModel.java
 create mode 100644 src/main/resources/no/nibio/vips/model/septoriahumiditymodel/texts.properties
 create mode 100644 src/main/resources/no/nibio/vips/model/septoriahumiditymodel/texts_nb.properties
 rename src/test/java/no/nibio/vips/model/{septoriawethourmodel/SeptoriaWetHourModelTest.java => septoriahumiditymodel/SeptoriaHumidityModelTest.java} (50%)

diff --git a/.gitignore b/.gitignore
old mode 100755
new mode 100644
index 23176e3..be1e642
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,3 @@
 target/
 classes/
+/nbproject/
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index cb02bae..24c198e 100644
--- a/pom.xml
+++ b/pom.xml
@@ -2,7 +2,7 @@
 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
     <modelVersion>4.0.0</modelVersion>
     <groupId>no.nibio.vips.model</groupId>
-    <artifactId>SeptoriaWetHourModel</artifactId>
+    <artifactId>SeptoriaHumidityModel</artifactId>
     <version>1.0-SNAPSHOT</version>
     <packaging>jar</packaging>
     <dependencies>
@@ -29,4 +29,5 @@
         <maven.compiler.source>1.8</maven.compiler.source>
         <maven.compiler.target>1.8</maven.compiler.target>
     </properties>
+    <name>SeptoriaHumidityModel</name>
 </project>
\ No newline at end of file
diff --git a/src/main/java/no/nibio/vips/model/septoriawethourmodel/DataMatrix.java b/src/main/java/no/nibio/vips/model/septoriahumiditymodel/DataMatrix.java
similarity index 72%
rename from src/main/java/no/nibio/vips/model/septoriawethourmodel/DataMatrix.java
rename to src/main/java/no/nibio/vips/model/septoriahumiditymodel/DataMatrix.java
index eb4b1d9..a9af02b 100644
--- a/src/main/java/no/nibio/vips/model/septoriawethourmodel/DataMatrix.java
+++ b/src/main/java/no/nibio/vips/model/septoriahumiditymodel/DataMatrix.java
@@ -17,7 +17,7 @@
  * 
  */
 
-package no.nibio.vips.model.septoriawethourmodel;
+package no.nibio.vips.model.septoriahumiditymodel;
 
 import no.nibio.vips.util.DateMap;
 
@@ -32,8 +32,13 @@ public class DataMatrix extends DateMap {
     public final static String UM = "UM";
     // Hourly leaf wetness
     public final static String BT = "BT";
-    // Wet hour sum for sliding middle
-    public final static String WHS = "WHS";
-    // Current hour is wet hour? 1 : 0
-    public final static String WH = "WH";
+    // Humid hour sum for sliding middle
+    public final static String HHS = "HHS";
+    
+    // Current hour is humid hour? 1 : 0
+    public final static String HH = "HH";
+    // Humid period hour (consecutive humid hours)
+    public final static String HPH = "HPH";
+    // Humid period hour (consecutive humid hours) corrected for protection period
+    public final static String HPHPP = "HPHPP";
 }
diff --git a/src/main/java/no/nibio/vips/model/septoriahumiditymodel/SeptoriaHumidityModel.java b/src/main/java/no/nibio/vips/model/septoriahumiditymodel/SeptoriaHumidityModel.java
new file mode 100644
index 0000000..fc94066
--- /dev/null
+++ b/src/main/java/no/nibio/vips/model/septoriahumiditymodel/SeptoriaHumidityModel.java
@@ -0,0 +1,504 @@
+/*
+ * Copyright (c) 2018 NIBIO <http://www.nibio.no/>. 
+ * 
+ * This file is part of SeptoriaHumidityModel.
+ * SeptoriaHumidityModel 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.
+ * 
+ * SeptoriaHumidityModel 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 SeptoriaHumidityModel.  If not, see <http://www.nibio.no/licenses/>.
+ * 
+ */
+
+package no.nibio.vips.model.septoriahumiditymodel;
+
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import java.io.IOException;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Date;
+import java.util.List;
+import java.util.TimeZone;
+import no.nibio.vips.entity.ModelConfiguration;
+import no.nibio.vips.entity.Result;
+import no.nibio.vips.entity.WeatherObservation;
+import no.nibio.vips.model.ConfigValidationException;
+import no.nibio.vips.model.Model;
+import no.nibio.vips.model.ModelExcecutionException;
+import no.nibio.vips.model.ModelId;
+import no.nibio.vips.util.WeatherElements;
+import no.nibio.vips.util.WeatherUtil;
+import java.util.Calendar;
+import java.util.LinkedList;
+import no.nibio.vips.entity.ResultImpl;
+import no.nibio.vips.i18n.I18nImpl;
+import no.nibio.vips.util.CommonNamespaces;
+import no.nibio.vips.util.DateTimeInterval;
+import no.nibio.vips.util.ModelUtil;
+import no.nibio.vips.util.XDate;
+
+/**
+ * Model developed by SEGES, Denmark
+ * @copyright 2018 <a href="http://www.nibio.no/">NIBIO</a>
+ * @author Tor-Einar Skog <tor-einar.skog@nibio.no>
+ */
+public class SeptoriaHumidityModel extends I18nImpl implements Model {
+    
+    private final static ModelId MODEL_ID = new ModelId("SEPTORIAHU");
+    
+    private Date dateGs31, date3rdUpperLeafEmerging, date2ndUpperLeafEmerging, dateUpperLeafEmerging, dateGs75;
+    private Date dateSpraying1, dateSpraying2, lastSprayingProtectionEnd;
+    private DateTimeInterval protectionPeriod1, protectionPeriod2;
+    private List<DateTimeInterval> protectionPeriods;
+    private TimeZone timeZone;
+    
+    private Double thresholdRelativeHumidity, thresholdLeafWetness, thresholdPrecipitation;
+    private Integer thresholdHumidPeriodHours, slidingHoursPast, slidingHoursAhead, sprayingProtectionDays;
+    
+    private DataMatrix dataMatrix;
+    
+    private final WeatherUtil weatherUtil;
+    private final ModelUtil modelUtil;
+    
+    public SeptoriaHumidityModel(){
+        // Setting the file name of the resource bundle
+        super("no.nibio.vips.model.septoriahumiditymodel.texts");
+        this.weatherUtil = new WeatherUtil();
+        this.modelUtil = new ModelUtil();
+    }
+
+    @Override
+    public List<Result> getResult() throws ModelExcecutionException {
+        // Start date for calculation is dateGs31 (mandatory), last date is whatever is first of today + 2 days or dateGs75
+        // But inside the model, we just use the weather data as far as they reach, as long as we're not past dateGs75
+        XDate currentDate = new XDate(this.dateGs31);
+        Date lastDate = this.dataMatrix.getLastDateWithParameterValue("RR");
+        Calendar cal = Calendar.getInstance();
+        
+        // Calculating values
+        LinkedList<Integer> humidHours = new LinkedList<>();
+        LinkedList<Result> humidHoursConsecutive = new LinkedList<>();
+
+        List<Result> retVal = new ArrayList<>();
+        Boolean humidPeriodStarted = false;
+        Integer humidPeriodHour = 0;
+        // This excludes dates before gs32 and inside protection periods
+        Integer humidPeriodHourinSusceptiblePhase = 0;
+        while(currentDate.compareTo(lastDate) <= 0){
+            Double RR = this.dataMatrix.getParamDoubleValueForDate(currentDate, DataMatrix.RR);
+            Double UM = this.dataMatrix.getParamDoubleValueForDate(currentDate, DataMatrix.UM);
+            Double BT = this.dataMatrix.getParamDoubleValueForDate(currentDate, DataMatrix.BT);
+
+            if(humidHours.size() > this.slidingHoursPast + this.slidingHoursAhead){
+                humidHours.removeFirst();
+            }
+            
+            Integer humidHour = (
+                        (BT != null && BT >= this.thresholdLeafWetness)
+                        || (UM != null && UM >= this.thresholdRelativeHumidity)
+                        || (RR != null && RR >= this.thresholdPrecipitation)
+                ) ?
+                1:0;
+            
+            humidHours.addLast(humidHour);
+            this.dataMatrix.setParamIntValueForDate(currentDate, DataMatrix.HH, humidHour);
+            
+            humidPeriodHour = humidHour == 1 ? humidPeriodHour + 1 : 0;
+            this.dataMatrix.setParamIntValueForDate(currentDate, DataMatrix.HPH, humidPeriodHour);
+            
+            humidPeriodHourinSusceptiblePhase = 
+                    humidHour == 1 
+                    && !DateTimeInterval.isDateInIntervals(currentDate, this.protectionPeriods) 
+                    && currentDate.after(this.date3rdUpperLeafEmerging)
+                    ? humidPeriodHourinSusceptiblePhase + 1 : 0;
+            
+            cal.setTime(currentDate);
+            cal.add(Calendar.HOUR_OF_DAY, -this.slidingHoursAhead );
+            Date middleOfSlidingWindowDate = cal.getTime();
+            Integer slidingWindowSum = humidHours.stream().mapToInt(Integer::intValue).sum();
+            this.dataMatrix.setParamIntValueForDate(middleOfSlidingWindowDate, DataMatrix.HHS, slidingWindowSum);
+            
+            
+            Result r = new ResultImpl();
+            r.setValidTimeStart(new Date(currentDate.getTime()));
+            r.setWarningStatus(currentDate.after(this.date3rdUpperLeafEmerging) && currentDate.before(this.dateGs75) ? Result.WARNING_STATUS_NO_RISK: Result.WARNING_STATUS_NO_WARNING);
+            r.setValue(SeptoriaHumidityModel.MODEL_ID.toString(), DataMatrix.HPH, String.valueOf(humidPeriodHour));
+            r.setValue(SeptoriaHumidityModel.MODEL_ID.toString(), DataMatrix.HPHPP, String.valueOf(humidPeriodHourinSusceptiblePhase));
+            r.setValue(SeptoriaHumidityModel.MODEL_ID.toString(), DataMatrix.HH, String.valueOf(humidHour));
+            r.setValue(CommonNamespaces.NS_WEATHER, WeatherElements.LEAF_WETNESS, String.valueOf(this.dataMatrix.getParamDoubleValueForDate(currentDate, DataMatrix.BT)));
+            r.setValue(CommonNamespaces.NS_WEATHER, WeatherElements.RELATIVE_HUMIDITY_MEAN, String.valueOf(this.dataMatrix.getParamDoubleValueForDate(currentDate, DataMatrix.UM)));
+            r.setValue(CommonNamespaces.NS_WEATHER, WeatherElements.PRECIPITATION, String.valueOf(this.dataMatrix.getParamDoubleValueForDate(currentDate, DataMatrix.RR)));
+
+            if(humidHour == 1){
+                humidHoursConsecutive.add(r);
+            }
+            else
+            {
+                Integer previousHumidPeriodHourinSusceptiblePhase = retVal.size() > 0 ? Integer.valueOf(retVal.get(retVal.size()-1).getValue(SeptoriaHumidityModel.MODEL_ID.toString(), DataMatrix.HPHPP)) : null;
+                // Set all collected Result objects as part of humid period if above threshold
+                if(humidHoursConsecutive.size() > this.thresholdHumidPeriodHours)
+                {
+                    for(Result re:humidHoursConsecutive)
+                    {
+                        if(previousHumidPeriodHourinSusceptiblePhase != null &&  previousHumidPeriodHourinSusceptiblePhase > this.thresholdHumidPeriodHours
+                                && !DateTimeInterval.isDateInIntervals(re.getValidTimeStart(), this.protectionPeriods) 
+                                && re.getValidTimeStart().after(this.date3rdUpperLeafEmerging))
+                        {
+                            re.setWarningStatus(Result.WARNING_STATUS_HIGH_RISK);
+                        }
+                    }
+                }
+                else
+                {
+                    // False alarm, not enough hours. Clear
+                    humidHoursConsecutive.stream().forEach(re->re.setValue(SeptoriaHumidityModel.MODEL_ID.toString(), DataMatrix.HPH, "0"));
+                }
+                humidHoursConsecutive.clear();
+            }
+            /*
+            // Decide the warning status
+            r.setWarningStatus(Result.WARNING_STATUS_NO_WARNING);
+            if(currentDate.compareTo(this.date3rdUpperLeafEmerging) >= 0 && currentDate.compareTo(this.dateGs75) <= 0)
+            {
+                if(humidPeriodHourOutsideProtectionPeriod > this.thresholdHumidPeriodHours)
+                {
+                    r.setWarningStatus(Result.WARNING_STATUS_HIGH_RISK);
+                    //humidPeriodStarted = Boolean.TRUE;
+                }
+                else
+                {
+                    r.setWarningStatus(Result.WARNING_STATUS_NO_RISK);
+                }
+            }*/
+            
+            /*Optional<Result> previousR = retVal.stream().filter(res->res.getValidTimeStart().compareTo(middleOfSlidingWindowDate) == 0).findFirst();
+            if(previousR.isPresent()){
+                Result inTheMiddleR = previousR.get();
+                inTheMiddleR.setValue(SeptoriaHumidityModel.MODEL_ID.toString(), DataMatrix.HHS, slidingWindowSum.toString());
+                
+                // Here we also decide the warning status
+                // If growth stage > 32 (date of 3rd upper leaf emerging)
+                // Account for all leaves being alive (75 days from emerging?)
+                // And we have a humid period (19 consecutive hours) -> Treatment
+                // If treatment, no risk until x days after treatment
+                
+                
+                // Challenge
+                if(inTheMiddleR.getValidTimeStart().compareTo(this.date3rdUpperLeafEmerging) >= 0
+                        && inTheMiddleR.getValidTimeStart().compareTo(this.dateGs75) <= 0        
+                        )
+                {
+                    if(humidPeriodStarted)
+                    {
+                        inTheMiddleR.setWarningStatus(Result.WARNING_STATUS_HIGH_RISK);
+                    }
+                    else
+                    {
+                        inTheMiddleR.setWarningStatus(Result.WARNING_STATUS_NO_RISK); // The default
+                        // Are we in a period of high/long humidity?
+                        if(Integer.valueOf(inTheMiddleR.getValue(SeptoriaHumidityModel.MODEL_ID.toString(), DataMatrix.HHS)) > this.thresholdHumidPeriodHours)
+                        {
+                            // are we after the last protected period (spraying applied + duration of protection)??
+                            if(this.lastSprayingProtectionEnd == null || inTheMiddleR.getValidTimeStart().compareTo(this.lastSprayingProtectionEnd) >= 0)
+                            {
+                                inTheMiddleR.setWarningStatus(Result.WARNING_STATUS_HIGH_RISK);
+                                humidPeriodStarted = Boolean.TRUE;
+                            }
+                        }
+                    }
+                }
+                else
+                {
+                    inTheMiddleR.setWarningStatus(Result.WARNING_STATUS_NO_WARNING);
+                }
+            }*/
+            retVal.add(r);
+            
+            currentDate.add1Hour();
+        }
+        //System.out.println(this.dataMatrix.toCSV());
+        return retVal;
+    }
+    
+
+    @Override
+    public ModelId getModelId() {
+        return SeptoriaHumidityModel.MODEL_ID;
+    }
+
+    @Override
+    public String getModelName() {
+        return this.getModelName(Model.DEFAULT_LANGUAGE);
+    }
+
+    @Override
+    public String getModelName(String language) {
+        return this.getText("name", language);
+    }
+
+    @Override
+    public String getLicense() {
+        return "Copyright (c) 2018 NIBIO <http://www.nibio.no/>. \n" +
+            "\n" +
+            "This file is part of SeptoriaHumidityModel. \n" + 
+            "SeptoriaHumidityModel is free software: you can redistribute it and/or modify \n" + 
+            "it under the terms of the NIBIO Open Source License as published by \n" + 
+            "NIBIO, either version 1 of the License, or (at your option) any \n" +
+            "later version. \n" +
+            "\n" +
+            "SeptoriaHumidityModel is distributed in the hope that it will be useful, \n" +
+            "but WITHOUT ANY WARRANTY; without even the implied warranty of \n" +
+            "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the \n" +
+            "NIBIO Open Source License for more details. \n" +
+            "" +
+            "You should have received a copy of the NIBIO Open Source License \n" +
+            "along with AppleScabModel.  If not, see <http://www.nibio.no/licenses/>. \n";
+    }
+
+    @Override
+    public String getCopyright() {
+        return "(c) 2018 NIBIO (http://www.nibio.no/). Contact: post@nibio.no";
+    }
+
+    @Override
+    public String getModelDescription() {
+        return this.getModelDescription(Model.DEFAULT_LANGUAGE);
+    }
+
+    @Override
+    public String getModelDescription(String language) {
+        try
+        {
+            return this.modelUtil.getTextWithBase64EncodedImages(this.getText("description", language), this.getClass());
+        }
+        catch(IOException ex)
+        {
+            return this.getText("description", language);
+        }
+    }
+
+    @Override
+    public String getWarningStatusInterpretation() {
+        return this.getWarningStatusInterpretation(Model.DEFAULT_LANGUAGE);
+    }
+
+    @Override
+    public String getWarningStatusInterpretation(String language) {
+        return this.getText("statusInterpretation", language);
+    }
+
+    @Override
+    public String getModelUsage() {
+        return this.getModelUsage(Model.DEFAULT_LANGUAGE);
+    }
+
+    @Override
+    public String getModelUsage(String language) {
+        return this.getText("usage", language);
+    }
+
+    @Override
+    public String getSampleConfig() {
+        return "{\n" +
+        "	\"loginInfo\": {\n" +
+        "		\"username\": \"example\",\n" +
+        "		\"password\": \"example\"\n" +
+        "	},\n" +
+        "	\"modelId\": \"SEPTORIAHU\",\n" +
+        "	\"configParameters\": {\n" +
+        "		\"date3rdUpperLeafEmerging\": \"2018-05-03\",\n" +
+        "		\"sprayingProtectionDays\": 10,\n" +
+        "		\"timeZone\": \"Europe/Copenhagen\",\n" +
+        "		\"dateGs31\": \"2018-04-23\",\n" +
+        "		\"dateGs75\": \"2018-06-30\",\n" +
+        "		\"thresholdPrecipitation\": 0.2,\n" +
+        "		\"thresholdLeafWetness\": 30.0,\n" +
+        "		\"thresholdRelativeHumidity\": 85.0,\n" +
+        "		\"slidingHoursAhead\": 36,\n" +
+        "		\"leafLifeTime\": 75,\n" +
+        "		\"date2ndUpperLeafEmerging\": \"2018-05-13\",\n" +
+        "		\"slidingHoursPast\": 36,\n" +
+        "		\"dateSpraying2\": \"\",\n" +
+        "		\"thresholdHumidPeriodHours\": 19,\n" +
+        "		\"dateSpraying1\": \"\",\n" +
+        "		\"dateUpperLeafEmerging\": \"2018-05-23\",\n" +
+        "		\"observations\": [{\n" +
+        "				\"timeMeasured\": \"2018-03-25T00:00:00+02:00\",\n" +
+        "				\"elementMeasurementTypeId\": \"RR\",\n" +
+        "				\"logIntervalId\": 1,\n" +
+        "				\"value\": 0\n" +
+        "			},\n" +
+        "                       {\n" +
+        "				\"timeMeasured\": \"2018-03-25T00:00:00+02:00\",\n" +
+        "				\"elementMeasurementTypeId\": \"UM\",\n" +
+        "				\"logIntervalId\": 1,\n" +
+        "				\"value\": 88.3\n" +
+        "			},\n" +
+        "			{\n" +
+        "				\"timeMeasured\": \"2018-03-25T00:00:00+02:00\",\n" +
+        "				\"elementMeasurementTypeId\": \"BT\",\n" +
+        "				\"logIntervalId\": 1,\n" +
+        "				\"value\": 0\n" +
+        "			}\n" +
+        "		]\n" +
+        "	}\n" +
+        "}";
+    }
+
+    @Override
+    public void setConfiguration(ModelConfiguration config) throws ConfigValidationException {
+        this.dataMatrix = new DataMatrix();
+        
+        // Object deserialization tool
+        ObjectMapper mapper = new ObjectMapper();
+        
+        
+        
+        // TODO: Have defaults for these?
+        try
+        {
+            this.thresholdRelativeHumidity = mapper.convertValue(config.getConfigParameter("thresholdRelativeHumidity"), Double.class);
+            this.thresholdLeafWetness = mapper.convertValue(config.getConfigParameter("thresholdLeafWetness"), Double.class);
+            this.thresholdPrecipitation = mapper.convertValue(config.getConfigParameter("thresholdPrecipitation"), Double.class);
+            this.thresholdHumidPeriodHours = mapper.convertValue(config.getConfigParameter("thresholdHumidPeriodHours"), Integer.class);
+            this.slidingHoursPast = mapper.convertValue(config.getConfigParameter("slidingHoursPast"), Integer.class);
+            this.slidingHoursAhead = mapper.convertValue(config.getConfigParameter("slidingHoursAhead"), Integer.class);
+            this.sprayingProtectionDays = mapper.convertValue(config.getConfigParameter("sprayingProtectionDays"), Integer.class);
+            
+            this.timeZone = TimeZone.getTimeZone((String) config.getConfigParameter("timeZone"));
+        }
+        catch(NullPointerException npe)
+        {
+            throw new ConfigValidationException("Missing one or more of these parameters: "
+                    + "thresholdRelativeHumidity, thresholdLeafWetness, thresholdPrecipitation, "
+                    + "thresholdHumidPeriodHours, slidingHoursPast, slidingHoursAhead, timeZone");
+        }
+        
+        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
+        format.setTimeZone(timeZone);
+        format.setLenient(false); // Make sure it doesn't try to interpret anything, but be strict
+        try
+        {
+            this.dateGs31 = format.parse(config.getConfigParameter("dateGs31").toString());
+        }
+        catch(ParseException | NullPointerException ex)
+        {
+            throw new ConfigValidationException("Illegal date format for (or missing completely) dateGs31: " + config.getConfigParameter("dateGs31"));
+        }
+        
+        // Optional spraying info
+        Calendar cal = Calendar.getInstance(this.timeZone);
+        try
+        {
+            if(!config.getConfigParameter("dateSpraying1").toString().isEmpty())
+            {
+                this.dateSpraying1 = format.parse(config.getConfigParameter("dateSpraying1").toString());
+            }
+        }
+        catch(ParseException | NullPointerException ex)
+        {
+            if(ex instanceof ParseException)
+            {
+                throw new ConfigValidationException("Illegal date format for dateSpraying1: " + config.getConfigParameter("dateSpraying1"));
+            }
+        }
+        
+        try
+        {
+            if(!config.getConfigParameter("dateSpraying2").toString().isEmpty())
+            {
+                this.dateSpraying2 = format.parse(config.getConfigParameter("dateSpraying2").toString());
+            }
+        }
+        catch(ParseException | NullPointerException ex)
+        {
+            if(ex instanceof ParseException)
+            {
+                throw new ConfigValidationException("Illegal date format for dateSpraying2: " + config.getConfigParameter("dateSpraying2"));
+            }
+        }
+        
+        // Setting protection periods, finding last date of spraying
+        this.protectionPeriods = new ArrayList<>();
+        if(this.dateSpraying1 != null || this.dateSpraying2 != null)
+        {
+            if(this.dateSpraying1 != null){
+                cal.setTime(this.dateSpraying1);
+                cal.add(Calendar.DATE, this.sprayingProtectionDays);
+                this.protectionPeriod1 = new DateTimeInterval(this.dateSpraying1, cal.getTime());
+                this.protectionPeriods.add(protectionPeriod1);
+            }
+            
+            if(this.dateSpraying2 != null){
+                cal.setTime(this.dateSpraying2);
+                cal.add(Calendar.DATE, this.sprayingProtectionDays);
+                this.protectionPeriod2 = new DateTimeInterval(this.dateSpraying2, cal.getTime());
+                this.protectionPeriods.add(protectionPeriod2);
+            }
+ 
+            this.lastSprayingProtectionEnd = DateTimeInterval.getLastEndDate(Arrays.asList(new DateTimeInterval[]{this.protectionPeriod1,this.protectionPeriod2}));
+        }
+        
+        List<WeatherObservation> observations = mapper.convertValue(config.getConfigParameter("observations"), new TypeReference<List<WeatherObservation>>(){});
+        for(WeatherObservation o:observations)
+        {
+            switch(o.getElementMeasurementTypeId())
+            {
+                case WeatherElements.PRECIPITATION:
+                    if(o.getLogIntervalId().equals(WeatherObservation.LOG_INTERVAL_ID_1H))
+                    {
+                        this.dataMatrix.setParamDoubleValueForDate(o.getTimeMeasured(), DataMatrix.RR, o.getValue());
+                    }
+                    break;
+                case WeatherElements.RELATIVE_HUMIDITY_MEAN:
+                    if(o.getLogIntervalId().equals(WeatherObservation.LOG_INTERVAL_ID_1H))
+                    {
+                        this.dataMatrix.setParamDoubleValueForDate(o.getTimeMeasured(), DataMatrix.UM, o.getValue());
+                    }
+                    break;
+                case WeatherElements.LEAF_WETNESS:
+                    if(o.getLogIntervalId().equals(WeatherObservation.LOG_INTERVAL_ID_1H))
+                    {
+                        this.dataMatrix.setParamDoubleValueForDate(o.getTimeMeasured(), DataMatrix.BT, o.getValue());
+                    }
+                default:
+                    // Keep calm and continue importing data
+                    break;
+            }
+        }
+        
+        // Make sure we have weather data from dateGs31
+        calculateGrowthStages();
+        if(this.dataMatrix.getFirstDateWithParameterValue("RR").after(dateGs31))
+        {
+            throw new ConfigValidationException("ERROR: Missing weather data. First date with precipitation data is " + this.dataMatrix.getFirstDateWithParameterValue("RR") + ", date for GS 31 = " + this.dateGs31);
+        }
+    }
+    
+    private void calculateGrowthStages(){
+        this.dateGs31 = weatherUtil.normalizeToExactDate(dateGs31, timeZone);
+        Calendar cal = Calendar.getInstance(this.timeZone);
+        cal.setTime(this.dateGs31);
+        cal.add(Calendar.DATE, 10);
+        this.date3rdUpperLeafEmerging = cal.getTime();
+        cal.add(Calendar.DATE, 10);
+        this.date2ndUpperLeafEmerging = cal.getTime();
+        cal.add(Calendar.DATE, 10);
+        this.dateUpperLeafEmerging = cal.getTime();
+        cal.setTime(this.date3rdUpperLeafEmerging);
+        cal.set(Calendar.MONTH, Calendar.JUNE);
+        cal.set(Calendar.DATE,30);
+        this.dateGs75 = cal.getTime();
+    }
+
+}
diff --git a/src/main/java/no/nibio/vips/model/septoriawethourmodel/SeptoriaWetHourModel.java b/src/main/java/no/nibio/vips/model/septoriawethourmodel/SeptoriaWetHourModel.java
deleted file mode 100644
index 3a30f80..0000000
--- a/src/main/java/no/nibio/vips/model/septoriawethourmodel/SeptoriaWetHourModel.java
+++ /dev/null
@@ -1,273 +0,0 @@
-/*
- * Copyright (c) 2018 NIBIO <http://www.nibio.no/>. 
- * 
- * This file is part of SeptoriaWetHourModel.
- * SeptoriaWetHourModel 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.
- * 
- * SeptoriaWetHourModel 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 SeptoriaWetHourModel.  If not, see <http://www.nibio.no/licenses/>.
- * 
- */
-
-package no.nibio.vips.model.septoriawethourmodel;
-
-import com.fasterxml.jackson.core.type.TypeReference;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import java.text.ParseException;
-import java.text.SimpleDateFormat;
-import java.util.ArrayList;
-import java.util.Date;
-import java.util.List;
-import java.util.TimeZone;
-import no.nibio.vips.entity.ModelConfiguration;
-import no.nibio.vips.entity.Result;
-import no.nibio.vips.entity.WeatherObservation;
-import no.nibio.vips.model.ConfigValidationException;
-import no.nibio.vips.model.Model;
-import no.nibio.vips.model.ModelExcecutionException;
-import no.nibio.vips.model.ModelId;
-import no.nibio.vips.util.WeatherElements;
-import no.nibio.vips.util.WeatherUtil;
-import java.util.Calendar;
-import java.util.LinkedList;
-import java.util.Optional;
-import no.nibio.vips.entity.ResultImpl;
-import no.nibio.vips.util.CommonNamespaces;
-import no.nibio.vips.util.XDate;
-
-/**
- * Model developed by SEGES, Denmark
- * @copyright 2018 <a href="http://www.nibio.no/">NIBIO</a>
- * @author Tor-Einar Skog <tor-einar.skog@nibio.no>
- */
-public class SeptoriaWetHourModel implements Model {
-    
-    private final static ModelId MODEL_ID = new ModelId("SEPTORIAWH");
-    
-    private Date dateGs31, date3rdUpperLeafEmerging, date2ndUpperLeafEmerging, dateUpperLeafEmerging, dateGs75;
-    private TimeZone timeZone;
-    
-    private Double thresholdRelativeHumidity, thresholdLeafWetness, thresholdPrecipitation;
-    private Integer thresholdHumidPeriodHours, slidingHoursPast, slidingHoursAhead;
-    
-    private DataMatrix dataMatrix;
-    
-    private final WeatherUtil weatherUtil;
-    
-    public SeptoriaWetHourModel(){
-        this.weatherUtil = new WeatherUtil();
-    }
-
-    @Override
-    public List<Result> getResult() throws ModelExcecutionException {
-        // Start date for calculation is dateGs31 (mandatory), last date is whatever is first of today + 2 days or dateGs75
-        // But inside the model, we just use the weather data as far as they reach
-        XDate currentDate = new XDate(this.dateGs31);
-        Date lastDate = this.dataMatrix.getLastDateWithParameterValue("RR");
-        Calendar cal = Calendar.getInstance();
-        
-        // Calculating values
-        LinkedList<Integer> humidHours = new LinkedList<>();
-        List<Result> retVal = new ArrayList<>();
-        while(currentDate.compareTo(lastDate) <= 0){
-            Double RR = this.dataMatrix.getParamDoubleValueForDate(currentDate, DataMatrix.RR);
-            Double UM = this.dataMatrix.getParamDoubleValueForDate(currentDate, DataMatrix.UM);
-            Double BT = this.dataMatrix.getParamDoubleValueForDate(currentDate, DataMatrix.BT);
-
-            if(humidHours.size() > this.slidingHoursPast + this.slidingHoursAhead){
-                humidHours.removeFirst();
-            }
-            Integer humidHour = (
-                        (BT != null && BT >= this.thresholdLeafWetness)
-                        || (UM != null && UM >= this.thresholdRelativeHumidity)
-                        || (RR != null && RR >= this.thresholdPrecipitation)
-                ) ?
-                1:0;
-            
-            humidHours.addLast(humidHour);
-            
-            this.dataMatrix.setParamIntValueForDate(currentDate, DataMatrix.WH, humidHour);
-            
-            cal.setTime(currentDate);
-            cal.add(Calendar.HOUR_OF_DAY, -this.slidingHoursAhead );
-            Date middleOfSlidingWindowDate = cal.getTime();
-            Integer slidingWindowSum = humidHours.stream().mapToInt(Integer::intValue).sum();
-            this.dataMatrix.setParamIntValueForDate(middleOfSlidingWindowDate, DataMatrix.WHS, slidingWindowSum);
-            
-            Result r = new ResultImpl();
-            r.setValidTimeStart(new Date(currentDate.getTime()));
-            r.setValue(SeptoriaWetHourModel.MODEL_ID.toString(), DataMatrix.WH, String.valueOf(this.dataMatrix.getParamIntValueForDate(currentDate, DataMatrix.WH)));
-            r.setValue(CommonNamespaces.NS_WEATHER, WeatherElements.LEAF_WETNESS, String.valueOf(this.dataMatrix.getParamDoubleValueForDate(currentDate, DataMatrix.BT)));
-            r.setValue(CommonNamespaces.NS_WEATHER, WeatherElements.RELATIVE_HUMIDITY_MEAN, String.valueOf(this.dataMatrix.getParamDoubleValueForDate(currentDate, DataMatrix.UM)));
-            r.setValue(CommonNamespaces.NS_WEATHER, WeatherElements.PRECIPITATION, String.valueOf(this.dataMatrix.getParamDoubleValueForDate(currentDate, DataMatrix.RR)));
-            
-            Optional<Result> previousR = retVal.stream().filter(res->res.getValidTimeStart().compareTo(middleOfSlidingWindowDate) == 0).findFirst();
-            if(previousR.isPresent()){
-                previousR.get().setValue(SeptoriaWetHourModel.MODEL_ID.toString(), DataMatrix.WHS, slidingWindowSum.toString());
-            }
-            retVal.add(r);
-            
-            currentDate.add1Hour();
-        }
-        //System.out.println(this.dataMatrix.toCSV());
-        return retVal;
-    }
-
-    @Override
-    public ModelId getModelId() {
-        return SeptoriaWetHourModel.MODEL_ID;
-    }
-
-    @Override
-    public String getModelName() {
-        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
-    }
-
-    @Override
-    public String getModelName(String language) {
-        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
-    }
-
-    @Override
-    public String getLicense() {
-        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
-    }
-
-    @Override
-    public String getCopyright() {
-        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
-    }
-
-    @Override
-    public String getModelDescription() {
-        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
-    }
-
-    @Override
-    public String getModelDescription(String language) {
-        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
-    }
-
-    @Override
-    public String getWarningStatusInterpretation() {
-        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
-    }
-
-    @Override
-    public String getWarningStatusInterpretation(String language) {
-        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
-    }
-
-    @Override
-    public String getModelUsage() {
-        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
-    }
-
-    @Override
-    public String getModelUsage(String language) {
-        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
-    }
-
-    @Override
-    public String getSampleConfig() {
-        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
-    }
-
-    @Override
-    public void setConfiguration(ModelConfiguration config) throws ConfigValidationException {
-        System.out.println("JAUDA");
-        this.dataMatrix = new DataMatrix();
-        
-        // Object deserialization tool
-        ObjectMapper mapper = new ObjectMapper();
-        try
-        {
-            this.thresholdRelativeHumidity = mapper.convertValue(config.getConfigParameter("thresholdRelativeHumidity"), Double.class);
-            this.thresholdLeafWetness = mapper.convertValue(config.getConfigParameter("thresholdLeafWetness"), Double.class);
-            this.thresholdPrecipitation = mapper.convertValue(config.getConfigParameter("thresholdPrecipitation"), Double.class);
-            this.thresholdHumidPeriodHours = mapper.convertValue(config.getConfigParameter("thresholdHumidPeriodHours"), Integer.class);
-            this.slidingHoursPast = mapper.convertValue(config.getConfigParameter("slidingHoursPast"), Integer.class);
-            this.slidingHoursAhead = mapper.convertValue(config.getConfigParameter("slidingHoursAhead"), Integer.class);
-            
-            this.timeZone = TimeZone.getTimeZone((String) config.getConfigParameter("timeZone"));
-        }
-        catch(NullPointerException npe)
-        {
-            throw new ConfigValidationException("Missing one or more of these parameters: "
-                    + "thresholdRelativeHumidity, thresholdLeafWetness, thresholdPrecipitation, "
-                    + "thresholdHumidPeriodHours, slidingHoursPast, slidingHoursAhead, timeZone");
-        }
-        
-        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
-        format.setTimeZone(timeZone);
-        try
-        {
-            this.dateGs31 = format.parse(config.getConfigParameter("dateGs31").toString());
-        }
-        catch(ParseException | NullPointerException ex)
-        {
-            throw new ConfigValidationException("Illegal date format for (or missing completely) dateGs31: " + config.getConfigParameter("dateGs31"));
-        }
-        
-        WeatherUtil wUtil = new WeatherUtil();
-        List<WeatherObservation> observations = mapper.convertValue(config.getConfigParameter("observations"), new TypeReference<List<WeatherObservation>>(){});
-        for(WeatherObservation o:observations)
-        {
-            switch(o.getElementMeasurementTypeId())
-            {
-                case WeatherElements.PRECIPITATION:
-                    if(o.getLogIntervalId().equals(WeatherObservation.LOG_INTERVAL_ID_1H))
-                    {
-                        this.dataMatrix.setParamDoubleValueForDate(o.getTimeMeasured(), DataMatrix.RR, o.getValue());
-                    }
-                    break;
-                case WeatherElements.RELATIVE_HUMIDITY_MEAN:
-                    if(o.getLogIntervalId().equals(WeatherObservation.LOG_INTERVAL_ID_1H))
-                    {
-                        this.dataMatrix.setParamDoubleValueForDate(o.getTimeMeasured(), DataMatrix.UM, o.getValue());
-                    }
-                    break;
-                case WeatherElements.LEAF_WETNESS:
-                    if(o.getLogIntervalId().equals(WeatherObservation.LOG_INTERVAL_ID_1H))
-                    {
-                        this.dataMatrix.setParamDoubleValueForDate(o.getTimeMeasured(), DataMatrix.BT, o.getValue());
-                    }
-                default:
-                    // Keep calm and continue importing data
-                    break;
-            }
-        }
-        
-        // Make sure we have weather data from dateGs31
-        calculateGrowthStages();
-        if(this.dataMatrix.getFirstDateWithParameterValue("RR").after(dateGs31))
-        {
-            throw new ConfigValidationException("ERROR: Missing weather data. First date with precipitation data is " + this.dataMatrix.getFirstDateWithParameterValue("RR") + ", date for GS 31 = " + this.dateGs31);
-        }
-    }
-    
-    private void calculateGrowthStages(){
-        this.dateGs31 = weatherUtil.normalizeToExactDate(dateGs31, timeZone);
-        Calendar cal = Calendar.getInstance(this.timeZone);
-        cal.setTime(this.dateGs31);
-        cal.add(Calendar.DATE, 10);
-        this.date3rdUpperLeafEmerging = cal.getTime();
-        cal.add(Calendar.DATE, 10);
-        this.date2ndUpperLeafEmerging = cal.getTime();
-        cal.add(Calendar.DATE, 10);
-        this.dateUpperLeafEmerging = cal.getTime();
-        cal.setTime(this.date3rdUpperLeafEmerging);
-        cal.set(Calendar.MONTH, Calendar.JUNE);
-        cal.set(Calendar.DATE,30);
-        this.dateGs75 = cal.getTime();
-    }
-
-}
diff --git a/src/main/resources/no/nibio/vips/model/septoriahumiditymodel/texts.properties b/src/main/resources/no/nibio/vips/model/septoriahumiditymodel/texts.properties
new file mode 100644
index 0000000..b31ad35
--- /dev/null
+++ b/src/main/resources/no/nibio/vips/model/septoriahumiditymodel/texts.properties
@@ -0,0 +1,21 @@
+# Copyright (c) 2014 NIBIO <http://www.nibio.no/>. 
+# 
+# This file is part of AppleScabModel.
+# AppleScabModel 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.
+# 
+# AppleScabModel 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 AppleScabModel.  If not, see <http://www.nibio.no/licenses/>.
+# 
+
+name=Septoria Humitidy Model
+usage=TODO\t
+description=TODO
+statusInterpretation=TODO
diff --git a/src/main/resources/no/nibio/vips/model/septoriahumiditymodel/texts_nb.properties b/src/main/resources/no/nibio/vips/model/septoriahumiditymodel/texts_nb.properties
new file mode 100644
index 0000000..5743f00
--- /dev/null
+++ b/src/main/resources/no/nibio/vips/model/septoriahumiditymodel/texts_nb.properties
@@ -0,0 +1,22 @@
+# Copyright (c) 2014 NIBIO <http://www.nibio.no/>. 
+# 
+# This file is part of AppleScabModel.
+# AppleScabModel 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.
+# 
+# AppleScabModel 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 AppleScabModel.  If not, see <http://www.nibio.no/licenses/>.
+# 
+
+
+name=Septoria-fuktmodell
+usage=TODO
+description=TODO
+statusInterpretation=TODO
diff --git a/src/test/java/no/nibio/vips/model/septoriawethourmodel/SeptoriaWetHourModelTest.java b/src/test/java/no/nibio/vips/model/septoriahumiditymodel/SeptoriaHumidityModelTest.java
similarity index 50%
rename from src/test/java/no/nibio/vips/model/septoriawethourmodel/SeptoriaWetHourModelTest.java
rename to src/test/java/no/nibio/vips/model/septoriahumiditymodel/SeptoriaHumidityModelTest.java
index 9bc8705..b57ee0b 100644
--- a/src/test/java/no/nibio/vips/model/septoriawethourmodel/SeptoriaWetHourModelTest.java
+++ b/src/test/java/no/nibio/vips/model/septoriahumiditymodel/SeptoriaHumidityModelTest.java
@@ -1,27 +1,28 @@
 /*
  * Copyright (c) 2018 NIBIO <http://www.nibio.no/>. 
  * 
- * This file is part of SeptoriaWetHourModel.
- * SeptoriaWetHourModel is free software: you can redistribute it and/or modify
+ * This file is part of SeptoriaHumidityModel.
+ * SeptoriaHumidityModel 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.
  * 
- * SeptoriaWetHourModel is distributed in the hope that it will be useful,
+ * SeptoriaHumidityModel 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 SeptoriaWetHourModel.  If not, see <http://www.nibio.no/licenses/>.
+ * along with SeptoriaHumidityModel.  If not, see <http://www.nibio.no/licenses/>.
  * 
  */
-package no.nibio.vips.model.septoriawethourmodel;
+package no.nibio.vips.model.septoriahumiditymodel;
 
 
 import java.util.List;
 import no.nibio.vips.entity.ModelConfiguration;
 import no.nibio.vips.entity.Result;
+import no.nibio.vips.model.ConfigValidationException;
 import no.nibio.vips.model.ModelId;
 import no.nibio.vips.util.test.WeatherDataFileReader;
 import org.junit.After;
@@ -35,11 +36,11 @@ import static org.junit.Assert.*;
  *
  * @author treinar
  */
-public class SeptoriaWetHourModelTest {
+public class SeptoriaHumidityModelTest {
     
     private WeatherDataFileReader weatherDataFileReader;
     
-    public SeptoriaWetHourModelTest() {
+    public SeptoriaHumidityModelTest() {
     }
     
     @BeforeClass
@@ -60,12 +61,12 @@ public class SeptoriaWetHourModelTest {
     }
 
     /**
-     * Test of getResult method, of class SeptoriaWetHourModel.
+     * Test of getResult method, of class SeptoriaHumidityModel.
      */
     @org.junit.Test
     public void testGetResult() throws Exception {
         System.out.println("getResult");
-        SeptoriaWetHourModel instance = new SeptoriaWetHourModel();
+        SeptoriaHumidityModel instance = new SeptoriaHumidityModel();
         ModelConfiguration config = this.weatherDataFileReader.getModelConfigurationWithWeatherData("/2017_aalborg.json", instance.getModelId().toString());
         config.setConfigParameter("timeZone", "Europe/Oslo");
         config.setConfigParameter("thresholdRelativeHumidity", 85.0);
@@ -74,197 +75,168 @@ public class SeptoriaWetHourModelTest {
         config.setConfigParameter("thresholdHumidPeriodHours", 19);
         config.setConfigParameter("slidingHoursPast", 36);
         config.setConfigParameter("slidingHoursAhead", 36);
+        config.setConfigParameter("sprayingProtectionDays", 10);
         config.setConfigParameter("dateGs31", "2017-05-01");
+        config.setConfigParameter("dateSpraying1", "2017-05-11");
+        config.setConfigParameter("dateSpraying2", "2017-05-19");
         
         
         instance.setConfiguration(config);
-        List<Result> expResult = null;
+        
         List<Result> result = instance.getResult();
         assertNotNull(result);
-        result.stream().forEach(r->System.out.println(r));
-        // TODO review the generated test code and remove the default call to fail.
-        fail("The test case is a prototype.");
+        //result.stream().forEach(r->System.out.println(r));
+
     }
 
     /**
-     * Test of getModelId method, of class SeptoriaWetHourModel.
+     * Test of getModelId method, of class SeptoriaHumidityModel.
      */
-    //@org.junit.Test
+    @org.junit.Test
     public void testGetModelId() {
         System.out.println("getModelId");
-        SeptoriaWetHourModel instance = new SeptoriaWetHourModel();
-        ModelId expResult = null;
+        SeptoriaHumidityModel instance = new SeptoriaHumidityModel();
+        ModelId expResult = new ModelId("SEPTORIAHU");
         ModelId result = instance.getModelId();
-        assertEquals(expResult, result);
-        // TODO review the generated test code and remove the default call to fail.
-        fail("The test case is a prototype.");
+        assertEquals(expResult.toString(), result.toString());
+        
     }
 
     /**
-     * Test of getModelName method, of class SeptoriaWetHourModel.
+     * Test of getModelName method, of class SeptoriaHumidityModel.
      */
-    //@org.junit.Test
+    @org.junit.Test
     public void testGetModelName_0args() {
         System.out.println("getModelName");
-        SeptoriaWetHourModel instance = new SeptoriaWetHourModel();
-        String expResult = "";
+        SeptoriaHumidityModel instance = new SeptoriaHumidityModel();
         String result = instance.getModelName();
-        assertEquals(expResult, result);
-        // TODO review the generated test code and remove the default call to fail.
-        fail("The test case is a prototype.");
+        assertNotNull(result);
+        
     }
 
     /**
-     * Test of getModelName method, of class SeptoriaWetHourModel.
+     * Test of getModelName method, of class SeptoriaHumidityModel.
      */
-    //@org.junit.Test
+    @org.junit.Test
     public void testGetModelName_String() {
         System.out.println("getModelName");
         String language = "";
-        SeptoriaWetHourModel instance = new SeptoriaWetHourModel();
-        String expResult = "";
+        SeptoriaHumidityModel instance = new SeptoriaHumidityModel();
         String result = instance.getModelName(language);
-        assertEquals(expResult, result);
-        // TODO review the generated test code and remove the default call to fail.
-        fail("The test case is a prototype.");
+        assertNotNull(result);
     }
 
     /**
-     * Test of getLicense method, of class SeptoriaWetHourModel.
+     * Test of getLicense method, of class SeptoriaHumidityModel.
      */
-    //@org.junit.Test
+    @org.junit.Test
     public void testGetLicense() {
         System.out.println("getLicense");
-        SeptoriaWetHourModel instance = new SeptoriaWetHourModel();
-        String expResult = "";
+        SeptoriaHumidityModel instance = new SeptoriaHumidityModel();
         String result = instance.getLicense();
-        assertEquals(expResult, result);
-        // TODO review the generated test code and remove the default call to fail.
-        fail("The test case is a prototype.");
+        assertNotNull(result);
+        
     }
 
     /**
-     * Test of getCopyright method, of class SeptoriaWetHourModel.
+     * Test of getCopyright method, of class SeptoriaHumidityModel.
      */
-    //@org.junit.Test
+    @org.junit.Test
     public void testGetCopyright() {
         System.out.println("getCopyright");
-        SeptoriaWetHourModel instance = new SeptoriaWetHourModel();
-        String expResult = "";
+        SeptoriaHumidityModel instance = new SeptoriaHumidityModel();
         String result = instance.getCopyright();
-        assertEquals(expResult, result);
-        // TODO review the generated test code and remove the default call to fail.
-        fail("The test case is a prototype.");
+        assertNotNull(result);
     }
 
     /**
-     * Test of getModelDescription method, of class SeptoriaWetHourModel.
+     * Test of getModelDescription method, of class SeptoriaHumidityModel.
      */
-    //@org.junit.Test
+    @org.junit.Test
     public void testGetModelDescription_0args() {
         System.out.println("getModelDescription");
-        SeptoriaWetHourModel instance = new SeptoriaWetHourModel();
-        String expResult = "";
+        SeptoriaHumidityModel instance = new SeptoriaHumidityModel();
         String result = instance.getModelDescription();
-        assertEquals(expResult, result);
-        // TODO review the generated test code and remove the default call to fail.
-        fail("The test case is a prototype.");
+        assertNotNull(result);
     }
 
     /**
-     * Test of getModelDescription method, of class SeptoriaWetHourModel.
+     * Test of getModelDescription method, of class SeptoriaHumidityModel.
      */
-    //@org.junit.Test
+    @org.junit.Test
     public void testGetModelDescription_String() {
         System.out.println("getModelDescription");
         String language = "";
-        SeptoriaWetHourModel instance = new SeptoriaWetHourModel();
-        String expResult = "";
+        SeptoriaHumidityModel instance = new SeptoriaHumidityModel();
         String result = instance.getModelDescription(language);
-        assertEquals(expResult, result);
-        // TODO review the generated test code and remove the default call to fail.
-        fail("The test case is a prototype.");
+        assertNotNull(result);
     }
 
     /**
-     * Test of getWarningStatusInterpretation method, of class SeptoriaWetHourModel.
+     * Test of getWarningStatusInterpretation method, of class SeptoriaHumidityModel.
      */
-    //@org.junit.Test
+    @org.junit.Test
     public void testGetWarningStatusInterpretation_0args() {
         System.out.println("getWarningStatusInterpretation");
-        SeptoriaWetHourModel instance = new SeptoriaWetHourModel();
-        String expResult = "";
+        SeptoriaHumidityModel instance = new SeptoriaHumidityModel();
         String result = instance.getWarningStatusInterpretation();
-        assertEquals(expResult, result);
-        // TODO review the generated test code and remove the default call to fail.
-        fail("The test case is a prototype.");
+        assertNotNull(result);
     }
 
     /**
-     * Test of getWarningStatusInterpretation method, of class SeptoriaWetHourModel.
+     * Test of getWarningStatusInterpretation method, of class SeptoriaHumidityModel.
      */
-    //@org.junit.Test
+    @org.junit.Test
     public void testGetWarningStatusInterpretation_String() {
         System.out.println("getWarningStatusInterpretation");
         String language = "";
-        SeptoriaWetHourModel instance = new SeptoriaWetHourModel();
-        String expResult = "";
+        SeptoriaHumidityModel instance = new SeptoriaHumidityModel();
         String result = instance.getWarningStatusInterpretation(language);
-        assertEquals(expResult, result);
-        // TODO review the generated test code and remove the default call to fail.
-        fail("The test case is a prototype.");
+        assertNotNull(result);
     }
 
     /**
-     * Test of getModelUsage method, of class SeptoriaWetHourModel.
+     * Test of getModelUsage method, of class SeptoriaHumidityModel.
      */
-    //@org.junit.Test
+    @org.junit.Test
     public void testGetModelUsage_0args() {
         System.out.println("getModelUsage");
-        SeptoriaWetHourModel instance = new SeptoriaWetHourModel();
-        String expResult = "";
+        SeptoriaHumidityModel instance = new SeptoriaHumidityModel();
         String result = instance.getModelUsage();
-        assertEquals(expResult, result);
-        // TODO review the generated test code and remove the default call to fail.
-        fail("The test case is a prototype.");
+        assertNotNull(result);
     }
 
     /**
-     * Test of getModelUsage method, of class SeptoriaWetHourModel.
+     * Test of getModelUsage method, of class SeptoriaHumidityModel.
      */
-    //@org.junit.Test
+    @org.junit.Test
     public void testGetModelUsage_String() {
         System.out.println("getModelUsage");
         String language = "";
-        SeptoriaWetHourModel instance = new SeptoriaWetHourModel();
-        String expResult = "";
+        SeptoriaHumidityModel instance = new SeptoriaHumidityModel();
         String result = instance.getModelUsage(language);
-        assertEquals(expResult, result);
-        // TODO review the generated test code and remove the default call to fail.
-        fail("The test case is a prototype.");
+        assertNotNull(result);
     }
 
     /**
-     * Test of getSampleConfig method, of class SeptoriaWetHourModel.
+     * Test of getSampleConfig method, of class SeptoriaHumidityModel.
      */
-    //@org.junit.Test
+    @org.junit.Test
     public void testGetSampleConfig() {
         System.out.println("getSampleConfig");
-        SeptoriaWetHourModel instance = new SeptoriaWetHourModel();
-        String expResult = "";
+        SeptoriaHumidityModel instance = new SeptoriaHumidityModel();
         String result = instance.getSampleConfig();
-        assertEquals(expResult, result);
-        // TODO review the generated test code and remove the default call to fail.
-        fail("The test case is a prototype.");
+        assertNotNull(result);
+        
     }
 
     /**
-     * Test of setConfiguration method, of class SeptoriaWetHourModel.
+     * Test of setConfiguration method, of class SeptoriaHumidityModel.
      */
     @org.junit.Test
     public void testSetConfiguration() throws Exception {
         System.out.println("setConfiguration");
-        SeptoriaWetHourModel instance = new SeptoriaWetHourModel();
+        SeptoriaHumidityModel instance = new SeptoriaHumidityModel();
         ModelConfiguration config = this.weatherDataFileReader.getModelConfigurationWithWeatherData("/2017_aas.json", instance.getModelId().toString());
         config.setConfigParameter("timeZone", "Europe/Oslo");
         config.setConfigParameter("thresholdRelativeHumidity", 85.0);
@@ -273,10 +245,17 @@ public class SeptoriaWetHourModelTest {
         config.setConfigParameter("thresholdHumidPeriodHours", 19);
         config.setConfigParameter("slidingHoursPast", 36);
         config.setConfigParameter("slidingHoursAhead", 36);
+        config.setConfigParameter("sprayingProtectionDays", 10);
         config.setConfigParameter("dateGs31", "2017-05-01");
+        config.setConfigParameter("dateSpraying1", "2017-05-01");
+        config.setConfigParameter("dateSpraying2", "2017-05-10");
         
-        
-        instance.setConfiguration(config);
+        try
+        {
+            instance.setConfiguration(config);
+        }catch(ConfigValidationException ex){
+            fail(ex.getMessage());
+        }
         
     }
     
-- 
GitLab