001 package dk.deepthought.sidious.rules;
002 
003 import java.util.ArrayList;
004 import java.util.Collection;
005 import java.util.Properties;
006 
007 import org.apache.commons.logging.Log;
008 import org.apache.commons.logging.LogFactory;
009 
010 import dk.deepthought.sidious.goalhandler.Goal;
011 import dk.deepthought.sidious.greenhouse.ClimaticState;
012 import dk.deepthought.sidious.greenhouse.SensorInput;
013 import dk.deepthought.sidious.services.ServiceEngine;
014 import dk.deepthought.sidious.supportsystem.State;
015 import dk.deepthought.sidious.supportsystem.Step;
016 import dk.deepthought.sidious.supportsystem.SuperLinkID;
017 import dk.deepthought.sidious.util.RuleProperty;
018 
019 /**
020  * This class represents the rule to facilitate a morning drop.
021  <p>
022  * This rule will dictate a 5 to 6 degrees Celsius drop in temperature, starting
023  * approx. 30 min before sunrise, and maintaining this drop for two hours.
024  
025  @author Deepthought
026  
027  */
028 public class MorningDropRule extends Rule {
029     /**
030      * Logger for this class
031      */
032     private static final Log logger = LogFactory.getLog(MorningDropRule.class);
033 
034     /**
035      * The RuleProperty of this class
036      */
037     private static RuleProperty ruleProperty;
038 
039     /**
040      * The duration of the temperature drop.
041      */
042     private final int dropDuration;
043 
044     /**
045      * Drop initialization time, in minutes before sunrise.
046      */
047     private final int minutesBeforeSunrise;
048 
049     /**
050      * The target degrees of the drop.
051      */
052     private final double dropTarget;
053 
054     /**
055      * The ID of the time sensor this Rule depends on.
056      */
057     private final SuperLinkID timeSensorID;
058 
059     /**
060      * The ID of the temperature sensor this Rule depends on.
061      */
062     private final SuperLinkID temperatureSensorID;
063 
064     /**
065      * The time of sunrise, represented in min after midnight.
066      <p>
067      * XXX Should be retrieved from an external calendar/forecast.
068      */
069     private static final int sunrise = 360// 6 o'clock
070 
071     /**
072      * Constructor.
073      
074      @param parentID
075      *            the id of the parent <code>PlanRequester</code>
076      */
077     public MorningDropRule(final SuperLinkID parentID) {
078         if (parentID == null) {
079             logger.error("MorningDropRule(SuperLinkID parentID=null) "
080                     "- null not valid input");
081             throw new IllegalArgumentException("null not valid ID");
082         }
083         if (ruleProperty == null) {
084             ruleProperty = new RuleProperty(this.getClass().getSimpleName());
085         }
086         timeSensorID = ruleProperty.getID("time_sensor_id");
087         temperatureSensorID = ruleProperty.getID("temperature_sensor_id");
088         dropTarget = ruleProperty.getFloat("dropTarget"14f);
089         dropDuration = ruleProperty.getInt("dropDuration"120);
090         minutesBeforeSunrise = ruleProperty.getInt("minutesBeforeSunrise"30);
091         setParentID(parentID);
092     }
093 
094     /**
095      * Static factory for constructing a MorningDropRule with the specified
096      * properties.
097      
098      @param parentID
099      *            the id of the parent <code>PlanRequester</code>
100      @param properties
101      *            the properties
102      @return a new MorningDropRule from the given properties
103      */
104     public static MorningDropRule constructMorningDropRule(
105             final SuperLinkID parentID, Properties properties) {
106         ruleProperty = new RuleProperty(properties);
107         return new MorningDropRule(parentID);
108     }
109 
110     /*
111      * (non-Javadoc)
112      
113      * @see dk.deepthought.sidious.rules.Rule#desire(dk.deepthought.sidious.supportsystem.State,
114      *      dk.deepthought.sidious.supportsystem.State)
115      */
116     public double desire(State currentState, State newState, Step step) {
117         int newTime = (intgetSensorValue(newState, timeSensorID);
118         double newTemperature = getSensorValue(newState, temperatureSensorID);
119         if (newTime > sunrise - minutesBeforeSunrise
120                 && newTime < sunrise + (dropDuration - minutesBeforeSunrise)) {
121             double desireValue = ((newTemperature - dropTarget/ dropTarget);
122             if (desireValue > 1) {
123                 desireValue = 1;
124             else if (desireValue < 0) {
125                 desireValue = 0;
126             }
127             return desireValue;
128         }
129         return 0;
130     }
131 
132     /*
133      * (non-Javadoc)
134      
135      * @see dk.deepthought.sidious.rules.Rule#getGoals()
136      */
137     public Collection<Goal> getGoals() {
138         SensorInput temperatureGoal = new SensorInput(temperatureSensorID,
139                 dropTarget);
140         ArrayList<SensorInput> sensors = new ArrayList<SensorInput>();
141         sensors.add(temperatureGoal);
142         ClimaticState goalClima = new ClimaticState(sensors);
143         Goal goal = new Goal(goalClima, desire(goalClima, ServiceEngine
144                 .getCurrentState()null), getParentID());
145         ArrayList<Goal> goals = new ArrayList<Goal>();
146         goals.add(goal);
147         return goals;
148     }
149 
150 }