package net.sf.openrocket.aerodynamics; import net.sf.openrocket.l10n.Translator; import net.sf.openrocket.motor.Motor; import net.sf.openrocket.startup.Application; import net.sf.openrocket.unit.UnitGroup; public abstract class Warning { /** support to multiple languages warning */ private static final Translator trans = Application.getTranslator(); /** * @return a Warning with the specific text. */ public static Warning fromString(String text) { return new Warning.Other(text); } /** * Return <code>true</code> if the <code>other</code> warning should replace * this warning. The method should return <code>true</code> if the other * warning indicates a "worse" condition than the current warning. * * @param other the warning to compare to * @return whether this warning should be replaced */ public abstract boolean replaceBy(Warning other); /** * Two <code>Warning</code>s are by default considered equal if they are of * the same class. Therefore only one instance of a particular warning type * is stored in a {@link WarningSet}. Subclasses may override this method for * more specific functionality. */ @Override public boolean equals(Object o) { return o != null && (o.getClass() == this.getClass()); } /** * A <code>hashCode</code> method compatible with the <code>equals</code> method. */ @Override public int hashCode() { return this.getClass().hashCode(); } ///////////// Specific warning classes ///////////// /** * A <code>Warning</code> indicating a large angle of attack was encountered. * * @author Sampo Niskanen <sampo.niskanen@iki.fi> */ public static class LargeAOA extends Warning { private double aoa; /** * Sole constructor. The argument is the AOA that caused this warning. * * @param aoa the angle of attack that caused this warning */ public LargeAOA(double aoa) { this.aoa = aoa; } @Override public String toString() { if (Double.isNaN(aoa)) //// Large angle of attack encountered. return trans.get("Warning.LargeAOA.str1"); //// Large angle of attack encountered ( return (trans.get("Warning.LargeAOA.str2") + UnitGroup.UNITS_ANGLE.getDefaultUnit().toString(aoa) + ")."); } @Override public boolean replaceBy(Warning other) { if (!(other instanceof LargeAOA)) return false; LargeAOA o = (LargeAOA) other; if (Double.isNaN(this.aoa)) // If this has value NaN then replace return true; return (o.aoa > this.aoa); } } /** * A <code>Warning</code> indicating recovery device deployment at high speed was encountered. * * @author Craig Earls <enderw88@gmail.com> */ public static class HighSpeedDeployment extends Warning { private double recoverySpeed; /** * Sole constructor. The argument is the speed that caused this warning. * * @param speed the speed that caused this warning */ public HighSpeedDeployment(double speed) { this.recoverySpeed = speed; } @Override public String toString() { if (Double.isNaN(recoverySpeed)) { return trans.get("Warning.RECOVERY_HIGH_SPEED"); } return trans.get("Warning.RECOVERY_HIGH_SPEED") + " (" + UnitGroup.UNITS_VELOCITY.toStringUnit(recoverySpeed) + ")"; } @Override public boolean replaceBy(Warning other) { return false; } } public static class MissingMotor extends Warning { private Motor.Type type = null; private String manufacturer = null; private String designation = null; private String digest = null; private double diameter = Double.NaN; private double length = Double.NaN; private double delay = Double.NaN; @Override public String toString() { String str = "No motor with designation '" + designation + "'"; if (manufacturer != null) str += " for manufacturer '" + manufacturer + "'"; str += " found."; return str; } public Motor.Type getType() { return type; } public void setType(Motor.Type type) { this.type = type; } public String getManufacturer() { return manufacturer; } public void setManufacturer(String manufacturer) { this.manufacturer = manufacturer; } public String getDesignation() { return designation; } public void setDesignation(String designation) { this.designation = designation; } public String getDigest() { return digest; } public void setDigest(String digest) { this.digest = digest; } public double getDiameter() { return diameter; } public void setDiameter(double diameter) { this.diameter = diameter; } public double getLength() { return length; } public void setLength(double length) { this.length = length; } public double getDelay() { return delay; } public void setDelay(double delay) { this.delay = delay; } @Override public boolean replaceBy(Warning other) { return false; } @Override public int hashCode() { final int prime = 31; int result = super.hashCode(); long temp; temp = Double.doubleToLongBits(delay); result = prime * result + (int) (temp ^ (temp >>> 32)); result = prime * result + ((designation == null) ? 0 : designation.hashCode()); temp = Double.doubleToLongBits(diameter); result = prime * result + (int) (temp ^ (temp >>> 32)); result = prime * result + ((digest == null) ? 0 : digest.hashCode()); temp = Double.doubleToLongBits(length); result = prime * result + (int) (temp ^ (temp >>> 32)); result = prime * result + ((manufacturer == null) ? 0 : manufacturer.hashCode()); result = prime * result + ((type == null) ? 0 : type.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (!super.equals(obj)) return false; if (getClass() != obj.getClass()) return false; MissingMotor other = (MissingMotor) obj; if (Double.doubleToLongBits(delay) != Double .doubleToLongBits(other.delay)) return false; if (designation == null) { if (other.designation != null) return false; } else if (!designation.equals(other.designation)) return false; if (Double.doubleToLongBits(diameter) != Double .doubleToLongBits(other.diameter)) return false; if (digest == null) { if (other.digest != null) return false; } else if (!digest.equals(other.digest)) return false; if (Double.doubleToLongBits(length) != Double .doubleToLongBits(other.length)) return false; if (manufacturer == null) { if (other.manufacturer != null) return false; } else if (!manufacturer.equals(other.manufacturer)) return false; if (type != other.type) return false; return true; } } /** * An unspecified warning type. This warning type holds a <code>String</code> * describing it. Two warnings of this type are considered equal if the strings * are identical. * * @author Sampo Niskanen <sampo.niskanen@iki.fi> */ public static class Other extends Warning { private String description; public Other(String description) { this.description = description; } @Override public String toString() { return description; } @Override public boolean equals(Object other) { if (!(other instanceof Other)) return false; Other o = (Other) other; return (o.description.equals(this.description)); } @Override public int hashCode() { return description.hashCode(); } @Override public boolean replaceBy(Warning other) { return false; } } /** A <code>Warning</code> that the body diameter is discontinuous. */ ////Discontinuity in rocket body diameter. public static final Warning DISCONTINUITY = new Other(trans.get("Warning.DISCONTINUITY")); /** A <code>Warning</code> that the fins are thick compared to the rocket body. */ ////Thick fins may not be modeled accurately. public static final Warning THICK_FIN = new Other(trans.get("Warning.THICK_FIN")); /** A <code>Warning</code> that the fins have jagged edges. */ ////Jagged-edged fin predictions may be inaccurate. public static final Warning JAGGED_EDGED_FIN = new Other(trans.get("Warning.JAGGED_EDGED_FIN")); /** A <code>Warning</code> that simulation listeners have affected the simulation */ ////Listeners modified the flight simulation public static final Warning LISTENERS_AFFECTED = new Other(trans.get("Warning.LISTENERS_AFFECTED")); ////Recovery device opened while motor still burning. public static final Warning RECOVERY_DEPLOYMENT_WHILE_BURNING = new Other(trans.get("Warning.RECOVERY_DEPLOYMENT_WHILE_BURNING")); //// Invalid parameter encountered, ignoring. public static final Warning FILE_INVALID_PARAMETER = new Other(trans.get("Warning.FILE_INVALID_PARAMETER")); public static final Warning PARALLEL_FINS = new Other(trans.get("Warning.PARALLEL_FINS")); public static final Warning SUPERSONIC = new Other(trans.get("Warning.SUPERSONIC")); public static final Warning RECOVERY_LAUNCH_ROD = new Other(trans.get("Warning.RECOVERY_LAUNCH_ROD")); public static final Warning TUMBLE_UNDER_THRUST = new Other(trans.get("Warning.TUMBLE_UNDER_THRUST")); }