version 1.0.0
[debian/openrocket] / src / net / sf / openrocket / file / motor / RASPMotorLoader.java
1 package net.sf.openrocket.file.motor;
2
3 import java.io.BufferedReader;
4 import java.io.IOException;
5 import java.io.Reader;
6 import java.nio.charset.Charset;
7 import java.util.ArrayList;
8 import java.util.Collections;
9 import java.util.List;
10
11 import net.sf.openrocket.file.MotorLoader;
12 import net.sf.openrocket.motor.Manufacturer;
13 import net.sf.openrocket.motor.Motor;
14 import net.sf.openrocket.motor.MotorDigest;
15 import net.sf.openrocket.motor.ThrustCurveMotor;
16 import net.sf.openrocket.motor.MotorDigest.DataType;
17 import net.sf.openrocket.util.Coordinate;
18
19 public class RASPMotorLoader extends MotorLoader {
20
21         public static final String CHARSET_NAME = "ISO-8859-1";
22         
23         public static final Charset CHARSET = Charset.forName(CHARSET_NAME);
24         
25         
26         
27         
28         @Override
29         protected Charset getDefaultCharset() {
30                 return CHARSET;
31         }
32
33         
34         /**
35          * Load a <code>Motor</code> from a RASP file specified by the <code>Reader</code>.
36          * The <code>Reader</code> is responsible for using the correct charset.
37          * <p>
38          * The CG is assumed to be located at the center of the motor casing and the mass
39          * is calculated from the thrust curve by assuming a constant exhaust velocity.
40          * 
41          * @param reader  the source of the file.
42          * @return                a list of the {@link Motor} objects defined in the file.
43          * @throws IOException  if an I/O error occurs or if the file format is illegal.
44          */
45         @Override
46         public List<Motor> load(Reader reader, String filename) throws IOException {
47                 List<Motor> motors = new ArrayList<Motor>();
48                 BufferedReader in = new BufferedReader(reader);
49
50                 String manufacturer = "";
51                 String designation = "";
52                 String comment = "";
53                 
54                 double length = 0;
55                 double diameter = 0;
56                 ArrayList<Double> delays = null;
57                 
58                 List<Double> time = new ArrayList<Double>();
59                 List<Double> thrust = new ArrayList<Double>();
60                 
61                 double propW = 0;
62                 double totalW = 0;
63                 
64                 try {
65                         String line;
66                         String[] pieces, buf;
67
68                         line = in.readLine();
69                         main: while (line != null) {   // Until EOF
70
71                                 manufacturer = "";
72                                 designation = "";
73                                 comment = "";
74                                 length = 0;
75                                 diameter = 0;
76                                 delays = new ArrayList<Double>();
77                                 propW = 0;
78                                 totalW = 0;
79                                 time.clear();
80                                 thrust .clear();
81                         
82                                 // Read comment
83                                 while (line.length()==0 || line.charAt(0)==';') {
84                                         if (line.length() > 0) {
85                                                 comment += line.substring(1).trim() + "\n";
86                                         }
87                                         line = in.readLine();
88                                         if (line == null)
89                                                 break main;
90                                 }
91                                 comment = comment.trim();
92                                 
93                                 // Parse header line, example:
94                                 // F32 24 124 5-10-15-P .0377 .0695 RV
95                                 // desig diam len delays prop.w tot.w manufacturer
96                                 pieces = split(line);
97                                 if (pieces.length != 7) {
98                                         throw new IOException("Illegal file format.");
99                                 }
100                                 
101                                 designation = pieces[0];
102                                 diameter = Double.parseDouble(pieces[1]) / 1000.0;
103                                 length = Double.parseDouble(pieces[2]) / 1000.0;
104                                 
105                                 if (pieces[3].equalsIgnoreCase("None")) {
106
107                                 } else {
108                                         buf = split(pieces[3],"[-,]+");
109                                         for (int i=0; i < buf.length; i++) {
110                                                 if (buf[i].equalsIgnoreCase("P") || 
111                                                                 buf[i].equalsIgnoreCase("plugged")) {
112                                                         delays.add(Motor.PLUGGED);
113                                                 } else {
114                                                         // Many RASP files have "100" as an only delay
115                                                         double d = Double.parseDouble(buf[i]);
116                                                         if (d < 99)
117                                                                 delays.add(d);
118                                                 }
119                                         }
120                                         Collections.sort(delays);
121                                 }
122                                 
123                                 propW = Double.parseDouble(pieces[4]);
124                                 totalW = Double.parseDouble(pieces[5]);
125                                 manufacturer = pieces[6];
126                                 
127                                 if (propW > totalW) {
128                                         throw new IOException("Propellant weight exceeds total weight in " +
129                                                         "RASP file " + filename);
130                                 }
131                                 
132                                 // Read the data
133                                 for (line = in.readLine(); 
134                                          (line != null) && (line.length()==0 || line.charAt(0) != ';');
135                                          line = in.readLine()) {
136                                         
137                                         buf = split(line);
138                                         if (buf.length == 0) {
139                                                 continue;
140                                         } else if (buf.length == 2) {
141                                                 
142                                                 time.add(Double.parseDouble(buf[0]));
143                                                 thrust .add(Double.parseDouble(buf[1]));
144                                                 
145                                         } else {
146                                                 throw new IOException("Illegal file format.");
147                                         }
148                                 }
149                                 
150                                 // Comment of EOF encountered, marks the start of the next motor
151                                 if (time.size() < 2) {
152                                         throw new IOException("Illegal file format, too short thrust-curve.");
153                                 }
154                                 double[] delayArray = new double[delays.size()];
155                                 for (int i=0; i<delays.size(); i++) {
156                                         delayArray[i] = delays.get(i);
157                                 }
158                                 motors.add(createRASPMotor(manufacturer, designation, comment,
159                                                 length, diameter, delayArray, propW, totalW, time, thrust));
160                         }
161                         
162                 } catch (NumberFormatException e) {
163                         
164                         throw new IOException("Illegal file format.");
165                         
166                 } finally {
167                         
168                         in.close();
169                         
170                 }
171                 
172                 return motors;
173         }
174         
175         
176         /**
177          * Create a motor from RASP file data.
178          * @throws IOException  if the data is illegal for a thrust curve
179          */
180         private static Motor createRASPMotor(String manufacturer, String designation,
181                         String comment, double length, double diameter, double[] delays,
182                         double propW, double totalW, List<Double> time, List<Double> thrust) 
183                         throws IOException {
184                 
185                 // Add zero time/thrust if necessary
186                 sortLists(time, thrust);
187                 finalizeThrustCurve(time, thrust);
188                 List<Double> mass = calculateMass(time,thrust,totalW,propW);
189                 
190                 double[] timeArray = new double[time.size()];
191                 double[] thrustArray = new double[time.size()];
192                 Coordinate[] cgArray = new Coordinate[time.size()];
193                 for (int i=0; i < time.size(); i++) {
194                         timeArray[i] = time.get(i);
195                         thrustArray[i] = thrust.get(i);
196                         cgArray[i] = new Coordinate(length/2,0,0,mass.get(i));
197                 }
198                 
199                 designation = removeDelay(designation);
200                 
201                 // Create the motor digest from data available in RASP files
202                 MotorDigest motorDigest = new MotorDigest();
203                 motorDigest.update(DataType.TIME_ARRAY, timeArray);
204                 motorDigest.update(DataType.MASS_SPECIFIC, totalW, totalW-propW);
205                 motorDigest.update(DataType.FORCE_PER_TIME, thrustArray);
206                 final String digest = motorDigest.getDigest();
207                 
208                 
209                 try {
210                         
211                         return new ThrustCurveMotor(Manufacturer.getManufacturer(manufacturer), 
212                                         designation, comment, Motor.Type.UNKNOWN,
213                                         delays, diameter, length, timeArray, thrustArray, cgArray, digest);
214                         
215                 } catch (IllegalArgumentException e) {
216                         
217                         // Bad data read from file.
218                         throw new IOException("Illegal file format.", e);
219                         
220                 }
221         }
222 }