- Timestamp:
- 10/06/20 13:12:20 (4 years ago)
- Location:
- protocol
- Files:
-
- 5 added
- 31 edited
Legend:
- Unmodified
- Added
- Removed
-
protocol/pom.xml
r23 r24 6 6 <groupId>geniusweb</groupId> 7 7 <artifactId>protocol</artifactId> 8 <version>1.5. 2</version> <!-- must equal ${geniusweb.version} -->8 <version>1.5.3</version> <!-- must equal ${geniusweb.version} --> 9 9 <packaging>jar</packaging> 10 10 … … 17 17 <passwd>${env.ARTIFACTORY_PASS}</passwd> 18 18 <jackson-2-version>2.9.10</jackson-2-version> 19 <geniusweb.version>1.5. 2</geniusweb.version>19 <geniusweb.version>1.5.3</geniusweb.version> 20 20 </properties> 21 21 … … 28 28 29 29 <dependencies> 30 30 <dependency> 31 31 <groupId>geniusweb</groupId> 32 32 <artifactId>issuevalue</artifactId> … … 43 43 <version>${geniusweb.version}</version> 44 44 </dependency> 45 <!-- <dependency> 46 <groupId>geniusweb</groupId> 47 <artifactId>party</artifactId> 48 <version>${geniusweb.version}</version> 49 </dependency> 50 --> <dependency> 45 <dependency> 51 46 <groupId>geniusweb</groupId> 52 47 <artifactId>references</artifactId> … … 191 186 <groupId>org.apache.maven.plugins</groupId> 192 187 <artifactId>maven-javadoc-plugin</artifactId> 193 <version> 2.10.1</version>188 <version>3.2.0</version> 194 189 <executions> 195 190 <execution> … … 198 193 <goal>jar</goal> 199 194 </goals> 200 <configuration>201 <additionalparam>${javadoc.opts}</additionalparam>202 <additionalparam>-Xdoclint:none</additionalparam>203 </configuration>204 195 </execution> 205 196 </executions> -
protocol/src/main/java/geniusweb/protocol/NegoProtocol.java
r21 r24 13 13 import geniusweb.protocol.partyconnection.ProtocolToPartyConnFactory; 14 14 import geniusweb.protocol.session.SessionProtocol; 15 import geniusweb.protocol.session.SessionSettings;16 15 import geniusweb.protocol.session.SessionState; 17 16 import geniusweb.protocol.tournament.TournamentProtocol; … … 30 29 * 31 30 * A protocol is mutable because the incoming connections cause state changes. 32 * But it is recommended to push all changing properties into the state. 31 * But it is recommended to push changing properties into the state so that the 32 * complete state can be recovered and analysed. 33 33 * <p> 34 34 * Because a protocol contains an internal state, it can be used only once. 35 * <p>36 35 * <p> 37 36 * The protocol can emit a {@link CurrentState} event at any time. It should do … … 42 41 * which it can resolve received {@link Reference}s. <br> 43 42 * First call to instances <b>must be</b> 44 * {@link #start( SessionSettings, ConnectionFactory)}.43 * {@link #start(ProtocolToPartyConnFactory)}. 45 44 * 46 45 * <h2>Ensure time deadline</h2> … … 48 47 * The protocol also needs to keep an eye on the deadline and take appropriate 49 48 * actions when the deadline is reached. <br> 50 * A protocol should emit a {@link SessionEnded} or {@link TournamentEnded}51 * event when it is finished.52 49 * <p> 53 50 * All protocol implementations must ensure that the deadline is kept and that … … 73 70 * <p> 74 71 * 75 * All errors are to be handled through {@link SessionState#getError()} 76 * except for plain {@link IllegalArgumentException}s. <br> 72 * All errors are to be handled through {@link SessionState#getResult()} 73 * except for bugs that use {@link RuntimeException} like 74 * {@link IllegalArgumentException}s. <br> 77 75 * The protocol usually uses the incoming connections to keep running. It 78 76 * does not need to run in a separate thread or so. -
protocol/src/main/java/geniusweb/protocol/NegoState.java
r21 r24 11 11 12 12 /** 13 * The current state of the session/tournament. Must be serializabl;e so that it 14 * can be restarted if a crash occurs. 13 * The current state of the session/tournament. Must be (de)serializabl;e so 14 * that it can be restarted if a crash occurs. Notice that this restart 15 * functionality is not yet available. 16 * <p> 17 * In general the state contains all the information to control the flow of the 18 * negotiation: who did what, are we finished, etc. This object may be stored to 19 * record the final result as well 15 20 */ 16 21 @JsonAutoDetect(fieldVisibility = Visibility.ANY, getterVisibility = Visibility.NONE, setterVisibility = Visibility.NONE, isGetterVisibility = Visibility.NONE) -
protocol/src/main/java/geniusweb/protocol/ProtocolException.java
r21 r24 5 5 6 6 /** 7 * thrown if a {@link Party} violates the protocols (that includes 8 * disconnecting). 7 * thrown if a Party violates the protocols (that includes disconnecting). 9 8 */ 10 9 public class ProtocolException extends Exception { -
protocol/src/main/java/geniusweb/protocol/partyconnection/ProtocolToPartyConnections.java
r21 r24 49 49 50 50 /** 51 * Broadcast info to all parties 51 * Broadcast info to all parties. Notice that the broadcast immediately 52 * aborts if an error occurs and remaining parties will not receive the 53 * event. Therefore it is recommended to instead send to all parties 54 * individually to ensure all parties are handled individually. 52 55 * 53 56 * @param info the {@link Inform} to broadcast 57 * @throws IOException if the send fails. 54 58 */ 55 59 public void broadcast(Inform info) throws IOException { … … 68 72 69 73 /** 70 * @param i 74 * @param i the connection number 71 75 * @return the ith connection 72 76 */ -
protocol/src/main/java/geniusweb/protocol/session/SessionResult.java
r23 r24 67 67 68 68 /** 69 * 8return the final {@link Agreements} of the session. May be empty, not70 * null69 * @return the final {@link Agreements} of the session. May be empty, not 70 * null 71 71 */ 72 72 public Agreements getAgreements() { -
protocol/src/main/java/geniusweb/protocol/session/SessionState.java
r21 r24 18 18 * and the parties currently connected. <br> 19 19 * The state checks if transitions (Actions from the party) are following the 20 * protocol, and thus implement most of the protocol . See 21 * {@link #with(geniusweb.actions.PartyId, Action)}. <br> 22 * 23 * Use {@link #with(geniusweb.actions.PartyId, Action)} and 24 * {@link #with(geniusweb.actions.PartyId, tudelft.utilities.connection.Connection)} 25 * to create a new state <br> 26 * 20 * protocol, and thus implement most of the protocol . <br> 27 21 * 28 22 * If protocol errors occur, these should be stored in the state and the state 29 * should become {@link #isFinal( )}. Throwing should happen only in case of a30 * bug.<br>23 * should become {@link #isFinal(long)}. Throwing should happen only in case of 24 * a bug.<br> 31 25 * 32 26 * Implementations should be immutable (to ensure thread safety, testability … … 66 60 * @return the current standing agreement, or null if there is no agreement 67 61 * at this point. An agreement does not necessarily mean 68 * {@link #isFinal( )}.62 * {@link #isFinal(long)}. 69 63 */ 70 64 Agreements getAgreements(); … … 72 66 /** 73 67 * 74 * @return the {@link SessionResult}. Assumes {@link #isFinal(long)}. result 75 * may be undefined if not. 68 * @return the {@link SessionResult} which is a short report of the final 69 * outcome. Assumes {@link #isFinal(long)}. result may be undefined 70 * if not. 76 71 */ 77 72 SessionResult getResult(); -
protocol/src/main/java/geniusweb/protocol/session/amop/AMOP.java
r21 r24 28 28 import geniusweb.protocol.CurrentNegoState; 29 29 import geniusweb.protocol.ProtocolException; 30 import geniusweb.protocol.WillBeCalled;31 30 import geniusweb.protocol.partyconnection.ProtocolToPartyConn; 32 31 import geniusweb.protocol.partyconnection.ProtocolToPartyConnFactory; … … 51 50 * <h1>parameter</h1> AMOP parties can receive a parameter: minVotes containing 52 51 * a Double. If set, the AMOP protocol checks that all {@link Votes} from that 53 * party have {@link Vote#getMinPower()} > minVotes. 54 * <h1>Protocol steps</h1> The protocol tries to start all parties. If not all 55 * parties start, the parties are freed up and another attempt is done to start 56 * all parties some time later. 52 * party have {@link Vote#getMinPower()} > minVotes. 53 * <h1>Protocol steps</h1> 54 * <ol> 55 * <li>The protocol tries to start all parties. If not all parties start, the 56 * parties are freed up and another attempt is done to start all parties some 57 * time later. 57 58 * <li>the variable remainingparties = {all parties} 58 59 * <li>The session deadline clock now starts ticking. 59 60 * <li>All parties are sent their settings. 60 * <li>Loop until {@link Deadline} is reached or |remainingparties| <2:61 * <li>Loop until {@link Deadline} is reached or |remainingparties|<2: 61 62 * <ol> 62 63 * <li>protocol sends {@link YourTurn} to all remainingparties. Each party now 63 64 * must submit an {@link Offer} within {@link #PHASE_TIME} seconds. If a party 64 65 * fails to submit it is send Finished and removed from from remainingparties. 65 * <li>protocol sends a {@link Voting} containing a List <Bid> containing all66 * received {@link Bid}s. Each party must place his {@link Votes} within67 * {@link #PHASE_TIME} seconds. If a party does not submit, it is send a66 * <li>protocol sends a {@link Voting} containing a List of {@link Bid} 67 * containing all received {@link Bid}s. Each party must place his {@link Votes} 68 * within {@link #PHASE_TIME} seconds. If a party does not submit, it is send a 68 69 * {@link Finished} and removed from remainingparties. Previous votes for the 69 70 * same bid do not count. But see {@link Agreements}. 70 * <li>The protocol determines a maximum sized subset of size N >=2 of the votes71 * for bid B for which the vote conditions hold. If there is such a subset, the72 * parties that placed these votes reached an agreement. They are added to the73 * a greement set, sent the {@link Finished} info and terminated. They are74 * removed from the remainingparties.71 * <li>The protocol determines a maximum sized subset of size N≥2 of the 72 * votes for bid B for which the vote conditions hold. If there is such a 73 * subset, the parties that placed these votes reached an agreement. They are 74 * added to the agreement set, sent the {@link Finished} info and terminated. 75 * They are removed from the remainingparties. 75 76 * </ol> 76 77 * <li>Any remaining parties are sent a {@link Finished} object without … … 109 110 /** 110 111 * 111 * @param state normally the initial state coming from SAOPSettings 112 * @param state normally the initial state coming from SAOPSettings 113 * @param logger the {@link Reporter} to use 112 114 */ 113 115 public AMOP(AMOPState state, Reporter logger) { … … 218 220 * overridable factory method, used for testing. 219 221 * 220 * @param r 221 * @param delayMs 222 * @param r the {@link Runnable} that will be called 223 * @param delayMs the time after which r will be called 222 224 * @return new WillBeCalled(r,delayms) 223 225 */ -
protocol/src/main/java/geniusweb/protocol/session/amop/AMOPSettings.java
r21 r24 30 30 * protocol. But SAOP can be initialized with less, for 31 31 * use in TournamentSettings. 32 * @param deadline 33 * @param minimumVotes the minimum number of votes allowed for a bid. 32 * @param deadline the {@link Deadline} of the negotiation 34 33 */ 35 34 @JsonCreator -
protocol/src/main/java/geniusweb/protocol/session/amop/AMOPState.java
r23 r24 197 197 198 198 /** 199 * @param actor the actor that did this action. Can be used to check 200 * if action is valid. NOTICE caller has to make sure 201 * the current state is not final. MUST NOT be null. 202 * @param action the action that was proposed by actor. MUST NOT be 203 * null. 204 * @param currentTimeMs the current time in ms since 1970, see 205 * {@link System#currentTimeMillis()} 199 * @param actor the actor that did this action. Can be used to check if 200 * action is valid. NOTICE caller has to make sure the current 201 * state is not final. MUST NOT be null. 202 * @param action the action that was proposed by actor. MUST NOT be null. 206 203 * @return new SessionState with the action added as last action. 207 204 * @throws ProtocolException if actor is violating the protocol -
protocol/src/main/java/geniusweb/protocol/session/mopac/MOPAC.java
r23 r24 2 2 3 3 import java.io.IOException; 4 import java.util.Collections; 4 5 import java.util.List; 5 6 import java.util.Timer; … … 55 56 * parties are freed up and another attempt is done to start all parties some 56 57 * time later. 57 * <li>the variable remainingparties = {all parties}58 58 * <li>The session deadline clock now starts ticking. 59 59 * <li>remainingparties are sent their settings. 60 * <li>Loop until {@link Deadline} is reached or |remainingparties| <2:60 * <li>Loop until {@link Deadline} is reached or |remainingparties| ≤ 2: 61 61 * <ol> 62 62 * <li>protocol sends {@link YourTurn} to all remainingparties. Each party now 63 63 * must submit an {@link Offer} within {@link Phase#PHASE_MAXTIME} seconds. If a 64 64 * party fails to submit it is removed from from remainingparties. 65 * <li>protocol sends a {@link Voting} containing a List <Bid>containing all66 * received {@link Bid}s. Each party must place his {@link Votes} within 67 * {@link #PHASE_TIME} seconds. If a party does not submit, it is terminated and68 * removed from remainingparties. Previous votes for the same bid do not count.69 * But see {@link Agreements}. A party that misbehaves after submitting its vote70 * isremoved but it Votes remain standing.65 * <li>protocol sends a {@link Voting} containing a List of Bid containing all 66 * received {@link Bid}s. Each party must place his {@link Votes} within the 67 * provided deadline. If a party does not submit, it is terminated and removed 68 * from remainingparties. Previous votes for the same bid do not count. But see 69 * {@link Agreements}. A party that misbehaves after submitting its vote is 70 * removed but it Votes remain standing. 71 71 * <li>protocol sends to all remainingparties a OptIn containing all received 72 * votes. Each party now must submit again a {@link Votes} object within 73 * {@link #PHASE_TIME} seconds. This new Votes must equal or extend the previous74 * Votes of theparty.75 * <li>The protocol use the {@link MOPACState#getEvaluator()} to determine the76 * ... . If there is such a subset, the parties that placed these votes reached77 * an agreement. They are added to the agreement set, sent the {@link Finished}78 * info and terminated. They areremoved from the remainingparties.72 * votes. Each party now must submit again a {@link Votes} object within the 73 * deadline. This new Votes must equal or extend the previous Votes of the 74 * party. 75 * <li>The protocol uses the {@link Phase#getEvaluator()} to determine the 76 * agreements from the votes. If there are agreements, the parties that placed 77 * these votes reached an agreement. They are moved to the agreement set and 78 * removed from the remainingparties. 79 79 * </ol> 80 80 * <li>Any remaining parties are sent a {@link Finished} object without … … 114 114 private final Reporter log; 115 115 private MOPACState state = null; // mutable! 116 /** 117 * the existing party connections. we assume ownership of this so it should 118 * not be modified although connections may of course break. mutable! 119 */ 120 private ProtocolToPartyConnections connections = new ProtocolToPartyConnections( 121 Collections.emptyList()); 116 122 117 123 /** … … 124 130 /** 125 131 * 126 * @param state normally the initial state coming from SAOPSettings 132 * @param state normally the initial state coming from SAOPSettings 133 * @param logger the {@link Reporter} to use 127 134 */ 128 135 public MOPAC(MOPACState state, Reporter logger) { … … 145 152 ProtocolToPartyConnFactory connectionfactory) { 146 153 try { 147 // System.out.println("starting MOPAC");148 // we're in Phase.INIT still149 154 connect(connectionfactory); 150 setupParties();151 long now = System.currentTimeMillis();152 state = state.initPhase(now);153 startPhase(now);154 155 } catch (Throwable e) { 155 e.printStackTrace(); 156 handleError("Failed to start MOPAC session", new PartyId("BUG"), e); 157 } 156 /** We can't {@link #handleError} yet. FIXME */ 157 throw new RuntimeException("Failed to connect", e); 158 } 159 long now = System.currentTimeMillis(); 160 state = state.initPhase( 161 ProgressFactory.create(state.getSettings().getDeadline(), now), 162 now); 163 setupParties(now); 164 startPhase(now); 165 158 166 } 159 167 … … 212 220 .map(parti -> (parti.getParty().getPartyRef())) 213 221 .collect(Collectors.toList()); 214 List<ProtocolToPartyConn> connections = null;215 222 log.log(Level.INFO, "MOPAC connect " + parties); 216 while (connections == null) { 223 List<ProtocolToPartyConn> newconnections = null; 224 while (newconnections == null) { 217 225 try { 218 connections = connectionfactory.connect(parties);226 newconnections = connectionfactory.connect(parties); 219 227 } catch (NoResourcesNowException e) { 220 228 long waitms = e.getLater().getTime() … … 228 236 } 229 237 for (int i = 0; i < participants.size(); i++) { 230 state = state.with(connections.get(i), participants.get(i)); 238 ProtocolToPartyConn conn = newconnections.get(i); 239 connections = connections.with(conn); 240 state = state.with(conn.getParty(), participants.get(i)); 231 241 } 232 242 } … … 239 249 * part of the interface. 240 250 * 241 * @throws ProtocolException if a party does not follow the protocol 242 */ 243 protected synchronized void setupParties() throws ProtocolException { 244 for (ProtocolToPartyConn conn : state.getConnections()) { 245 conn.addListener(action -> actionRequest(conn, action, 246 System.currentTimeMillis())); 247 } 248 Long now = System.currentTimeMillis(); 249 state = state.with( 250 ProgressFactory.create(state.getSettings().getDeadline(), now)); 251 for (ProtocolToPartyConn connection : state.getConnections()) { 251 * @param now the current time. 252 */ 253 protected synchronized void setupParties(long now) { 254 for (ProtocolToPartyConn conn : connections) { 255 conn.addListener(action -> actionRequest(conn, action, now)); 256 } 257 for (ProtocolToPartyConn connection : connections) { 252 258 try { 253 259 sendSettings(connection); … … 257 263 } 258 264 } 259 260 265 } 261 266 … … 357 362 .getNegotiatingParties()) { 358 363 try { 359 state.getConnections().get(party).send(info);364 connections.get(party).send(info); 360 365 } catch (IOException e) { 361 handleError("Party seems to have disconnected", party, e); 362 } 363 } 364 } 365 366 /** 367 * Update state to include the given error and closes the party. 368 * 369 * @param message The message to attach to the error 370 * @param party the party where the error occured 371 * @param e the exception that occured. 372 */ 373 private void handleError(final String message, final PartyId partyid, 374 final Throwable e) { 375 if (e instanceof ProtocolException) { 376 state = state.with((ProtocolException) e); 377 } else { 378 state = state.with(new ProtocolException(message, partyid, e)); 379 } 380 log.log(Level.WARNING, 381 "MOPAC intercepted error from party " + partyid + ":" + message, 382 e); 383 } 384 385 // /** 386 // * Sets the new state. If the new state is final, the finish-up procedure is 387 // * executed. All state changes go through here to ensure we check isFinal 388 // * before any state change. 389 // * 390 // * @param newstate the new state. 391 // */ 392 // private synchronized void setState(MOPACState newstate) { 393 // long now = System.currentTimeMillis(); 394 // if (state.isFinal(now)) { 395 // endNegotiation(); 396 // return; 397 // } 398 // 399 // this.state = newstate; 400 // if (newstate.isFinal(now)) { 401 // endNegotiation(); 402 // } 403 // } 366 state = state.with(new ProtocolException( 367 "Party seems to have disconnected", party, e)); 368 } 369 } 370 } 404 371 405 372 /** … … 413 380 finished = true; 414 381 Finished info = new Finished(state.getAgreements()); 415 for (ProtocolToPartyConn conn : state.getConnections()) {382 for (ProtocolToPartyConn conn : connections) { 416 383 try { 417 384 conn.send(info); -
protocol/src/main/java/geniusweb/protocol/session/mopac/MOPACSettings.java
r21 r24 19 19 /** 20 20 * Settings for MOPAC negotiation. in MOPAC, each party may get a "power" 21 * parameter containing an natural number >=1.21 * parameter containing an natural number ≤1. 22 22 */ 23 23 public class MOPACSettings implements SessionSettings { … … 30 30 * @param participants the list of {@link PartyWithProfile} in clockwise 31 31 * order. There must be at least 2 to run the MOPAC 32 * protocol. But SAOP can be initialized with less, for 33 * use in TournamentSettings. 34 * 35 * All provided participants must 36 * 37 * @param deadline 38 * @param minimumVotes the minimum number of votes allowed for a bid. 32 * protocol. This is not tested in the constructor 33 * because this can be initialized with less, for use in 34 * TournamentSettings. 35 * @param deadline the {@link Deadline} for the negotiation 36 * @param votingeval the {@link VotingEvaluator} to use. 39 37 */ 40 38 @JsonCreator … … 90 88 91 89 @Override 92 public SessionSettings with(TeamOfPartiesAndProfiles party) {90 public MOPACSettings with(TeamOfPartiesAndProfiles party) { 93 91 if (!(party instanceof OnePartyTeam)) 94 92 throw new IllegalArgumentException( -
protocol/src/main/java/geniusweb/protocol/session/mopac/MOPACState.java
r23 r24 17 17 import geniusweb.progress.Progress; 18 18 import geniusweb.progress.ProgressRounds; 19 import geniusweb.protocol.NegoProtocol; 19 20 import geniusweb.protocol.ProtocolException; 20 import geniusweb.protocol.partyconnection.ProtocolToPartyConn;21 import geniusweb.protocol.partyconnection.ProtocolToPartyConnections;22 21 import geniusweb.protocol.session.SessionResult; 23 22 import geniusweb.protocol.session.SessionState; … … 27 26 import geniusweb.protocol.session.saop.SAOPSettings; 28 27 import geniusweb.references.PartyWithProfile; 29 import geniusweb.voting.VotingEvaluator; 30 28 29 /** 30 * Keeps track of the current {@link Phase}. Adds initializing stuff and 31 * time/deadline checking. This state does not contain connections, this assumes 32 * that someone else handles (i.e. {@link NegoProtocol} that and the connections 33 * with the parties and that negotiation events are just pumped in from there. 34 * <p> 35 * This object is a bit tricky. It has two states 36 * <ol> 37 * <li>The initial state, where phase=null and connections are being made to all 38 * parties. At this point, problems can not be handled nicely yet because there 39 * are no PartyId's for problematic parties 40 * <li>The working state, where all parties are connected and all problems can 41 * be connected to an offending party. 42 * </ol> 43 */ 31 44 public class MOPACState implements SessionState { 32 45 33 private final Phase phase; 46 private final Phase phase; // maybe null while initializing 34 47 private final MOPACSettings settings; 35 48 private final Map<PartyId, PartyWithProfile> partyprofiles; 36 private final ProtocolToPartyConnections connections;37 49 private final List<Action> actions; 38 50 private final Progress progress; … … 44 56 */ 45 57 public MOPACState(MOPACSettings settings) { 46 this(null, Arrays.asList(), 47 new ProtocolToPartyConnections(Collections.emptyList()), null, 48 settings, Collections.emptyMap()); 58 this(null, Arrays.asList(), null, settings, Collections.emptyMap()); 49 59 50 60 } … … 54 64 * set something only after we have connections. 55 65 * @param actions the legal actions that have been done in the 56 * negotiation. A new-sub-list is added for each phase 57 * change. It is assumed that the last element of the 58 * list is the list with actions taken in the current 59 * phase. first action in first list is the oldest. 60 * This MUST NOT contain illegal actions. Parties doing 61 * illegal actions are killed and the offending action 62 * ends up in the stacktrace. Previous actions of 63 * crashed parties remain standing and valid. 64 * @param conns the existing party connections. we assume ownership 65 * of this so it should not be modified although 66 * connections may of course break. 66 * negotiation. {@link PartyStates#getActions()} is 67 * called to collect the actions after the phase is 68 * finished.first action in list is the oldest. This 69 * will not contain actions that immediately led to an 70 * agreement, because {@link PartyStates} removes the 71 * actions that led to an agreement. This MUST NOT 72 * contain illegal actions. Parties doing illegal 73 * actions are killed and the offending action ends up 74 * in the stacktrace. Previous actions of crashed 75 * parties remain standing and valid. 67 76 * @param progress the {@link Progress} line. can be null if not yet 68 * known. This happens because during setup we first 69 * add all connections, and only when we have that we 70 * set the correct deadline. 77 * known. null happens because during initialization 78 * phase the protocol first add all connections. During 79 * this time, parties may already enter the 80 * failed/exception state. 71 81 * @param settings the {@link SAOPSettings} 72 82 * @param partyprofiles map with the {@link PartyWithProfile} for connected 73 83 * parties. null is equivalent to an empty map. 74 * @param evaluator the {@link VotingEvaluator}75 84 */ 76 85 @JsonCreator 77 86 protected MOPACState(@JsonProperty("phase") Phase phase, 78 87 @JsonProperty("actions") List<Action> actions, 79 @JsonProperty("connections") ProtocolToPartyConnections conns,80 88 @JsonProperty("progress") Progress progress, 81 89 @JsonProperty("settings") MOPACSettings settings, … … 83 91 this.phase = phase; 84 92 this.actions = actions; 85 this.connections = conns;86 93 this.progress = progress; 87 94 this.settings = settings; … … 90 97 91 98 /** 92 * Can be called after all connections are initialized. 93 * 94 * @param now current time ms since 1970 95 * 96 * @return state with the initial partystates set. 97 */ 98 public MOPACState initPhase(long now) { 99 PartyStates partyStates = new PartyStates(getPowers()); 100 Phase firstPhase = new OfferPhase(null, partyStates, 101 now + getAvailablePhaseTime(now), 102 settings.getVotingEvaluation()); 103 return new MOPACState(firstPhase, actions, connections, progress, 104 settings, partyprofiles); 105 } 106 107 @Override 108 public List<Action> getActions() { 109 return Collections.unmodifiableList(actions); 110 } 111 112 @Override 113 public Progress getProgress() { 114 return progress; 115 } 116 117 public Map<PartyId, PartyWithProfile> getPartyProfiles() { 118 return Collections.unmodifiableMap(partyprofiles); 119 } 120 121 /** 122 * @return all current/remaining active party connections. Finished/crashed 123 * parties should be removed immediately. 124 */ 125 public ProtocolToPartyConnections getConnections() { 126 return connections; 127 } 128 129 /** 130 * @param now current time ms since 1970 131 * @return the max possible duration in ms of the NEXT phase. Maybe 0 or 132 * negative if past deadline. 133 */ 134 private Long getAvailablePhaseTime(long now) { 135 // explicit check, to check also the round counts. 136 if (incrementProgress().isPastDeadline(now + Phase.PHASE_MINTIME)) 137 return 0l; 138 return Math.min(progress.getTerminationTime().getTime() - now, 139 Phase.PHASE_MAXTIME); 140 } 141 142 /** 143 * 144 * @param connection the new {@link ProtocolToPartyConn} 145 * @param partyprofile the {@link PartyWithProfile} that is associated with 146 * this state 147 * @return new {@link MOPACState} with the new connection added. This call 148 * ignores the progress (does not check isFinal) because we uses 149 * this during the setup where the deadline is not yet relevant. 150 */ 151 protected MOPACState with(ProtocolToPartyConn connection, 152 PartyWithProfile partyprofile) { 153 if (phase != null) 154 throw new IllegalStateException( 155 "Adding connections only allowed while initializing"); 156 157 ProtocolToPartyConnections newconns = getConnections().with(connection); 158 Map<PartyId, PartyWithProfile> newprofiles = new HashMap<>( 159 partyprofiles); 160 newprofiles.put(connection.getParty(), partyprofile); 161 return new MOPACState(null, actions, newconns, progress, settings, 162 newprofiles); 163 } 164 165 /** 166 * @param id the {@link PartyId} of the party that failed. 167 * @param e the {@link ProtocolException} that occurred in the party 168 * @return a new state with the error set. 169 */ 170 public MOPACState with(ProtocolException e) { 171 return new MOPACState(phase.with(e), actions, connections, progress, 172 settings, partyprofiles); 173 } 174 175 /** 176 * Sets the progress for this session. Can be set only if progress=null. 177 * Should be set in INIT phase. 178 * 179 * @param newprogress the new progress 180 * @return new {@link MOPACState} with the progress set 181 */ 182 public MOPACState with(Progress newprogress) { 99 * Sets the progress for this session and initial phase. Must be called 100 * after all parties have been connected with 101 * {@link #with(PartyId, PartyWithProfile)}. 102 * 103 * @param newprogress the initial {@link Progress} typically matching the 104 * settings deadline object 105 * @param now current time ms since 1970 106 * 107 * @return state with the initial partystates , progress set. 108 */ 109 public MOPACState initPhase(Progress newprogress, long now) { 183 110 if (progress != null || newprogress == null || phase != null) { 184 111 throw new IllegalArgumentException( 185 112 "progress must be null, newprogress must be not null and phase must be INIT"); 186 113 } 187 return new MOPACState(phase, actions, connections, newprogress, 188 getSettings(), partyprofiles); 114 115 PartyStates partyStates = new PartyStates(getPowers()); 116 Phase firstPhase = new OfferPhase(partyStates, 117 now + getAvailablePhaseTime(newprogress, now), 118 settings.getVotingEvaluation()); 119 return new MOPACState(firstPhase, actions, newprogress, settings, 120 partyprofiles); 121 } 122 123 @Override 124 public List<Action> getActions() { 125 return Collections.unmodifiableList(actions); 126 } 127 128 @Override 129 public Progress getProgress() { 130 return progress; 131 } 132 133 @Override 134 public Agreements getAgreements() { 135 return phase.getPartyStates().getAgreements(); 136 } 137 138 @Override 139 public MOPACSettings getSettings() { 140 return settings; 141 } 142 143 public Map<PartyId, PartyWithProfile> getPartyProfiles() { 144 return Collections.unmodifiableMap(partyprofiles); 145 } 146 147 @Override 148 public boolean isFinal(long now) { 149 return phase != null && phase.isFinal(now) && !isNewPhasePossible(now); 150 } 151 152 @Override 153 public SessionResult getResult() { 154 return new SessionResult(partyprofiles, getAgreements(), 155 Collections.emptyMap(), null); 156 } 157 158 /** 159 * @param progress the Progress that needs to be checked 160 * @param now current time ms since 1970 161 * @return the max possible duration in ms of a phase considering the 162 * progress. 163 */ 164 private static Long getAvailablePhaseTime(Progress aprogress, long now) { 165 return Math.min(aprogress.getTerminationTime().getTime() - now, 166 Phase.PHASE_MAXTIME); 167 } 168 169 /** 170 * @param id the new {@link PartyId} 171 * @param partyprofile the {@link PartyWithProfile} that is associated with 172 * this state 173 * @return new {@link MOPACState} with the new party added. This call 174 * ignores the progress (does not check isFinal) because we uses 175 * this during the setup where the deadline is not yet relevant. 176 */ 177 protected MOPACState with(PartyId id, PartyWithProfile partyprofile) { 178 if (phase != null) 179 throw new IllegalStateException( 180 "Adding connections only allowed while initializing"); 181 182 Map<PartyId, PartyWithProfile> newprofiles = new HashMap<>( 183 partyprofiles); 184 newprofiles.put(id, partyprofile); 185 return new MOPACState(null, actions, progress, settings, newprofiles); 186 } 187 188 /** 189 * @param e the {@link ProtocolException} that occured 190 * @return a new state with the error set. You MUST have called 191 * {@link #initPhase(Progress, long)} before using this 192 */ 193 public MOPACState with(ProtocolException e) { 194 return new MOPACState(phase.with(e), actions, progress, settings, 195 partyprofiles); 189 196 } 190 197 … … 202 209 Math.min(remainingNegoTime, Phase.PHASE_MAXTIME)); 203 210 204 return new MOPACState(newphase, actions, connections, 205 incrementProgress(), getSettings(), partyprofiles); 206 } 207 208 /** 209 * 210 * @return the next progress. Progress round advances if phase is 211 * {@link OptIn}. 212 */ 213 private Progress incrementProgress() { 214 if (progress instanceof ProgressRounds && phase instanceof OptInPhase) 215 return ((ProgressRounds) progress).advance(); 216 return progress; 217 } 218 219 @Override 220 public boolean isFinal(long now) { 221 return phase != null && phase.isFinal(now) && !isNewPhasePossible(now); 211 return new MOPACState(newphase, actions, increment(progress, phase), 212 getSettings(), partyprofiles); 222 213 } 223 214 … … 225 216 * When this is called, all parties should have acted. 226 217 * 227 * @param now 228 * @return 218 * @param now current time 219 * @return true if there are still >2 parties active and we have enough 220 * time for a new phase. 229 221 */ 230 222 public boolean isNewPhasePossible(long now) { 231 223 // System.out.println("phase=" + phase); 232 boolean a = phase.getPartyStates().getNegotiatingParties().size() >= 2 233 && getAvailablePhaseTime(now) > Phase.PHASE_MINTIME; 234 // System.out.println("newstate possible:" + a); 235 return a; 236 } 237 238 @Override 239 public Agreements getAgreements() { 240 return phase.getPartyStates().getAgreements(); 241 } 242 243 @Override 244 public MOPACSettings getSettings() { 245 return settings; 224 Progress newprogress = increment(progress, phase); 225 if (newprogress.isPastDeadline(now + Phase.PHASE_MINTIME)) 226 return false; 227 228 return phase.getPartyStates().getNegotiatingParties().size() >= 2 229 && getAvailablePhaseTime(newprogress, 230 now) > Phase.PHASE_MINTIME; 246 231 } 247 232 … … 261 246 * @param now the current time in ms since 1970, see 262 247 * {@link System#currentTimeMillis()} 248 * @return new {@link MOPACState} with the action checked and registered. If 249 * the action is not allowed, the new state may be that the actor is 250 * in the exception list. 263 251 */ 264 252 265 253 public MOPACState with(PartyId actor, Action action, long now) { 266 return new MOPACState(phase.with(actor, action, now), actions, 267 connections, progress, settings, partyprofiles); 268 } 269 270 @Override 271 public SessionResult getResult() { 272 return new SessionResult(partyprofiles, getAgreements(), 273 Collections.emptyMap(), null); 254 return new MOPACState(phase.with(actor, action, now), actions, progress, 255 settings, partyprofiles); 256 } 257 258 /** 259 * @param aprogress the progress that might need to be advanced 260 * @param aphase the phase 261 * @return the next progress. Progress round advances if phase is 262 * {@link OptIn}. 263 */ 264 private static Progress increment(Progress aprogress, Phase aphase) { 265 if (aprogress instanceof ProgressRounds && aphase instanceof OptInPhase) 266 return ((ProgressRounds) aprogress).advance(); 267 return aprogress; 274 268 } 275 269 … … 294 288 public String toString() { 295 289 return "MOPACState[" + phase + "," + settings + "," + partyprofiles 296 + "," + connections + "," + progress + ","+ "]";290 + "," + progress + "]"; 297 291 } 298 292 … … 306 300 LinkedList<Action> newactions = new LinkedList<Action>(actions); 307 301 newactions.addAll(newphase.getPartyStates().getActions()); 308 return new MOPACState(newphase, newactions, connections, progress, 309 settings, partyprofiles); 302 return new MOPACState(newphase, newactions, progress, settings, 303 partyprofiles); 304 } 305 306 @Override 307 public int hashCode() { 308 final int prime = 31; 309 int result = 1; 310 result = prime * result + ((actions == null) ? 0 : actions.hashCode()); 311 result = prime * result 312 + ((partyprofiles == null) ? 0 : partyprofiles.hashCode()); 313 result = prime * result + ((phase == null) ? 0 : phase.hashCode()); 314 result = prime * result 315 + ((progress == null) ? 0 : progress.hashCode()); 316 result = prime * result 317 + ((settings == null) ? 0 : settings.hashCode()); 318 return result; 319 } 320 321 @Override 322 public boolean equals(Object obj) { 323 if (this == obj) 324 return true; 325 if (obj == null) 326 return false; 327 if (getClass() != obj.getClass()) 328 return false; 329 MOPACState other = (MOPACState) obj; 330 if (actions == null) { 331 if (other.actions != null) 332 return false; 333 } else if (!actions.equals(other.actions)) 334 return false; 335 if (partyprofiles == null) { 336 if (other.partyprofiles != null) 337 return false; 338 } else if (!partyprofiles.equals(other.partyprofiles)) 339 return false; 340 if (phase == null) { 341 if (other.phase != null) 342 return false; 343 } else if (!phase.equals(other.phase)) 344 return false; 345 if (progress == null) { 346 if (other.progress != null) 347 return false; 348 } else if (!progress.equals(other.progress)) 349 return false; 350 if (settings == null) { 351 if (other.settings != null) 352 return false; 353 } else if (!settings.equals(other.settings)) 354 return false; 355 return true; 310 356 } 311 357 -
protocol/src/main/java/geniusweb/protocol/session/mopac/PartyStates.java
r21 r24 1 1 package geniusweb.protocol.session.mopac; 2 2 3 import java.util.Arrays;4 import java.util.Collection;5 3 import java.util.Collections; 6 4 import java.util.HashMap; … … 12 10 import java.util.stream.Collectors; 13 11 12 import com.fasterxml.jackson.annotation.JsonAutoDetect; 13 import com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility; 14 import com.fasterxml.jackson.annotation.JsonCreator; 15 import com.fasterxml.jackson.annotation.JsonProperty; 16 14 17 import geniusweb.actions.Action; 15 18 import geniusweb.actions.EndNegotiation; … … 19 22 20 23 /** 21 * The current state of all participating parties. A party either notYetActed,22 * did action, reached an agreement, walked away or made a24 * Invariant: contains the current state of all participating parties. A party 25 * either notYetActed, did action, reached an agreement, walked away or made a 23 26 * {@link ProtocolException}. 24 27 * <p> … … 26 29 * agreements and move remaining parties back to notYetActed. 27 30 * 28 * This is not considering current time or checking actions.29 31 */ 32 @JsonAutoDetect(fieldVisibility = Visibility.ANY, getterVisibility = Visibility.NONE, setterVisibility = Visibility.NONE, isGetterVisibility = Visibility.NONE) 30 33 public class PartyStates { 31 34 // all parties must be in exactly one state at all times. … … 35 38 private final List<PartyId> walkedAway; 36 39 private final Map<PartyId, ProtocolException> exceptions; 37 private Map<PartyId, Integer> powers; 40 private final Map<PartyId, Integer> powers; 41 42 @JsonCreator 43 protected PartyStates(@JsonProperty("notYetActed") Set<PartyId> notYetActed, 44 @JsonProperty("actions") List<Action> actions, 45 @JsonProperty("agreements") Agreements agreements, 46 @JsonProperty("walkedAway") List<PartyId> walkedAway, 47 @JsonProperty("exceptions") Map<PartyId, ProtocolException> exceptions, 48 @JsonProperty("powers") Map<PartyId, Integer> powers) { 49 this.notYetActed = notYetActed; 50 this.actions = actions; 51 this.agreements = agreements; 52 this.walkedAway = walkedAway; 53 this.exceptions = exceptions; 54 this.powers = powers; 55 } 38 56 39 57 /** … … 51 69 } 52 70 53 public PartyStates(Set<PartyId> notYetActed, List<Action> actions, 54 Agreements agreements, List<PartyId> walkedAway, 55 Map<PartyId, ProtocolException> exceptions, 56 Map<PartyId, Integer> powers) { 57 this.notYetActed = notYetActed; 58 this.actions = actions; 59 this.agreements = agreements; 60 this.walkedAway = walkedAway; 61 this.exceptions = exceptions; 62 this.powers = powers; 63 } 64 65 /** 66 * 67 * @param action 68 * @return new state with party done given action. 71 /** 72 * 73 * @param action the action done by some party. The correctness of action, 74 * particularly of {@link Action#getActor()}, must be correct. 75 * @return new state with party done given action. This just accepts any 76 * given action and is not considering number of rounds, time or 77 * whether an action is allowed. 78 * 69 79 * @throws IllegalArgumentException if party doing action already acted. 70 80 * This is just a safety check as legality … … 151 161 152 162 /** 153 *154 163 * @param actor 155 164 * @return {@link #notYetActed} with actor removed 156 */ 157 private Set<PartyId> removeParty(PartyId actor) { 158 return removeParties(new HashSet<>(Arrays.asList(actor))); 165 * @throws IllegalArgumentException if party already acted (not in 166 * {@link #notYetActed}). 167 */ 168 private Set<PartyId> removeParty(PartyId party) { 169 Set<PartyId> newActiveParties = new HashSet<>(notYetActed); 170 if (!newActiveParties.remove(party)) 171 throw new IllegalArgumentException( 172 "Party " + party + " is not active, can't be removed"); 173 return newActiveParties; 174 159 175 } 160 176 … … 169 185 public Map<PartyId, ProtocolException> getExceptions() { 170 186 return Collections.unmodifiableMap(exceptions); 171 }172 173 /**174 *175 * @param parties the parties to remove176 * @return {@link #notYetActed} without the given parties.177 */178 private Set<PartyId> removeParties(Collection<PartyId> parties) {179 Set<PartyId> newActiveParties = new HashSet<>(notYetActed);180 for (PartyId party : parties) {181 if (!newActiveParties.remove(party))182 throw new IllegalArgumentException(183 "Party " + party + " is not active, can't be removed");184 }185 return newActiveParties;186 187 } 187 188 … … 204 205 205 206 /** 206 * @param type the type of actions to extract 207 * 208 * @return all parties that walked away 209 */ 210 public List<PartyId> getWalkedAway() { 211 return walkedAway; 212 } 213 214 /** 215 * @param <T> the type of objects requested 216 * @param type the type of actions to extract. Must be of type T, needed 217 * because of java's type erasure. 218 * 207 219 * @return all actions of type done in this phase 208 220 */ … … 233 245 } 234 246 247 @Override 248 public int hashCode() { 249 final int prime = 31; 250 int result = 1; 251 result = prime * result + ((actions == null) ? 0 : actions.hashCode()); 252 result = prime * result 253 + ((agreements == null) ? 0 : agreements.hashCode()); 254 result = prime * result 255 + ((exceptions == null) ? 0 : exceptions.hashCode()); 256 result = prime * result 257 + ((notYetActed == null) ? 0 : notYetActed.hashCode()); 258 result = prime * result + ((powers == null) ? 0 : powers.hashCode()); 259 result = prime * result 260 + ((walkedAway == null) ? 0 : walkedAway.hashCode()); 261 return result; 262 } 263 264 @Override 265 public boolean equals(Object obj) { 266 if (this == obj) 267 return true; 268 if (obj == null) 269 return false; 270 if (getClass() != obj.getClass()) 271 return false; 272 PartyStates other = (PartyStates) obj; 273 if (actions == null) { 274 if (other.actions != null) 275 return false; 276 } else if (!actions.equals(other.actions)) 277 return false; 278 if (agreements == null) { 279 if (other.agreements != null) 280 return false; 281 } else if (!agreements.equals(other.agreements)) 282 return false; 283 if (exceptions == null) { 284 if (other.exceptions != null) 285 return false; 286 } else if (!exceptions.equals(other.exceptions)) 287 return false; 288 if (notYetActed == null) { 289 if (other.notYetActed != null) 290 return false; 291 } else if (!notYetActed.equals(other.notYetActed)) 292 return false; 293 if (powers == null) { 294 if (other.powers != null) 295 return false; 296 } else if (!powers.equals(other.powers)) 297 return false; 298 if (walkedAway == null) { 299 if (other.walkedAway != null) 300 return false; 301 } else if (!walkedAway.equals(other.walkedAway)) 302 return false; 303 return true; 304 } 305 235 306 } -
protocol/src/main/java/geniusweb/protocol/session/mopac/phase/DefaultPhase.java
r23 r24 1 1 package geniusweb.protocol.session.mopac.phase; 2 3 import java.util.List;4 import java.util.stream.Collectors;5 6 import com.fasterxml.jackson.annotation.JsonIgnore;7 2 8 3 import geniusweb.actions.Action; 9 4 import geniusweb.actions.PartyId; 10 import geniusweb.actions.Votes;11 5 import geniusweb.protocol.ProtocolException; 12 6 import geniusweb.protocol.session.mopac.PartyStates; … … 17 11 protected final Long deadline; 18 12 protected final PartyStates partyStates; 19 20 // don't serialize this, users don't need it..21 @JsonIgnore22 13 protected final VotingEvaluator evaluator; 23 14 24 // don't serialize this, it will cause very large file25 @JsonIgnore26 protected final Phase prevPhase;27 28 15 /** 29 * 30 * @param actions the actions done in this phase . 31 * @param prevPhase the previous phase, can be used to collect previous 32 * votes etc. 33 * @param partyStates 16 * @param partyStates the {@link PartyStates} 34 17 * @param deadline deadline for this phase, ms since 1970 18 * @param evaluator the {@link VotingEvaluator} to be used 35 19 */ 36 public DefaultPhase(P hase prevPhase, PartyStates partyStates, Long deadline,20 public DefaultPhase(PartyStates partyStates, Long deadline, 37 21 VotingEvaluator evaluator) { 38 22 this.partyStates = partyStates; 39 23 this.deadline = deadline; 40 this.prevPhase = prevPhase;41 24 this.evaluator = evaluator; 42 25 } … … 53 36 54 37 /** 55 * @return all votes done in this phase.56 */57 public List<Votes> getVotes() {58 return partyStates.getActions().stream()59 .filter(act -> act instanceof Votes).map(act -> (Votes) act)60 .collect(Collectors.toList());61 }62 63 /**64 38 * Check if actor can do given action. Basic checks: 65 39 * <ul> … … 70 44 * </ul> 71 45 * 72 * @param activeParties the currently active parties 73 * @param actor 74 * @param action 75 * @param timems 76 * @throws ProtocolException 77 * @throw ProtocolException if the action violates the protocol, or null if 78 * ok 46 * @param actor the actor that really acted 47 * @param action the action that was done 48 * @param now current time 49 * @throws ProtocolException if the action violates the protocol 79 50 */ 80 protected void checkAction(PartyId actor, Action action, long timems)51 protected void checkAction(PartyId actor, Action action, long now) 81 52 throws ProtocolException { 82 53 if (action == null) … … 86 57 "Incorrect actor info in action:" + action.getActor(), 87 58 actor); 88 if (isFinal( timems))59 if (isFinal(now)) 89 60 throw new ProtocolException("passed deadline", actor); 90 61 if (!(getAllowedActions().contains(action.getClass()))) 91 throw new ProtocolException( 92 "Action not allowed in " + this.getClass() + ":" + action, 93 actor); 62 throw new ProtocolException("Action not allowed in " 63 + this.getClass().getSimpleName() + ": " + action, actor); 94 64 if (!partyStates.getNotYetActed().contains(actor)) 95 65 throw new ProtocolException("Actor can not act anymore", actor); … … 98 68 99 69 /** 100 * @param timems current time101 70 * @return current PartyStates 102 71 */ … … 116 85 throw new IllegalArgumentException("Bug, illegal duration"); 117 86 if (!isFinal(now)) 118 throw new IllegalStateException( 119 "next must only be called when phase isFinal"); 120 if (!partyStates.getNotYetActed().isEmpty()) 121 throw new IllegalStateException("Bug. State has not been finished"); 87 throw new IllegalStateException("phase is not final"); 122 88 return checkedNext(now + duration); 123 89 } 124 90 125 91 /** 92 * As {@link #next(long, long)} but DefaultPhase already checked that 1. 93 * there is enough time for a next phase 2. current state is final 3. 126 94 * 127 * @param d eadline95 * @param dl the deadline for the next phase (ms since 1970). 128 96 * @return the next phase 129 97 */ 130 protected abstract Phase checkedNext(long d eadline);98 protected abstract Phase checkedNext(long dl); 131 99 132 100 @Override 133 101 public String toString() { 134 // don't print prev state, it will give HUGE list because it also135 // contains prevstate.....136 102 return getClass().getSimpleName() + "[" + partyStates + "," + deadline 137 103 + "," + evaluator + "]"; 138 104 } 105 106 @Override 107 public int hashCode() { 108 final int prime = 31; 109 int result = 1; 110 result = prime * result 111 + ((deadline == null) ? 0 : deadline.hashCode()); 112 result = prime * result 113 + ((evaluator == null) ? 0 : evaluator.hashCode()); 114 result = prime * result 115 + ((partyStates == null) ? 0 : partyStates.hashCode()); 116 return result; 117 } 118 119 @Override 120 public boolean equals(Object obj) { 121 if (this == obj) 122 return true; 123 if (obj == null) 124 return false; 125 if (getClass() != obj.getClass()) 126 return false; 127 DefaultPhase other = (DefaultPhase) obj; 128 if (deadline == null) { 129 if (other.deadline != null) 130 return false; 131 } else if (!deadline.equals(other.deadline)) 132 return false; 133 if (evaluator == null) { 134 if (other.evaluator != null) 135 return false; 136 } else if (!evaluator.equals(other.evaluator)) 137 return false; 138 if (partyStates == null) { 139 if (other.partyStates != null) 140 return false; 141 } else if (!partyStates.equals(other.partyStates)) 142 return false; 143 return true; 144 } 139 145 } -
protocol/src/main/java/geniusweb/protocol/session/mopac/phase/OfferPhase.java
r23 r24 4 4 import java.util.List; 5 5 import java.util.stream.Collectors; 6 7 import com.fasterxml.jackson.annotation.JsonCreator; 8 import com.fasterxml.jackson.annotation.JsonProperty; 6 9 7 10 import geniusweb.actions.Action; … … 18 21 public class OfferPhase extends DefaultPhase { 19 22 20 public OfferPhase(Phase prevPhase, PartyStates partyStates, Long deadlinems, 21 VotingEvaluator evaluator) { 22 super(prevPhase, partyStates, deadlinems, evaluator); 23 @JsonCreator 24 public OfferPhase(@JsonProperty("partyStates") PartyStates partyStates, 25 @JsonProperty("deadlinems") Long deadlinems, 26 @JsonProperty("evaluator") VotingEvaluator evaluator) { 27 super(partyStates, deadlinems, evaluator); 23 28 } 24 29 … … 30 35 return this.with(ex); 31 36 } 32 return new OfferPhase(prevPhase, partyStates.with(action), deadline, 33 evaluator); 37 return new OfferPhase(partyStates.with(action), deadline, evaluator); 34 38 } 35 39 … … 42 46 public OfferPhase with(ProtocolException e) { 43 47 System.out.println("Party kicked because of protocol exception:" + e); 44 return new OfferPhase(prevPhase, partyStates.with(e), deadline, 45 evaluator); 48 return new OfferPhase(partyStates.with(e), deadline, evaluator); 46 49 } 47 50 48 51 @Override 49 52 public Phase finish() { 50 return new OfferPhase(prevPhase, partyStates.finish(), deadline, 51 evaluator); 53 return new OfferPhase(partyStates.finish(), deadline, evaluator); 52 54 } 53 55 54 56 @Override 55 57 public VotingPhase checkedNext(long deadln) { 56 return new VotingPhase(this, partyStates.flush(), deadln, evaluator); 58 return new VotingPhase(getOffers(), partyStates.flush(), deadln, 59 evaluator); 57 60 } 58 61 59 p ublicList<Bid> getOffers() {62 protected List<Bid> getOffers() { 60 63 return partyStates.getActions(Offer.class).stream() 61 64 .map(offer -> offer.getBid()).collect(Collectors.toList()); -
protocol/src/main/java/geniusweb/protocol/session/mopac/phase/OptInPhase.java
r23 r24 5 5 import java.util.Map; 6 6 import java.util.stream.Collectors; 7 8 import com.fasterxml.jackson.annotation.JsonCreator; 9 import com.fasterxml.jackson.annotation.JsonProperty; 7 10 8 11 import geniusweb.actions.Action; … … 20 23 public class OptInPhase extends DefaultPhase { 21 24 22 protected OptInPhase(Phase prevPhase, PartyStates partyStates, 23 Long deadlinems, VotingEvaluator evaluator) { 24 super(prevPhase, partyStates, deadlinems, evaluator); 25 /** 26 * The votes received in the {@link VotingPhase} 27 */ 28 private final List<Votes> votes; 29 30 @JsonCreator 31 protected OptInPhase(@JsonProperty("votes") List<Votes> votes, 32 @JsonProperty("partyStates") PartyStates partyStates, 33 @JsonProperty("deadlinems") Long deadlinems, 34 @JsonProperty("evaluator") VotingEvaluator evaluator) { 35 super(partyStates, deadlinems, evaluator); 36 this.votes = votes; 25 37 } 26 38 27 39 @Override 28 40 public Inform getInform() { 29 return new OptIn( ((VotingPhase) prevPhase).getVotes());41 return new OptIn(votes); 30 42 } 31 43 … … 35 47 checkAction(actor, action, now); 36 48 if (action instanceof Votes) 37 checkExtends( action);49 checkExtends((Votes) action); 38 50 39 return new OptInPhase( prevPhase, partyStates.with(action), deadline,51 return new OptInPhase(votes, partyStates.with(action), deadline, 40 52 evaluator); 41 53 … … 48 60 * Check that this action extends previous action. 49 61 * 50 * @param action 51 * @param phase 62 * @param newvotes new {@link Votes} just received 52 63 * @throws ProtocolException if this action does not correctly extend 53 64 * previous vote. 54 65 */ 55 private void checkExtends(Action action) throws ProtocolException { 56 57 Votes votes = (Votes) action; 58 PartyId actor = action.getActor(); 66 private void checkExtends(Votes newvotes) throws ProtocolException { 67 PartyId actor = newvotes.getActor(); 59 68 // this actor is active so he must have voted in previous round. 60 Votes prevVotes = ((VotingPhase) prevPhase).getVotes().stream()61 .fi lter(v -> v.getActor().equals(actor)).findFirst().get();62 if (!( votes.isExtending(prevVotes)))63 throw new ProtocolException("New votes " + action69 Votes prevVotes = votes.stream().filter(v -> v.getActor().equals(actor)) 70 .findFirst().get(); 71 if (!(newvotes.isExtending(prevVotes))) 72 throw new ProtocolException("New votes " + newvotes 64 73 + " does not extend previous vote " + prevVotes, actor); 65 74 } … … 67 76 @Override 68 77 public OptInPhase with(ProtocolException e) { 69 return new OptInPhase(prevPhase, partyStates.with(e), deadline, 70 evaluator); 78 return new OptInPhase(votes, partyStates.with(e), deadline, evaluator); 71 79 } 72 80 … … 84 92 PartyStates finalStates = states.with(newAgree); 85 93 86 return new OptInPhase( prevPhase, finalStates, deadline, evaluator);94 return new OptInPhase(votes, finalStates, deadline, evaluator); 87 95 } 88 96 89 97 @Override 90 98 public OfferPhase checkedNext(long newdeadline) { 91 return new OfferPhase(this, partyStates.flush(), newdeadline, 92 evaluator); 99 return new OfferPhase(partyStates.flush(), newdeadline, evaluator); 93 100 } 94 101 -
protocol/src/main/java/geniusweb/protocol/session/mopac/phase/Phase.java
r23 r24 2 2 3 3 import java.util.List; 4 import java.util.Set;5 4 6 5 import com.fasterxml.jackson.annotation.JsonAutoDetect; 7 6 import com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility; 7 import com.fasterxml.jackson.annotation.JsonSubTypes; 8 import com.fasterxml.jackson.annotation.JsonTypeInfo; 8 9 9 10 import geniusweb.actions.Action; … … 17 18 * A Phase is a part of the round structure. In each round parties have to take 18 19 * multiple actions. Each action is part of a phase. 19 * 20 * 21 * Invariant: A phase object handles negotiation events, ensuring that the 22 * events are handled according to the possible actions in this phase. A phase 23 * object must always remain in a consistent state. It does so by modifying the 24 * contained {@link PartyStates} as needed. 25 * <p> 26 * The standard exception handling is assumed: unchecked exceptions are thrown 27 * only if there is a bug in the protocol. Because none of the functions in this 28 * interface throws, any error must be either ignored or the party must be 29 * kicked. 20 30 */ 21 @JsonAutoDetect(fieldVisibility = Visibility.ANY, getterVisibility = Visibility.NONE, setterVisibility = Visibility.NONE) 31 @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.WRAPPER_OBJECT) 32 @JsonAutoDetect(fieldVisibility = Visibility.ANY, getterVisibility = Visibility.NONE, setterVisibility = Visibility.NONE, isGetterVisibility = Visibility.NONE) 33 @JsonSubTypes({ @JsonSubTypes.Type(value = OfferPhase.class), 34 @JsonSubTypes.Type(value = OptInPhase.class), 35 @JsonSubTypes.Type(value = VotingPhase.class) }) 22 36 public interface Phase { 23 37 public static final Long PHASE_MAXTIME = 30000l; // 30sec … … 28 42 * handled by updating the PartyStates 29 43 * 30 * @param prevPhases the list of all previous phases31 * @param actor the real actor32 * @param action the action submitted by actor, which this phase can33 * reallyhandle.34 * @param now 44 * @param actor the real actor (may differ from the actor contained in the 45 * action) 46 * @param action the action submitted by actor, which this phase can really 47 * handle. 48 * @param now the current time 35 49 * @return new VotingPhase 36 50 */ … … 73 87 * after {@link #finish()} 74 88 * 75 * @param now the curren time76 * @param duration the max duration of the next phase. Must be between89 * @param now the current time 90 * @param duration the max duration (ms) of the next phase. Must be between 77 91 * {@link #PHASE_MINTIME} and {@link #PHASE_MAXTIME}. Also 78 92 * make sure that now+duration is at most at the total … … 83 97 84 98 /** 85 * Get the voting evaluator 86 * 87 * @return 99 * @return the voting evaluator 88 100 */ 89 101 public VotingEvaluator getEvaluator(); … … 97 109 98 110 /** 99 * @param now the current time100 *101 111 * @return the party states. Notice that someone must call 102 * {@link PartyStates#finish( Set)} if passed the deadline.112 * {@link PartyStates#finish()} if passed the deadline. 103 113 */ 104 114 public PartyStates getPartyStates(); -
protocol/src/main/java/geniusweb/protocol/session/mopac/phase/VotingPhase.java
r23 r24 3 3 import java.util.Arrays; 4 4 import java.util.List; 5 import java.util.stream.Collectors; 6 7 import com.fasterxml.jackson.annotation.JsonCreator; 8 import com.fasterxml.jackson.annotation.JsonProperty; 5 9 6 10 import geniusweb.actions.Action; … … 10 14 import geniusweb.inform.Inform; 11 15 import geniusweb.inform.Voting; 16 import geniusweb.issuevalue.Bid; 12 17 import geniusweb.protocol.ProtocolException; 13 18 import geniusweb.protocol.session.mopac.PartyStates; … … 16 21 public class VotingPhase extends DefaultPhase { 17 22 18 VotingPhase(Phase prevPhase, PartyStates partyStates, Long deadlinems, 19 VotingEvaluator evaluator) { 20 super(prevPhase, partyStates, deadlinems, evaluator); 23 /** 24 * the offers received in the {@link OfferPhase} 25 */ 26 private final List<Bid> offers; 27 28 @JsonCreator 29 protected VotingPhase(@JsonProperty("offers") List<Bid> offers, 30 @JsonProperty("partyStates") PartyStates partyStates, 31 @JsonProperty("deadlinems") Long deadlinems, 32 @JsonProperty("evaluator") VotingEvaluator evaluator) { 33 super(partyStates, deadlinems, evaluator); 34 this.offers = offers; 21 35 } 22 36 … … 28 42 return this.with(ex); 29 43 } 30 return new VotingPhase( prevPhase, partyStates.with(action), deadline,44 return new VotingPhase(offers, partyStates.with(action), deadline, 31 45 evaluator); 32 46 } … … 34 48 @Override 35 49 public Inform getInform() { 36 return new Voting(((OfferPhase) prevPhase).getOffers(), 37 partyStates.getPowers()); 50 return new Voting(offers, partyStates.getPowers()); 38 51 } 39 52 40 53 @Override 41 54 public VotingPhase with(ProtocolException e) { 42 return new VotingPhase( prevPhase, partyStates.with(e), deadline,55 return new VotingPhase(offers, partyStates.with(e), deadline, 43 56 evaluator); 44 57 } … … 46 59 @Override 47 60 public VotingPhase finish() { 48 return new VotingPhase( prevPhase, partyStates.finish(), deadline,61 return new VotingPhase(offers, partyStates.finish(), deadline, 49 62 evaluator); 50 63 } … … 52 65 @Override 53 66 protected Phase checkedNext(long deadln) { 54 return new OptInPhase(this, partyStates.flush(), deadln, evaluator); 67 return new OptInPhase(getVotes(), partyStates.flush(), deadln, 68 evaluator); 55 69 } 56 70 … … 60 74 } 61 75 76 /** 77 * @return all votes done in this phase. 78 */ 79 public List<Votes> getVotes() { 80 return partyStates.getActions().stream() 81 .filter(act -> act instanceof Votes).map(act -> (Votes) act) 82 .collect(Collectors.toList()); 83 } 84 62 85 } -
protocol/src/main/java/geniusweb/protocol/session/saop/SAOP.java
r21 r24 38 38 39 39 /** 40 * 41 * All parties are first sent the {@link SessionSettings}. Only parties 42 * specified initially in the settings do participate. 40 * The protocol runs as follows 43 41 * <ol> 44 * The protocol tries to start all parties. If not all parties start, the42 * <li>The protocol tries to start all parties. If not all parties start, the 45 43 * parties are freed up and another attempt is done to start all parties some 46 44 * time later. 45 * <li>All parties are sent the {@link SessionSettings}. Only parties specified 46 * initially in the settings do participate. 47 47 * <li>The session deadline clock now starts ticking. 48 48 * <li>All parties are sent their settings. … … 61 61 * the protocol. 62 62 * <p> 63 * Thread safe: all entrypoints are synhronized.63 * Thread safe: all entry points are synchronized. 64 64 */ 65 65 public class SAOP extends DefaultListenable<ProtocolEvent> … … 79 79 /** 80 80 * 81 * @param state normally the initial state coming from SAOPSettings 81 * @param state normally the initial state coming from SAOPSettings 82 * @param logger the Reporter to log to 82 83 */ 83 84 public SAOP(SAOPState state, Reporter logger) { -
protocol/src/main/java/geniusweb/protocol/session/saop/SAOPSettings.java
r21 r24 27 27 * protocol. But SAOP can be initialized with less, for 28 28 * use in TournamentSettings. 29 * @param deadline 29 * @param deadline the deadline of the negotiation 30 30 */ 31 31 @JsonCreator -
protocol/src/main/java/geniusweb/protocol/session/saop/SAOPState.java
r23 r24 33 33 /** 34 34 * 35 * @param actions 35 * @param actions the actions done by the parties 36 36 * @param conns the existing party connections. we assume ownership 37 37 * of this so it should not be modified although … … 88 88 /** 89 89 * 90 * @param e the error that occured 91 * @param currentTimeMs the current time in ms since 1970, see 92 * {@link System#currentTimeMillis()} 90 * @param e the error that occured 93 91 * @return a new state with the error set. 94 92 */ … … 160 158 161 159 /** 162 * @param actor the actor that did this action. Can be used to check 163 * if action is valid. NOTICE caller has to make sure 164 * the current state is not final. 165 * @param action the action that was proposed by actor. 166 * @param currentTimeMs the current time in ms since 1970, see 167 * {@link System#currentTimeMillis()} 168 * @return new SessionState with the action added as last action. 160 * @param actor the actor that did this action. Can be used to check if 161 * action is valid. NOTICE caller has to make sure the current 162 * state is not final. 163 * @param action the action that was proposed by actor. 164 * @return new SAOPState with the action added as last action. 169 165 */ 170 166 -
protocol/src/main/java/geniusweb/protocol/session/shaop/BareSHAOPState.java
r23 r24 44 44 /** 45 45 * 46 * @param actions value for actions done so far. null equals to empty47 * list48 * @param conns the currently existing connections. Can be empty/null.49 * Each connection represents another party. Normally the50 * connections are in the order SHAOP1,COB1,SHAOP2,COB2,..51 * so 2 parties for each team. The protocol should check52 * this.53 * @param progr the {@link Progress} that governs this session. Can be54 * null if session did not yet start.55 * @param settings the settings used for the session56 * @param e the exception that occured, usually null. All errors57 * occuring due to faulty {@link Action}s translate to58 * {@link ProtocolException}s. All errors in our own code59 * are bugs (not ProtocolExceptions) and should result in60 * a throw.61 * @param teamNr the teamnr (0,1,2..) that has the turn. 2* gives index62 * {@link #connections} and settings63 * @param partyNrs a map for each known PartyId to a number. The number is64 * the index in both {@link SHAOPSettings#getTeams()} and65 * in {@link #connections}. null is empyt map.66 * @param totalSpent total accumulated elicitation costs so far. only SHAOP67 * parties accumulate costs. null = emptymap46 * @param actions value for actions done so far. null equals to empty list 47 * @param conns the currently existing connections. Can be empty/null. 48 * Each connection represents another party. Normally the 49 * connections are in the order SHAOP1,COB1,SHAOP2,COB2,.. 50 * so 2 parties for each team. The protocol should check 51 * this. 52 * @param progr the {@link Progress} that governs this session. Can be 53 * null if session did not yet start. 54 * @param settings the settings used for the session 55 * @param e the exception that occured, usually null. All errors 56 * occuring due to faulty {@link Action}s translate to 57 * {@link ProtocolException}s. All errors in our own code 58 * are bugs (not ProtocolExceptions) and should result in a 59 * throw. 60 * @param teamNr the teamnr (0,1,2..) that has the turn. 2* gives index 61 * {@link #connections} and settings 62 * @param partyNrs a map for each known PartyId to a number. The number is 63 * the index in both {@link SHAOPSettings#getTeams()} and in 64 * {@link #connections}. null is empyt map. 65 * @param spent total accumulated elicitation costs so far for each 66 * party. only SHAOP parties accumulate costs. null = empty 67 * map 68 68 */ 69 69 @JsonCreator -
protocol/src/main/java/geniusweb/protocol/session/shaop/SHAOP.java
r21 r24 85 85 /** 86 86 * 87 * @param state normally the initial state coming from SAOPSettings 87 * @param state normally the initial state coming from SAOPSettings 88 * @param logger the {@link Reporter} to use 88 89 */ 89 90 public SHAOP(SHAOPState state, Reporter logger) { -
protocol/src/main/java/geniusweb/protocol/session/shaop/SHAOPState.java
r21 r24 38 38 * see {@link BareSHAOPState}. 39 39 */ 40 /** 41 * 42 * @param actions see 43 * {@link BareSHAOPState#BareSHAOPState(List, ProtocolToPartyConnections, Progress, SHAOPSettings, ProtocolException, int, Map, Map)}. 44 * @param conns see 45 * {@link BareSHAOPState#BareSHAOPState(List, ProtocolToPartyConnections, Progress, SHAOPSettings, ProtocolException, int, Map, Map)}. 46 * @param progress see 47 * {@link BareSHAOPState#BareSHAOPState(List, ProtocolToPartyConnections, Progress, SHAOPSettings, ProtocolException, int, Map, Map)}. 48 * @param settings see 49 * {@link BareSHAOPState#BareSHAOPState(List, ProtocolToPartyConnections, Progress, SHAOPSettings, ProtocolException, int, Map, Map)}. 50 * @param e see 51 * {@link BareSHAOPState#BareSHAOPState(List, ProtocolToPartyConnections, Progress, SHAOPSettings, ProtocolException, int, Map, Map)}. 52 * @param teamNr see 53 * {@link BareSHAOPState#BareSHAOPState(List, ProtocolToPartyConnections, Progress, SHAOPSettings, ProtocolException, int, Map, Map)}. 54 * @param partytNumbers see 55 * {@link BareSHAOPState#BareSHAOPState(List, ProtocolToPartyConnections, Progress, SHAOPSettings, ProtocolException, int, Map, Map)}. 56 * @param spent see 57 * {@link BareSHAOPState#BareSHAOPState(List, ProtocolToPartyConnections, Progress, SHAOPSettings, ProtocolException, int, Map, Map)}. 58 */ 40 59 @JsonCreator 41 60 public SHAOPState(@JsonProperty("actions") List<Action> actions, … … 72 91 /** 73 92 * 74 * @param party 75 * @return true iff party is a SHAOP party .93 * @param party the {@link PartyId} to test 94 * @return true iff party is a SHAOP party (not a COB party). 76 95 */ 77 96 public boolean isShaopParty(PartyId party) { … … 81 100 /** 82 101 * 83 * @return the team leader {@link PartyId}s .102 * @return the team leader {@link PartyId}s which are the SHAOP parties. 84 103 */ 85 104 private Set<PartyId> getLeaders() { … … 149 168 /** 150 169 * 151 * @param e the error that occured 152 * @param currentTimeMs the current time in ms since 1970, see 153 * {@link System#currentTimeMillis()} 170 * @param e the error that occured 154 171 * @return a new state with the error set. 155 172 */ … … 201 218 202 219 /** 203 * @param actor the actor that did this action. Can be used to check 204 * if action is valid. NOTICE caller has to make sure 205 * the current state is not final. 206 * @param action the action that was proposed by actor. 207 * @param currentTimeMs the current time in ms since 1970, see 208 * {@link System#currentTimeMillis()} 220 * @param actor the actor that did this action. Can be used to check if 221 * action is valid. NOTICE caller has to make sure the current 222 * state is not final. 223 * @param action the action that was proposed by actor. 209 224 * @return new SessionState with the action added as last action. 210 225 */ -
protocol/src/main/java/geniusweb/protocol/tournament/allpermutations/AllPermutationsProtocol.java
r20 r24 34 34 /** 35 35 * 36 * @param state 36 * @param state the {@link AllPermutationsState} 37 37 * @param logger used for all logging, about the tournament, and the created 38 38 * the session and protocols. … … 81 81 long now = System.currentTimeMillis(); 82 82 if (sessionstate.isFinal(now)) { 83 // List<TeamOfPartiesAndProfiles> participants =84 // sessionstate.getSettings().getParticipants()85 83 SessionResult result = sessionstate.getResult(); 86 84 state = state.with(result); -
protocol/src/main/java/geniusweb/protocol/tournament/allpermutations/AllPermutationsSettings.java
r21 r24 69 69 /** 70 70 * 71 * @param teams a list of {@link Team}s. Must contain at least 72 * {@link #teamsPerSession} elements. The 73 * <teamsize> must match the protocol: (SAOP:1, 74 * SHAOP:2) 75 * @param reuseTeams if true, we use PermutationsWithReturn, if false 76 * we use PermutationsWithoutReturn to create the 77 * teams. 78 * @param plists list of available {@link ProfileList}s to be 79 * permutated over the teams. Each 80 * {@link ProfileList} must contain <teamsize> 81 * elements. 82 * @param teamsPerSession number of parties per session, must be at least 83 * 2. 84 * @param sesettings The generic {@link SessionSetting}. 85 * {@link SessionSettings#with(PartyWithProfile)} 86 * will be used to add the required 87 * {@link PartyWithProfile}s 88 * @param numberTournaments the number of times the tournament should be 89 * run. 71 * @param teams a list of {@link Team}s. Must contain at least 72 * {@link #teamsPerSession} elements. The 73 * {@link #teamsPerSession} must match the protocol: 74 * (SAOP:1, SHAOP:2) 75 * @param reuseTeams if true, we use PermutationsWithReturn, if false 76 * we use PermutationsWithoutReturn to create the 77 * teams. 78 * @param plists list of available {@link ProfileList}s to be 79 * permutated over the teams. Each 80 * {@link ProfileList} must contain 81 * {@link #teamsPerSession} elements. 82 * @param teamsPerSession number of parties per session, must be at least 2. 83 * @param sesettings The generic {@link SessionSettings}. 84 * {@link SessionSettings#with(TeamOfPartiesAndProfiles)} 85 * will be used to add the required 86 * {@link TeamOfPartiesAndProfiles}s 87 * @param nTournaments the number of times the tournament should be run. 90 88 */ 91 89 @JsonCreator -
protocol/src/test/java/geniusweb/protocol/session/mopac/MOPACTest.java
r21 r24 2 2 3 3 import static org.junit.Assert.assertEquals; 4 import static org.junit.Assert.assertFalse; 4 5 import static org.junit.Assert.assertNotNull; 5 6 import static org.junit.Assert.assertTrue; 6 7 import static org.mockito.Matchers.any; 8 import static org.mockito.Matchers.anyLong; 7 9 import static org.mockito.Mockito.mock; 8 10 import static org.mockito.Mockito.times; … … 12 14 import java.io.IOException; 13 15 import java.util.Arrays; 16 import java.util.Date; 14 17 import java.util.List; 15 18 16 19 import org.junit.Before; 17 import org.junit.Ignore;18 20 import org.junit.Test; 19 21 … … 28 30 import geniusweb.protocol.partyconnection.ProtocolToPartyConn; 29 31 import geniusweb.protocol.partyconnection.ProtocolToPartyConnFactory; 32 import geniusweb.protocol.session.mopac.phase.OfferPhase; 33 import geniusweb.protocol.session.mopac.phase.Phase; 34 import geniusweb.protocol.session.mopac.phase.VotingPhase; 30 35 import tudelft.utilities.logging.Reporter; 31 36 import tudelft.utilities.repository.NoResourcesNowException; … … 57 62 conn3 = mock(ProtocolToPartyConn.class); 58 63 64 private List<ProtocolToPartyConn> connections; 65 59 66 @Before 60 67 public void before() throws JsonParseException, JsonMappingException, … … 63 70 mopac = settings.getProtocol(logger); 64 71 65 Listconnections = Arrays.asList(conn1, conn2, conn3);72 connections = Arrays.asList(conn1, conn2, conn3); 66 73 when(factory.connect(any(List.class))).thenReturn(connections); 67 74 … … 94 101 } 95 102 96 @Ignore97 103 @Test 98 104 public void testWorkingCheckDeadline() … … 101 107 mopac.start(factory); 102 108 103 System.out.println(mopac.getState()); 104 109 assertFalse(mopac.getState().isFinal(System.currentTimeMillis())); 105 110 // we have deadline in 100ms so check 106 111 Thread.sleep(200); 107 108 System.out.println(mopac.getState());109 112 assertTrue(mopac.getState().isFinal(System.currentTimeMillis())); 110 113 } 111 114 112 @Ignore113 115 @Test 114 116 public void testSubscribedToConnections() { … … 119 121 } 120 122 121 @Ignore122 123 @Test 123 124 public void testActionIsBroadcast() … … 134 135 } 135 136 136 @Test 137 public void testAgreementTerminates() { 138 139 } 137 /** 138 * Fatal error occurs, run should fail 139 */ 140 @Test(expected = RuntimeException.class) 141 public void testPartyFailsConnect() 142 throws IOException, NoResourcesNowException { 143 ProtocolToPartyConnFactory factory1 = mock( 144 ProtocolToPartyConnFactory.class); 145 // irrecoverable fail test 146 when(factory1.connect(any(List.class))) 147 .thenThrow(new IOException("Failed to connect to parties")); 148 149 mopac.start(factory1); 150 151 } 152 153 /** 154 * Nonfatal error occurs, protocol should retry till success 155 */ 156 @Test 157 public void testPartyFailsConnect2ndtimeOK() 158 throws IOException, NoResourcesNowException { 159 long now = System.currentTimeMillis(); 160 ProtocolToPartyConnFactory factory1 = mock( 161 ProtocolToPartyConnFactory.class); 162 // recoverable fail, and then success. 163 when(factory1.connect(any(List.class))) 164 .thenThrow(new NoResourcesNowException("try again later", 165 new Date(now + 100))) 166 .thenReturn(connections); 167 168 mopac.start(factory1); 169 170 } 171 172 /** 173 * Test that in Offer phase, and party does action, the next phase is 174 * entered. 175 */ 176 @Test 177 public void testProceedsNextPhase() { 178 // the state before the last party makes the offer 179 MOPACState offerstate = mock(MOPACState.class); 180 when(offerstate.getSettings()).thenReturn(settings); 181 OfferPhase offerphase = mock(OfferPhase.class); 182 when(offerphase.isFinal(anyLong())).thenReturn(false); 183 when(offerstate.getPhase()).thenReturn(offerphase); 184 185 // the phase where all parties placed an offer 186 OfferPhase finalofferphase = mock(OfferPhase.class); 187 when(finalofferphase.isFinal(anyLong())).thenReturn(true); 188 MOPACState finalofferstate = mock(MOPACState.class); 189 when(finalofferstate.getPhase()).thenReturn(finalofferphase); 190 when(finalofferstate.finishPhase()).thenReturn(finalofferstate); 191 192 when(offerstate.with(any(PartyId.class), any(Action.class), anyLong())) 193 .thenReturn(finalofferstate); 194 195 // the phase where all parties can start voting. 196 // this is the state to be reached. 197 long now = System.currentTimeMillis(); 198 MOPACState votingstate = mock(MOPACState.class); 199 Phase votingphase = mock(VotingPhase.class); 200 PartyStates votingpartystates = mock(PartyStates.class); 201 when(votingphase.getDeadline()).thenReturn(now + 100); 202 when(votingphase.getPartyStates()).thenReturn(votingpartystates); 203 when(votingstate.getPhase()).thenReturn(votingphase); 204 205 when(finalofferstate.nextPhase(anyLong())).thenReturn(votingstate); 206 207 mopac = new MOPAC(offerstate, logger); 208 Offer action = mock(Offer.class); 209 mopac.actionRequest(conn3, action, now); 210 211 // check that the action result in reaching the voting phase 212 assertEquals(votingstate, mopac.getState()); 213 } 214 140 215 } -
protocol/src/test/java/geniusweb/protocol/session/mopac/PartyStatesTest.java
r21 r24 3 3 import static org.junit.Assert.assertEquals; 4 4 5 import java.io.IOException; 6 import java.net.URISyntaxException; 5 7 import java.util.Arrays; 6 8 import java.util.Collections; 7 9 import java.util.HashMap; 8 10 import java.util.HashSet; 11 import java.util.List; 9 12 import java.util.Map; 10 13 11 14 import org.junit.Test; 12 15 16 import com.fasterxml.jackson.core.JsonProcessingException; 17 import com.fasterxml.jackson.databind.ObjectMapper; 18 13 19 import geniusweb.actions.PartyId; 14 20 import geniusweb.inform.Agreements; 15 21 import geniusweb.protocol.ProtocolException; 22 import tudelft.utilities.junit.GeneralTests; 16 23 17 public class PartyStatesTest { 24 public class PartyStatesTest extends GeneralTests<PartyStates> { 25 private final ObjectMapper jackson = new ObjectMapper(); 18 26 19 27 private final PartyId party1 = new PartyId("party1"); … … 22 30 23 31 private final Map<PartyId, Integer> powers = new HashMap<>(); 24 private final PartyStates states; 32 private final PartyStates states1, states1a, states2; 33 private final String serialized = "{\"notYetActed\":[\"party2\",\"party1\",\"party3\"],\"actions\":[],\"agreements\":{},\"walkedAway\":[],\"exceptions\":{},\"powers\":{\"party2\":3,\"party1\":2,\"party3\":3}}"; 25 34 26 35 public PartyStatesTest() { 36 37 // FIXME use the other constructor to really test this. 38 // PartyStates(Set<PartyId> notYetActed, List<Action> actions, 39 // Agreements agreements, List<PartyId> walkedAway, 40 // Map<PartyId, ProtocolException> exceptions, 41 // Map<PartyId, Integer> powers) 42 // 27 43 powers.put(party1, 2); 28 44 powers.put(party2, 3); 45 states2 = new PartyStates(powers); 29 46 powers.put(party3, 3); 30 states = new PartyStates(powers); 47 states1 = new PartyStates(powers); 48 states1a = new PartyStates(powers); 49 } 50 51 @Override 52 public List<List<PartyStates>> getGeneralTestData() { 53 return Arrays.asList(Arrays.asList(states1, states1a), 54 Arrays.asList(states2)); 55 } 56 57 @Override 58 public List<String> getGeneralTestStrings() { 59 return Arrays.asList( 60 "PartyStates.*\\[party2, party1, party3\\],\\[\\],Agreements\\{\\},\\[\\],\\{\\}.*", 61 "PartyStates.*\\[party2, party1\\],\\[\\],Agreements\\{\\},\\[\\],\\{\\}.*"); 31 62 } 32 63 33 64 @Test 34 65 public void testBasics() { 35 assertEquals(powers.keySet(), states .getNegotiatingParties());36 assertEquals(powers.keySet(), states .getNotYetActed());37 assertEquals(0, states .getExceptions().size());66 assertEquals(powers.keySet(), states1.getNegotiatingParties()); 67 assertEquals(powers.keySet(), states1.getNotYetActed()); 68 assertEquals(0, states1.getExceptions().size()); 38 69 } 39 70 40 71 @Test 41 72 public void testException() { 42 PartyStates newstates = states 73 PartyStates newstates = states1 43 74 .with(new ProtocolException("bla", party1)); 44 75 assertEquals(new Agreements(), newstates.getAgreements()); 45 assertEquals(powers.keySet(), states .getNegotiatingParties());76 assertEquals(powers.keySet(), states1.getNegotiatingParties()); 46 77 assertEquals(new HashSet<>(Arrays.asList(party2, party3)), 47 78 newstates.getNotYetActed()); … … 50 81 @Test 51 82 public void testFinish() { 52 PartyStates newstates = states .finish();83 PartyStates newstates = states1.finish(); 53 84 assertEquals(new Agreements(), newstates.getAgreements()); 54 assertEquals(powers.keySet(), states .getNegotiatingParties());85 assertEquals(powers.keySet(), states1.getNegotiatingParties()); 55 86 assertEquals(Collections.emptySet(), newstates.getNotYetActed()); 56 87 } 88 89 @Test 90 public void testDeserialize() throws IOException { 91 PartyStates obj = jackson.readValue(serialized, PartyStates.class); 92 System.out.println(obj); 93 assertEquals(states1, obj); 94 } 95 96 @Test 97 public void testSerialize() 98 throws JsonProcessingException, URISyntaxException { 99 100 String string = jackson.writeValueAsString(states1); 101 System.out.println(string); 102 assertEquals(serialized, string); 103 } 104 105 @Test 106 public void testWalkAway() { 107 PartyStates walkawaystate = states1.withWalkAway(party2); 108 assertEquals(new HashSet<>(Arrays.asList(party1, party3)), 109 walkawaystate.getNotYetActed()); 110 assertEquals(Arrays.asList(party2), walkawaystate.getWalkedAway()); 111 } 57 112 } -
protocol/src/test/java/geniusweb/protocol/session/mopac/phase/OfferPhaseTest.java
r21 r24 4 4 import static org.junit.Assert.assertFalse; 5 5 import static org.junit.Assert.assertTrue; 6 import static org.junit.Assert.fail; 6 7 import static org.mockito.Mockito.mock; 7 8 import static org.mockito.Mockito.when; 9 10 import java.io.IOException; 11 import java.net.URISyntaxException; 12 import java.util.Arrays; 8 13 import java.util.Collections; 9 14 import java.util.HashMap; 15 import java.util.List; 10 16 import java.util.Map; 11 17 12 18 import org.junit.Test; 13 19 20 import com.fasterxml.jackson.core.JsonProcessingException; 21 import com.fasterxml.jackson.databind.ObjectMapper; 22 23 import geniusweb.actions.Accept; 14 24 import geniusweb.actions.EndNegotiation; 25 import geniusweb.actions.Offer; 15 26 import geniusweb.actions.PartyId; 16 27 import geniusweb.actions.Votes; 28 import geniusweb.inform.YourTurn; 29 import geniusweb.issuevalue.Bid; 30 import geniusweb.issuevalue.DiscreteValue; 17 31 import geniusweb.protocol.ProtocolException; 18 32 import geniusweb.protocol.session.mopac.PartyStates; 19 33 import geniusweb.voting.VotingEvaluator; 34 import geniusweb.voting.votingevaluators.LargestAgreement; 35 import geniusweb.voting.votingevaluators.LargestAgreementsLoop; 36 import tudelft.utilities.junit.GeneralTests; 20 37 21 38 /** 22 39 * We also test defaultPhase here. 23 40 */ 24 public class OfferPhaseTest { 25 41 public class OfferPhaseTest extends GeneralTests<OfferPhase> { 42 private final ObjectMapper jackson = new ObjectMapper(); 43 44 private static final long DEADLINE = 10l; 26 45 private final PartyId party1 = new PartyId("party1"); 27 46 private final PartyId party2 = new PartyId("party2"); … … 29 48 30 49 private final Map<PartyId, Integer> powers = new HashMap<>(); 31 private final PartyStates states; 32 private final VotingEvaluator evaluator = mock(VotingEvaluator.class); 33 private final OfferPhase phase; 50 private final PartyStates states, states2; 51 private final VotingEvaluator evaluator = new LargestAgreement(); 52 private final VotingEvaluator evaluator2 = new LargestAgreementsLoop(); 53 private final OfferPhase phase, phase1, phase1a, phase2, phase3, phase4; 54 55 // just a test bid 56 private final Bid bid = new Bid("issue", new DiscreteValue("yes")); 57 private final Offer offer = new Offer(party1, bid); 58 59 private final String serialized = "{\"OfferPhase\":{\"partyStates\":{\"notYetActed\":[\"party2\",\"party1\",\"party3\"],\"actions\":[],\"agreements\":{},\"walkedAway\":[],\"exceptions\":{},\"powers\":{\"party2\":3,\"party1\":2,\"party3\":3}},\"evaluator\":{\"LargestAgreement\":{}},\"deadline\":10}}"; 34 60 35 61 public OfferPhaseTest() { 36 62 powers.put(party1, 2); 37 63 powers.put(party2, 3); 64 states2 = new PartyStates(powers); 38 65 powers.put(party3, 3); 39 66 states = new PartyStates(powers); 40 phase = new OfferPhase(null, states, 10l, evaluator); 41 } 42 43 @Test 44 public void isInitFinalTest() { 67 phase = new OfferPhase(states, DEADLINE, evaluator); 68 69 phase1 = new OfferPhase(states, 10l, evaluator); 70 phase1a = new OfferPhase(states, 10l, evaluator); 71 phase2 = new OfferPhase(states2, 10l, evaluator); 72 phase3 = new OfferPhase(states, 20l, evaluator); 73 phase4 = new OfferPhase(states, 10l, evaluator2); 74 75 } 76 77 @Override 78 public List<List<OfferPhase>> getGeneralTestData() { 79 return Arrays.asList(Arrays.asList(phase1, phase1a), 80 Arrays.asList(phase2), Arrays.asList(phase3), 81 Arrays.asList(phase4)); 82 } 83 84 @Override 85 public List<String> getGeneralTestStrings() { 86 return Arrays.asList( 87 "OfferPhase.*PartyStates.*party2, party1, party3.*\\[\\],Agreements.*\\[\\],\\{\\}.*],10,LargestAgreement.*", 88 "OfferPhase.*PartyStates.*party2, party1.*\\[\\],Agreements.*\\[\\],\\{\\}.*],10,LargestAgreement.*", 89 "OfferPhase.*PartyStates.*party2, party1, party3.*\\[\\],Agreements.*\\[\\],\\{\\}.*],20,LargestAgreement.*", 90 "OfferPhase.*PartyStates.*party2, party1, party3.*\\[\\],Agreements.*\\[\\],\\{\\}.*],10,LargestAgreementsLoop.*"); 91 } 92 93 @Test 94 public void smokeTest() { 95 } 96 97 @Test 98 public void testInitState() { 99 assertEquals(3, phase.getPartyStates().getNotYetActed().size()); 100 } 101 102 @Test 103 public void testInform() { 104 assertEquals(new YourTurn(), phase.getInform()); 105 } 106 107 @Test 108 public void isFinalTest() { 45 109 assertFalse(phase.isFinal(1l)); 46 110 assertTrue(phase.isFinal(10l)); 111 } 112 113 @Test 114 public void isFinalTestActorNotYetActed() { 115 PartyStates actedstate = mock(PartyStates.class); 116 when(actedstate.getNotYetActed()) 117 .thenReturn(Collections.singleton(party1)); 118 OfferPhase testphase = new OfferPhase(actedstate, 10l, evaluator); 119 assertFalse(testphase.isFinal(1l)); 120 } 121 122 @Test 123 public void isFinalTestAllActorsActed() { 124 PartyStates actedstate = mock(PartyStates.class); 125 when(actedstate.getNotYetActed()).thenReturn(Collections.emptySet()); 126 OfferPhase testphase = new OfferPhase(actedstate, 10l, evaluator); 127 assertTrue(testphase.isFinal(1l)); 47 128 } 48 129 … … 65 146 } 66 147 148 @Test 149 public void testFinish() { 150 Phase ph = phase.finish(); 151 assertTrue(ph.getPartyStates().getNotYetActed().isEmpty()); 152 assertEquals(3, ph.getPartyStates().getExceptions().size()); 153 assertTrue(phase.getPartyStates().getAgreements().getMap().isEmpty()); 154 } 155 156 @Test(expected = IllegalStateException.class) 157 public void testNextWrong() { 158 // state is not final, should not work 159 phase.next(1, 1000); 160 } 161 162 @Test 163 public void testNextNoParties() { 164 Phase ph = phase.finish(); 165 // no parties are left now, all failed 166 // but this is not part of the next() check. 167 Phase next = ph.next(1, 1000); 168 assertTrue(next instanceof VotingPhase); 169 // no remaining parties, since finish kicked all 170 assertTrue(next.getPartyStates().getNotYetActed().isEmpty()); 171 } 172 173 @Test 174 public void testAllowed() { 175 phase.with(party1, offer, 1); 176 } 177 178 @Test 179 public void testAllowedWrongClass() { 180 try { 181 phase.checkAction(party1, new Accept(party1, bid), 1); 182 } catch (ProtocolException e) { 183 assertTrue(e.getMessage().contains("not allowed in OfferPhase")); 184 return; 185 } 186 fail("checkAction did not throw as expected"); 187 } 188 189 @Test 190 public void testAllowedWrongActor() { 191 try { 192 phase.checkAction(party1, new Accept(party2, bid), 1); 193 } catch (ProtocolException e) { 194 assertTrue( 195 e.getMessage().contains("Incorrect actor info in action")); 196 return; 197 } 198 fail("checkAction did not throw as expected"); 199 } 200 201 @Test 202 public void testAllowedActorAlreadyActed() { 203 OfferPhase testphase = phase.with(party1, offer, 1); 204 205 try { 206 testphase.checkAction(party1, offer, 2); 207 } catch (ProtocolException e) { 208 assertTrue(e.getMessage().contains("can not act anymore")); 209 return; 210 } 211 fail("checkAction did not throw as expected"); 212 } 213 214 @Test 215 public void testAllowedActorAlreadyActed1() { 216 // as theoprevious test, but using with() instead of checkAction 217 OfferPhase testphase = phase.with(party1, offer, 1); 218 219 OfferPhase newphase = testphase.with(party1, offer, 2); 220 // the party must remain as acted, because we can't retract his 221 // action... 222 assertEquals(1, newphase.getPartyStates().getActions().size()); 223 assertEquals(offer, newphase.getPartyStates().getActions().get(0)); 224 assertFalse( 225 newphase.getPartyStates().getExceptions().containsKey(party1)); 226 } 227 228 @Test 229 public void testAllowedActingTooLate() { 230 231 try { 232 phase.checkAction(party1, offer, DEADLINE + 1); 233 } catch (ProtocolException e) { 234 assertTrue(e.getMessage().contains("passed deadline")); 235 return; 236 } 237 fail("checkAction did not throw as expected"); 238 } 239 240 @Test 241 public void getOffersTest() { 242 assertEquals(Collections.emptyList(), phase.getOffers()); 243 List<Bid> offs = phase.with(party1, offer, 1).getOffers(); 244 assertEquals(Arrays.asList(bid), offs); 245 } 246 247 @Test(expected = IllegalArgumentException.class) 248 public void testNextTooShortDuration() { 249 phase.next(1, Phase.PHASE_MINTIME - 1); 250 } 251 252 @Test(expected = IllegalStateException.class) 253 public void testNextNotFinished() { 254 phase.next(1, Phase.PHASE_MINTIME + 1); 255 } 256 257 @Test(expected = IllegalStateException.class) 258 public void testNext() { 259 phase.next(11, Phase.PHASE_MINTIME + 1); 260 } 261 262 @Test 263 public void testDeserialize() throws IOException { 264 Phase obj = jackson.readValue(serialized, Phase.class); 265 System.out.println(obj); 266 assertEquals(phase1, obj); 267 } 268 269 @Test 270 public void testSerialize() 271 throws JsonProcessingException, URISyntaxException { 272 273 String string = jackson.writeValueAsString(phase1); 274 System.out.println(string); 275 assertEquals(serialized, string); 276 } 67 277 } -
protocol/src/test/java/geniusweb/protocol/session/saop/SAOPTest.java
r21 r24 34 34 import geniusweb.events.CurrentState; 35 35 import geniusweb.events.ProtocolEvent; 36 import geniusweb.inform.Agreements; 36 37 import geniusweb.inform.Finished; 37 38 import geniusweb.inform.Inform; … … 177 178 when(state.toString()).thenReturn(asText); 178 179 when(state.with(any(ProtocolException.class))).thenReturn(failstate); 180 when(state.getAgreements()).thenReturn(mock(Agreements.class)); 179 181 } 180 182 … … 260 262 @Test 261 263 public void testActionRequestWrongActor() { 262 263 264 saop.actionRequest(conn2, mock(EndNegotiation.class)); 264 265 … … 290 291 when(state.with(any(PartyId.class), any(EndNegotiation.class))) 291 292 .thenReturn(finalstate); 293 // when(finalstate.getAgreements()).thenReturn(mock(Agreements.class)); 292 294 293 295 saop.actionRequest(conn1, mock(EndNegotiation.class)); … … 311 313 doThrow(new IOException("fail sending yourturn")).when(conn1) 312 314 .send(any(YourTurn.class)); 313 315 // CHECK is the state really final after an exception? 316 when(state.with(any(ProtocolException.class))).thenReturn(finalstate); 317 // when(state.getAgreements()).thenReturn(mock(Agreements.class)); 314 318 saop.actionRequest(conn1, mock(Accept.class)); 315 319 … … 322 326 doThrow(new IOException("fail sending yourturn")).when(conn1) 323 327 .send(any(YourTurn.class)); 328 // when(failstate.getAgreements()).thenReturn(mock(Agreements.class)); 324 329 // not turn of conn2. 325 330 saop.actionRequest(conn2, mock(EndNegotiation.class)); … … 332 337 public void testActionInFinalState() throws IOException { 333 338 saop = new SAOP(finalstate, new ReportToLogger("test")); 339 // when(finalstate.getAgreements()).thenReturn(mock(Agreements.class)); 334 340 335 341 saop.actionRequest(conn1, mock(Offer.class));
Note:
See TracChangeset
for help on using the changeset viewer.