1 package net.sf.openrocket.file.motor;
3 import java.io.IOException;
4 import java.io.InputStream;
5 import java.io.InputStreamReader;
7 import java.nio.charset.Charset;
8 import java.util.ArrayList;
9 import java.util.Arrays;
10 import java.util.Collections;
11 import java.util.List;
13 import net.sf.openrocket.motor.Motor;
14 import net.sf.openrocket.util.MathUtil;
16 public abstract class AbstractMotorLoader implements MotorLoader {
22 * This method delegates the reading to the loaded from the Reader using the charset
23 * returned by {@link #getDefaultCharset()}.
25 public List<Motor> load(InputStream stream, String filename) throws IOException {
26 return load(new InputStreamReader(stream, getDefaultCharset()), filename);
31 * Load motors from the specified <code>Reader</code>.
33 * @param reader the source of the motor definitions.
34 * @param filename the file name of the file, may be <code>null</code> if not
36 * @return a list of motors contained in the file.
37 * @throws IOException if an I/O exception occurs of the file format is invalid.
39 protected abstract List<Motor> load(Reader reader, String filename) throws IOException;
44 * Return the default charset to use when loading rocket files of this type.
46 * If the method {@link #load(InputStream, String)} is overridden as well, this
47 * method may return <code>null</code>.
49 * @return the charset to use when loading the rocket file.
51 protected abstract Charset getDefaultCharset();
56 ////////// Helper methods //////////
60 * Calculate the mass of a motor at distinct points in time based on the
61 * initial total mass, propellant weight and thrust.
63 * This calculation assumes that the velocity of the exhaust remains constant
64 * during the burning. This derives from the mass-flow and thrust relation
65 * <pre>F = m' * v</pre>
67 * @param time list of time points
68 * @param thrust thrust at the discrete times
69 * @param total total weight of the motor
70 * @param prop propellant amount consumed during burning
71 * @return a list of the mass at the specified time points
73 protected static List<Double> calculateMass(List<Double> time, List<Double> thrust,
74 double total, double prop) {
75 List<Double> mass = new ArrayList<Double>();
76 List<Double> deltam = new ArrayList<Double>();
79 double totalMassChange = 0;
82 // First calculate mass change between points
85 for (int i = 1; i < time.size(); i++) {
86 double t1 = time.get(i);
87 double f1 = thrust.get(i);
89 double dm = 0.5 * (f0 + f1) * (t1 - t0);
91 totalMassChange += dm;
96 // Scale mass change and calculate mass
98 scale = prop / totalMassChange;
99 for (double dm : deltam) {
109 * Helper method to remove a delay (or plugged) from the end of a motor designation,
112 * @param designation the motor designation.
113 * @return the designation with a possible delay removed.
115 protected static String removeDelay(String designation) {
116 if (designation.matches(".*-([0-9]+|[pP])$")) {
117 designation = designation.substring(0, designation.lastIndexOf('-'));
125 * Helper method to tokenize a string using whitespace as the delimiter.
127 protected static String[] split(String str) {
128 return split(str, "\\s+");
133 * Helper method to tokenize a string using the given delimiter.
135 protected static String[] split(String str, String delim) {
136 String[] pieces = str.split(delim);
137 if (pieces.length == 0 || !pieces[0].equals(""))
139 return Arrays.copyOfRange(pieces, 1, pieces.length);
144 * Sort the primary list and other lists in that order.
146 * @param primary the list to order.
147 * @param lists lists to order in the same permutation.
149 protected static void sortLists(List<Double> primary, List<?>... lists) {
151 // TODO: LOW: Very idiotic sort algorithm, but should be fast enough
152 // since the time should be sorted already
157 for (index = 0; index < primary.size() - 1; index++) {
158 if (primary.get(index + 1) < primary.get(index)) {
159 Collections.swap(primary, index, index + 1);
160 for (List<?> l : lists) {
161 Collections.swap(l, index, index + 1);
166 } while (index < primary.size() - 1);
171 @SuppressWarnings("unchecked")
172 protected static void finalizeThrustCurve(List<Double> time, List<Double> thrust,
175 if (time.size() == 0)
179 if (!MathUtil.equals(time.get(0), 0) || !MathUtil.equals(thrust.get(0), 0)) {
182 for (List l : lists) {
189 int n = time.size() - 1;
190 if (!MathUtil.equals(thrust.get(n), 0)) {
191 time.add(time.get(n));
193 for (List l : lists) {