StateMachineBuilder is responsible for setting up the linkage between the states. It stores a map of the names of the states and the state itself. It also includes convenience methods to easily add pre-defined States to the state machine, reducing the complexity of adding states. When all the states are done being added, the build method is called, which returns a StateMachine object.
ftc/electronvolts/statemachine/StateMachineBuilder.java
package ftc.electronvolts.statemachine;
import java.util.HashMap;
import java.util.Map;
import ftc.electronvolts.util.MatchTimer;
import ftc.electronvolts.util.ResultReceiver;
import ftc.electronvolts.util.units.Time;
/**
* This file was made by the electronVolts, FTC team 7393
*
* The state machine builder simplifies the creation of the state machine. The
* builder requires an enum with values for each state. See the wiki for an
* example of how to use it.
*
* To write your own StateMachine builder, make a class that extends this one
* and add your own convenience methods such as addDrive or addServoTurn. It
* will inherit all these methods as well, so that when you use your class, you
* will have access to all these methods and your own in one place.
*/
public class StateMachineBuilder {
// the map the links a state's name to the state
private Map<StateName, State> stateMap = new HashMap<>();
private final StateName firstStateName;
/**
* A constructor for the builder. The State machine must have a state to
* start with
*
* @param firstStateName the first state to be executed in order
*/
public StateMachineBuilder(StateName firstStateName) {
this.firstStateName = firstStateName;
}
/**
* Create a new transition
*
* @param nextStateName the name of the enum for the next state
* @param endCondition the end condition for the next state
* @return a map containing the one transition
*/
public Map<StateName, EndCondition> t(StateName nextStateName, EndCondition endCondition) {
return StateMap.of(nextStateName, endCondition);
}
/**
* Create a new transition with a timed end condition
*
* @param nextStateName the enum value associated with the next state
* @param durationMillis the amount of time to wait before advancing to the
* next state
* @return a map containing the one transition
*/
public Map<StateName, EndCondition> t(StateName nextStateName, long durationMillis) {
return t(nextStateName, EndConditions.timed(durationMillis));
}
/**
* Create a new transition with a timed end condition
*
* @param nextStateName the enum value associated with the next state
* @param duration the amount of time to wait before advancing to the next
* state
* @return a map containing the one transition
*/
public Map<StateName, EndCondition> t(StateName nextStateName, Time duration) {
return t(nextStateName, EndConditions.timed(duration));
}
/**
* Add a state to the state machine
*
* @param state the state to be added
*/
public void add(StateName stateName, State state) {
stateMap.put(stateName, state);
}
/**
* Add an empty state that waits a certain duration
*
* @param stateName the enum value to be associated with the wait state
* @param nextStateName the name of the next state
* @param durationMillis the length of time to wait in millis
*/
public void addWait(StateName stateName, StateName nextStateName, long durationMillis) {
add(stateName, States.empty(t(nextStateName, EndConditions.timed(durationMillis))));
}
/**
* Add an empty state that waits a certain duration
*
* @param stateName the enum value to be associated with the wait state
* @param nextStateName the name of the next state
* @param duration the length of time to wait
*/
public void addWait(StateName stateName, StateName nextStateName, Time duration) {
add(stateName, States.empty(t(nextStateName, EndConditions.timed(duration))));
}
/**
* Add an empty state that waits until a certain amount of time has passed
* since the beginning of the match
*
* @param stateName the enum value to be associated with the wait state
* @param nextStateName the name of the next state
* @param matchTimer a reference to the match timer object
* @param durationMillis how many millis from the match start to wait
* @see MatchTimer
*/
public void addWait(StateName stateName, StateName nextStateName, MatchTimer matchTimer, long durationMillis) {
add(stateName, States.empty(t(nextStateName, EndConditions.matchTimed(matchTimer, durationMillis))));
}
/**
* Add an empty state that waits until a certain amount of time has passed
* since the beginning of the match
*
* @param stateName the enum value to be associated with the wait state
* @param nextStateName the name of the next state
* @param matchTimer a reference to the match timer object
* @param duration how much time from the match start to wait
* @see MatchTimer
*/
public void addWait(StateName stateName, StateName nextStateName, MatchTimer matchTimer, Time duration) {
add(stateName, States.empty(t(nextStateName, EndConditions.matchTimed(matchTimer, duration))));
}
/**
* @param stateName the enum value to be associated with the wait state
* @param trueStateName the state to go to if the condition is true
* @param falseStateName the state to go to if the condition is false
* @param condition the boolean to decide which branch to go to
*/
public void addBranch(StateName stateName, StateName trueStateName, StateName falseStateName, boolean condition) {
add(stateName, States.branch(trueStateName, falseStateName, condition));
}
/**
* @param stateName the enum value to be associated with the wait state
* @param trueStateName the state to go to if the condition is true
* @param falseStateName the state to go to if the condition is false
* @param nullStateName the state to go to if the condition is null
* @param condition the boolean to decide which branch to go to
*/
public void addBranch(StateName stateName, StateName trueStateName, StateName falseStateName, StateName nullStateName, Boolean condition) {
add(stateName, States.branch(trueStateName, falseStateName, nullStateName, condition));
}
/**
* @param stateName the enum value to be associated with the wait state
* @param trueStateName the state to go to if the receiver returns true
* @param falseStateName the state to go to if the receiver returns false
* @param nullStateName the state to go to if the receiver returns null
* @param receiver the receiver that decides which branch to go to
*/
public void addBranch(StateName stateName, StateName trueStateName, StateName falseStateName, StateName nullStateName, ResultReceiver<Boolean> receiver) {
add(stateName, States.branch(trueStateName, falseStateName, nullStateName, receiver));
}
/**
* Adds an empty state that does nothing and moves to the next state
*
* @param stateName the name of the state
* @param nextStateName the name of the state to go to next
*/
public void addEmpty(StateName stateName, StateName nextStateName) {
add(stateName, States.empty(nextStateName));
}
public void addEmpty(StateName stateName, Map<StateName, EndCondition> transitions) {
add(stateName, States.empty(transitions));
}
/**
* Adds a stop state to the stateMap
*
* @param stateName name of the stop state
*/
public void addStop(StateName stateName) {
add(stateName, States.stop());
}
/**
* A state used to run a thread. Useful for off-loading computer intensive
* tasks such as image processing.
*
* @param stateName the name of the state
* @param nextStateName the next state to be transitioned to immediately
* @param thread the thread to be run at the start of the state
*/
public void addThread(StateName stateName, StateName nextStateName, Thread thread) {
add(stateName, States.runThread(nextStateName, thread));
}
/**
* Add a state that moves to continueStateName for the first n times it is
* called, then moves to doneStateName after that
*
* @param stateName the name of the state
* @param continueStateName will be transitioned to first
* @param doneStateName will be transitioned to after
* @param n the number of times to return continueStateName
*/
public void addCount(StateName stateName, StateName continueStateName, StateName doneStateName, int n) {
add(stateName, States.count(continueStateName, doneStateName, n));
}
/**
* Build the state machine with the added states
*
* @return the created state machine
* @see StateMachine
*/
public StateMachine build() {
return new StateMachine(stateMap, firstStateName);
}
/**
* Build the state machine with the added states
*
* @param firstStateName the state to start at
* @return the created state machine
* @see StateMachine
*/
public StateMachine build(StateName firstStateName) {
return new StateMachine(stateMap, firstStateName);
}
}