EMMA Coverage Report (generated Tue May 01 18:46:53 CEST 2007)
[all classes][dk.deepthought.sidious.rules]

COVERAGE SUMMARY FOR SOURCE FILE [PhotosynthesisRule.java]

nameclass, %method, %block, %line, %
PhotosynthesisRule.java100% (1/1)75%  (6/8)70%  (327/469)84%  (66/79)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class PhotosynthesisRule100% (1/1)75%  (6/8)70%  (327/469)84%  (66/79)
calculateDesire (State, Step): double 0%   (0/1)0%   (0/53)0%   (0/7)
getCalculationCounter (): long 0%   (0/1)0%   (0/2)0%   (0/1)
desire (State, State, Step): double 100% (1/1)58%  (58/100)89%  (16/18)
calculateMax (double, double, ArrayList): double 100% (1/1)59%  (60/102)87%  (13/15)
getGoals (): Collection 100% (1/1)98%  (141/144)95%  (20/21)
<static initializer> 100% (1/1)100% (6/6)100% (2/2)
PhotosynthesisRule (SuperLinkID): void 100% (1/1)100% (18/18)100% (6/6)
calculateRate (State): double 100% (1/1)100% (44/44)100% (9/9)

1package dk.deepthought.sidious.rules;
2 
3import java.util.ArrayList;
4import java.util.Arrays;
5import java.util.Collection;
6import java.util.List;
7 
8import org.apache.commons.logging.Log;
9import org.apache.commons.logging.LogFactory;
10 
11import dk.deepthought.sidious.goalhandler.Goal;
12import dk.deepthought.sidious.greenhouse.ClimaticState;
13import dk.deepthought.sidious.greenhouse.LeafPhotosynthesisModel;
14import dk.deepthought.sidious.greenhouse.ScreenSetPoint;
15import dk.deepthought.sidious.greenhouse.SensorInput;
16import dk.deepthought.sidious.services.ServiceEngine;
17import dk.deepthought.sidious.supportsystem.Adjustable;
18import dk.deepthought.sidious.supportsystem.State;
19import dk.deepthought.sidious.supportsystem.Step;
20import dk.deepthought.sidious.supportsystem.SuperLinkID;
21import dk.deepthought.sidious.supportsystem.SystemSettings;
22import dk.deepthought.sidious.util.RuleProperty;
23 
24/**
25 * Class represents a photosynthesis rule.
26 * <p>
27 * It is responsible for maintaining a desired photosynthesis rate.
28 * 
29 * @author Deepthought
30 * 
31 */
32public class PhotosynthesisRule extends Rule {
33        /**
34         * Logger for this class
35         */
36        private static final Log logger = LogFactory
37                        .getLog(PhotosynthesisRule.class);
38 
39        /**
40         * The RuleProperty of this class
41         */
42        private static RuleProperty ruleProperty;
43        
44        /**
45         * Value is defaulted in the calculate method.
46         */
47        private static final double GLASS_FACTOR = Double.NaN;
48 
49        /**
50         * Value is defaulted in the calculate method.
51         */
52        private static final double SHADE_FACTOR = Double.NaN;
53 
54        // TODO extract into rule property file.
55        static final int T_START = 18;
56 
57        // TODO extract into rule property file.
58        static final int CO2_START = 300;
59 
60        // TODO extract into rule property file.
61        static final int CO2_INCREMENT = 100;
62 
63        // TODO extract into rule property file.
64        private static final int T_END = 36;
65 
66        // TODO extract into rule property file.
67        private static final int CO2_END = 1600;
68 
69        // TODO extract into rule property file.
70        private static final double DESIRED_RATE = 0.8;
71 
72        /**
73         * Value sets the importance of this rule.
74         * TODO extract into rule property file 
75         */
76        private double tweakValue = 1;
77        
78        /**
79         * Used to keep track of the amount of model calculations done by this
80         */
81        private static long calculationCounter = 0; 
82 
83 
84        public PhotosynthesisRule(final SuperLinkID parentID) {
85                if (ruleProperty == null) {
86                        ruleProperty = new RuleProperty(this.getClass().getSimpleName());
87                }
88                setParentID(parentID);
89        }
90 
91        /*
92         * (non-Javadoc)
93         * 
94         * @see dk.deepthought.sidious.rules.Rule#desire(dk.deepthought.sidious.supportsystem.State,
95         *      dk.deepthought.sidious.supportsystem.State, dk.deepthought.sidious.supportsystem.Step)
96         */
97        public double desire(State currentState, State newState, Step step) {
98                if (logger.isDebugEnabled()) {
99                        logger.debug("desire(State currentState=" + currentState
100                                        + ", State newState=" + newState + ", Step step=" + step
101                                        + ") - start");
102                }
103                double desire = 0;
104                double oldRate = calculateRate(currentState);
105                double newRate = calculateRate(newState);
106                double deltaRate = oldRate - newRate;
107                if (deltaRate > 0) {
108                        desire += deltaRate;
109                }
110                desire += (DESIRED_RATE - newRate);
111 
112                if (newRate > DESIRED_RATE) {
113                        desire = Math.abs(desire);
114                }
115                if (Math.abs(newRate - DESIRED_RATE) < 0.001) {
116                        desire = 0;
117                }
118                if (desire > 1) {
119                        desire = 1;
120                }
121                if (logger.isDebugEnabled()) {
122                        logger.debug("desire(State currentState=" + currentState
123                                        + ", State newState=" + newState + ", Step step=" + step
124                                        + ") - end - return value=" + desire);
125                }
126                return desire;
127        }
128 
129        /**
130         * Returns the desire related to <code>DESIRED_RATE</code>.
131         * 
132         * @param state
133         *            the state containing needed sensors
134         * @param step
135         *            the step containing needed adjustables
136         * @return the calculated desire
137         */
138        double calculateDesire(State state, Step step) {
139                if (logger.isDebugEnabled()) {
140                        logger.debug("calculateDesire(State state=" + state
141                                        + ", Step step=" + step + ") - start");
142                }
143                double rate = calculateRate(state);
144                
145                double returndouble = Math.abs(rate - DESIRED_RATE) / DESIRED_RATE;
146                // Ny Rate formel + distance mellem goal og new state (evt. manhattan).
147                // dist(new, goal) / dist(source, goal)
148                if (logger.isDebugEnabled()) {
149                        logger.debug("calculateDesire(State state=" + state
150                                        + ", Step step=" + step + ") - end - return value="
151                                        + returndouble);
152                }
153                return returndouble;
154        }
155 
156        /**
157         * Calculates the photosynthesis rate for a given state.
158         * @param state the state
159         * @return the rate of photosynthesis
160         */
161        private double calculateRate(State state) {
162                //Retrieve necessary state 
163                double shade = 0;
164                double sun = getSensorValue(state, SystemSettings.getIrradianceID());
165                double temperature = getSensorValue(state, SystemSettings
166                                .getTemperatureID());
167                double co2 = getSensorValue(state, SystemSettings.getCO2ID());
168                LeafPhotosynthesisModel model = new LeafPhotosynthesisModel();
169                //Calculate
170                double currentPhotosynthesis = model.calculate(temperature, co2, sun,
171                                GLASS_FACTOR, SHADE_FACTOR, shade);
172                double maxPhotosynthesis = calculateMax(shade, sun,
173                                new ArrayList<ArrayList<Double>>());
174                double rate = currentPhotosynthesis / maxPhotosynthesis;
175                return rate;
176        }
177 
178        /**
179         * Method calculates the maximum photosynthesis level. All calculated values
180         * are stored in the input matrix.
181         * <p>
182         * The format of the matrix is:
183         * 
184         * <pre>
185         * Rows = temperature interval
186         * Columns = CO2 level
187         * 
188         * [t1=[co2_level_1, co2_level_2, co2_level_3, ... , co2_level_n]]
189         * [t2=[co2_level_1, co2_level_2, co2_level_3, ... , co2_level_n]]
190         * [t3=[co2_level_1, co2_level_2, co2_level_3, ... , co2_level_n]]
191         * ...
192         * [tm=[co2_level_1, co2_level_2, co2_level_3, ... , co2_level_n]]
193         * 
194         * Where: 
195         * CO2_START &lt; n &lt; CO2_END, and 
196         *   T_START &lt; m &lt; T_END 
197         * 
198         * Increments:
199         * Temperature increment = 1
200         * CO2 increment = CO2_INCREMENT
201         * 
202         * </pre>
203         * 
204         * @param shade
205         *            screen setpoint value
206         * @param sun
207         *            irradiance level
208         * @param matrix
209         *            the matrix to be filled with all calculated values
210         * @return maximum photosynthesis value
211         */
212        double calculateMax(double shade, double sun,
213                        ArrayList<ArrayList<Double>> matrix) {
214                if (logger.isDebugEnabled()) {
215                        logger.debug("calculateMax(double shade=" + shade + ", double sun="
216                                        + sun + ", ArrayList<ArrayList<Double>> matrix=" + matrix
217                                        + ") - start");
218                }
219 
220                LeafPhotosynthesisModel model = new LeafPhotosynthesisModel();
221                double max = 0;
222                for (int temperature = T_START; temperature < T_END; temperature++) {
223                        ArrayList<Double> inner = new ArrayList<Double>();
224                        for (int co2 = CO2_START; co2 < CO2_END; co2 += CO2_INCREMENT) {
225                                // updating the counter
226                                calculationCounter++;
227                                double val = model.calculate(temperature, co2, sun,
228                                                GLASS_FACTOR, SHADE_FACTOR, shade);
229                                inner.add(val);
230                                max = Math.max(val, max);
231                        }
232                        matrix.add(inner);
233                }
234 
235                if (logger.isDebugEnabled()) {
236                        logger.debug("calculateMax(double shade=" + shade + ", double sun="
237                                        + sun + ", ArrayList<ArrayList<Double>> matrix=" + matrix
238                                        + ") - end - return value=" + max);
239                }
240                return max;
241        }
242 
243        /*
244         * (non-Javadoc)
245         * 
246         * @see dk.deepthought.sidious.rules.Rule#getGoals()
247         */
248        public Collection<Goal> getGoals() {
249                if (logger.isDebugEnabled()) {
250                        logger.debug("getGoals() - start");
251                }
252                double shade = getAdjustableSettingFromParent(SystemSettings
253                                .getScreenSetPointID());
254                double sun = ServiceEngine.getSensorValue(SystemSettings
255                                .getIrradianceID());
256                ArrayList<ArrayList<Double>> matrix = new ArrayList<ArrayList<Double>>();
257                double max = calculateMax(shade, sun, matrix);
258                List<Goal> goals = new ArrayList<Goal>();
259                for (int i = 0; i < matrix.size(); i++) {
260                        ArrayList<Double> inner = matrix.get(i);
261                        for (int j = 0; j < inner.size(); j++) {
262                                double photosynthesis = inner.get(j);
263                                if (photosynthesis / max >= DESIRED_RATE) {
264                                        SensorInput temperatureSensor = new SensorInput(
265                                                        SystemSettings.getTemperatureID(), i + T_START);
266                                        SensorInput co2Sensor = new SensorInput(SystemSettings
267                                                        .getCO2ID(), (j * CO2_INCREMENT) + CO2_START);
268                                        SensorInput sunSensor = new SensorInput(SystemSettings
269                                                        .getIrradianceID(), sun);
270 
271                                        State goalState = new ClimaticState(Arrays.asList(
272                                                        temperatureSensor, sunSensor, co2Sensor));
273                                        Adjustable screenSetPoint = new ScreenSetPoint(shade);
274                                        Step step = new Step(Arrays.asList(screenSetPoint));
275                                        double desire = desire(ServiceEngine.getCurrentState(),
276                                                        goalState, step);
277                                        goals.add(new Goal(goalState, tweakValue * (DESIRED_RATE-desire), getParentID()));
278                                }
279                        }
280                }
281                return goals;
282        }
283        
284        /**
285         * Gets the amount of calculations made by this.
286         * @return the calculationCounter
287         */
288        public static long getCalculationCounter() {
289                return calculationCounter;
290        }
291        
292        
293}

[all classes][dk.deepthought.sidious.rules]
EMMA 2.0.5312 (C) Vladimir Roubtsov