package net.sf.openrocket.motor;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import net.sf.openrocket.models.atmosphere.AtmosphericConditions;
import net.sf.openrocket.rocketcomponent.IgnitionConfiguration;
import net.sf.openrocket.rocketcomponent.IgnitionConfiguration.IgnitionEvent;
import net.sf.openrocket.rocketcomponent.MotorMount;
import net.sf.openrocket.util.Coordinate;
import net.sf.openrocket.util.Monitorable;
/**
* A configuration of motor instances identified by a string id. Each motor instance has
* an individual position, ingition time etc.
*
* @author Sampo Niskanen <sampo.niskanen@iki.fi>
*/
public final class MotorInstanceConfiguration implements Monitorable, Cloneable {
private final List<MotorId> ids = new ArrayList<MotorId>();
private final List<MotorId> unmodifiableIds = Collections.unmodifiableList(ids);
private final List<MotorInstance> motors = new ArrayList<MotorInstance>();
private final List<Double> ejectionDelays = new ArrayList<Double>();
private final List<MotorMount> mounts = new ArrayList<MotorMount>();
private final List<IgnitionConfiguration.IgnitionEvent> ignitionEvents = new ArrayList<IgnitionConfiguration.IgnitionEvent>();
private final List<Double> ignitionDelays = new ArrayList<Double>();
private final List<Coordinate> positions = new ArrayList<Coordinate>();
private final List<Double> ignitionTimes = new ArrayList<Double>();
private int modID = 0;
/**
* Add a motor instance to this configuration. The motor is placed at
* the specified position and with an infinite ignition time (never ignited).
*
* @param id the ID of this motor instance.
* @param motor the motor instance.
* @param mount the motor mount containing this motor
* @param ignitionEvent the ignition event for the motor
* @param ignitionDelay the ignition delay for the motor
* @param position the position of the motor in absolute coordinates.
* @throws IllegalArgumentException if a motor with the specified ID already exists.
*/
public void addMotor(MotorId id, MotorInstance motor, double ejectionDelay, MotorMount mount,
IgnitionEvent ignitionEvent, double ignitionDelay, Coordinate position) {
if (this.ids.contains(id)) {
throw new IllegalArgumentException("MotorInstanceConfiguration already " +
"contains a motor with id " + id);
}
this.ids.add(id);
this.motors.add(motor);
this.ejectionDelays.add(ejectionDelay);
this.mounts.add(mount);
this.ignitionEvents.add(ignitionEvent);
this.ignitionDelays.add(ignitionDelay);
this.positions.add(position);
this.ignitionTimes.add(Double.POSITIVE_INFINITY);
modID++;
}
/**
* Return a list of all motor IDs in this configuration (not only ones in active stages).
*/
public List<MotorId> getMotorIDs() {
return unmodifiableIds;
}
public MotorInstance getMotorInstance(MotorId id) {
return motors.get(indexOf(id));
}
public double getEjectionDelay(MotorId id) {
return ejectionDelays.get(indexOf(id));
}
public MotorMount getMotorMount(MotorId id) {
return mounts.get(indexOf(id));
}
public Coordinate getMotorPosition(MotorId id) {
return positions.get(indexOf(id));
}
public void setMotorPosition(MotorId id, Coordinate position) {
positions.set(indexOf(id), position);
modID++;
}
public double getMotorIgnitionTime(MotorId id) {
return ignitionTimes.get(indexOf(id));
}
public void setMotorIgnitionTime(MotorId id, double time) {
this.ignitionTimes.set(indexOf(id), time);
modID++;
}
public double getMotorIgnitionDelay(MotorId id) {
return ignitionDelays.get(indexOf(id));
}
public IgnitionEvent getMotorIgnitionEvent(MotorId id) {
return ignitionEvents.get(indexOf(id));
}
private int indexOf(MotorId id) {
int index = ids.indexOf(id);
if (index < 0) {
throw new IllegalArgumentException("MotorInstanceConfiguration does not " +
"contain a motor with id " + id);
}
return index;
}
/**
* Step all of the motor instances to the specified time minus their ignition time.
* @param time the "global" time
*/
public void step(double time, double acceleration, AtmosphericConditions cond) {
for (int i = 0; i < motors.size(); i++) {
double t = time - ignitionTimes.get(i);
if (t >= 0) {
motors.get(i).step(t, acceleration, cond);
}
}
modID++;
}
@Override
public int getModID() {
int id = modID;
for (MotorInstance motor : motors) {
id += motor.getModID();
}
return id;
}
/**
* Return a copy of this motor instance configuration with independent motor instances
* from this instance.
*/
@Override
public MotorInstanceConfiguration clone() {
MotorInstanceConfiguration clone = new MotorInstanceConfiguration();
clone.ids.addAll(this.ids);
clone.mounts.addAll(this.mounts);
clone.positions.addAll(this.positions);
clone.ejectionDelays.addAll(this.ejectionDelays);
clone.ignitionTimes.addAll(this.ignitionTimes);
clone.ignitionEvents.addAll(this.ignitionEvents);
clone.ignitionDelays.addAll(this.ignitionDelays);
for (MotorInstance motor : this.motors) {
clone.motors.add(motor.clone());
}
clone.modID = this.modID;
return clone;
}
}