001 package dk.deepthought.sidious.greenhouse;
002 
003 import java.util.ArrayList;
004 import java.util.Collection;
005 
006 import net.jcip.annotations.Immutable;
007 
008 import org.apache.commons.logging.Log;
009 import org.apache.commons.logging.LogFactory;
010 
011 import dk.deepthought.sidious.supportsystem.Adjustable;
012 import dk.deepthought.sidious.supportsystem.State;
013 import dk.deepthought.sidious.supportsystem.SuperLinkID;
014 import dk.deepthought.sidious.supportsystem.SystemSettings;
015 
016 /**
017  * This class implements the abstraction of a setpoint of the heater.
018  
019  @author Deepthought
020  
021  */
022 @Immutable
023 public final class HeaterSetPoint implements Adjustable {
024 
025     private static final Log logger = LogFactory.getLog(HeaterSetPoint.class);
026 
027     /**
028      * The setting of this setpoint.
029      */
030     private final double setting;
031 
032     /**
033      * Id of the temperature sensor.
034      */
035     private final SuperLinkID temperatureID;
036 
037     /**
038      * Id of the humidity sensor.
039      */
040     private final SuperLinkID humidityID;
041 
042     private static final double FACTOR_PER_MINUTE = 0.1;
043 
044     /**
045      * Internal enum to describe possible adjustments.
046      */
047     private enum HeaterStep {
048         UP(1f), DOWN(-1f);
049 
050         private double increment;
051 
052         HeaterStep(double increment) {
053             this.increment = increment;
054         }
055 
056         public double getIncrement() {
057             return increment;
058         }
059     }
060 
061     /**
062      * Creates a new <code>HeaterSetPoint</code> with the specified setting.
063      
064      @param setting
065      *            the setting
066      */
067     public HeaterSetPoint(final double setting) {
068         humidityID = SystemSettings.getHumidityID();
069         temperatureID = SystemSettings.getTemperatureID();
070         this.setting = setting;
071     }
072 
073     /*
074      * (non-Javadoc)
075      
076      * @see dk.deepthought.sidious.supportsystem.Adjustable#consequence(dk.deepthought.sidious.supportsystem.State,
077      *      dk.deepthought.sidious.supportsystem.Step)
078      */
079     public State consequence(State state) {
080         if (logger.isDebugEnabled()) {
081             logger.debug("consequence(State state=" + state
082                     ") - start - setting=" + setting);
083         }
084         if (!(state instanceof ClimaticState)) {
085             String fail = "Input state must be a climatic state. - state=" + state;
086             logger.error(fail);
087             throw new IllegalArgumentException(fail);
088         }
089         int timestep = SystemSettings.getTimestep();
090         ClimaticState climaticState = (ClimaticStatestate;
091         Collection<SensorInput> sensors = climaticState.getSensors();
092         Collection<SensorInput> newSensors = new ArrayList<SensorInput>();
093         // When temperature increases, humidity decreases
094         for (SensorInput input : sensors) {
095             if (input.getID().equals(temperatureID)) {
096                 double temperature = input.getValue();
097                 double delta = setting - temperature;
098                 double newValue = temperature + timestep * FACTOR_PER_MINUTE
099                         * delta;
100                 newSensors.add(input.newInstanceWithNewValue(newValue));
101             else if (input.getID().equals(humidityID)) {
102                 double decreaseFactor = decreaseFactor(input.getValue());
103                 newSensors.add(input.newInstanceWithNewValue(decreaseFactor));
104             else {
105                 newSensors.add(input);
106             }
107         }
108         State returnState = new ClimaticState(newSensors);
109         if (logger.isDebugEnabled()) {
110             logger.debug("consequence(State state=" + state
111                     ") - end - return value=" + returnState);
112         }
113         return returnState;
114     }
115 
116     /**
117      * Calculates the humidity decrease factor with respect to the increase in
118      * temperature.
119      
120      @param humidity
121      *            value of humidity
122      @return the decrease factor
123      */
124     private double decreaseFactor(double humidity) {
125         //FIXME WTF?!?
126         //Vi sammenligner humidity med setting af heater?!?
127         double delta = setting - humidity;
128         double factor = -delta * 0.01 + humidity;
129         return factor;
130     }
131 
132     /*
133      * (non-Javadoc)
134      
135      * @see dk.deepthought.sidious.supportsystem.Adjustable#possibleAdjustments()
136      */
137     public Collection<Adjustable> possibleAdjustments() {
138         if (logger.isDebugEnabled()) {
139             logger.debug("possibleAdjustments() - start");
140         }
141 
142         Collection<Adjustable> setpoints = new ArrayList<Adjustable>();
143         for (HeaterStep possibleDirection : HeaterStep.values()) {
144             double result = setting + possibleDirection.getIncrement();
145             assert result != Float.MAX_VALUE : "result exceeded Float.MAX_VALUE";
146             setpoints.add(new HeaterSetPoint(result));
147         }
148         logger.debug(setpoints.size() " possible adjustments created");
149         return setpoints;
150     }
151 
152     /*
153      * (non-Javadoc)
154      
155      * @see dk.deepthought.sidious.supportsystem.Adjustable#getID()
156      */
157     public SuperLinkID getID() {
158         return SystemSettings.getHeaterSetPointID();
159     }
160 
161     /*
162      * (non-Javadoc)
163      
164      * @see dk.deepthought.sidious.supportsystem.Adjustable#getSetting()
165      */
166     public double getSetting() {
167         return setting;
168     }
169 
170     
171     
172     /* (non-Javadoc)
173      * @see java.lang.Object#hashCode()
174      */
175     @Override
176     public int hashCode() {
177         final int PRIME = 31;
178         int result = 1;
179         long temp;
180         temp = Double.doubleToLongBits(setting);
181         result = PRIME * result + (int) (temp ^ (temp >>> 32));
182         return result;
183     }
184 
185     /* (non-Javadoc)
186      * @see java.lang.Object#equals(java.lang.Object)
187      */
188     @Override
189     public boolean equals(Object obj) {
190         if (this == obj)
191             return true;
192         if (obj == null)
193             return false;
194         if (getClass() != obj.getClass())
195             return false;
196         final HeaterSetPoint other = (HeaterSetPointobj;
197         if (Double.doubleToLongBits(setting!= Double.doubleToLongBits(other.setting))
198             return false;
199         return true;
200     }
201 
202     /*
203      * (non-Javadoc)
204      
205      * @see java.lang.Object#toString()
206      */
207     @Override
208     public String toString() {
209         return getClass().getSimpleName() "[setting=" + setting + "]";
210     }
211 
212 }