package geniusweb.protocol.session.mopac.phase; import java.util.List; import com.fasterxml.jackson.annotation.JsonAutoDetect; import com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility; import com.fasterxml.jackson.annotation.JsonSubTypes; import com.fasterxml.jackson.annotation.JsonTypeInfo; import geniusweb.actions.Action; import geniusweb.actions.PartyId; import geniusweb.inform.Inform; import geniusweb.protocol.ProtocolException; import geniusweb.protocol.session.mopac.PartyStates; import geniusweb.voting.VotingEvaluator; /** * A Phase is a part of the round structure. In each round parties have to take * multiple actions. Each action is part of a phase. * * Invariant: A phase object handles negotiation events, ensuring that the * events are handled according to the possible actions in this phase. A phase * object must always remain in a consistent state. It does so by modifying the * contained {@link PartyStates} as needed. *

* The standard exception handling is assumed: unchecked exceptions are thrown * only if there is a bug in the protocol. Because none of the functions in this * interface throws, any error must be either ignored or the party must be * kicked. */ @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.WRAPPER_OBJECT) @JsonAutoDetect(fieldVisibility = Visibility.ANY, getterVisibility = Visibility.NONE, setterVisibility = Visibility.NONE, isGetterVisibility = Visibility.NONE) @JsonSubTypes({ @JsonSubTypes.Type(value = OfferPhase.class), @JsonSubTypes.Type(value = OptInPhase.class), @JsonSubTypes.Type(value = VotingPhase.class) }) public interface Phase { public static final Long PHASE_MAXTIME = 30000l; // 30sec public static final Long PHASE_MINTIME = 100l; // 100 millisec /** * Handle an actor's action. If a {@link ProtocolException} occurs, this is * handled by updating the PartyStates * * @param actor the real actor (may differ from the actor contained in the * action) * @param action the action submitted by actor, which this phase can really * handle. * @param now the current time * @return new Phase */ public Phase with(PartyId actor, Action action, long now); /** * * @param e a {@link ProtocolException} * @return new Phase with a party disabled because it violated a protocol eg * breaking a websocket link. */ public Phase with(ProtocolException e); /** * * @return the inform object to send to all parties at start of phase. */ public Inform getInform(); /** * * @param now the current time * @return true iff past deadline or no more actions are allowed anyway. * (which usually means, all parties have done exactly one act). * Notice, this is the main reason that it is desirable to require * all parties to act exactly once in each phase. Without such a * rule, the protocol will always have to wait till the deadline. */ public boolean isFinal(long now); /** * * @return finished state. That means, all parties that did not act have * been kicked, new agreements have been computed, etc. */ public Phase finish(); /** * Determines the next phase. Resets the actions field. Can only be called * after {@link #finish()} * * @param now the current time * @param duration the max duration (ms) of the next phase. Must be between * {@link #PHASE_MINTIME} and {@link #PHASE_MAXTIME}. Also * make sure that now+duration is at most at the total * negotiation deadline. * @return the next phase, or null if negotiation is complete. */ public Phase next(long now, long duration); /** * @return the voting evaluator */ public VotingEvaluator getEvaluator(); /** * * @return time (ms since 1970) at which phase ends. The phase may end * before, but never after this. */ public long getDeadline(); /** * @return the party states. Notice that someone must call * {@link PartyStates#finish()} if passed the deadline. */ public PartyStates getPartyStates(); /** * @return the allowed actinos in this phase */ public abstract List> getAllowedActions(); }