From d1c83cb9b40ec9fc5cba699d63d208d6e9ef6ac0 Mon Sep 17 00:00:00 2001 From: Kevin Ruland Date: Mon, 16 Apr 2012 19:18:25 +0000 Subject: [PATCH] Refactored the ComponentPreset.create method into the ComponentPresetFactory object to make code maintenance easier. Added support for Bulk heads. --- .../presets/semroc/bulkheadpresets.csv | 31 +++ .../database/ComponentPresetDatabase.java | 3 +- .../sf/openrocket/preset/ComponentPreset.java | 181 +++------------- .../preset/ComponentPresetFactory.java | 199 ++++++++++++++++++ 4 files changed, 266 insertions(+), 148 deletions(-) create mode 100644 core/resources/datafiles/presets/semroc/bulkheadpresets.csv create mode 100644 core/src/net/sf/openrocket/preset/ComponentPresetFactory.java diff --git a/core/resources/datafiles/presets/semroc/bulkheadpresets.csv b/core/resources/datafiles/presets/semroc/bulkheadpresets.csv new file mode 100644 index 000000000..5ba55bd54 --- /dev/null +++ b/core/resources/datafiles/presets/semroc/bulkheadpresets.csv @@ -0,0 +1,31 @@ +Manufacturer,PartNo,Description,Type,OuterDiameter,Length,Material,Mass +Semroc,BTC-5,Solid Balsa Tube Adapter - Series 5,BULK_HEAD,0.013081,0.01905,Balsa,0.000283495 +Semroc,BTC-7,Solid Balsa Tube Adapter - Series 7,BULK_HEAD,0.018161,0.0254,Balsa,0.000737087 +Semroc,BTC-8,Solid Balsa Tube Adapter - Series 8,BULK_HEAD,0.021971,0.0254,Balsa,0.001077281 +Semroc,BTC-8F,Solid Balsa Tube Adapter - Series 8F,BULK_HEAD,0.022479,0.0254,Balsa,0.001077281 +Semroc,BTC-9,Solid Balsa Tube Adapter - Series 9,BULK_HEAD,0.02413,0.0381,Balsa,0.001275727 +Semroc,BTC-10,Solid Balsa Tube Adapter - Series 10,BULK_HEAD,0.0254,0.0381,Balsa,0.001814368 +Semroc,BTC-11,Solid Balsa Tube Adapter - Series 11,BULK_HEAD,0.028702,0.0381,Balsa,0.001956115 +Semroc,BTC-13,Solid Balsa Tube Adapter - Series 13,BULK_HEAD,0.03302,0.04445,Balsa,0.003543687 +Semroc,BTC-16,Solid Balsa Tube Adapter - Series 16,BULK_HEAD,0.04064,0.04445,Balsa,0.004961161 +Semroc,BTC-18,Solid Balsa Tube Adapter - Series 18,BULK_HEAD,0.04572,0.04445,Balsa,0.005669899 +Semroc,BTC-20,Solid Balsa Tube Adapter - Series 20,BULK_HEAD,0.0508,0.05334,Balsa,0.007512616 +Semroc,BTC-085,Solid Balsa Tube Adapter - Series 85,BULK_HEAD,0.021971,0.0381,Balsa,0.001615921 +Semroc,BTC-115,Solid Balsa Tube Adapter - Series 115,BULK_HEAD,0.02921,0.04445,Balsa,0.003175143 +Semroc,BTC-125,Solid Balsa Tube Adapter - Series 125,BULK_HEAD,0.03175,0.0508,Balsa,0.004535919 +Semroc,BTC-150,Solid Balsa Tube Adapter - Series 150,BULK_HEAD,0.0381,0.0508,Balsa,0.006662131 +Semroc,BTC-175,Solid Balsa Tube Adapter - Series 175,BULK_HEAD,0.04445,0.05715,Balsa,0.00949708 +Semroc,BTC-225,Solid Balsa Tube Adapter - Series 225,BULK_HEAD,0.05715,0.0635,Balsa,0.018001928 +Semroc,BTC-275,Solid Balsa Tube Adapter - Series 275,BULK_HEAD,0.06985,0.0762,Balsa,0.032176674 +Semroc,NB-3,Solid Balsa Tube Adapter - Series BT-3,BULK_HEAD,0.0088646,0.01905,Balsa,0.000198446 +Semroc,NB-5,Solid Balsa Tube Adapter - Series BT-5,BULK_HEAD,0.013081,0.01905,Balsa,0.000283495 +Semroc,NB-20,Solid Balsa Tube Adapter - Series BT-20,BULK_HEAD,0.018034,0.01905,Balsa,0.00056699 +Semroc,NB-30,Solid Balsa Tube Adapter - Series BT-30,BULK_HEAD,0.018415,0.01905,Balsa,0.00056699 +Semroc,NB-40,Solid Balsa Tube Adapter - Series BT-40,BULK_HEAD,0.019431,0.0254,Balsa,0.000793786 +Semroc,NB-50,Solid Balsa Tube Adapter - Series BT-50,BULK_HEAD,0.02413,0.0254,Balsa,0.00113398 +Semroc,NB-50L,Solid Balsa Tube Adapter - Series BT-50,BULK_HEAD,0.02413,0.030226,Balsa,0.002182911 +Semroc,NB-55,Solid Balsa Tube Adapter - Series BT-55,BULK_HEAD,0.0325882,0.03175,Balsa,0.003260192 +Semroc,NB-60,Solid Balsa Tube Adapter - Series BT-60,BULK_HEAD,0.040513,0.0381,Balsa,0.004819414 +Semroc,NB-65,Solid Balsa Tube Adapter - Series BT-65,BULK_HEAD,0.04445,0.04445,Balsa,0.005953393 +Semroc,NB-70,Solid Balsa Tube Adapter - Series BT-70,BULK_HEAD,0.055245,0.0508,Balsa,0.006236888 +Semroc,NB-80,Solid Balsa Tube Adapter - Series BT-80,BULK_HEAD,0.0649732,0.0762,Balsa,0.010489312 diff --git a/core/src/net/sf/openrocket/database/ComponentPresetDatabase.java b/core/src/net/sf/openrocket/database/ComponentPresetDatabase.java index a382be211..d7cab153e 100644 --- a/core/src/net/sf/openrocket/database/ComponentPresetDatabase.java +++ b/core/src/net/sf/openrocket/database/ComponentPresetDatabase.java @@ -12,6 +12,7 @@ import net.sf.openrocket.file.Loader; import net.sf.openrocket.file.preset.PresetCSVReader; import net.sf.openrocket.logging.LogHelper; import net.sf.openrocket.preset.ComponentPreset; +import net.sf.openrocket.preset.ComponentPresetFactory; import net.sf.openrocket.preset.InvalidComponentPresetException; import net.sf.openrocket.preset.TypedPropertyMap; import net.sf.openrocket.startup.Application; @@ -37,7 +38,7 @@ public class ComponentPresetDatabase extends Database implement List list = parser.parse(); for( TypedPropertyMap o : list ) { try { - ComponentPreset preset = ComponentPreset.create(o); + ComponentPreset preset = ComponentPresetFactory.create(o); if ( favorites.contains(preset.preferenceKey())) { preset.setFavorite(true); } diff --git a/core/src/net/sf/openrocket/preset/ComponentPreset.java b/core/src/net/sf/openrocket/preset/ComponentPreset.java index 94c1973d2..2ad9fad78 100644 --- a/core/src/net/sf/openrocket/preset/ComponentPreset.java +++ b/core/src/net/sf/openrocket/preset/ComponentPreset.java @@ -61,8 +61,14 @@ public class ComponentPreset implements Comparable { ComponentPreset.SHAPE, ComponentPreset.FORE_OUTER_DIAMETER, ComponentPreset.OUTER_DIAMETER, - ComponentPreset.LENGTH - } ) ; + ComponentPreset.LENGTH} ), + + BULK_HEAD( new TypedKey[] { + ComponentPreset.MANUFACTURER, + ComponentPreset.PARTNO, + ComponentPreset.DESCRIPTION, + ComponentPreset.OUTER_DIAMETER, + ComponentPreset.LENGTH} ); Type[] compatibleTypes; TypedKey[] displayedColumns; @@ -135,150 +141,8 @@ public class ComponentPreset implements Comparable { keyMap.put(MASS.getName(), MASS); } - public static ComponentPreset create( TypedPropertyMap props ) throws InvalidComponentPresetException { - - ComponentPreset preset = new ComponentPreset(); - // First do validation. - if ( !props.containsKey(TYPE)) { - throw new InvalidComponentPresetException("No Type specified " + props.toString() ); - } - - if (!props.containsKey(MANUFACTURER)) { - throw new InvalidComponentPresetException("No Manufacturer specified " + props.toString() ); - } - - if (!props.containsKey(PARTNO)) { - throw new InvalidComponentPresetException("No PartNo specified " + props.toString() ); - } - - preset.properties.putAll(props); - - // Should check for various bits of each of the types. - Type t = props.get(TYPE); - switch ( t ) { - case BODY_TUBE: { - - if ( !props.containsKey(LENGTH) ) { - throw new InvalidComponentPresetException( "No Length specified for body tube preset " + props.toString()); - } - - BodyTube bt = new BodyTube(); - - bt.setLength(props.get(LENGTH)); - - // Need to verify contains 2 of OD, thickness, ID. Compute the third. - boolean hasOd = props.containsKey(OUTER_DIAMETER); - boolean hasId = props.containsKey(INNER_DIAMETER); - boolean hasThickness = props.containsKey(THICKNESS); - - if ( hasOd ) { - double outerRadius = props.get(OUTER_DIAMETER)/2.0; - double thickness = 0; - bt.setOuterRadius( outerRadius ); - if ( hasId ) { - thickness = outerRadius - props.get(INNER_DIAMETER)/2.0; - } else if ( hasThickness ) { - thickness = props.get(THICKNESS); - } else { - throw new InvalidComponentPresetException("Body tube preset underspecified " + props.toString()); - } - bt.setThickness( thickness ); - } else { - if ( ! hasId && ! hasThickness ) { - throw new InvalidComponentPresetException("Body tube preset underspecified " + props.toString()); - } - double innerRadius = props.get(INNER_DIAMETER)/2.0; - double thickness = props.get(THICKNESS); - bt.setOuterRadius(innerRadius + thickness); - bt.setThickness(thickness); - } - - preset.properties.put(OUTER_DIAMETER, bt.getOuterRadius() *2.0); - preset.properties.put(INNER_DIAMETER, bt.getInnerRadius() *2.0); - preset.properties.put(THICKNESS, bt.getThickness()); - - // Need to translate Mass to Density. - if ( props.containsKey(MASS) ) { - String materialName = "TubeCustom"; - if ( props.containsKey(MATERIAL) ) { - materialName = props.get(MATERIAL).getName(); - } - Material m = Material.newMaterial(Material.Type.BULK, materialName, props.get(MASS)/bt.getComponentVolume(), false); - preset.properties.put(MATERIAL, m); - } - - break; - } - case NOSE_CONE: { - - if ( !props.containsKey(LENGTH) ) { - throw new InvalidComponentPresetException( "No Length specified for nose cone preset " + props.toString()); - } - if ( !props.containsKey(SHAPE) ) { - throw new InvalidComponentPresetException( "No Shape specified for nose cone preset " + props.toString()); - } - if ( !props.containsKey(OUTER_DIAMETER) ) { - throw new InvalidComponentPresetException( "No Outer Diameter specified for nose cone preset " + props.toString()); - } - - if ( props.containsKey(MASS) ) { - // compute a density for this component - double mass = props.get(MASS); - NoseCone nc = new NoseCone(); - nc.loadPreset(preset); - double density = mass / nc.getComponentVolume(); - - String materialName = "NoseConeCustom"; - if ( props.containsKey(MATERIAL) ) { - materialName = props.get(MATERIAL).getName(); - } - - Material m = Material.newMaterial(Material.Type.BULK, materialName,density, false); - preset.properties.put(MATERIAL, m); - - } - break; - } - case TRANSITION: { - - if ( !props.containsKey(LENGTH) ) { - throw new InvalidComponentPresetException( "No Length specified for transition preset " + props.toString()); - } - if ( !props.containsKey(OUTER_DIAMETER) ) { - throw new InvalidComponentPresetException( "No Outer Diameter specified for transition preset " + props.toString()); - } - if ( !props.containsKey(FORE_OUTER_DIAMETER) ) { - throw new InvalidComponentPresetException( "No Fore Outer Diameter specified for transition preset " + props.toString()); - } - - if ( props.containsKey(MASS) ) { - // compute a density for this component - double mass = props.get(MASS); - Transition tr = new Transition(); - tr.loadPreset(preset); - double density = mass / tr.getComponentVolume(); - - String materialName = "TransitionCustom"; - if ( props.containsKey(MATERIAL) ) { - materialName = props.get(MATERIAL).getName(); - } - - Material m = Material.newMaterial(Material.Type.BULK, materialName,density, false); - preset.properties.put(MATERIAL, m); - - } - break; - } - } - - preset.computeDigest(); - - return preset; - - } - - // Private constructor to encourage use of factory. - private ComponentPreset() { + // package scope constructor to encourage use of factory. + ComponentPreset() { } /** @@ -314,6 +178,26 @@ public class ComponentPreset implements Comparable { return properties.containsKey(key); } + /** + * Package scope so the ComponentPresetFactory can call it. + * @param other + */ + void putAll(TypedPropertyMap other) { + if (other == null) { + return; + } + properties.putAll(other); + } + + /** + * Package scope so the ComponentPresetFactory can call it. + * @param key + * @param value + */ + void put( TypedKey key, T value ) { + properties.put(key, value); + } + public T get(TypedKey key) { T value = properties.get(key); if (value == null) { @@ -349,7 +233,10 @@ public class ComponentPreset implements Comparable { return get(MANUFACTURER).toString() + "|" + get(PARTNO); } - private void computeDigest() { + /** + * Package scope so the factory can call it. + */ + void computeDigest() { try { ByteArrayOutputStream bos = new ByteArrayOutputStream(); diff --git a/core/src/net/sf/openrocket/preset/ComponentPresetFactory.java b/core/src/net/sf/openrocket/preset/ComponentPresetFactory.java new file mode 100644 index 000000000..8ade5b927 --- /dev/null +++ b/core/src/net/sf/openrocket/preset/ComponentPresetFactory.java @@ -0,0 +1,199 @@ +package net.sf.openrocket.preset; + +import static net.sf.openrocket.preset.ComponentPreset.FORE_OUTER_DIAMETER; +import static net.sf.openrocket.preset.ComponentPreset.INNER_DIAMETER; +import static net.sf.openrocket.preset.ComponentPreset.LENGTH; +import static net.sf.openrocket.preset.ComponentPreset.MANUFACTURER; +import static net.sf.openrocket.preset.ComponentPreset.MASS; +import static net.sf.openrocket.preset.ComponentPreset.MATERIAL; +import static net.sf.openrocket.preset.ComponentPreset.OUTER_DIAMETER; +import static net.sf.openrocket.preset.ComponentPreset.PARTNO; +import static net.sf.openrocket.preset.ComponentPreset.SHAPE; +import static net.sf.openrocket.preset.ComponentPreset.THICKNESS; +import static net.sf.openrocket.preset.ComponentPreset.TYPE; +import net.sf.openrocket.material.Material; +import net.sf.openrocket.preset.ComponentPreset.Type; +import net.sf.openrocket.rocketcomponent.BodyTube; +import net.sf.openrocket.rocketcomponent.Bulkhead; +import net.sf.openrocket.rocketcomponent.NoseCone; +import net.sf.openrocket.rocketcomponent.Transition; + +public abstract class ComponentPresetFactory { + + public static ComponentPreset create( TypedPropertyMap props ) throws InvalidComponentPresetException { + + ComponentPreset preset = new ComponentPreset(); + // First do validation. + if ( !props.containsKey(TYPE)) { + throw new InvalidComponentPresetException("No Type specified " + props.toString() ); + } + + if (!props.containsKey(MANUFACTURER)) { + throw new InvalidComponentPresetException("No Manufacturer specified " + props.toString() ); + } + + if (!props.containsKey(PARTNO)) { + throw new InvalidComponentPresetException("No PartNo specified " + props.toString() ); + } + + preset.putAll(props); + + // Should check for various bits of each of the types. + Type t = props.get(TYPE); + switch ( t ) { + case BODY_TUBE: { + makeBodyTube(preset); + break; + } + case NOSE_CONE: { + makeNoseCone(preset); + break; + } + case TRANSITION: { + makeTransition(preset); + break; + } + case BULK_HEAD: { + makeBulkHead(preset); + break; + } + } + + preset.computeDigest(); + + return preset; + + } + + private static void makeBodyTube( ComponentPreset preset ) throws InvalidComponentPresetException { + + checkRequiredFields( preset, LENGTH ); + + BodyTube bt = new BodyTube(); + + bt.setLength(preset.get(LENGTH)); + + // Need to verify contains 2 of OD, thickness, ID. Compute the third. + boolean hasOd = preset.has(OUTER_DIAMETER); + boolean hasId = preset.has(INNER_DIAMETER); + boolean hasThickness = preset.has(THICKNESS); + + if ( hasOd ) { + double outerRadius = preset.get(OUTER_DIAMETER)/2.0; + double thickness = 0; + bt.setOuterRadius( outerRadius ); + if ( hasId ) { + thickness = outerRadius - preset.get(INNER_DIAMETER)/2.0; + } else if ( hasThickness ) { + thickness = preset.get(THICKNESS); + } else { + throw new InvalidComponentPresetException("Body tube preset underspecified " + preset.toString()); + } + bt.setThickness( thickness ); + } else { + if ( ! hasId && ! hasThickness ) { + throw new InvalidComponentPresetException("Body tube preset underspecified " + preset.toString()); + } + double innerRadius = preset.get(INNER_DIAMETER)/2.0; + double thickness = preset.get(THICKNESS); + bt.setOuterRadius(innerRadius + thickness); + bt.setThickness(thickness); + } + + preset.put(OUTER_DIAMETER, bt.getOuterRadius() *2.0); + preset.put(INNER_DIAMETER, bt.getInnerRadius() *2.0); + preset.put(THICKNESS, bt.getThickness()); + + // Need to translate Mass to Density. + if ( preset.has(MASS) ) { + String materialName = "TubeCustom"; + if ( preset.has(MATERIAL) ) { + materialName = preset.get(MATERIAL).getName(); + } + Material m = Material.newMaterial(Material.Type.BULK, materialName, preset.get(MASS)/bt.getComponentVolume(), false); + preset.put(MATERIAL, m); + } + + + } + + private static void makeNoseCone( ComponentPreset preset ) throws InvalidComponentPresetException { + + checkRequiredFields( preset, LENGTH, SHAPE, OUTER_DIAMETER ); + + if ( preset.has(MASS) ) { + // compute a density for this component + double mass = preset.get(MASS); + NoseCone nc = new NoseCone(); + nc.loadPreset(preset); + double density = mass / nc.getComponentVolume(); + + String materialName = "NoseConeCustom"; + if ( preset.has(MATERIAL) ) { + materialName = preset.get(MATERIAL).getName(); + } + + Material m = Material.newMaterial(Material.Type.BULK, materialName,density, false); + preset.put(MATERIAL, m); + + } + + } + + private static void makeTransition( ComponentPreset preset ) throws InvalidComponentPresetException { + checkRequiredFields(preset, LENGTH, OUTER_DIAMETER, FORE_OUTER_DIAMETER); + + if ( preset.has(MASS) ) { + // compute a density for this component + double mass = preset.get(MASS); + Transition tr = new Transition(); + tr.loadPreset(preset); + double density = mass / tr.getComponentVolume(); + + String materialName = "TransitionCustom"; + if ( preset.has(MATERIAL) ) { + materialName = preset.get(MATERIAL).getName(); + } + + Material m = Material.newMaterial(Material.Type.BULK, materialName,density, false); + preset.put(MATERIAL, m); + + } + + } + + private static void makeBulkHead( ComponentPreset preset ) throws InvalidComponentPresetException { + checkRequiredFields(preset, LENGTH, OUTER_DIAMETER ); + + if ( preset.has(MASS) ) { + // compute a density for this component + double mass = preset.get(MASS); + Bulkhead tr = new Bulkhead(); + tr.loadPreset(preset); + // FIXME - Bulkhead.getComponentVolume does not exist! + // double density = mass / tr.getComponentVolume(); + + double volume = Math.pow(preset.get(OUTER_DIAMETER),2) * Math.PI / 4.0; + double density = mass / volume; + + String materialName = "TransitionCustom"; + if ( preset.has(MATERIAL) ) { + materialName = preset.get(MATERIAL).getName(); + } + + Material m = Material.newMaterial(Material.Type.BULK, materialName,density, false); + preset.put(MATERIAL, m); + + } + + } + + private static void checkRequiredFields( ComponentPreset preset, TypedKey ... keys ) throws InvalidComponentPresetException { + for( TypedKey key: keys ) { + if (! preset.has(key) ) { + throw new InvalidComponentPresetException( "No " + key.getName() + " specified for " + preset.getType().name() + " preset " + preset.toString()); + } + } + } + +}