356014faf98e99ab26013575ef2f869b1d2bc7de
[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.20;
19         /** Maximum allowed difference in total impulse */
20         private static final double TOTAL_IMPULSE_MARGIN = 0.10;
21         /** Maximum allowed difference in mass values */
22         private static final double MASS_MARGIN = 0.10;
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.15;
28         /** Number of invalid time points allowed */
29         private static final int ALLOWED_INVALID_POINTS = 15;
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                 if (motors.size() == 0) {
76                         System.err.println("No motors loaded.");
77                         System.out.println("ERROR: No motors loaded.\n");
78                         return;
79                         
80                 }
81                 
82                 if (motors.size() == 1) {
83                         System.out.println("Best (ONLY): " + files.get(0));
84                         System.out.println();
85                         return;
86                 }
87                 
88                 final int n = motors.size(); 
89                 goodness = new int[n];
90                 
91                 
92                 // Manufacturers
93                 System.out.printf("Manufacture:");
94                 Manufacturer mfg = motors.get(0).getManufacturer();
95                 for (Motor m: motors) {
96                         System.out.printf("\t%s", m.getManufacturer());
97                         if (m.getManufacturer() != mfg) {
98                                 cause.add("Manufacturer");
99                                 bad = true;
100                         }
101                 }
102                 System.out.println();
103                 
104                 
105                 // Max. thrust
106                 max = 0;
107                 min = Double.MAX_VALUE;
108                 System.out.printf("Max.thrust :");
109                 for (Motor m: motors) {
110                         double f = m.getMaxThrust();
111                         System.out.printf("\t%.2f", f);
112                         max = Math.max(max, f);
113                         min = Math.min(min, f);
114                 }
115                 diff = (max-min)/min;
116                 if (diff > MAX_THRUST_MARGIN) {
117                         bad = true;
118                         cause.add("Max thrust");
119                 }
120                 System.out.printf("\t(discrepancy %.1f%%)\n", 100.0*diff);
121                 maxThrust = (min+max)/2;
122                 
123                 
124                 // Total time
125                 max = 0;
126                 min = Double.MAX_VALUE;
127                 System.out.printf("Total time :");
128                 for (Motor m: motors) {
129                         double t = m.getTotalTime();
130                         System.out.printf("\t%.2f", t);
131                         max = Math.max(max, t);
132                         min = Math.min(min, t);
133                 }
134                 diff = (max-min)/min;
135                 System.out.printf("\t(discrepancy %.1f%%)\n", 100.0*diff);
136                 maxTime = max;
137                 
138                 
139                 // Total impulse
140                 max = 0;
141                 min = Double.MAX_VALUE;
142                 System.out.printf("Impulse    :");
143                 for (Motor m: motors) {
144                         double f = m.getTotalImpulse();
145                         System.out.printf("\t%.2f", f);
146                         max = Math.max(max, f);
147                         min = Math.min(min, f);
148                 }
149                 diff = (max-min)/min;
150                 if (diff > TOTAL_IMPULSE_MARGIN) {
151                         bad = true;
152                         cause.add("Total impulse");
153                 }
154                 System.out.printf("\t(discrepancy %.1f%%)\n", 100.0*diff);
155                 
156                 
157                 // Initial mass
158                 max = 0;
159                 min = Double.MAX_VALUE;
160                 System.out.printf("Init mass  :");
161                 for (Motor m: motors) {
162                         double f = m.getMass(0);
163                         System.out.printf("\t%.2f", f*1000);
164                         max = Math.max(max, f);
165                         min = Math.min(min, f);
166                 }
167                 diff = (max-min)/min;
168                 if (diff > MASS_MARGIN) {
169                         bad = true;
170                         cause.add("Initial mass");
171                 }
172                 System.out.printf("\t(discrepancy %.1f%%)\n", 100.0*diff);
173                 
174                 
175                 // Empty mass
176                 max = 0;
177                 min = Double.MAX_VALUE;
178                 System.out.printf("Empty mass :");
179                 for (Motor m: motors) {
180                         double f = m.getMass(Double.POSITIVE_INFINITY);
181                         System.out.printf("\t%.2f", f*1000);
182                         max = Math.max(max, f);
183                         min = Math.min(min, f);
184                 }
185                 diff = (max-min)/min;
186                 if (diff > MASS_MARGIN) {
187                         bad = true;
188                         cause.add("Empty mass");
189                 }
190                 System.out.printf("\t(discrepancy %.1f%%)\n", 100.0*diff);
191                 
192                 
193                 // Delays
194                 maxDelays = 0;
195                 System.out.printf("Delays     :");
196                 for (Motor m: motors) {
197                         System.out.printf("\t%d", m.getStandardDelays().length);
198                         maxDelays = Math.max(maxDelays, m.getStandardDelays().length);
199                 }
200                 System.out.println();
201                 
202                 
203                 // Data points
204                 maxPoints = 0;
205                 System.out.printf("Points     :");
206                 for (Motor m: motors) {
207                         System.out.printf("\t%d", ((ThrustCurveMotor)m).getTimePoints().length);
208                         maxPoints = Math.max(maxPoints, ((ThrustCurveMotor)m).getTimePoints().length);
209                 }
210                 System.out.println();
211                 
212                 
213                 // Comment length
214                 maxCommentLen = 0;
215                 System.out.printf("Comment len:");
216                 for (Motor m: motors) {
217                         System.out.printf("\t%d", m.getDescription().length());
218                         maxCommentLen = Math.max(maxCommentLen, m.getDescription().length());
219                 }
220                 System.out.println();
221                 
222                 
223                 if (bad) {
224                         String str = "ERROR: ";
225                         for (int i=0; i<cause.size(); i++) {
226                                 str += cause.get(i);
227                                 if (i < cause.size()-1)
228                                         str += ", ";
229                         }
230                         str += " differs";
231                         System.out.println(str);
232                         System.out.println();
233                         return;
234                 }
235                 
236                 // Check consistency
237                 int invalidPoints = 0;
238                 for (int i=0; i < DIVISIONS; i++) {
239                         double t = maxTime * i/(DIVISIONS-1);
240                         min = Double.MAX_VALUE;
241                         max = 0;
242 //                      System.out.printf("%.2f:", t);
243                         for (Motor m: motors) {
244                                 double f = m.getThrust(t);
245 //                              System.out.printf("\t%.2f", f);
246                                 min = Math.min(min, f);
247                                 max = Math.max(max, f);
248                         }
249                         diff = (max-min)/maxThrust;
250 //                      System.out.printf("\t(diff %.1f%%)\n", diff*100);
251                         if (diff > THRUST_MARGIN)
252                                 invalidPoints++;
253                 }
254                 
255                 if (invalidPoints > ALLOWED_INVALID_POINTS) {
256                         System.out.println("ERROR: " + invalidPoints + "/" + DIVISIONS 
257                                         + " points have thrust differing over " + (THRUST_MARGIN*100) + "%");
258                         System.out.println();
259                         return;
260                 }
261                 
262                 
263                 // Check goodness
264                 for (int i=0; i<n; i++) {
265                         Motor m = motors.get(i);
266                         if (m.getStandardDelays().length == maxDelays)
267                                 goodness[i] += 1000;
268                         if (((ThrustCurveMotor)m).getTimePoints().length == maxPoints)
269                                 goodness[i] += 100;
270                         if (m.getDescription().length() == maxCommentLen)
271                                 goodness[i] += 10;
272                         if (files.get(i).matches(".*\\.[rR][sS][eE]$"))
273                                 goodness[i] += 1;
274                 }
275                 int best = 0;
276                 for (int i=1; i<n; i++) {
277                         if (goodness[i] > goodness[best])
278                                 best = i;
279                 }
280                 
281                 
282                 // Verify enough points
283                 int pts = ((ThrustCurveMotor)motors.get(best)).getTimePoints().length;
284                 if (pts < MIN_POINTS) {
285                         System.out.println("ERROR: Best has only " + pts + " data points");
286                         System.out.println();
287                         return;
288                 }
289                 
290                 System.out.println("Best (" + goodness[best] + "): " + files.get(best));
291                 System.out.println();
292                 
293                 
294         }
295         
296 }