Added fixme in version check. Need to add test for flight

configurations.
This commit is contained in:
kruland2607 2013-03-16 18:21:27 -05:00
parent 2cfd46760d
commit c882ff2e19

View File

@ -38,59 +38,59 @@ import net.sf.openrocket.util.TextUtil;
public class OpenRocketSaver extends RocketSaver { public class OpenRocketSaver extends RocketSaver {
private static final LogHelper log = Application.getLogger(); private static final LogHelper log = Application.getLogger();
/** /**
* Divisor used in converting an integer version to the point-represented version. * Divisor used in converting an integer version to the point-represented version.
* The integer version divided by this value is the major version and the remainder is * The integer version divided by this value is the major version and the remainder is
* the minor version. For example 101 corresponds to file version "1.1". * the minor version. For example 101 corresponds to file version "1.1".
*/ */
public static final int FILE_VERSION_DIVISOR = 100; public static final int FILE_VERSION_DIVISOR = 100;
private static final String OPENROCKET_CHARSET = "UTF-8"; private static final String OPENROCKET_CHARSET = "UTF-8";
private static final String METHOD_PACKAGE = "net.sf.openrocket.file.openrocket.savers"; private static final String METHOD_PACKAGE = "net.sf.openrocket.file.openrocket.savers";
private static final String METHOD_SUFFIX = "Saver"; private static final String METHOD_SUFFIX = "Saver";
// Estimated storage used by different portions // Estimated storage used by different portions
// These have been hand-estimated from saved files // These have been hand-estimated from saved files
private static final int BYTES_PER_COMPONENT_COMPRESSED = 80; private static final int BYTES_PER_COMPONENT_COMPRESSED = 80;
private static final int BYTES_PER_SIMULATION_COMPRESSED = 100; private static final int BYTES_PER_SIMULATION_COMPRESSED = 100;
private static final int BYTES_PER_DATAPOINT_COMPRESSED = 100; private static final int BYTES_PER_DATAPOINT_COMPRESSED = 100;
private int indent; private int indent;
private Writer dest; private Writer dest;
@Override @Override
public void save(OutputStream output, OpenRocketDocument document, StorageOptions options) throws IOException { public void save(OutputStream output, OpenRocketDocument document, StorageOptions options) throws IOException {
log.info("Saving .ork file"); log.info("Saving .ork file");
dest = new BufferedWriter(new OutputStreamWriter(output, OPENROCKET_CHARSET)); dest = new BufferedWriter(new OutputStreamWriter(output, OPENROCKET_CHARSET));
// Select file version number // Select file version number
final int fileVersion = calculateNecessaryFileVersion(document, options); final int fileVersion = calculateNecessaryFileVersion(document, options);
final String fileVersionString = final String fileVersionString =
(fileVersion / FILE_VERSION_DIVISOR) + "." + (fileVersion % FILE_VERSION_DIVISOR); (fileVersion / FILE_VERSION_DIVISOR) + "." + (fileVersion % FILE_VERSION_DIVISOR);
log.debug("Storing file version " + fileVersionString); log.debug("Storing file version " + fileVersionString);
this.indent = 0; this.indent = 0;
writeln("<?xml version='1.0' encoding='utf-8'?>"); writeln("<?xml version='1.0' encoding='utf-8'?>");
writeln("<openrocket version=\"" + fileVersionString + "\" creator=\"OpenRocket " writeln("<openrocket version=\"" + fileVersionString + "\" creator=\"OpenRocket "
+ BuildProperties.getVersion() + "\">"); + BuildProperties.getVersion() + "\">");
indent++; indent++;
// Recursively save the rocket structure // Recursively save the rocket structure
saveComponent(document.getRocket()); saveComponent(document.getRocket());
writeln(""); writeln("");
// Save custom expressions; // Save custom expressions;
saveCustomDatatypes(document); saveCustomDatatypes(document);
@ -156,7 +156,7 @@ public class OpenRocketSaver extends RocketSaver {
long size = 0; long size = 0;
// FIXME - estimate decals // FIXME - estimate decals
// Size per component // Size per component
int componentCount = 0; int componentCount = 0;
Rocket rocket = doc.getRocket(); Rocket rocket = doc.getRocket();
@ -165,14 +165,14 @@ public class OpenRocketSaver extends RocketSaver {
iterator.next(); iterator.next();
componentCount++; componentCount++;
} }
size += componentCount * BYTES_PER_COMPONENT_COMPRESSED; size += componentCount * BYTES_PER_COMPONENT_COMPRESSED;
// Size per simulation // Size per simulation
size += doc.getSimulationCount() * BYTES_PER_SIMULATION_COMPRESSED; size += doc.getSimulationCount() * BYTES_PER_SIMULATION_COMPRESSED;
// Size per flight data point // Size per flight data point
int pointCount = 0; int pointCount = 0;
double timeSkip = options.getSimulationTimeSkip(); double timeSkip = options.getSimulationTimeSkip();
@ -186,13 +186,13 @@ public class OpenRocketSaver extends RocketSaver {
} }
} }
} }
size += pointCount * BYTES_PER_DATAPOINT_COMPRESSED; size += pointCount * BYTES_PER_DATAPOINT_COMPRESSED;
return size; return size;
} }
/** /**
* Determine which file version is required in order to store all the features of the * Determine which file version is required in order to store all the features of the
* current design. By default the oldest version that supports all the necessary features * current design. By default the oldest version that supports all the necessary features
@ -205,7 +205,7 @@ public class OpenRocketSaver extends RocketSaver {
private int calculateNecessaryFileVersion(OpenRocketDocument document, StorageOptions opts) { private int calculateNecessaryFileVersion(OpenRocketDocument document, StorageOptions opts) {
/* /*
* File version 1.6 is required for: * File version 1.6 is required for:
* - saving files using appearances and textures * - saving files using appearances and textures, flight configurations.
* *
* File version 1.5 is requires for: * File version 1.5 is requires for:
* - saving designs using ComponentPrests * - saving designs using ComponentPrests
@ -222,21 +222,22 @@ public class OpenRocketSaver extends RocketSaver {
* *
* Otherwise use version 1.0. * Otherwise use version 1.0.
*/ */
// Search the rocket for any Appearnces (version 1.6) // Search the rocket for any Appearnces or non-motor flight configurations (version 1.6)
for (RocketComponent c : document.getRocket()) { for (RocketComponent c : document.getRocket()) {
if (c.getAppearance() != null) { if (c.getAppearance() != null) {
return FILE_VERSION_DIVISOR + 6; return FILE_VERSION_DIVISOR + 6;
} }
// FIXME - test for flight configurations
} }
// Search the rocket for any ComponentPresets (version 1.5) // Search the rocket for any ComponentPresets (version 1.5)
for (RocketComponent c : document.getRocket()) { for (RocketComponent c : document.getRocket()) {
if (c.getPresetComponent() != null) { if (c.getPresetComponent() != null) {
return FILE_VERSION_DIVISOR + 5; return FILE_VERSION_DIVISOR + 5;
} }
} }
// Search for recovery device deployment type LOWER_STAGE_SEPARATION (version 1.5) // Search for recovery device deployment type LOWER_STAGE_SEPARATION (version 1.5)
for (RocketComponent c : document.getRocket()) { for (RocketComponent c : document.getRocket()) {
if (c instanceof RecoveryDevice) { if (c instanceof RecoveryDevice) {
@ -250,17 +251,17 @@ public class OpenRocketSaver extends RocketSaver {
if (!document.getCustomExpressions().isEmpty()) { if (!document.getCustomExpressions().isEmpty()) {
return FILE_VERSION_DIVISOR + 5; return FILE_VERSION_DIVISOR + 5;
} }
// Check if design has simulations defined (version 1.4) // Check if design has simulations defined (version 1.4)
if (document.getSimulationCount() > 0) { if (document.getSimulationCount() > 0) {
return FILE_VERSION_DIVISOR + 4; return FILE_VERSION_DIVISOR + 4;
} }
// Check for motor definitions (version 1.4) // Check for motor definitions (version 1.4)
for (RocketComponent c : document.getRocket()) { for (RocketComponent c : document.getRocket()) {
if (!(c instanceof MotorMount)) if (!(c instanceof MotorMount))
continue; continue;
MotorMount mount = (MotorMount) c; MotorMount mount = (MotorMount) c;
for (String id : document.getRocket().getFlightConfigurationIDs()) { for (String id : document.getRocket().getFlightConfigurationIDs()) {
if (mount.getMotor(id) != null) { if (mount.getMotor(id) != null) {
@ -268,7 +269,7 @@ public class OpenRocketSaver extends RocketSaver {
} }
} }
} }
// Check for fin tabs (version 1.1) // Check for fin tabs (version 1.1)
for (RocketComponent c : document.getRocket()) { for (RocketComponent c : document.getRocket()) {
// Check for fin tabs // Check for fin tabs
@ -279,7 +280,7 @@ public class OpenRocketSaver extends RocketSaver {
return FILE_VERSION_DIVISOR + 1; return FILE_VERSION_DIVISOR + 1;
} }
} }
// Check for components attached to tube coupler // Check for components attached to tube coupler
if (c instanceof TubeCoupler) { if (c instanceof TubeCoupler) {
if (c.getChildCount() > 0) { if (c.getChildCount() > 0) {
@ -287,45 +288,45 @@ public class OpenRocketSaver extends RocketSaver {
} }
} }
} }
// Default (version 1.0) // Default (version 1.0)
return FILE_VERSION_DIVISOR + 0; return FILE_VERSION_DIVISOR + 0;
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
private void saveComponent(RocketComponent component) throws IOException { private void saveComponent(RocketComponent component) throws IOException {
log.debug("Saving component " + component.getComponentName()); log.debug("Saving component " + component.getComponentName());
Reflection.Method m = Reflection.findMethod(METHOD_PACKAGE, component, METHOD_SUFFIX, Reflection.Method m = Reflection.findMethod(METHOD_PACKAGE, component, METHOD_SUFFIX,
"getElements", RocketComponent.class); "getElements", RocketComponent.class);
if (m == null) { if (m == null) {
throw new BugException("Unable to find saving class for component " + throw new BugException("Unable to find saving class for component " +
component.getComponentName()); component.getComponentName());
} }
// Get the strings to save // Get the strings to save
List<String> list = (List<String>) m.invokeStatic(component); List<String> list = (List<String>) m.invokeStatic(component);
int length = list.size(); int length = list.size();
if (length == 0) // Nothing to do if (length == 0) // Nothing to do
return; return;
if (length < 2) { if (length < 2) {
throw new RuntimeException("BUG, component data length less than two lines."); throw new RuntimeException("BUG, component data length less than two lines.");
} }
// Open element // Open element
writeln(list.get(0)); writeln(list.get(0));
indent++; indent++;
// Write parameters // Write parameters
for (int i = 1; i < length - 1; i++) { for (int i = 1; i < length - 1; i++) {
writeln(list.get(i)); writeln(list.get(i));
} }
// Recursively write subcomponents // Recursively write subcomponents
if (component.getChildCount() > 0) { if (component.getChildCount() > 0) {
writeln(""); writeln("");
@ -341,25 +342,25 @@ public class OpenRocketSaver extends RocketSaver {
indent--; indent--;
writeln("</subcomponents>"); writeln("</subcomponents>");
} }
// Close element // Close element
indent--; indent--;
writeln(list.get(length - 1)); writeln(list.get(length - 1));
} }
private void saveSimulation(Simulation simulation, double timeSkip) throws IOException { private void saveSimulation(Simulation simulation, double timeSkip) throws IOException {
SimulationOptions cond = simulation.getOptions(); SimulationOptions cond = simulation.getOptions();
writeln("<simulation status=\"" + enumToXMLName(simulation.getStatus()) + "\">"); writeln("<simulation status=\"" + enumToXMLName(simulation.getStatus()) + "\">");
indent++; indent++;
writeln("<name>" + escapeXML(simulation.getName()) + "</name>"); writeln("<name>" + escapeXML(simulation.getName()) + "</name>");
// TODO: MEDIUM: Other simulators/calculators // TODO: MEDIUM: Other simulators/calculators
writeln("<simulator>RK4Simulator</simulator>"); writeln("<simulator>RK4Simulator</simulator>");
writeln("<calculator>BarrowmanCalculator</calculator>"); writeln("<calculator>BarrowmanCalculator</calculator>");
writeln("<conditions>"); writeln("<conditions>");
indent++; indent++;
@ -373,7 +374,7 @@ public class OpenRocketSaver extends RocketSaver {
writeElement("launchlatitude", cond.getLaunchLatitude()); writeElement("launchlatitude", cond.getLaunchLatitude());
writeElement("launchlongitude", cond.getLaunchLongitude()); writeElement("launchlongitude", cond.getLaunchLongitude());
writeElement("geodeticmethod", cond.getGeodeticComputation().name().toLowerCase(Locale.ENGLISH)); writeElement("geodeticmethod", cond.getGeodeticComputation().name().toLowerCase(Locale.ENGLISH));
if (cond.isISAAtmosphere()) { if (cond.isISAAtmosphere()) {
writeln("<atmosphere model=\"isa\"/>"); writeln("<atmosphere model=\"isa\"/>");
} else { } else {
@ -384,19 +385,19 @@ public class OpenRocketSaver extends RocketSaver {
indent--; indent--;
writeln("</atmosphere>"); writeln("</atmosphere>");
} }
writeElement("timestep", cond.getTimeStep()); writeElement("timestep", cond.getTimeStep());
indent--; indent--;
writeln("</conditions>"); writeln("</conditions>");
for (String s : simulation.getSimulationListeners()) { for (String s : simulation.getSimulationListeners()) {
writeElement("listener", escapeXML(s)); writeElement("listener", escapeXML(s));
} }
// Write basic simulation data // Write basic simulation data
FlightData data = simulation.getSimulatedData(); FlightData data = simulation.getSimulatedData();
if (data != null) { if (data != null) {
String str = "<flightdata"; String str = "<flightdata";
@ -421,53 +422,53 @@ public class OpenRocketSaver extends RocketSaver {
str += ">"; str += ">";
writeln(str); writeln(str);
indent++; indent++;
for (Warning w : data.getWarningSet()) { for (Warning w : data.getWarningSet()) {
writeElement("warning", escapeXML(w.toString())); writeElement("warning", escapeXML(w.toString()));
} }
// Check whether to store data // Check whether to store data
if (simulation.getStatus() == Simulation.Status.EXTERNAL) // Always store external data if (simulation.getStatus() == Simulation.Status.EXTERNAL) // Always store external data
timeSkip = 0; timeSkip = 0;
if (timeSkip != StorageOptions.SIMULATION_DATA_NONE) { if (timeSkip != StorageOptions.SIMULATION_DATA_NONE) {
for (int i = 0; i < data.getBranchCount(); i++) { for (int i = 0; i < data.getBranchCount(); i++) {
FlightDataBranch branch = data.getBranch(i); FlightDataBranch branch = data.getBranch(i);
saveFlightDataBranch(branch, timeSkip); saveFlightDataBranch(branch, timeSkip);
} }
} }
indent--; indent--;
writeln("</flightdata>"); writeln("</flightdata>");
} }
indent--; indent--;
writeln("</simulation>"); writeln("</simulation>");
} }
private void saveFlightDataBranch(FlightDataBranch branch, double timeSkip) private void saveFlightDataBranch(FlightDataBranch branch, double timeSkip)
throws IOException { throws IOException {
double previousTime = -100000; double previousTime = -100000;
if (branch == null) if (branch == null)
return; return;
// Retrieve the types from the branch // Retrieve the types from the branch
FlightDataType[] types = branch.getTypes(); FlightDataType[] types = branch.getTypes();
if (types.length == 0) if (types.length == 0)
return; return;
// Retrieve the data from the branch // Retrieve the data from the branch
List<List<Double>> data = new ArrayList<List<Double>>(types.length); List<List<Double>> data = new ArrayList<List<Double>>(types.length);
for (int i = 0; i < types.length; i++) { for (int i = 0; i < types.length; i++) {
data.add(branch.get(types[i])); data.add(branch.get(types[i]));
} }
List<Double> timeData = branch.get(FlightDataType.TYPE_TIME); List<Double> timeData = branch.get(FlightDataType.TYPE_TIME);
// Build the <databranch> tag // Build the <databranch> tag
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
sb.append("<databranch name=\""); sb.append("<databranch name=\"");
@ -492,20 +493,20 @@ public class OpenRocketSaver extends RocketSaver {
sb.append("\">"); sb.append("\">");
writeln(sb.toString()); writeln(sb.toString());
indent++; indent++;
// Write events // Write events
for (FlightEvent event : branch.getEvents()) { for (FlightEvent event : branch.getEvents()) {
writeln("<event time=\"" + TextUtil.doubleToString(event.getTime()) writeln("<event time=\"" + TextUtil.doubleToString(event.getTime())
+ "\" type=\"" + enumToXMLName(event.getType()) + "\"/>"); + "\" type=\"" + enumToXMLName(event.getType()) + "\"/>");
} }
// Write the data // Write the data
int length = branch.getLength(); int length = branch.getLength();
if (length > 0) { if (length > 0) {
writeDataPointString(data, 0, sb); writeDataPointString(data, 0, sb);
previousTime = timeData.get(0); previousTime = timeData.get(0);
} }
for (int i = 1; i < length - 1; i++) { for (int i = 1; i < length - 1; i++) {
if (timeData != null) { if (timeData != null) {
if (Math.abs(timeData.get(i) - previousTime - timeSkip) < Math.abs(timeData.get(i + 1) - previousTime - timeSkip)) { if (Math.abs(timeData.get(i) - previousTime - timeSkip) < Math.abs(timeData.get(i + 1) - previousTime - timeSkip)) {
@ -517,61 +518,61 @@ public class OpenRocketSaver extends RocketSaver {
writeDataPointString(data, i, sb); writeDataPointString(data, i, sb);
} }
} }
if (length > 1) { if (length > 1) {
writeDataPointString(data, length - 1, sb); writeDataPointString(data, length - 1, sb);
} }
indent--; indent--;
writeln("</databranch>"); writeln("</databranch>");
} }
/* TODO: LOW: This is largely duplicated from above! */ /* TODO: LOW: This is largely duplicated from above! */
private int countFlightDataBranchPoints(FlightDataBranch branch, double timeSkip) { private int countFlightDataBranchPoints(FlightDataBranch branch, double timeSkip) {
int count = 0; int count = 0;
double previousTime = -100000; double previousTime = -100000;
if (branch == null) if (branch == null)
return 0; return 0;
// Retrieve the types from the branch // Retrieve the types from the branch
FlightDataType[] types = branch.getTypes(); FlightDataType[] types = branch.getTypes();
if (types.length == 0) if (types.length == 0)
return 0; return 0;
List<Double> timeData = branch.get(FlightDataType.TYPE_TIME); List<Double> timeData = branch.get(FlightDataType.TYPE_TIME);
if (timeData == null) { if (timeData == null) {
// If time data not available, store all points // If time data not available, store all points
return branch.getLength(); return branch.getLength();
} }
// Write the data // Write the data
int length = branch.getLength(); int length = branch.getLength();
if (length > 0) { if (length > 0) {
count++; count++;
previousTime = timeData.get(0); previousTime = timeData.get(0);
} }
for (int i = 1; i < length - 1; i++) { for (int i = 1; i < length - 1; i++) {
if (Math.abs(timeData.get(i) - previousTime - timeSkip) < Math.abs(timeData.get(i + 1) - previousTime - timeSkip)) { if (Math.abs(timeData.get(i) - previousTime - timeSkip) < Math.abs(timeData.get(i + 1) - previousTime - timeSkip)) {
count++; count++;
previousTime = timeData.get(i); previousTime = timeData.get(i);
} }
} }
if (length > 1) { if (length > 1) {
count++; count++;
} }
return count; return count;
} }
private void writeDataPointString(List<List<Double>> data, int index, StringBuilder sb) private void writeDataPointString(List<List<Double>> data, int index, StringBuilder sb)
throws IOException { throws IOException {
sb.setLength(0); sb.setLength(0);
@ -584,17 +585,17 @@ public class OpenRocketSaver extends RocketSaver {
sb.append("</datapoint>"); sb.append("</datapoint>");
writeln(sb.toString()); writeln(sb.toString());
} }
private void writeElement(String element, Object content) throws IOException { private void writeElement(String element, Object content) throws IOException {
if (content == null) if (content == null)
content = ""; content = "";
writeln("<" + element + ">" + content + "</" + element + ">"); writeln("<" + element + ">" + content + "</" + element + ">");
} }
private void writeln(String str) throws IOException { private void writeln(String str) throws IOException {
if (str.length() == 0) { if (str.length() == 0) {
dest.write("\n"); dest.write("\n");
@ -606,10 +607,10 @@ public class OpenRocketSaver extends RocketSaver {
s = s + str + "\n"; s = s + str + "\n";
dest.write(s); dest.write(s);
} }
/** /**
* Return the XML equivalent of an enum name. * Return the XML equivalent of an enum name.
* *
@ -619,5 +620,5 @@ public class OpenRocketSaver extends RocketSaver {
public static String enumToXMLName(Enum<?> e) { public static String enumToXMLName(Enum<?> e) {
return e.name().toLowerCase(Locale.ENGLISH).replace("_", ""); return e.name().toLowerCase(Locale.ENGLISH).replace("_", "");
} }
} }