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 represents the CO2 setpoint of the greenhouse.
018  
019  @author Deepthought
020  
021  */
022 @Immutable
023 public class CO2SetPoint implements Adjustable {
024     /**
025      * Logger for this class
026      */
027     private static final Log logger = LogFactory.getLog(CO2SetPoint.class);
028 
029     /**
030      * The setting of this CO2SetPoint.
031      */
032     private final double setting;
033 
034     /**
035      * The id of the CO2 setpoint.
036      */
037     private final SuperLinkID co2ID;
038 
039     /**
040      * Expected increase per minute.
041      */
042     private static final double INCREASE_PER_MIN = 10;
043 
044     /**
045      * Expected decrease per minute.
046      */
047     private static final double DECREASE_PER_MIN = -4;
048 
049     /**
050      * Internal enum to describe possible adjustments.
051      */
052     private enum CO2Step {
053         UP(100), DOWN(-100);
054 
055         private double increment;
056 
057         CO2Step(double increment) {
058             this.increment = increment;
059         }
060 
061         public double getIncrement() {
062             return increment;
063         }
064     }
065 
066     /**
067      * Constructor.
068      
069      @param setting
070      *            the setting of this CO2SetPoint
071      */
072     public CO2SetPoint(double setting) {
073         this.co2ID = SystemSettings.getCO2ID();
074         this.setting = setting;
075     }
076 
077     /*
078      * (non-Javadoc)
079      
080      * @see dk.deepthought.sidious.supportsystem.Adjustable#consequence(dk.deepthought.sidious.supportsystem.State)
081      */
082     public State consequence(State state) {
083         if (!(state instanceof ClimaticState)) {
084             String fail = "Input state must be a climatic state. - state="
085                     + state;
086             logger.error(fail);
087             throw new IllegalArgumentException(fail);
088         }
089         int timestep = SystemSettings.getTimestep();
090         Collection<SensorInput> inputSensors = ((ClimaticStatestate)
091                 .getSensors();
092         Collection<SensorInput> newSensors = new ArrayList<SensorInput>();
093         for (SensorInput input : inputSensors) {
094             if (input.getID().equals(co2ID)) {
095                 double sensorValue = input.getValue();
096                 double delta = setting - sensorValue;
097                 double newValue = 0;
098                 if (delta < 0) {
099                     double decreaseFactor = DECREASE_PER_MIN * timestep;
100                     if (delta >= decreaseFactor) {
101                         newValue = setting;
102                     else {
103                         newValue = decreaseFactor + sensorValue;
104                     }
105                 else {
106                     double increaseFactor = INCREASE_PER_MIN * timestep;
107                     if (delta <= increaseFactor) {
108                         newValue = setting;
109                     else {
110                         newValue = increaseFactor + sensorValue;
111                     }
112                 }
113                 newSensors.add(input.newInstanceWithNewValue(newValue));
114             else {
115                 newSensors.add(input);
116             }
117         }
118         return new ClimaticState(newSensors);
119     }
120 
121     /*
122      * (non-Javadoc)
123      
124      * @see dk.deepthought.sidious.supportsystem.Adjustable#possibleAdjustments()
125      */
126     public Collection<Adjustable> possibleAdjustments() {
127         if (logger.isDebugEnabled()) {
128             logger.debug("possibleAdjustments() - start");
129         }
130 
131         Collection<Adjustable> setpoints = new ArrayList<Adjustable>();
132         for (CO2Step possibleDirection : CO2Step.values()) {
133             double result = setting + possibleDirection.getIncrement();
134             assert result != Float.MAX_VALUE : "result exceeded Float.MAX_VALUE";
135             setpoints.add(new CO2SetPoint(result));
136         }
137 
138         if (logger.isDebugEnabled()) {
139             logger.debug("possibleAdjustments() - end - return value="
140                     + setpoints);
141         }
142         return setpoints;
143     }
144 
145     /*
146      * (non-Javadoc)
147      
148      * @see dk.deepthought.sidious.supportsystem.Adjustable#getID()
149      */
150     public SuperLinkID getID() {
151         return SystemSettings.getCO2SetPointID();
152     }
153 
154     /*
155      * (non-Javadoc)
156      
157      * @see dk.deepthought.sidious.supportsystem.Adjustable#getSetting()
158      */
159     public double getSetting() {
160         return setting;
161     }
162 
163     
164     
165     /* (non-Javadoc)
166      * @see java.lang.Object#hashCode()
167      */
168     @Override
169     public int hashCode() {
170         final int PRIME = 31;
171         int result = 1;
172         long temp;
173         temp = Double.doubleToLongBits(setting);
174         result = PRIME * result + (int) (temp ^ (temp >>> 32));
175         return result;
176     }
177 
178     /* (non-Javadoc)
179      * @see java.lang.Object#equals(java.lang.Object)
180      */
181     @Override
182     public boolean equals(Object obj) {
183         if (this == obj)
184             return true;
185         if (obj == null)
186             return false;
187         if (getClass() != obj.getClass())
188             return false;
189         final CO2SetPoint other = (CO2SetPointobj;
190         if (Double.doubleToLongBits(setting!= Double.doubleToLongBits(other.setting))
191             return false;
192         return true;
193     }
194 
195     @Override
196     public String toString() {
197         return getClass().getSimpleName() "[setting=" + setting + "]";
198     }
199 }