Index: protocol/src/main/java/geniusweb/protocol/SessionResult.java
===================================================================
--- protocol/src/main/java/geniusweb/protocol/SessionResult.java	(revision 25)
+++ 	(revision )
@@ -1,135 +1,0 @@
-package geniusweb.protocol;
-
-import java.util.Collections;
-import java.util.List;
-
-import com.fasterxml.jackson.annotation.JsonAutoDetect;
-import com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility;
-import com.fasterxml.jackson.annotation.JsonCreator;
-import com.fasterxml.jackson.annotation.JsonProperty;
-import com.fasterxml.jackson.annotation.JsonTypeInfo;
-
-import geniusweb.issuevalue.Bid;
-import geniusweb.references.PartyWithProfile;
-
-/**
- * All results collected from running a session. Normally this does not contain
- * all the details, only the final outcome and other global notes.
- */
-@JsonAutoDetect(fieldVisibility = Visibility.ANY, getterVisibility = Visibility.NONE, setterVisibility = Visibility.NONE)
-public class SessionResult {
-	private final List<PartyWithProfile> participants;
-	private final Bid agreement;
-
-	// add more type info so that jackson can deserialize the actual class
-	@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.WRAPPER_OBJECT)
-	private final Throwable error;
-
-	/**
-	 * 
-	 * @param participants the list oof {@link PartyWithProfile}, in the proper
-	 *                     order (this is relevant for the protocol etc). Should
-	 *                     never be null. Some of them may have entered later of
-	 *                     left early. This list should contain them all.
-	 * @param agreement    the final agreement {@link Bid} of the session. Null
-	 *                     if no agreement was reached.
-	 * @param error        a fatal error that terminated the session. Non-fatal
-	 *                     errors (warnings) are not to be reported. Null if no
-	 *                     fatal error occured (session ended following the
-	 *                     protocol). Normally, a fatal error results in no
-	 *                     agreement but there might be protocols that allow a
-	 *                     session to end with an error but stick with a already
-	 *                     reached agreement as well.
-	 */
-	@JsonCreator
-	public SessionResult(
-			@JsonProperty("participants") List<PartyWithProfile> participants,
-			@JsonProperty("agreement") Bid agreement,
-			@JsonProperty("error") Throwable error) {
-		this.participants = participants;
-		this.agreement = agreement;
-		this.error = error;
-	}
-
-	/**
-	 * 
-	 * @return the list oof {@link PartyWithProfile}, in the proper order (this
-	 *         is relevant for the protocol etc). Should never be null. Some of
-	 *         them may have entered later of left early. This list should
-	 *         contain them all.
-	 */
-	public List<PartyWithProfile> getParticipants() {
-		return Collections.unmodifiableList(participants);
-	}
-
-	/**
-	 * 8return the final agreement {@link Bid} of the session. Null if no
-	 * agreement was reached.
-	 */
-	public Bid getAgreement() {
-		return agreement;
-	};
-
-	/**
-	 * 
-	 * @return a fatal error that terminated the session. Non-fatal errors
-	 *         (warnings) are not to be reported. Null if no fatal error occured
-	 *         (session ended following the protocol). Normally, a fatal error
-	 *         results in no agreement but there might be protocols that allow a
-	 *         session to end with an error but stick with a already reached
-	 *         agreement as well.
-	 */
-	public Throwable getError() {
-		return error;
-	}
-
-	@Override
-	public String toString() {
-		return "SessionResult[" + participants + "," + agreement + "," + error
-				+ "]";
-	}
-
-	@Override
-	public int hashCode() {
-		final int prime = 31;
-		int result = 1;
-		result = prime * result
-				+ ((agreement == null) ? 0 : agreement.hashCode());
-		result = prime * result + ((error == null) ? 0 : error.hashCode());
-		result = prime * result
-				+ ((participants == null) ? 0 : participants.hashCode());
-		return result;
-	}
-
-	@Override
-	public boolean equals(Object obj) {
-		if (this == obj)
-			return true;
-		if (obj == null)
-			return false;
-		if (getClass() != obj.getClass())
-			return false;
-		SessionResult other = (SessionResult) obj;
-		if (agreement == null) {
-			if (other.agreement != null)
-				return false;
-		} else if (!agreement.equals(other.agreement))
-			return false;
-		if (error == null) {
-			if (other.error != null)
-				return false;
-		} else if (other.error == null)
-			return false;
-		else if (!error.toString().equals(other.error.toString()))
-			// HACK error does not have equals implemented!
-			// so we hacked in toString() here to work around it.
-			return false;
-		if (participants == null) {
-			if (other.participants != null)
-				return false;
-		} else if (!participants.equals(other.participants))
-			return false;
-		return true;
-	}
-
-}
Index: protocol/src/main/java/geniusweb/protocol/WillBeCalled.java
===================================================================
--- protocol/src/main/java/geniusweb/protocol/WillBeCalled.java	(revision 25)
+++ 	(revision )
@@ -1,46 +1,0 @@
-package geniusweb.protocol;
-
-import java.util.concurrent.ScheduledThreadPoolExecutor;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicBoolean;
-
-/**
- * Object containing function that will be called exactly once, on demand or at
- * given deadline.
- *
- */
-public class WillBeCalled {
-	private static volatile ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(
-			2);
-	private final Runnable runnable;
-	private volatile AtomicBoolean done = new AtomicBoolean(false);
-
-	/**
-	 * @param r       the runnable that will be run once, either when the user
-	 *                calls {@link #complete(Void)} or after delayMs, whichever
-	 *                comes first.
-	 * @param delayMs the delay after this will be called anywa (the 'deadline'
-	 *                in milliseconds. If null, no deadline call will be made
-	 *                and the user must call {@link #complete(Void)} himself.
-	 */
-	public WillBeCalled(Runnable r, Long delayMs) {
-		this.runnable = r;
-		if (delayMs != null) {
-			executor.schedule(() -> complete(), delayMs, TimeUnit.MILLISECONDS);
-		}
-	}
-
-	/**
-	 * Tells the runnable to be executed. Only the first time the function is
-	 * run, subsequent calls do nothing. Failures in runnable are NOT caught
-	 * here, as they are probably bugs
-	 * 
-	 * We must avoid synchronized here because users may use synchronized blocks
-	 * already.
-	 */
-	public void complete() {
-		if (!done.compareAndSet(false, true))
-			return;
-		runnable.run();
-	}
-}
Index: protocol/src/main/java/geniusweb/protocol/partyconnection/ConnectionWithParties.java
===================================================================
--- protocol/src/main/java/geniusweb/protocol/partyconnection/ConnectionWithParties.java	(revision 25)
+++ 	(revision )
@@ -1,123 +1,0 @@
-package geniusweb.protocol.partyconnection;
-
-import java.io.IOException;
-import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.stream.Collectors;
-import java.util.stream.Stream;
-
-import geniusweb.actions.PartyId;
-import geniusweb.party.inform.Inform;
-
-/**
- * Contains all parties with their connections. immutable
- */
-public class ConnectionWithParties implements Iterable<ConnectionWithParty> {
-	private List<ConnectionWithParty> connections;
-
-	public ConnectionWithParties(List<ConnectionWithParty> connections) {
-		this.connections = connections;
-	}
-
-	/**
-	 * @param id the {@link PartyId} needed
-	 * @return a connection with that party, or null if no such connection.
-	 */
-	public ConnectionWithParty get(PartyId id) {
-		return connections.stream().filter(conn -> id.equals(conn.getParty()))
-				.findAny().orElse(null);
-	}
-
-	/**
-	 * 
-	 * @return true iff all parties have one connection only
-	 */
-	public boolean allunique() {
-		return getParties().size() == connections.size();
-	}
-
-	/**
-	 * 
-	 * @return list of parties currently in the connections.
-	 */
-	private List<PartyId> getParties() {
-		return connections.stream().map(conn -> conn.getParty()).distinct()
-				.collect(Collectors.toList());
-	}
-
-	/**
-	 * Broadcast info to all parties
-	 * 
-	 * @param info the {@link Inform} to broadcast
-	 */
-	public void broadcast(Inform info) throws IOException {
-		for (ConnectionWithParty conn : connections) {
-			conn.send(info);
-		}
-	}
-
-	/**
-	 * 
-	 * @return number of connections available
-	 */
-	public int size() {
-		return connections.size();
-	}
-
-	/**
-	 * @param i
-	 * @return the ith connection
-	 */
-	public ConnectionWithParty get(int i) {
-		return connections.get(i);
-	}
-
-	public Stream<ConnectionWithParty> stream() {
-		return connections.stream();
-	}
-
-	@Override
-	public Iterator<ConnectionWithParty> iterator() {
-		return connections.iterator();
-	}
-
-	public ConnectionWithParties with(ConnectionWithParty conn) {
-		List<ConnectionWithParty> newconnections = new LinkedList<>(
-				connections);
-		newconnections.add(conn);
-		return new ConnectionWithParties(newconnections);
-	}
-
-	@Override
-	public String toString() {
-		return "ConnectionWithParties" + connections;
-	}
-
-	@Override
-	public int hashCode() {
-		final int prime = 31;
-		int result = 1;
-		result = prime * result
-				+ ((connections == null) ? 0 : connections.hashCode());
-		return result;
-	}
-
-	@Override
-	public boolean equals(Object obj) {
-		if (this == obj)
-			return true;
-		if (obj == null)
-			return false;
-		if (getClass() != obj.getClass())
-			return false;
-		ConnectionWithParties other = (ConnectionWithParties) obj;
-		if (connections == null) {
-			if (other.connections != null)
-				return false;
-		} else if (!connections.equals(other.connections))
-			return false;
-		return true;
-	}
-
-}
Index: protocol/src/main/java/geniusweb/protocol/partyconnection/ConnectionWithParty.java
===================================================================
--- protocol/src/main/java/geniusweb/protocol/partyconnection/ConnectionWithParty.java	(revision 25)
+++ 	(revision )
@@ -1,19 +1,0 @@
-package geniusweb.protocol.partyconnection;
-
-import geniusweb.actions.Action;
-import geniusweb.actions.PartyId;
-import geniusweb.connection.Connection;
-import geniusweb.party.inform.Inform;
-
-/**
- * Connection of the protocol with a party. Note, this is the opposite direction
- * of a connection of the party with the protocol.
- */
-public interface ConnectionWithParty extends Connection<Action, Inform> {
-
-	/**
-	 * 
-	 * @return the partyId of the party that this connects to
-	 */
-	PartyId getParty();
-}
Index: protocol/src/main/java/geniusweb/protocol/partyconnection/ConnectionWithPartyFactory.java
===================================================================
--- protocol/src/main/java/geniusweb/protocol/partyconnection/ConnectionWithPartyFactory.java	(revision 25)
+++ 	(revision )
@@ -1,39 +1,0 @@
-package geniusweb.protocol.partyconnection;
-
-import java.io.IOException;
-import java.util.List;
-
-import geniusweb.actions.Action;
-import geniusweb.connection.ConnectionFactory;
-import geniusweb.party.inform.Inform;
-import geniusweb.references.Reference;
-import tudelft.utilities.repository.NoResourcesNowException;
-
-/**
- * An extended {@link ConnectionFactory} that store PartyIDs with the
- * connections, making it possible to find back the appropriate connection given
- * a PartyID. Also, it allows the connection factory to actually assign the
- * PartyIDs.
- *
- */
-public interface ConnectionWithPartyFactory
-		extends ConnectionFactory<Action, Inform> {
-	@Override
-	public ConnectionWithParty connect(Reference reference)
-			throws IOException, NoResourcesNowException;
-
-	/**
-	 * Connects a set of References in one go, following a modified Banker's
-	 * algorthm.
-	 * 
-	 * @param references the list of references to connect with
-	 * @return a List of connections, one fore each Reference.
-	 * @throws IOException             if a connection is failing irrecoverably.
-	 * @throws NoResourcesNowException is there are insufficient resources now.
-	 *                                 This also includes a suggested moment to
-	 *                                 retry.
-	 */
-	List<ConnectionWithParty> connect(List<Reference> references)
-			throws IOException, NoResourcesNowException;
-
-}
Index: protocol/src/main/java/geniusweb/protocol/partyconnection/ProtocolToPartyConnections.java
===================================================================
--- protocol/src/main/java/geniusweb/protocol/partyconnection/ProtocolToPartyConnections.java	(revision 25)
+++ protocol/src/main/java/geniusweb/protocol/partyconnection/ProtocolToPartyConnections.java	(revision 26)
@@ -2,7 +2,9 @@
 
 import java.io.IOException;
