moving to core/
[debian/openrocket] / core / src / net / sf / openrocket / utils / MotorCompare.java
1 package net.sf.openrocket.utils;
2
3 import java.io.FileInputStream;
4 import java.io.IOException;
5 import java.io.InputStream;
6 import java.util.ArrayList;
7 import java.util.List;
8
9 import net.sf.openrocket.file.motor.GeneralMotorLoader;
10 import net.sf.openrocket.file.motor.MotorLoader;
11 import net.sf.openrocket.motor.Manufacturer;
12 import net.sf.openrocket.motor.Motor;
13 import net.sf.openrocket.motor.ThrustCurveMotor;
14
15 public class MotorCompare {
16         
17         /** Maximum allowed difference in maximum thrust */
18         private static final double MAX_THRUST_MARGIN = 0.30;
19         /** Maximum allowed difference in total impulse */
20         private static final double TOTAL_IMPULSE_MARGIN = 0.20;
21         /** Maximum allowed difference in mass values */
22         private static final double MASS_MARGIN = 0.20;
23         
24         /** Number of time points in thrust curve to compare */
25         private static final int DIVISIONS = 100;
26         /** Maximum difference in thrust for a time point to be considered invalid */
27         private static final double THRUST_MARGIN = 0.20;
28         /** Number of invalid time points allowed */
29         private static final int ALLOWED_INVALID_POINTS = 20;
30         
31         /** Minimum number of thrust curve points allowed (incl. start and end points) */
32         private static final int MIN_POINTS = 7;
33         
34         
35         public static void main(String[] args) throws IOException {
36                 final double maxThrust;
37                 final double maxTime;
38                 int maxDelays;
39                 int maxPoints;
40                 int maxCommentLen;
41                 
42                 double min, max;
43                 double diff;
44                 
45                 int[] goodness;
46                 
47                 boolean bad = false;
48                 List<String> cause = new ArrayList<String>();
49                 
50                 MotorLoader loader = new GeneralMotorLoader();
51                 List<ThrustCurveMotor> motors = new ArrayList<ThrustCurveMotor>();
52                 List<String> files = new ArrayList<String>();
53                 
54                 // Load files
55                 System.out.printf("Files      :");
56                 for (String file : args) {
57                         System.out.printf("\t%s", file);
58                         List<Motor> m = null;
59                         try {
60                                 InputStream stream = new FileInputStream(file);
61                                 m = loader.load(stream, file);
62                                 stream.close();
63                         } catch (IOException e) {
64                                 e.printStackTrace();
65                                 System.out.print("(ERR:" + e.getMessage() + ")");
66                         }
67                         if (m != null) {
68                                 motors.addAll((List) m);
69                                 for (int i = 0; i < m.size(); i++)
70                                         files.add(file);
71                         }
72                 }
73                 System.out.println();
74                 
75                 compare(motors, files);
76         }
77         
78         
79
80
81
82         public static void compare(List<ThrustCurveMotor> motors, List<String> files) {
83                 final double maxThrust;
84                 final double maxTime;
85                 int maxDelays;
86                 int maxPoints;
87                 int maxCommentLen;
88                 
89                 double min, max;
90                 double diff;
91                 
92                 int[] goodness;
93                 
94                 boolean bad = false;
95                 List<String> cause = new ArrayList<String>();
96                 
97
98                 if (motors.size() == 0) {
99                         System.err.println("No motors loaded.");
100                         System.out.println("ERROR: No motors loaded.\n");
101                         return;
102                         
103                 }
104                 
105                 if (motors.size() == 1) {
106                         System.out.println("Best (ONLY): " + files.get(0));
107                         System.out.println();
108                         return;
109                 }
110                 
111                 final int n = motors.size();
112                 goodness = new int[n];
113                 
114
115                 for (String s : files) {
116                         System.out.print("\t" + s);
117                 }
118                 System.out.println();
119                 
120
121                 // Designations
122                 System.out.printf("Designation:");
123                 String des = motors.get(0).getDesignation();
124                 for (Motor m : motors) {
125                         System.out.printf("\t%s", m.getDesignation());
126                         if (!m.getDesignation().equals(des)) {
127                                 cause.add("Designation");
128                                 bad = true;
129                         }
130                 }
131                 System.out.println();
132                 
133                 // Manufacturers
134                 System.out.printf("Manufacture:");
135                 Manufacturer mfg = motors.get(0).getManufacturer();
136                 for (ThrustCurveMotor m : motors) {
137                         System.out.printf("\t%s", m.getManufacturer());
138                         if (m.getManufacturer() != mfg) {
139                                 cause.add("Manufacturer");
140                                 bad = true;
141                         }
142                 }
143                 System.out.println();
144                 
145
146                 // Max. thrust
147                 max = 0;
148                 min = Double.MAX_VALUE;
149                 System.out.printf("Max.thrust :");
150                 for (Motor m : motors) {
151                         double f = m.getMaxThrustEstimate();
152                         System.out.printf("\t%.2f", f);
153                         max = Math.max(max, f);
154                         min = Math.min(min, f);
155                 }
156                 diff = (max - min) / min;
157                 if (diff > MAX_THRUST_MARGIN) {
158                         bad = true;
159                         cause.add("Max thrust");
160                 }
161                 System.out.printf("\t(discrepancy %.1f%%)\n", 100.0 * diff);
162                 maxThrust = (min + max) / 2;
163                 
164
165                 // Total time
166                 max = 0;
167                 min = Double.MAX_VALUE;
168                 System.out.printf("Burn time :");
169                 for (Motor m : motors) {
170                         double t = m.getBurnTimeEstimate();
171                         System.out.printf("\t%.2f", t);
172                         max = Math.max(max, t);
173                         min = Math.min(min, t);
174                 }
175                 diff = (max - min) / min;
176                 System.out.printf("\t(discrepancy %.1f%%)\n", 100.0 * diff);
177                 maxTime = max;
178                 
179
180                 // Total impulse
181                 max = 0;
182                 min = Double.MAX_VALUE;
183                 System.out.printf("Impulse    :");
184                 for (Motor m : motors) {
185                         double f = m.getTotalImpulseEstimate();
186                         System.out.printf("\t%.2f", f);
187                         max = Math.max(max, f);
188                         min = Math.min(min, f);
189                 }
190                 diff = (max - min) / min;
191                 if (diff > TOTAL_IMPULSE_MARGIN) {
192                         bad = true;
193                         cause.add("Total impulse");
194                 }
195                 System.out.printf("\t(discrepancy %.1f%%)\n", 100.0 * diff);
196                 
197
198                 // Initial mass
199                 max = 0;
200                 min = Double.MAX_VALUE;
201                 System.out.printf("Init mass  :");
202                 for (Motor m : motors) {
203                         double f = m.getLaunchCG().weight;
204                         System.out.printf("\t%.2f", f * 1000);
205                         max = Math.max(max, f);
206                         min = Math.min(min, f);
207                 }
208                 diff = (max - min) / min;
209                 if (diff > MASS_MARGIN) {
210                         bad = true;
211                         cause.add("Initial mass");
212                 }
213                 System.out.printf("\t(discrepancy %.1f%%)\n", 100.0 * diff);
214                 
215
216                 // Empty mass
217                 max = 0;
218                 min = Double.MAX_VALUE;
219                 System.out.printf("Empty mass :");
220                 for (Motor m : motors) {
221                         double f = m.getEmptyCG().weight;
222                         System.out.printf("\t%.2f", f * 1000);
223                         max = Math.max(max, f);
224                         min = Math.min(min, f);
225                 }
226                 diff = (max - min) / min;
227                 if (diff > MASS_MARGIN) {
228                         bad = true;
229                         cause.add("Empty mass");
230                 }
231                 System.out.printf("\t(discrepancy %.1f%%)\n", 100.0 * diff);
232                 
233
234                 // Delays
235                 maxDelays = 0;
236                 System.out.printf("Delays     :");
237                 for (ThrustCurveMotor m : motors) {
238                         System.out.printf("\t%d", m.getStandardDelays().length);
239                         maxDelays = Math.max(maxDelays, m.getStandardDelays().length);
240                 }
241                 System.out.println();
242                 
243
244                 // Data points
245                 maxPoints = 0;
246                 System.out.printf("Points     :");
247                 for (Motor m : motors) {
248                         System.out.printf("\t%d", ((ThrustCurveMotor) m).getTimePoints().length);
249                         maxPoints = Math.max(maxPoints, ((ThrustCurveMotor) m).getTimePoints().length);
250                 }
251                 System.out.println();
252                 
253
254                 // Comment length
255                 maxCommentLen = 0;
256                 System.out.printf("Comment len:");
257                 for (Motor m : motors) {
258                         System.out.printf("\t%d", m.getDescription().length());
259                         maxCommentLen = Math.max(maxCommentLen, m.getDescription().length());
260                 }
261                 System.out.println();
262                 
263
264                 if (bad) {
265                         String str = "ERROR: ";
266                         for (int i = 0; i < cause.size(); i++) {
267                                 str += cause.get(i);
268                                 if (i < cause.size() - 1)
269                                         str += ", ";
270                         }
271                         str += " differs";
272                         System.out.println(str);
273                         System.out.println();
274                         return;
275                 }
276                 
277                 // Check consistency
278                 // TODO: Does not check consistency
279                 //              int invalidPoints = 0;
280                 //              for (int i = 0; i < DIVISIONS; i++) {
281                 //                      double t = maxTime * i / (DIVISIONS - 1);
282                 //                      min = Double.MAX_VALUE;
283                 //                      max = 0;
284                 //                      //                              System.out.printf("%.2f:", t);
285                 //                      for (Motor m : motors) {
286                 //                              double f = m.getThrust(t);
287                 //                              //                                      System.out.printf("\t%.2f", f);
288                 //                              min = Math.min(min, f);
289                 //                              max = Math.max(max, f);
290                 //                      }
291                 //                      diff = (max - min) / maxThrust;
292                 //                      //                              System.out.printf("\t(diff %.1f%%)\n", diff*100);
293                 //                      if (diff > THRUST_MARGIN)
294                 //                              invalidPoints++;
295                 //              }
296                 //              
297                 //              if (invalidPoints > ALLOWED_INVALID_POINTS) {
298                 //                      System.out.println("ERROR: " + invalidPoints + "/" + DIVISIONS
299                 //                                      + " points have thrust differing over " + (THRUST_MARGIN * 100) + "%");
300                 //                      System.out.println();
301                 //                      return;
302                 //              }
303                 
304
305                 // Check goodness
306                 for (int i = 0; i < n; i++) {
307                         ThrustCurveMotor m = motors.get(i);
308                         if (m.getStandardDelays().length == maxDelays)
309                                 goodness[i] += 1000;
310                         if (((ThrustCurveMotor) m).getTimePoints().length == maxPoints)
311                                 goodness[i] += 100;
312                         if (m.getDescription().length() == maxCommentLen)
313                                 goodness[i] += 10;
314                         if (files.get(i).matches(".*\\.[rR][sS][eE]$"))
315                                 goodness[i] += 1;
316                 }
317                 int best = 0;
318                 for (int i = 1; i < n; i++) {
319                         if (goodness[i] > goodness[best])
320                                 best = i;
321                 }
322                 
323
324                 // Verify enough points
325                 int pts = ((ThrustCurveMotor) motors.get(best)).getTimePoints().length;
326                 if (pts < MIN_POINTS) {
327                         System.out.println("WARNING: Best has only " + pts + " data points");
328                 }
329                 
330                 System.out.println("Best (" + goodness[best] + "): " + files.get(best));
331                 System.out.println();
332                 
333
334         }
335         
336 }