This page is out of date (unsupported feature)

The States factory class is used to keep all the implementations of the State interface in a central location. All of these implementations use BasicAbstractState or AbstractState. These factory methods are used in the StateMachineBuilder.

ftc/electronvolts/statemachine/States.java

package ftc.electronvolts.statemachine;

import java.util.Map;

import ftc.electronvolts.util.ResultReceiver;

/**
 * This file was made by the electronVolts, FTC team 7393
 *
 * A factory class containing methods that return several useful states.
 *
 * To write your own State factory, make a class that extends this one and add
 * your own methods. 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 States {
    /**
     * Creates a state machine inside a state of another state machine
     * "Yo, dawg, we heard you like states so we put a state machine inside a
     * state of another state machine so your state can act while your state
     * machine acts, dawg."
     * 
     * @param subStateToState map that links the sub states to the states in the main state machine
     * @param stateMachineBuilder the builder to add the sub-states to
     * @return the created State
     */
    public static State subStates(final Map<StateName, StateName> subStateToState, final StateMachineBuilder stateMachineBuilder) {
        for (Map.Entry<StateName, StateName> entry : subStateToState.entrySet()) {
            StateName subState = entry.getKey();
            stateMachineBuilder.addStop(subState);
        }
        final StateMachine stateMachine = stateMachineBuilder.build();
        return new BasicAbstractState() {
            private StateName nextStateName;

            @Override
            public void init() {
            }

            @Override
            public boolean isDone() {
                stateMachine.act();
                for (Map.Entry<StateName, StateName> entry : subStateToState.entrySet()) {
                    StateName subState = entry.getKey();
                    StateName state = entry.getValue();
                    // if the current state is one of the ending sub-states
                    if (stateMachine.getCurrentStateName() == subState) {
                        // go to the corresponding super-state
                        nextStateName = state;
                        return true;
                    }
                }
                return false;
            }

            @Override
            public StateName getNextStateName() {
                return nextStateName;
            }
        };
    }

    /**
     * "Go back from whence you came -- and never return!"
     * 
     * A state that never returns
     *
     * @return the created state
     */
    public static State stop() {
        return new BasicAbstractState() {
            @Override
            public void init() {
            }

            @Override
            public boolean isDone() {
                return false;
            }

            @Override
            public StateName getNextStateName() {
                return null;
            }
        };
    }

    /**
     * "An empty-head thinks mischief is fun, but a mindful person relishes wisdom."
     * (Proverbs 2^10-1)
     * 
     * An empty state.
     *
     * @param transitions the transitions to be considered
     * @return the created State
     */
    public static State empty(Map<StateName, EndCondition> transitions) {
        return new AbstractState(transitions) {
            @Override
            public void init() {
            }

            @Override
            public void run() {
            }

            @Override
            public void dispose() {
            }
        };
    }

    /**
     * "Stop! The cup is full!" said Tokusan.
     * 
     * "Exactly," said Master Ryutan. "You are like this cup; you are full of
     * ideas. You come and ask for teaching, but your cup is full; I can't put
     * anything in. Before I can teach you, you'll have to empty your cup."
     * 
     * An empty state.
     *
     * @param nextStateName the next state to be run
     * @return the created State
     */
    public static State empty(final StateName nextStateName) {
        return new BasicAbstractState() {
            @Override
            public void init() {
            }

            @Override
            public boolean isDone() {
                return true;
            }

            @Override
            public StateName getNextStateName() {
                return nextStateName;
            }
        };
    }

    /**
     * "She set up a great loom in her palace, and set to weaving a web of
     * threads long and fine. Then she said to us: 'Young men, my suitors
     * now that the great Odysseus has perished, wait, though you are eager
     * to marry me, until I finish this web, so that my weaving will not be
     * useless and wasted.'"
     * ~Penelope, the Odyssey
     * 
     * A state used to run a thread. Useful for off-loading computer intensive
     * tasks such as image processing.
     *
     * @param nextStateName the next state to be run immediately
     * @param thread the thread to be run at the start of the state
     * @return the created State
     */
    public static State runThread(final StateName nextStateName, final Thread thread) {
        return new BasicAbstractState() {
            @Override
            public void init() {
                thread.start();
            }

            @Override
            public boolean isDone() {
                return true;
            }

            @Override
            public StateName getNextStateName() {
                return nextStateName;
            }
        };
    }

    /**
     * "The power of the Executive Branch is vested in the President of the
     * United States, who also acts as head of state and Commander-in-Chief of
     * the armed forces."
     * 
     * This is used to do branching and decision trees in the state machine
     * can be used for doing different things depending on which side of the
     * field you are on
     *
     * @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
     * @return the created State
     */
    public static State branch(final StateName trueStateName, final StateName falseStateName, final boolean condition) {
        return new BasicAbstractState() {
            @Override
            public void init() {
            }

            @Override
            public boolean isDone() {
                return true;
            }

            @Override
            public StateName getNextStateName() {
                if (condition) {
                    return trueStateName;
                } else {
                    return falseStateName;
                }
            }
        };
    }

    /**
     * "Established by Article I of the Constitution, the Legislative Branch
     * consists of the House of Representatives and the Senate, which together
     * form the United States Congress."
     * 
     * This is used to do branching and decision trees in the state machine
     * can be used for doing different things depending on which side of the
     * field you are on
     *
     * @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
     * @return the created State
     */
    public static State branch(final StateName trueStateName, final StateName falseStateName, final StateName nullStateName, final Boolean condition) {
        return new BasicAbstractState() {
            @Override
            public void init() {
            }

            @Override
            public boolean isDone() {
                return true;
            }

            @Override
            public StateName getNextStateName() {
                if (condition == null) {
                    return nullStateName;
                } else if (condition) {
                    return trueStateName;
                } else {
                    return falseStateName;
                }
            }
        };
    }

    /**
     * "Where the Executive and Legislative branches are elected by the people,
     * members of the Judicial Branch are appointed by the President and
     * confirmed by the Senate."
     * 
     * This is used to do branching and decision trees in the state machine
     * using a result
     * acquired while it is running, and to communicate between threads
     *
     * @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
     * @return the created State
     */
    public static State branch(final StateName trueStateName, final StateName falseStateName, final StateName nullStateName, final ResultReceiver<Boolean> receiver) {
        return new BasicAbstractState() {
            @Override
            public void init() {
            }

            @Override
            public boolean isDone() {
                return receiver.isReady();
            }

            @Override
            public StateName getNextStateName() {
                if (receiver.getValue() == null) {
                    return nullStateName;
                } else if (receiver.getValue()) {
                    return trueStateName;
                } else {
                    return falseStateName;
                }
            }
        };
    }

    /**
     * Count von Count: Five bananas. Six bananas. SEVEN BANANAS!
     * [thunder strikes]
     * Count von Count: Ah, ah, ah. Now, that was silly. Wouldn't you agree, my
     * bats? Ah, ah, ah.
     * 
     * Moves to continueStateName for the first n times it is called, then moves
     * to doneStateName after that
     * 
     * @param continueStateName will be transitioned to first
     * @param doneStateName will be transitioned to after
     * @param n the number of times to return continueStateName
     * @return the created State
     */
    public static State count(final StateName continueStateName, final StateName doneStateName, final int n) {
        return new BasicAbstractState() {
            int i = 0;

            @Override
            public void init() {
                i++;
            }

            @Override
            public boolean isDone() {
                return true;
            }

            @Override
            public StateName getNextStateName() {
                return i <= n ? continueStateName : doneStateName;
            }
        };
    }
}