motor loading refactoring
authorplaa <plaa@180e2498-e6e9-4542-8430-84ac67f01cd8>
Sun, 29 Jan 2012 18:13:23 +0000 (18:13 +0000)
committerplaa <plaa@180e2498-e6e9-4542-8430-84ac67f01cd8>
Sun, 29 Jan 2012 18:13:23 +0000 (18:13 +0000)
git-svn-id: https://openrocket.svn.sourceforge.net/svnroot/openrocket/trunk@378 180e2498-e6e9-4542-8430-84ac67f01cd8

13 files changed:
core/src/net/sf/openrocket/file/AbstractRocketLoader.java
core/src/net/sf/openrocket/file/DatabaseMotorFinder.java [new file with mode: 0644]
core/src/net/sf/openrocket/file/GeneralRocketLoader.java
core/src/net/sf/openrocket/file/MotorFinder.java [new file with mode: 0644]
core/src/net/sf/openrocket/file/RocketLoader.java
core/src/net/sf/openrocket/file/openrocket/importt/DocumentLoadingContext.java
core/src/net/sf/openrocket/file/openrocket/importt/OpenRocketLoader.java
core/src/net/sf/openrocket/file/openrocket/importt/PreferredMotorDigests.java [deleted file]
core/src/net/sf/openrocket/file/rocksim/importt/RocksimLoader.java
core/src/net/sf/openrocket/gui/util/OpenFileWorker.java
core/src/net/sf/openrocket/utils/RocksimConverter.java
core/test/net/sf/openrocket/IntegrationTest.java
core/test/net/sf/openrocket/file/rocksim/importt/RocksimLoaderTest.java