+import java.util.HashMap;
 import java.util.Iterator;
 import java.util.LinkedList;
 import java.util.List;
+import java.util.Map;
 import java.util.stream.Collectors;
 import java.util.stream.Stream;
@@ -55,10 +57,18 @@
 	 * 
 	 * @param info the {@link Inform} to broadcast
-	 * @throws IOException if the send fails.
+	 * @return a Map&lt;PartyId, IOException&gt; where possible exceptions for
+	 *         each party are stored. Normally a protocol would kick these
+	 *         parties.
 	 */
-	public void broadcast(Inform info) throws IOException {
+	public Map<PartyId, IOException> broadcast(Inform info) {
+		Map<PartyId, IOException> exceptions = new HashMap<>();
 		for (ProtocolToPartyConn conn : connections) {
-			conn.send(info);
+			try {
+				conn.send(info);
+			} catch (IOException e) {
+				exceptions.put(conn.getParty(), e);
+			}
 		}
+		return exceptions;
 	}
 
Index: protocol/src/main/java/geniusweb/protocol/session/amop/AMOP.java
===================================================================
--- protocol/src/main/java/geniusweb/protocol/session/amop/AMOP.java	(revision 25)
+++ protocol/src/main/java/geniusweb/protocol/session/amop/AMOP.java	(revision 26)
@@ -312,11 +312,13 @@
 		try {
 			setState(state.with(partyconn.getParty(), action));
-			state.getConnections().broadcast(new ActionDone(action));
-			if (state.isAllPartiesActed()) {
-				endPhase.complete();
-			}
 		} catch (Throwable e) {
 			handleError("failed to handle action " + action,
 					partyconn.getParty(), e);
+		}
+		// we ignore broadcast errors here, may need to be fixed.
+		broadcast(new ActionDone(action));
+
+		if (state.isAllPartiesActed()) {
+			endPhase.complete();
 		}
 
@@ -333,9 +335,8 @@
 			return;
 
-		List<Bid> bids = null;
+		List<Offer> bids = null;
 		if (state.getPhase() == Phase.OFFER) {
 			bids = state.getPhaseActions().values().stream()
-					.map(act -> ((Offer) act).getBid())
-					.collect(Collectors.toList());
+					.map(act -> ((Offer) act)).collect(Collectors.toList());
 		}
 
Index: protocol/src/main/java/geniusweb/protocol/session/amop/AMOPState.java
===================================================================
--- protocol/src/main/java/geniusweb/protocol/session/amop/AMOPState.java	(revision 25)
+++ protocol/src/main/java/geniusweb/protocol/session/amop/AMOPState.java	(revision 26)
@@ -356,5 +356,6 @@
 					.max(Comparator.comparingInt(bid -> agrees.get(bid).size()))
 					.get();
-			newagreements = newagreements.with(maxbid, agrees.get(maxbid));
+			newagreements = newagreements
+					.with(new Agreements(maxbid, agrees.get(maxbid)));
 			for (PartyId party : agrees.get(maxbid)) {
 				allvotes.remove(party);
Index: protocol/src/main/java/geniusweb/protocol/session/mopac/MOPAC.java
===================================================================
--- protocol/src/main/java/geniusweb/protocol/session/mopac/MOPAC.java	(revision 25)
+++ protocol/src/main/java/geniusweb/protocol/session/mopac/MOPAC.java	(revision 26)
@@ -4,4 +4,5 @@
 import java.util.Collections;
 import java.util.List;
+import java.util.Map;
 import java.util.Timer;
 import java.util.TimerTask;
@@ -358,13 +359,8 @@
 	 */
 	private void broadcastNegotiators(Inform info) {
-		// System.out.println("broadcasting " + info);
-		for (PartyId party : state.getPhase().getPartyStates()
-				.getNegotiatingParties()) {
-			try {
-				connections.get(party).send(info);
-			} catch (IOException e) {
-				state = state.with(new ProtocolException(
-						"Party seems to have disconnected", party, e));
-			}
+		Map<PartyId, IOException> errs = connections.broadcast(info);
+		for (PartyId pid : errs.keySet()) {
+			state = state.with(new ProtocolException(
+					"Party seems to have disconnected", pid, errs.get(pid)));
 		}
 	}
Index: protocol/src/main/java/geniusweb/protocol/session/mopac/phase/OfferPhase.java
===================================================================
--- protocol/src/main/java/geniusweb/protocol/session/mopac/phase/OfferPhase.java	(revision 25)
+++ protocol/src/main/java/geniusweb/protocol/session/mopac/phase/OfferPhase.java	(revision 26)
@@ -14,5 +14,4 @@
 import geniusweb.inform.Inform;
 import geniusweb.inform.YourTurn;
-import geniusweb.issuevalue.Bid;
 import geniusweb.protocol.ProtocolException;
 import geniusweb.protocol.session.mopac.PartyStates;
@@ -60,7 +59,7 @@
 	}
 
-	protected List<Bid> getOffers() {
+	protected List<Offer> getOffers() {
 		return partyStates.getActions(Offer.class).stream()
-				.map(offer -> offer.getBid()).collect(Collectors.toList());
+				.collect(Collectors.toList());
 	}
 
Index: protocol/src/main/java/geniusweb/protocol/session/mopac/phase/VotingPhase.java
===================================================================
--- protocol/src/main/java/geniusweb/protocol/session/mopac/phase/VotingPhase.java	(revision 25)
+++ protocol/src/main/java/geniusweb/protocol/session/mopac/phase/VotingPhase.java	(revision 26)
@@ -10,9 +10,9 @@
 import geniusweb.actions.Action;
 import geniusweb.actions.EndNegotiation;
+import geniusweb.actions.Offer;
 import geniusweb.actions.PartyId;
 import geniusweb.actions.Votes;
 import geniusweb.inform.Inform;
 import geniusweb.inform.Voting;
-import geniusweb.issuevalue.Bid;
 import geniusweb.protocol.ProtocolException;
 import geniusweb.protocol.session.mopac.PartyStates;
@@ -24,8 +24,8 @@
 	 * the offers received in the {@link OfferPhase}
 	 */
-	private final List<Bid> offers;
+	private final List<Offer> offers;
 
 	@JsonCreator
-	protected VotingPhase(@JsonProperty("offers") List<Bid> offers,
+	protected VotingPhase(@JsonProperty("offers") List<Offer> offers,
 			@JsonProperty("partyStates") PartyStates partyStates,
 			@JsonProperty("deadlinems") Long deadlinems,
Index: protocol/src/main/java/geniusweb/protocol/session/saop/SAOP.java
===================================================================
--- protocol/src/main/java/geniusweb/protocol/session/saop/SAOP.java	(revision 25)
+++ protocol/src/main/java/geniusweb/protocol/session/saop/SAOP.java	(revision 26)
@@ -281,4 +281,5 @@
 						partyconn.getParty());
 			}
+			// FIXME? this ignores possible broadcast errors
 			state.getConnections().broadcast(new ActionDone(action));
 			setState(state.with(partyconn.getParty(), action));
Index: protocol/src/main/java/geniusweb/protocol/session/saop/SAOPState.java
===================================================================
--- protocol/src/main/java/geniusweb/protocol/session/saop/SAOPState.java	(revision 25)
+++ protocol/src/main/java/geniusweb/protocol/session/saop/SAOPState.java	(revision 26)
@@ -131,5 +131,5 @@
 						&& bid.equals(((Accept) act).getBid()));
 		if (allaccept)
-			agree = agree.with(bid, getParties());
+			agree = agree.with(new Agreements(bid, getParties()));
 		return agree;
 	}
Index: protocol/src/main/java/geniusweb/protocol/session/saop/SaopPartyWithProfile.java
===================================================================
--- protocol/src/main/java/geniusweb/protocol/session/saop/SaopPartyWithProfile.java	(revision 25)
+++ 	(revision )
@@ -1,29 +1,0 @@
-package geniusweb.protocol.session.saop;
-
-import java.util.Arrays;
-import java.util.List;
-
-import com.fasterxml.jackson.annotation.JsonCreator;
-import com.fasterxml.jackson.annotation.JsonProperty;
-
-import geniusweb.protocol.session.TeamOfPartiesAndProfiles;
-import geniusweb.references.PartyWithParameters;
-import geniusweb.references.PartyWithProfile;
-import geniusweb.references.ProfileRef;
-
-public class SaopPartyWithProfile extends PartyWithProfile
-		implements TeamOfPartiesAndProfiles {
-
-	@JsonCreator
-	public SaopPartyWithProfile(
-			@JsonProperty("party") PartyWithParameters party,
-			@JsonProperty("profile") ProfileRef profile) {
-		super(party, profile);
-	}
-
-	@Override
-	public List<PartyWithProfile> getAllParties() {
-		return Arrays.asList(this);
-	}
-
-}
Index: protocol/src/main/java/geniusweb/protocol/session/shaop/SHAOP.java
===================================================================
--- protocol/src/main/java/geniusweb/protocol/session/shaop/SHAOP.java	(revision 25)
+++ protocol/src/main/java/geniusweb/protocol/session/shaop/SHAOP.java	(revision 26)
@@ -316,4 +316,5 @@
 						"Party acts without having the turn", partyid);
 			setState(state.with(partyconn.getParty(), action));
+			// FIXME? this ignores possible broadcast errors
 			state.connections.broadcast(new ActionDone(action));
 			if (!state.isFinal(System.currentTimeMillis()))
Index: protocol/src/main/java/geniusweb/protocol/session/shaop/SHAOPState.java
===================================================================
--- protocol/src/main/java/geniusweb/protocol/session/shaop/SHAOPState.java	(revision 25)
+++ protocol/src/main/java/geniusweb/protocol/session/shaop/SHAOPState.java	(revision 26)
@@ -209,5 +209,6 @@
 				continue;
 			if (requiredaccepts == 0 && act instanceof Offer)
-				return agrees.with(((Offer) act).getBid(), getLeaders());
+				return agrees.with(
+						new Agreements(((Offer) act).getBid(), getLeaders()));
 			if (!(act instanceof Accept))
 				return agrees;
