release 0.9.6
[debian/openrocket] / 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.GeneralMotorLoader;
10 import net.sf.openrocket.file.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<Motor> motors = new ArrayList<Motor>();
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(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         
83         public static void compare(List<Motor> motors, List<String> files) {
84                 final double maxThrust;
85                 final double maxTime;
86                 int maxDelays;
87                 int maxPoints;
88                 int maxCommentLen;
89
90                 double min, max;
91                 double diff;
92
93                 int[] goodness;
94
95                 boolean bad = false;
96                 List<String> cause = new ArrayList<String>();
97
98
99                 if (motors.size() == 0) {
100                         System.err.println("No motors loaded.");
101                         System.out.println("ERROR: No motors loaded.\n");
102                         return;
103
104                 }
105
106                 if (motors.size() == 1) {
107                         System.out.println("Best (ONLY): " + files.get(0));
108                         System.out.println();
109                         return;
110                 }
111
112                 final int n = motors.size(); 
113                 goodness = new int[n];
114
115                 
116                 for (String s: files) {
117                         System.out.print("\t"+s);
118                 }
119                 System.out.println();
120
121
122                 // Designations
123                 System.out.printf("Designation:");
124                 String des = motors.get(0).getDesignation();
125                 for (Motor m: motors) {
126                         System.out.printf("\t%s", m.getDesignation());
127                         if (!m.getDesignation().equals(des)) {
128                                 cause.add("Designation");
129                                 bad = true;
130                         }
131                 }
132                 System.out.println();
133
134                 // Manufacturers
135                 System.out.printf("Manufacture:");
136                 Manufacturer mfg = motors.get(0).getManufacturer();
137                 for (Motor m: motors) {
138                         System.out.printf("\t%s", m.getManufacturer());
139                         if (m.getManufacturer() != mfg) {
140                                 cause.add("Manufacturer");
141                                 bad = true;
142                         }
143                 }
144                 System.out.println();
145
146
147                 // Max. thrust
148                 max = 0;
149                 min = Double.MAX_VALUE;
150                 System.out.printf("Max.thrust :");
151                 for (Motor m: motors) {
152                         double f = m.getMaxThrust();
153                         System.out.printf("\t%.2f", f);
154                         max = Math.max(max, f);
155                         min = Math.min(min, f);
156                 }
157                 diff = (max-min)/min;
158                 if (diff > MAX_THRUST_MARGIN) {
159                         bad = true;
160                         cause.add("Max thrust");
161                 }
162                 System.out.printf("\t(discrepancy %.1f%%)\n", 100.0*diff);
163                 maxThrust = (min+max)/2;
164
165
166                 // Total time
167                 max = 0;
168                 min = Double.MAX_VALUE;
169                 System.out.printf("Total time :");
170                 for (Motor m: motors) {
171                         double t = m.getTotalTime();
172                         System.out.printf("\t%.2f", t);
173                         max = Math.max(max, t);
174                         min = Math.min(min, t);
175                 }
176                 diff = (max-min)/min;
177                 System.out.printf("\t(discrepancy %.1f%%)\n", 100.0*diff);
178                 maxTime = max;
179
180
181                 // Total impulse
182                 max = 0;
183                 min = Double.MAX_VALUE;
184                 System.out.printf("Impulse    :");
185                 for (Motor m: motors) {
186                         double f = m.getTotalImpulse();
187                         System.out.printf("\t%.2f", f);
188                         max = Math.max(max, f);
189                         min = Math.min(min, f);
190                 }
191                 diff = (max-min)/min;
192                 if (diff > TOTAL_IMPULSE_MARGIN) {
193                         bad = true;
194                         cause.add("Total impulse");
195                 }
196                 System.out.printf("\t(discrepancy %.1f%%)\n", 100.0*diff);
197
198
199                 // Initial mass
200                 max = 0;
201                 min = Double.MAX_VALUE;
202                 System.out.printf("Init mass  :");
203                 for (Motor m: motors) {
204                         double f = m.getMass(0);
205                         System.out.printf("\t%.2f", f*1000);
206                         max = Math.max(max, f);
207                         min = Math.min(min, f);
208                 }
209                 diff = (max-min)/min;
210                 if (diff > MASS_MARGIN) {
211                         bad = true;
212                         cause.add("Initial mass");
213                 }
214                 System.out.printf("\t(discrepancy %.1f%%)\n", 100.0*diff);
215
216
217                 // Empty mass
218                 max = 0;
219                 min = Double.MAX_VALUE;
220                 System.out.printf("Empty mass :");
221                 for (Motor m: motors) {
222                         double f = m.getMass(Double.POSITIVE_INFINITY);
223                         System.out.printf("\t%.2f", f*1000);
224                         max = Math.max(max, f);
225                         min = Math.min(min, f);
226                 }
227                 diff = (max-min)/min;
228                 if (diff > MASS_MARGIN) {
229                         bad = true;
230                         cause.add("Empty mass");
231                 }
232                 System.out.printf("\t(discrepancy %.1f%%)\n", 100.0*diff);
233
234
235                 // Delays
236                 maxDelays = 0;
237                 System.out.printf("Delays     :");
238                 for (Motor m: motors) {
239                         System.out.printf("\t%d", m.getStandardDelays().length);
240                         maxDelays = Math.max(maxDelays, m.getStandardDelays().length);
241                 }
242                 System.out.println();
243
244
245                 // Data points
246                 maxPoints = 0;
247                 System.out.printf("Points     :");
248                 for (Motor m: motors) {
249                         System.out.printf("\t%d", ((ThrustCurveMotor)m).getTimePoints().length);
250                         maxPoints = Math.max(maxPoints, ((ThrustCurveMotor)m).getTimePoints().length);
251                 }
252                 System.out.println();
253
254
255                 // Comment length
256                 maxCommentLen = 0;
257                 System.out.printf("Comment len:");
258                 for (Motor m: motors) {
259                         System.out.printf("\t%d", m.getDescription().length());
260                         maxCommentLen = Math.max(maxCommentLen, m.getDescription().length());
261                 }
262                 System.out.println();
263
264
265                 if (bad) {
266                         String str = "ERROR: ";
267                         for (int i=0; i<cause.size(); i++) {
268                                 str += cause.get(i);
269                                 if (i < cause.size()-1)
270                                         str += ", ";
271                         }
272                         str += " differs";
273                         System.out.println(str);
274                         System.out.println();
275                         return;
276                 }
277
278                 // 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                         Motor 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 }