1 | package dk.deepthought.sidious.greenhouse; |
2 | |
3 | import java.util.ArrayList; |
4 | import java.util.Collection; |
5 | |
6 | import net.jcip.annotations.Immutable; |
7 | |
8 | import org.apache.commons.logging.Log; |
9 | import org.apache.commons.logging.LogFactory; |
10 | |
11 | import dk.deepthought.sidious.supportsystem.Adjustable; |
12 | import dk.deepthought.sidious.supportsystem.State; |
13 | import dk.deepthought.sidious.supportsystem.SuperLinkID; |
14 | import dk.deepthought.sidious.supportsystem.SystemSettings; |
15 | |
16 | /** |
17 | * This class implements the abstraction of a setpoint of the screens. |
18 | * |
19 | * @author Deepthought |
20 | * |
21 | */ |
22 | @Immutable |
23 | public class ScreenSetPoint implements Adjustable { |
24 | |
25 | /** |
26 | * Logger for this class. |
27 | */ |
28 | private static final Log logger = LogFactory.getLog(ScreenSetPoint.class); |
29 | |
30 | |
31 | /** |
32 | * The setting of this setpoint. |
33 | */ |
34 | private final double setting; |
35 | |
36 | /** |
37 | * The id of the irradiance sensor. |
38 | */ |
39 | private final SuperLinkID irradianceID; |
40 | |
41 | /** |
42 | * Internal enum to describe possible adjustments. |
43 | */ |
44 | private enum ScreenStep { |
45 | UP(1f), DOWN(-1f); // Percent up and down |
46 | |
47 | private double increment; |
48 | |
49 | ScreenStep(double increment) { |
50 | this.increment = increment; |
51 | } |
52 | |
53 | public double getIncrement() { |
54 | return increment; |
55 | } |
56 | } |
57 | |
58 | /** |
59 | * Creates a new <code>ScreenSetPoint</code> with the specified setting. |
60 | * <p> |
61 | * Input parameters should be between 0 and 100 percent. Parameters outside |
62 | * this will be rounded to nearest limit. |
63 | * |
64 | * @param setting |
65 | * the setting |
66 | */ |
67 | public ScreenSetPoint(double setting) { |
68 | irradianceID = SystemSettings.getIrradianceID(); |
69 | if (setting > 100) { |
70 | setting = 100; |
71 | } |
72 | if (setting < 0) { |
73 | setting = 0; |
74 | } |
75 | this.setting = setting; |
76 | } |
77 | |
78 | /* |
79 | * (non-Javadoc) |
80 | * |
81 | * @see dk.deepthought.sidious.supportsystem.Adjustable#consequence(dk.deepthought.sidious.supportsystem.State) |
82 | */ |
83 | public State consequence(State state) { |
84 | if (!(state instanceof ClimaticState)) { |
85 | String fail = "Input state must be a climatic state. - state=" |
86 | + state; |
87 | logger.error(fail); |
88 | throw new IllegalArgumentException(fail); |
89 | } |
90 | ClimaticState cs = (ClimaticState) state; |
91 | Collection<SensorInput> sensors = cs.getSensors(); |
92 | Collection<SensorInput> newSensors = new ArrayList<SensorInput>(); |
93 | for (SensorInput input : sensors) { |
94 | if (input.getID().equals(irradianceID)) { |
95 | double newValue = input.getValue() * (1 - (setting / 100)); |
96 | newSensors.add(input.newInstanceWithNewValue(newValue)); |
97 | } else { |
98 | newSensors.add(input); |
99 | } |
100 | } |
101 | return new ClimaticState(newSensors); |
102 | } |
103 | |
104 | /* |
105 | * (non-Javadoc) |
106 | * |
107 | * @see dk.deepthought.sidious.supportsystem.Adjustable#possibleAdjustments() |
108 | */ |
109 | public Collection<Adjustable> possibleAdjustments() { |
110 | Collection<Adjustable> setpoints = new ArrayList<Adjustable>(); |
111 | for (ScreenStep possibleDirection : ScreenStep.values()) { |
112 | double result = setting + possibleDirection.getIncrement(); |
113 | assert result != Float.MAX_VALUE : "result exceeded Float.MAX_VALUE"; |
114 | int min = 0; // Minimum value (windows closed) |
115 | int max = 100; // Maximum value (windows opened up all the way) |
116 | if (result < min) { |
117 | result = min; |
118 | if (setting != min) { |
119 | setpoints.add(new ScreenSetPoint(result)); |
120 | } |
121 | } else if (result > max) { |
122 | result = max; |
123 | if (setting != max) { |
124 | setpoints.add(new ScreenSetPoint(result)); |
125 | } |
126 | } else { |
127 | setpoints.add(new ScreenSetPoint(result)); |
128 | } |
129 | } |
130 | return setpoints; |
131 | } |
132 | |
133 | /* |
134 | * (non-Javadoc) |
135 | * |
136 | * @see dk.deepthought.sidious.supportsystem.Adjustable#getID() |
137 | */ |
138 | public SuperLinkID getID() { |
139 | return SystemSettings.getScreenSetPointID(); |
140 | } |
141 | |
142 | /* |
143 | * (non-Javadoc) |
144 | * |
145 | * @see dk.deepthought.sidious.supportsystem.Adjustable#getSetting() |
146 | */ |
147 | public double getSetting() { |
148 | return setting; |
149 | } |
150 | |
151 | /* (non-Javadoc) |
152 | * @see java.lang.Object#hashCode() |
153 | */ |
154 | @Override |
155 | public int hashCode() { |
156 | final int PRIME = 31; |
157 | int result = 1; |
158 | long temp; |
159 | temp = Double.doubleToLongBits(setting); |
160 | result = PRIME * result + (int) (temp ^ (temp >>> 32)); |
161 | return result; |
162 | } |
163 | |
164 | /* (non-Javadoc) |
165 | * @see java.lang.Object#equals(java.lang.Object) |
166 | */ |
167 | @Override |
168 | public boolean equals(Object obj) { |
169 | if (this == obj) |
170 | return true; |
171 | if (obj == null) |
172 | return false; |
173 | if (getClass() != obj.getClass()) |
174 | return false; |
175 | final ScreenSetPoint other = (ScreenSetPoint) obj; |
176 | if (Double.doubleToLongBits(setting) != Double.doubleToLongBits(other.setting)) |
177 | return false; |
178 | return true; |
179 | } |
180 | |
181 | /* |
182 | * (non-Javadoc) |
183 | * |
184 | * @see java.lang.Object#toString() |
185 | */ |
186 | @Override |
187 | public String toString() { |
188 | return getClass().getSimpleName() + "[setting=" + setting + "]"; |
189 | } |
190 | } |