extensions/net.sf.basedb.labenv/trunk/src/net/sf/basedb/labenv/servlet/LabEnvironmentDisplayServlet.java

Code
Comments
Other
Rev Date Author Line
2401 06 May 14 olle 1 package net.sf.basedb.labenv.servlet;
2401 06 May 14 olle 2
2401 06 May 14 olle 3 import java.io.IOException;
2401 06 May 14 olle 4 import java.text.DateFormat;
2401 06 May 14 olle 5 import java.text.SimpleDateFormat;
2401 06 May 14 olle 6 import java.util.Calendar;
2401 06 May 14 olle 7 import java.util.Collections;
2401 06 May 14 olle 8 import java.util.Date;
2401 06 May 14 olle 9 import java.util.GregorianCalendar;
2401 06 May 14 olle 10 import java.util.HashMap;
2401 06 May 14 olle 11 import java.util.ArrayList;
2401 06 May 14 olle 12 import java.util.List;
2401 06 May 14 olle 13
2401 06 May 14 olle 14 import javax.servlet.ServletException;
2401 06 May 14 olle 15 import javax.servlet.http.HttpServlet;
2401 06 May 14 olle 16 import javax.servlet.http.HttpServletRequest;
2401 06 May 14 olle 17 import javax.servlet.http.HttpServletResponse;
2401 06 May 14 olle 18 import net.sf.basedb.labenv.LabEnv;
2401 06 May 14 olle 19 import net.sf.basedb.labenv.LabEnvironment;
2401 06 May 14 olle 20 import net.sf.basedb.labenv.LabEnvironmentConfiguration;
2401 06 May 14 olle 21 import net.sf.basedb.labenv.converter.DateToStringConverter;
2401 06 May 14 olle 22 import net.sf.basedb.labenv.converter.StringToDateConverter;
2401 06 May 14 olle 23 import net.sf.basedb.labenv.dao.LabEnvironmentData;
2401 06 May 14 olle 24 import net.sf.basedb.labenv.dao.LabSensorConfig;
2401 06 May 14 olle 25 import net.sf.basedb.labenv.util.LabEnvironmentStorageUtil;
2401 06 May 14 olle 26 import net.sf.basedb.labenv.util.ReportTableUtil;
2401 06 May 14 olle 27 import net.sf.basedb.util.EqualsHelper;
2401 06 May 14 olle 28 import net.sf.basedb.util.Values;
2401 06 May 14 olle 29 import net.sf.basedb.util.error.ThrowableUtil;
2401 06 May 14 olle 30 import net.sf.basedb.util.formatter.DateFormatter;
2401 06 May 14 olle 31
2401 06 May 14 olle 32 import org.json.simple.JSONArray;
2401 06 May 14 olle 33 import org.json.simple.JSONObject;
2401 06 May 14 olle 34 import org.slf4j.Logger;
2401 06 May 14 olle 35 import org.slf4j.LoggerFactory;
2401 06 May 14 olle 36
2401 06 May 14 olle 37 public class LabEnvironmentDisplayServlet
2401 06 May 14 olle 38   extends HttpServlet 
2401 06 May 14 olle 39 {
3013 05 Dec 14 nicklas 40
3013 05 Dec 14 nicklas 41   private static final long serialVersionUID = 4079851665481814331L;
3013 05 Dec 14 nicklas 42   
2401 06 May 14 olle 43   private static final Logger log = LoggerFactory.getLogger(LabEnvironmentDisplayServlet.class);
2401 06 May 14 olle 44   public static final String weekdayFilterAll = "all";
2401 06 May 14 olle 45   public static final String weekdayFilterMondayToFriday = "mondaytofriday";
2401 06 May 14 olle 46   public static final String weekdayFilterSaturdayToSunday = "saturdaytosunday";
2401 06 May 14 olle 47   public static final String weekdayFilterWorkdays = "workdays";
2401 06 May 14 olle 48   public static final String weekdayFilterNonWorkdays = "nonworkdays";
2401 06 May 14 olle 49   public static final String variableTypeTemperature = "temperature";
2401 06 May 14 olle 50   public static final String variableTypeHumidity = "humidity";
2401 06 May 14 olle 51   /**
2401 06 May 14 olle 52     Default converter for string values to date+time values: yyyyMMdd HHmm
2401 06 May 14 olle 53     @since 1.0
2401 06 May 14 olle 54   */
2401 06 May 14 olle 55   public static final StringToDateConverter CONVERTER_STRING_TO_DATETIME = new StringToDateConverter(new SimpleDateFormat("yyyyMMdd HHmm"));
2401 06 May 14 olle 56   public static final StringToDateConverter CONVERTER_STRING_TO_DATE = new StringToDateConverter(new SimpleDateFormat("yyyy-MM-dd"));
2401 06 May 14 olle 57
2401 06 May 14 olle 58   private ReportTableUtil tableUtil;
2401 06 May 14 olle 59
2401 06 May 14 olle 60   private static int numberOfDecimals = 1;
2401 06 May 14 olle 61   private int minItemsForStatisticsCalculation = 5;
2401 06 May 14 olle 62   private DateFormat yearMonthDayFormat = new SimpleDateFormat("YYYYMMdd");
2401 06 May 14 olle 63   private DateFormat monthDayFormat = new SimpleDateFormat("MMdd");
2401 06 May 14 olle 64   private HashMap<String, Boolean> workdayFlagSeHashMap = new HashMap<String, Boolean>();
2401 06 May 14 olle 65   
2401 06 May 14 olle 66   public LabEnvironmentDisplayServlet()
2401 06 May 14 olle 67   {
2401 06 May 14 olle 68     // Create new instance of ReportTableUtil for common report table utilities
2401 06 May 14 olle 69     tableUtil = new ReportTableUtil();
2401 06 May 14 olle 70   }
2401 06 May 14 olle 71
2401 06 May 14 olle 72
2401 06 May 14 olle 73   @Override
2401 06 May 14 olle 74   protected void doGet(HttpServletRequest req, HttpServletResponse resp)
2401 06 May 14 olle 75     throws ServletException, IOException 
2401 06 May 14 olle 76   {  
2401 06 May 14 olle 77     String ID = req.getParameter("ID");
2401 06 May 14 olle 78     String cmd = req.getParameter("cmd");
2401 06 May 14 olle 79     resp.setContentType("application/json");
2401 06 May 14 olle 80     resp.setCharacterEncoding("UTF-8");
2401 06 May 14 olle 81     
2401 06 May 14 olle 82     JSONObject json = new JSONObject();
2401 06 May 14 olle 83     json.put("status", "ok");
2401 06 May 14 olle 84
2401 06 May 14 olle 85     try
2401 06 May 14 olle 86     {
2401 06 May 14 olle 87       log.debug("cmd = " + cmd);
2401 06 May 14 olle 88       if ("labenvironmentdailydisplay".equals(cmd) ||
2401 06 May 14 olle 89           "labenvironmentweeklydisplay".equals(cmd) ||
4526 19 Jun 17 nicklas 90           "labenvironmentoverviewdisplay".equals(cmd) ||
4526 19 Jun 17 nicklas 91           "last24hours".equals(cmd))
2401 06 May 14 olle 92       {
2401 06 May 14 olle 93         String viewType = "dailyDisplay";
2401 06 May 14 olle 94         if ("labenvironmentweeklydisplay".equals(cmd))
2401 06 May 14 olle 95         {
2401 06 May 14 olle 96           viewType = "weeklyDisplay";
2401 06 May 14 olle 97         }
2401 06 May 14 olle 98         else if ("labenvironmentoverviewdisplay".equals(cmd))
2401 06 May 14 olle 99         {
2401 06 May 14 olle 100           viewType = "overviewDisplay";
2401 06 May 14 olle 101         }
2401 06 May 14 olle 102         // Get query time interval
4525 15 Jun 17 nicklas 103         String startDateStrInput = Values.getStringOrNull(req.getParameter("fdate"));
2401 06 May 14 olle 104         String startDateStr = startDateStrInput;
2401 06 May 14 olle 105         if (!"labenvironmentoverviewdisplay".equals(cmd))
2401 06 May 14 olle 106         {
2401 06 May 14 olle 107           // If start date not set, set it to current date
2401 06 May 14 olle 108           if (startDateStr == null || startDateStr.equals(""))
2401 06 May 14 olle 109           {
2401 06 May 14 olle 110             DateFormatter dateFormat = new DateFormatter("yyyyMMdd");
2401 06 May 14 olle 111             startDateStr = dateFormat.format(new Date());
2401 06 May 14 olle 112           }
2401 06 May 14 olle 113         }
2401 06 May 14 olle 114         String startTimeStr = "0000";
2401 06 May 14 olle 115         String startDateTimeStr = dateAndTimeStringsToDateTimeString(startDateStr, startTimeStr);
2401 06 May 14 olle 116         Date startTime = dateTimeStringToDate(startDateTimeStr);
2401 06 May 14 olle 117         log.debug("startDateStr = " + startDateStr + " startTime = " + startTime);
2401 06 May 14 olle 118         if ("labenvironmentweeklydisplay".equals(cmd))
2401 06 May 14 olle 119         {
2401 06 May 14 olle 120           // If start date not set, set it to 6 days before current date
2401 06 May 14 olle 121           if (startDateStrInput == null || startDateStrInput.equals(""))
2401 06 May 14 olle 122           {
2401 06 May 14 olle 123             startTime = addDays(startTime, -6);
2401 06 May 14 olle 124           }
2401 06 May 14 olle 125         }
2401 06 May 14 olle 126         log.debug("startDateStrInput = " + startDateStrInput + "startDateStr = " + startDateStr + " startTime = " + startTime);
2401 06 May 14 olle 127         Date endTime = null;
4526 19 Jun 17 nicklas 128         if ("last24hours".equals(cmd))
2401 06 May 14 olle 129         {
4526 19 Jun 17 nicklas 130           endTime = new Date();
4526 19 Jun 17 nicklas 131           startTime = new Date(endTime.getTime() - 1000L * 3600L * 24);
4526 19 Jun 17 nicklas 132           viewType = "last24hours";
4526 19 Jun 17 nicklas 133         }
4526 19 Jun 17 nicklas 134         else if ("labenvironmentdailydisplay".equals(cmd))
4526 19 Jun 17 nicklas 135         {
2401 06 May 14 olle 136           endTime = addDays(startTime, 1);
2401 06 May 14 olle 137         }
2401 06 May 14 olle 138         else if ("labenvironmentweeklydisplay".equals(cmd))
2401 06 May 14 olle 139         {
2401 06 May 14 olle 140           endTime = addDays(startTime, 7);
2401 06 May 14 olle 141         }
2401 06 May 14 olle 142         else if ("labenvironmentoverviewdisplay".equals(cmd))
2401 06 May 14 olle 143         {
2401 06 May 14 olle 144           // Set end time to current time
2401 06 May 14 olle 145           endTime = new Date();
2401 06 May 14 olle 146         }
2401 06 May 14 olle 147         // If end time is in the future, re-set it to current time
2401 06 May 14 olle 148         Date currentTime = new Date();
2401 06 May 14 olle 149         if (endTime.after(currentTime))
2401 06 May 14 olle 150         {
2401 06 May 14 olle 151           endTime = currentTime;
2401 06 May 14 olle 152         }
2401 06 May 14 olle 153         log.debug("endTime = " + endTime);
2401 06 May 14 olle 154         String weekdayFilter = null;
2401 06 May 14 olle 155         String weekdayFilterParameter = Values.getString(req.getParameter("weekdayfilter"), null);
2401 06 May 14 olle 156         if (weekdayFilterParameter != null)
2401 06 May 14 olle 157         {
2401 06 May 14 olle 158           weekdayFilter = weekdayFilterParameter;
2401 06 May 14 olle 159         }
2401 06 May 14 olle 160         log.debug("weekdayFilter = " + weekdayFilter);
2401 06 May 14 olle 161         // Optional daytime filter
2401 06 May 14 olle 162         String filterFromTime = null;
2401 06 May 14 olle 163         String filterFromTimeParameter = Values.getString(req.getParameter("filterfromtime"), null);
2401 06 May 14 olle 164         if (filterFromTimeParameter != null)
2401 06 May 14 olle 165         {
2401 06 May 14 olle 166           filterFromTime = filterFromTimeParameter;
2401 06 May 14 olle 167         }
2401 06 May 14 olle 168         log.debug("filterFromTime = " + filterFromTime);
2401 06 May 14 olle 169         String filterToTime = null;
2401 06 May 14 olle 170         String filterToTimeParameter = Values.getString(req.getParameter("filtertotime"), null);
2401 06 May 14 olle 171         if (filterToTimeParameter != null)
2401 06 May 14 olle 172         {
2401 06 May 14 olle 173           filterToTime = filterToTimeParameter;
2401 06 May 14 olle 174         }
2401 06 May 14 olle 175         log.debug("filterToTime = " + filterToTime);
2401 06 May 14 olle 176         String chartVariant = "all";
2401 06 May 14 olle 177         String chartVariantParameter = Values.getString(req.getParameter("cvariant"), null);
2401 06 May 14 olle 178         if (chartVariantParameter != null)
2401 06 May 14 olle 179         {
2401 06 May 14 olle 180           chartVariant = chartVariantParameter;
2401 06 May 14 olle 181         }
2401 06 May 14 olle 182         log.debug("chartVariant = " + chartVariant);
2401 06 May 14 olle 183         // Get lab environment configuration from singleton LabEnvironment
2401 06 May 14 olle 184         LabEnvironment labEnvironment = LabEnvironment.getInstance();
2401 06 May 14 olle 185         LabEnvironmentConfiguration labEnvironmentConfiguration = labEnvironment.getLabEnvironmentConfiguration();
2401 06 May 14 olle 186         // Create sensor URL list
2401 06 May 14 olle 187         List<String> sensorUrlList = new ArrayList<String>();
2401 06 May 14 olle 188         if (chartVariant.equals("all"))
2401 06 May 14 olle 189         {
2401 06 May 14 olle 190           List<LabSensorConfig> labSensorConfigList = labEnvironmentConfiguration.getLabSensorConfigList();
2401 06 May 14 olle 191           for (LabSensorConfig labSensorConf: labSensorConfigList)
2401 06 May 14 olle 192           {
2401 06 May 14 olle 193             String startDate = labSensorConf.getStartDate();
2401 06 May 14 olle 194             if (startDate != null && !startDate.equals(""))
2401 06 May 14 olle 195             {
2401 06 May 14 olle 196               sensorUrlList.add(labSensorConf.getUrl());
2401 06 May 14 olle 197             }
2401 06 May 14 olle 198           }
2401 06 May 14 olle 199         }
2401 06 May 14 olle 200         else
2401 06 May 14 olle 201         {
2401 06 May 14 olle 202           sensorUrlList.add(chartVariant);
2401 06 May 14 olle 203         }
2401 06 May 14 olle 204         log.debug("chartVariant = " + chartVariant + " sensorUrlList = " + sensorUrlList);
2463 02 Jun 14 olle 205         // Optional page title
2463 02 Jun 14 olle 206         String pageTitle = null;
2463 02 Jun 14 olle 207         String pageTitleParameter = Values.getString(req.getParameter("pagetitle"), null);
2463 02 Jun 14 olle 208         if (pageTitleParameter != null)
2463 02 Jun 14 olle 209         {
2463 02 Jun 14 olle 210           pageTitle = pageTitleParameter;
2463 02 Jun 14 olle 211         }
2463 02 Jun 14 olle 212         log.debug("pageTitle = " + pageTitle);
2401 06 May 14 olle 213         // Create JSON array for plot data
2401 06 May 14 olle 214         JSONArray jsonStatisticsPlotArray = new JSONArray();
3018 09 Dec 14 nicklas 215         LabEnvironmentStorageUtil storage = new LabEnvironmentStorageUtil();
2401 06 May 14 olle 216         for (String sensorUrl: sensorUrlList)
2401 06 May 14 olle 217         {
2401 06 May 14 olle 218           // Get lab sensor number from lab sensor url
2401 06 May 14 olle 219           LabSensorConfig labSensorConfig = labEnvironmentConfiguration.findByUrl(sensorUrl);
2401 06 May 14 olle 220           Integer labSensorNumber = null;
2401 06 May 14 olle 221           String sensorName = "Sensor";
2401 06 May 14 olle 222           if (labSensorConfig != null)
2401 06 May 14 olle 223           {
2401 06 May 14 olle 224             labSensorNumber = labSensorConfig.getNumber();
2401 06 May 14 olle 225             sensorName = labSensorConfig.getName();
2401 06 May 14 olle 226           }
2401 06 May 14 olle 227           log.debug("labSensorNumber = " + labSensorNumber + " startTime = " + startTime + " endTime = " + endTime);
2401 06 May 14 olle 228           // Perform database query
3018 09 Dec 14 nicklas 229           List<LabEnvironmentData> lthdList = storage.queryLabEnvDb(labSensorNumber, startTime, endTime);
2401 06 May 14 olle 230           // Apply optional weekday filter
2465 02 Jun 14 olle 231           if ("labenvironmentweeklydisplay".equals(cmd) || "labenvironmentoverviewdisplay".equals(cmd))
2465 02 Jun 14 olle 232           {
2465 02 Jun 14 olle 233             lthdList = applyWeekdayFilter(weekdayFilter, lthdList);
2465 02 Jun 14 olle 234           }
2465 02 Jun 14 olle 235           // Apply optional daytime filter
2465 02 Jun 14 olle 236           if ("labenvironmentweeklydisplay".equals(cmd) || "labenvironmentoverviewdisplay".equals(cmd))
2465 02 Jun 14 olle 237           {
2465 02 Jun 14 olle 238             lthdList = applyDaytimeFilter(filterFromTime, filterToTime, lthdList);
2465 02 Jun 14 olle 239           }
2401 06 May 14 olle 240           if ("labenvironmentoverviewdisplay".equals(cmd))
2401 06 May 14 olle 241           {
2401 06 May 14 olle 242             // Create JSON statistics for overview display
2401 06 May 14 olle 243             jsonStatisticsPlotArray = createLabEnvironmentOverviewReport(jsonStatisticsPlotArray, lthdList, startTime, endTime, chartVariant, viewType, sensorName, weekdayFilter, filterFromTime, filterToTime);
2401 06 May 14 olle 244           }
2401 06 May 14 olle 245           else
2401 06 May 14 olle 246           {
2401 06 May 14 olle 247             // Create JSON statistics for daily distribution
2465 02 Jun 14 olle 248             jsonStatisticsPlotArray = createLabEnvironmentDailyDistributionReport(jsonStatisticsPlotArray, lthdList, startTime, endTime, chartVariant, viewType, sensorName, weekdayFilter, filterFromTime, filterToTime);
2401 06 May 14 olle 249           }
2401 06 May 14 olle 250         }
2401 06 May 14 olle 251         // Create JSON report
2401 06 May 14 olle 252         JSONObject jsonReport = new JSONObject();
2401 06 May 14 olle 253         // Add JSON statistics plot array to report
2401 06 May 14 olle 254         jsonReport.put("plotStatistics", jsonStatisticsPlotArray);
2401 06 May 14 olle 255 /*
2401 06 May 14 olle 256         // Appended info
2401 06 May 14 olle 257         String appendedInfoText = "";
2401 06 May 14 olle 258         // Add info on special samples if chart for min to RNAlater is selected
2401 06 May 14 olle 259         if (chartVariantList.contains(minutesToRnaLaterChart))
2401 06 May 14 olle 260         {
2401 06 May 14 olle 261           appendedInfoText += "<h2 class=\"pagebreak\">Appended Info</h2>";
2401 06 May 14 olle 262           appendedInfoText += "<br>";
2401 06 May 14 olle 263         }
2401 06 May 14 olle 264         // Add JSON appended info to report
2401 06 May 14 olle 265         jsonReport.put("appendedInfo", appendedInfoText);
2401 06 May 14 olle 266 */
2401 06 May 14 olle 267         // Add other data to report
2401 06 May 14 olle 268         DateToStringConverter date2StringConverter = LabEnv.CONVERTER_DATE_TO_STRING;
2401 06 May 14 olle 269         jsonReport.put("beginDate", date2StringConverter.convert(startTime));
2401 06 May 14 olle 270         jsonReport.put("endDate", date2StringConverter.convert(endTime));
2463 02 Jun 14 olle 271         jsonReport.put("pageTitle", pageTitle);
2401 06 May 14 olle 272         //
2401 06 May 14 olle 273         json.put("report", jsonReport);
2401 06 May 14 olle 274       }
2401 06 May 14 olle 275     }
2401 06 May 14 olle 276     catch (Throwable t)
2401 06 May 14 olle 277     {
2401 06 May 14 olle 278       t.printStackTrace();
2401 06 May 14 olle 279       json.clear();
2401 06 May 14 olle 280       json.put("status", "error");
2401 06 May 14 olle 281       json.put("message", t.getMessage());
2401 06 May 14 olle 282       json.put("stacktrace", ThrowableUtil.stackTraceToString(t));
2401 06 May 14 olle 283     }
2401 06 May 14 olle 284     finally
2401 06 May 14 olle 285     {
2401 06 May 14 olle 286       json.writeJSONString(resp.getWriter());
2401 06 May 14 olle 287     }
2401 06 May 14 olle 288   }
2401 06 May 14 olle 289
2401 06 May 14 olle 290
2401 06 May 14 olle 291   /**
2401 06 May 14 olle 292    * Apply weekday filter to raw lab environment data list.
2401 06 May 14 olle 293    * 
2401 06 May 14 olle 294    * @param weekdayFilter String Weekday filter option.
2401 06 May 14 olle 295    * @param lthdRawList List<LabEnvironmentData> Raw lab environment data list.
2401 06 May 14 olle 296    * @return List<LabEnvironmentData> Lab environment data list after applying weekday filter. 
2401 06 May 14 olle 297    */
2401 06 May 14 olle 298   private List<LabEnvironmentData> applyWeekdayFilter(String weekdayFilter, List<LabEnvironmentData> lthdRawList)
2401 06 May 14 olle 299   {    
2401 06 May 14 olle 300     // Apply optional weekday filter
2401 06 May 14 olle 301     List<LabEnvironmentData> lthdList = new ArrayList<LabEnvironmentData>(); 
2401 06 May 14 olle 302     if (weekdayFilter == null || weekdayFilter.equals(weekdayFilterAll))
2401 06 May 14 olle 303     {
2401 06 May 14 olle 304       lthdList = lthdRawList;
2401 06 May 14 olle 305     }
2401 06 May 14 olle 306     else if (weekdayFilter.equals(weekdayFilterMondayToFriday))
2401 06 May 14 olle 307     {
2401 06 May 14 olle 308       for (LabEnvironmentData lthd: lthdRawList)
2401 06 May 14 olle 309       {
2401 06 May 14 olle 310         if (lthd != null)
2401 06 May 14 olle 311         {
2401 06 May 14 olle 312           long unixTimeInSeconds = lthd.getUnixTime();
2401 06 May 14 olle 313           Calendar cal = GregorianCalendar.getInstance();
2401 06 May 14 olle 314           cal.setTimeInMillis(unixTimeInSeconds*1000L);
2401 06 May 14 olle 315           int dayOfWeek = cal.get(Calendar.DAY_OF_WEEK);
2401 06 May 14 olle 316           if (dayOfWeek != Calendar.SATURDAY && dayOfWeek != Calendar.SUNDAY)
2401 06 May 14 olle 317           {
2401 06 May 14 olle 318             lthdList.add(lthd);
2401 06 May 14 olle 319           }
2401 06 May 14 olle 320         }
2401 06 May 14 olle 321       }
2401 06 May 14 olle 322     }
2401 06 May 14 olle 323     else if (weekdayFilter.equals(weekdayFilterSaturdayToSunday))
2401 06 May 14 olle 324     {
2401 06 May 14 olle 325       for (LabEnvironmentData lthd: lthdRawList)
2401 06 May 14 olle 326       {
2401 06 May 14 olle 327         if (lthd != null)
2401 06 May 14 olle 328         {
2401 06 May 14 olle 329           long unixTimeInSeconds = lthd.getUnixTime();
2401 06 May 14 olle 330           Calendar cal = GregorianCalendar.getInstance();
2401 06 May 14 olle 331           cal.setTimeInMillis(unixTimeInSeconds*1000L);
2401 06 May 14 olle 332           int dayOfWeek = cal.get(Calendar.DAY_OF_WEEK);
2401 06 May 14 olle 333           if (dayOfWeek == Calendar.SATURDAY || dayOfWeek == Calendar.SUNDAY)
2401 06 May 14 olle 334           {
2401 06 May 14 olle 335             lthdList.add(lthd);
2401 06 May 14 olle 336           }
2401 06 May 14 olle 337         }
2401 06 May 14 olle 338       }
2401 06 May 14 olle 339     }
2401 06 May 14 olle 340     else if (weekdayFilter.equals(weekdayFilterWorkdays))
2401 06 May 14 olle 341     {
2401 06 May 14 olle 342       for (LabEnvironmentData lthd: lthdRawList)
2401 06 May 14 olle 343       {
2401 06 May 14 olle 344         if (lthd != null)
2401 06 May 14 olle 345         {
2401 06 May 14 olle 346           long unixTimeInSeconds = lthd.getUnixTime();
2401 06 May 14 olle 347           Date date = new Date(unixTimeInSeconds*1000L);
2401 06 May 14 olle 348           if (dayIsWorkday(date, "se"))
2401 06 May 14 olle 349           {
2401 06 May 14 olle 350             lthdList.add(lthd);
2401 06 May 14 olle 351           }
2401 06 May 14 olle 352         }
2401 06 May 14 olle 353       }
2401 06 May 14 olle 354     }
2401 06 May 14 olle 355     else if (weekdayFilter.equals(weekdayFilterNonWorkdays))
2401 06 May 14 olle 356     {
2401 06 May 14 olle 357       for (LabEnvironmentData lthd: lthdRawList)
2401 06 May 14 olle 358       {
2401 06 May 14 olle 359         if (lthd != null)
2401 06 May 14 olle 360         {
2401 06 May 14 olle 361           long unixTimeInSeconds = lthd.getUnixTime();
2401 06 May 14 olle 362           Date date = new Date(unixTimeInSeconds*1000L);
2401 06 May 14 olle 363           if (!dayIsWorkday(date, "se"))
2401 06 May 14 olle 364           {
2401 06 May 14 olle 365             lthdList.add(lthd);
2401 06 May 14 olle 366           }
2401 06 May 14 olle 367         }
2401 06 May 14 olle 368       }
2401 06 May 14 olle 369     }
2401 06 May 14 olle 370     return lthdList;
2401 06 May 14 olle 371   }
2401 06 May 14 olle 372
2401 06 May 14 olle 373
2401 06 May 14 olle 374   /**
2401 06 May 14 olle 375    * Checks if a date is a work day.
2401 06 May 14 olle 376    * 
2401 06 May 14 olle 377    * @param date Date Date to check for work day status.
2401 06 May 14 olle 378    * @param countryCode String Code for country when checking for work day status ("se" -> Sweden).
2401 06 May 14 olle 379    * @return Boolean Returns `true` if day is work day, else `false`, or `null` if status could not be determined.
2401 06 May 14 olle 380    */
2401 06 May 14 olle 381   public Boolean dayIsWorkday(Date date, String countryCode)
2401 06 May 14 olle 382   {
2401 06 May 14 olle 383     Boolean dayIsWorkday = null;
2401 06 May 14 olle 384     if (date != null && countryCode != null && !countryCode.equals(""))
2401 06 May 14 olle 385     {
2401 06 May 14 olle 386       if (countryCode.equals("se"))
2401 06 May 14 olle 387       {
2401 06 May 14 olle 388         // Check if result is stored for day of interest
2401 06 May 14 olle 389         String yearMonthDayStr = yearMonthDayFormat.format(date);
2401 06 May 14 olle 390         if (workdayFlagSeHashMap.containsKey(yearMonthDayStr))
2401 06 May 14 olle 391         {
2401 06 May 14 olle 392           dayIsWorkday = workdayFlagSeHashMap.get(yearMonthDayStr);
2401 06 May 14 olle 393         }
2401 06 May 14 olle 394         if (dayIsWorkday == null)
2401 06 May 14 olle 395         {
2401 06 May 14 olle 396           dayIsWorkday = true;
2401 06 May 14 olle 397           String debugStr = "";
2401 06 May 14 olle 398           // Check for Saturdays and Sundays
2401 06 May 14 olle 399           Calendar cal = GregorianCalendar.getInstance();
2401 06 May 14 olle 400           cal.setTime(date);
2401 06 May 14 olle 401           int dayOfWeek = cal.get(Calendar.DAY_OF_WEEK);
2401 06 May 14 olle 402           if (dayOfWeek == Calendar.SATURDAY || dayOfWeek == Calendar.SUNDAY)
2401 06 May 14 olle 403           {
2401 06 May 14 olle 404             dayIsWorkday = false;
2401 06 May 14 olle 405             if (dayOfWeek == Calendar.SATURDAY)
2401 06 May 14 olle 406             {
2401 06 May 14 olle 407               debugStr = "Saturday";
2401 06 May 14 olle 408             }
2401 06 May 14 olle 409             else if (dayOfWeek == Calendar.SUNDAY)
2401 06 May 14 olle 410             {
2401 06 May 14 olle 411               debugStr = "Sunday";
2401 06 May 14 olle 412             }
2401 06 May 14 olle 413           }
2401 06 May 14 olle 414           if (dayIsWorkday)
2401 06 May 14 olle 415           {
2401 06 May 14 olle 416             // Check for fixed date holidays
2401 06 May 14 olle 417             String monthDayStr = monthDayFormat.format(date);
2401 06 May 14 olle 418             if (monthDayStr.equals("0101"))
2401 06 May 14 olle 419             {
2401 06 May 14 olle 420               // New Year's Day
2401 06 May 14 olle 421               dayIsWorkday = false;
2401 06 May 14 olle 422               debugStr = "New Year's Day";
2401 06 May 14 olle 423             }
2401 06 May 14 olle 424             else if (monthDayStr.equals("0106"))
2401 06 May 14 olle 425             {
2401 06 May 14 olle 426               // Epiphany ("Trettondagen")
2401 06 May 14 olle 427               dayIsWorkday = false;
2401 06 May 14 olle 428               debugStr = "Epiphany";
2401 06 May 14 olle 429             }
2401 06 May 14 olle 430             else if (monthDayStr.equals("0501"))
2401 06 May 14 olle 431             {
2401 06 May 14 olle 432               // May 1st
2401 06 May 14 olle 433               dayIsWorkday = false;
2401 06 May 14 olle 434               debugStr = "May 1st";
2401 06 May 14 olle 435             }
2401 06 May 14 olle 436             else if (monthDayStr.equals("0606"))
2401 06 May 14 olle 437             {
2401 06 May 14 olle 438               // National Day of Sweden ("Sveriges nationaldag och svenska flaggans dag")
2401 06 May 14 olle 439               dayIsWorkday = false;
2401 06 May 14 olle 440               debugStr = "National Day of Sweden";
2401 06 May 14 olle 441             }
2401 06 May 14 olle 442             else if (monthDayStr.equals("1224"))
2401 06 May 14 olle 443             {
2401 06 May 14 olle 444               // Christmas Eve
2401 06 May 14 olle 445               dayIsWorkday = false;
2401 06 May 14 olle 446               debugStr = "Cristmas Eve";
2401 06 May 14 olle 447             }
2401 06 May 14 olle 448             else if (monthDayStr.equals("1225"))
2401 06 May 14 olle 449             {
2401 06 May 14 olle 450               // Christmas Day
2401 06 May 14 olle 451               dayIsWorkday = false;
2401 06 May 14 olle 452               debugStr = "Cristmas Day";
2401 06 May 14 olle 453             }
2401 06 May 14 olle 454             else if (monthDayStr.equals("1226"))
2401 06 May 14 olle 455             {
2401 06 May 14 olle 456               // Boxing Day ("Annandag jul")
2401 06 May 14 olle 457               dayIsWorkday = false;
2401 06 May 14 olle 458               debugStr = "Boxing Day";
2401 06 May 14 olle 459             }
2401 06 May 14 olle 460             else if (monthDayStr.equals("1231"))
2401 06 May 14 olle 461             {
2401 06 May 14 olle 462               // New Year's Eve
2401 06 May 14 olle 463               dayIsWorkday = false;
2401 06 May 14 olle 464               debugStr = "New Year's Eve";
2401 06 May 14 olle 465             }
2401 06 May 14 olle 466             if (dayIsWorkday)
2401 06 May 14 olle 467             {
2401 06 May 14 olle 468               // Check for holidays related to Easter
2401 06 May 14 olle 469               int year = cal.get(Calendar.YEAR);
2401 06 May 14 olle 470               Date easterSundayDate = easterSundayDateGregorianCalendar(year);
2401 06 May 14 olle 471               //log.debug("year = " + year + " Easter Sunday date = " + easterSundayDate);
2401 06 May 14 olle 472               Calendar easterSundayCal = GregorianCalendar.getInstance();
2401 06 May 14 olle 473               easterSundayCal.setTime(easterSundayDate);
2401 06 May 14 olle 474               // Good Friday ("Långfredag")
2401 06 May 14 olle 475               Date goodFridayDate = addDays(easterSundayDate, -2);
2401 06 May 14 olle 476               String goodFridayStr = yearMonthDayFormat.format(goodFridayDate);
2401 06 May 14 olle 477               if (yearMonthDayStr.equals(goodFridayStr))
2401 06 May 14 olle 478               {
2401 06 May 14 olle 479                 dayIsWorkday = false;
2401 06 May 14 olle 480                 debugStr = "Good Friday";
2401 06 May 14 olle 481               }
2401 06 May 14 olle 482               else
2401 06 May 14 olle 483               {
2401 06 May 14 olle 484                 // Easter Monday ("Annandag påsk")
2401 06 May 14 olle 485                 Date easterMondayDate = addDays(easterSundayDate, 1);
2401 06 May 14 olle 486                 String easterMondayStr = yearMonthDayFormat.format(easterMondayDate);
2401 06 May 14 olle 487                 if (yearMonthDayStr.equals(easterMondayStr))
2401 06 May 14 olle 488                 {
2401 06 May 14 olle 489                   dayIsWorkday = false;
2401 06 May 14 olle 490                   debugStr = "Easter Monday";
2401 06 May 14 olle 491                 }
2401 06 May 14 olle 492                 else
2401 06 May 14 olle 493                 {
2401 06 May 14 olle 494                   // Ascension Day ("Kristi Himmelsfärdsdag")
2401 06 May 14 olle 495                   Date ascensionDayDate = addDays(easterSundayDate, 39);
2401 06 May 14 olle 496                   String ascensionDayStr = yearMonthDayFormat.format(ascensionDayDate);
2401 06 May 14 olle 497                   if (yearMonthDayStr.equals(ascensionDayStr))
2401 06 May 14 olle 498                   {
2401 06 May 14 olle 499                     dayIsWorkday = false;
2401 06 May 14 olle 500                     debugStr = "Ascension Day";
2401 06 May 14 olle 501                   }              
2401 06 May 14 olle 502                 }
2401 06 May 14 olle 503               }
2401 06 May 14 olle 504               if (dayIsWorkday)
2401 06 May 14 olle 505               {
2401 06 May 14 olle 506                 // Check for Midsummer's Eve
2401 06 May 14 olle 507                 // In Sweden since 1953 Midsummer's Eve is the Friday in the 7-day period June 19th - 25th
2401 06 May 14 olle 508                 // Get day in week of June 19th
2401 06 May 14 olle 509                 Calendar tmpCal = GregorianCalendar.getInstance();
2401 06 May 14 olle 510                 tmpCal.set(Calendar.YEAR, year);
2401 06 May 14 olle 511                 tmpCal.set(Calendar.MONTH, 6-1);
2401 06 May 14 olle 512                 tmpCal.set(Calendar.DATE, 19);
2401 06 May 14 olle 513                 // Day of week is 1 for Sunday, 2 for Monday, ... , 6 for Friday, 7 for Saturday 
2401 06 May 14 olle 514                 dayOfWeek = tmpCal.get(Calendar.DAY_OF_WEEK);
2401 06 May 14 olle 515                 int daysToFriday = 6 - dayOfWeek;
2401 06 May 14 olle 516                 if (daysToFriday < 0)
2401 06 May 14 olle 517                 {
2401 06 May 14 olle 518                   daysToFriday += 7;
2401 06 May 14 olle 519                 }
2401 06 May 14 olle 520                 // Get date for Midsummer's Eve Friday
2401 06 May 14 olle 521                 tmpCal.add(Calendar.DATE, daysToFriday);
2401 06 May 14 olle 522                 Date midsummersEveDate = tmpCal.getTime();
2401 06 May 14 olle 523                 String midsummersEveStr = yearMonthDayFormat.format(midsummersEveDate);
2401 06 May 14 olle 524                 if (yearMonthDayStr.equals(midsummersEveStr))
2401 06 May 14 olle 525                 {
2401 06 May 14 olle 526                   dayIsWorkday = false;
2401 06 May 14 olle 527                   debugStr = "Midsummer's Eve";  
2401 06 May 14 olle 528                 }
2401 06 May 14 olle 529               }
2401 06 May 14 olle 530             }
2401 06 May 14 olle 531           }
2401 06 May 14 olle 532           // Store value for current day
2401 06 May 14 olle 533           workdayFlagSeHashMap.put(yearMonthDayStr, dayIsWorkday);
2401 06 May 14 olle 534           if (debugStr != null && !debugStr.equals(""))
2401 06 May 14 olle 535           {            
2401 06 May 14 olle 536             log.debug("date = " + yearMonthDayStr + " is " + debugStr);
2401 06 May 14 olle 537           }
2401 06 May 14 olle 538         }
2401 06 May 14 olle 539       }
2401 06 May 14 olle 540     }
2401 06 May 14 olle 541     return dayIsWorkday;
2401 06 May 14 olle 542   }
2401 06 May 14 olle 543
2401 06 May 14 olle 544
2401 06 May 14 olle 545   /**
2401 06 May 14 olle 546    * Returns the date of Easter Sunday in the Gregorian calendar
2401 06 May 14 olle 547    * for a specified year. The “Meeus/Jones/Butcher” algorithm
2401 06 May 14 olle 548    * is used for the date calculation.
2401 06 May 14 olle 549    * 
2401 06 May 14 olle 550    * @param year int The year to calculate Easter Sunday date for.
2401 06 May 14 olle 551    * @return Date Date for Easter Sunday in the Gregorian calendar for the specified year.
2401 06 May 14 olle 552    */
2401 06 May 14 olle 553   public Date easterSundayDateGregorianCalendar(int year)
2401 06 May 14 olle 554   {
2401 06 May 14 olle 555     int a = year % 19;
2401 06 May 14 olle 556     int b = year/100;
2401 06 May 14 olle 557     int c = year % 100;
2401 06 May 14 olle 558     int d = b/4;
2401 06 May 14 olle 559     int e = b % 4;
2401 06 May 14 olle 560     int f = ((b + 8)/25);
2401 06 May 14 olle 561     int g = ((b - f + 1)/3);
2401 06 May 14 olle 562     int h = (19*a + b - d - g + 15) % 30;
2401 06 May 14 olle 563     int i = c/4;
2401 06 May 14 olle 564     int k = c % 4;
2401 06 May 14 olle 565     int L = (32 + 2*e + 2*i -h -k) % 7;
2401 06 May 14 olle 566     int m = ((a + 11*h + 22*L)/451);
2401 06 May 14 olle 567     int month = ((h + L - 7*m + 114)/31);
2401 06 May 14 olle 568     int day = ((h + L - 7*m + 114) % 31) + 1;
2401 06 May 14 olle 569     Calendar cal = GregorianCalendar.getInstance();
2401 06 May 14 olle 570     cal.set(Calendar.YEAR, year);
2401 06 May 14 olle 571     cal.set(Calendar.MONTH, month - 1);
2401 06 May 14 olle 572     cal.set(Calendar.DAY_OF_MONTH, day);
2401 06 May 14 olle 573     return cal.getTime();
2401 06 May 14 olle 574   }
2401 06 May 14 olle 575
2401 06 May 14 olle 576
2401 06 May 14 olle 577   /**
2401 06 May 14 olle 578    * Create overview selection from raw lab environment data list.
2401 06 May 14 olle 579    * 
2401 06 May 14 olle 580    * @param lthdRawList List<LabEnvironmentData> Raw lab environment data list.
2401 06 May 14 olle 581    * @return List<LabEnvironmentData> Lab environment data list after overview selection. 
2401 06 May 14 olle 582    */
2401 06 May 14 olle 583   private List<LabEnvironmentDayData> createOverviewSelection(List<LabEnvironmentData> lthdRawList)
2401 06 May 14 olle 584   {    
2401 06 May 14 olle 585     // Select min, mean, and max result of each day, for all variables
2401 06 May 14 olle 586     List<LabEnvironmentDayData> labEnvDayDataList = new ArrayList<LabEnvironmentDayData>();
2401 06 May 14 olle 587     List<LabEnvironmentData> lthdList = new ArrayList<LabEnvironmentData>(); 
2401 06 May 14 olle 588     List<LabEnvironmentData> lthdTmpList = new ArrayList<LabEnvironmentData>();
2401 06 May 14 olle 589     List<Integer> minTempIndexList = new ArrayList<Integer>();
2401 06 May 14 olle 590     List<Integer> maxTempIndexList = new ArrayList<Integer>();
2401 06 May 14 olle 591     List<Integer> minHumIndexList = new ArrayList<Integer>();
2401 06 May 14 olle 592     List<Integer> maxHumIndexList = new ArrayList<Integer>();
2401 06 May 14 olle 593     HashMap<Date, Double> meanTempHashMap = new HashMap<Date, Double>();
2401 06 May 14 olle 594     HashMap<Date, Double> meanHumHashMap = new HashMap<Date, Double>();
2401 06 May 14 olle 595     DateFormat pureDateFormat = new SimpleDateFormat("YYYYMMdd");
2401 06 May 14 olle 596     String currentDateStr = null;
2401 06 May 14 olle 597     Date currentDate = null;
2401 06 May 14 olle 598     int tempMinIndex = -1;
2401 06 May 14 olle 599     int tempMaxIndex = -1;
2401 06 May 14 olle 600     int humMinIndex = -1;
2401 06 May 14 olle 601     int humMaxIndex = -1;
2401 06 May 14 olle 602     double tempMin = 1000000;
2401 06 May 14 olle 603     double tempMax = -1000000;
2401 06 May 14 olle 604     double tempMean = 0.0;
2401 06 May 14 olle 605     double humMin = 1000000;
2401 06 May 14 olle 606     double humMax = -1000000;
2401 06 May 14 olle 607     double humMean = 0.0;
2401 06 May 14 olle 608     int numMean = 0;
2401 06 May 14 olle 609     log.debug("lthdRawList.size() = " + lthdRawList.size());
2401 06 May 14 olle 610     for (int i = 0; i < lthdRawList.size(); i++)
2401 06 May 14 olle 611     {
2401 06 May 14 olle 612       LabEnvironmentData lthd = (LabEnvironmentData) lthdRawList.get(i);
2401 06 May 14 olle 613       if (lthd != null)
2401 06 May 14 olle 614       {
2401 06 May 14 olle 615         long unixTimeInSeconds = lthd.getUnixTime();
2401 06 May 14 olle 616         Date date = new Date(unixTimeInSeconds*1000L);
2401 06 May 14 olle 617         String dateStr = pureDateFormat.format(date);
2401 06 May 14 olle 618         //log.debug("i = " + i + " currentDateStr = " + currentDateStr + " dateStr = " + dateStr + " temp = " + lthd.getTemperature() + " hum = " + lthd.getHumidity() + " tempMin = " + tempMin + " tempMax = " + tempMax);
2401 06 May 14 olle 619         if (currentDateStr == null)
2401 06 May 14 olle 620         {
2401 06 May 14 olle 621           currentDateStr = dateStr;
2401 06 May 14 olle 622           currentDate = date;
2401 06 May 14 olle 623           tempMin = lthd.getTemperature();
2401 06 May 14 olle 624           tempMax = lthd.getTemperature();
2401 06 May 14 olle 625           tempMean = lthd.getTemperature();
2401 06 May 14 olle 626           humMin = lthd.getHumidity();
2401 06 May 14 olle 627           humMax = lthd.getHumidity();
2401 06 May 14 olle 628           humMean = lthd.getHumidity();
2401 06 May 14 olle 629           tempMinIndex = i;
2401 06 May 14 olle 630           tempMaxIndex = i;
2401 06 May 14 olle 631           humMinIndex = i;
2401 06 May 14 olle 632           humMaxIndex = i;
2401 06 May 14 olle 633           numMean = 1;
2401 06 May 14 olle 634         }
2401 06 May 14 olle 635         else if (dateStr.equals(currentDateStr))
2401 06 May 14 olle 636         {
2401 06 May 14 olle 637           // Optional update of min and max values
2401 06 May 14 olle 638           double temp = lthd.getTemperature();
2401 06 May 14 olle 639           if (temp < tempMin)
2401 06 May 14 olle 640           {
2401 06 May 14 olle 641             tempMin = temp;
2401 06 May 14 olle 642             tempMinIndex = i;
2401 06 May 14 olle 643           }
2401 06 May 14 olle 644           if (temp > tempMax)
2401 06 May 14 olle 645           {
2401 06 May 14 olle 646             tempMax = temp;
2401 06 May 14 olle 647             tempMaxIndex = i;
2401 06 May 14 olle 648           }
2401 06 May 14 olle 649           double hum = lthd.getHumidity();
2401 06 May 14 olle 650           if (hum < humMin)
2401 06 May 14 olle 651           {
2401 06 May 14 olle 652             humMin = hum;
2401 06 May 14 olle 653             humMinIndex = i;
2401 06 May 14 olle 654           }
2401 06 May 14 olle 655           if (hum > humMax)
2401 06 May 14 olle 656           {
2401 06 May 14 olle 657             humMax = hum;
2401 06 May 14 olle 658             humMaxIndex = i;
2401 06 May 14 olle 659           }
2401 06 May 14 olle 660           // Update values for mean value calculation
2401 06 May 14 olle 661           tempMean += temp;
2401 06 May 14 olle 662           humMean += hum;
2401 06 May 14 olle 663           numMean++;
2401 06 May 14 olle 664         }
2401 06 May 14 olle 665         else
2401 06 May 14 olle 666         {
2401 06 May 14 olle 667           // Update lab environment overview data list
2401 06 May 14 olle 668           minTempIndexList.add(tempMinIndex);
2401 06 May 14 olle 669           maxTempIndexList.add(tempMaxIndex);
2401 06 May 14 olle 670           minHumIndexList.add(humMinIndex);
2401 06 May 14 olle 671           maxHumIndexList.add(humMaxIndex);
2401 06 May 14 olle 672           tempMean /= numMean;
2401 06 May 14 olle 673           humMean /= numMean;
2401 06 May 14 olle 674           meanTempHashMap.put(currentDate, tempMean);
2401 06 May 14 olle 675           meanHumHashMap.put(currentDate, humMean);
2401 06 May 14 olle 676           // Store data with start of current date (midnight)
2401 06 May 14 olle 677           Calendar cal = GregorianCalendar.getInstance();
2401 06 May 14 olle 678           cal.setTime(currentDate);
2401 06 May 14 olle 679           cal.set(Calendar.HOUR_OF_DAY, 0);
2401 06 May 14 olle 680           cal.set(Calendar.MINUTE, 0);
2401 06 May 14 olle 681           cal.set(Calendar.SECOND, 0);
2401 06 May 14 olle 682           cal.set(Calendar.MILLISECOND, 0);
2401 06 May 14 olle 683           Date dateMidnight = cal.getTime();
2401 06 May 14 olle 684           //log.debug("i = " + i + " dateMidnight = " + dateMidnight + " tempMin = " + tempMin + " tempMean = " + tempMean + " tempMax = " + tempMax + " humMin = " + humMin + " humMean = " + humMean + " humMax = " + humMax);
2401 06 May 14 olle 685           LabEnvironmentDayData labEnvironmentDayData = new LabEnvironmentDayData(dateMidnight, tempMin, tempMax, tempMean, humMin, humMax, humMean);
2401 06 May 14 olle 686           labEnvDayDataList.add(labEnvironmentDayData);
2401 06 May 14 olle 687           // Prepare for first entry for next date
2401 06 May 14 olle 688           currentDateStr = dateStr;
2401 06 May 14 olle 689           currentDate = date;
2401 06 May 14 olle 690           tempMin = lthd.getTemperature();
2401 06 May 14 olle 691           tempMax = lthd.getTemperature();
2401 06 May 14 olle 692           tempMean = lthd.getTemperature();
2401 06 May 14 olle 693           humMin = lthd.getHumidity();
2401 06 May 14 olle 694           humMax = lthd.getHumidity();
2401 06 May 14 olle 695           humMean = lthd.getHumidity();
2401 06 May 14 olle 696           tempMinIndex = i;
2401 06 May 14 olle 697           tempMaxIndex = i;
2401 06 May 14 olle 698           humMinIndex = i;
2401 06 May 14 olle 699           humMaxIndex = i;
2401 06 May 14 olle 700           numMean = 1;
2401 06 May 14 olle 701         }
2401 06 May 14 olle 702         if (i == lthdRawList.size() - 1)
2401 06 May 14 olle 703         {
2401 06 May 14 olle 704           // Update lab environment overview data list for last entry
2401 06 May 14 olle 705           minTempIndexList.add(tempMinIndex);
2401 06 May 14 olle 706           maxTempIndexList.add(tempMaxIndex);
2401 06 May 14 olle 707           minHumIndexList.add(humMinIndex);
2401 06 May 14 olle 708           maxHumIndexList.add(humMaxIndex);
2401 06 May 14 olle 709           tempMean /= numMean;
2401 06 May 14 olle 710           humMean /= numMean;
2401 06 May 14 olle 711           meanTempHashMap.put(currentDate, tempMean);
2401 06 May 14 olle 712           meanHumHashMap.put(currentDate, humMean);
2401 06 May 14 olle 713           // Store data with start of current date (midnight)
2401 06 May 14 olle 714           Calendar cal = GregorianCalendar.getInstance();
2401 06 May 14 olle 715           cal.setTime(currentDate);
2401 06 May 14 olle 716           cal.set(Calendar.HOUR_OF_DAY, 0);
2401 06 May 14 olle 717           cal.set(Calendar.MINUTE, 0);
2401 06 May 14 olle 718           cal.set(Calendar.SECOND, 0);
2401 06 May 14 olle 719           cal.set(Calendar.MILLISECOND, 0);
2401 06 May 14 olle 720           Date dateMidnight = cal.getTime();
2401 06 May 14 olle 721           log.debug("i = " + i + " dateMidnight = " + dateMidnight + " tempMin = " + tempMin + " tempMean = " + tempMean + " tempMax = " + tempMax + " humMin = " + humMin + " humMean = " + humMean + " humMax = " + humMax);
2401 06 May 14 olle 722           LabEnvironmentDayData labEnvironmentDayData = new LabEnvironmentDayData(currentDate, tempMin, tempMax, tempMean, humMin, humMax, humMean);
2401 06 May 14 olle 723           labEnvDayDataList.add(labEnvironmentDayData);
2401 06 May 14 olle 724         }
2401 06 May 14 olle 725       }
2401 06 May 14 olle 726     }
2401 06 May 14 olle 727     log.debug("lthdRawList.size() = " + lthdRawList.size() + " labEnvDayDataList.size() = " + labEnvDayDataList.size());
2401 06 May 14 olle 728     return labEnvDayDataList;
2401 06 May 14 olle 729   }
2401 06 May 14 olle 730
2401 06 May 14 olle 731   
2401 06 May 14 olle 732   /**
2401 06 May 14 olle 733    * Apply daytime filter to raw lab environment data list.
2401 06 May 14 olle 734    * 
2401 06 May 14 olle 735    * @param filterFromTime String Daytime filter from time in "HHmm" format, or empty string.
2401 06 May 14 olle 736    * @param filterToTime String Daytime filter from time in "HHmm" format, or empty string.
2401 06 May 14 olle 737    * @param lthdRawList List<LabEnvironmentData> Raw lab environment data list.
2401 06 May 14 olle 738    * @return List<LabEnvironmentData> Lab environment data list after applying daytime filter. 
2401 06 May 14 olle 739    */
2401 06 May 14 olle 740   private List<LabEnvironmentData> applyDaytimeFilter(String filterFromTime, String filterToTime, List<LabEnvironmentData> lthdRawList)
2401 06 May 14 olle 741   {
2401 06 May 14 olle 742     // Apply optional daytime filter
2401 06 May 14 olle 743     List<LabEnvironmentData> lthdList = new ArrayList<LabEnvironmentData>(); 
2401 06 May 14 olle 744     if ((filterFromTime == null || filterFromTime.equals("")) && (filterToTime == null || filterToTime.equals("")))
2401 06 May 14 olle 745     {
2401 06 May 14 olle 746       lthdList = lthdRawList;
2401 06 May 14 olle 747     }
2401 06 May 14 olle 748     else
2401 06 May 14 olle 749     {
2401 06 May 14 olle 750       // Note: The procedure below may seem to give bad performance,
2401 06 May 14 olle 751       // since dates are converted to strings for comparison, but it
2401 06 May 14 olle 752       // should work also on dates when daylight saving time starts
2401 06 May 14 olle 753       // or ends.
2401 06 May 14 olle 754       if (filterFromTime == null || filterFromTime.equals(""))
2401 06 May 14 olle 755       {
2401 06 May 14 olle 756         filterFromTime = "0000";
2401 06 May 14 olle 757       }
2401 06 May 14 olle 758       if (filterToTime == null || filterToTime.equals(""))
2401 06 May 14 olle 759       {
2401 06 May 14 olle 760         filterToTime = "2359";
2401 06 May 14 olle 761       }
2401 06 May 14 olle 762       DateFormat hourMinuteDateFormat = new SimpleDateFormat("HHmm");
2401 06 May 14 olle 763       for (LabEnvironmentData lthd: lthdRawList)
2401 06 May 14 olle 764       {
2401 06 May 14 olle 765         if (lthd != null)
2401 06 May 14 olle 766         {
2401 06 May 14 olle 767           long unixTimeInSeconds = lthd.getUnixTime();
2401 06 May 14 olle 768           Calendar cal = GregorianCalendar.getInstance();
2401 06 May 14 olle 769           cal.setTimeInMillis(unixTimeInSeconds*1000L);
2401 06 May 14 olle 770           Date date = cal.getTime();
2401 06 May 14 olle 771           String hourMinutesStr = hourMinuteDateFormat.format(date);
2401 06 May 14 olle 772           if (filterFromTime.compareTo(filterToTime) <= 0)
2401 06 May 14 olle 773           {
2401 06 May 14 olle 774             // filterFromTime <= hourMinutesStr <= filterToTime e.g. 08:00 - 16:00
2401 06 May 14 olle 775             if (filterFromTime.compareTo(hourMinutesStr) <= 0 && filterToTime.compareTo(hourMinutesStr) >= 0)
2401 06 May 14 olle 776             {
2401 06 May 14 olle 777               lthdList.add(lthd);
2401 06 May 14 olle 778             }
2401 06 May 14 olle 779           }
2401 06 May 14 olle 780           else
2401 06 May 14 olle 781           {
2401 06 May 14 olle 782             // hourMinutesStr <= filterToTime || filterFromTime <= hourMinutesStr e.g. 16:00 - 08:00
2401 06 May 14 olle 783             if (filterFromTime.compareTo(hourMinutesStr) <= 0 || filterToTime.compareTo(hourMinutesStr) >= 0)
2401 06 May 14 olle 784             {
2401 06 May 14 olle 785               lthdList.add(lthd);
2401 06 May 14 olle 786             }
2401 06 May 14 olle 787           }
2401 06 May 14 olle 788         }
2401 06 May 14 olle 789       }
2401 06 May 14 olle 790     }
2401 06 May 14 olle 791     return lthdList;
2401 06 May 14 olle 792   }
2401 06 May 14 olle 793
2401 06 May 14 olle 794   
2401 06 May 14 olle 795   private JSONArray createLabEnvironmentDailyDistributionReport(JSONArray jsonStatisticsPlotArray, List<LabEnvironmentData> lthdList, Date startDate, Date endDate, String chartVariant, String viewType, String sensorName, String weekdayFilter, String daytimeFilterFromTime, String daytimeFilterToTime)
2401 06 May 14 olle 796     throws ServletException, IOException 
2401 06 May 14 olle 797   {  
2401 06 May 14 olle 798     JSONObject jsonReport = new JSONObject();
2401 06 May 14 olle 799
2401 06 May 14 olle 800     Date date = null;
2401 06 May 14 olle 801     // Converter to check timestamps against midnight: 00:00:00
2401 06 May 14 olle 802     DateToStringConverter timeConverter = new DateToStringConverter(new SimpleDateFormat("HH:mm:ss"));
2401 06 May 14 olle 803     // Create list of view types for plots
2401 06 May 14 olle 804     List<String> viewTypeList = new ArrayList<String>();
2401 06 May 14 olle 805     // Get lab environment configuration from singleton LabEnvironment
2401 06 May 14 olle 806     LabEnvironment labEnvironment = LabEnvironment.getInstance();
2401 06 May 14 olle 807     LabEnvironmentConfiguration labEnvironmentConfiguration = labEnvironment.getLabEnvironmentConfiguration();
2401 06 May 14 olle 808     List<LabSensorConfig> labSensorConfigList = labEnvironmentConfiguration.getLabSensorConfigList();
2401 06 May 14 olle 809     // Prepare additional data
2401 06 May 14 olle 810     String chartSite = sensorName;
2401 06 May 14 olle 811     List<String> variableTypeList = new ArrayList<String>();
2401 06 May 14 olle 812     variableTypeList.add(variableTypeTemperature);
2401 06 May 14 olle 813     variableTypeList.add(variableTypeHumidity);
2401 06 May 14 olle 814     // Create plot statistics data and put in JSON statistics plot array
2401 06 May 14 olle 815     for (String variableType: variableTypeList)
2401 06 May 14 olle 816     {
2401 06 May 14 olle 817       // Get JSON statistics data
2401 06 May 14 olle 818       String cVariant = "labEnvironmentDailyDistribution";
2401 06 May 14 olle 819       JSONObject plotJsonData = createJsonPlot(cVariant, lthdList, startDate, endDate, viewType, chartSite, variableType, weekdayFilter, daytimeFilterFromTime, daytimeFilterToTime);
2401 06 May 14 olle 820       //
2401 06 May 14 olle 821       plotJsonData = addExtraInfo(plotJsonData, cVariant);
2401 06 May 14 olle 822       JSONObject plotJsonDataContainer = new JSONObject();
2401 06 May 14 olle 823       plotJsonDataContainer.put("chartSite", chartSite);
2401 06 May 14 olle 824       plotJsonDataContainer.put("chartVariant", cVariant);
2401 06 May 14 olle 825       plotJsonDataContainer.put("viewType", viewType);
2401 06 May 14 olle 826       plotJsonDataContainer.put("plotData", plotJsonData);
2401 06 May 14 olle 827       String optionalHeadline = "";
2401 06 May 14 olle 828       plotJsonDataContainer.put("optionalHeadline", optionalHeadline);
2401 06 May 14 olle 829       jsonStatisticsPlotArray.add(plotJsonDataContainer);
2401 06 May 14 olle 830     }
2401 06 May 14 olle 831     return jsonStatisticsPlotArray;
2401 06 May 14 olle 832   }
2401 06 May 14 olle 833
2401 06 May 14 olle 834
2401 06 May 14 olle 835   private JSONArray createLabEnvironmentOverviewReport(JSONArray jsonStatisticsPlotArray, List<LabEnvironmentData> lthdList, Date startDate, Date endDate, String chartVariant, String viewType, String sensorName, String weekdayFilter, String daytimeFilterFromTime, String daytimeFilterToTime)
2401 06 May 14 olle 836     throws ServletException, IOException 
2401 06 May 14 olle 837   {  
2401 06 May 14 olle 838     JSONObject jsonReport = new JSONObject();
2401 06 May 14 olle 839
2401 06 May 14 olle 840     Date date = null;
2401 06 May 14 olle 841     // Converter to check timestamps against midnight: 00:00:00
2401 06 May 14 olle 842     DateToStringConverter timeConverter = new DateToStringConverter(new SimpleDateFormat("HH:mm:ss"));
2401 06 May 14 olle 843     // Create list of view types for plots
2401 06 May 14 olle 844     List<String> viewTypeList = new ArrayList<String>();
2401 06 May 14 olle 845     // Get lab environment configuration from singleton LabEnvironment
2401 06 May 14 olle 846     LabEnvironment labEnvironment = LabEnvironment.getInstance();
2401 06 May 14 olle 847     LabEnvironmentConfiguration labEnvironmentConfiguration = labEnvironment.getLabEnvironmentConfiguration();
2401 06 May 14 olle 848     List<LabSensorConfig> labSensorConfigList = labEnvironmentConfiguration.getLabSensorConfigList();
2401 06 May 14 olle 849     // Prepare additional data
2401 06 May 14 olle 850     String chartSite = sensorName;
2401 06 May 14 olle 851     List<String> variableTypeList = new ArrayList<String>();
2401 06 May 14 olle 852     variableTypeList.add(variableTypeTemperature);
2401 06 May 14 olle 853     variableTypeList.add(variableTypeHumidity);
2401 06 May 14 olle 854     // Create plot statistics data and put in JSON statistics plot array
2401 06 May 14 olle 855     for (String variableType: variableTypeList)
2401 06 May 14 olle 856     {
2401 06 May 14 olle 857       // Get JSON statistics data
2401 06 May 14 olle 858       String cVariant = "labEnvironmentDailyDistribution";
2401 06 May 14 olle 859       JSONObject plotJsonData = createJsonOverviewPlot(cVariant, lthdList, startDate, endDate, viewType, chartSite, variableType, weekdayFilter, daytimeFilterFromTime, daytimeFilterToTime);
2401 06 May 14 olle 860       //
2401 06 May 14 olle 861       plotJsonData = addExtraInfo(plotJsonData, cVariant);
2401 06 May 14 olle 862       JSONObject plotJsonDataContainer = new JSONObject();
2401 06 May 14 olle 863       plotJsonDataContainer.put("chartSite", chartSite);
2401 06 May 14 olle 864       plotJsonDataContainer.put("chartVariant", cVariant);
2401 06 May 14 olle 865       plotJsonDataContainer.put("viewType", viewType);
2401 06 May 14 olle 866       plotJsonDataContainer.put("plotData", plotJsonData);
2401 06 May 14 olle 867       String optionalHeadline = "";
2401 06 May 14 olle 868       plotJsonDataContainer.put("optionalHeadline", optionalHeadline);
2401 06 May 14 olle 869       jsonStatisticsPlotArray.add(plotJsonDataContainer);
2401 06 May 14 olle 870     }
2401 06 May 14 olle 871     return jsonStatisticsPlotArray;
2401 06 May 14 olle 872   }
2401 06 May 14 olle 873
2401 06 May 14 olle 874
2401 06 May 14 olle 875   /**
2401 06 May 14 olle 876    * Returns a Date object from input dateTime string in format (yyyyMMdd HHmm).
2401 06 May 14 olle 877    * Returns `null` if input dateTime string is
2401 06 May 14 olle 878    * `null` or blank.
2401 06 May 14 olle 879    * 
2401 06 May 14 olle 880    * @param dateTimeStr String Input dateTime string in (yyyyMMdd HHmm) format.
2401 06 May 14 olle 881    * @return Date Date object from input dateTime string.
2401 06 May 14 olle 882    */
2401 06 May 14 olle 883   private Date dateTimeStringToDate(String dateTimeStr)
2401 06 May 14 olle 884   {
2401 06 May 14 olle 885     Date date = null;
2401 06 May 14 olle 886     if (dateTimeStr != null && !dateTimeStr.equals(""))
2401 06 May 14 olle 887     {
2401 06 May 14 olle 888       date = CONVERTER_STRING_TO_DATETIME.convert(dateTimeStr);
2401 06 May 14 olle 889     }
2401 06 May 14 olle 890     return date;
2401 06 May 14 olle 891   }
2401 06 May 14 olle 892
2401 06 May 14 olle 893
2401 06 May 14 olle 894   /**
2401 06 May 14 olle 895    * Returns a Date object from input date string in format (yyyy-MM-dd).
2401 06 May 14 olle 896    * Returns `null` if input string is `null` or blank.
2401 06 May 14 olle 897    * 
2401 06 May 14 olle 898    * @param dateStr String Input date string in (yyyy-MM-dd) format.
2401 06 May 14 olle 899    * @return Date Date object from input date string.
2401 06 May 14 olle 900    */
2401 06 May 14 olle 901   private Date dateStringToDate(String dateStr)
2401 06 May 14 olle 902   {
2401 06 May 14 olle 903     Date date = null;
2401 06 May 14 olle 904     if (dateStr != null && !dateStr.equals(""))
2401 06 May 14 olle 905     {
2401 06 May 14 olle 906       date = CONVERTER_STRING_TO_DATE.convert(dateStr);
2401 06 May 14 olle 907     }
2401 06 May 14 olle 908     return date;
2401 06 May 14 olle 909   }
2401 06 May 14 olle 910
2401 06 May 14 olle 911
2401 06 May 14 olle 912   /**
2401 06 May 14 olle 913    * Returns a dateTime string in format (yyyyMMdd HHmm) from input
2401 06 May 14 olle 914    * date and time strings. Returns `null` if input date string is
2401 06 May 14 olle 915    * `null` or blank. Provided input date string is OK; if input time
2401 06 May 14 olle 916    * string is `null` or blank, time is set to "0000".
2401 06 May 14 olle 917    * 
2401 06 May 14 olle 918    * @param dateStr String Input date string in (yyyyMMdd) format.
2401 06 May 14 olle 919    * @param timeStr String Input time string in (HHmm) format.
2401 06 May 14 olle 920    * @return String DateTime string in format (yyyyMMdd HHmm) from input date and time strings.
2401 06 May 14 olle 921    */
2401 06 May 14 olle 922   private String dateAndTimeStringsToDateTimeString(String dateStr, String timeStr)
2401 06 May 14 olle 923   {
2401 06 May 14 olle 924     String dateTimeStr = null;
2401 06 May 14 olle 925     if (dateStr != null && !dateStr.equals(""))
2401 06 May 14 olle 926     {
2401 06 May 14 olle 927       dateStr.replaceAll("-", "");
2401 06 May 14 olle 928       dateTimeStr = "" + dateStr;
2401 06 May 14 olle 929       if (timeStr != null && !timeStr.equals(""))
2401 06 May 14 olle 930       {
2401 06 May 14 olle 931         timeStr.replaceAll(":", "");
2401 06 May 14 olle 932       }
2401 06 May 14 olle 933       else
2401 06 May 14 olle 934       {
2401 06 May 14 olle 935         timeStr = "0000";
2401 06 May 14 olle 936       }
2401 06 May 14 olle 937       dateTimeStr += " " + timeStr;    
2401 06 May 14 olle 938     }
2401 06 May 14 olle 939     return dateTimeStr;
2401 06 May 14 olle 940   }
2401 06 May 14 olle 941
2401 06 May 14 olle 942
2401 06 May 14 olle 943   /**
2401 06 May 14 olle 944    * Returns the date obtained by adding a specified number
2401 06 May 14 olle 945    * of days to an input date in the Gregorian calendar
2401 06 May 14 olle 946    * (a negative number of days to add equals subtraction of
2401 06 May 14 olle 947    * the number of days). Returns `null` if input date is `null`.
2401 06 May 14 olle 948    * 
2401 06 May 14 olle 949    * @param date Date The date to add a number of days to.
2401 06 May 14 olle 950    * @param daysToAdd int The number of days to add.
2401 06 May 14 olle 951    * @return The date after adding a number of days, or `null` if input date is `null`.
2401 06 May 14 olle 952    */
2401 06 May 14 olle 953   private Date addDays(Date date, int daysToAdd)
2401 06 May 14 olle 954   {
2401 06 May 14 olle 955     if (date == null)
2401 06 May 14 olle 956     {
2401 06 May 14 olle 957       return null;
2401 06 May 14 olle 958     }
2401 06 May 14 olle 959     Calendar cal = GregorianCalendar.getInstance();
2401 06 May 14 olle 960     cal.setTimeInMillis(date.getTime());
2401 06 May 14 olle 961     cal.add(Calendar.DAY_OF_MONTH, daysToAdd);
2401 06 May 14 olle 962     return cal.getTime();
2401 06 May 14 olle 963   }
2401 06 May 14 olle 964
2401 06 May 14 olle 965   private JSONObject createJsonPlot(String chartVariant, List<LabEnvironmentData> lthdList, Date startDate, Date endDate, String viewType, String chartSite, String variableType, String weekdayFilter, String daytimeFilterFromTime, String daytimeFilterToTime)
2401 06 May 14 olle 966     throws ServletException, IOException 
2401 06 May 14 olle 967   {
2401 06 May 14 olle 968     if (lthdList != null)
2401 06 May 14 olle 969     {
2401 06 May 14 olle 970       log.debug("lthdList.size() = " + lthdList.size());
2401 06 May 14 olle 971     }
2401 06 May 14 olle 972     else
2401 06 May 14 olle 973     {
2401 06 May 14 olle 974       log.debug("lthdList == null");
2401 06 May 14 olle 975     }
2401 06 May 14 olle 976     // Get JSON statistics data
2401 06 May 14 olle 977     String chartHeaderTitle = fetchChartHeaderTitle(chartVariant, viewType, chartSite, variableType, weekdayFilter);
2401 06 May 14 olle 978     String chartTitle = fetchChartTitle(viewType, variableType, startDate, endDate, daytimeFilterFromTime, daytimeFilterToTime);
2401 06 May 14 olle 979     String chartYAxisTitle = fetchChartYAxisTitle(variableType);
2401 06 May 14 olle 980     // Get HashMap with lists of samples for chosen time periods 
4526 19 Jun 17 nicklas 981     HashMap<String,List<Float>> periodStringFloatListHashMap = createPeriodStringFloatListHashMap(chartVariant, lthdList, viewType, variableType, startDate);
2401 06 May 14 olle 982     //log.debug("periodStringFloatListHashMap = " + periodStringFloatListHashMap);
2401 06 May 14 olle 983     JSONObject jsonPlot = null;
4526 19 Jun 17 nicklas 984     if (viewType != null && (viewType.equals("last24hours") || viewType.equals("dailyDisplay") || viewType.equals("weeklyDisplay") || viewType.equals("overviewDisplay")))
2401 06 May 14 olle 985     {
2401 06 May 14 olle 986       jsonPlot = createJSONPlotDisplay(chartVariant, chartHeaderTitle, chartTitle, chartYAxisTitle, periodStringFloatListHashMap, viewType, startDate);
2401 06 May 14 olle 987     }
2401 06 May 14 olle 988     return jsonPlot;
2401 06 May 14 olle 989   }
2401 06 May 14 olle 990
2401 06 May 14 olle 991
2401 06 May 14 olle 992   private JSONObject createJsonOverviewPlot(String chartVariant, List<LabEnvironmentData> lthdList, Date startDate, Date endDate, String viewType, String chartSite, String variableType, String weekdayFilter, String daytimeFilterFromTime, String daytimeFilterToTime)
2401 06 May 14 olle 993     throws ServletException, IOException 
2401 06 May 14 olle 994   {
2401 06 May 14 olle 995     if (lthdList != null)
2401 06 May 14 olle 996     {
2401 06 May 14 olle 997       log.debug("lthdList.size() = " + lthdList.size());
2401 06 May 14 olle 998     }
2401 06 May 14 olle 999     else
2401 06 May 14 olle 1000     {
2401 06 May 14 olle 1001       log.debug("lthdList == null");
2401 06 May 14 olle 1002       return null;
2401 06 May 14 olle 1003     }
2401 06 May 14 olle 1004     // Calculate statistics for all samples
2401 06 May 14 olle 1005     List<Float> floatList = singleFloatList(lthdList, variableType);
2401 06 May 14 olle 1006     int numItems = floatList.size();
2401 06 May 14 olle 1007     Float floatMin = calculateMinValue(floatList);
2401 06 May 14 olle 1008     Float floatMax = calculateMaxValue(floatList);
2401 06 May 14 olle 1009     Float floatMean = calculateMeanValue(floatList);
2401 06 May 14 olle 1010     Float floatSDev = calculateSDev(floatList);
2401 06 May 14 olle 1011     Collections.sort(floatList);
2401 06 May 14 olle 1012     Float floatPct25 = calculatePercentile(floatList, 0.25f);
2401 06 May 14 olle 1013     Float floatPct50 = calculatePercentile(floatList, 0.50f);
2401 06 May 14 olle 1014     Float floatPct75 = calculatePercentile(floatList, 0.75f);
2401 06 May 14 olle 1015     int localNumberOfDecimals = numberOfDecimals;
2401 06 May 14 olle 1016     if (floatPct25 != null && floatPct25 < 1)
2401 06 May 14 olle 1017     {
2401 06 May 14 olle 1018       localNumberOfDecimals = numberOfDecimals + 1;
2401 06 May 14 olle 1019     }
2401 06 May 14 olle 1020     List<LabEnvironmentDayData> labEnvDayDataList = createOverviewSelection(lthdList);
2401 06 May 14 olle 1021     //int numItems = labEnvDayDataList.size();
2401 06 May 14 olle 1022     if (startDate == null)
2401 06 May 14 olle 1023     {
2401 06 May 14 olle 1024       // Set report start date to earliest configured sensor start date
2401 06 May 14 olle 1025       // Get lab environment configuration from singleton LabEnvironment
2401 06 May 14 olle 1026       LabEnvironment labEnvironment = LabEnvironment.getInstance();
2401 06 May 14 olle 1027       LabEnvironmentConfiguration labEnvironmentConfiguration = labEnvironment.getLabEnvironmentConfiguration();
2401 06 May 14 olle 1028       List<LabSensorConfig> labSensorConfigList = labEnvironmentConfiguration.getLabSensorConfigList();
2401 06 May 14 olle 1029       for (LabSensorConfig labSensorConfig: labSensorConfigList)
2401 06 May 14 olle 1030       {
2401 06 May 14 olle 1031         String sensorStartDateStr = labSensorConfig.getStartDate();
2401 06 May 14 olle 1032         // Skip sensors with start date not set
2401 06 May 14 olle 1033         if (sensorStartDateStr != null && !sensorStartDateStr.equals(""))
2401 06 May 14 olle 1034         {
2401 06 May 14 olle 1035           // Set report start date to earliest sensor date
2401 06 May 14 olle 1036           Date sensorDate = dateStringToDate(sensorStartDateStr);
2401 06 May 14 olle 1037           if (startDate == null || startDate.compareTo(sensorDate) > 0)
2401 06 May 14 olle 1038           {
2401 06 May 14 olle 1039             startDate = sensorDate;
2401 06 May 14 olle 1040           }
2401 06 May 14 olle 1041         }
2401 06 May 14 olle 1042       }
2401 06 May 14 olle 1043     }
2401 06 May 14 olle 1044     log.debug("startDate = " + startDate + " endDate = " + endDate + " daytimeFilterFromTime = " + daytimeFilterFromTime + " daytimeFilterToTime = " + daytimeFilterToTime);
2401 06 May 14 olle 1045     // Get JSON statistics data
2401 06 May 14 olle 1046     String chartHeaderTitle = fetchChartHeaderTitle(chartVariant, viewType, chartSite, variableType, weekdayFilter);
2401 06 May 14 olle 1047     String chartTitle = fetchChartTitle(viewType, variableType, startDate, endDate, daytimeFilterFromTime, daytimeFilterToTime);
2401 06 May 14 olle 1048     String chartYAxisTitle = fetchChartYAxisTitle(variableType);
2401 06 May 14 olle 1049     // Create JSON object with sample statistics
2401 06 May 14 olle 1050     JSONObject jsonPlot = new JSONObject();
2401 06 May 14 olle 1051     jsonPlot.put("headerTitleTop", chartHeaderTitle);
2401 06 May 14 olle 1052     jsonPlot.put("titleTop", chartTitle);
2401 06 May 14 olle 1053     jsonPlot.put("titleBottom", "");
2401 06 May 14 olle 1054     jsonPlot.put("subTitleRight", "n = " + numItems);
2401 06 May 14 olle 1055     jsonPlot.put("subTitleLeft01", "mean, " + Values.formatNumber(floatMean, localNumberOfDecimals));
2401 06 May 14 olle 1056     jsonPlot.put("subTitleLeft02", "sd, " + Values.formatNumber(floatSDev, localNumberOfDecimals));
2401 06 May 14 olle 1057     jsonPlot.put("subTitleLeft03", "range, " + Values.formatNumber(floatMin, localNumberOfDecimals) + ", " + Values.formatNumber(floatMax, localNumberOfDecimals));
2401 06 May 14 olle 1058     jsonPlot.put("yAxisTitleLeft", chartYAxisTitle);
2401 06 May 14 olle 1059     jsonPlot.put("yAxisTitleRight", "");
2401 06 May 14 olle 1060     // Create JSON array of sample statistics for time periods
2401 06 May 14 olle 1061     JSONArray jsonPeriodPercentilesArray = new JSONArray();
2401 06 May 14 olle 1062     // Create JSON array of percentile data for all samples
2401 06 May 14 olle 1063     JSONArray jsonPercentilesArray = new JSONArray();
2401 06 May 14 olle 1064     JSONObject jsonPct25 = createValueWithText(floatPct25, localNumberOfDecimals);
2401 06 May 14 olle 1065     jsonPercentilesArray.add(jsonPct25);
2401 06 May 14 olle 1066     JSONObject jsonPct50 = createValueWithText(floatPct50, localNumberOfDecimals);
2401 06 May 14 olle 1067     jsonPercentilesArray.add(jsonPct50);
2401 06 May 14 olle 1068     JSONObject jsonPct75 = createValueWithText(floatPct75, localNumberOfDecimals);
2401 06 May 14 olle 1069     jsonPercentilesArray.add(jsonPct75);
2401 06 May 14 olle 1070     jsonPlot.put("valueGuideLinesY", jsonPercentilesArray);
2401 06 May 14 olle 1071     for (int i = 0; i < labEnvDayDataList.size(); i++)
2401 06 May 14 olle 1072     {
2401 06 May 14 olle 1073       LabEnvironmentDayData labEnvDayData = (LabEnvironmentDayData) labEnvDayDataList.get(i);
2401 06 May 14 olle 1074       Date date = labEnvDayData.getDate();
2401 06 May 14 olle 1075       // Get current period
4526 19 Jun 17 nicklas 1076       String period = tableUtil.getCurrentPeriod(date, viewType, startDate);
2401 06 May 14 olle 1077       String periodName = fetchPeriodNameForPlot(period, viewType, startDate);
2401 06 May 14 olle 1078       int numPeriodItems = 0;
2401 06 May 14 olle 1079       //log.debug("date = " + date + " currentPeriod = " + currentPeriod + " viewType = " + viewType);
2401 06 May 14 olle 1080       Float valueMin = null;
2401 06 May 14 olle 1081       Float valueMean = null;
2401 06 May 14 olle 1082       Float valueMax = null;
2401 06 May 14 olle 1083       // Get value of desired variables
2401 06 May 14 olle 1084       if (variableType.equals(variableTypeTemperature))
2401 06 May 14 olle 1085       {
2401 06 May 14 olle 1086         valueMin = Double.valueOf(labEnvDayData.getTemperatureMin()).floatValue();
2401 06 May 14 olle 1087         valueMean = Double.valueOf(labEnvDayData.getTemperatureMean()).floatValue();
2401 06 May 14 olle 1088         valueMax = Double.valueOf(labEnvDayData.getTemperatureMax()).floatValue();
2401 06 May 14 olle 1089       }
2401 06 May 14 olle 1090       else if (variableType.equals(variableTypeHumidity))
2401 06 May 14 olle 1091       {
2401 06 May 14 olle 1092         valueMin = Double.valueOf(labEnvDayData.getHumidityMin()).floatValue();
2401 06 May 14 olle 1093         valueMean = Double.valueOf(labEnvDayData.getHumidityMean()).floatValue();
2401 06 May 14 olle 1094         valueMax = Double.valueOf(labEnvDayData.getHumidityMax()).floatValue();
2401 06 May 14 olle 1095       }
2401 06 May 14 olle 1096       JSONObject jsonPeriodData = new JSONObject();
2401 06 May 14 olle 1097       jsonPeriodData.put("name", periodName);
2401 06 May 14 olle 1098       jsonPeriodData.put("numItems", numPeriodItems);
2401 06 May 14 olle 1099       jsonPeriodData.put("v1", valueMin);
2401 06 May 14 olle 1100       jsonPeriodData.put("v2", valueMean);
2401 06 May 14 olle 1101       jsonPeriodData.put("v3", valueMax);
2401 06 May 14 olle 1102       jsonPeriodPercentilesArray.add(jsonPeriodData);
2401 06 May 14 olle 1103       //log.debug("i = " + i + " date = " + date + " name = " + periodName + " numItems = " + numPeriodItems + " v1 = " + valueMin + " v2 = " + valueMean + " v3 = " + valueMax);
2401 06 May 14 olle 1104     }
2401 06 May 14 olle 1105     jsonPlot.put("percentileData", jsonPeriodPercentilesArray);
2401 06 May 14 olle 1106     jsonPlot.put("valueGuideLinesY", jsonPercentilesArray);
2401 06 May 14 olle 1107     log.debug("jsonPeriodPercentilesArray = " + jsonPeriodPercentilesArray.toJSONString());
2531 26 Jun 14 olle 1108     // Get end date as date for next midnight
2531 26 Jun 14 olle 1109     Calendar calEnd = GregorianCalendar.getInstance();
2531 26 Jun 14 olle 1110     // Get current date-time, reset to midnight, then add one day
2531 26 Jun 14 olle 1111     calEnd.setTime(new Date());
2531 26 Jun 14 olle 1112     calEnd.set(Calendar.HOUR_OF_DAY, 0);
2531 26 Jun 14 olle 1113     calEnd.set(Calendar.MINUTE, 0);
2531 26 Jun 14 olle 1114     calEnd.set(Calendar.SECOND, 0);
2531 26 Jun 14 olle 1115     calEnd.set(Calendar.MILLISECOND, 0);
2531 26 Jun 14 olle 1116     calEnd.add(Calendar.DATE, 1);
2531 26 Jun 14 olle 1117     Date dateEnd = calEnd.getTime();
4526 19 Jun 17 nicklas 1118     String latestPeriod = tableUtil.getCurrentPeriod(dateEnd, viewType, startDate);
2531 26 Jun 14 olle 1119     String latestPeriodName = fetchPeriodNameForPlot(latestPeriod, viewType, startDate);
2401 06 May 14 olle 1120     // For overview display, add extra JSON data with text for day markers in graph
2401 06 May 14 olle 1121     if (viewType != null && viewType.equals("overviewDisplay"))
2401 06 May 14 olle 1122     {
2401 06 May 14 olle 1123       Calendar cal = GregorianCalendar.getInstance();
2401 06 May 14 olle 1124       cal.setTime(startDate);
2401 06 May 14 olle 1125       ReportTableUtil reportTableUtil = new ReportTableUtil();
2401 06 May 14 olle 1126       DateFormat yearMonthDayPeriodDateFormat = reportTableUtil.getYearMonthDayPeriodDateFormat();
2401 06 May 14 olle 1127       //DateFormat dateFormat = reportTableUtil.getYearMonthDayPeriodDateFormat();
2401 06 May 14 olle 1128       JSONObject jsonDayInWeekString = new JSONObject();
2401 06 May 14 olle 1129       long numRawMarkers = ((calEnd.getTimeInMillis() - cal.getTimeInMillis())/(3600L*1000L))/24L + 1L;
2401 06 May 14 olle 1130       log.debug("numRawMarkers = " + numRawMarkers);
2401 06 May 14 olle 1131       int numMarkers = 0;
2401 06 May 14 olle 1132       int i = 0;
2401 06 May 14 olle 1133       Date tmpDate = cal.getTime();
2401 06 May 14 olle 1134       // Repeat as long as tmpDate is earlier than or equal to end date
2401 06 May 14 olle 1135       while (tmpDate.compareTo(dateEnd) <= 0)
2401 06 May 14 olle 1136       {
2401 06 May 14 olle 1137         String yearMonthDayStr = yearMonthDayPeriodDateFormat.format(tmpDate);
2401 06 May 14 olle 1138         String dayInWeekStr = yearMonthDayStr;
2401 06 May 14 olle 1139         boolean drawMarker = false;
2401 06 May 14 olle 1140         if (numRawMarkers <= 30)
2401 06 May 14 olle 1141         {
2401 06 May 14 olle 1142           drawMarker = true;
2401 06 May 14 olle 1143         }
2465 02 Jun 14 olle 1144 /*
2401 06 May 14 olle 1145         else if (numRawMarkers <= 150)
2401 06 May 14 olle 1146         {
2401 06 May 14 olle 1147           // Draw marker for day 1, 5, 10, 15, 20, and 25 in each month
2401 06 May 14 olle 1148           String dayStr = dayInWeekStr.substring(6);
2401 06 May 14 olle 1149           if (dayStr != null && (dayStr.equals("01") || dayStr.equals("10") || dayStr.equals("20") || dayStr.endsWith("5")))
2401 06 May 14 olle 1150           {
2401 06 May 14 olle 1151             drawMarker = true;
2401 06 May 14 olle 1152           }
2401 06 May 14 olle 1153         }
2401 06 May 14 olle 1154         else if (numRawMarkers <= 300)
2401 06 May 14 olle 1155         {
2401 06 May 14 olle 1156           // Draw marker for day 1, 10, and 20 in each month
2401 06 May 14 olle 1157           String dayStr = dayInWeekStr.substring(6);
2401 06 May 14 olle 1158           if (dayStr != null && (dayStr.equals("01") || dayStr.equals("10") || dayStr.equals("20")))
2401 06 May 14 olle 1159           {
2401 06 May 14 olle 1160             drawMarker = true;
2401 06 May 14 olle 1161           }
2401 06 May 14 olle 1162         }
2465 02 Jun 14 olle 1163 */
2465 02 Jun 14 olle 1164         else if (numRawMarkers <= 367)
2465 02 Jun 14 olle 1165         {
2465 02 Jun 14 olle 1166           // Draw marker for Mondays
2465 02 Jun 14 olle 1167           // Day of week is 1 for Sunday, 2 for Monday, ... , 6 for Friday, 7 for Saturday 
2465 02 Jun 14 olle 1168           int dayOfWeek = cal.get(Calendar.DAY_OF_WEEK);
2465 02 Jun 14 olle 1169           if (dayOfWeek == Calendar.MONDAY)
2465 02 Jun 14 olle 1170           {
2465 02 Jun 14 olle 1171             drawMarker = true;
2465 02 Jun 14 olle 1172           }
2465 02 Jun 14 olle 1173         }
2401 06 May 14 olle 1174         else
2401 06 May 14 olle 1175         {
2401 06 May 14 olle 1176           // Draw marker for first day in each month
2401 06 May 14 olle 1177           String dayStr = dayInWeekStr.substring(6);
2401 06 May 14 olle 1178           if (dayStr != null && dayStr.equals("01"))
2401 06 May 14 olle 1179           {
2401 06 May 14 olle 1180             drawMarker = true;
2401 06 May 14 olle 1181           }
2401 06 May 14 olle 1182         }
2401 06 May 14 olle 1183         if (drawMarker)
2401 06 May 14 olle 1184         {
2401 06 May 14 olle 1185           //log.debug("dayInWeekStr = " + dayInWeekStr);
2401 06 May 14 olle 1186           String dayInWeekIndexKey = "" + i;
2401 06 May 14 olle 1187           if (i < 10)
2401 06 May 14 olle 1188           {
2401 06 May 14 olle 1189             dayInWeekIndexKey = "0" + dayInWeekIndexKey;
2401 06 May 14 olle 1190           }
2401 06 May 14 olle 1191           if (i < 100)
2401 06 May 14 olle 1192           {
2401 06 May 14 olle 1193             dayInWeekIndexKey = "0" + dayInWeekIndexKey;
2401 06 May 14 olle 1194           }
2401 06 May 14 olle 1195           if (i < 1000)
2401 06 May 14 olle 1196           {
2401 06 May 14 olle 1197             dayInWeekIndexKey = "0" + dayInWeekIndexKey;
2401 06 May 14 olle 1198           }
2401 06 May 14 olle 1199           jsonDayInWeekString.put(dayInWeekIndexKey, dayInWeekStr);
2401 06 May 14 olle 1200           numMarkers++;
2401 06 May 14 olle 1201         }
2463 02 Jun 14 olle 1202         //log.debug("i = " + i + " tmpDate = " + tmpDate + " dateEnd = " + dateEnd + " dayInWeekIndexKey = " + dayInWeekIndexKey + " dayInWeekStr = " + dayInWeekStr);
2463 02 Jun 14 olle 1203         // Add one day to temporary date
2401 06 May 14 olle 1204         cal.add(Calendar.DATE, 1);
2401 06 May 14 olle 1205         tmpDate = cal.getTime();
2401 06 May 14 olle 1206         i++;
2401 06 May 14 olle 1207       }
2401 06 May 14 olle 1208       log.debug("numMarkers = " + numMarkers);
2401 06 May 14 olle 1209       // Use number of printed plus hidden markers in JSON object, as it is used for correct marker placement
2401 06 May 14 olle 1210       jsonDayInWeekString.put("numMarkers", numRawMarkers);
2401 06 May 14 olle 1211       jsonPlot.put("dayInWeekString", jsonDayInWeekString);
2531 26 Jun 14 olle 1212       jsonPlot.put("latestPeriodName", latestPeriodName);
2401 06 May 14 olle 1213     }
2401 06 May 14 olle 1214     return jsonPlot;
2401 06 May 14 olle 1215   }
2401 06 May 14 olle 1216
2401 06 May 14 olle 1217
2401 06 May 14 olle 1218   private int numMarkers(Date startDate, Date endDate)
2401 06 May 14 olle 1219   {
2401 06 May 14 olle 1220     int numMarkers = 0;
2401 06 May 14 olle 1221     return numMarkers;
2401 06 May 14 olle 1222   }
2401 06 May 14 olle 1223
2401 06 May 14 olle 1224   private JSONObject createJSONPlotStatistics(String chartVariant, String headerTitle, String title, String variableTitle, HashMap<String,List<Float>> periodStringFloatListHashMap, String viewType)
2401 06 May 14 olle 1225     throws ServletException, IOException 
2401 06 May 14 olle 1226   {
2401 06 May 14 olle 1227     // Calculate statistics for all samples
2401 06 May 14 olle 1228     List<Float> floatList = singleFloatList(periodStringFloatListHashMap);
2401 06 May 14 olle 1229     int numItems = floatList.size();
2401 06 May 14 olle 1230     Float floatMin = calculateMinValue(floatList);
2401 06 May 14 olle 1231     Float floatMax = calculateMaxValue(floatList);
2401 06 May 14 olle 1232     Float floatMean = calculateMeanValue(floatList);
2401 06 May 14 olle 1233     Float floatSDev = calculateSDev(floatList);
2401 06 May 14 olle 1234     Collections.sort(floatList);
2401 06 May 14 olle 1235     Float floatPct25 = calculatePercentile(floatList, 0.25f);
2401 06 May 14 olle 1236     Float floatPct50 = calculatePercentile(floatList, 0.50f);
2401 06 May 14 olle 1237     Float floatPct75 = calculatePercentile(floatList, 0.75f);
2401 06 May 14 olle 1238     int localNumberOfDecimals = numberOfDecimals;
2401 06 May 14 olle 1239     if (floatPct25 != null && floatPct25 < 1)
2401 06 May 14 olle 1240     {
2401 06 May 14 olle 1241       localNumberOfDecimals = numberOfDecimals + 1;
2401 06 May 14 olle 1242     }
2401 06 May 14 olle 1243     // Create JSON object with sample statistics
2401 06 May 14 olle 1244     JSONObject jsonStat = new JSONObject();
2401 06 May 14 olle 1245     jsonStat.put("headerTitleTop", headerTitle);
2401 06 May 14 olle 1246     jsonStat.put("titleTop", title);
2401 06 May 14 olle 1247     jsonStat.put("titleBottom", "");
2401 06 May 14 olle 1248     jsonStat.put("subTitleRight", "n = " + numItems);
2401 06 May 14 olle 1249     jsonStat.put("subTitleLeft01", "mean, " + Values.formatNumber(floatMean, localNumberOfDecimals));
2401 06 May 14 olle 1250     jsonStat.put("subTitleLeft02", "sd, " + Values.formatNumber(floatSDev, localNumberOfDecimals));
2401 06 May 14 olle 1251     jsonStat.put("subTitleLeft03", "range, " + Values.formatNumber(floatMin, localNumberOfDecimals) + ", " + Values.formatNumber(floatMax, localNumberOfDecimals));
2401 06 May 14 olle 1252     jsonStat.put("yAxisTitleLeft", variableTitle);
2401 06 May 14 olle 1253     jsonStat.put("yAxisTitleRight", "");
2401 06 May 14 olle 1254     // Create JSON array of sample statistics for time periods
2401 06 May 14 olle 1255     JSONArray jsonPeriodPercentilesArray = new JSONArray();
2401 06 May 14 olle 1256     List<String> periodList = new ArrayList<String>();
2401 06 May 14 olle 1257     for (String period: periodStringFloatListHashMap.keySet())
2401 06 May 14 olle 1258     {
2401 06 May 14 olle 1259       periodList.add(period);
2401 06 May 14 olle 1260     }
2401 06 May 14 olle 1261     Collections.sort(periodList);
2401 06 May 14 olle 1262     for (String period: periodList)
2401 06 May 14 olle 1263     {
2401 06 May 14 olle 1264       if (periodStringFloatListHashMap.get(period).size() >= minItemsForStatisticsCalculation)
2401 06 May 14 olle 1265       {
2401 06 May 14 olle 1266         List<Float> periodFloatList = periodStringFloatListHashMap.get(period);
2401 06 May 14 olle 1267         // Get name of time period in standard format for plot
2401 06 May 14 olle 1268         String periodName = fetchPeriodNameForPlot(period, viewType, null);
2401 06 May 14 olle 1269         JSONObject jsonPeriodData = createSamplePeriodJSONStatistics(periodFloatList, periodName);
2401 06 May 14 olle 1270         jsonPeriodPercentilesArray.add(jsonPeriodData);
2401 06 May 14 olle 1271       }
2401 06 May 14 olle 1272     }
2401 06 May 14 olle 1273     jsonStat.put("percentileData", jsonPeriodPercentilesArray);
2401 06 May 14 olle 1274     // Create JSON array of percentile data for all samples
2401 06 May 14 olle 1275     JSONArray jsonPercentilesArray = new JSONArray();
2401 06 May 14 olle 1276     JSONObject jsonPct25 = createValueWithText(floatPct25, localNumberOfDecimals);
2401 06 May 14 olle 1277     jsonPercentilesArray.add(jsonPct25);
2401 06 May 14 olle 1278     JSONObject jsonPct50 = createValueWithText(floatPct50, localNumberOfDecimals);
2401 06 May 14 olle 1279     jsonPercentilesArray.add(jsonPct50);
2401 06 May 14 olle 1280     JSONObject jsonPct75 = createValueWithText(floatPct75, localNumberOfDecimals);
2401 06 May 14 olle 1281     jsonPercentilesArray.add(jsonPct75);
2401 06 May 14 olle 1282     jsonStat.put("valueGuideLinesY", jsonPercentilesArray);
2401 06 May 14 olle 1283     return jsonStat;        
2401 06 May 14 olle 1284   }
2401 06 May 14 olle 1285
2401 06 May 14 olle 1286
2401 06 May 14 olle 1287
2401 06 May 14 olle 1288   private JSONObject createJSONPlotDisplay(String chartVariant, String headerTitle, String title, String variableTitle, HashMap<String,List<Float>> periodStringFloatListHashMap, String viewType, Date startDate)
2401 06 May 14 olle 1289     throws ServletException, IOException 
2401 06 May 14 olle 1290   {
2401 06 May 14 olle 1291     // Calculate statistics for all samples
2401 06 May 14 olle 1292     List<Float> floatList = singleFloatList(periodStringFloatListHashMap);
2401 06 May 14 olle 1293     int numItems = floatList.size();
2401 06 May 14 olle 1294     Float floatMin = calculateMinValue(floatList);
2401 06 May 14 olle 1295     Float floatMax = calculateMaxValue(floatList);
2401 06 May 14 olle 1296     Float floatMean = calculateMeanValue(floatList);
2401 06 May 14 olle 1297     Float floatSDev = calculateSDev(floatList);
2401 06 May 14 olle 1298     Collections.sort(floatList);
2401 06 May 14 olle 1299     Float floatPct25 = calculatePercentile(floatList, 0.25f);
2401 06 May 14 olle 1300     Float floatPct50 = calculatePercentile(floatList, 0.50f);
2401 06 May 14 olle 1301     Float floatPct75 = calculatePercentile(floatList, 0.75f);
2401 06 May 14 olle 1302     int localNumberOfDecimals = numberOfDecimals;
2401 06 May 14 olle 1303     if (floatPct25 != null && floatPct25 < 1)
2401 06 May 14 olle 1304     {
2401 06 May 14 olle 1305       localNumberOfDecimals = numberOfDecimals + 1;
2401 06 May 14 olle 1306     }
2401 06 May 14 olle 1307     // Create JSON object with sample statistics
2401 06 May 14 olle 1308     JSONObject jsonStat = new JSONObject();
2401 06 May 14 olle 1309     jsonStat.put("headerTitleTop", headerTitle);
2401 06 May 14 olle 1310     jsonStat.put("titleTop", title);
2401 06 May 14 olle 1311     jsonStat.put("titleBottom", "");
2401 06 May 14 olle 1312     jsonStat.put("subTitleRight", "n = " + numItems);
2401 06 May 14 olle 1313     jsonStat.put("subTitleLeft01", "mean, " + Values.formatNumber(floatMean, localNumberOfDecimals));
2401 06 May 14 olle 1314     jsonStat.put("subTitleLeft02", "sd, " + Values.formatNumber(floatSDev, localNumberOfDecimals));
2401 06 May 14 olle 1315     jsonStat.put("subTitleLeft03", "range, " + Values.formatNumber(floatMin, localNumberOfDecimals) + ", " + Values.formatNumber(floatMax, localNumberOfDecimals));
2401 06 May 14 olle 1316     jsonStat.put("yAxisTitleLeft", variableTitle);
2401 06 May 14 olle 1317     jsonStat.put("yAxisTitleRight", "");
2401 06 May 14 olle 1318     // Create JSON array of sample statistics for time periods
2401 06 May 14 olle 1319     JSONArray jsonPeriodPercentilesArray = new JSONArray();
2401 06 May 14 olle 1320     List<String> periodList = new ArrayList<String>();
2401 06 May 14 olle 1321     for (String period: periodStringFloatListHashMap.keySet())
2401 06 May 14 olle 1322     {
2401 06 May 14 olle 1323       periodList.add(period);
2401 06 May 14 olle 1324     }
2401 06 May 14 olle 1325     Collections.sort(periodList);
2405 07 May 14 olle 1326     //log.debug("periodList = " + periodList);
2401 06 May 14 olle 1327     // For overview display, set missing start date to midnight of first data entry
2401 06 May 14 olle 1328     if (viewType != null && viewType.equals("overviewDisplay") && startDate == null)
2401 06 May 14 olle 1329     {
2401 06 May 14 olle 1330       if (periodList != null && periodList.size() > 0)
2401 06 May 14 olle 1331       {
2401 06 May 14 olle 1332         String firstPeriod = (String) periodList.get(0);
2401 06 May 14 olle 1333         if (firstPeriod != null && !firstPeriod.equals(""))
2401 06 May 14 olle 1334         {
2401 06 May 14 olle 1335           // Set start time to midnight of first day
2401 06 May 14 olle 1336           long minutesSinceEpoch = Long.parseLong(firstPeriod);
2401 06 May 14 olle 1337           Calendar cal = GregorianCalendar.getInstance();
2401 06 May 14 olle 1338           cal.setTimeInMillis(minutesSinceEpoch*60L*1000L);
2401 06 May 14 olle 1339           cal.set(Calendar.HOUR_OF_DAY, 0);
2401 06 May 14 olle 1340           cal.set(Calendar.MINUTE, 0);
2401 06 May 14 olle 1341           cal.set(Calendar.SECOND, 0);
2401 06 May 14 olle 1342           cal.set(Calendar.MILLISECOND, 0);
2401 06 May 14 olle 1343           startDate = cal.getTime();
2401 06 May 14 olle 1344         }
2401 06 May 14 olle 1345       }
2401 06 May 14 olle 1346     }
2401 06 May 14 olle 1347     for (String period: periodList)
2401 06 May 14 olle 1348     {
2401 06 May 14 olle 1349       List<Float> periodFloatList = periodStringFloatListHashMap.get(period);
2401 06 May 14 olle 1350       // Get name of time period in standard format for plot
2401 06 May 14 olle 1351       String periodName = fetchPeriodNameForPlot(period, viewType, startDate);
2401 06 May 14 olle 1352       //log.debug("period = " + period + " periodName = " + periodName + " periodFloatList = " + periodFloatList);
2401 06 May 14 olle 1353       int numPeriodItems = periodFloatList.size();
2401 06 May 14 olle 1354       if (numPeriodItems > 0)
2401 06 May 14 olle 1355       {
2401 06 May 14 olle 1356         float floatValue = (float) periodFloatList.get(0);
2401 06 May 14 olle 1357         JSONObject jsonPeriodData = new JSONObject();
2401 06 May 14 olle 1358         jsonPeriodData.put("name", periodName);
2401 06 May 14 olle 1359         jsonPeriodData.put("numItems", numPeriodItems);
2401 06 May 14 olle 1360         jsonPeriodData.put("v3", floatValue);
2401 06 May 14 olle 1361         jsonPeriodPercentilesArray.add(jsonPeriodData);
2401 06 May 14 olle 1362       }
2401 06 May 14 olle 1363     }
2401 06 May 14 olle 1364     jsonStat.put("percentileData", jsonPeriodPercentilesArray);
2401 06 May 14 olle 1365     // Create JSON array of percentile data for all samples
2401 06 May 14 olle 1366     JSONArray jsonPercentilesArray = new JSONArray();
2401 06 May 14 olle 1367     JSONObject jsonPct25 = createValueWithText(floatPct25, localNumberOfDecimals);
2401 06 May 14 olle 1368     jsonPercentilesArray.add(jsonPct25);
2401 06 May 14 olle 1369     JSONObject jsonPct50 = createValueWithText(floatPct50, localNumberOfDecimals);
2401 06 May 14 olle 1370     jsonPercentilesArray.add(jsonPct50);
2401 06 May 14 olle 1371     JSONObject jsonPct75 = createValueWithText(floatPct75, localNumberOfDecimals);
2401 06 May 14 olle 1372     jsonPercentilesArray.add(jsonPct75);
2401 06 May 14 olle 1373     jsonStat.put("valueGuideLinesY", jsonPercentilesArray);
2401 06 May 14 olle 1374     // For weekly display, add extra JSON data with text for day markers in graph
2401 06 May 14 olle 1375     if (viewType != null && viewType.equals("weeklyDisplay"))
2401 06 May 14 olle 1376     {
2401 06 May 14 olle 1377       Calendar cal = GregorianCalendar.getInstance();
2401 06 May 14 olle 1378       cal.setTime(startDate);
2401 06 May 14 olle 1379       ReportTableUtil reportTableUtil = new ReportTableUtil();
2401 06 May 14 olle 1380       DateFormat yearMonthDayPeriodDateFormat = reportTableUtil.getYearMonthDayPeriodDateFormat();
2401 06 May 14 olle 1381       DateFormat dateFormat = reportTableUtil.getYearMonthDayPeriodDateFormat();
2401 06 May 14 olle 1382       JSONObject jsonDayInWeekString = new JSONObject();
2401 06 May 14 olle 1383       for (int i = 0; i < 8; i++)
2401 06 May 14 olle 1384       {
2401 06 May 14 olle 1385         if (i > 0)
2401 06 May 14 olle 1386         {
2401 06 May 14 olle 1387           // Add one day to temporary date
2401 06 May 14 olle 1388           cal.add(Calendar.DATE, 1);
2401 06 May 14 olle 1389         }
2401 06 May 14 olle 1390         Date tmpDate = cal.getTime();
2401 06 May 14 olle 1391         String yearMonthDayStr = yearMonthDayPeriodDateFormat.format(tmpDate);
2401 06 May 14 olle 1392         String dayOfWeekStr = reportTableUtil.getDayOfWeekString(tmpDate, false);
2401 06 May 14 olle 1393         String dayInWeekStr = yearMonthDayStr + "_" + dayOfWeekStr;
2401 06 May 14 olle 1394         String dayInWeekIndexKey = "0" + i;
2401 06 May 14 olle 1395         jsonDayInWeekString.put(dayInWeekIndexKey, dayInWeekStr);
2401 06 May 14 olle 1396       }
2401 06 May 14 olle 1397       jsonStat.put("dayInWeekString", jsonDayInWeekString);
2401 06 May 14 olle 1398     }
2401 06 May 14 olle 1399     // For overview display, add extra JSON data with text for day markers in graph
2401 06 May 14 olle 1400     if (viewType != null && viewType.equals("overviewDisplay"))
2401 06 May 14 olle 1401     {
2401 06 May 14 olle 1402       // Get end date
2401 06 May 14 olle 1403       Calendar calEnd = GregorianCalendar.getInstance();
2401 06 May 14 olle 1404       calEnd.setTime(new Date());
2401 06 May 14 olle 1405       calEnd.add(Calendar.DATE, 1);
2401 06 May 14 olle 1406       Date tomorrow = calEnd.getTime();
2401 06 May 14 olle 1407       //
2401 06 May 14 olle 1408       Calendar cal = GregorianCalendar.getInstance();
2401 06 May 14 olle 1409       cal.setTime(startDate);
2401 06 May 14 olle 1410       ReportTableUtil reportTableUtil = new ReportTableUtil();
2401 06 May 14 olle 1411       DateFormat yearMonthDayPeriodDateFormat = reportTableUtil.getYearMonthDayPeriodDateFormat();
2401 06 May 14 olle 1412       //DateFormat dateFormat = reportTableUtil.getYearMonthDayPeriodDateFormat();
2401 06 May 14 olle 1413       JSONObject jsonDayInWeekString = new JSONObject();
2401 06 May 14 olle 1414       Date tmpDate = cal.getTime();
2401 06 May 14 olle 1415       int numMarkers = 0;
2401 06 May 14 olle 1416       int i = 0;
2401 06 May 14 olle 1417       while (tmpDate.compareTo(tomorrow) < 0)
2401 06 May 14 olle 1418       {
2401 06 May 14 olle 1419         if (i > 0)
2401 06 May 14 olle 1420         {
2401 06 May 14 olle 1421           // Add one day to temporary date
2401 06 May 14 olle 1422           cal.add(Calendar.DATE, 1);
2401 06 May 14 olle 1423         }
2401 06 May 14 olle 1424         tmpDate = cal.getTime();
2401 06 May 14 olle 1425         if (tmpDate.compareTo(tomorrow) < 0)
2401 06 May 14 olle 1426         {
2401 06 May 14 olle 1427           String yearMonthDayStr = yearMonthDayPeriodDateFormat.format(tmpDate);
2401 06 May 14 olle 1428           String dayOfWeekStr = reportTableUtil.getDayOfWeekString(tmpDate, false);
2401 06 May 14 olle 1429           //String dayInWeekStr = yearMonthDayStr + "_" + dayOfWeekStr;
2401 06 May 14 olle 1430           String dayInWeekStr = yearMonthDayStr;
2401 06 May 14 olle 1431           String dayInWeekIndexKey = "" + i;
2401 06 May 14 olle 1432           if (i < 10)
2401 06 May 14 olle 1433           {
2401 06 May 14 olle 1434             dayInWeekIndexKey = "0" + dayInWeekIndexKey;
2401 06 May 14 olle 1435           }
2401 06 May 14 olle 1436           if (i < 100)
2401 06 May 14 olle 1437           {
2401 06 May 14 olle 1438             dayInWeekIndexKey = "0" + dayInWeekIndexKey;
2401 06 May 14 olle 1439           }
2401 06 May 14 olle 1440           if (i < 1000)
2401 06 May 14 olle 1441           {
2401 06 May 14 olle 1442             dayInWeekIndexKey = "0" + dayInWeekIndexKey;
2401 06 May 14 olle 1443           }
2401 06 May 14 olle 1444           jsonDayInWeekString.put(dayInWeekIndexKey, dayInWeekStr);
2401 06 May 14 olle 1445           numMarkers++;
2401 06 May 14 olle 1446           log.debug("i = " + i + " dayInWeekIndexKey = " + dayInWeekIndexKey + " dayInWeekStr = " + dayInWeekStr);
2401 06 May 14 olle 1447         }
2401 06 May 14 olle 1448         i++;
2401 06 May 14 olle 1449       }
2401 06 May 14 olle 1450       jsonDayInWeekString.put("numMarkers", numMarkers);
2401 06 May 14 olle 1451       jsonStat.put("dayInWeekString", jsonDayInWeekString);
2401 06 May 14 olle 1452     }
2401 06 May 14 olle 1453     return jsonStat;        
2401 06 May 14 olle 1454   }
2401 06 May 14 olle 1455
2401 06 May 14 olle 1456   private JSONObject createValueWithText(Float value, int numberOfDecimalsShown)
2401 06 May 14 olle 1457   {
2401 06 May 14 olle 1458     if (value == null)
2401 06 May 14 olle 1459     {
2401 06 May 14 olle 1460       return null;
2401 06 May 14 olle 1461     }
2401 06 May 14 olle 1462     JSONObject jsonValueWithText = createValueWithText(value, Values.formatNumber(value, numberOfDecimalsShown));
2401 06 May 14 olle 1463     return jsonValueWithText;
2401 06 May 14 olle 1464   }
2401 06 May 14 olle 1465
2401 06 May 14 olle 1466   private JSONObject createValueWithText(Float value, String text)
2401 06 May 14 olle 1467   {
2401 06 May 14 olle 1468     if (value == null)
2401 06 May 14 olle 1469     {
2401 06 May 14 olle 1470       return null;
2401 06 May 14 olle 1471     }
2401 06 May 14 olle 1472     JSONObject jsonValueWithText = new JSONObject();
2401 06 May 14 olle 1473     jsonValueWithText.put("value", value);
2401 06 May 14 olle 1474     jsonValueWithText.put("text", text);    
2401 06 May 14 olle 1475     return jsonValueWithText;
2401 06 May 14 olle 1476   }
2401 06 May 14 olle 1477
2401 06 May 14 olle 1478   private JSONObject createSamplePeriodJSONStatistics(List<Float> floatList, String periodName)
2401 06 May 14 olle 1479       throws ServletException, IOException 
2401 06 May 14 olle 1480     {  
2401 06 May 14 olle 1481       // Calculate statistics for samples
2401 06 May 14 olle 1482       int numItems = floatList.size();
2401 06 May 14 olle 1483       Collections.sort(floatList);
2401 06 May 14 olle 1484       //Float floatPct05 = calculatePercentile(floatList, 0.05f);
2401 06 May 14 olle 1485       Float floatPct25 = calculatePercentile(floatList, 0.25f);
2401 06 May 14 olle 1486       Float floatPct50 = calculatePercentile(floatList, 0.50f);
2401 06 May 14 olle 1487       Float floatPct75 = calculatePercentile(floatList, 0.75f);
2401 06 May 14 olle 1488       //Float floatPct95 = calculatePercentile(floatList, 0.95f);
2401 06 May 14 olle 1489       // Inter-percentile range ipr = pct75 - pct25
2401 06 May 14 olle 1490       // Calculate whisker values as lowest and highest data values within coef*ipr from box ends
2401 06 May 14 olle 1491       float coef = 1.5f;
2401 06 May 14 olle 1492       Float w1 = calculateBoxPlotWhiskerValue(floatList, floatPct25, floatPct75, coef, "lower");
2401 06 May 14 olle 1493       Float w2 = calculateBoxPlotWhiskerValue(floatList, floatPct25, floatPct75, coef, "upper");
2401 06 May 14 olle 1494       // Create JSON object with sample statistics for period
2401 06 May 14 olle 1495       JSONObject jsonStat = new JSONObject();
2401 06 May 14 olle 1496       jsonStat.put("name", periodName);
2401 06 May 14 olle 1497       jsonStat.put("numItems", numItems);
2401 06 May 14 olle 1498       jsonStat.put("v1", w1);
2401 06 May 14 olle 1499       jsonStat.put("v2", floatPct25);
2401 06 May 14 olle 1500       jsonStat.put("v3", floatPct50);
2401 06 May 14 olle 1501       jsonStat.put("v4", floatPct75);
2401 06 May 14 olle 1502       jsonStat.put("v5", w2);
2401 06 May 14 olle 1503       return jsonStat;        
2401 06 May 14 olle 1504     }
2401 06 May 14 olle 1505
2401 06 May 14 olle 1506   /**
2401 06 May 14 olle 1507    *  Returns a period string intended for use as label in graph plot.
2401 06 May 14 olle 1508    *  The period string will be modified as follows for different view types:<br>
2401 06 May 14 olle 1509    *
2401 06 May 14 olle 1510    *  Daily display:    Number of minutes since midnight
2401 06 May 14 olle 1511    *  Weekly display:   Number of minutes since midnight of first day
2401 06 May 14 olle 1512    *  Overview display: Number of minutes since midnight of first day
2401 06 May 14 olle 1513    *
2401 06 May 14 olle 1514    *  Year view:    yyyy  ->  yyyy    (no change)<br>
2401 06 May 14 olle 1515    *  Quarter view: yyyyq  -> yyyy-Qq (e.g. 20123  -> 2012-Q3)<br>
2401 06 May 14 olle 1516    *  Month view:   yyyymm -> yyyy-mm (e.g. 201203 -> 2012-03)<br>
2401 06 May 14 olle 1517    *  Week view:    yyyyww -> yyyy-ww (e.g. 201203 -> 2012-03)<br>
2401 06 May 14 olle 1518    * 
2401 06 May 14 olle 1519    *  @param period String The period string in pure number format.
2401 06 May 14 olle 1520    *  @param viewType String The view type.
2401 06 May 14 olle 1521    *  @param startDate Date Start date (needed for viewType "weeklyDisplay" only)
2401 06 May 14 olle 1522    *  @return String A period string intended for use as label in box plot.
2401 06 May 14 olle 1523    */
2401 06 May 14 olle 1524   private String fetchPeriodNameForPlot(String period, String viewType, Date startDate)
2401 06 May 14 olle 1525   {
2401 06 May 14 olle 1526     if (viewType != null && viewType.equals("dailyDisplay"))
2401 06 May 14 olle 1527     {
2401 06 May 14 olle 1528       // Remove all initial zeroes except last single zero
2401 06 May 14 olle 1529       String tmp = period;
2401 06 May 14 olle 1530       int zeroIndex = tmp.indexOf("0");
2401 06 May 14 olle 1531       while (tmp.length() > 1 && zeroIndex == 0)
2401 06 May 14 olle 1532       {
2401 06 May 14 olle 1533         // Remove first zero and check if more should be removed
2401 06 May 14 olle 1534         tmp = tmp.substring(1);
2401 06 May 14 olle 1535         zeroIndex = tmp.indexOf("0");
2401 06 May 14 olle 1536       }
2401 06 May 14 olle 1537       return tmp;
2401 06 May 14 olle 1538     }
2401 06 May 14 olle 1539     else if (viewType != null && viewType.equals("weeklyDisplay"))
2401 06 May 14 olle 1540     {
2401 06 May 14 olle 1541       // Return number of minutes since midnight of first day
2401 06 May 14 olle 1542       // Input period string is number of minutes after 1970-01-01 00:00:00
2401 06 May 14 olle 1543       // 2000-01-01 00:00:00 ~ 15 778 080 min, 2100-01-01 00:00:00 ~ 68 374 080; no initial zeroes needed until 2160-02-18 10:40:00
2401 06 May 14 olle 1544       if (period != null && startDate != null)
2401 06 May 14 olle 1545       {
2401 06 May 14 olle 1546         long minutesSinceEpoch = Long.parseLong(period);
2401 06 May 14 olle 1547         long startDateMinutesSinceEpoch = startDate.getTime()/(1000L*60L);
2401 06 May 14 olle 1548         long minutesSinceMidnightFirstDay = minutesSinceEpoch - startDateMinutesSinceEpoch;
2401 06 May 14 olle 1549         period = "" + minutesSinceMidnightFirstDay;
2401 06 May 14 olle 1550       }
2401 06 May 14 olle 1551       return period;
2401 06 May 14 olle 1552     }
2401 06 May 14 olle 1553     else if (viewType != null && viewType.equals("overviewDisplay"))
2401 06 May 14 olle 1554     {
2401 06 May 14 olle 1555       // Return number of minutes since midnight of first day
2401 06 May 14 olle 1556       // Input period string is number of minutes after 1970-01-01 00:00:00
2401 06 May 14 olle 1557       // 2000-01-01 00:00:00 ~ 15 778 080 min, 2100-01-01 00:00:00 ~ 68 374 080; no initial zeroes needed until 2160-02-18 10:40:00
2401 06 May 14 olle 1558       if (period != null && startDate != null)
2401 06 May 14 olle 1559       {
2401 06 May 14 olle 1560         long minutesSinceEpoch = Long.parseLong(period);
2401 06 May 14 olle 1561         long startDateMinutesSinceEpoch = startDate.getTime()/(1000L*60L);
2401 06 May 14 olle 1562         long minutesSinceMidnightFirstDay = minutesSinceEpoch - startDateMinutesSinceEpoch;
2401 06 May 14 olle 1563         period = "" + minutesSinceMidnightFirstDay;
2401 06 May 14 olle 1564       }
2401 06 May 14 olle 1565       return period;
2401 06 May 14 olle 1566     }
2401 06 May 14 olle 1567     if (period == null || period.length() < 4)
2401 06 May 14 olle 1568     {
2401 06 May 14 olle 1569       return period;
2401 06 May 14 olle 1570     }
2401 06 May 14 olle 1571     String yearStr = period.substring(0,4);
2401 06 May 14 olle 1572     String residueStr = period.substring(4);
2401 06 May 14 olle 1573     // Add year string
2401 06 May 14 olle 1574     String periodName = yearStr;
2401 06 May 14 olle 1575     if (residueStr.length() > 0)
2401 06 May 14 olle 1576     {
2401 06 May 14 olle 1577       // Add hyphen after year string
2401 06 May 14 olle 1578       periodName += "-";
2401 06 May 14 olle 1579       if (viewType.equals(ReportTableUtil.quarterView))
2401 06 May 14 olle 1580       {
2401 06 May 14 olle 1581         // Add 'Q' after year string
2401 06 May 14 olle 1582         periodName += "Q";
2401 06 May 14 olle 1583       }
2401 06 May 14 olle 1584       // Add residue string (quarter, month, or week string)
2401 06 May 14 olle 1585       periodName += residueStr;
2401 06 May 14 olle 1586     }
2401 06 May 14 olle 1587     return periodName;
2401 06 May 14 olle 1588   }
2401 06 May 14 olle 1589
2401 06 May 14 olle 1590
4526 19 Jun 17 nicklas 1591   private HashMap<String, List<Float>> createPeriodStringFloatListHashMap(String chartVariant, List<LabEnvironmentData> lthdList, String viewType, String variableType, Date startDate)
2401 06 May 14 olle 1592     throws ServletException, IOException 
2401 06 May 14 olle 1593   {
2401 06 May 14 olle 1594     // Default variable is temperature
2401 06 May 14 olle 1595     if (variableType == null || variableType.equals(""))
2401 06 May 14 olle 1596     {
2401 06 May 14 olle 1597       variableType = variableTypeTemperature;
2401 06 May 14 olle 1598     }
2401 06 May 14 olle 1599     // Create HashMap to keep track of values for each time period
2401 06 May 14 olle 1600     HashMap<String, List<Float>> periodStringFloatListHashMap = new HashMap<String, List<Float>>();
2401 06 May 14 olle 1601     
2401 06 May 14 olle 1602     for (LabEnvironmentData lthd: lthdList)
2401 06 May 14 olle 1603     {
2401 06 May 14 olle 1604       Date dateTime = lthd.getDateTime();
2401 06 May 14 olle 1605       // Get current period
4526 19 Jun 17 nicklas 1606       String currentPeriod = tableUtil.getCurrentPeriod(dateTime, viewType, startDate);
2401 06 May 14 olle 1607       //log.debug("dateTime = " + dateTime + " currentPeriod = " + currentPeriod + " viewType = " + viewType);
2401 06 May 14 olle 1608       // Update period value hash map
2401 06 May 14 olle 1609       Float value = null;
2401 06 May 14 olle 1610       // Get value of desired variable
2401 06 May 14 olle 1611       if (variableType.equals(variableTypeTemperature))
2401 06 May 14 olle 1612       {
2401 06 May 14 olle 1613         value = Double.valueOf(lthd.getTemperature()).floatValue();
2401 06 May 14 olle 1614       }
2401 06 May 14 olle 1615       else if (variableType.equals(variableTypeHumidity))
2401 06 May 14 olle 1616       {
2401 06 May 14 olle 1617         value = Double.valueOf(lthd.getHumidity()).floatValue();
2401 06 May 14 olle 1618       }
2401 06 May 14 olle 1619       updateStringFloatListHashMap(periodStringFloatListHashMap, currentPeriod, value);
2401 06 May 14 olle 1620 /*
2401 06 May 14 olle 1621       //
2401 06 May 14 olle 1622       long unixTimeInSeconds = lthd.getUnixTime();
2401 06 May 14 olle 1623       Calendar cal = GregorianCalendar.getInstance();
2401 06 May 14 olle 1624       cal.setTimeInMillis(unixTimeInSeconds*1000L);
2401 06 May 14 olle 1625 */
2401 06 May 14 olle 1626     }
2401 06 May 14 olle 1627     return periodStringFloatListHashMap;        
2401 06 May 14 olle 1628   }
2401 06 May 14 olle 1629
2401 06 May 14 olle 1630   private JSONObject addExtraInfo(JSONObject plotJsonData, String chartVariant)
2401 06 May 14 olle 1631   {
2401 06 May 14 olle 1632     if (plotJsonData != null && chartVariant != null)
2401 06 May 14 olle 1633     {
2401 06 May 14 olle 1634 /*
2401 06 May 14 olle 1635       if (chartVariant.equals(remainingQuantityForScanBSpecimenChart))
2401 06 May 14 olle 1636       {
2401 06 May 14 olle 1637         String subTitleRight = (String) plotJsonData.get("subTitleRight");
2401 06 May 14 olle 1638         subTitleRight += "; > 1 mg, n = " + getNumRemainingTissueItemsGT1Mg();
2401 06 May 14 olle 1639         plotJsonData.put("subTitleRight", subTitleRight);
2401 06 May 14 olle 1640       }
2401 06 May 14 olle 1641 */    
2401 06 May 14 olle 1642     }
2401 06 May 14 olle 1643     return plotJsonData;
2401 06 May 14 olle 1644   }
2401 06 May 14 olle 1645
2401 06 May 14 olle 1646   private HashMap<String, List<Float>> updateStringFloatListHashMap(HashMap<String, List<Float>> stringFloatListHashMap, String string, Float value)
2401 06 May 14 olle 1647   {
2401 06 May 14 olle 1648     if (stringFloatListHashMap == null)
2401 06 May 14 olle 1649     {
2401 06 May 14 olle 1650       stringFloatListHashMap = new HashMap<String, List<Float>>();
2401 06 May 14 olle 1651     }
2401 06 May 14 olle 1652     if (string != null && !string.equals("") && value != null)
2401 06 May 14 olle 1653     {
2401 06 May 14 olle 1654       List<Float> floatList = stringFloatListHashMap.get(string);
2401 06 May 14 olle 1655       if (floatList == null)
2401 06 May 14 olle 1656       {
2401 06 May 14 olle 1657         floatList = new ArrayList<Float>();
2401 06 May 14 olle 1658       }
2401 06 May 14 olle 1659       floatList.add(value);
2401 06 May 14 olle 1660       stringFloatListHashMap.put(string,  floatList);
2401 06 May 14 olle 1661     }
2401 06 May 14 olle 1662     return stringFloatListHashMap;
2401 06 May 14 olle 1663   }
2401 06 May 14 olle 1664
2401 06 May 14 olle 1665   /**
2401 06 May 14 olle 1666    *  Returns a single List<Float> with all values in all the
2401 06 May 14 olle 1667    *  lists in the HashMap<String, List<Float>>.
2401 06 May 14 olle 1668    *
2401 06 May 14 olle 1669    *  @param stringFloatListHashMap HashMap<String, List<Float>> The HashMap to use.
2401 06 May 14 olle 1670    *  @return List<Float> The list of float values in all the lists in the HashMap<String, List<Float>>.
2401 06 May 14 olle 1671    */
2401 06 May 14 olle 1672   private List<Float> singleFloatList(HashMap<String, List<Float>> stringFloatListHashMap)
2401 06 May 14 olle 1673   {
2401 06 May 14 olle 1674     List<Float> singleFloatList = new ArrayList<Float>();
2401 06 May 14 olle 1675     for (List<Float> floatList: stringFloatListHashMap.values())
2401 06 May 14 olle 1676     {
2401 06 May 14 olle 1677       for (Float value: floatList)
2401 06 May 14 olle 1678       {
2401 06 May 14 olle 1679         singleFloatList.add(value);
2401 06 May 14 olle 1680       }
2401 06 May 14 olle 1681     }
2401 06 May 14 olle 1682     return singleFloatList;
2401 06 May 14 olle 1683   }
2401 06 May 14 olle 1684
2401 06 May 14 olle 1685   /**
2401 06 May 14 olle 1686    *  Returns a single List<Float> with all values in the input LabEnvironmentData
2401 06 May 14 olle 1687    *  list for the variable of interest.
2401 06 May 14 olle 1688    *
2401 06 May 14 olle 1689    *  @param lthdList List<LabEnvironmentData> The LabEnvironemntData list
2401 06 May 14 olle 1690    *  @param variableType String The variable type to extract values for.
2401 06 May 14 olle 1691    *  @return List<Float> The list of float values of the variable type of interest.
2401 06 May 14 olle 1692    */
2401 06 May 14 olle 1693   private List<Float> singleFloatList(List<LabEnvironmentData> lthdList, String variableType)
2401 06 May 14 olle 1694   {
2401 06 May 14 olle 1695     List<Float> singleFloatList = new ArrayList<Float>();
2401 06 May 14 olle 1696     for (LabEnvironmentData lthd: lthdList)
2401 06 May 14 olle 1697     {
2401 06 May 14 olle 1698       // Get value of desired variables
2401 06 May 14 olle 1699       if (variableType.equals(variableTypeTemperature))
2401 06 May 14 olle 1700       {
2401 06 May 14 olle 1701         singleFloatList.add((float) lthd.getTemperature());
2401 06 May 14 olle 1702       }
2401 06 May 14 olle 1703       else if (variableType.equals(variableTypeHumidity))
2401 06 May 14 olle 1704       {
2401 06 May 14 olle 1705         singleFloatList.add((float) lthd.getHumidity());
2401 06 May 14 olle 1706       }
2401 06 May 14 olle 1707     }
2401 06 May 14 olle 1708     return singleFloatList;
2401 06 May 14 olle 1709   }
2401 06 May 14 olle 1710
2401 06 May 14 olle 1711   private Float calculateMinValue(List<Float> floatList)
2401 06 May 14 olle 1712   {
2401 06 May 14 olle 1713     Float floatMin = Float.valueOf("1000000000.0");
2401 06 May 14 olle 1714     for (Float value: floatList)
2401 06 May 14 olle 1715     {
2401 06 May 14 olle 1716       if (value != null && value < floatMin)
2401 06 May 14 olle 1717       {
2401 06 May 14 olle 1718         floatMin = value;
2401 06 May 14 olle 1719       }
2401 06 May 14 olle 1720     }
2401 06 May 14 olle 1721     return floatMin;
2401 06 May 14 olle 1722   }
2401 06 May 14 olle 1723
2401 06 May 14 olle 1724   private Float calculateMaxValue(List<Float> floatList)
2401 06 May 14 olle 1725   {
2401 06 May 14 olle 1726     Float floatMax = Float.valueOf("-1000000000.0");
2401 06 May 14 olle 1727     for (Float value: floatList)
2401 06 May 14 olle 1728     {
2401 06 May 14 olle 1729       if (value != null && value > floatMax)
2401 06 May 14 olle 1730       {
2401 06 May 14 olle 1731         floatMax = value;
2401 06 May 14 olle 1732       }
2401 06 May 14 olle 1733     }
2401 06 May 14 olle 1734     return floatMax;
2401 06 May 14 olle 1735   }
2401 06 May 14 olle 1736
2401 06 May 14 olle 1737   private Float calculateMeanValue(List<Float> floatList)
2401 06 May 14 olle 1738   {
2401 06 May 14 olle 1739     Float mean = Float.valueOf("0.0");
2401 06 May 14 olle 1740     int n = 0;
2401 06 May 14 olle 1741     for (Float value: floatList)
2401 06 May 14 olle 1742     {
2401 06 May 14 olle 1743       if (value != null)
2401 06 May 14 olle 1744       {
2401 06 May 14 olle 1745         mean += value;
2401 06 May 14 olle 1746         n++;
2401 06 May 14 olle 1747       }
2401 06 May 14 olle 1748     }
2401 06 May 14 olle 1749     if (n > 0)
2401 06 May 14 olle 1750     {
2401 06 May 14 olle 1751       mean /= n;
2401 06 May 14 olle 1752     }
2401 06 May 14 olle 1753     return mean;
2401 06 May 14 olle 1754   }
2401 06 May 14 olle 1755
2401 06 May 14 olle 1756   private Float calculateSDev(List<Float> floatList)
2401 06 May 14 olle 1757   {
2401 06 May 14 olle 1758     Float var = Float.valueOf("0.0");
2401 06 May 14 olle 1759     Float mean = calculateMeanValue(floatList);
2401 06 May 14 olle 1760     int n = 0;
2401 06 May 14 olle 1761     Float dist = Float.valueOf("0.0");
2401 06 May 14 olle 1762     for (Float value: floatList)
2401 06 May 14 olle 1763     {
2401 06 May 14 olle 1764       if (value != null)
2401 06 May 14 olle 1765       {
2401 06 May 14 olle 1766         dist = (value - mean);
2401 06 May 14 olle 1767         var += dist*dist;
2401 06 May 14 olle 1768         n++;
2401 06 May 14 olle 1769       }
2401 06 May 14 olle 1770     }
2401 06 May 14 olle 1771     if (n > 1)
2401 06 May 14 olle 1772     {
2401 06 May 14 olle 1773       var /= (n - 1);
2401 06 May 14 olle 1774     }
2401 06 May 14 olle 1775     Float sDev = Double.valueOf(Math.sqrt(var)).floatValue();
2401 06 May 14 olle 1776     return sDev;
2401 06 May 14 olle 1777   }
2401 06 May 14 olle 1778
2401 06 May 14 olle 1779   private Float calculatePercentile(List<Float> sortedAscFloatList, float fraction)
2401 06 May 14 olle 1780   {
2401 06 May 14 olle 1781     Float percentileValue = null;
2401 06 May 14 olle 1782     if (sortedAscFloatList == null || sortedAscFloatList.size() < 1 || fraction <= 0.0 || fraction >= 1.0)
2401 06 May 14 olle 1783     {
2401 06 May 14 olle 1784       return null;
2401 06 May 14 olle 1785     }
2401 06 May 14 olle 1786     int len = sortedAscFloatList.size();
2401 06 May 14 olle 1787     // List index values goes from 0 to (len - 1)
2401 06 May 14 olle 1788     float indexVal = fraction*(len - 1);
2401 06 May 14 olle 1789     float floorVal = Double.valueOf(Math.floor(indexVal)).floatValue();
2401 06 May 14 olle 1790     float ceilVal = Double.valueOf(Math.ceil(indexVal)).floatValue();
2401 06 May 14 olle 1791     if (floorVal == ceilVal)
2401 06 May 14 olle 1792     {
2401 06 May 14 olle 1793       percentileValue = sortedAscFloatList.get((int) indexVal);
2401 06 May 14 olle 1794     }
2401 06 May 14 olle 1795     else
2401 06 May 14 olle 1796     {
2401 06 May 14 olle 1797       // Calculate percentile value as weighted value of two list values
2401 06 May 14 olle 1798       float d0 = sortedAscFloatList.get((int) floorVal) * (ceilVal - indexVal);
2401 06 May 14 olle 1799       float d1 = sortedAscFloatList.get((int) ceilVal)  * (indexVal - floorVal);
2401 06 May 14 olle 1800       percentileValue = d0 + d1;
2401 06 May 14 olle 1801     }
2401 06 May 14 olle 1802     return percentileValue;
2401 06 May 14 olle 1803   }
2401 06 May 14 olle 1804
2401 06 May 14 olle 1805   private Float calculateBoxPlotWhiskerValue(List<Float> sortedAscFloatList, Float pct25, Float pct75, float coef, String plotEnd)
2401 06 May 14 olle 1806   {
2401 06 May 14 olle 1807     Float whiskerValue = null;
2401 06 May 14 olle 1808     if (sortedAscFloatList == null || sortedAscFloatList.size() < 1 || pct25 == null || pct75 == null || coef <= 0.0 || plotEnd == null || !(plotEnd.equals("lower") || plotEnd.equals("upper")))
2401 06 May 14 olle 1809     {
2401 06 May 14 olle 1810       return null;
2401 06 May 14 olle 1811     }
2401 06 May 14 olle 1812     int len = sortedAscFloatList.size();
2401 06 May 14 olle 1813     // List index values goes from 0 to (len - 1)
2401 06 May 14 olle 1814     float ipr = pct75 - pct25;
2401 06 May 14 olle 1815     float limit = 0.0f;
2401 06 May 14 olle 1816     if (plotEnd.equals("lower"))
2401 06 May 14 olle 1817     {
2401 06 May 14 olle 1818       limit = pct25 - ipr*coef;
2401 06 May 14 olle 1819       float value = 1000000000.0f;
2401 06 May 14 olle 1820       for (int i=(len-1); i >= 0; i--)
2401 06 May 14 olle 1821       {
2401 06 May 14 olle 1822         value = sortedAscFloatList.get(i);
2401 06 May 14 olle 1823         if (value < limit)
2401 06 May 14 olle 1824         {
2401 06 May 14 olle 1825           break;
2401 06 May 14 olle 1826         }
2401 06 May 14 olle 1827         whiskerValue = value;
2401 06 May 14 olle 1828       }
2401 06 May 14 olle 1829     }
2401 06 May 14 olle 1830     else if (plotEnd.equals("upper"))
2401 06 May 14 olle 1831     {
2401 06 May 14 olle 1832       limit = pct75 + ipr*coef;
2401 06 May 14 olle 1833       float value = -1000000000.0f;
2401 06 May 14 olle 1834       for (int i=0; i < len; i++)
2401 06 May 14 olle 1835       {
2401 06 May 14 olle 1836         value = sortedAscFloatList.get(i);
2401 06 May 14 olle 1837         if (value > limit)
2401 06 May 14 olle 1838         {
2401 06 May 14 olle 1839           break;
2401 06 May 14 olle 1840         }
2401 06 May 14 olle 1841         whiskerValue = value;
2401 06 May 14 olle 1842       }
2401 06 May 14 olle 1843     }
2401 06 May 14 olle 1844     return whiskerValue;
2401 06 May 14 olle 1845   }
2401 06 May 14 olle 1846
2401 06 May 14 olle 1847   /**
2401 06 May 14 olle 1848    *  Returns a chart header title given a chart variant string.
2401 06 May 14 olle 1849    *  If a plot is shown, this is normally the header title
2401 06 May 14 olle 1850    *  printed over the plot itself.
2401 06 May 14 olle 1851    *
2401 06 May 14 olle 1852    *  @param chartVariant String The chart variant to get a plot title for.
2401 06 May 14 olle 1853    *  @param viewType String The view type used for the period selection for the plot.
2401 06 May 14 olle 1854    *  @param chartSite String The site used for the data selection for the plot.
2401 06 May 14 olle 1855    *  @param variableType String The variable used for the data selection for the plot.
2401 06 May 14 olle 1856    *  @param weekdayFilter String Optional weekday filter.
2401 06 May 14 olle 1857    *  @return String A plot title for the given chart variant string.
2401 06 May 14 olle 1858    */
2401 06 May 14 olle 1859   private String fetchChartHeaderTitle(String chartVariant, String viewType, String chartSite, String variableType, String weekdayFilter)
2401 06 May 14 olle 1860   {
2401 06 May 14 olle 1861     // Get time period name for title
2401 06 May 14 olle 1862     String periodName = fetchTimePeriodName(viewType);
2401 06 May 14 olle 1863     // Get plot title
2401 06 May 14 olle 1864     String title = "New chart";
2401 06 May 14 olle 1865     if (chartVariant != null)
2401 06 May 14 olle 1866     {
2401 06 May 14 olle 1867       // String "\u00B5" is the micro character in unicode
2401 06 May 14 olle 1868       // String "\u223C" is the tilde character in unicode
2401 06 May 14 olle 1869       String chartContents = null;
4526 19 Jun 17 nicklas 1870       if (viewType.equals("last24hours"))
2401 06 May 14 olle 1871       {
4526 19 Jun 17 nicklas 1872         chartContents = "last 24 hours";
4526 19 Jun 17 nicklas 1873       }
4526 19 Jun 17 nicklas 1874       else if (viewType.equals("dailyDisplay"))
4526 19 Jun 17 nicklas 1875       {
2401 06 May 14 olle 1876         chartContents = "daily display";
2401 06 May 14 olle 1877       }
2401 06 May 14 olle 1878       else if (viewType.equals("weeklyDisplay"))
2401 06 May 14 olle 1879       {
2401 06 May 14 olle 1880         chartContents = "weekly display";
2401 06 May 14 olle 1881       }
2401 06 May 14 olle 1882       else if (viewType.equals("overviewDisplay"))
2401 06 May 14 olle 1883       {
2428 16 May 14 olle 1884         chartContents = "min, mean, max display";
2401 06 May 14 olle 1885       }
2401 06 May 14 olle 1886       String weekdayStr = "";
2401 06 May 14 olle 1887       if (weekdayFilter != null)
2401 06 May 14 olle 1888       {
2401 06 May 14 olle 1889         if (weekdayFilter.equals(weekdayFilterMondayToFriday))
2401 06 May 14 olle 1890         {
2401 06 May 14 olle 1891           weekdayStr = "Mon-Fri";
2401 06 May 14 olle 1892         }
2401 06 May 14 olle 1893         else if (weekdayFilter.equals(weekdayFilterSaturdayToSunday))
2401 06 May 14 olle 1894         {
2401 06 May 14 olle 1895           weekdayStr = "Sat-Sun";
2401 06 May 14 olle 1896         }
2401 06 May 14 olle 1897         else if (weekdayFilter.equals(weekdayFilterWorkdays))
2401 06 May 14 olle 1898         {
2401 06 May 14 olle 1899           weekdayStr = "Workdays";
2401 06 May 14 olle 1900         }
2401 06 May 14 olle 1901         else if (weekdayFilter.equals(weekdayFilterNonWorkdays))
2401 06 May 14 olle 1902         {
2401 06 May 14 olle 1903           weekdayStr = "Non-workdays";
2401 06 May 14 olle 1904         }
2401 06 May 14 olle 1905       }
2401 06 May 14 olle 1906       if (chartContents != null)
2401 06 May 14 olle 1907       {
2401 06 May 14 olle 1908         if (weekdayStr.equals(""))
2401 06 May 14 olle 1909         {
2401 06 May 14 olle 1910           title = chartSite + " " + chartContents + " of " + variableType;
2401 06 May 14 olle 1911         }
2401 06 May 14 olle 1912         else
2401 06 May 14 olle 1913         {
2401 06 May 14 olle 1914           title = chartSite + " " + chartContents + " of " + variableType + " (" + weekdayStr + ")";
2401 06 May 14 olle 1915         }
2401 06 May 14 olle 1916       }
2401 06 May 14 olle 1917     }
2401 06 May 14 olle 1918     return title;
2401 06 May 14 olle 1919   }
2401 06 May 14 olle 1920
2401 06 May 14 olle 1921   /**
2401 06 May 14 olle 1922    *  Returns a chart header title given a chart variant string.
2401 06 May 14 olle 1923    *  If a plot is shown, this is normally the header title
2401 06 May 14 olle 1924    *  printed over the plot itself.
2401 06 May 14 olle 1925    *
2401 06 May 14 olle 1926    *  @param chartVariant String The chart variant to get a plot title for.
2401 06 May 14 olle 1927    *  @param viewType String The view type used for the period selection for the plot.
2401 06 May 14 olle 1928    *  @param chartSite String The site used for the data selection for the plot.
2401 06 May 14 olle 1929    *  @param variableType String The variable used for the data selection for the plot.
2401 06 May 14 olle 1930    *  @param startDate Date The start date/time for the data selection for the plot.
2401 06 May 14 olle 1931    *  @param endDate Date The end date/time for the data selection for the plot.
2401 06 May 14 olle 1932    *  @return String A plot title for the given chart variant string.
2401 06 May 14 olle 1933    */
2401 06 May 14 olle 1934   private String fetchChartHeaderTitle(String viewType, Date startDate, Date endDate)
2401 06 May 14 olle 1935   {
2401 06 May 14 olle 1936     // Get plot title
2401 06 May 14 olle 1937     String title = "New chart";
2401 06 May 14 olle 1938     DateFormatter dateFormat = new DateFormatter("yyyy-MM-dd HH:mm");
2401 06 May 14 olle 1939     String startDateStr = "Start";
2401 06 May 14 olle 1940     String endDateStr = "Current";
2401 06 May 14 olle 1941     if (startDate != null)
2401 06 May 14 olle 1942     {
2401 06 May 14 olle 1943       startDateStr = dateFormat.format(startDate);
2401 06 May 14 olle 1944     }
2401 06 May 14 olle 1945     if (endDate != null)
2401 06 May 14 olle 1946     {
2401 06 May 14 olle 1947       endDateStr = dateFormat.format(endDate);
2401 06 May 14 olle 1948     }
2401 06 May 14 olle 1949     if (viewType != null)
2401 06 May 14 olle 1950     {
2401 06 May 14 olle 1951       // String "\u00B5" is the micro character in unicode
2401 06 May 14 olle 1952       // String "\u223C" is the tilde character in unicode
2401 06 May 14 olle 1953       String chartContents = null;
2401 06 May 14 olle 1954       if (viewType.equals("dailyDisplay"))
2401 06 May 14 olle 1955       {
2401 06 May 14 olle 1956         chartContents = "Daily display";
2401 06 May 14 olle 1957       }
2401 06 May 14 olle 1958       else if (viewType.equals("weeklyDisplay"))
2401 06 May 14 olle 1959       {
2401 06 May 14 olle 1960         chartContents = "Weekly display";
2401 06 May 14 olle 1961       }
2401 06 May 14 olle 1962       if (chartContents != null)
2401 06 May 14 olle 1963       {
2401 06 May 14 olle 1964         title = chartContents + " for period " + startDateStr + " - " + endDateStr;
2401 06 May 14 olle 1965       }
2401 06 May 14 olle 1966     }
2401 06 May 14 olle 1967     return title;
2401 06 May 14 olle 1968   }
2401 06 May 14 olle 1969
2401 06 May 14 olle 1970   /**
2401 06 May 14 olle 1971    *  Returns the time period name for a view type string.
2401 06 May 14 olle 1972    *
2401 06 May 14 olle 1973    *  @param viewType String The view type used for time period selection.
2401 06 May 14 olle 1974    *  @return String The time period name.
2401 06 May 14 olle 1975    */
2401 06 May 14 olle 1976   private String fetchTimePeriodName(String viewType)
2401 06 May 14 olle 1977   {
2401 06 May 14 olle 1978     // Get time period name
2401 06 May 14 olle 1979     String periodName = "year";
2401 06 May 14 olle 1980     if (viewType.equals(ReportTableUtil.quarterView))
2401 06 May 14 olle 1981     {
2401 06 May 14 olle 1982       periodName = "quarter";
2401 06 May 14 olle 1983     }
2401 06 May 14 olle 1984     else if (viewType.equals(ReportTableUtil.monthView))
2401 06 May 14 olle 1985     {
2401 06 May 14 olle 1986       periodName = "month";
2401 06 May 14 olle 1987     }
2401 06 May 14 olle 1988     else if (viewType.equals(ReportTableUtil.weekView))
2401 06 May 14 olle 1989     {
2401 06 May 14 olle 1990       periodName = "week";
2401 06 May 14 olle 1991     }
2401 06 May 14 olle 1992     return periodName;
2401 06 May 14 olle 1993   }
2401 06 May 14 olle 1994
2401 06 May 14 olle 1995   /**
2401 06 May 14 olle 1996    *  Returns a chart title given mixed information.
2401 06 May 14 olle 1997    *
2401 06 May 14 olle 1998    *  @param viewType String The view type used.
2401 06 May 14 olle 1999    *  @param variableType String The variable used for the data selection for the plot.
2401 06 May 14 olle 2000    *  @param startDate Date The start date/time for the data selection for the plot.
2401 06 May 14 olle 2001    *  @param endDate Date The end date/time for the data selection for the plot.
2401 06 May 14 olle 2002    *  @param daytimeFilterFromTime String Optional daytime filter start time.
2401 06 May 14 olle 2003    *  @param daytimeFilterToTime String Optional daytime filter end time.
2401 06 May 14 olle 2004    *  @return String A chart title for the given input.
2401 06 May 14 olle 2005    */
2401 06 May 14 olle 2006   private String fetchChartTitle(String viewType, String variableType, Date startDate, Date endDate, String daytimeFilterFromTime, String daytimeFilterToTime)
2401 06 May 14 olle 2007     throws ServletException
2401 06 May 14 olle 2008   {
2401 06 May 14 olle 2009     // Get plot title
2401 06 May 14 olle 2010     String title = "New chart";
2401 06 May 14 olle 2011     DateFormatter dateFormat = new DateFormatter("yyyy-MM-dd HH:mm");
2401 06 May 14 olle 2012     // Get report start date
2401 06 May 14 olle 2013     Date reportStartDate = null;
2401 06 May 14 olle 2014     if (startDate != null)
2401 06 May 14 olle 2015     {
2401 06 May 14 olle 2016       reportStartDate = startDate;
2401 06 May 14 olle 2017     }
2401 06 May 14 olle 2018     else
2401 06 May 14 olle 2019     {
2401 06 May 14 olle 2020       // Set report start date to earliest configured sensor start date
2401 06 May 14 olle 2021       // Get lab environment configuration from singleton LabEnvironment
2401 06 May 14 olle 2022       LabEnvironment labEnvironment = LabEnvironment.getInstance();
2401 06 May 14 olle 2023       LabEnvironmentConfiguration labEnvironmentConfiguration = labEnvironment.getLabEnvironmentConfiguration();
2401 06 May 14 olle 2024       List<LabSensorConfig> labSensorConfigList = labEnvironmentConfiguration.getLabSensorConfigList();
2401 06 May 14 olle 2025       for (LabSensorConfig labSensorConfig: labSensorConfigList)
2401 06 May 14 olle 2026       {
2401 06 May 14 olle 2027         String sensorStartDateStr = labSensorConfig.getStartDate();
2401 06 May 14 olle 2028         // Skip sensors with start date not set
2401 06 May 14 olle 2029         if (sensorStartDateStr != null && !sensorStartDateStr.equals(""))
2401 06 May 14 olle 2030         {
2401 06 May 14 olle 2031           // Set report start date to earliest sensor date
2401 06 May 14 olle 2032           Date sensorDate = dateStringToDate(sensorStartDateStr);
2401 06 May 14 olle 2033           if (reportStartDate == null || reportStartDate.compareTo(sensorDate) > 0)
2401 06 May 14 olle 2034           {
2401 06 May 14 olle 2035             reportStartDate = sensorDate;
2401 06 May 14 olle 2036           }
2401 06 May 14 olle 2037         }
2401 06 May 14 olle 2038       }
2401 06 May 14 olle 2039     }
2401 06 May 14 olle 2040     // Get report end date
2401 06 May 14 olle 2041     Date reportEndDate = null;
2401 06 May 14 olle 2042     if (endDate != null)
2401 06 May 14 olle 2043     {
2401 06 May 14 olle 2044       reportEndDate = endDate;
2401 06 May 14 olle 2045     }
2401 06 May 14 olle 2046     else
2401 06 May 14 olle 2047     {
2401 06 May 14 olle 2048       // Set report end date to current date/time
2401 06 May 14 olle 2049       reportEndDate = new Date();
2401 06 May 14 olle 2050     }
2401 06 May 14 olle 2051     // Get report start and end date strings
2401 06 May 14 olle 2052     String reportStartDateStr = "Start";
2401 06 May 14 olle 2053     String reportEndDateStr = "Current";
2401 06 May 14 olle 2054     if (reportStartDate != null)
2401 06 May 14 olle 2055     {
2401 06 May 14 olle 2056       reportStartDateStr = dateFormat.format(reportStartDate);
2401 06 May 14 olle 2057     }
2401 06 May 14 olle 2058     if (reportEndDate != null)
2401 06 May 14 olle 2059     {
2401 06 May 14 olle 2060       reportEndDateStr = dateFormat.format(reportEndDate);
2401 06 May 14 olle 2061     }
2401 06 May 14 olle 2062     // Start variable type string with capital
2401 06 May 14 olle 2063     String varTypeStr = "Variable";
2401 06 May 14 olle 2064     if (variableType != null && variableType.length() > 0)
2401 06 May 14 olle 2065     {
2401 06 May 14 olle 2066       String firstChar = variableType.substring(0,1).toUpperCase();
2401 06 May 14 olle 2067       varTypeStr = firstChar + variableType.substring(1);
2401 06 May 14 olle 2068     }
2401 06 May 14 olle 2069     // Optional daytime filter
2401 06 May 14 olle 2070     String daytimeFilterStr = null;
2401 06 May 14 olle 2071     if ((daytimeFilterFromTime != null && !daytimeFilterFromTime.equals("")) ||
2401 06 May 14 olle 2072       (daytimeFilterToTime != null && !daytimeFilterToTime.equals("")))
2401 06 May 14 olle 2073     {
2401 06 May 14 olle 2074       if (daytimeFilterFromTime == null || daytimeFilterFromTime.equals(""))
2401 06 May 14 olle 2075       {
2401 06 May 14 olle 2076         daytimeFilterFromTime = "0000";
2401 06 May 14 olle 2077       }
2401 06 May 14 olle 2078       if (daytimeFilterToTime == null || daytimeFilterToTime.equals(""))
2401 06 May 14 olle 2079       {
2401 06 May 14 olle 2080         daytimeFilterToTime = "2359";
2401 06 May 14 olle 2081       }
2401 06 May 14 olle 2082       daytimeFilterStr = daytimeFilterFromTime + " - " + daytimeFilterToTime;
2401 06 May 14 olle 2083     }
2401 06 May 14 olle 2084     if (daytimeFilterStr == null)
2401 06 May 14 olle 2085     {
2401 06 May 14 olle 2086       title = varTypeStr + " (" + reportStartDateStr + " - " + reportEndDateStr + ")";
2401 06 May 14 olle 2087     }
2401 06 May 14 olle 2088     else
2401 06 May 14 olle 2089     {
2401 06 May 14 olle 2090       title = "(" + reportStartDateStr + " - " + reportEndDateStr + ") " + daytimeFilterStr;
2401 06 May 14 olle 2091     }
2401 06 May 14 olle 2092     return title;
2401 06 May 14 olle 2093   }
2401 06 May 14 olle 2094
2401 06 May 14 olle 2095   /**
2401 06 May 14 olle 2096    *  Returns a chart y-axis title given a variable type string.
2401 06 May 14 olle 2097    *
2401 06 May 14 olle 2098    *  @param variableType String The variable type to get a y-axis title for.
2401 06 May 14 olle 2099    *  @return String A chart y-axis title for the given variable type string.
2401 06 May 14 olle 2100    */
2401 06 May 14 olle 2101   private String fetchChartYAxisTitle(String variableType)
2401 06 May 14 olle 2102   {
2401 06 May 14 olle 2103     String title = "New chart";
2401 06 May 14 olle 2104     if (variableType != null)
2401 06 May 14 olle 2105     {
2401 06 May 14 olle 2106       // String "\u00B5" is the micro character in unicode
2401 06 May 14 olle 2107       // String "\u223C" is the tilde character in unicode
2401 06 May 14 olle 2108       // String "\u00B0" is the degree character in unicode
2401 06 May 14 olle 2109       if (variableType.equals(variableTypeTemperature))
2401 06 May 14 olle 2110       {
2401 06 May 14 olle 2111         title = "Temperature (\u00B0C)";
2401 06 May 14 olle 2112       }
2401 06 May 14 olle 2113       else if (variableType.equals(variableTypeHumidity))
2401 06 May 14 olle 2114       {
2401 06 May 14 olle 2115         title = "Humidity (%)";
2401 06 May 14 olle 2116       }
2401 06 May 14 olle 2117     }
2401 06 May 14 olle 2118     return title;
2401 06 May 14 olle 2119   }
2401 06 May 14 olle 2120
2401 06 May 14 olle 2121
2401 06 May 14 olle 2122   private class LabEnvironmentDayData
2401 06 May 14 olle 2123   implements Comparable<LabEnvironmentDayData>
2401 06 May 14 olle 2124   {
2401 06 May 14 olle 2125     private final int numberOfDecimals = 2;
2401 06 May 14 olle 2126     private Date date;
2401 06 May 14 olle 2127     private double temperatureMin;
2401 06 May 14 olle 2128     private double temperatureMax;
2401 06 May 14 olle 2129     private double temperatureMean;
2401 06 May 14 olle 2130     private double humidityMin;
2401 06 May 14 olle 2131     private double humidityMax;
2401 06 May 14 olle 2132     private double humidityMean;
2401 06 May 14 olle 2133   
2401 06 May 14 olle 2134     public Date getDate()
2401 06 May 14 olle 2135     {
2401 06 May 14 olle 2136       return this.date;
2401 06 May 14 olle 2137     }
2401 06 May 14 olle 2138     
2401 06 May 14 olle 2139     public double getTemperatureMin()
2401 06 May 14 olle 2140     {
2401 06 May 14 olle 2141       return this.temperatureMin;
2401 06 May 14 olle 2142     }
2401 06 May 14 olle 2143     
2401 06 May 14 olle 2144     public double getTemperatureMax()
2401 06 May 14 olle 2145     {
2401 06 May 14 olle 2146       return this.temperatureMax;
2401 06 May 14 olle 2147     }
2401 06 May 14 olle 2148     
2401 06 May 14 olle 2149     public double getTemperatureMean()
2401 06 May 14 olle 2150     {
2401 06 May 14 olle 2151       return this.temperatureMean;
2401 06 May 14 olle 2152     }
2401 06 May 14 olle 2153     
2401 06 May 14 olle 2154     public double getHumidityMin()
2401 06 May 14 olle 2155     {
2401 06 May 14 olle 2156       return this.humidityMin;
2401 06 May 14 olle 2157     }
2401 06 May 14 olle 2158     
2401 06 May 14 olle 2159     public double getHumidityMax()
2401 06 May 14 olle 2160     {
2401 06 May 14 olle 2161       return this.humidityMax;
2401 06 May 14 olle 2162     }
2401 06 May 14 olle 2163     
2401 06 May 14 olle 2164     public double getHumidityMean()
2401 06 May 14 olle 2165     {
2401 06 May 14 olle 2166       return this.humidityMean;
2401 06 May 14 olle 2167     }
2401 06 May 14 olle 2168     
2401 06 May 14 olle 2169     public LabEnvironmentDayData(Date date, double temperatureMin, double temperatureMax, double temperatureMean, double humidityMin, double humidityMax, double humidityMean)
2401 06 May 14 olle 2170     {
2401 06 May 14 olle 2171       this.date = date;
2401 06 May 14 olle 2172       this.temperatureMin = temperatureMin;
2401 06 May 14 olle 2173       this.temperatureMax = temperatureMax;
2401 06 May 14 olle 2174       this.temperatureMean = temperatureMean;
2401 06 May 14 olle 2175       this.humidityMin = humidityMin;
2401 06 May 14 olle 2176       this.humidityMax = humidityMax;
2401 06 May 14 olle 2177       this.humidityMean = humidityMean;
2401 06 May 14 olle 2178     }
2401 06 May 14 olle 2179   
2401 06 May 14 olle 2180     @Override
2401 06 May 14 olle 2181     public String toString()
2401 06 May 14 olle 2182     {
2401 06 May 14 olle 2183       // Get variable value strings from variable values
2401 06 May 14 olle 2184       DateFormatter dateFormat = new DateFormatter("yyyy-MM-dd HH:mm:ss");
2401 06 May 14 olle 2185       String dateStr = dateFormat.format(date);
2401 06 May 14 olle 2186       String temperatureMinStr = Values.formatNumber((float) temperatureMin, numberOfDecimals);
2401 06 May 14 olle 2187       String temperatureMeanStr = Values.formatNumber((float) temperatureMean, numberOfDecimals);
2401 06 May 14 olle 2188       String temperatureMaxStr = Values.formatNumber((float) temperatureMax, numberOfDecimals);
2401 06 May 14 olle 2189       String humidityMinStr = Values.formatNumber((float) humidityMin, numberOfDecimals);
2401 06 May 14 olle 2190       String humidityMeanStr = Values.formatNumber((float) humidityMean, numberOfDecimals);
2401 06 May 14 olle 2191       String humidityMaxStr = Values.formatNumber((float) humidityMax, numberOfDecimals);
2401 06 May 14 olle 2192       return dateStr + "\t" + temperatureMinStr + temperatureMeanStr + temperatureMaxStr + "\t" + humidityMinStr + "\t" + humidityMeanStr + "\t" + humidityMaxStr;
2401 06 May 14 olle 2193     }
2401 06 May 14 olle 2194
2401 06 May 14 olle 2195     @Override
2401 06 May 14 olle 2196     public int hashCode() 
2401 06 May 14 olle 2197     {
2401 06 May 14 olle 2198       return date.hashCode();
2401 06 May 14 olle 2199     }
2401 06 May 14 olle 2200
2401 06 May 14 olle 2201     @Override
2401 06 May 14 olle 2202     public boolean equals(Object obj) 
2401 06 May 14 olle 2203     {
2401 06 May 14 olle 2204       if (obj == null) return false;
2401 06 May 14 olle 2205       if (this == obj) return true;
2401 06 May 14 olle 2206     
2401 06 May 14 olle 2207       if (obj.getClass() != this.getClass()) return false;
2401 06 May 14 olle 2208       LabEnvironmentDayData o = (LabEnvironmentDayData)obj;
2401 06 May 14 olle 2209       return EqualsHelper.equals(this.date, o.date) && 
2401 06 May 14 olle 2210           EqualsHelper.equals(this.temperatureMin, o.temperatureMin) &&
2401 06 May 14 olle 2211           EqualsHelper.equals(this.temperatureMean, o.temperatureMean) &&
2401 06 May 14 olle 2212           EqualsHelper.equals(this.temperatureMax, o.temperatureMax) &&
2401 06 May 14 olle 2213           EqualsHelper.equals(this.humidityMin, o.humidityMin) &&
2401 06 May 14 olle 2214           EqualsHelper.equals(this.humidityMean, o.humidityMean) &&
2401 06 May 14 olle 2215           EqualsHelper.equals(this.humidityMax, o.humidityMax);
2401 06 May 14 olle 2216     }
2401 06 May 14 olle 2217
2401 06 May 14 olle 2218     @Override
2401 06 May 14 olle 2219     public int compareTo(LabEnvironmentDayData o)
2401 06 May 14 olle 2220     {
2401 06 May 14 olle 2221       int result = LabEnv.nullSafeCompare(this.date, o.date);
2401 06 May 14 olle 2222       if (result == 0)
2401 06 May 14 olle 2223       {
2401 06 May 14 olle 2224         result =  LabEnv.nullSafeCompare(this.temperatureMin, o.temperatureMin);
2401 06 May 14 olle 2225         if (result == 0)
2401 06 May 14 olle 2226         {
2401 06 May 14 olle 2227           result =  LabEnv.nullSafeCompare(this.temperatureMean, o.temperatureMean);
2401 06 May 14 olle 2228           if (result == 0)
2401 06 May 14 olle 2229           {
2401 06 May 14 olle 2230             result =  LabEnv.nullSafeCompare(this.temperatureMax, o.temperatureMax);
2401 06 May 14 olle 2231             if (result == 0)
2401 06 May 14 olle 2232             {
2401 06 May 14 olle 2233               result = LabEnv.nullSafeCompare(this.humidityMin, o.humidityMin);
2401 06 May 14 olle 2234               if (result == 0)
2401 06 May 14 olle 2235               {
2401 06 May 14 olle 2236                 result = LabEnv.nullSafeCompare(this.humidityMean, o.humidityMean);
2401 06 May 14 olle 2237                 if (result == 0)
2401 06 May 14 olle 2238                 {
2401 06 May 14 olle 2239                   result = LabEnv.nullSafeCompare(this.humidityMax, o.humidityMax);
2401 06 May 14 olle 2240                 }
2401 06 May 14 olle 2241               }
2401 06 May 14 olle 2242             }
2401 06 May 14 olle 2243           }
2401 06 May 14 olle 2244         }
2401 06 May 14 olle 2245       }
2401 06 May 14 olle 2246       return result;
2401 06 May 14 olle 2247     }
2401 06 May 14 olle 2248   }
2401 06 May 14 olle 2249 }