index 0cb19110aa38d7963e3dd71e981808a74a3a7143..f0c7464dfe4e985135a0152d176a00d4b044a132 100644 (file)
@@ -19,14 +19,14 @@ public abstract class AbstractRocketLoader implements RocketLoader {
         * Loads a rocket from the specified File object.
         */
        @Override
-       public final OpenRocketDocument load(File source) throws RocketLoadException {
+       public final OpenRocketDocument load(File source, MotorFinder motorFinder) throws RocketLoadException {
                warnings.clear();
                InputStream stream = null;
                
                try {
                        
                        stream = new BufferedInputStream(new FileInputStream(source));
-                       return load(stream);
+                       return load(stream, motorFinder);
                        
                } catch (FileNotFoundException e) {
                        throw new RocketLoadException("File not found: " + source);
@@ -45,11 +45,11 @@ public abstract class AbstractRocketLoader implements RocketLoader {
         * Loads a rocket from the specified InputStream.
         */
        @Override
-       public final OpenRocketDocument load(InputStream source) throws RocketLoadException {
+       public final OpenRocketDocument load(InputStream source, MotorFinder motorFinder) throws RocketLoadException {
                warnings.clear();
                
                try {
-                       return loadFromStream(source);
+                       return loadFromStream(source, motorFinder);
                } catch (RocketLoadException e) {
                        throw e;
                } catch (IOException e) {
@@ -60,12 +60,12 @@ public abstract class AbstractRocketLoader implements RocketLoader {
        
        
        /**
-        * This method is called by the default implementations of {@link #load(File)} 
-        * and {@link #load(InputStream)} to load the rocket.
+        * This method is called by the default implementations of #load(File) 
+        * and load(InputStream) to load the rocket.
         * 
         * @throws RocketLoadException  if an error occurs during loading.
         */
-       protected abstract OpenRocketDocument loadFromStream(InputStream source) throws IOException,
+       protected abstract OpenRocketDocument loadFromStream(InputStream source, MotorFinder motorFinder) throws IOException,
                        RocketLoadException;
        
        
diff --git a/core/src/net/sf/openrocket/file/DatabaseMotorFinder.java b/core/src/net/sf/openrocket/file/DatabaseMotorFinder.java
new file mode 100644 (file)
index 0000000..9af7a73
--- /dev/null
@@ -0,0 +1,82 @@
+package net.sf.openrocket.file;
+
+import java.util.List;
+
+import net.sf.openrocket.aerodynamics.Warning;
+import net.sf.openrocket.aerodynamics.WarningSet;
+import net.sf.openrocket.motor.Motor;
+import net.sf.openrocket.motor.Motor.Type;
+import net.sf.openrocket.startup.Application;
+
+/**
+ * A MotorFinder implementation that searches the thrust curve motor database
+ * for a motor.
+ * 
+ * @author Sampo Niskanen <sampo.niskanen@iki.fi>
+ */
+public class DatabaseMotorFinder implements MotorFinder {
+       
+       @Override
+       public Motor findMotor(Type type, String manufacturer, String designation, double diameter, double length, String digest, WarningSet warnings) {
+               
+               if (designation == null) {
+                       warnings.add(Warning.fromString("No motor specified, ignoring."));
+                       return null;
+               }
+               
+               List<? extends Motor> motors = Application.getMotorSetDatabase().findMotors(type, manufacturer, designation, diameter, length);
+               
+               // No motors
+               if (motors.size() == 0) {
+                       Warning.MissingMotor mmw = new Warning.MissingMotor();
+                       mmw.setDesignation(designation);
+                       mmw.setDigest(digest);
+                       mmw.setDiameter(diameter);
+                       mmw.setLength(length);
+                       mmw.setManufacturer(manufacturer);
+                       mmw.setType(type);
+                       warnings.add(mmw);
+                       return null;
+               }
+               
+               // One motor
+               if (motors.size() == 1) {
+                       Motor m = motors.get(0);
+                       if (digest != null && !digest.equals(m.getDigest())) {
+                               String str = "Motor with designation '" + designation + "'";
+                               if (manufacturer != null)
+                                       str += " for manufacturer '" + manufacturer + "'";
+                               str += " has differing thrust curve than the original.";
+                               warnings.add(str);
+                       }
+                       return m;
+               }
+               
+               // Multiple motors, check digest for which one to use
+               if (digest != null) {
+                       
+                       // Check for motor with correct digest
+                       for (Motor m : motors) {
+                               if (digest.equals(m.getDigest())) {
+                                       return m;
+                               }
+                       }
+                       String str = "Motor with designation '" + designation + "'";
+                       if (manufacturer != null)
+                               str += " for manufacturer '" + manufacturer + "'";
+                       str += " has differing thrust curve than the original.";
+                       warnings.add(str);
+                       
+               } else {
+                       
+                       String str = "Multiple motors with designation '" + designation + "'";
+                       if (manufacturer != null)
+                               str += " for manufacturer '" + manufacturer + "'";
+                       str += " found, one chosen arbitrarily.";
+                       warnings.add(str);
+                       
+               }
+               return motors.get(0);
+       }
+       
+}
index 68555d1052b26b6d2ebc5c30cc361767ac955518..775d9eddfa9dc219ce1e3b1a2bbea9ce3398f60f 100644 (file)
@@ -35,7 +35,7 @@ public class GeneralRocketLoader extends AbstractRocketLoader {
        private final RocksimLoader rocksimLoader = new RocksimLoader();
        
        @Override
-       protected OpenRocketDocument loadFromStream(InputStream source) throws IOException,
+       protected OpenRocketDocument loadFromStream(InputStream source, MotorFinder motorFinder) throws IOException,
                        RocketLoadException {
                
                // Check for mark() support
@@ -58,7 +58,7 @@ public class GeneralRocketLoader extends AbstractRocketLoader {
                
                // Check for GZIP
                if (buffer[0] == GZIP_SIGNATURE[0] && buffer[1] == GZIP_SIGNATURE[1]) {
-                       OpenRocketDocument doc = loadFromStream(new GZIPInputStream(source));
+                       OpenRocketDocument doc = loadFromStream(new GZIPInputStream(source), motorFinder);
                        doc.getDefaultStorageOptions().setCompressionEnabled(true);
                        return doc;
                }
@@ -73,7 +73,7 @@ public class GeneralRocketLoader extends AbstractRocketLoader {
                                        throw new RocketLoadException("Unsupported or corrupt file.");
                                }
                                if (entry.getName().matches(".*\\.[oO][rR][kK]$")) {
-                                       OpenRocketDocument doc = loadFromStream(in);
+                                       OpenRocketDocument doc = loadFromStream(in, motorFinder);
                                        doc.getDefaultStorageOptions().setCompressionEnabled(true);
                                        return doc;
                                }
@@ -86,7 +86,7 @@ public class GeneralRocketLoader extends AbstractRocketLoader {
                        if (buffer[i] == OPENROCKET_SIGNATURE[match]) {
                                match++;
                                if (match == OPENROCKET_SIGNATURE.length) {
-                                       return loadUsing(source, openRocketLoader);
+                                       return loadUsing(source, openRocketLoader, motorFinder);
                                }
                        } else {
                                match = 0;
@@ -95,15 +95,15 @@ public class GeneralRocketLoader extends AbstractRocketLoader {
                
                byte[] typeIdentifier = Arrays.copyOf(buffer, ROCKSIM_SIGNATURE.length);
                if (Arrays.equals(ROCKSIM_SIGNATURE, typeIdentifier)) {
-                       return loadUsing(source, rocksimLoader);
+                       return loadUsing(source, rocksimLoader, motorFinder);
                }
                throw new RocketLoadException("Unsupported or corrupt file.");
        }
        
-       private OpenRocketDocument loadUsing(InputStream source, RocketLoader loader)
+       private OpenRocketDocument loadUsing(InputStream source, RocketLoader loader, MotorFinder motorFinder)
                        throws RocketLoadException {
                warnings.clear();
-               OpenRocketDocument doc = loader.load(source);
+               OpenRocketDocument doc = loader.load(source, motorFinder);
                warnings.addAll(loader.getWarnings());
                return doc;
        }
diff --git a/core/src/net/sf/openrocket/file/MotorFinder.java b/core/src/net/sf/openrocket/file/MotorFinder.java
new file mode 100644 (file)
index 0000000..b17e664
--- /dev/null
@@ -0,0 +1,28 @@
+package net.sf.openrocket.file;
+
+import net.sf.openrocket.aerodynamics.WarningSet;
+import net.sf.openrocket.motor.Motor;
+
+/**
+ * Interface for finding the appropriate motor for one defined in an ORK file.
+ * 
+ * @author Sampo Niskanen <sampo.niskanen@iki.fi>
+ */
+public interface MotorFinder {
+       
+       /**
+        * Return the motor to inject to the rocket design when loading a file.
+        * This may also return dysfunctional motor placeholders that will later be
+        * replaced with the appropriate motor.
+        * <p>
+        * Any parameter that is null/NaN should be ignored when finding the motors.
+        * The method can also add appropriate warnings to the provided warning set
+        * in case there are problems selecting the motor.
+        * 
+        * @return      the motor to use in the design, or <code>null</code> for no motor.
+        */
+       public Motor findMotor(Motor.Type type, String manufacturer, String designation, double diameter,
+                       double length, String digest, WarningSet warnings);
+       
+       
+}
index 6918acd1f2e3be0dd3425bdd7dbfd0aedcfb8de4..81bcb0ac8c0e5090ad75ac9d23f77ddb9cd077c9 100644 (file)
@@ -8,9 +8,9 @@ import net.sf.openrocket.document.OpenRocketDocument;
 
 public interface RocketLoader {
        
-       public OpenRocketDocument load(File source) throws RocketLoadException;
+       public OpenRocketDocument load(File source, MotorFinder motorFinder) throws RocketLoadException;
        
-       public OpenRocketDocument load(InputStream source) throws RocketLoadException;
+       public OpenRocketDocument load(InputStream source, MotorFinder motorFinder) throws RocketLoadException;
        
        public WarningSet getWarnings();
        
index ec80db4270d58d80dd423769c5338f1df709c3a6..cd920eae340b06f85bb9328a2837cd0425875e18 100644 (file)
@@ -1,8 +1,12 @@
 package net.sf.openrocket.file.openrocket.importt;
 
+import net.sf.openrocket.file.MotorFinder;
+
 public class DocumentLoadingContext {
        
        private int fileVersion;
+       private MotorFinder motorFinder;
+       
        
        public int getFileVersion() {
                return fileVersion;
@@ -12,4 +16,12 @@ public class DocumentLoadingContext {
                this.fileVersion = fileVersion;
        }
        
+       public MotorFinder getMotorFinder() {
+               return motorFinder;
+       }
+       
+       public void setMotorFinder(MotorFinder motorFinder) {
+               this.motorFinder = motorFinder;
+       }
+       
 }
index 071d5710afabe90010389a358341a9209b214652..ab8ef8de2e58085601c190d8b9675af0a24a9a72 100644 (file)
@@ -18,6 +18,7 @@ import net.sf.openrocket.document.Simulation;
 import net.sf.openrocket.document.Simulation.Status;
 import net.sf.openrocket.document.StorageOptions;
 import net.sf.openrocket.file.AbstractRocketLoader;
+import net.sf.openrocket.file.MotorFinder;
 import net.sf.openrocket.file.RocketLoadException;
 import net.sf.openrocket.file.simplesax.ElementHandler;
 import net.sf.openrocket.file.simplesax.PlainTextHandler;
@@ -86,7 +87,7 @@ import org.xml.sax.SAXException;
  * Class that loads a rocket definition from an OpenRocket rocket file.
  * <p>
  * This class uses SAX to read the XML file format.  The 
- * {@link #loadFromStream(InputStream)} method simply sets the system up and 
+ * #loadFromStream(InputStream) method simply sets the system up and 
  * starts the parsing, while the actual logic is in the private inner class
  * <code>OpenRocketHandler</code>.
  * 
@@ -97,10 +98,11 @@ public class OpenRocketLoader extends AbstractRocketLoader {
        
        
        @Override
-       public OpenRocketDocument loadFromStream(InputStream source) throws RocketLoadException,
+       public OpenRocketDocument loadFromStream(InputStream source, MotorFinder motorFinder) throws RocketLoadException,
                        IOException {
                log.info("Loading .ork file");
                DocumentLoadingContext context = new DocumentLoadingContext();
+               context.setMotorFinder(motorFinder);
                
                InputSource xmlSource = new InputSource(source);
                OpenRocketHandler handler = new OpenRocketHandler(context);
@@ -1022,7 +1024,6 @@ class MotorHandler extends ElementHandler {
        /** File version where latest digest format was introduced */
        private static final int MOTOR_DIGEST_VERSION = 104;
        
-       @SuppressWarnings("unused")
        private final DocumentLoadingContext context;
        private Motor.Type type = null;
        private String manufacturer = null;
@@ -1048,73 +1049,7 @@ class MotorHandler extends ElementHandler {
         * Return the motor to use, or null.
         */
        public Motor getMotor(WarningSet warnings) {
-               if (designation == null) {
-                       warnings.add(Warning.fromString("No motor specified, ignoring."));
-                       return null;
-               }
-               
-               List<? extends Motor> motors = Application.getMotorSetDatabase().findMotors(type, manufacturer,
-                               designation, diameter, length);
-               
-               // No motors
-               if (motors.size() == 0) {
-                       Warning.MissingMotor mmw = new Warning.MissingMotor();
-                       mmw.setDesignation(designation);
-                       mmw.setDigest(digest);
-                       mmw.setDiameter(diameter);
-                       mmw.setLength(length);
-                       mmw.setManufacturer(manufacturer);
-                       mmw.setType(type);
-                       warnings.add(mmw);
-                       return null;
-               }
-               
-               // One motor
-               if (motors.size() == 1) {
-                       Motor m = motors.get(0);
-                       if (digest != null && !digest.equals(m.getDigest())) {
-                               String str = "Motor with designation '" + designation + "'";
-                               if (manufacturer != null)
-                                       str += " for manufacturer '" + manufacturer + "'";
-                               str += " has differing thrust curve than the original.";
-                               warnings.add(str);
-                       }
-                       return m;
-               }
-               
-               // Multiple motors, check digest for which one to use
-               if (digest != null) {
-                       
-                       // Check for motor with correct digest
-                       for (Motor m : motors) {
-                               if (digest.equals(m.getDigest())) {
-                                       return m;
-                               }
-                       }
-                       String str = "Motor with designation '" + designation + "'";
-                       if (manufacturer != null)
-                               str += " for manufacturer '" + manufacturer + "'";
-                       str += " has differing thrust curve than the original.";
-                       warnings.add(str);
-                       
-               } else {
-                       
-                       // No digest, check for preferred digest (OpenRocket <= 1.1.0)
-                       // TODO: MEDIUM: This should only be done for document versions 1.1 and below
-                       for (Motor m : motors) {
-                               if (PreferredMotorDigests.DIGESTS.contains(m.getDigest())) {
-                                       return m;
-                               }
-                       }
-                       
-                       String str = "Multiple motors with designation '" + designation + "'";
-                       if (manufacturer != null)
-                               str += " for manufacturer '" + manufacturer + "'";
-                       str += " found, one chosen arbitrarily.";
-                       warnings.add(str);
-                       
-               }
-               return motors.get(0);
+               return context.getMotorFinder().findMotor(type, manufacturer, designation, diameter, length, digest, warnings);
        }
        
        /**
diff --git a/core/src/net/sf/openrocket/file/openrocket/importt/PreferredMotorDigests.java b/core/src/net/sf/openrocket/file/openrocket/importt/PreferredMotorDigests.java
deleted file mode 100644 (file)
index ffcedf7..0000000
+++ /dev/null
@@ -1,887 +0,0 @@
-package net.sf.openrocket.file.openrocket.importt;
-
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.Set;
-
-/**
- * This class contains the motor digests of motors included in OpenRocket versions prior to 1.1.1.
- * Before this the motor digest was not included in the design files, and therefore if the motor
- * digest is missing when loading a file, the loader should prefer the motors with a digest defined
- * in this class.
- * <p>
- * This is not a requirement for supporting the OpenRocket format, but allows opening older OpenRocket
- * design files accurately without warnings of multiple motors. 
- * 
- * @author Sampo Niskanen <sampo.niskanen@iki.fi>
- */
-final class PreferredMotorDigests {
-       
-       // FIXME:  This class is obsolete/broken after digesting algorithm changes
-       
-       /**
-        * A set containing the preferred motor digests.
-        */
-       public static final Set<String> DIGESTS;
-       static {
-               /*
-                * The list contains 845 digests, set initial parameters suitably to
-                * prevent any rehashing operations and to minimize size (power of two).
-                *    845/1024 = 0.825
-                */
-               Set<String> set = new HashSet<String>(1024, 0.85f);
-               
-               set.add("000ffb4c8e49ae47b2ab9a659da9e59b");
-               set.add("0039ed088e61360d934d9bd8503fad92");
-               set.add("003eeba358de7ebf9293b0e4c4ca9e66");
-               set.add("00e1a0576a93101d458c1c3d68d3eee0");
-               set.add("0111b89926277a6ea3f6075052343105");
-               set.add("0142c270a670ffff41c43268b0f129b9");
-               set.add("01be1f9100e05fb15df4c13395f7181c");
-               set.add("026f5924c48693077f2b11cdcdeb7452");
-               set.add("029082f7acda395568ca7f7df40764e1");
-               set.add("02dd1b3e2df7daf48b763f5ace35345e");
-               set.add("036e124dce42859ff08efa79e1f202e8");
-               set.add("03b88e64af521b03803247922801c996");
-               set.add("0468d7dc3dca25ac073dac1bd674e271");
-               set.add("048cfb7c2477c6e957d501c5ed3bc252");
-               set.add("049dda2ad1a709321734f393dc8a115b");
-               set.add("056d61b6a268283411e9dc9731dbb5e6");
-               set.add("05b85612f288726b02cdc47af7026aac");
-               set.add("05e205dc5dbd95db25305aa5c77b1192");
-               set.add("0601c6944d02e8736c09c2a8bb7cba49");
-               set.add("0622884d0a0954b1df6694ead24868bf");
-               set.add("063e7748d9a96508a70b1a2a1887aa3d");
-               set.add("06634321a8c5d533eb5efcbb40143257");
-               set.add("069a54372ed2776286160384ca0cac4f");
-               set.add("075539867b13c2afcc5198e00d7f4b5c");
-               set.add("076d9374af5fb0f2469083f9b57b7b96");
-               set.add("07c44b615a67060bca83c6faed56c0c6");
-               set.add("0825628215a980eed5fb4bed4eaec3b8");
-               set.add("082bad018f6d1e5622c371c1fe3148d6");
-               set.add("0837c3014078c8c8e79961b939be83cb");
-               set.add("08abceec22c5f6be5e9864be38df8ad5");
-               set.add("08c3b40a4bcf7a33256e5543e484f995");
-               set.add("08ca5be1a598772a8683016db619de36");
-               set.add("0a80cecafb53ae0ac73e6aec1a4567dd");
-               set.add("0add7ca688bcd32df8c3367a094e7847");
-               set.add("0b175b4beb0057db1b169d61061208a7");
-               set.add("0b955870dc2007c2b5f07eea57609420");
-               set.add("0c60a51d36ee5118fe29173aff2f6e49");
-               set.add("0c96cd95432d8e2ce6a6463ebf50beb1");
-               set.add("0d06d195c29a7f6fde6d002171922f2e");
-               set.add("0d642d7cb1544d19ec471124db97b92e");
-               set.add("0dd49968e2b1c4b1077e3c7ade056a79");
-               set.add("0e0d93ee28216440a5fa9452c9082351");
-               set.add("0e6774068b61579e20b89771b8a8f273");
-               set.add("0eac15679d3ae2fbd41083492b356b03");
-               set.add("0eca4c015dd1de561c2bbc47eaa4daf6");
-               set.add("0f0e1d09c7dec3a05b870b399ddbf6ee");
-               set.add("0f3c31b26b5768b3202f02f9d6bcc71c");
-               set.add("0f47293601d59fbad2076012090665dc");
-               set.add("0f5a1b31c333b722e4a72acbeba3a189");
-               set.add("0f6a55aca8a317f4d3d3236e4944343d");
-               set.add("0ffaa291ee52495d7dfec03b3a845636");
-               set.add("1092f5c5b48c2dcd4ac0bb16fa5383a8");
-               set.add("10a1689703dc533d435bef7265dd9ac0");
-               set.add("11bcc433b82e714f59809d76eed0ba05");
-               set.add("11ce2ec12b216f3e8d71fd9c53782b23");
-               set.add("11d11cdff93f18d10a1286cc3485c8c7");
-               set.add("11eac86852e12b9c3a2d0a4b183c3b79");
-               set.add("120eab6dd03b9bee7f5eb717e4e9d491");
-               set.add("1272d1a6979ea20a2efee3eb04657915");
-               set.add("12f6c5360c83656356c902ece3c0ff1b");
-               set.add("138a603a483dcf4127f1dcf208843e67");
-               set.add("140276d009fde1357ecdcb5d9ddc8a80");
-               set.add("1491fae1c7ce940915dd8296c74320f3");
-               set.add("14955ccec83043f3b1ef92f8524b3e67");
-               set.add("150b1279bc8b7f509a030274ee8e3f35");
-               set.add("153374d45687af1e96d5b8b1b03a2515");
-               set.add("1536a1389a9cd4ecf5bfaac9f4333852");
-               set.add("1539231d9952fdbe0533df405c46356c");
-               set.add("15d6a88bb656579740291df01297aa5c");
-               set.add("15fbf68a7c02161beb6cad00325752c3");
-               set.add("161cd37f60e13b9850e881bac61c840f");
-               set.add("161ed36663b694184f7f4131d1d5f3df");
-               set.add("167df7bf13809a19da8ff90a27f4b522");
-               set.add("170e81af0371550ea20c827669fbf0fd");
-               set.add("177c0df08cb85a4e13bf7412dacf2699");
-               set.add("179b9694bca64255ce9c0b06a08f46e6");
-               set.add("17d55e2cd3df50ef07aff9be6b160915");
-               set.add("1835337dfceafa20029fe6e472e7c7f0");
-               set.add("185820cacfb62e34c1f6c2e1feb42d27");
-               set.add("18981fde366efeca850bdf490253f0ec");
-               set.add("18b7f1dce04bc7838f3d2b234923de27");
-               set.add("18c2d213b8de15fc11ef66f7a7ad04a4");
-               set.add("1914ab609416b8559eeefda814867b9b");
-               set.add("19ae231357c49b6bf9427fa178dc58ab");
-               set.add("19b0b447800ba36f2d4ce76264009e2d");
-               set.add("19c9120e2fb7bbf6d21d71659f77439c");
-               set.add("19c9753bd99d7f0328792a434625f8a5");
-               set.add("1a508ce5b461be1998750bdad26764a3");
-               set.add("1a77681a4646cd21461df84c49074fe3");
-               set.add("1aa169a73004fc66a932576ac2732b15");
-               set.add("1aa1f3cc21a0f6a6eadb6166d468284c");
-               set.add("1ac8dac1b547a064a306bf42e568b5bc");
-               set.add("1af11d2e99f06b69ab5103731592ae8e");
-               set.add("1af30f73640ac1f9f3c8ef32fd04bfb8");
-               set.add("1b337a115a491abfc3abcd62399704d2");
-               set.add("1bb9c002f22ccd24bfcec36957ac0367");
-               set.add("1cbb12c9b58adc33642e1165b77c2e58");
-               set.add("1d30457aa2af0f212a26b9d2c203a216");
-               set.add("1d390d2ede88fb2f77ad7e7432155466");
-               set.add("1d920d4ee2bef0c7ffb28a91b9e325f6");
-               set.add("1e09cd01462e6d4728efafc4a550a5a6");
-               set.add("1e26c7969adb5bfc507da22802f17053");
-               set.add("1e5378337317821ffa4f53e9ecf47fbd");
-               set.add("1e68b1ce7eb224dc65b39546d0892299");
-               set.add("1e757827e2e03a781905e9f983c89933");
-               set.add("1f2564b3f0d78751b4e1d5836d54f7b1");
-               set.add("210bd4536d1c1872d213995420cf9513");
-               set.add("21bdc48d9411ffc8e811e32c45640f58");
-               set.add("21d4e53c3308cf3a1e916ef6cafff873");
-               set.add("21db7fea27e33cbab6fa2984017c241c");
-               set.add("221ab691a72a6f8b65792233b7bdf884");
-               set.add("222b7613b7a9a85d45051fb263b511bf");
-               set.add("224c062a8213f22058c0479c91ce470a");
-               set.add("22777fde378d9610258e4223fb5563f5");
-               set.add("22929b4849129644531a722397786513");
-               set.add("22c31705c3948c39721ced4ca04b2e65");
-               set.add("22e355a9e573b7f6f86c7e0791647ba7");
-               set.add("2320f4b15fb78448ce16a5a625f6f8f2");
-               set.add("234467bcf00a15e7377ceca46b7302f8");
-               set.add("23e140b2126af53487781f63082615e5");
-               set.add("245d147c568faf00dfb47d9c9080871c");
-               set.add("24a5102957c91107a092704f4f166e77");
-               set.add("24b7b0f55cea9329f981f00d922cfe61");
-               set.add("24d9308fa5d88f89365760a6e54f557f");
-               set.add("24fe3f1922a6d16b21f57b9925558296");
-               set.add("2571d40a353d275cdd8a4ba6e80a32fd");
-               set.add("259a0325a52acf54184fd439d1b2521d");
-               set.add("259d90773b3387c58aecb648c2c3812e");
-               set.add("25fd0f44fbbadfb70cee0467f9b53d3e");
-               set.add("26331fa38f2af84b18df5dd1db0244f0");
-               set.add("26a5e7834018943090396d419ca64662");
-               set.add("271f29d0b199d0d3f036e8f99ce76975");
-               set.add("2762f40ffacbc78b4c949cd38101a02a");
-               set.add("2769033a0acfff04e1f427027643c03a");
-               set.add("27b1601bb3a33c7cd2745caa651f0705");
-               set.add("27e522bd25f54343584ae89e90e64ee3");
-               set.add("2815e68ed1683663820682c8e00fd795");
-               set.add("285e598a676de414661a022f72967d29");
-               set.add("2886ee93f5dd4f02b331089928520e4f");
-               set.add("28f53f74ab45da2ab83072143f0d01d0");
-               set.add("2967cd7a160b396ef96f09695429d8e9");
-               set.add("29e99fbfab8c9771f4b5a86195db0c46");
-               set.add("2a1f5f5a829badfd64e2c20cd17bd38b");
-               set.add("2a941643d418880e0e7337aaaa00c555");
-               set.add("2a9d2a64b4601046774c9d27202de593");
-               set.add("2ad8de03de84415f1397cb2d4c77fb84");
-               set.add("2af7bcae566ada617d8888f34a5f70a3");
-               set.add("2bb2cea5465ab43f9b7e83cb44851223");
-               set.add("2bc22736450a8d0efb8d898bdcf52d43");
-               set.add("2c19c0cd4c005877798821dd65a2ff2e");
-               set.add("2c39985a5a49fa07759dc880e3722203");
-               set.add("2c58d5382b8d5fdbe1800e013f200f38");
-               set.add("2c8f6954ba9842ad9fc9bb367d14cf72");
-               set.add("2d13c151bbf6e1d7d7378c86d191d2d8");
-               set.add("2df4ee3f8a2c3611b267936e47bd3d3f");
-               set.add("2e6c8ecf50ee9ea82f407a8b0acd4f85");
-               set.add("2e97a2f015b1247b01b5e022bf6109cc");
-               set.add("2eae476e3eb97e2a1ad54c5b8fa48208");
-               set.add("2f44b9347e986c91ab886dc2e508885f");
-               set.add("2f478d2efa82571d5c3e49fde16c936e");
-               set.add("2f7460de6e7581a6775f739f894d86c6");
-               set.add("2fa429a16950f6c3f19a051b3417aac7");
-               set.add("2fa4545430dae966dce186984c98d0b7");
-               set.add("3027d63763f7aca58b41d52689f38dbd");
-               set.add("302b34ea5ec261fd74a4901d041d3f82");
-               set.add("30b5952157345beb00d753425a728757");
-               set.add("3136fef31b6d0e1d9a0dbbbdac05b0a3");
-               set.add("321377ccf346be4efa1fb8658032298a");
-               set.add("325e3898dc252f6c936301412be06505");
-               set.add("32fe6eecb5e97a6ff9c4f1c005857435");
-               set.add("33197b8e7194af401da6150c68004d7b");
-               set.add("3393a92e46a045c4eaf6b9e18f7044e3");
-               set.add("33a89133876e91fccc4058627b34d617");
-               set.add("3466c5940034ddb1371c4f86dabce964");
-               set.add("348abf304c63a702e4a229db28feee16");
-               set.add("349260e7bc0291ba2e4c26d4db00bee9");
-               set.add("3507c7d2b11a693620235ea3872dce66");
-               set.add("353236b8cb07eef73d80f25e240acddb");
-               set.add("35aeed248d254fbc3542b5cd3aa9842d");
-               set.add("36218bbb51e99aed53ea822ebaa2c873");
-               set.add("3666b06f839465adc5d36a6e75066a47");
-               set.add("36fb9fb79c253ee61e498e459f0cf395");
-               set.add("3703dd15904a118a05d771e7ee6e3f11");
-               set.add("370b98cc77577db1a07021e46c21cd3b");
-               set.add("3719475cc57cf3b5312f21b1efd228ef");
-               set.add("3738564e4327367bc2f359cdbb442304");
-               set.add("37bf1e76b05f333eefc0495e4f725838");
-               set.add("38715f11bf91b5ce06494e1ddd94c444");
-               set.add("387eea945f83c9567fa42c6e150b7ba9");
-               set.add("389687548b9f05e6c99d93a2ecf76307");
-               set.add("38b1e93cc1910ecc5301502fbb9bd8a3");
-               set.add("3a0b2ffd2d4593581c52bdc1094d92d8");
-               set.add("3a99a5318497e7108995a08675fa70d5");
-               set.add("3b4573f1f11db1ffedd14e10d539aad3");
-               set.add("3bc526028cf0be42fcbb75936810d41c");
-               set.add("3bc5834ec0726b10465b67f17b77044e");
-               set.add("3bf858e6c91e0292259a886b8bf793c3");
-               set.add("3c4eea57e65806dc59dd4c206bef79e1");
-               set.add("3c7b9e1836fe07f7a4ffaea90e7f33fc");
-               set.add("3c8aee818229c48b9a882caa6de58c18");
-               set.add("3cf831629486be08e747671a14d113f5");
-               set.add("3d6b990aaee7dff0be939343711dfa74");
-               set.add("3e2d355d7fd39e54ceead835d14df7e9");
-               set.add("3e8697fe46496d41528387e2d37d734a");
-               set.add("3ea538f54677ecaffbed1ae5f2e12d28");
-               set.add("3f654d824783b4392396b34ad2b44974");
-               set.add("3fc4889ea40aea23fedc994704ba4708");
-               set.add("41145e8204991f0b644b831cd859c4e2");
-               set.add("415fecbed32f8de16ffbab8e97edb4cb");
-               set.add("41633604778611785d7453c23823b0b3");
-               set.add("41d37971a99bb08d0f5f4fdcfcd87e8d");
-               set.add("428c0aeb520fe9e77d3b464543620716");
-               set.add("42cc2865a6fc399e689d2d569c58de2a");
-               set.add("43a6db581840e3645459ce51953ca9a5");
-               set.add("43a72eab1f3f874da7d68092e83357ec");
-               set.add("44255564acd68eca32ffab8e6130c5cc");
-               set.add("4448ff245bfd8d2606b418f33797571f");
-               set.add("44a4e02e520657221706cd6d69bcfb13");
-               set.add("44b12361fee8a2385a9b90e44fd079f3");
-               set.add("44b7c1c17e8e4728fadeecb6ba797af0");
-               set.add("44d734a18b45937c3035a047f9063dfd");
-               set.add("44edf41dd7624a6e2259d8e451622527");
-               set.add("4528bda7194c6dfafada95d68c2faa3a");
-               set.add("45a8a995a3614f823c04f3c157effe97");
-               set.add("45d2f014e70681483d6bc5864cf94b20");
-               set.add("46232174087bfb178ad7cc35bfb387a8");
-               set.add("46401106d96b729d330375a63e655374");
-               set.add("46ac2356b12ed7519ae2dd5f199b7c10");
-               set.add("4790684e33d48e3dfe99b6ff7712be8a");
-               set.add("479a2848353fef692063ec37e7d556dc");
-               set.add("47a649cae70a90e7d1ae2b2ab10465f0");
-               set.add("47bc150e2585e61cf9380ed540de4465");
-               set.add("4863872b48ecad3005e7b60d114c0fde");
-               set.add("487c3163ebf25cd3b4479e13e30cba5b");
-               set.add("48c5d84e56a982689f4268ed9b50cded");
-               set.add("493a84bde424f5946290238998d64873");
-               set.add("499e8c7c38dd4d8068eefc4eb58d4cf5");
-               set.add("4a03d963b887b4ade3d574e87d111e9d");
-               set.add("4a5509929d6991507c6e136178942a2d");
-               set.add("4a933f8824eba082555515e69d3bfe43");
-               set.add("4abc93cb926e33fbb97aa0d2ffe7885a");
-               set.add("4ad536d6aee9fffe1e84c9e75698f5cf");
-               set.add("4af14f94870a2e3d47dbd78cc05e58a8");
-               set.add("4b0a7961ee650f518533f03c38ca8320");
-               set.add("4b166cec69dc9ace3a9f598674c35b3c");
-               set.add("4b5a632e55f4dbea5435e151145337a7");
-               set.add("4b797a7d23faae4daf8b2946d6cb24dd");
-               set.add("4b9e8ea91d6bd67b22be67dd40b871a7");
-               set.add("4bd7e46dd429e45ddee5736f86d494cc");
-               set.add("4beec7064114b6e49cc76cc2f71594ec");
-               set.add("4c3f47c263ea5b933ac5184466573f6d");
-               set.add("4c9b11094fa43b8a9aaf1a1568bf60c2");
-               set.add("4ca44906c21909f396774827017e007e");
-               set.add("4ca7dd633f56f76f794faf958416f4c1");
-               set.add("4d6956c8d3db98528dfbdafa4a3316b6");
-               set.add("4d84b18416836b7297b990a408a6eda3");
-               set.add("4e13b8d5d4a77393b2fbfbaebe9ea1ca");
-               set.add("4e3b029d124b898f1d11a8d15d2a6688");
-               set.add("4e9723863a06235d9339cd00912871ed");
-               set.add("4efdf67cd98424e7cb008dd09b169942");
-               set.add("4f25dd1fcb4aedb512f24758961d87f9");
-               set.add("4f86907e557c00d13b42a2393b834d8d");
-               set.add("4fdb3ba6ebc9b3e9ab133c15312f995a");
-               set.add("504bbb5991ad94728e6b73c6ddc6c476");
-               set.add("515f449c1e9fd279dbdadf3cc38fd008");
-               set.add("51d9a0c78486de462af6a490acea1fcb");
-               set.add("52032bb8c1acb8bf7320aa73babd2e50");
-               set.add("5203feb9b0d422a38052d9df4103e3ab");
-               set.add("5222c37a7e8618d4cb43ce8c4a188129");
-               set.add("52731882ea73ad5b1d39c25e2969d9aa");
-               set.add("536af35745c20e4ee25486a31c2fb57c");
-               set.add("5379086fb93464cbdad4459101ed4d07");
-               set.add("542f3505366c2d6575e73064aacf536a");
-               set.add("54350b63fafc31af32bdf49cf0bbfda2");
-               set.add("5498ead583ab6cd6900a533b1cb69df8");
-               set.add("553eb9e396b2f304f963b717bb3a9059");
-               set.add("55c5181d0e1b170cfd05c3a9271b3bc6");
-               set.add("566ff170b185c5cfd893030c97080451");
-               set.add("568c906117202c4d4451dfb3be697921");
-               set.add("56a9926b91222c8943640da0b642d617");
-               set.add("56fcddb2fc61ab068e1ce98a226fd34d");
-               set.add("573f9b1aa16e771da95df44fe3a62167");
-               set.add("5805ae3e1c5fa9f7a604152c40c9d06d");
-               set.add("5844ffd995e179e21476fe41a72c7e85");
-               set.add("5866a0ca3348c1b406e4a4a869b183ae");
-               set.add("5922a04c19e52d4a3844b61b559a89d4");
-               set.add("5957b399b3380e097b70cfc09bae1bd3");
-               set.add("59785d3feccf91b7a9fcd96fe5e686de");
-               set.add("59cc15fde8f2bab7beac6a9542662df3");
-               set.add("59ef8fd572ad56b7c00092f185512c0a");
-               set.add("5a26e5d6effb9634941bbdaecf1cc4ce");
-               set.add("5a94fedb054c29331d22c4442ad619a6");
-               set.add("5b1a41ab325cdfb925f500868f77e058");
-               set.add("5b20fd5088ed40d65a52c38fbe314373");
-               set.add("5b3510c0aa53405e1fbd7a67b3af34fd");
-               set.add("5b96ce711afb37fb511e70ac12cb717f");
-               set.add("5bb8c694f0d7e39aceaa7fe7a885a6e1");
-               set.add("5bc7dae98ed248bc85f4782783c7a383");
-               set.add("5c1e091a898470db28aaddc968071a00");
-               set.add("5c603c37c8ae3b7441a49bfdd93a2426");
-               set.add("5ca4eac1f0b43f03288c19c42e1ccb2b");
-               set.add("5ced682df2330890f2239e8da8d33061");
-               set.add("5d437ac21a6da33b77c980abef5af0ac");
-               set.add("5d4f136bcd4f5f71e0402819f2f666ea");
-               set.add("5d9d43530d78a07475063de4f6b82578");
-               set.add("5e8973f53dfe0e36537e7d88ac84cfaa");
-               set.add("5e8b973df438112549cbd73b38240094");
-               set.add("5ec17176ac8ca3ffe5c7707d4b33aba0");
-               set.add("5ecdf016b2374b2029c58dce498548cf");
-               set.add("5f4d8576e9299aecd4ece33f8b4ffb3d");
-               set.add("5f5bc13ecb72cde7c4c6e89279e836f0");
-               set.add("5fc7b23ca79086fde585ac92b8ddfa61");
-               set.add("5fc8dfad0c6503b16fcbdaf2140f5bd6");
-               set.add("610b21fa92e08d26b0ebbd27ac406558");
-               set.add("618c82b1f690b74209a68062f0b7f50e");
-               set.add("6214548d7b510154960ca3d23da4f38d");
-               set.add("6244a9533207c9f3d89bd48d2c946d72");
-               set.add("628475d3f98ce21920983b2335d29771");
-               set.add("62b5f08d8f9087672b45485f5177b688");
-               set.add("62c0ca2c1be43447418c673a27f69a53");
-               set.add("62dd2d23b56d1991111028754f7d5718");
-               set.add("62fe634a6ec154d4b675a8944ab98a7b");
-               set.add("638e84fef470490263300ed27293aca9");
-               set.add("643181e6ca3418a86b5dac6858805839");
-               set.add("6431d2ee351952b0ca1c8e24aee89d9a");
-               set.add("64cf9d529b625818f06f910fd5a51ebc");
-               set.add("64f5901476b159bd9c4f5ed9aa2b4cc7");
-               set.add("651c5d94aa8b742ea6bf89eb4760d88b");
-               set.add("6535664e59493ee6581d3ec49d666a05");
-               set.add("659bd0331a1348d14e9cd72006008d5b");
-               set.add("659d8f3f58c60862ec21306475d5b86c");
-               set.add("65ed980ed9e129e301e3c219be11999c");
-               set.add("661c50f934f8b021101df91c063c2662");
-               set.add("66289df1c8d41414638696d9847188a7");
-               set.add("667f3707995e365e210a1bb9e1926455");
-               set.add("66ff6174d6a5b1c8a40637c8a3a8a7b9");
-               set.add("673d52c40a3153d07e7a81ad3bf2027c");
-               set.add("67c803799e8e1d877eb3f713dc775444");
-               set.add("680708ce5f383f0c7511eb3d7b7209d9");
-               set.add("68ee06fe147e143b6e1486d292fbc9b4");
-               set.add("690da28e475ebd2dec079e7de4c60719");
-               set.add("693db94b6ffb0c1afa7b82499d17b25f");
-               set.add("6961f9a08f066d0318669a9c9c94017d");
-               set.add("69a38fb26f994ccc04e84e66441e0287");
-               set.add("69f5b82d6acf05cee8615ff5d05f7921");
-               set.add("6a1e040ce59176bcbe4c47654dcf83a7");
-               set.add("6a26a773a6223c79697e12838582f122");
-               set.add("6a6e0e4350ef8d4a3489aa4398bd674b");
-               set.add("6a8abe4a6fe236bf93d9b85681db2c0e");
-               set.add("6aaddb50ae45f1006852479932dfbd54");
-               set.add("6adb0778b8930a8e6a2f1e99de2ef074");
-               set.add("6b54ec7203070bb29e514eb7d684e380");
-               set.add("6b598530a066271059bc94c1fa0cd7a1");
-               set.add("6be4f1c5af0ff30131481d009e87133b");
-               set.add("6be8cb8a938f1ecef2b36c823e8e6ade");
-               set.add("6bfe9b78813cfa4014e630454f7a06a5");
-               set.add("6cb4d52135f005a2c7ba8ccc3b8781e3");
-               set.add("6cd5f8dd36648fcafcfecc8d5b990e9b");
-               set.add("6cfdb07efc0d3c1f36b2d992263253f9");
-               set.add("6d95c9c12fe5498af055b013bf7ceb7d");
-               set.add("6e8f160f1b2b54c3c89b81c4f9a98283");
-               set.add("6eadec5ff4cb05c8ef1a64d2c94d627b");
-               set.add("6eceba3c0a19666f5a9adbc13ceb1ae7");
-               set.add("6f47bff8d62f5bd51cee156f78e8cfcb");
-               set.add("6f484725ba3abcadfe8fbfb4e6e83db6");
-               set.add("7031b89c62590b6a41e7ad524bb0a308");
-               set.add("7058fc792efe7aaddf8a0323bf998f72");
-               set.add("706e502b5a6db25407c2565457944633");
-               set.add("70cfd491765d3e4e6a4e4b1ccaf9c343");
-               set.add("711e7a11c4be36563cae1b71234dc414");
-               set.add("71794c9ad0e60b6d0dcd44b51c3704f0");
-               set.add("7193a4c6f286f7b86b18cc7908498d06");
-               set.add("71b17eeb05fd473e42aa5c4e51e47a15");
-               set.add("71e0014aeaebda1113a12cecb51fd20c");
-               set.add("71e2d06eaa0ab3ae59d0f7b7ef20fc31");
-               set.add("71fe7c7f2a54587c2278b3e630faee56");
-               set.add("729ba9dde60740e6d5e8140fae54f4c6");
-               set.add("72b5be92417a4a6a09f5e01c106cf96a");
-               set.add("72c0c6f5a653bb57a1aba44e7edb202b");
-               set.add("72f6580c0aa3b101acffce59adf7809b");
-               set.add("730ac94082f25931179a313af186b335");
-               set.add("73243d82b8157406558562b5eb70818b");
-               set.add("73371ae751751a5998c3bc8de577b83e");
-               set.add("733c6d4df3b6781473ba0a3a169ca74a");
-               set.add("7376d2568492e6f6c0fadab86e22416b");
-               set.add("737b791d27930ccba061fa36c4046208");
-               set.add("73a47e531e9c0ddf5a334c40508f6361");
-               set.add("73b2859aedfe1bf317841bbc150e0491");
-               set.add("7413c1de6d5f286055e8244101da306c");
-               set.add("741bfaabd99301c5503fd36d17912627");
-               set.add("7423f1b74c8367863a1071bcd0864d42");
-               set.add("747ddec4bc30cbde2ebefac7b8df466c");
-               set.add("7494df6c5102bbfb6e48c9b30281325b");
-               set.add("74c5cb4f540e2c9b27ae60dcc8247eae");
-               set.add("74f6a218f8877fb76f74eacc9df32fc6");
-               set.add("751ff3c7f3e77c8d3ba24c568fd11845");
-               set.add("757c05f3194d6d4b848b83c0e3e5f1a3");
-               set.add("75f724e20c3f2e26d2de13927fbf78f1");
-               set.add("761c6d190a411231fccfeef67f08eacf");
-               set.add("763eddbcb1f6787b3350f65c64b44ba4");
-               set.add("765a1a5d8f09ddffec749d3a6920c4a7");
-               set.add("76acd0d7e4d38152771480bedacba209");
-               set.add("76dc5d4b4f65aacb1dfc1a5a8f61b023");
-               set.add("771cc4503662f2fc2c5f15f46e7e58b6");
-               set.add("772a3193a3cf3e18fd2058c3f45c35f8");
-               set.add("7823311e8d60374d4b37c50d927507c8");
-               set.add("78282abebd03a40f2dd21f1505a5f789");
-               set.add("782e12a60bbef943f13f2fa1af1e39f1");
-               set.add("782e6df5b10a60b26117e0648e76c6c4");
-               set.add("7875a865fbaf33ba617cdb7c7f0f7140");
-               set.add("78ee37b2f7acb3d892e54f0e9d2e0c14");
-               set.add("791f7d21ea119ccd49df31b2f614a0d6");
-               set.add("795036eafd006f62ee5a68ba1c309865");
-               set.add("795fcaf2d6d9e1c37a4c283876f26cec");
-               set.add("79688fa15c424b73454d9cd0a070472f");
-               set.add("796c759040e72b8efd4630754bd3f30b");
-               set.add("798ad9ae186a9d89e6f69e065bc22a86");
-               set.add("7a2a604d923e5bd87846902e47acc438");
-               set.add("7a39ea82b6b2bb75f9f6a7b817dab9cb");
-               set.add("7a62872422cf100af636b434f4a0b307");
-               set.add("7acda66f5d077fa708de7d153882b97c");
-               set.add("7b1aca3caab3a61147d4ebf5f7971d42");
-               set.add("7b5bc0bfd0de5126b4d278aa5775abd7");
-               set.add("7bd0735d3b5d579f0c97e11309a12451");
-               set.add("7be2fb055d29d5c8e42c559295ee8113");
-               set.add("7c14e11e0126b310217db2488f898127");
-               set.add("7c4ab23d9b1db15ea1f49fe017edf346");
-               set.add("7c6080928783078289d9a473efecc134");
-               set.add("7ccde35451846731eff4ae16e40f661f");
-               set.add("7cce66eec1313c11f5b9005db8f2823d");
-               set.add("7d40723bc0200f13675626309559ce6d");
-               set.add("7da7fa494528cd0836f9988f3e7ada96");
-               set.add("7e3bc2bc33f34ad791573e94021381d5");
-               set.add("7fb1e485fa41841779a0a1f95a2b7cd8");
-               set.add("809b63d7a153ee60272ffc224766fd72");
-               set.add("80fc9ff72737286ad64fe7de1524c799");
-               set.add("82b602bacfe681cee58d5530ac9e8b99");
-               set.add("82f69b66499f2bc375467ee933fe4577");
-               set.add("83243e87941f4ec7f8841571dd90b3b2");
-               set.add("836481fe9bfd7612506e0545bdcf279d");
-               set.add("83a498353a59dea68538962eb2642ba8");
-               set.add("83eafb190276935630f43cddf3d78143");
-               set.add("845c54809778f5b838e32443a7d44072");
-               set.add("849b5885cbf965447675610ee1d0dca2");
-               set.add("84a895acdcd487244b6803082036fad7");
-               set.add("84bdf63a67691194e37082e3f7f6d712");
-               set.add("84c99be383e4ada00f4e6bd335774655");
-               set.add("84ed2fb163b5b2525a9a731056ffd144");
-               set.add("8517e14d6f657f1244c0344d4f1a828b");
-               set.add("8541aca6dd06f2dc6984d5e1b664900c");
-               set.add("85cc38b178bd721bf7225144dd301b0f");
-               set.add("85d00ae1ce88ace2bc6918750a97502f");
-               set.add("868af0eab556081846fdbff18df40b28");
-               set.add("871f7fe309f61ec7e45e4b29833349d9");
-               set.add("878e7848ab58bf9271fc04766e969c8f");
-               set.add("87b872efe9433147c61d5d2c3dcca14f");
-               set.add("87cd3518578a2ef76341b33f9c95198f");
-               set.add("87cd3a0a86f398ba1026cdb969e55090");
-               set.add("87cdeb3fcaa050209091a1600ce1df11");
-               set.add("88008ed2e9b600fa2e453390688aaa7e");
-               set.add("8833c25743e0f9725ca22dbc6e54d1bf");
-               set.add("88693556ff80aacd354c1948675c0674");
-               set.add("888664c26a3296f9571d561723b44255");
-               set.add("88ed07b96422ec99767fb35bf6a51966");
-               set.add("88ed43ef6f483b9a7e34c34b46335dea");
-               set.add("8a2e4445364c3c9151dcf4622c6add51");
-               set.add("8a73ce2e18dacf250a961dac49338407");
-               set.add("8ba75b207cc0bee8ec624e9f33019161");
-               set.add("8bc592cc7aaa336637b9c82c43cbb081");
-               set.add("8c1bdef25d6a6df69c303be204748da9");
-               set.add("8c8b182ec0845de4a5fed3245e5601ea");
-               set.add("8c8d724fba729940b1234e58e64125b8");
-               set.add("8ce47ac01efd8c0ab75ae5371ff0f7ba");
-               set.add("8e1600a04363c86199d660ccb7085735");
-               set.add("8eb548ee8bf98a6426f0b5a11e32c88a");
-               set.add("8ec54a8bd1ab30f324eb0f03ef79d097");
-               set.add("8ede1653debc5617deae6a7632c18502");
-               set.add("903594c774fd5be01132f559c00778b4");
-               set.add("9079d8f7488bca4504d58be0bc76deea");
-               set.add("909a1f7458c8f1f1138dff9ce019fb6c");
-               set.add("90b8dd2817509c2374b20a1975ca1a54");
-               set.add("90d0f3d40769a6219608964628d40e55");
-               set.add("9104737f888d85480d0cc9aef8587e77");
-               set.add("9118a19b2abc5d1d624b10f2bceb18bb");
-               set.add("912e499f9a4a55f11133e01b33542ad1");
-               set.add("915fcc373ba5d8a13814f236c1a9e4e5");
-               set.add("918ca652867678984ae1149a3b5467bd");
-               set.add("91fbebd600bbd88370994b739ae8e1f8");
-               set.add("92fc949a982c897ca4a17750e2ee4afd");
-               set.add("93c0446ee508efe75a176035986627cc");
-               set.add("93d4329e22ed50d3502b2d0bc117baa6");
-               set.add("93f33bcfa6201057376a3fe53eb29959");
-               set.add("944b74b5ff9c617312ca2b0868e8cbc2");
-               set.add("94bacf4caccc653a74a68698be0da4bc");
-               set.add("9572f2ed73f01766b0ede9ec3d52715a");
-               set.add("965e3d6087eec8e991175aada15a550a");
-               set.add("967119411833b80c9ea55f0e64dacad6");
-               set.add("968c5025a59e782d96682b09c4e94746");
-               set.add("97824aa7746b63a32ea6d0dedb3e3f84");
-               set.add("97aa914f28281f67ae3ac5222566c2a0");
-               set.add("97f5a198489144a2f306456c1a346f9b");
-               set.add("98a7e979d454d7f46ceb4a4283794d3c");
-               set.add("98ff8ee9107e864d7c52d631070fff3b");
-               set.add("993739fad4a47f34eb65e3ee48d15c09");
-               set.add("99bb411f89eb34ebfa59900de36581fc");
-               set.add("9a13940746bcf4cbe210150833b2a58b");
-               set.add("9a3d7af6ccb7d277e3ed582d8932b5db");
-               set.add("9a76e86b4275099983c5ede78626e0dd");
-               set.add("9a9caad4a9c674daf41b5cb616092501");
-               set.add("9ae6b0ad5010301ea610f49e008adf8c");
-               set.add("9b6033bd4470408ecf2949d88531d6a1");
-               set.add("9bfc7853ff00c7ea0e2f8972dc2595d4");
-               set.add("9c8bdd485912f9d9eaaba3d5872be726");
-               set.add("9cba07b76b4e79c0265deda5df2e2381");
-               set.add("9e082b9bb6c1361965c0f0e06f051acb");
-               set.add("9e24dbadcadc67447af65d571ffaee55");
-               set.add("9e6a5f03a8b524ffa3264a3f32818e1c");
-               set.add("9ead837b9e4f8c922f74ddbff0d2b88a");
-               set.add("9fb7aa659c0475d5dc72bb35567247c9");
-               set.add("a0006978c9a542518b425c0caa67042b");
-               set.add("a01bdd6575c3cad9f9a4cb8aac9c716a");
-               set.add("a02500e28eeb7e56e343607a822e2a7e");
-               set.add("a05c1799e061712459e6c46f533263a6");
-               set.add("a0799831bfb3f9b77b63c03fad39cce0");
-               set.add("a0d4911294ccb20c0920a3cc6705f326");
-               set.add("a11dfa1b02b1671d42b1abc858de2f2e");
-               set.add("a11e237bd6d3c4a4ee8a7ee791444ad3");
-               set.add("a148d83d50cf0852f6c08ceacbea0296");
-               set.add("a1d8b81c03860585fb40613e828c1b2e");
-               set.add("a20c867fdbb93bbe1d1231d9a8ea76c5");
-               set.add("a21e0795fe0977d50a4496ba60e685e1");
-               set.add("a260bb11468a2252a8dedff81f5672fd");
-               set.add("a2b01bf43bc1d403e6ab3a9b71f32484");
-               set.add("a2c15ded3e16d9aa12b9c07f3383c098");
-               set.add("a360659a62e2e34f4edc89ce5e8b8a0c");
-               set.add("a3a985e0ae5a9c96c74b8ee647101439");
-               set.add("a3bf05e31288667a43b4c39cc0604c97");
-               set.add("a427397e35b28706c5b8aa50e8f92a1c");
-               set.add("a432e1b27b7d9814368d8f4071cf2dd0");
-               set.add("a4b4800082feb6fcaf1cd56dda3a28c6");
-               set.add("a4b83742cb45f1dd9130250cd72c460e");
-               set.add("a5a8b20a222bd51b707e50303fdae33a");
-               set.add("a5cf16d12d611ddc5ae1b010083690ad");
-               set.add("a67b1720a7f123bb943c3f1ee74b8f00");
-               set.add("a6b31c2e971254f85e231653abdc3a06");
-               set.add("a6f9fe8c867cbef07730db4d1d461960");
-               set.add("a706de20cf1a31e379d98807d1cb2060");
-               set.add("a7b5467023706646a6b8ce2602bba226");
-               set.add("a7bb7f7f68b538fb778856d4fbda50b7");
-               set.add("a7fee39f2151056370c57d383e486348");
-               set.add("a84a5f90f1083075081f135c74314bff");
-               set.add("a8a6b73342c6a92638e41b86e6838958");
-               set.add("a8f1c8b28c017186778e3074637e52ef");
-               set.add("a90e513d9b2d0f55b875c3229e2d9816");
-               set.add("a9e697026e08d1a8765497a9569b04e6");
-               set.add("aa3218984177ce38bfdf06e38fbaa64b");
-               set.add("aaa0291aa11c304b3a2300d4025db74d");
-               set.add("aad63a3685d9f906a7c6c8716d626c0b");
-               set.add("aafee591c7a3ae5f3c4f44f2d0f8a70f");
-               set.add("ab85503c9acb730fcb9ed2a4dd74e2d7");
-               set.add("ab8ad454409604808d1b444b068e602d");
-               set.add("ac4c8af4d29676c8c79ac9ef180fc5df");
-               set.add("ac4cd34387b04786cc5315b464006ec8");
-               set.add("ac9c443698ac77bcb3a73a959f6ca0f0");
-               set.add("acde934989eba2c7fef7cce095ce85c7");
-               set.add("ad053830e5d0bb7e736ab98a8f3f1612");
-               set.add("ad08d0d2d84298deb08b4c4a1cf62f39");
-               set.add("ad0a1f2424a1b831f9777e638e8f829a");
-               set.add("add039636134cb123908df5053304f3e");
-               set.add("adf89cbcb01a2ec6d4afb24914790a67");
-               set.add("ae1ae7c31f46325ce6a28104fa7070e6");
-               set.add("af8c83664fd6eec8089ef1992aec463f");
-               set.add("afcd59e32572ecb7ebe2d9c993d5fa9d");
-               set.add("b012115b4276791c5049dace174933f7");
-               set.add("b218489d2d4d7ddbfee2f073e238ff30");
-               set.add("b251290e1d8690953d9cc0c1ea3bac6f");
-               set.add("b2843a551894de318b80f790565dcfe3");
-               set.add("b2a414aeb8800edfa8945863ffa5fbc9");
-               set.add("b2d68ad2619bbb15a827b7baca6677b0");
-               set.add("b2fe203ee319ae28b9ccdad26a8f21de");
-               set.add("b33afd95fbd9aae903bbe7cb853cbbf3");
-               set.add("b385f0f86168fea4f5f456b7700a8ffe");
-               set.add("b3bd462a51847d58ed348f17c8718dca");
-               set.add("b3d1befe2272f354b85f0ca5a3162dc8");
-               set.add("b3f50d0da11772487101b44ae8aeb4ac");
-               set.add("b42625f51295803ae1f99daf241c0bd0");
-               set.add("b49cdae29a3394a25058e94b4eb5573c");
-               set.add("b4ce8f683ec172aecf22cf8e516cce05");
-               set.add("b4ffd04e41c1b8757149777a894f33f2");
-               set.add("b5a1510fcf6dd596e87f497bfd5317bb");
-               set.add("b5a75d8c18db0a96a3423e06554122c8");
-               set.add("b5d312d32267bd15ee43f36077feefe9");
-               set.add("b6645bb07f58754b8838d54e24562c06");
-               set.add("b69831350ae6a3dfc18c0c05db0c25a8");
-               set.add("b6b70e569be8de2fdecf285730319735");
-               set.add("b6ee0ea7d82d3d7e0ab8bc62057c0385");
-               set.add("b707a076a44ca9b3e6b8dc1dcde7d877");
-               set.add("b77df6081bbeb4da02c075befb4beb9b");
-               set.add("b7bdcedd416cccc742643e8e244f6282");
-               set.add("b7ea4565381c6dc534cf0af8305f27ac");
-               set.add("b7f3fb01d8c41525b103fc5faba23362");
-               set.add("b80bf674f28284a3614596800ec02b3a");
-               set.add("b81ab08e53854aba9462ebbaee1ff248");
-               set.add("b87e12381d354360f7945299ad92a4d2");
-               set.add("b8bd5737f81fddbaf120ebe43a0010e4");
-               set.add("b92f1e45fdb62c1fd6d7f3e774b4b610");
-               set.add("b9769bfc0d93a570d94fa130de750b1f");
-               set.add("b980c7a501ce63ebb6e20b04348298b7");
-               set.add("b9e4b006db3e1597b21fb7aba13f79c2");
-               set.add("ba031cf2febc03ddbff278200dca45a0");
-               set.add("bb0f54037f5ab70e96c7d8ba7f57ca4b");
-               set.add("bb2eb6b3f7383d7ef521409fa7710385");
-               set.add("bb3eb6a5dbe0582b31f35e5dc2b457a7");
-               set.add("bbc22cc7f6851e06fadfac40a6225419");
-               set.add("bc4d886813fe2eba9ccd7bef0b4d05ca");
-               set.add("bc8162e261658ece13f8bc61aa43ab74");
-               set.add("bc89ec14f4629c3afe1e286b07e588f6");
-               set.add("bccdb576cb50b44ae34806c2a2781c52");
-               set.add("bd10772f1554ccd6e245d6869d84efe8");
-               set.add("bd969e90ff4b1362e2f24553124a66cc");
-               set.add("bde145f138ed13399b8a747da20c1826");
-               set.add("be11a726b56813c4b1aea0574c8302b2");
-               set.add("be1cfa6a82eb4fbf7186efd6ddbb0161");
-               set.add("be5f3dcf0badef84475741cc47e2ddc0");
-               set.add("bf316e6ad7e72f7dc4033207dd033c76");
-               set.add("bfadbf9c4cde6071e54e43a5da64aca9");
-               set.add("c029503ea85e7a7742d826bc184d65ce");
-               set.add("c049499ca03fd69115352e5d4be72de7");
-               set.add("c0524ddd036991b4718f6ab0ab4e4f42");
-               set.add("c056cf25df6751f7bb8a94bc4f64750f");
-               set.add("c0a9c2fd4f0ed2b8f2bdc7f2c0a7a7ce");
-               set.add("c165e480073bcdccb3fad1c5e507159f");
-               set.add("c24ac1ab205eb3fbd1c64841f0f288d6");
-               set.add("c26987c1c7e95810bbb6f2e284861494");
-               set.add("c295b3b2493aff880daac1532a063b72");
-               set.add("c2b18390691697037d5698b683eee361");
-               set.add("c2cd680e3032ce3a70d3bffdb7d0582f");
-               set.add("c2defcfb93d217c4be28aa27ec62978b");
-               set.add("c332adf9d689dcbbb38fead7098781b3");
-               set.add("c4d8f1baafe99501b0d80e8a9c8c3086");
-               set.add("c4e5ca3e96b219539e3e61c3c4fbe5a9");
-               set.add("c5e1448d1fb24ebcef161ee65f21a725");
-               set.add("c60db0ccfc2a22a152f7470505eef8d3");
-               set.add("c65e2561352e75a66b5738268b1d126a");
-               set.add("c69c01ed9b781941561c3a9dcfacf7ca");
-               set.add("c76bb0011d2519fc9e3af85de593e8a9");
-               set.add("c7a946bb164a3f642e4c5f1b7af337f1");
-               set.add("c833820441cbbf28a25d1ea7934ad6f8");
-               set.add("c8762972b9325b7ec040c782aa9414d0");
-               set.add("c8b1563c45f4fd4dc8ba5fafd5c566d2");
-               set.add("c8f2a5a0533de5eae8d1d01da8fcfc1c");
-               set.add("c94045226f625ab9a507552f64892fbe");
-               set.add("ca365baface31f6167328e65a0aec03b");
-               set.add("ca3dc74a6eb57042ea911afa05b1021b");
-               set.add("ca5b57fca35c5bfa4281802b13381d0c");
-               set.add("cab05efb1584bddbc5e4f064c1628a13");
-               set.add("cad2db4a8a73a867a6cdacceec4044ac");
-               set.add("cb6b65a06bbb9ba5536936188a08d836");
-               set.add("cba49b7c8d1982635866a32956861df3");
-               set.add("cbd94e882bdb84ec79ea2bebc1eb4aed");
-               set.add("cc49ecf163d383488b44dbb17dd5b4d9");
-               set.add("cc4bcc37de4d7bf87acea95ac914997e");
-               set.add("cc9300ecd7f2799c750ca3efcde7ce20");
-               set.add("ccccf43f691ed8bb94ac27d3eab98659");
-               set.add("cd0d8952d3e5742f4bf62195e4b385ec");
-               set.add("cd57964f0a86f3c9afbcca44733081d2");
-               set.add("cd80d4f5366cd31ae31e377c636a773a");
-               set.add("cd987a30667f7ff04a5852fd3f15fe3b");
-               set.add("ce16d46a26c771b1adbff14cc7272bf2");
-               set.add("ce43a9cf2d81a1e09237ed2279ca04be");
-               set.add("ce7a500ffd8f5925bea7a48401fae95e");
-               set.add("cf3894401e317e2545d0ae284802291f");
-               set.add("cf779cafecefb6bae5137bb77582e7e2");
-               set.add("cfdbc0be3829a6d55a5403ad92c77bcf");
-               set.add("cff24b5ef480cd58324e927e4ba0ed37");
-               set.add("d05a83622e817871306a3878a9d867e9");
-               set.add("d060e6662cda17c2c523c74963d2d556");
-               set.add("d0b058971d8a20e840de043c68c140b1");
-               set.add("d0c122a8a62cb5728f1423816b26c49f");
-               set.add("d141ed3ad5b33d6f92c976ad8d518b3b");
-               set.add("d15c7bdb5fc7b9316d1cc60a85acdc64");
-               set.add("d1c8ba5392f01f13dfef28e4ecd11cc2");
-               set.add("d1e661c0bfe1c23ca4e91cfa0a40a9d3");
-               set.add("d25a8aef0d42d7a31783e3da52dd4ee8");
-               set.add("d26ef38d4ea39ba85171f444a8947443");
-               set.add("d30b7d8663c7852f2be21d886b79a6eb");
-               set.add("d315c862f290b99466e3d406d3104413");
-               set.add("d4007ee1fd6ede4a148bdca7ab778dd3");
-               set.add("d4805374b5f1ece75c0dd51d6283a0f6");
-               set.add("d55b77d76f6ece8bbd33cb2afdbd040f");
-               set.add("d570cb3cbfe88dfdf086bb1ab9ef76f8");
-               set.add("d587ebc9902ba2620d52a610441470cc");
-               set.add("d6196bfd55d758dd5a4899ce84cea85b");
-               set.add("d6815ec0b3e12fea0f470c01c0da3888");
-               set.add("d68971ffd271de2ddde6ac10c2817451");
-               set.add("d68ff175d25d083eee4f31bf0701a0d8");
-               set.add("d7fca16ff4e4ed99b72046f99533eef3");
-               set.add("d815d7a8dd0446ba21ddbc37d3733f36");
-               set.add("d8d40312d0751951b4c45f2100379950");
-               set.add("d97e0d0fbea2a015d5e7ea229b99a6c3");
-               set.add("d98c6a23fafafb0f9981f2123b1a1938");
-               set.add("d99d6bfaede491ceae109a644cf54098");
-               set.add("da0f523e815ce990a3a5f5b5574cec4a");
-               set.add("da686b7f2a26a36051b273bbabdd7ecc");
-               set.add("dadb54d4a8ba762a8d2a2fad5fcd7582");
-               set.add("db03b5399e1a324660934ad81036d987");
-               set.add("db29f48ac45b41ad389b1b4e8e30f553");
-               set.add("db98a87e4be1e5b59f589335e1509996");
-               set.add("db9be69a1dd929be69406f9e75533fd3");
-               set.add("dba45dfda4d06aebf3adc194ca4ec35d");
-               set.add("dc339714def04ec3e5e280faec8445e5");
-               set.add("dc3fb757715c96f7c629b7712d87ca61");
-               set.add("dc5dabf20b3fbee0d3a0b1d800c74d4f");
-               set.add("dcc7b2c56f358641ea9a73c6a81479f5");
-               set.add("dd922d98ecf5096482946d8671b647e3");
-               set.add("dda8214d7b53392f8ed9fbe4178e90b9");
-               set.add("ddd37af5af0a69bed06bc50cc0a6f4c2");
-               set.add("de8d217fad9883d9bfdee5af01472971");
-               set.add("def34fc0fd41527b300d3181a70cdecf");
-               set.add("df00d9361332c48cba23bfcd41e799d4");
-               set.add("df35772f10769bc28701c488d33e89b2");
-               set.add("df769f9dc2477135b0c4320e7e7b4c2f");
-               set.add("df95377a3f69b8fbe5dcdfa041491717");
-               set.add("df98c3766238aa84f9a9dd92cd73fe72");
-               set.add("dfd019d69302047a67434458d0fa8952");
-               set.add("e037a9e26a8b319437ab7c962714dc56");
-               set.add("e0d2f02d29a965fafd85a4ae6ad37246");
-               set.add("e10e651cd85e41be3402f51885bbf107");
-               set.add("e162d7b2e436ae6d369f4fbaf53af4b4");
-               set.add("e176177a2b64669a6bcd1cf8beb35df2");
-               set.add("e194252a63a3433b5a5278f68678b7dc");
-               set.add("e19d16546c555d073454ea56ece1cbd6");
-               set.add("e1cb375938189d4090b000ab41c77a06");
-               set.add("e1ce2428389f0c2356881e626f161ccc");
-               set.add("e27c22419443eb612af1620f4c8be007");
-               set.add("e2a5adcdd7b01611736b6b74f8c506ee");
-               set.add("e3084721ba7ae53996337e82c5f469ab");
-               set.add("e35f4cccfe57bdd7338dadeba55609f1");
-               set.add("e39a2ef2eaaaf7ba74623f14c917ee1d");
-               set.add("e3e11cf57dc3f1c6ca59acb06370698f");
-               set.add("e4557f7733332200116b753408cdb966");
-               set.add("e48c96d6025b38addad2278f24c963ef");
-               set.add("e48db7db130af48cccb2d830d3cbaa14");
-               set.add("e4d169990e34bfeab0c6a780d6a49d58");
-               set.add("e4ea1f6b01c9cdcf9e550792ed336384");
-               set.add("e4ee8ada1fbbe886fb25a7f484609690");
-               set.add("e54846d325334547923d8b64da70f529");
-               set.add("e56ccf6eca77d62dde88c895abfc1c1a");
-               set.add("e591790779db1c866b179d6f85b09dda");
-               set.add("e5bec4799ceef43816054f92de9652b5");
-               set.add("e5db5832d59e14d6999144fa8cd10e3f");
-               set.add("e611fb9e857f9bee391056e1f971a0aa");
-               set.add("e6321fdd099d70352883b45f6c2a20a9");
-               set.add("e682fc42ee7ecdbf595116293cbe8a6b");
-               set.add("e6ae48418d10883fe9657075b476274d");
-               set.add("e6fa2a139e5c56f8f483aaeeee0b7fbb");
-               set.add("e77d3c78240ec60f7f4dd67a2e71085a");
-               set.add("e78ad15fb1fd450f9221147e458b1abd");
-               set.add("e7a1dc89a6cab821776ea61fe6ba10f4");
-               set.add("e7df074666f6caa44b798342bdab6230");
-               set.add("e7f25163d78c2c658300cd0f9a8a3b04");
-               set.add("e80f22347419025053de7da1f07912ec");
-               set.add("e828123fa3cdf86dc0fe1b5c86d7c87d");
-               set.add("e8764c00097a0a1254f43a16c98a1d7f");
-               set.add("e89df60deddf270cbc2232bbe26420d1");
-               set.add("e8d289f3c1aa961cf4ac8d164e286dde");
-               set.add("e9051eac7829dc1a95987230fb21d2d9");
-               set.add("e90846d2c3e16de5ed5dff4c21356edd");
-               set.add("e954907cdfba1cf07f19f64af5cf45b1");
-               set.add("e96e004e988b8e36b2ab9ed1b0f65649");
-               set.add("e984d3924451d3498a3efccd845a77fe");
-               set.add("e98b4097ddb057755e561c33a0f3428d");
-               set.add("e9a2ba17cc4b93063d61813359fd6798");
-               set.add("ea90b42f6ada6e0ac5d179af4129022d");
-               set.add("eab4231af5b3ffab13f9a04b8aef0fad");
-               set.add("eac17a7d30d24e60e6b2ce10059b37a0");
-               set.add("eaf3af4d0b61df60ee8fe3a808de6ffd");
-               set.add("eb3178d36a578fd8b430ea82429ee145");
-               set.add("eb4fbf9835a3584e6015260f0dff2174");
-               set.add("ec3a9437b1481db4d8cbc3b4fc0888a1");
-               set.add("ec47d133c23dba3d015ae730a1b9659f");
-               set.add("ec6d321581a133fee9766eedff4db9d6");
-               set.add("eca16f6d986bd893af3c4a97b99df623");
-               set.add("ecf09182c51e5110d636828364ba3ee6");
-               set.add("ecfbf6f7017f0981ba6d30331c9dc870");
-               set.add("ed1eaef061f0d30503a64f27d8ea2825");
-               set.add("ed2e4441ad7dcbe0a5d3e62bc31aa9bc");
-               set.add("ed6304572c0f1283fd06f9c09ef32b61");
-               set.add("ed7d650fc0f5de8c9da107e53025f220");
-               set.add("ef405c5b0de638c01cf57c379aaff45b");
-               set.add("ef5ec03860cd32e910a3ddb2d8740300");
-               set.add("efdc8c21ee843f98a0dc08ef694b6db7");
-               set.add("f0111af67e822944e1dc1ab24e5b8458");
-               set.add("f0e8026289bc1f9109b25f4599556aaf");
-               set.add("f0ff5a7aa6f4e8785fa406636618c01d");
-               set.add("f19a809facb46a7a094c17039126eb3e");
-               set.add("f1c7524d454c25cdd837662a80709030");
-               set.add("f202d26f911074235ac8e4a5c1ed4dad");
-               set.add("f2250dd8736aa007a7e2530dca1c6081");
-               set.add("f2e9d36561ed03eb23d38005919625d2");
-               set.add("f303e8a2a96635d2f44c414229c349bb");
-               set.add("f35b8eac398bae58ba622ef643f64aa2");
-               set.add("f3a37dbd51e59af2801272fffe457d64");
-               set.add("f3c4afc965427977685da607f8a6edca");
-               set.add("f468c204661ab47379613a1d03f56571");
-               set.add("f4ff8d1667c95377ac96e870170bfe64");
-               set.add("f585dccae7fae67affbf500ecf9a3839");
-               set.add("f59a4193ec432bd26f780a6b74b8be38");
-               set.add("f5d44e9d1523c3e6834108d9c76b2da9");
-               set.add("f69f58acf2b80f5dc29682c64de8da7f");
-               set.add("f6adafaf98b92438e1ad916e51a65366");
-               set.add("f6f175a7910c5039d0fa51393c920df8");
-               set.add("f71a00225b1abf1dddfcace79d0345a2");
-               set.add("f7446eb342242f011c118bb3439335a0");
-               set.add("f76e6e86c9b0d84638c1c26c55b16cc4");
-               set.add("f775463704e3d13817abd9674d62f468");
-               set.add("f80df9b85c1219fd2030ada584fbfc35");
-               set.add("f843fa1d0cd00122fcbcfd7caf1cb8ca");
-               set.add("f88e05d8303a6e5dfbd60ceed3988d78");
-               set.add("f92dbcd91aac65e0770f5fe947fc5a80");
-               set.add("f9512c5cc198adeff74fed3d4b0f4509");
-               set.add("f9e1ffe33f3676d0e39bc24e63cf3a99");
-               set.add("fa492225fbf03ad58ee88b6d84914583");
-               set.add("fa6279cc58de3fe6c617559684afec4f");
-               set.add("fb2a4db1a1a68dae79653dd2e32ade50");
-               set.add("fb2bc93f011d62ac03aed40d92b26ba2");
-               set.add("fb9b6d2d2d5e3c219e0163092181e014");
-               set.add("fbdc7fc274e5c71226372606beedb706");
-               set.add("fbe25dc54e2761c2c5e9f1f3a98d7f0f");
-               set.add("fbec5f910872b333be655c5143b1cb37");
-               set.add("fc372707722b210b257ef9e2f731edc3");
-               set.add("fcedc7e1d4fc17c7c4f2c6f6c7a820e0");
-               set.add("fcff88f351f2535dcbab726dec9060ee");
-               set.add("fd15d45e5f876ac3ff10cef478077e8b");
-               set.add("fd21ff84af0fe74de102f1985d068dee");
-               set.add("fd30f89057cd8ad151d612def38afb41");
-               set.add("fdab6eed0ecadf924ae128f25e8b1a10");
-               set.add("fdced723077daed39d0e4da044f75d64");
-               set.add("fddbc361461ae318e147e420a805a428");
-               set.add("fdee78ddeb6f567a636b9850f942256f");
-               set.add("fe858217631f3aaf02d8aaf849c7b2c9");
-               set.add("fec4bbfe3563397790d48ce6f5b48260");
-               set.add("ff73d7804897f4e1624a3b5571e48fbb");
-               set.add("ff78c3b27889d5365a03b3a3fd3a4c1e");
-               set.add("ffac65c383eb053e54b267fe4dfd2141");
-               
-               DIGESTS = Collections.unmodifiableSet(set);
-       }
-       
-       private PreferredMotorDigests() {
-               // Prevent instantiation
-       }
-       
-}
index 6f3a2dc5fed52bd84e9b925e0a14a305d521f1aa..41fdaad4cf914bb23d8e3b8341560339784bf8fa 100644 (file)
@@ -8,6 +8,7 @@ import java.io.InputStream;
 
 import net.sf.openrocket.document.OpenRocketDocument;
 import net.sf.openrocket.file.AbstractRocketLoader;
+import net.sf.openrocket.file.MotorFinder;
 import net.sf.openrocket.file.RocketLoadException;
 import net.sf.openrocket.file.simplesax.SimpleSAX;
 
@@ -38,7 +39,7 @@ public class RocksimLoader extends AbstractRocketLoader {
         *          if an error occurs during loading.
         */
        @Override
-       protected OpenRocketDocument loadFromStream(InputStream source) throws IOException, RocketLoadException {
+       protected OpenRocketDocument loadFromStream(InputStream source, MotorFinder motorFinder) throws IOException, RocketLoadException {
                
                InputSource xmlSource = new InputSource(source);
                
index 1b186408da148f636b48e2428a59d1f781de74e6..da193c165aa276ddbd391e698a448f5e07252d7e 100644 (file)
@@ -11,6 +11,7 @@ import java.io.InterruptedIOException;
 import javax.swing.SwingWorker;
 
 import net.sf.openrocket.document.OpenRocketDocument;
+import net.sf.openrocket.file.DatabaseMotorFinder;
 import net.sf.openrocket.file.RocketLoader;
 import net.sf.openrocket.logging.LogHelper;
 import net.sf.openrocket.startup.Application;
@@ -66,7 +67,7 @@ public class OpenFileWorker extends SwingWorker<OpenRocketDocument, Void> {
                is = new ProgressInputStream(is);
                
                try {
-                       return loader.load(is);
+                       return loader.load(is, new DatabaseMotorFinder());
                } finally {
                        try {
                                is.close();
@@ -77,8 +78,8 @@ public class OpenFileWorker extends SwingWorker<OpenRocketDocument, Void> {
        }
        
        
-
-
+       
+       
        private class ProgressInputStream extends FilterInputStream {
                
                private final int size;
@@ -98,7 +99,7 @@ public class OpenFileWorker extends SwingWorker<OpenRocketDocument, Void> {
                }
                
                
-
+               
                @Override
                public int read() throws IOException {
                        int c = in.read();
@@ -162,7 +163,7 @@ public class OpenFileWorker extends SwingWorker<OpenRocketDocument, Void> {
                }
                
                
-
+               
                private void setProgress() {
                        int p = MathUtil.clamp(readBytes * 100 / size, 0, 100);
                        if (progress != p) {
index 91530a302cd9c522916bf9152897b3a874652ddf..49b91de69b00cdd7c3e0a188f2b3c136fba1bc01 100644 (file)
@@ -1,7 +1,12 @@
 package net.sf.openrocket.utils;
 
+import java.io.File;
+import java.io.IOException;
+import java.util.Locale;
+
 import net.sf.openrocket.document.OpenRocketDocument;
 import net.sf.openrocket.document.StorageOptions;
+import net.sf.openrocket.file.DatabaseMotorFinder;
 import net.sf.openrocket.file.RocketLoadException;
 import net.sf.openrocket.file.RocketLoader;
 import net.sf.openrocket.file.RocketSaver;
@@ -11,10 +16,6 @@ import net.sf.openrocket.l10n.ResourceBundleTranslator;
 import net.sf.openrocket.logging.LogLevel;
 import net.sf.openrocket.startup.Application;
 
-import java.io.File;
-import java.io.IOException;
-import java.util.Locale;
-
 /**
  * Utility that loads Rocksim file formats and saves them in ORK format.
  * File is saved with the .rkt extension replaced with .ork.
@@ -62,7 +63,7 @@ public class RocksimConverter {
                                opts.setSimulationTimeSkip(StorageOptions.SIMULATION_DATA_NONE);
                                opts.setExplicitlySet(true);
                                
-                               OpenRocketDocument document = loader.load(input);
+                               OpenRocketDocument document = loader.load(input, new DatabaseMotorFinder());
                                saver.save(output, document, opts);
                                
                        } catch (RocketLoadException e) {
index af73af34c6dbb8fe72f9b40d727d5a89aae1bf10..b06a6c34cf155a0553d68747ea01a957f2738eb4 100644 (file)
@@ -1,10 +1,6 @@
 package net.sf.openrocket;
 
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
+import static org.junit.Assert.*;
 
 import java.awt.event.ActionEvent;
 import java.io.IOException;
@@ -18,6 +14,7 @@ import net.sf.openrocket.aerodynamics.FlightConditions;
 import net.sf.openrocket.database.ThrustCurveMotorSetDatabase;
 import net.sf.openrocket.document.OpenRocketDocument;
 import net.sf.openrocket.document.Simulation;
+import net.sf.openrocket.file.DatabaseMotorFinder;
 import net.sf.openrocket.file.GeneralRocketLoader;
 import net.sf.openrocket.file.RocketLoadException;
 import net.sf.openrocket.file.motor.GeneralMotorLoader;
@@ -94,119 +91,119 @@ public class IntegrationTest extends BaseTestCase {
                GeneralRocketLoader loader = new GeneralRocketLoader();
                InputStream is = this.getClass().getResourceAsStream("simplerocket.ork");
                assertNotNull("Problem in unit test, cannot find simplerocket.ork", is);
-               document = loader.load(is);
+               document = loader.load(is, new DatabaseMotorFinder());
                is.close();
                
-               undoAction = UndoRedoAction.newUndoAction(document );
+               undoAction = UndoRedoAction.newUndoAction(document);
                redoAction = UndoRedoAction.newRedoAction(document);
                config = document.getSimulation(0).getConfiguration();
                conditions = new FlightConditions(config);
                
-
+               
                // Test undo state
                checkUndoState(null, null);
                
-
+               
                // Compute cg+cp + altitude
                checkCgCp(0.248, 0.0645, 0.320, 12.0);
                checkAlt(48.2);
                
-
+               
                // Mass modification
                document.addUndoPosition("Modify mass");
                checkUndoState(null, null);
                massComponent().setComponentMass(0.01);
                checkUndoState("Modify mass", null);
                
-
+               
                // Check cg+cp + altitude
                checkCgCp(0.230, 0.0745, 0.320, 12.0);
                checkAlt(37.2);
                
-
+               
                // Non-change
                document.addUndoPosition("No change");
                checkUndoState("Modify mass", null);
                
-
+               
                // Non-funcitonal change
                document.addUndoPosition("Name change");
                checkUndoState("Modify mass", null);
                massComponent().setName("Foobar component");
                checkUndoState("Name change", null);
                
-
+               
                // Check cg+cp
                checkCgCp(0.230, 0.0745, 0.320, 12.0);
                
-
+               
                // Aerodynamic modification
                document.addUndoPosition("Remove component");
                checkUndoState("Name change", null);
                document.getRocket().getChild(0).removeChild(0);
                checkUndoState("Remove component", null);
                
-
+               
                // Check cg+cp + altitude
                checkCgCp(0.163, 0.0613, 0.275, 9.95);
                checkAlt(45.0);
                
-
+               
                // Undo "Remove component" change
                undoAction.actionPerformed(new ActionEvent(this, 0, "foo"));
                assertTrue(document.getRocket().getChild(0).getChild(0) instanceof NoseCone);
                checkUndoState("Name change", "Remove component");
                
-
+               
                // Check cg+cp + altitude
                checkCgCp(0.230, 0.0745, 0.320, 12.0);
                checkAlt(37.2);
                
-
+               
                // Undo "Name change" change
                undoAction.actionPerformed(new ActionEvent(this, 0, "foo"));
                assertEquals("Extra mass", massComponent().getName());
                checkUndoState("Modify mass", "Name change");
                
-
+               
                // Check cg+cp
                checkCgCp(0.230, 0.0745, 0.320, 12.0);
                
-
+               
                // Undo "Modify mass" change
                undoAction.actionPerformed(new ActionEvent(this, 0, "foo"));
                assertEquals(0, massComponent().getComponentMass(), 0);
                checkUndoState(null, "Modify mass");
                
-
+               
                // Check cg+cp + altitude
                checkCgCp(0.248, 0.0645, 0.320, 12.0);
                checkAlt(48.2);
                
-
+               
                // Redo "Modify mass" change
                redoAction.actionPerformed(new ActionEvent(this, 0, "foo"));
                assertEquals(0.010, massComponent().getComponentMass(), 0.00001);
                checkUndoState("Modify mass", "Name change");
                
-
+               
                // Check cg+cp + altitude
                checkCgCp(0.230, 0.0745, 0.320, 12.0);
                checkAlt(37.2);
                
-
+               
                // Mass modification
                document.addUndoPosition("Modify mass2");
                checkUndoState("Modify mass", "Name change");
                massComponent().setComponentMass(0.015);
                checkUndoState("Modify mass2", null);
                
-
+               
                // Check cg+cp + altitude
                checkCgCp(0.223, 0.0795, 0.320, 12.0);
                checkAlt(32.7);
                
-
+               
                // Perform component movement
                document.startUndo("Move component");
                document.getRocket().freeze();
@@ -220,55 +217,55 @@ public class IntegrationTest extends BaseTestCase {
                checkUndoState("Move component", null);
                document.stopUndo();
                
-
+               
                // Check cg+cp + altitude
                checkCgCp(0.221, 0.0797, 0.320, 12.0);
                checkAlt(32.7);
                
-
+               
                // Modify mass without setting undo description
                massComponent().setComponentMass(0.020);
                checkUndoState("Modify mass2", null);
                
-
+               
                // Check cg+cp + altitude
                checkCgCp(0.215, 0.0847, 0.320, 12.0);
                checkAlt(29.0);
                
-
+               
                // Undo "Modify mass2" change
                undoAction.actionPerformed(new ActionEvent(this, 0, "foo"));
                assertEquals(0.015, massComponent().getComponentMass(), 0.0000001);
                checkUndoState("Move component", "Modify mass2");
                
-
+               
                // Check cg+cp + altitude
                checkCgCp(0.221, 0.0797, 0.320, 12.0);
                checkAlt(32.7);
                
-
+               
                // Undo "Move component" change
                undoAction.actionPerformed(new ActionEvent(this, 0, "foo"));
                assertTrue(document.getRocket().getChild(0).getChild(1).getChild(2).getChild(0) instanceof EngineBlock);
                checkUndoState("Modify mass2", "Move component");
                
-
+               
                // Check cg+cp + altitude
                checkCgCp(0.223, 0.0795, 0.320, 12.0);
                checkAlt(32.7);
                
-
+               
                // Redo "Move component" change
                redoAction.actionPerformed(new ActionEvent(this, 0, "foo"));
                assertTrue(document.getRocket().getChild(0).getChild(1).getChild(0) instanceof EngineBlock);
                checkUndoState("Move component", "Modify mass2");
                
-
+               
                // Check cg+cp + altitude
                checkCgCp(0.221, 0.0797, 0.320, 12.0);
                checkAlt(32.7);
                
-
+               
        }
        
        private String massComponentID = null;
index 92a0eea3df743ca61f1a4aa46352567b76b3682b..48ea77aff515242493b7a57e0f767fea463caa34 100644 (file)
  */
 package net.sf.openrocket.file.rocksim.importt;
 
+import java.io.BufferedInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
 import net.sf.openrocket.document.OpenRocketDocument;
+import net.sf.openrocket.file.DatabaseMotorFinder;
 import net.sf.openrocket.file.RocketLoadException;
 import net.sf.openrocket.rocketcomponent.BodyTube;
 import net.sf.openrocket.rocketcomponent.LaunchLug;
 import net.sf.openrocket.rocketcomponent.Rocket;
 import net.sf.openrocket.rocketcomponent.Stage;
-import org.junit.Assert;
 
-import java.io.BufferedInputStream;
-import java.io.IOException;
-import java.io.InputStream;
+import org.junit.Assert;
 
 /**
  * RocksimLoader Tester.
  */
 public class RocksimLoaderTest {
-
-    /**
-     * Test a bug reported via automated bug report.  I have been unable to reproduce this bug
-     * (hanging finset off of an inner body tube) when creating a Rocksim file using Rocksim.  The bug
-     * is reproducible when manually modifying the Rocksim file, which is what is tested here.
-     */
-    @org.junit.Test
-    public void testFinsOnInnerTube() throws Exception {
-        RocksimLoader loader = new RocksimLoader();
-        InputStream stream = this.getClass().getResourceAsStream("PodFins.rkt");
-        Assert.assertNotNull("Could not open PodFins.rkt", stream);
-        try {
-            OpenRocketDocument doc = loader.loadFromStream(new BufferedInputStream(stream));
-            Assert.assertNotNull(doc);
-            Rocket rocket = doc.getRocket();
-            Assert.assertNotNull(rocket);
-        } catch (IllegalStateException ise) {
-            Assert.fail(ise.getMessage());
-        }
-        Assert.assertTrue(loader.getWarnings().size() == 2);
-    }
-
-    /**
-     * Method: loadFromStream(InputStream source)
-     *
-     * @throws Exception thrown if something goes awry
-     */
-    @org.junit.Test
-    public void testLoadFromStream() throws Exception {
-        RocksimLoader loader = new RocksimLoader();
-        //Stupid single stage rocket
-        OpenRocketDocument doc = loadRocksimRocket(loader);
-        InputStream stream;
-
-        Assert.assertNotNull(doc);
-        Rocket rocket = doc.getRocket();
-        Assert.assertNotNull(rocket);
-        Assert.assertEquals("FooBar Test", doc.getRocket().getName());
-        Assert.assertTrue(loader.getWarnings().isEmpty());
-
-        stream = this.getClass().getResourceAsStream("rocksimTestRocket2.rkt");
-        Assert.assertNotNull("Could not open rocksimTestRocket2.rkt", stream);
-        doc = loader.loadFromStream(new BufferedInputStream(stream));
-
-        Assert.assertNotNull(doc);
-        rocket = doc.getRocket();
-        Assert.assertNotNull(rocket);
-
-        //Do some simple asserts;  the important thing here is just validating that the mass and cg were
-        //not overridden for each stage.
-        Assert.assertEquals("Three Stage Everything Included Rocket", doc.getRocket().getName());
-        Assert.assertEquals(1, loader.getWarnings().size());
-        Assert.assertEquals(3, rocket.getStageCount());
-        Stage stage1 = (Stage) rocket.getChild(0);
-        Assert.assertFalse(stage1.isMassOverridden());
-        Assert.assertFalse(stage1.isCGOverridden());
-        Stage stage2 = (Stage) rocket.getChild(1);
-        Assert.assertFalse(stage2.isMassOverridden());
-        Assert.assertFalse(stage2.isCGOverridden());
-        Stage stage3 = (Stage) rocket.getChild(2);
-        Assert.assertFalse(stage3.isMassOverridden());
-        Assert.assertFalse(stage3.isCGOverridden());
-
-        stream = this.getClass().getResourceAsStream("rocksimTestRocket3.rkt");
-        Assert.assertNotNull("Could not open rocksimTestRocket3.rkt", stream);
-        doc = loader.loadFromStream(new BufferedInputStream(stream));
-
-        Assert.assertNotNull(doc);
-        rocket = doc.getRocket();
-        Assert.assertNotNull(rocket);
-        Assert.assertEquals("Three Stage Everything Included Rocket - Override Total Mass/CG", doc.getRocket().getName());
-        Assert.assertEquals(3, rocket.getStageCount());
-        stage1 = (Stage) rocket.getChild(0);
-        stage2 = (Stage) rocket.getChild(1);
-        stage3 = (Stage) rocket.getChild(2);
-
-        //Do some 1st level and simple asserts; the idea here is to not do a deep validation as that 
-        //should have been covered elsewhere.  Assert that the stage overrides are correct.
-        Assert.assertEquals(2, stage1.getChildCount());
-        Assert.assertEquals("Nose cone", stage1.getChild(0).getName());
-        Assert.assertEquals("Body tube", stage1.getChild(1).getName());
-        Assert.assertTrue(stage1.isMassOverridden());
-        Assert.assertEquals(0.185d, stage1.getOverrideMass(), 0.001);
-        Assert.assertTrue(stage1.isCGOverridden());
-        Assert.assertEquals(0.3d, stage1.getOverrideCG().x, 0.001);
-        Assert.assertEquals(4, loader.getWarnings().size());
-
-        Assert.assertEquals(1, stage2.getChildCount());
-        Assert.assertEquals("2nd Stage Tube", stage2.getChild(0).getName());
-        Assert.assertTrue(stage2.isMassOverridden());
-        Assert.assertEquals(0.21d, stage2.getOverrideMass(), 0.001);
-        Assert.assertTrue(stage2.isCGOverridden());
-        Assert.assertEquals(0.4d, stage2.getOverrideCG().x, 0.001);
-
-        BodyTube bt = (BodyTube) stage2.getChild(0);
-        LaunchLug ll = (LaunchLug) bt.getChild(6);
-        Assert.assertEquals(1.22d, ll.getRadialDirection(), 0.001);
-
-        Assert.assertEquals(2, stage3.getChildCount());
-        Assert.assertEquals("Transition", stage3.getChild(0).getName());
-        Assert.assertEquals("Body tube", stage3.getChild(1).getName());
-        Assert.assertTrue(stage2.isMassOverridden());
-        Assert.assertEquals(0.33d, stage3.getOverrideMass(), 0.001);
-        Assert.assertTrue(stage2.isCGOverridden());
-        Assert.assertEquals(0.5d, stage3.getOverrideCG().x, 0.001);
-    }
-
-    public static OpenRocketDocument loadRocksimRocket(RocksimLoader theLoader) throws IOException, RocketLoadException {
-        InputStream stream = RocksimLoaderTest.class.getResourceAsStream("rocksimTestRocket1.rkt");
-        try {
-            Assert.assertNotNull("Could not open rocksimTestRocket1.rkt", stream);
-            return theLoader.loadFromStream(new BufferedInputStream(stream));
-        } finally {
-            stream.close();
-        }
-    }
-
-    public static OpenRocketDocument loadRocksimRocket3(RocksimLoader theLoader) throws IOException, RocketLoadException {
-        InputStream stream = RocksimLoaderTest.class.getResourceAsStream("rocksimTestRocket3.rkt");
-        try {
-            Assert.assertNotNull("Could not open rocksimTestRocket3.rkt", stream);
-            return theLoader.loadFromStream(new BufferedInputStream(stream));
-        } finally {
-            stream.close();
-        }
-    }
-
+       
+       /**
+        * Test a bug reported via automated bug report.  I have been unable to reproduce this bug
+        * (hanging finset off of an inner body tube) when creating a Rocksim file using Rocksim.  The bug
+        * is reproducible when manually modifying the Rocksim file, which is what is tested here.
+        */
+       @org.junit.Test
+       public void testFinsOnInnerTube() throws Exception {
+               RocksimLoader loader = new RocksimLoader();
+               InputStream stream = this.getClass().getResourceAsStream("PodFins.rkt");
+               Assert.assertNotNull("Could not open PodFins.rkt", stream);
+               try {
+                       OpenRocketDocument doc = loader.loadFromStream(new BufferedInputStream(stream), new DatabaseMotorFinder());
+                       Assert.assertNotNull(doc);
+                       Rocket rocket = doc.getRocket();
+                       Assert.assertNotNull(rocket);
+               } catch (IllegalStateException ise) {
+                       Assert.fail(ise.getMessage());
+               }
+               Assert.assertTrue(loader.getWarnings().size() == 2);
+       }
+       
+       /**
+        * Method: loadFromStream(InputStream source)
+        *
+        * @throws Exception thrown if something goes awry
+        */
+       @org.junit.Test
+       public void testLoadFromStream() throws Exception {
+               RocksimLoader loader = new RocksimLoader();
+               //Stupid single stage rocket
+               OpenRocketDocument doc = loadRocksimRocket(loader);
+               InputStream stream;
+               
+               Assert.assertNotNull(doc);
+               Rocket rocket = doc.getRocket();
+               Assert.assertNotNull(rocket);
+               Assert.assertEquals("FooBar Test", doc.getRocket().getName());
+               Assert.assertTrue(loader.getWarnings().isEmpty());
+               
+               stream = this.getClass().getResourceAsStream("rocksimTestRocket2.rkt");
+               Assert.assertNotNull("Could not open rocksimTestRocket2.rkt", stream);
+               doc = loader.loadFromStream(new BufferedInputStream(stream), new DatabaseMotorFinder());
+               
+               Assert.assertNotNull(doc);
+               rocket = doc.getRocket();
+               Assert.assertNotNull(rocket);
+               
+               //Do some simple asserts;  the important thing here is just validating that the mass and cg were
+               //not overridden for each stage.
+               Assert.assertEquals("Three Stage Everything Included Rocket", doc.getRocket().getName());
+               Assert.assertEquals(1, loader.getWarnings().size());
+               Assert.assertEquals(3, rocket.getStageCount());
+               Stage stage1 = (Stage) rocket.getChild(0);
+               Assert.assertFalse(stage1.isMassOverridden());
+               Assert.assertFalse(stage1.isCGOverridden());
+               Stage stage2 = (Stage) rocket.getChild(1);
+               Assert.assertFalse(stage2.isMassOverridden());
+               Assert.assertFalse(stage2.isCGOverridden());
+               Stage stage3 = (Stage) rocket.getChild(2);
+               Assert.assertFalse(stage3.isMassOverridden());
+               Assert.assertFalse(stage3.isCGOverridden());
+               
+               stream = this.getClass().getResourceAsStream("rocksimTestRocket3.rkt");
+               Assert.assertNotNull("Could not open rocksimTestRocket3.rkt", stream);
+               doc = loader.loadFromStream(new BufferedInputStream(stream), new DatabaseMotorFinder());
+               
+               Assert.assertNotNull(doc);
+               rocket = doc.getRocket();
+               Assert.assertNotNull(rocket);
+               Assert.assertEquals("Three Stage Everything Included Rocket - Override Total Mass/CG", doc.getRocket().getName());
+               Assert.assertEquals(3, rocket.getStageCount());
+               stage1 = (Stage) rocket.getChild(0);
+               stage2 = (Stage) rocket.getChild(1);
+               stage3 = (Stage) rocket.getChild(2);
+               
+               //Do some 1st level and simple asserts; the idea here is to not do a deep validation as that 
+               //should have been covered elsewhere.  Assert that the stage overrides are correct.
+               Assert.assertEquals(2, stage1.getChildCount());
+               Assert.assertEquals("Nose cone", stage1.getChild(0).getName());
+               Assert.assertEquals("Body tube", stage1.getChild(1).getName());
+               Assert.assertTrue(stage1.isMassOverridden());
+               Assert.assertEquals(0.185d, stage1.getOverrideMass(), 0.001);
+               Assert.assertTrue(stage1.isCGOverridden());
+               Assert.assertEquals(0.3d, stage1.getOverrideCG().x, 0.001);
+               Assert.assertEquals(4, loader.getWarnings().size());
+               
+               Assert.assertEquals(1, stage2.getChildCount());
+               Assert.assertEquals("2nd Stage Tube", stage2.getChild(0).getName());
+               Assert.assertTrue(stage2.isMassOverridden());
+               Assert.assertEquals(0.21d, stage2.getOverrideMass(), 0.001);
+               Assert.assertTrue(stage2.isCGOverridden());
+               Assert.assertEquals(0.4d, stage2.getOverrideCG().x, 0.001);
+               
+               BodyTube bt = (BodyTube) stage2.getChild(0);
+               LaunchLug ll = (LaunchLug) bt.getChild(6);
+               Assert.assertEquals(1.22d, ll.getRadialDirection(), 0.001);
+               
+               Assert.assertEquals(2, stage3.getChildCount());
+               Assert.assertEquals("Transition", stage3.getChild(0).getName());
+               Assert.assertEquals("Body tube", stage3.getChild(1).getName());
+               Assert.assertTrue(stage2.isMassOverridden());
+               Assert.assertEquals(0.33d, stage3.getOverrideMass(), 0.001);
+               Assert.assertTrue(stage2.isCGOverridden());
+               Assert.assertEquals(0.5d, stage3.getOverrideCG().x, 0.001);
+       }
+       
+       public static OpenRocketDocument loadRocksimRocket(RocksimLoader theLoader) throws IOException, RocketLoadException {
+               InputStream stream = RocksimLoaderTest.class.getResourceAsStream("rocksimTestRocket1.rkt");
+               try {
+                       Assert.assertNotNull("Could not open rocksimTestRocket1.rkt", stream);
+                       return theLoader.loadFromStream(new BufferedInputStream(stream), new DatabaseMotorFinder());
+               } finally {
+                       stream.close();
+               }
+       }
+       
+       public static OpenRocketDocument loadRocksimRocket3(RocksimLoader theLoader) throws IOException, RocketLoadException {
+               InputStream stream = RocksimLoaderTest.class.getResourceAsStream("rocksimTestRocket3.rkt");
+               try {
+                       Assert.assertNotNull("Could not open rocksimTestRocket3.rkt", stream);
+                       return theLoader.loadFromStream(new BufferedInputStream(stream), new DatabaseMotorFinder());
+               } finally {
+                       stream.close();
+               }
+       }
+       
 }