Index: /bidspace/pom.xml
===================================================================
--- /bidspace/pom.xml	(revision 25)
+++ /bidspace/pom.xml	(revision 26)
@@ -6,5 +6,5 @@
 	<groupId>geniusweb</groupId>
 	<artifactId>bidspace</artifactId>
-	<version>1.5.4</version> <!-- must equal ${geniusweb.version} -->
+	<version>1.5.5</version> <!-- must equal ${geniusweb.version} -->
 	<packaging>jar</packaging>
 
@@ -16,5 +16,5 @@
 		<passwd>${env.ARTIFACTORY_PASS}</passwd>
 		<jackson-2-version>2.9.10</jackson-2-version>
-		<geniusweb.version>1.5.4</geniusweb.version>
+		<geniusweb.version>1.5.5</geniusweb.version>
 	</properties>
 
Index: dspace/src/main/java/geniusweb/bidspace/FrequencyOpponentModel.java
===================================================================
--- /bidspace/src/main/java/geniusweb/bidspace/FrequencyOpponentModel.java	(revision 25)
+++ 	(revision )
@@ -1,194 +1,0 @@
-package geniusweb.bidspace;
-
-import java.math.BigDecimal;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.stream.Collectors;
-
-import geniusweb.issuevalue.Bid;
-import geniusweb.issuevalue.Domain;
-import geniusweb.issuevalue.NumberValue;
-import geniusweb.issuevalue.Value;
-import geniusweb.profile.utilityspace.NumberValueSetUtilities;
-
-/**
- * implements an {@link OpponentModel} by counting frequencies of bids placed by
- * the opponent.
- * <p>
- * NOTE: {@link NumberValue}s are also treated as 'discrete', so the frequency
- * of one value does not influence the influence the frequency of nearby values
- * (as you might expect as {@link NumberValueSetUtilities} is only affected by
- * the endpoints).
- *
- */
-public class FrequencyOpponentModel implements OpponentModel {
-
-	private static final int DECIMALS = 4; // accuracy of our computations.
-	private final Domain domain;
-	private final Map<String, Map<Value, Integer>> bidFrequencies;
-	private final BigDecimal totalBids;
-	private static int serial = 1; // counter for auto name generation
-
-	public FrequencyOpponentModel(Domain domain) {
-		// map with empth hashmap for each issue.
-		this(domain,
-				domain.getIssues().stream().collect(
-						Collectors.toMap(iss -> iss, iss -> new HashMap<>())),
-				BigDecimal.ZERO);
-	}
-
-	@Override
-	public BigDecimal getUtility(Bid bid) {
-		String err = domain.isComplete(bid);
-		if (err != null) {
-			throw new IllegalArgumentException(err);
-		}
-		if (totalBids == BigDecimal.ZERO) {
-			return BigDecimal.ONE;
-		}
-		BigDecimal sum = BigDecimal.ZERO;
-		// Assume all issues have equal weight.
-		for (String issue : domain.getIssues()) {
-			sum = sum.add(getFraction(issue, bid.getValue(issue)));
-		}
-		return sum.divide(new BigDecimal(bidFrequencies.size()), DECIMALS,
-				BigDecimal.ROUND_HALF_UP);
-	}
-
-	@Override
-	public String getName() {
-		return "FreqOppModel" + (serial++) + "For" + domain;
-	}
-
-	/**
-	 * 
-	 * @param issue the issue to check
-	 * @param value the value to check
-	 * @return the fraction of the total cases that bids contained given value
-	 *         for the issue.
-	 */
-	private BigDecimal getFraction(String issue, Value value) {
-		if (totalBids == BigDecimal.ZERO) {
-			return BigDecimal.ONE;
-		}
-		Integer freq = bidFrequencies.get(issue).get(value);
-		if (freq == null) {
-			freq = 0;
-		}
-		return new BigDecimal(freq).divide(totalBids, DECIMALS,
-				BigDecimal.ROUND_HALF_UP);
-	}
-
-	@Override
-	public Domain getDomain() {
-		return domain;
-	}
-
-	@Override
-	public OpponentModel update(Bid bid) {
-		String err = domain.isComplete(bid);
-		if (err != null) {
-			throw new IllegalArgumentException(err);
-		}
-		Map<String, Map<Value, Integer>> newFreqs = cloneMap(bidFrequencies);
-		for (String issue : domain.getIssues()) {
-			Map<Value, Integer> freqs = newFreqs.get(issue);
-			Value value = bid.getValue(issue);
-			Integer oldfreq = freqs.get(value);
-			if (oldfreq == null) {
-				oldfreq = 0;
-			}
-			freqs.put(value, oldfreq + 1);
-		}
-
-		return new FrequencyOpponentModel(domain, newFreqs,
-				totalBids.add(BigDecimal.ONE));
-	}
-
-	/**
-	 * internal constructor. Assumes the freqs keyset is equal to the available
-	 * issues.
-	 * 
-	 * @param domain the domain
-	 * @param freqs  the observed frequencies for all issue values. This map is
-	 *               assumed to be a fresh private-access only copy.
-	 * @param total  the total number of bids contained in the freqs map. This
-	 *               must be equal to the sum of the Integer values in the
-	 *               {@link #bidFrequencies} for each issue (this is not
-	 *               checked).
-	 */
-	private FrequencyOpponentModel(Domain domain,
-			Map<String, Map<Value, Integer>> freqs, BigDecimal total) {
-		if (domain == null) {
-			throw new NullPointerException("domain=null");
-		}
-		this.domain = domain;
-		this.bidFrequencies = freqs;
-		this.totalBids = total;
-	}
-
-	/**
-	 * 
-	 * @param freqs
-	 * @return deep copy of freqs map.
-	 */
-	private static Map<String, Map<Value, Integer>> cloneMap(
-			Map<String, Map<Value, Integer>> freqs) {
-		Map<String, Map<Value, Integer>> map = new HashMap<>();
-		for (String issue : freqs.keySet()) {
-			map.put(issue, new HashMap<Value, Integer>(freqs.get(issue)));
-		}
-		return map;
-	}
-
-	@Override
-	public int hashCode() {
-		final int prime = 31;
-		int result = 1;
-		result = prime * result
-				+ ((bidFrequencies == null) ? 0 : bidFrequencies.hashCode());
-		result = prime * result + ((domain == null) ? 0 : domain.hashCode());
-		result = prime * result
-				+ ((totalBids == null) ? 0 : totalBids.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;
-		FrequencyOpponentModel other = (FrequencyOpponentModel) obj;
-		if (bidFrequencies == null) {
-			if (other.bidFrequencies != null)
-				return false;
-		} else if (!bidFrequencies.equals(other.bidFrequencies))
-			return false;
-		if (domain == null) {
-			if (other.domain != null)
-				return false;
-		} else if (!domain.equals(other.domain))
-			return false;
-		if (totalBids == null) {
-			if (other.totalBids != null)
-				return false;
-		} else if (!totalBids.equals(other.totalBids))
-			return false;
-		return true;
-	}
-
-	@Override
-	public String toString() {
-		return "FrequencyOpponentModel[" + totalBids + "," + bidFrequencies
-				+ "]";
-	}
-
-	@Override
-	public Bid getReservationBid() {
-		throw new UnsupportedOperationException();
-	}
-
-}
Index: dspace/src/main/java/geniusweb/bidspace/OpponentModel.java
===================================================================
--- /bidspace/src/main/java/geniusweb/bidspace/OpponentModel.java	(revision 25)
+++ 	(revision )
@@ -1,18 +1,0 @@
-package geniusweb.bidspace;
-
-import geniusweb.issuevalue.Bid;
-import geniusweb.profile.utilityspace.UtilitySpace;
-
-/**
- * An opponentmodel estimates a {@link UtilitySpace} from received opponent
- * bids.
- */
-public interface OpponentModel extends UtilitySpace {
-	/**
-	 *
-	 * @param bid the next bid that was received
-	 * @return a new {@link OpponentModel} that takes the next bid into account.
-	 */
-	OpponentModel update(Bid bid);
-
-}
Index: dspace/src/test/java/geniusweb/bidspace/FrequencyOppModelTest.java
===================================================================
--- /bidspace/src/test/java/geniusweb/bidspace/FrequencyOppModelTest.java	(revision 25)
+++ 	(revision )
@@ -1,138 +1,0 @@
-package geniusweb.bidspace;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-
-import java.math.BigDecimal;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-
-import org.junit.Test;
-
-import geniusweb.bidspace.FrequencyOpponentModel;
-import geniusweb.bidspace.OpponentModel;
-import geniusweb.issuevalue.Bid;
-import geniusweb.issuevalue.DiscreteValue;
-import geniusweb.issuevalue.DiscreteValueSet;
-import geniusweb.issuevalue.Domain;
-import geniusweb.issuevalue.NumberValue;
-import geniusweb.issuevalue.NumberValueSet;
-import geniusweb.issuevalue.Value;
-import geniusweb.issuevalue.ValueSet;
-import tudelft.utilities.junit.GeneralTests;
-
-public class FrequencyOppModelTest extends GeneralTests<FrequencyOpponentModel> {
-	private final static String ISS1 = "issue1";
-	private final static String ISS2 = "issue2";
-	private static final DiscreteValue I1V1 = new DiscreteValue("i1v1");
-	private static final DiscreteValue I1V2 = new DiscreteValue("i1v2");
-	private static final DiscreteValue I1V2b = new DiscreteValue("i1v2b");
-
-	private static Domain domain, domain2, domain3;
-	private static FrequencyOpponentModel oppModel1, oppModel1b, oppModel2, oppModel3, oppModel4;
-
-	private final static List<List<Bid>> list = new LinkedList<>();
-
-	private final static Bid bid1, bid2, bid3;
-	private static final BigDecimal HALF = new BigDecimal("0.5");
-
-	static {
-		Map<String, ValueSet> issues = new HashMap<>();
-		Collection<DiscreteValue> discretevalues1 = new LinkedList<>();
-		discretevalues1.add(I1V1);
-		discretevalues1.add(I1V2);
-		DiscreteValueSet values1 = new DiscreteValueSet(discretevalues1);
-		issues.put(ISS1, values1);
-		NumberValueSet values2 = new NumberValueSet(BigDecimal.ZERO, BigDecimal.TEN, new BigDecimal("0.3"));
-		issues.put(ISS2, values2);
-		domain = new Domain("test", issues);
-		domain2 = new Domain("test2", issues);
-
-		// slightly different issue1
-		issues = new HashMap<>();
-		discretevalues1 = new LinkedList<>();
-		discretevalues1.add(I1V1);
-		discretevalues1.add(I1V2b);
-		values1 = new DiscreteValueSet(discretevalues1);
-		issues.put(ISS1, values1);
-		values2 = new NumberValueSet(BigDecimal.ZERO, BigDecimal.TEN, new BigDecimal("0.3"));
-		issues.put(ISS2, values2);
-		domain3 = new Domain("test", issues);
-
-		// all bids are for domain
-		Map<String, Value> issuevalues = new HashMap<>();
-		issuevalues.put(ISS1, I1V1);
-		issuevalues.put(ISS2, new NumberValue(new BigDecimal("1.2")));
-		bid1 = new Bid(issuevalues);
-
-		issuevalues.put(ISS1, I1V1);
-		issuevalues.put(ISS2, new NumberValue(new BigDecimal("1.5")));
-		bid2 = new Bid(issuevalues);
-
-		issuevalues.put(ISS1, I1V2);
-		issuevalues.put(ISS2, new NumberValue(new BigDecimal("1.5")));
-		bid3 = new Bid(issuevalues);
-
-		oppModel1 = new FrequencyOpponentModel(domain);
-		oppModel1b = new FrequencyOpponentModel(domain);
-		oppModel2 = new FrequencyOpponentModel(domain2);
-		oppModel3 = new FrequencyOpponentModel(domain3);
-		oppModel4 = (FrequencyOpponentModel) oppModel3.update(bid1);
-
-	}
-
-	@Override
-	public List<List<FrequencyOpponentModel>> getGeneralTestData() {
-		return Arrays.asList(Arrays.asList(oppModel1, oppModel1b), Arrays.asList(oppModel2), Arrays.asList(oppModel3),
-				Arrays.asList(oppModel4));
-	}
-
-	@Override
-	public List<String> getGeneralTestStrings() {
-		return Arrays.asList("FrequencyOpponentModel\\[0,\\{issue2=\\{\\}, issue1=\\{\\}\\}\\]",
-				"FrequencyOpponentModel\\[0,\\{issue2=\\{\\}, issue1=\\{\\}\\}\\]",
-				"FrequencyOpponentModel\\[0,\\{issue2=\\{\\}, issue1=\\{\\}\\}\\]",
-				"FrequencyOpponentModel\\[1,\\{issue2=\\{1.2=1\\}, issue1=\\{\"i1v1\"=1\\}\\}\\]");
-	}
-
-	@Test(expected = NullPointerException.class)
-	public void smokeNullTest() {
-		new FrequencyOpponentModel(null);
-	}
-
-	@Test
-	public void smokeTest() {
-		new FrequencyOpponentModel(domain);
-	}
-
-	@Test
-	public void testEmptyModel() {
-		FrequencyOpponentModel oppModel = new FrequencyOpponentModel(domain);
-		assertEquals(BigDecimal.ONE, oppModel.getUtility(bid1));
-		assertEquals(BigDecimal.ONE, oppModel.getUtility(bid2));
-	}
-
-	@Test
-	public void testUpdate() {
-		OpponentModel oppModel = oppModel1.update(bid1);
-		assertTrue(BigDecimal.ONE.compareTo(oppModel.getUtility(bid1)) == 0);
-		assertTrue(BigDecimal.ZERO.compareTo(oppModel.getUtility(bid3)) == 0);
-		// bid2 has 1 of 2 issue values same as bid1.
-		assertTrue(HALF.compareTo(oppModel.getUtility(bid2)) == 0);
-	}
-
-	@Test
-	public void testUpdate2() {
-		// bid1 and bid2 both want I1V1. They differ on the number value.
-		// bid3 wants I1V2 but does have the number value from bid2
-		OpponentModel oppModel = oppModel1.update(bid1).update(bid2);
-		assertTrue(new BigDecimal("0.75").compareTo(oppModel.getUtility(bid1)) == 0);
-		assertTrue(new BigDecimal("0.75").compareTo(oppModel.getUtility(bid2)) == 0);
-		assertTrue(new BigDecimal("0.25").compareTo(oppModel.getUtility(bid3)) == 0);
-	}
-
-}
Index: /boa/pom.xml
===================================================================
--- /boa/pom.xml	(revision 25)
+++ /boa/pom.xml	(revision 26)
@@ -6,5 +6,5 @@
 	<groupId>geniusweb</groupId>
 	<artifactId>boa</artifactId>
-	<version>1.5.4</version> <!-- must equal ${geniusweb.version} -->
+	<version>1.5.5</version> <!-- must equal ${geniusweb.version} -->
 	<packaging>jar</packaging>
 
@@ -17,5 +17,5 @@
 		<passwd>${env.ARTIFACTORY_PASS}</passwd>
 		<jackson-2-version>2.9.10</jackson-2-version>
-		<geniusweb.version>1.5.4</geniusweb.version>
+		<geniusweb.version>1.5.5</geniusweb.version>
 	</properties>
 
Index: /collectparties.sh
===================================================================
--- /collectparties.sh	(revision 25)
+++ /collectparties.sh	(revision 26)
@@ -7,5 +7,5 @@
 rm -rf collectedparties
 mkdir collectedparties
-VERSION=1.5.4
+VERSION=1.5.5
 
 cp "exampleparties/anac2019/agentgg/target/agentgg-${VERSION}-jar-with-dependencies.jar" collectedparties
Index: /events/pom.xml
===================================================================
--- /events/pom.xml	(revision 25)
+++ /events/pom.xml	(revision 26)
@@ -6,5 +6,5 @@
 	<groupId>geniusweb</groupId>
 	<artifactId>events</artifactId>
-	<version>1.5.4</version> <!-- must equal ${geniusweb.version} -->
+	<version>1.5.5</version> <!-- must equal ${geniusweb.version} -->
 	<packaging>jar</packaging>
 
@@ -17,5 +17,5 @@
 		<passwd>${env.ARTIFACTORY_PASS}</passwd>
 		<jackson-2-version>2.9.10</jackson-2-version>
-		<geniusweb.version>1.5.4</geniusweb.version>
+		<geniusweb.version>1.5.5</geniusweb.version>
 	</properties>
 
Index: /events/src/main/java/geniusweb/actions/Votes.java
===================================================================
--- /events/src/main/java/geniusweb/actions/Votes.java	(revision 25)
+++ /events/src/main/java/geniusweb/actions/Votes.java	(revision 26)
@@ -2,8 +2,8 @@
 
 import java.util.Collections;
-import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
 import java.util.Optional;
+import java.util.Set;
 import java.util.stream.Collectors;
 
@@ -18,5 +18,5 @@
  */
 public class Votes extends AbstractAction {
-	private final List<Vote> votes;
+	private final Set<Vote> votes;
 
 	/**
@@ -24,10 +24,10 @@
 	 * @param id    party id
 	 * @param votes the {@link Vote}s that the party can agree on, if the
-	 *              condition of the Vote holds. There can be at most 1
-	 *              {@link Vote} for each bid.
+	 *              condition of the Vote holds. Every {@link Vote#getActor()}
+	 *              should equal the id
 	 */
 	@JsonCreator
 	public Votes(@JsonProperty("actor") PartyId id,
-			@JsonProperty("votes") List<Vote> votes) {
+			@JsonProperty("votes") Set<Vote> votes) {
 		super(id);
 		this.votes = votes;
@@ -40,4 +40,5 @@
 			}
 		}
+		// check for duplicate Vote's, possibly with different powers
 		Map<Bid, Long> counts = votes.stream().map(vote -> vote.getBid())
 				.collect(Collectors.groupingBy(bid -> bid,
@@ -86,6 +87,6 @@
 	}
 
-	public List<Vote> getVotes() {
-		return Collections.unmodifiableList(votes);
+	public Set<Vote> getVotes() {
+		return Collections.unmodifiableSet(votes);
 	}
 
Index: /events/src/main/java/geniusweb/inform/Agreements.java
===================================================================
--- /events/src/main/java/geniusweb/inform/Agreements.java	(revision 25)
+++ /events/src/main/java/geniusweb/inform/Agreements.java	(revision 26)
@@ -5,4 +5,5 @@
 import java.util.Map;
 import java.util.Set;
+import java.util.stream.Collectors;
 
 import com.fasterxml.jackson.annotation.JsonAutoDetect;
@@ -29,6 +30,15 @@
 
 	@JsonCreator
-	private Agreements(Map<PartyId, Bid> agrees) {
+	protected Agreements(Map<PartyId, Bid> agrees) {
 		this.agreements = agrees;
+	}
+
+	/**
+	 * @param bid     a bid that all parties agreed on
+	 * @param parties the {@link PartyId}s of the agreeing parties
+	 */
+	public Agreements(Bid bid, Set<PartyId> parties) {
+		this(parties.stream()
+				.collect(Collectors.toMap(pid -> pid, pid -> bid)));
 	}
 
@@ -48,25 +58,4 @@
 		}
 		return new Agreements(newagrees);
-	}
-
-	/**
-	 * @param bid     a {@link Bid} to be added
-	 * @param parties {@link Set} of the {@link PartyId}s that accepted the bid
-	 * @return new Agreements, with the new bid/parties added.
-	 */
-	public Agreements with(Bid bid, Set<PartyId> parties) {
-		if (parties.size() < 2) {
-			throw new IllegalArgumentException(
-					"Agreement must contain at least 2 parties");
-		}
-		Map<PartyId, Bid> newagreements = new HashMap<>(agreements);
-		for (PartyId party : parties) {
-			if (agreements.containsKey(party)) {
-				throw new IllegalArgumentException(
-						"A party can agree only on 1 bid");
-			}
-			newagreements.put(party, bid);
-		}
-		return new Agreements(newagreements);
 	}
 
Index: /events/src/main/java/geniusweb/inform/Voting.java
===================================================================
--- /events/src/main/java/geniusweb/inform/Voting.java	(revision 25)
+++ /events/src/main/java/geniusweb/inform/Voting.java	(revision 26)
@@ -8,6 +8,6 @@
 import com.fasterxml.jackson.annotation.JsonProperty;
 
+import geniusweb.actions.Offer;
 import geniusweb.actions.PartyId;
-import geniusweb.issuevalue.Bid;
 
 /**
@@ -16,11 +16,11 @@
 public class Voting implements Inform {
 
-	private final List<Bid> bids;
+	private final List<Offer> offers;
 	private final Map<PartyId, Integer> powers;
 
 	@JsonCreator
-	public Voting(@JsonProperty("bids") List<Bid> bids,
+	public Voting(@JsonProperty("offers") List<Offer> offers,
 			@JsonProperty("powers") Map<PartyId, Integer> powers) {
-		this.bids = bids;
+		this.offers = offers;
 		this.powers = powers;
 	}
@@ -29,6 +29,6 @@
 	 * @return list of bids to be voted on
 	 */
-	public List<Bid> getBids() {
-		return Collections.unmodifiableList(bids);
+	public List<Offer> getBids() {
+		return Collections.unmodifiableList(offers);
 	}
 
@@ -47,5 +47,5 @@
 		final int prime = 31;
 		int result = 1;
-		result = prime * result + ((bids == null) ? 0 : bids.hashCode());
+		result = prime * result + ((offers == null) ? 0 : offers.hashCode());
 		result = prime * result + ((powers == null) ? 0 : powers.hashCode());
 		return result;
@@ -61,8 +61,8 @@
 			return false;
 		Voting other = (Voting) obj;
-		if (bids == null) {
-			if (other.bids != null)
+		if (offers == null) {
+			if (other.offers != null)
 				return false;
-		} else if (!bids.equals(other.bids))
+		} else if (!offers.equals(other.offers))
 			return false;
 		if (powers == null) {
@@ -76,5 +76,5 @@
 	@Override
 	public String toString() {
-		return "Voting[" + bids + "," + powers + "]";
+		return "Voting[" + offers + "," + powers + "]";
 	}
 
Index: /events/src/test/java/geniusweb/actions/AcceptTest.java
===================================================================
--- /events/src/test/java/geniusweb/actions/AcceptTest.java	(revision 26)
+++ /events/src/test/java/geniusweb/actions/AcceptTest.java	(revision 26)
@@ -0,0 +1,91 @@
+package geniusweb.actions;
+
+import static org.junit.Assert.assertEquals;
+
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+import geniusweb.issuevalue.Bid;
+import geniusweb.issuevalue.DiscreteValue;
+import geniusweb.issuevalue.NumberValue;
+import geniusweb.issuevalue.Value;
+import tudelft.utilities.junit.GeneralTests;
+
+public class AcceptTest extends GeneralTests<Accept> {
+	private final ObjectMapper jackson = new ObjectMapper();
+
+	private static final PartyId id = new PartyId("party1");
+	private static final PartyId id2 = new PartyId("party2");
+	private final static Map<String, Value> issuevalues = new HashMap<String, Value>();
+	private final static Map<String, Value> issuevaluesb = new HashMap<String, Value>();
+	private static Bid bid;
+	private static Bid bidb;
+	private final static String ISSUE1 = "issue1";
+	private final static Value VALUE1 = new DiscreteValue("value1");
+	private final static String ISSUE2 = "issue2";
+	private final static Value VALUE2 = new NumberValue("10");
+	// issue 2 is NUMBER and thus serializes with leading '='
+	private final String acceptstring = "{\"accept\":{\"actor\":\"party1\",\"bid\":{\"issuevalues\":{\"issue2\":10,\"issue1\":\"value1\"}}}}";
+
+	private static Accept accept, accept1, accept2, acceptb;
+
+	static {
+		issuevalues.put(ISSUE1, VALUE1);
+		issuevalues.put(ISSUE2, VALUE2);
+		bid = new Bid(issuevalues);
+		accept = new Accept(id, bid);
+		accept1 = new Accept(id, bid);
+
+		accept2 = new Accept(id2, bid);
+
+		// values swapped, so different issuevalues.
+		issuevaluesb.put(ISSUE1, VALUE2);
+		issuevaluesb.put(ISSUE2, VALUE2);
+		bidb = new Bid(issuevaluesb);
+		acceptb = new Accept(id, bidb);
+
+	}
+
+	@Override
+	public List<List<Accept>> getGeneralTestData() {
+		List<List<Accept>> list = new LinkedList<>();
+		list.add(Arrays.asList(accept, accept1));
+		list.add(Arrays.asList(accept2));
+		list.add(Arrays.asList(acceptb));
+		return list;
+	}
+
+	@Override
+	public List<String> getGeneralTestStrings() {
+		return Arrays.asList("Accept.*" + id + ".*]", "Accept.*" + id2 + ".*]",
+				"Accept.*" + id + ".*]");
+	}
+
+	@Before
+	public void before() {
+
+	}
+
+	@Test
+	public void serializeAcceptTest() throws JsonProcessingException {
+		System.out.println(jackson.writeValueAsString(accept));
+		assertEquals(acceptstring, jackson.writeValueAsString(accept));
+	}
+
+	@Test
+	public void deserializeAcceptTest() throws IOException {
+		Action act = jackson.readValue(acceptstring, Action.class);
+		assertEquals(accept, act);
+	}
+
+}
Index: /events/src/test/java/geniusweb/actions/ComparisonTest.java
===================================================================
--- /events/src/test/java/geniusweb/actions/ComparisonTest.java	(revision 26)
+++ /events/src/test/java/geniusweb/actions/ComparisonTest.java	(revision 26)
@@ -0,0 +1,97 @@
+package geniusweb.actions;
+
+import static org.junit.Assert.assertEquals;
+
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+import geniusweb.issuevalue.Bid;
+import geniusweb.issuevalue.DiscreteValue;
+import geniusweb.issuevalue.NumberValue;
+import geniusweb.issuevalue.Value;
+import tudelft.utilities.junit.GeneralTests;
+
+public class ComparisonTest extends GeneralTests<Comparison> {
+	private final ObjectMapper jackson = new ObjectMapper();
+
+	private static final PartyId id = new PartyId("party1");
+	private static final PartyId id2 = new PartyId("party2");
+	private final static Map<String, Value> issuevalues = new HashMap<String, Value>();
+	private final static Map<String, Value> issuevaluesb = new HashMap<String, Value>();
+	private static Bid bid;
+	private static Bid bidb;
+	private final static String ISSUE1 = "issue1";
+	private final static Value VALUE1 = new DiscreteValue("value1");
+	private final static String ISSUE2 = "issue2";
+	private final static Value VALUE2 = new NumberValue("10");
+	// issue 2 is NUMBER and thus serializes with leading '='
+	private final String acceptstring = "{\"Comparison\":{\"bid\":{\"issuevalues\":{\"issue2\":10,\"issue1\":\"value1\"}},\"better\":[],\"worse\":[],\"actor\":\"party1\"}}";
+
+	private static Comparison accept, accept1, accept2, acceptb, acceptc,
+			acceptd;
+
+	@Before
+	public void before() {
+		issuevalues.put(ISSUE1, VALUE1);
+		issuevalues.put(ISSUE2, VALUE2);
+		bid = new Bid(issuevalues);
+		List<Bid> better = Collections.EMPTY_LIST;
+		List<Bid> worse = Collections.EMPTY_LIST;
+		accept = new Comparison(id, bid, better, worse);
+		accept1 = new Comparison(id, bid, better, worse);
+
+		accept2 = new Comparison(id2, bid, better, worse);
+
+		// values swapped, so different issuevalues.
+		issuevaluesb.put(ISSUE1, VALUE2);
+		issuevaluesb.put(ISSUE2, VALUE2);
+		bidb = new Bid(issuevaluesb);
+		acceptb = new Comparison(id, bidb, better, worse);
+
+		List<Bid> better1 = Arrays.asList(bid);
+		List<Bid> worse1 = Arrays.asList(bidb);
+		acceptc = new Comparison(id, bidb, better1, worse);
+		acceptd = new Comparison(id, bidb, better, worse1);
+
+	}
+
+	@Override
+	public List<List<Comparison>> getGeneralTestData() {
+		return Arrays.asList(Arrays.asList(accept, accept1),
+				Arrays.asList(accept2), Arrays.asList(acceptb),
+				Arrays.asList(acceptc), Arrays.asList(acceptd));
+	}
+
+	@Override
+	public List<String> getGeneralTestStrings() {
+		return Arrays.asList(
+				"Comparison.*Bid.*issue2=10.*issue1=\"value1\".*better=\\[\\].*worse=\\[\\].*",
+				"Comparison.*party2.*Bid.*issue2=10.*issue1=\"value1\".*better=\\[\\].*worse=\\[\\].*",
+				"Comparison.*party1.*Bid.*issue2=10.*issue1=10.*better=\\[\\].*worse=\\[\\].*",
+				"Comparison.*party1.*Bid.*issue2=10.*issue1=10.*better=\\[Bid.*issue2=10.*issue1=\"value1\".*\\].*worse=\\[\\].*",
+				"Comparison.*party1.*Bid.*issue2=10.*issue1=10.*better=\\[\\].*worse=\\[Bid.*issue2=10.*issue1=10.*\\].*");
+	}
+
+	@Test
+	public void serializeAcceptTest() throws JsonProcessingException {
+		System.out.println(jackson.writeValueAsString(accept));
+		assertEquals(acceptstring, jackson.writeValueAsString(accept));
+	}
+
+	@Test
+	public void deserializeAcceptTest() throws IOException {
+		Action act = jackson.readValue(acceptstring, Action.class);
+		assertEquals(accept, act);
+	}
+
+}
Index: /events/src/test/java/geniusweb/actions/ElicitComparisonTest.java
===================================================================
--- /events/src/test/java/geniusweb/actions/ElicitComparisonTest.java	(revision 26)
+++ /events/src/test/java/geniusweb/actions/ElicitComparisonTest.java	(revision 26)
@@ -0,0 +1,89 @@
+package geniusweb.actions;
+
+import static org.junit.Assert.assertEquals;
+
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+import geniusweb.issuevalue.Bid;
+import geniusweb.issuevalue.DiscreteValue;
+import geniusweb.issuevalue.NumberValue;
+import geniusweb.issuevalue.Value;
+import tudelft.utilities.junit.GeneralTests;
+
+public class ElicitComparisonTest extends GeneralTests<ElicitComparison> {
+	private final ObjectMapper jackson = new ObjectMapper();
+
+	private static final PartyId id = new PartyId("party1");
+	private static final PartyId id2 = new PartyId("party2");
+	private final static Map<String, Value> issuevalues = new HashMap<String, Value>();
+	private final static Map<String, Value> issuevaluesb = new HashMap<String, Value>();
+	private static Bid bid;
+	private static Bid bidb;
+	private final static String ISSUE1 = "issue1";
+	private final static Value VALUE1 = new DiscreteValue("value1");
+	private final static String ISSUE2 = "issue2";
+	private final static Value VALUE2 = new NumberValue("10");
+	// issue 2 is NUMBER and thus serializes with leading '='
+	private final String acceptstring = "{\"ElicitComparison\":{\"actor\":\"party1\",\"bid\":{\"issuevalues\":{\"issue2\":10,\"issue1\":\"value1\"}},\"options\":[{\"issuevalues\":{\"issue2\":10,\"issue1\":\"value1\"}}]}}";
+
+	private static ElicitComparison accept1, accept1a, accept2, accept3,
+			accept4;
+
+	@Before
+	public void before() {
+		issuevalues.put(ISSUE1, VALUE1);
+		issuevalues.put(ISSUE2, VALUE2);
+
+		issuevaluesb.put(ISSUE1, VALUE2);
+		bid = new Bid(issuevalues);
+		bidb = new Bid(issuevaluesb);
+
+		List<Bid> opts = Arrays.asList(bid);
+		List<Bid> opts2 = Arrays.asList(bidb);
+
+		accept1 = new ElicitComparison(id, bid, opts);
+		accept1a = new ElicitComparison(id, bid, opts);
+		accept2 = new ElicitComparison(id2, bid, opts);
+		accept3 = new ElicitComparison(id, bidb, opts);
+		accept4 = new ElicitComparison(id, bid, opts2);
+	}
+
+	@Override
+	public List<List<ElicitComparison>> getGeneralTestData() {
+		return Arrays.asList(Arrays.asList(accept1, accept1a),
+				Arrays.asList(accept2), Arrays.asList(accept3),
+				Arrays.asList(accept4));
+	}
+
+	@Override
+	public List<String> getGeneralTestStrings() {
+		return Arrays.asList(
+				"ElicitComparison.*party1.*Bid.*10.*value1.*\\[.*Bid.*10.*value1.*\\].*",
+				"ElicitComparison.*party2.*Bid.*10.*value1.*\\[.*Bid.*10.*value1.*\\].*",
+				"ElicitComparison.*party1.*Bid.*10.*\\[.*Bid.*10.*value1.*\\].*",
+				"ElicitComparison.*party1.*Bid.*10.*value1.*\\[.*Bid.*10.*\\].*");
+	}
+
+	@Test
+	public void serializeAcceptTest() throws JsonProcessingException {
+		System.out.println(jackson.writeValueAsString(accept1));
+		assertEquals(acceptstring, jackson.writeValueAsString(accept1));
+	}
+
+	@Test
+	public void deserializeAcceptTest() throws IOException {
+		Action act = jackson.readValue(acceptstring, Action.class);
+		assertEquals(accept1, act);
+	}
+
+}
Index: /events/src/test/java/geniusweb/actions/EndNegoTest.java
===================================================================
--- /events/src/test/java/geniusweb/actions/EndNegoTest.java	(revision 26)
+++ /events/src/test/java/geniusweb/actions/EndNegoTest.java	(revision 26)
@@ -0,0 +1,52 @@
+package geniusweb.actions;
+
+import static org.junit.Assert.assertEquals;
+
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.List;
+
+import org.junit.Test;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+import tudelft.utilities.junit.GeneralTests;
+
+public class EndNegoTest extends GeneralTests<EndNegotiation> {
+	private final ObjectMapper jackson = new ObjectMapper();
+
+	private final PartyId id = new PartyId("party1");
+	private final PartyId idb = new PartyId("party2");
+
+	private final EndNegotiation endnego = new EndNegotiation(id);
+	private final EndNegotiation endnego1 = new EndNegotiation(id);
+	private final EndNegotiation endnegob = new EndNegotiation(idb);
+
+	private final String endnegostring = "{\"endnegotiation\":{\"actor\":\"party1\"}}";
+
+	@Override
+	public List<List<EndNegotiation>> getGeneralTestData() {
+		return Arrays.asList(Arrays.asList(endnego, endnego1),
+				Arrays.asList(endnegob));
+	}
+
+	@Override
+	public List<String> getGeneralTestStrings() {
+		return Arrays.asList("EndNegotiation\\[.*" + id + ".*\\]",
+				"EndNegotiation\\[.*" + idb + ".*\\]");
+	}
+
+	@Test
+	public void serializeEndNegoTest() throws JsonProcessingException {
+		System.out.println(jackson.writeValueAsString(endnego));
+		assertEquals(endnegostring, jackson.writeValueAsString(endnego));
+	}
+
+	@Test
+	public void deserializeEndNegoTest() throws IOException {
+		Action act = jackson.readValue(endnegostring, Action.class);
+		assertEquals(endnego, act);
+	}
+
+}
Index: /events/src/test/java/geniusweb/actions/OfferTest.java
===================================================================
--- /events/src/test/java/geniusweb/actions/OfferTest.java	(revision 26)
+++ /events/src/test/java/geniusweb/actions/OfferTest.java	(revision 26)
@@ -0,0 +1,79 @@
+package geniusweb.actions;
+
+import static org.junit.Assert.assertEquals;
+
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.junit.Test;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+import geniusweb.issuevalue.Bid;
+import geniusweb.issuevalue.DiscreteValue;
+import geniusweb.issuevalue.NumberValue;
+import geniusweb.issuevalue.Value;
+import tudelft.utilities.junit.GeneralTests;
+
+public class OfferTest extends GeneralTests<Offer> {
+	private final ObjectMapper jackson = new ObjectMapper();
+
+	private static final PartyId id = new PartyId("party1");
+	private static final Map<String, Value> issuevalues = new HashMap<String, Value>();
+	private static final Map<String, Value> issuevaluesb = new HashMap<String, Value>();
+	private static Bid bid;
+	private static Bid bidb;
+	private static final String ISSUE1 = "issue1";
+	private static final Value VALUE1 = new DiscreteValue("value1");
+	private static final String ISSUE2 = "issue2";
+	private static final Value VALUE2 = new NumberValue("10");
+	private static final String acceptstring = "{\"offer\":{\"actor\":\"party1\",\"bid\":{\"issuevalues\":{\"issue2\":10,\"issue1\":\"value1\"}}}}";
+
+	private static Offer offer;
+	private static Offer offer1;
+	private static Offer offerb;
+
+	static {
+		issuevalues.put(ISSUE1, VALUE1);
+		issuevalues.put(ISSUE2, VALUE2);
+		bid = new Bid(issuevalues);
+		offer = new Offer(id, bid);
+		offer1 = new Offer(id, bid);
+
+		// values swapped, so different issuevalues.
+		issuevaluesb.put(ISSUE1, VALUE2);
+		issuevaluesb.put(ISSUE2, VALUE2);
+		bidb = new Bid(issuevaluesb);
+		offerb = new Offer(id, bidb);
+
+	}
+
+	@Override
+	public List<List<Offer>> getGeneralTestData() {
+		return Arrays.asList(Arrays.asList(offer, offer1),
+				Arrays.asList(offerb));
+	}
+
+	@Override
+	public List<String> getGeneralTestStrings() {
+		return Arrays.asList("Offer\\[.*" + id + ".*Bid.*\\]",
+				"Offer\\[.*" + id + ".*Bid.*\\]");
+	}
+
+	@Test
+	public void serializeAcceptTest() throws JsonProcessingException {
+		System.out.println(jackson.writeValueAsString(offer));
+		assertEquals(acceptstring, jackson.writeValueAsString(offer));
+	}
+
+	@Test
+	public void deserializeAcceptTest() throws IOException {
+		Action act = jackson.readValue(acceptstring, Action.class);
+		assertEquals(offer, act);
+	}
+
+}
Index: /events/src/test/java/geniusweb/actions/PartyIdTest.java
===================================================================
--- /events/src/test/java/geniusweb/actions/PartyIdTest.java	(revision 26)
+++ /events/src/test/java/geniusweb/actions/PartyIdTest.java	(revision 26)
@@ -0,0 +1,74 @@
+package geniusweb.actions;
+
+import static org.junit.Assert.assertEquals;
+
+import java.util.Arrays;
+import java.util.List;
+
+import org.junit.Test;
+
+import tudelft.utilities.junit.GeneralTests;
+
+public class PartyIdTest extends GeneralTests<PartyId> {
+	private final PartyId id = new PartyId("party1");
+	private final PartyId id1 = new PartyId("party1");
+	private final PartyId idb = new PartyId("party2");
+
+	@Override
+	public List<List<PartyId>> getGeneralTestData() {
+		return Arrays.asList(Arrays.asList(id, id1), Arrays.asList(idb));
+	}
+
+	@Override
+	public List<String> getGeneralTestStrings() {
+		return Arrays.asList("party1", "party2");
+	}
+
+	@SuppressWarnings("unused")
+	@Test(expected = IllegalArgumentException.class)
+	public void testRestrictions() {
+		new PartyId("");
+	}
+
+	@SuppressWarnings("unused")
+	@Test(expected = IllegalArgumentException.class)
+	public void testRestrictions2() {
+		new PartyId("@2");
+	}
+
+	@SuppressWarnings("unused")
+	@Test(expected = IllegalArgumentException.class)
+	public void testRestrictions3() {
+		new PartyId("_12");
+	}
+
+	@SuppressWarnings("unused")
+	@Test(expected = IllegalArgumentException.class)
+	public void testRestrictions4() {
+		new PartyId("12A");
+	}
+
+	@SuppressWarnings("unused")
+	@Test(expected = IllegalArgumentException.class)
+	public void testRestrictions5() {
+		new PartyId(" fds ");
+	}
+
+	@Test
+	public void testGetName() {
+		assertEquals("party1", id.getName());
+	}
+
+	@SuppressWarnings("unused")
+	@Test
+	public void testRestrictions6() {
+		new PartyId("A_1_23_ok");
+	}
+
+	@SuppressWarnings("unused")
+	@Test
+	public void testRestrictions7() {
+		new PartyId("a_1_23_ok");
+	}
+
+}
Index: /events/src/test/java/geniusweb/actions/PartyIdTest1.java
===================================================================
--- /events/src/test/java/geniusweb/actions/PartyIdTest1.java	(revision 26)
+++ /events/src/test/java/geniusweb/actions/PartyIdTest1.java	(revision 26)
@@ -0,0 +1,74 @@
+package geniusweb.actions;
+
+import static org.junit.Assert.assertEquals;
+
+import java.io.IOException;
+import java.net.URISyntaxException;
+import java.util.Arrays;
+import java.util.List;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import com.fasterxml.jackson.core.JsonParseException;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.JsonMappingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+import tudelft.utilities.junit.GeneralTests;
+
+public class PartyIdTest1 extends GeneralTests<PartyId> {
+
+	private PartyId party1, party1a, party2, party3;
+	private String asJson = "\"party1\"";
+
+	@Before
+	public void before() throws URISyntaxException {
+		party1 = new PartyId("party1");
+		party1a = new PartyId("party1");
+		party2 = new PartyId("party2");
+		party3 = new PartyId("party3");
+	}
+
+	@Override
+	public List<List<PartyId>> getGeneralTestData() {
+		return Arrays.asList(Arrays.asList(party1, party1a),
+				Arrays.asList(party2), Arrays.asList(party3));
+	}
+
+	@Override
+	public List<String> getGeneralTestStrings() {
+		return Arrays.asList("party1", "party2", "party3");
+	}
+
+	@SuppressWarnings("unused")
+	@Test(expected = IllegalArgumentException.class)
+	public void smokeTest() throws URISyntaxException {
+		new PartyId("*Csh789&@#^!^@^&");
+	}
+
+	@SuppressWarnings("unused")
+	@Test(expected = IllegalArgumentException.class)
+	public void nullTest() throws URISyntaxException {
+		new PartyId(null);
+	}
+
+	@Test
+	public void testSerialize() throws JsonProcessingException {
+		ObjectMapper jackson = new ObjectMapper();
+
+		String json = jackson.writeValueAsString(party1);
+		System.out.println(json);
+		assertEquals(asJson, json);
+	}
+
+	@Test
+	public void testDeserialize()
+			throws JsonParseException, JsonMappingException, IOException {
+		ObjectMapper jackson = new ObjectMapper();
+		PartyId p = jackson.readValue(asJson, PartyId.class);
+		System.out.println(p);
+		assertEquals(party1, p);
+	}
+
+}
Index: /events/src/test/java/geniusweb/actions/VoteTest.java
===================================================================
--- /events/src/test/java/geniusweb/actions/VoteTest.java	(revision 26)
+++ /events/src/test/java/geniusweb/actions/VoteTest.java	(revision 26)
@@ -0,0 +1,94 @@
+package geniusweb.actions;
+
+import static org.junit.Assert.assertEquals;
+
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+import geniusweb.issuevalue.Bid;
+import geniusweb.issuevalue.DiscreteValue;
+import geniusweb.issuevalue.NumberValue;
+import geniusweb.issuevalue.Value;
+import tudelft.utilities.junit.GeneralTests;
+
+public class VoteTest extends GeneralTests<Vote> {
+	private final ObjectMapper jackson = new ObjectMapper();
+
+	private static final PartyId id = new PartyId("party1");
+	private static final PartyId id2 = new PartyId("party2");
+	private final static Map<String, Value> issuevalues = new HashMap<String, Value>();
+	private final static Map<String, Value> issuevaluesb = new HashMap<String, Value>();
+	private static Bid bid;
+	private static Bid bidb;
+	private final static String ISSUE1 = "issue1";
+	private final static Value VALUE1 = new DiscreteValue("value1");
+	private final static String ISSUE2 = "issue2";
+	private final static Value VALUE2 = new NumberValue("10");
+	// issue 2 is NUMBER and thus serializes with leading '='
+	private final String votestring = "{\"vote\":{\"actor\":\"party1\",\"bid\":{\"issuevalues\":{\"issue2\":10,\"issue1\":\"value1\"}},\"minPower\":1,\"maxPower\":2}}";
+
+	private static Vote vote1, vote1a, vote2, vote3, vote4, vote5;
+
+	static {
+		issuevalues.put(ISSUE1, VALUE1);
+		issuevalues.put(ISSUE2, VALUE2);
+		bid = new Bid(issuevalues);
+		vote1 = new Vote(id, bid, 1, 2);
+		vote1a = new Vote(id, bid, 1, 2);
+
+		vote2 = new Vote(id2, bid, 1, 2);
+
+		// values swapped, so different issuevalues.
+		issuevaluesb.put(ISSUE1, VALUE2);
+		issuevaluesb.put(ISSUE2, VALUE2);
+		bidb = new Bid(issuevaluesb);
+		vote3 = new Vote(id, bidb, 1, 2);
+
+		vote4 = new Vote(id, bid, 2, 2);
+		vote5 = new Vote(id, bid, 1, 3);
+
+	}
+
+	@Override
+	public List<List<Vote>> getGeneralTestData() {
+		return Arrays.asList(Arrays.asList(vote1, vote1a), Arrays.asList(vote2),
+				Arrays.asList(vote3), Arrays.asList(vote4),
+				Arrays.asList(vote5));
+	}
+
+	@Override
+	public List<String> getGeneralTestStrings() {
+		return Arrays.asList("Vote.*party1.*issue2=10.*issue1=.value1.*1.*2.*",
+				"Vote.*party2.*issue2=10.*issue1=.value1.*1.*2.*",
+				"Vote.*party1.*issue2=10.*issue1=10.*1.*2.*",
+				"Vote.*party1.*issue2=10.*issue1=.value1.*2.*2.*",
+				"Vote.*party1.*issue2=10.*issue1=.value1.*1.*3.*");
+	}
+
+	@Before
+	public void before() {
+
+	}
+
+	@Test
+	public void serializeTest() throws JsonProcessingException {
+		System.out.println(jackson.writeValueAsString(vote1));
+		assertEquals(votestring, jackson.writeValueAsString(vote1));
+	}
+
+	@Test
+	public void deserializeAcceptTest() throws IOException {
+		Action act = jackson.readValue(votestring, Action.class);
+		assertEquals(vote1, act);
+	}
+
+}
Index: /events/src/test/java/geniusweb/actions/VotesTest.java
===================================================================
--- /events/src/test/java/geniusweb/actions/VotesTest.java	(revision 26)
+++ /events/src/test/java/geniusweb/actions/VotesTest.java	(revision 26)
@@ -0,0 +1,147 @@
+package geniusweb.actions;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+
+import org.junit.Test;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+import geniusweb.issuevalue.Bid;
+import geniusweb.issuevalue.DiscreteValue;
+import tudelft.utilities.junit.GeneralTests;
+
+public class VotesTest extends GeneralTests<Votes> {
+	private final ObjectMapper jackson = new ObjectMapper();
+	private final String votestring = "{\"Votes\":{\"actor\":\"partyA\",\"votes\":[{\"vote\":{\"actor\":\"partyA\",\"bid\":{\"issuevalues\":{\"is1\":\"val1\"}},\"minPower\":2,\"maxPower\":9}},{\"vote\":{\"actor\":\"partyA\",\"bid\":{\"issuevalues\":{\"is1\":\"val2\"}},\"minPower\":2,\"maxPower\":9}}]}}";
+
+	private PartyId partyA = new PartyId("partyA");
+	private PartyId partyB = new PartyId("partyB");
+	private Bid bid1 = new Bid("is1", new DiscreteValue("val1")),
+			bid2 = new Bid("is1", new DiscreteValue("val2"));
+	private Vote voteA1 = new Vote(partyA, bid1, 2, 9);
+	private Vote voteA2 = new Vote(partyA, bid2, 2, 9);
+	private Vote voteB1 = new Vote(partyB, bid1, 2, 9);
+	private Vote voteB2 = new Vote(partyB, bid2, 2, 9);
+
+	private Votes votes1 = new Votes(partyA,
+			new HashSet<>(Arrays.asList(voteA1, voteA2)));
+	private Votes votes1a = new Votes(partyA,
+			new HashSet<>(Arrays.asList(voteA1, voteA2)));
+	private Votes votes2 = new Votes(partyB,
+			new HashSet<>(Arrays.asList(voteB1, voteB2)));
+
+	@Override
+	public List<List<Votes>> getGeneralTestData() {
+		return Arrays.asList(Arrays.asList(votes1, votes1a),
+				Arrays.asList(votes2));
+	}
+
+	@Override
+	public List<String> getGeneralTestStrings() {
+		return Arrays.asList(
+				"Votes.*Vote.*partyA,Bid.*is1.*val1.*2.*Vote.*partyA,Bid.*is1.*val2.*2.*",
+				"Votes.*Vote.*partyB,Bid.*is1.*val2.*2.*Vote.*partyB,Bid.*is1.*val1.*2.*");
+	}
+
+	@SuppressWarnings("unused")
+	@Test(expected = IllegalArgumentException.class)
+	public void testRejectVoteWithIncorrectParty() {
+		new Votes(partyA, Collections.singleton(voteB1));
+	}
+
+	@Test
+	public void serializeTest() throws JsonProcessingException {
+		System.out.println(jackson.writeValueAsString(votes1));
+		assertEquals(votestring, jackson.writeValueAsString(votes1));
+	}
+
+	@Test
+	public void deserializeTest() throws IOException {
+		Action act = jackson.readValue(votestring, Action.class);
+		assertEquals(votes1, act);
+	}
+
+	@Test(expected = IllegalArgumentException.class)
+	public void testWrongPartyName() {
+		new Votes(partyA, new HashSet<>(Arrays.asList(voteB1, voteB2)));
+	}
+
+	@Test
+	public void isExtendingTestExtraVote() {
+		Votes otherVotes = new Votes(partyA, Collections.singleton(voteA1));
+		assertTrue(votes1.isExtending(otherVotes));
+	}
+
+	@Test
+	public void isExtendingTestNoVotes() {
+		Votes otherVotes = new Votes(partyA, Collections.emptySet());
+		assertTrue(votes1.isExtending(otherVotes));
+	}
+
+	@Test
+	public void isExtendingTestMissing() {
+		Votes otherVotes = new Votes(partyA, Collections.singleton(voteA1));
+		assertFalse(otherVotes.isExtending(votes1));
+	}
+
+	@Test
+	public void isExtendingIdenticalVotes() {
+		assertTrue(votes1.isExtending(votes1));
+	}
+
+	@Test
+	public void isReallyExtendingVotesMin() {
+		Vote powervoteA1 = new Vote(partyA, bid1, 1, 9);
+		Votes powerVotes = new Votes(partyA,
+				new HashSet<>(Arrays.asList(powervoteA1, voteA2)));
+		assertTrue(powerVotes.isExtending(votes1));
+	}
+
+	@Test
+	public void isReallyExtendingVotesMax() {
+		Vote powervoteA1 = new Vote(partyA, bid1, 2, 10);
+		Votes powerVotes = new Votes(partyA,
+				new HashSet<>(Arrays.asList(powervoteA1, voteA2)));
+		assertTrue(powerVotes.isExtending(votes1));
+	}
+
+	@Test
+	public void IsNarrowingOneVoteRemoved() {
+		Votes narrowVotes = new Votes(partyA, Collections.singleton(voteA2));
+		assertFalse(narrowVotes.isExtending(votes1));
+	}
+
+	@Test
+	public void isNarrowingTestMoreMinPower() {
+		Vote narrowVoteA1 = new Vote(partyA, bid1, 3, 9);
+		Votes narrowVotes = new Votes(partyA,
+				new HashSet<>(Arrays.asList(narrowVoteA1, voteA2)));
+		assertFalse(narrowVotes.isExtending(votes1));
+		assertTrue(votes1.isExtending(narrowVotes));
+	}
+
+	@Test
+	public void isNarrowingLessMaxPower() {
+		Vote powervoteA1 = new Vote(partyA, bid1, 2, 8);
+		Votes narrowVotes = new Votes(partyA,
+				new HashSet<>(Arrays.asList(powervoteA1, voteA2)));
+		assertFalse(narrowVotes.isExtending(votes1));
+		assertTrue(votes1.isExtending(narrowVotes));
+	}
+
+	@Test(expected = IllegalArgumentException.class)
+	public void testDuplicateBidsNotAllowed() {
+		Vote voteA1similar = new Vote(partyA, bid1, 3, 9);
+		Votes votes = new Votes(partyA,
+				new HashSet<>(Arrays.asList(voteA1, voteA1similar)));
+	}
+}
Index: /events/src/test/java/geniusweb/events/ActionEventTest.java
===================================================================
--- /events/src/test/java/geniusweb/events/ActionEventTest.java	(revision 26)
+++ /events/src/test/java/geniusweb/events/ActionEventTest.java	(revision 26)
@@ -0,0 +1,71 @@
+package geniusweb.events;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.mock;
+
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.List;
+
+import org.junit.Test;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+import geniusweb.actions.Action;
+import geniusweb.actions.EndNegotiation;
+import geniusweb.actions.PartyId;
+import tudelft.utilities.junit.GeneralTests;
+
+public class ActionEventTest extends GeneralTests<ActionEvent> {
+	private static final long NOW = 101l;
+	private final ObjectMapper jackson = new ObjectMapper();
+	private final String string = "{\"actionevent\":{\"action\":{\"endnegotiation\":{\"actor\":\"party1\"}},\"time\":101}}";
+	private final PartyId id = new PartyId("party1");
+	private final Action action = new EndNegotiation(id);
+	private final ActionEvent evt = new ActionEvent(action, NOW);
+	private final ActionEvent evt1 = new ActionEvent(action, NOW);
+	private final ActionEvent evtb = new ActionEvent(action, NOW + 1);
+
+	@Override
+	public List<List<ActionEvent>> getGeneralTestData() {
+		return Arrays.asList(Arrays.asList(evt, evt1), Arrays.asList(evtb));
+	}
+
+	@Override
+	public List<String> getGeneralTestStrings() {
+		return Arrays.asList("ActionEvent\\[.*" + NOW + ".*EndNegotiation.*\\]",
+				"ActionEvent\\[.*" + (NOW + 1) + ".*EndNegotiation.*\\]");
+	}
+
+	@Test
+	public void smoketest() {
+		Action action = mock(EndNegotiation.class);
+		ActionEvent evt = new ActionEvent(action, 0l);
+	}
+
+	@Test
+	public void serializeTest() throws JsonProcessingException {
+		System.out.println(jackson.writeValueAsString(evt));
+		assertEquals(string, jackson.writeValueAsString(evt));
+	}
+
+	@Test
+	public void deserializeTestReadActionEvent() throws IOException {
+		ActionEvent evt1 = jackson.readValue(string, ActionEvent.class);
+		// compare fields, as evt is a derived/new inner class
+		assertEquals(EndNegotiation.class, evt1.getAction().getClass());
+		assertEquals((Long) 101l, evt1.getTime());
+	}
+
+	@Test
+	public void deserializeTestReadEvent() throws IOException {
+		NegotiationEvent evt1 = jackson.readValue(string,
+				NegotiationEvent.class);
+		assertEquals(ActionEvent.class, evt1.getClass());
+		ActionEvent ev1 = (ActionEvent) evt1;
+		assertEquals(EndNegotiation.class, ev1.getAction().getClass());
+		assertEquals((Long) 101l, ev1.getTime());
+	}
+
+}
Index: /events/src/test/java/geniusweb/events/SessionStartedTest.java
===================================================================
--- /events/src/test/java/geniusweb/events/SessionStartedTest.java	(revision 26)
+++ /events/src/test/java/geniusweb/events/SessionStartedTest.java	(revision 26)
@@ -0,0 +1,95 @@
+package geniusweb.events;
+
+import static org.junit.Assert.assertEquals;
+
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.LinkedList;
+import java.util.List;
+
+import org.junit.Test;
+import org.junit.experimental.theories.DataPoint;
+import org.junit.experimental.theories.DataPoints;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+import geniusweb.actions.PartyId;
+import tudelft.utilities.junit.GeneralTests;
+
+public class SessionStartedTest extends GeneralTests<SessionStarted> {
+
+	private final ObjectMapper jackson = new ObjectMapper();
+
+	private static final Long SESSIONNR = 1l;
+	protected static final Long NOW = (long) 101;
+	protected static final Long NOW1 = NOW + 1;
+
+	private static final PartyId PARTY1 = new PartyId("party1");
+	private static final PartyId PARTY2 = new PartyId("party2");
+
+	private static List<PartyId> parties = Arrays.asList(PARTY1, PARTY2);
+
+	private static final SessionStarted sessionStartedLater = new SessionStarted(
+			SESSIONNR, parties, NOW1);
+	private static final SessionStarted othersessionStarted = new SessionStarted(
+			SESSIONNR + 1, parties, NOW);
+
+	public static SessionStarted sessionStarted = new SessionStarted(SESSIONNR,
+			parties, NOW);
+	private static final SessionStarted sessionStarted1 = new SessionStarted(
+			SESSIONNR, parties, NOW);
+	// jackson expected format.
+	private static String sessionstartedstring = "{\"sessionstarted\":{\"sessionNumber\":1,\"parties\":[\"party1\",\"party2\"],\"time\":101}}";
+	// "{\"sessionstarted\":{\"time\":101,\"sessionNumber\":1,\"parties\":[\"party1\",\"party2\"]}}";
+	public static String expectedstring = "SessionStarted.*101.*";
+
+	@Override
+	public List<List<SessionStarted>> getGeneralTestData() {
+		List<List<SessionStarted>> list = new LinkedList<>();
+		list.add(Arrays.asList(sessionStarted, sessionStarted1));
+		list.add(Arrays.asList(sessionStartedLater));
+		list.add(Arrays.asList(othersessionStarted));
+		return list;
+	}
+
+	@Override
+	public List<String> getGeneralTestStrings() {
+		return Arrays.asList("SessionStarted.*" + SESSIONNR + ".*" + NOW + ".*",
+				"SessionStarted.*" + SESSIONNR + ".*" + NOW1 + ".*",
+				"SessionStarted.*" + (SESSIONNR + 1) + ".*" + NOW + ".*");
+	}
+
+	@DataPoints("equal")
+	public static SessionStarted[] equal() {
+		return new SessionStarted[] { sessionStarted, sessionStarted1 };
+	}
+
+	@DataPoints("notequal")
+	public static SessionStarted[] notequal() {
+		return new SessionStarted[] { sessionStartedLater,
+				sessionStartedLater };
+	}
+
+	@DataPoint("equalstring")
+
+	@Test
+	public void serializeStartedTest() throws JsonProcessingException {
+		System.out.println(jackson.writeValueAsString(sessionStarted));
+		assertEquals(sessionstartedstring,
+				jackson.writeValueAsString(sessionStarted));
+	}
+
+	@Test
+	public void deserializeStartedTest() throws IOException {
+		NegotiationEvent evt = jackson.readValue(sessionstartedstring,
+				NegotiationEvent.class);
+		assertEquals(SessionStarted.class, evt.getClass());
+		SessionStarted event = (SessionStarted) evt;
+		// compare fields, as sessionended is a derived/new inner class
+		assertEquals(NOW, event.getTime());
+		assertEquals(SESSIONNR, event.getSessionNumber());
+		assertEquals(2, event.getParties().size());
+	}
+
+}
Index: /events/src/test/java/geniusweb/events/TournamentStartedTest.java
===================================================================
--- /events/src/test/java/geniusweb/events/TournamentStartedTest.java	(revision 26)
+++ /events/src/test/java/geniusweb/events/TournamentStartedTest.java	(revision 26)
@@ -0,0 +1,84 @@
+package geniusweb.events;
+
+import static org.junit.Assert.assertEquals;
+
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.LinkedList;
+import java.util.List;
+
+import org.junit.Test;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+import tudelft.utilities.junit.GeneralTests;
+
+public class TournamentStartedTest extends GeneralTests<TournamentStarted> {
+
+	private final ObjectMapper jackson = new ObjectMapper();
+
+	private static final Long SESSIONNR = 1l;
+	protected static final Long NOW = (long) 101;
+	protected static final Long NOW1 = NOW + 1;
+	private static final Long NSESSIONS = 5l;
+
+	private static TournamentStarted tournamentStarted = new TournamentStarted(
+			NSESSIONS, NOW);
+	private static TournamentStarted tournamentStarteda = new TournamentStarted(
+			NSESSIONS, NOW);
+	private TournamentStarted otherTournamentStarted = new TournamentStarted(
+			NSESSIONS + 1, NOW);
+	private TournamentStarted tournamentStartedLater = new TournamentStarted(
+			NSESSIONS, NOW1);
+
+	private String tournamentstartedstring = "{\"tournamentstarted\":{\"time\":101,\"numberOfSessions\":5}}";
+
+	@Override
+	public List<List<TournamentStarted>> getGeneralTestData() {
+		List<List<TournamentStarted>> list = new LinkedList<>();
+		list.add(Arrays.asList(tournamentStarted, tournamentStarteda));
+		list.add(Arrays.asList(otherTournamentStarted));
+		list.add(Arrays.asList(tournamentStartedLater));
+		return list;
+	}
+
+	@Override
+	public List<String> getGeneralTestStrings() {
+		return Arrays.asList(
+				"TournamentStarted\\[.*" + NOW + ".*" + NSESSIONS + ".*\\]",
+				"TournamentStarted\\[.*" + NOW + ".*" + (NSESSIONS + 1)
+						+ ".*\\]",
+				"TournamentStarted\\[.*" + NOW1 + ".*" + NSESSIONS + ".*\\]");
+	}
+
+	@Test
+	public void serializeTournamentStartedTest()
+			throws JsonProcessingException {
+		System.out.println(jackson.writeValueAsString(tournamentStarted));
+		assertEquals(tournamentstartedstring,
+				jackson.writeValueAsString(tournamentStarted));
+	}
+
+	@Test
+	public void deserializeTournamentStartedTest() throws IOException {
+		NegotiationEvent evt = jackson.readValue(tournamentstartedstring,
+				NegotiationEvent.class);
+		assertEquals(TournamentStarted.class, evt.getClass());
+		TournamentStarted event = (TournamentStarted) evt;
+		// compare fields, as sessionended is a derived/new inner class
+		assertEquals(NSESSIONS, event.getNumberOfSessions());
+		assertEquals(NOW, event.getTime());
+	}
+
+	@Test(expected = IllegalArgumentException.class)
+	public void testNullTime() {
+		new TournamentStarted(NSESSIONS, null);
+	}
+
+	@Test(expected = IllegalArgumentException.class)
+	public void testNegativeTime() {
+		new TournamentStarted(NSESSIONS, -1l);
+	}
+
+}
Index: /events/src/test/java/geniusweb/inform/ActionDoneTest.java
===================================================================
--- /events/src/test/java/geniusweb/inform/ActionDoneTest.java	(revision 26)
+++ /events/src/test/java/geniusweb/inform/ActionDoneTest.java	(revision 26)
@@ -0,0 +1,69 @@
+package geniusweb.inform;
+
+import static org.junit.Assert.assertEquals;
+
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.List;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+import geniusweb.actions.Action;
+import geniusweb.actions.EndNegotiation;
+import geniusweb.actions.PartyId;
+import tudelft.utilities.junit.GeneralTests;
+
+public class ActionDoneTest extends GeneralTests<ActionDone> {
+	private final ObjectMapper jackson = new ObjectMapper();
+
+	private static final PartyId id = new PartyId("party1");
+	private static final PartyId id2 = new PartyId("party2");
+
+	private final String actiondonestr = "{\"ActionDone\":{\"action\":{\"endnegotiation\":{\"actor\":\"party1\"}}}}";
+
+	private final static Action act1 = new EndNegotiation(id);
+	private final static Action act2 = new EndNegotiation(id2);
+
+	private final static ActionDone done1 = new ActionDone(act1);
+	private final static ActionDone done1a = new ActionDone(act1);
+	private final static ActionDone done2 = new ActionDone(act2);
+
+	@Override
+	public List<List<ActionDone>> getGeneralTestData() {
+		return Arrays.asList(Arrays.asList(done1, done1a),
+				Arrays.asList(done2));
+	}
+
+	@Override
+	public List<String> getGeneralTestStrings() {
+		return Arrays.asList("ActionDone.*EndNegotiation.*party1.*",
+				"ActionDone.*EndNegotiation.*party2.*");
+	}
+
+	@Before
+	public void before() {
+
+	}
+
+	@Test
+	public void serializeAcceptTest() throws JsonProcessingException {
+		System.out.println(jackson.writeValueAsString(done1));
+		assertEquals(actiondonestr, jackson.writeValueAsString(done1));
+	}
+
+	@Test
+	public void deserializeAcceptTest() throws IOException {
+		Inform act = jackson.readValue(actiondonestr, Inform.class);
+		assertEquals(done1, act);
+	}
+
+	@Test
+	public void testGet() {
+		assertEquals(act1, done1.getAction());
+	}
+
+}
Index: /events/src/test/java/geniusweb/inform/AgreementsTest.java
===================================================================
--- /events/src/test/java/geniusweb/inform/AgreementsTest.java	(revision 26)
+++ /events/src/test/java/geniusweb/inform/AgreementsTest.java	(revision 26)
@@ -0,0 +1,100 @@
+package geniusweb.inform;
+
+import static org.junit.Assert.assertEquals;
+
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+import geniusweb.actions.PartyId;
+import geniusweb.issuevalue.Bid;
+import geniusweb.issuevalue.DiscreteValue;
+import geniusweb.issuevalue.Value;
+import tudelft.utilities.junit.GeneralTests;
+
+public class AgreementsTest extends GeneralTests<Agreements> {
+	private final ObjectMapper jackson = new ObjectMapper();
+
+	private static final PartyId id = new PartyId("party1");
+	private static final PartyId id2 = new PartyId("party2");
+	private final static Value VALUE1 = new DiscreteValue("value1");
+	private static Bid bid = new Bid(
+			Collections.singletonMap("issue1", VALUE1));
+	private static Bid bid2 = new Bid(
+			Collections.singletonMap("issue2", VALUE1));
+
+	private final String finishedstring = "{\"party1\":{\"issuevalues\":{\"issue1\":\"value1\"}}}";
+
+	private final static Agreements agrees1 = new Agreements(
+			Collections.singletonMap(id, bid));
+	private final static Agreements agrees1a = new Agreements(
+			Collections.singletonMap(id, bid));
+	private final static Agreements agrees2 = new Agreements(
+			Collections.singletonMap(id2, bid));
+	private final static Agreements agrees3 = new Agreements(
+			Collections.singletonMap(id, bid2));
+
+	@Override
+	public List<List<Agreements>> getGeneralTestData() {
+		return Arrays.asList(Arrays.asList(agrees1, agrees1a),
+				Arrays.asList(agrees2), Arrays.asList(agrees3));
+	}
+
+	@Override
+	public List<String> getGeneralTestStrings() {
+		return Arrays.asList("Agreements.*party1.*Bid.*issue1.*",
+				"Agreements.*party2.*Bid.*issue1.*",
+				"Agreements.*party1.*Bid.*issue2.*");
+	}
+
+	@Before
+	public void before() {
+
+	}
+
+	@Test
+	public void serializeAcceptTest() throws JsonProcessingException {
+		System.out.println(jackson.writeValueAsString(agrees1));
+		assertEquals(finishedstring, jackson.writeValueAsString(agrees1));
+	}
+
+	@Test
+	public void deserializeAcceptTest() throws IOException {
+		Agreements act = jackson.readValue(finishedstring, Agreements.class);
+		assertEquals(agrees1, act);
+	}
+
+	@SuppressWarnings("unused")
+	@Test
+	public void testNull() {
+		new Agreements();
+	}
+
+	@Test(expected = IllegalArgumentException.class)
+	public void testWithAlreadyActed() {
+		agrees1.with(agrees1);
+	}
+
+	@Test
+	public void testWith() {
+		Agreements agrees = agrees1.with(agrees2);
+		assertEquals(bid, agrees.getMap().get(id));
+		assertEquals(bid, agrees.getMap().get(id2));
+	}
+
+	@Test
+	public void testBidConstructor() {
+		Agreements agrees = new Agreements(bid,
+				new HashSet<PartyId>(Arrays.asList(id, id2)));
+		assertEquals(bid, agrees.getMap().get(id));
+		assertEquals(bid, agrees.getMap().get(id2));
+	}
+}
Index: /events/src/test/java/geniusweb/inform/FinishedTest.java
===================================================================
--- /events/src/test/java/geniusweb/inform/FinishedTest.java	(revision 26)
+++ /events/src/test/java/geniusweb/inform/FinishedTest.java	(revision 26)
@@ -0,0 +1,76 @@
+package geniusweb.inform;
+
+import static org.junit.Assert.assertEquals;
+
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+import geniusweb.actions.PartyId;
+import geniusweb.issuevalue.Bid;
+import geniusweb.issuevalue.DiscreteValue;
+import geniusweb.issuevalue.Value;
+import tudelft.utilities.junit.GeneralTests;
+
+public class FinishedTest extends GeneralTests<Finished> {
+	private final ObjectMapper jackson = new ObjectMapper();
+
+	private static final PartyId id = new PartyId("party1");
+	private static final PartyId id2 = new PartyId("party2");
+	private final static Value VALUE1 = new DiscreteValue("value1");
+	private static Bid bid = new Bid(
+			Collections.singletonMap("issue1", VALUE1));
+
+	private final String finishedstring = "{\"Finished\":{\"agreements\":{\"party1\":{\"issuevalues\":{\"issue1\":\"value1\"}}}}}";
+
+	private final static Agreements agrees1 = new Agreements(
+			Collections.singletonMap(id, bid));
+	private final static Agreements agrees2 = new Agreements(
+			Collections.singletonMap(id2, bid));
+
+	private final static Finished finished1 = new Finished(agrees1);
+	private final static Finished finished1a = new Finished(agrees1);
+	private final static Finished finished2 = new Finished(agrees2);
+
+	@Override
+	public List<List<Finished>> getGeneralTestData() {
+		return Arrays.asList(Arrays.asList(finished1, finished1a),
+				Arrays.asList(finished2));
+	}
+
+	@Override
+	public List<String> getGeneralTestStrings() {
+		return Arrays.asList("Finished.*party1.*Bid.*",
+				"Finished.*party2.*Bid.*");
+	}
+
+	@Before
+	public void before() {
+
+	}
+
+	@Test
+	public void serializeAcceptTest() throws JsonProcessingException {
+		System.out.println(jackson.writeValueAsString(finished1));
+		assertEquals(finishedstring, jackson.writeValueAsString(finished1));
+	}
+
+	@Test
+	public void deserializeAcceptTest() throws IOException {
+		Inform act = jackson.readValue(finishedstring, Inform.class);
+		assertEquals(finished1, act);
+	}
+
+	@Test(expected = NullPointerException.class)
+	public void testNull() {
+		new Finished(null);
+	}
+
+}
Index: /events/src/test/java/geniusweb/inform/OptInTest.java
===================================================================
--- /events/src/test/java/geniusweb/inform/OptInTest.java	(revision 26)
+++ /events/src/test/java/geniusweb/inform/OptInTest.java	(revision 26)
@@ -0,0 +1,77 @@
+package geniusweb.inform;
+
+import static org.junit.Assert.assertEquals;
+
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+
+import org.junit.Test;
+
+import com.fasterxml.jackson.core.JsonParseException;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.JsonMappingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+import geniusweb.actions.PartyId;
+import geniusweb.actions.Vote;
+import geniusweb.actions.Votes;
+import geniusweb.issuevalue.Bid;
+import geniusweb.issuevalue.DiscreteValue;
+import tudelft.utilities.junit.GeneralTests;
+
+public class OptInTest extends GeneralTests<OptIn> {
+
+	private Bid bid1 = new Bid("iss", new DiscreteValue("val1"));
+	private Bid bid2 = new Bid("iss", new DiscreteValue("val2"));
+	private PartyId partyA = new PartyId("partyA");
+	private PartyId partyB = new PartyId("partyB");
+
+	private final Vote voteA1 = new Vote(partyA, bid1, 2, 9);
+	private final Vote voteB1 = new Vote(partyB, bid1, 2, 9);
+	private final Vote voteB2 = new Vote(partyB, bid2, 2, 9);
+
+	private Votes votesA = new Votes(partyA, Collections.singleton(voteA1));
+	private Votes votesB = new Votes(partyB,
+			new HashSet<>(Arrays.asList(voteB1, voteB2)));
+
+	private final OptIn optIn1 = new OptIn(Arrays.asList(votesA, votesB));
+	private final OptIn optIn1a = new OptIn(Arrays.asList(votesA, votesB));
+	private final OptIn optIn2 = new OptIn(Arrays.asList(votesA));
+
+	private String asJson = "{\"OptIn\":{\"votes\":[{\"Votes\":{\"actor\":\"partyA\",\"votes\":[{\"vote\":{\"actor\":\"partyA\",\"bid\":{\"issuevalues\":{\"iss\":\"val1\"}},\"minPower\":2,\"maxPower\":9}}]}},{\"Votes\":{\"actor\":\"partyB\",\"votes\":[{\"vote\":{\"actor\":\"partyB\",\"bid\":{\"issuevalues\":{\"iss\":\"val2\"}},\"minPower\":2,\"maxPower\":9}},{\"vote\":{\"actor\":\"partyB\",\"bid\":{\"issuevalues\":{\"iss\":\"val1\"}},\"minPower\":2,\"maxPower\":9}}]}}]}}";
+
+	@Override
+	public List<List<OptIn>> getGeneralTestData() {
+		return Arrays.asList(Arrays.asList(optIn1, optIn1a),
+				Arrays.asList(optIn2));
+	}
+
+	@Override
+	public List<String> getGeneralTestStrings() {
+		return Arrays.asList(
+				"OptIn.*Votes.*Vote.*partyA.*iss.*val1.*2.*Votes.*Vote.*partyB.*iss.*val2.*.*2.*Vote.*partyB.*iss.*val1.*2.*",
+				"OptIn.*Votes.*Vote.*partyA.*iss.*val.*2.*");
+	}
+
+	@Test
+	public void testSerialize() throws JsonProcessingException {
+		ObjectMapper jackson = new ObjectMapper();
+
+		String json = jackson.writeValueAsString(optIn1);
+		System.out.println(json);
+		assertEquals(asJson, json);
+	}
+
+	@Test
+	public void testDeserialize()
+			throws JsonParseException, JsonMappingException, IOException {
+		ObjectMapper jackson = new ObjectMapper();
+		Inform p = jackson.readValue(asJson, Inform.class);
+		System.out.println(p);
+		assertEquals(optIn1, p);
+	}
+
+}
Index: /events/src/test/java/geniusweb/inform/SettingsTest.java
===================================================================
--- /events/src/test/java/geniusweb/inform/SettingsTest.java	(revision 26)
+++ /events/src/test/java/geniusweb/inform/SettingsTest.java	(revision 26)
@@ -0,0 +1,128 @@
+package geniusweb.inform;
+
+import static org.junit.Assert.assertEquals;
+
+import java.io.IOException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.Arrays;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import com.fasterxml.jackson.core.JsonParseException;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.JsonMappingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+import geniusweb.actions.PartyId;
+import geniusweb.progress.ProgressRounds;
+import geniusweb.references.Parameters;
+import geniusweb.references.PartyRef;
+import geniusweb.references.ProfileRef;
+import geniusweb.references.ProtocolRef;
+import tudelft.utilities.junit.GeneralTests;
+
+public class SettingsTest extends GeneralTests<Settings> {
+
+	private PartyId id = new PartyId("party1");
+	private PartyId id2 = new PartyId("party2");
+
+	private final String asJson = "{\"Settings\":"
+			+ "{\"id\":\"party1\",\"profile\":\"ws:profile1\","
+			+ "\"protocol\":\"ws:localhost/protocol1\","
+			+ "\"progress\":{\"rounds\":{\"duration\":10,\"currentRound\":0,\"endtime\":999}},"
+			+ "\"parameters\":{}}}";
+
+	private Settings negoinfo1, negoinfo1a;
+	private Settings negoinfo2, negoinfo3, negoinfo4, negoinfo5;
+	private final Date date = new Date(999);
+	private final static ObjectMapper jackson = new ObjectMapper();
+
+	@Before
+	public void before() throws URISyntaxException, JsonParseException,
+			JsonMappingException, IOException {
+		// we can't mock because we want to test the serializer
+		ProfileRef profile1 = new ProfileRef(new URI("ws:profile1"));
+		// jackson.readValue(serialized, Profile.class);
+
+		ProtocolRef protocol1 = new ProtocolRef(
+				new URI("ws:localhost/protocol1"));
+		ProtocolRef protocol1a = new ProtocolRef(
+				new URI("ws:localhost/protocol1"));
+		ProtocolRef protocol2 = new ProtocolRef(
+				new URI("ws:localhost/protocol2"));
+		ProgressRounds progress1 = new ProgressRounds(10, 0, date);
+		ProgressRounds progress1a = new ProgressRounds(10, 0, date);
+		ProgressRounds progress2 = new ProgressRounds(12, 0, date);
+
+		Parameters settings1 = new Parameters();
+		Parameters settings2 = new Parameters();
+		settings2.put("a", 1);
+
+		negoinfo1 = new Settings(id, profile1, protocol1, progress1, settings1);
+		negoinfo1a = new Settings(id, profile1, protocol1a, progress1a,
+				settings1);
+		negoinfo2 = new Settings(id, profile1, protocol2, progress1, settings1);
+		negoinfo3 = new Settings(id, profile1, protocol1, progress2, settings1);
+		negoinfo4 = new Settings(id2, profile1, protocol1, progress2,
+				settings1);
+		negoinfo5 = new Settings(id, profile1, protocol1, progress1, settings2);
+	}
+
+	@Override
+	public List<List<Settings>> getGeneralTestData() {
+		return Arrays.asList(Arrays.asList(negoinfo1, negoinfo1a),
+				Arrays.asList(negoinfo2), Arrays.asList(negoinfo3),
+				Arrays.asList(negoinfo4), Arrays.asList(negoinfo5));
+	}
+
+	@Override
+	public List<String> getGeneralTestStrings() {
+		return Arrays.asList(
+				"Settings.*party1.*ProtocolRef.*protocol1.*ProgressRounds.*0.*10.*",
+				"Settings.*party1.*ProtocolRef.*protocol2.*ProgressRounds.*0.*10.*",
+				"Settings.*party1.*ProtocolRef.*protocol1.*ProgressRounds.*0.*12.*",
+				"Settings.*party2.*ProtocolRef.*protocol1.*ProgressRounds.*0.*12.*",
+				"Settings.*party1.*ProtocolRef.*protocol1.*ProgressRounds.*0.*10.*");
+	}
+
+	@Test
+	public void smokeTest() throws URISyntaxException {
+		new PartyRef(new URI("ws:localhost"));
+	}
+
+	@Test(expected = IllegalArgumentException.class)
+	public void nullTest() throws URISyntaxException {
+		new PartyRef((URI) null);
+	}
+
+	@Test
+	public void testSerialize() throws JsonProcessingException {
+
+		String json = jackson.writeValueAsString(negoinfo1);
+		System.out.println(json);
+		assertEquals(asJson, json);
+	}
+
+	@Test
+	public void testDeserialize()
+			throws JsonParseException, JsonMappingException, IOException {
+		Settings p = (Settings) jackson.readValue(asJson, Inform.class);
+		System.out.println(p);
+		assertEquals(negoinfo1, p);
+	}
+
+	@Test
+	public void testGeneralDict()
+			throws JsonParseException, JsonMappingException, IOException {
+		Map val = jackson.readValue("{\"a\":0.3,\"b\":{\"x\":3},\"c\":[1,2,3]}",
+				HashMap.class);
+		System.out.println(val);
+	}
+
+}
Index: /events/src/test/java/geniusweb/inform/VotingTest.java
===================================================================
--- /events/src/test/java/geniusweb/inform/VotingTest.java	(revision 26)
+++ /events/src/test/java/geniusweb/inform/VotingTest.java	(revision 26)
@@ -0,0 +1,75 @@
+package geniusweb.inform;
+
+import static org.junit.Assert.assertEquals;
+
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+import org.junit.Test;
+
+import com.fasterxml.jackson.core.JsonParseException;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.JsonMappingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+import geniusweb.actions.Offer;
+import geniusweb.actions.PartyId;
+import geniusweb.issuevalue.Bid;
+import geniusweb.issuevalue.DiscreteValue;
+import tudelft.utilities.junit.GeneralTests;
+
+public class VotingTest extends GeneralTests<Voting> {
+
+	private PartyId party1 = new PartyId("party1");
+	private Bid bid1 = new Bid("iss", new DiscreteValue("val1"));
+	private Bid bid2 = new Bid("iss", new DiscreteValue("val2"));
+
+	private Map<PartyId, Integer> powers1 = Collections.singletonMap(party1, 2);
+	private Map<PartyId, Integer> powers2 = Collections.singletonMap(party1, 3);
+
+	private final Voting voting1 = new Voting(
+			Arrays.asList(new Offer(party1, bid1)), powers1);
+	private final Voting voting1a = new Voting(
+			Arrays.asList(new Offer(party1, bid1)), powers1);
+	private final Voting voting2 = new Voting(
+			Arrays.asList(new Offer(party1, bid2)), powers1);
+	private final Voting voting3 = new Voting(
+			Arrays.asList(new Offer(party1, bid1)), powers2);
+
+	private String asJson = "{\"Voting\":{\"offers\":[{\"offer\":{\"actor\":\"party1\",\"bid\":{\"issuevalues\":{\"iss\":\"val1\"}}}}],\"powers\":{\"party1\":2}}}";
+
+	@Override
+	public List<List<Voting>> getGeneralTestData() {
+		return Arrays.asList(Arrays.asList(voting1, voting1a),
+				Arrays.asList(voting2), Arrays.asList(voting3));
+	}
+
+	@Override
+	public List<String> getGeneralTestStrings() {
+		return Arrays.asList("Voting.*Bid.*iss.*val1.*party1.*2.*",
+				"Voting.*Bid.*iss.*val2.*party1.*2.*",
+				"Voting.*Bid.*iss.*val1.*party1.*3.*");
+	}
+
+	@Test
+	public void testSerialize() throws JsonProcessingException {
+		ObjectMapper jackson = new ObjectMapper();
+
+		String json = jackson.writeValueAsString(voting1);
+		System.out.println(json);
+		assertEquals(asJson, json);
+	}
+
+	@Test
+	public void testDeserialize()
+			throws JsonParseException, JsonMappingException, IOException {
+		ObjectMapper jackson = new ObjectMapper();
+		Inform p = jackson.readValue(asJson, Inform.class);
+		System.out.println(p);
+		assertEquals(voting1, p);
+	}
+
+}
Index: /events/src/test/java/geniusweb/inform/YourTurnTest.java
===================================================================
--- /events/src/test/java/geniusweb/inform/YourTurnTest.java	(revision 26)
+++ /events/src/test/java/geniusweb/inform/YourTurnTest.java	(revision 26)
@@ -0,0 +1,70 @@
+package geniusweb.inform;
+
+import static org.junit.Assert.assertEquals;
+
+import java.io.IOException;
+import java.net.URISyntaxException;
+import java.util.Arrays;
+import java.util.List;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import com.fasterxml.jackson.core.JsonParseException;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.JsonMappingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+import tudelft.utilities.junit.GeneralTests;
+
+public class YourTurnTest extends GeneralTests<YourTurn> {
+
+	private YourTurn yourturn1, yourturn1b;
+
+	private String asJson = "{\"YourTurn\":{}}";
+
+	private YourTurn yourturnb;
+
+	@Before
+	public void before() throws URISyntaxException {
+
+		yourturn1 = new YourTurn();
+		yourturn1b = new YourTurn();
+		yourturnb = new YourTurn() {
+			@Override
+			public int hashCode() {
+				return 2;
+			}
+		};
+	}
+
+	@Override
+	public List<List<YourTurn>> getGeneralTestData() {
+		return Arrays.asList(Arrays.asList(yourturn1, yourturn1b),
+				Arrays.asList(yourturnb));
+	}
+
+	@Override
+	public List<String> getGeneralTestStrings() {
+		return Arrays.asList("YourTurn*", "YourTurn*");
+	}
+
+	@Test
+	public void testSerialize() throws JsonProcessingException {
+		ObjectMapper jackson = new ObjectMapper();
+
+		String json = jackson.writeValueAsString(yourturn1);
+		System.out.println(json);
+		assertEquals(asJson, json);
+	}
+
+	@Test
+	public void testDeserialize()
+			throws JsonParseException, JsonMappingException, IOException {
+		ObjectMapper jackson = new ObjectMapper();
+		YourTurn p = (YourTurn) jackson.readValue(asJson, Inform.class);
+		System.out.println(p);
+		assertEquals(yourturn1, p);
+	}
+
+}
Index: /exampleparties/anac2019/agentgg/pom.xml
===================================================================
--- /exampleparties/anac2019/agentgg/pom.xml	(revision 25)
+++ /exampleparties/anac2019/agentgg/pom.xml	(revision 26)
@@ -6,5 +6,5 @@
 	<groupId>geniusweb.exampleparties.anac2019</groupId>
 	<artifactId>agentgg</artifactId>
-	<version>1.5.4</version> <!-- must equal ${geniusweb.version} -->
+	<version>1.5.5</version> <!-- must equal ${geniusweb.version} -->
 	<packaging>jar</packaging>
 
@@ -17,5 +17,5 @@
 		<passwd>${env.ARTIFACTORY_PASS}</passwd>
 		<jackson-2-version>2.9.6</jackson-2-version>
-		<geniusweb.version>1.5.4</geniusweb.version>
+		<geniusweb.version>1.5.5</geniusweb.version>
 	</properties>
 
Index: /exampleparties/anac2019/winkyagent/pom.xml
===================================================================
--- /exampleparties/anac2019/winkyagent/pom.xml	(revision 25)
+++ /exampleparties/anac2019/winkyagent/pom.xml	(revision 26)
@@ -6,5 +6,5 @@
 	<groupId>geniusweb.exampleparties.anac2019</groupId>
 	<artifactId>winkyagent</artifactId>
-	<version>1.5.4</version> <!-- must equal ${geniusweb.version} -->
+	<version>1.5.5</version> <!-- must equal ${geniusweb.version} -->
 	<packaging>jar</packaging>
 
@@ -17,5 +17,5 @@
 		<passwd>${env.ARTIFACTORY_PASS}</passwd>
 		<jackson-2-version>2.9.6</jackson-2-version>
-		<geniusweb.version>1.5.4</geniusweb.version>
+		<geniusweb.version>1.5.5</geniusweb.version>
 	</properties>
 
Index: /exampleparties/boulware/pom.xml
===================================================================
--- /exampleparties/boulware/pom.xml	(revision 25)
+++ /exampleparties/boulware/pom.xml	(revision 26)
@@ -6,5 +6,5 @@
 	<groupId>geniusweb.exampleparties</groupId>
 	<artifactId>boulware</artifactId>
-	<version>1.5.4</version> <!-- must equal ${geniusweb.version} -->
+	<version>1.5.5</version> <!-- must equal ${geniusweb.version} -->
 	<packaging>jar</packaging>
 
@@ -17,5 +17,5 @@
 		<passwd>${env.ARTIFACTORY_PASS}</passwd>
 		<jackson-2-version>2.9.10</jackson-2-version>
-		<geniusweb.version>1.5.4</geniusweb.version>
+		<geniusweb.version>1.5.5</geniusweb.version>
 	</properties>
 
Index: /exampleparties/comparebids/pom.xml
===================================================================
--- /exampleparties/comparebids/pom.xml	(revision 25)
+++ /exampleparties/comparebids/pom.xml	(revision 26)
@@ -6,5 +6,5 @@
 	<groupId>geniusweb.exampleparties</groupId>
 	<artifactId>comparebids</artifactId>
-	<version>1.5.4</version> <!-- must equal ${geniusweb.version} -->
+	<version>1.5.5</version> <!-- must equal ${geniusweb.version} -->
 	<packaging>jar</packaging>
 
@@ -17,5 +17,5 @@
 		<passwd>${env.ARTIFACTORY_PASS}</passwd>
 		<jackson-2-version>2.9.6</jackson-2-version>
-		<geniusweb.version>1.5.4</geniusweb.version>
+		<geniusweb.version>1.5.5</geniusweb.version>
 	</properties>
 
Index: /exampleparties/conceder/pom.xml
===================================================================
--- /exampleparties/conceder/pom.xml	(revision 25)
+++ /exampleparties/conceder/pom.xml	(revision 26)
@@ -6,5 +6,5 @@
 	<groupId>geniusweb.exampleparties</groupId>
 	<artifactId>conceder</artifactId>
-	<version>1.5.4</version> <!-- must equal ${geniusweb.version} -->
+	<version>1.5.5</version> <!-- must equal ${geniusweb.version} -->
 	<packaging>jar</packaging>
 
@@ -17,5 +17,5 @@
 		<passwd>${env.ARTIFACTORY_PASS}</passwd>
 		<jackson-2-version>2.9.10</jackson-2-version>
-		<geniusweb.version>1.5.4</geniusweb.version>
+		<geniusweb.version>1.5.5</geniusweb.version>
 	</properties>
 
Index: /exampleparties/hardliner/pom.xml
===================================================================
--- /exampleparties/hardliner/pom.xml	(revision 25)
+++ /exampleparties/hardliner/pom.xml	(revision 26)
@@ -6,5 +6,5 @@
 	<groupId>geniusweb.exampleparties</groupId>
 	<artifactId>hardliner</artifactId>
-	<version>1.5.4</version> <!-- must equal ${geniusweb.version} -->
+	<version>1.5.5</version> <!-- must equal ${geniusweb.version} -->
 	<packaging>jar</packaging>
 
@@ -17,5 +17,5 @@
 		<passwd>${env.ARTIFACTORY_PASS}</passwd>
 		<jackson-2-version>2.9.10</jackson-2-version>
-		<geniusweb.version>1.5.4</geniusweb.version>
+		<geniusweb.version>1.5.5</geniusweb.version>
 	</properties>
 
Index: /exampleparties/humangui/pom.xml
===================================================================
--- /exampleparties/humangui/pom.xml	(revision 25)
+++ /exampleparties/humangui/pom.xml	(revision 26)
@@ -6,5 +6,5 @@
 	<groupId>geniusweb.exampleparties</groupId>
 	<artifactId>humangui</artifactId>
-	<version>1.5.4</version> <!-- must equal ${geniusweb.version} -->
+	<version>1.5.5</version> <!-- must equal ${geniusweb.version} -->
 	<packaging>jar</packaging>
 
@@ -17,5 +17,5 @@
 		<passwd>${env.ARTIFACTORY_PASS}</passwd>
 		<jackson-2-version>2.9.6</jackson-2-version>
-		<geniusweb.version>1.5.4</geniusweb.version>
+		<geniusweb.version>1.5.5</geniusweb.version>
 	</properties>
 
Index: /exampleparties/linear/pom.xml
===================================================================
--- /exampleparties/linear/pom.xml	(revision 25)
+++ /exampleparties/linear/pom.xml	(revision 26)
@@ -6,5 +6,5 @@
 	<groupId>geniusweb.exampleparties</groupId>
 	<artifactId>linear</artifactId>
-	<version>1.5.4</version> <!-- must equal ${geniusweb.version} -->
+	<version>1.5.5</version> <!-- must equal ${geniusweb.version} -->
 	<packaging>jar</packaging>
 
@@ -17,5 +17,5 @@
 		<passwd>${env.ARTIFACTORY_PASS}</passwd>
 		<jackson-2-version>2.9.10</jackson-2-version>
-		<geniusweb.version>1.5.4</geniusweb.version>
+		<geniusweb.version>1.5.5</geniusweb.version>
 	</properties>
 
Index: /exampleparties/randomparty/pom.xml
===================================================================
--- /exampleparties/randomparty/pom.xml	(revision 25)
+++ /exampleparties/randomparty/pom.xml	(revision 26)
@@ -6,5 +6,5 @@
 	<groupId>geniusweb.exampleparties</groupId>
 	<artifactId>randomparty</artifactId>
-	<version>1.5.4</version> <!-- must equal ${geniusweb.version} -->
+	<version>1.5.5</version> <!-- must equal ${geniusweb.version} -->
 	<packaging>jar</packaging>
 
@@ -17,5 +17,5 @@
 		<passwd>${env.ARTIFACTORY_PASS}</passwd>
 		<jackson-2-version>2.9.6</jackson-2-version>
-		<geniusweb.version>1.5.4</geniusweb.version>
+		<geniusweb.version>1.5.5</geniusweb.version>
 	</properties>
 
Index: /exampleparties/randomparty/src/main/java/geniusweb/exampleparties/randomparty/RandomParty.java
===================================================================
--- /exampleparties/randomparty/src/main/java/geniusweb/exampleparties/randomparty/RandomParty.java	(revision 25)
+++ /exampleparties/randomparty/src/main/java/geniusweb/exampleparties/randomparty/RandomParty.java	(revision 26)
@@ -5,6 +5,6 @@
 import java.util.Arrays;
 import java.util.HashSet;
-import java.util.List;
 import java.util.Random;
+import java.util.Set;
 import java.util.logging.Level;
 import java.util.stream.Collectors;
@@ -204,8 +204,8 @@
 				: Integer.MAX_VALUE;
 
-		List<Vote> votes = voting.getBids().stream().distinct()
-				.filter(bid -> isGood(bid))
-				.map(bid -> new Vote(me, bid, minpower, maxpower))
-				.collect(Collectors.toList());
+		Set<Vote> votes = voting.getBids().stream().distinct()
+				.filter(offer -> isGood(offer.getBid()))
+				.map(offer -> new Vote(me, offer.getBid(), minpower, maxpower))
+				.collect(Collectors.toSet());
 		return new Votes(me, votes);
 	}
Index: /exampleparties/randomparty/src/test/java/geniusweb/exampleparties/randomparty/RandomPartyTest.java
===================================================================
--- /exampleparties/randomparty/src/test/java/geniusweb/exampleparties/randomparty/RandomPartyTest.java	(revision 25)
+++ /exampleparties/randomparty/src/test/java/geniusweb/exampleparties/randomparty/RandomPartyTest.java	(revision 26)
@@ -224,5 +224,6 @@
 
 		Bid bid = findGoodBid();
-		party.notifyChange(new Voting(Arrays.asList(bid),
+		Offer offer = new Offer(PARTY1, bid);
+		party.notifyChange(new Voting(Arrays.asList(offer),
 				Collections.singletonMap(PARTY1, 1)));
 		assertEquals(1, connection.getActions().size());
@@ -230,5 +231,6 @@
 		assertTrue(action instanceof Votes);
 		assertEquals(1, ((Votes) action).getVotes().size());
-		assertEquals(bid, ((Votes) action).getVotes().get(0).getBid());
+		assertEquals(bid,
+				((Votes) action).getVotes().iterator().next().getBid());
 	}
 
Index: /exampleparties/randompartypy/pom.xml
===================================================================
--- /exampleparties/randompartypy/pom.xml	(revision 25)
+++ /exampleparties/randompartypy/pom.xml	(revision 26)
@@ -6,5 +6,5 @@
 	<groupId>geniusweb.exampleparties</groupId>
 	<artifactId>randompyparty</artifactId>
-	<version>1.5.4</version> <!-- must equal ${geniusweb.version} -->
+	<version>1.5.5</version> <!-- must equal ${geniusweb.version} -->
 	<packaging>jar</packaging>
 
@@ -17,5 +17,5 @@
 		<passwd>${env.ARTIFACTORY_PASS}</passwd>
 		<jackson-2-version>2.9.10</jackson-2-version>
-		<geniusweb.version>1.5.4</geniusweb.version>
+		<geniusweb.version>1.5.5</geniusweb.version>
 	</properties>
 
Index: /exampleparties/simpleboa/pom.xml
===================================================================
--- /exampleparties/simpleboa/pom.xml	(revision 25)
+++ /exampleparties/simpleboa/pom.xml	(revision 26)
@@ -6,5 +6,5 @@
 	<groupId>geniusweb.exampleparties</groupId>
 	<artifactId>simpleboaparty</artifactId>
-	<version>1.5.4</version> <!-- must equal ${geniusweb.version} -->
+	<version>1.5.5</version> <!-- must equal ${geniusweb.version} -->
 	<packaging>jar</packaging>
 
@@ -17,5 +17,5 @@
 		<passwd>${env.ARTIFACTORY_PASS}</passwd>
 		<jackson-2-version>2.9.6</jackson-2-version>
-		<geniusweb.version>1.5.4</geniusweb.version>
+		<geniusweb.version>1.5.5</geniusweb.version>
 	</properties>
 
Index: /exampleparties/simpleshaop/pom.xml
===================================================================
--- /exampleparties/simpleshaop/pom.xml	(revision 25)
+++ /exampleparties/simpleshaop/pom.xml	(revision 26)
@@ -6,5 +6,5 @@
 	<groupId>geniusweb.exampleparties</groupId>
 	<artifactId>simpleshaop</artifactId>
-	<version>1.5.4</version> <!-- must equal ${geniusweb.version} -->
+	<version>1.5.5</version> <!-- must equal ${geniusweb.version} -->
 	<packaging>jar</packaging>
 
@@ -17,5 +17,5 @@
 		<passwd>${env.ARTIFACTORY_PASS}</passwd>
 		<jackson-2-version>2.9.6</jackson-2-version>
-		<geniusweb.version>1.5.4</geniusweb.version>
+		<geniusweb.version>1.5.5</geniusweb.version>
 	</properties>
 
Index: /exampleparties/timedependentparty/pom.xml
===================================================================
--- /exampleparties/timedependentparty/pom.xml	(revision 25)
+++ /exampleparties/timedependentparty/pom.xml	(revision 26)
@@ -6,5 +6,5 @@
 	<groupId>geniusweb.exampleparties</groupId>
 	<artifactId>timedependentparty</artifactId>
-	<version>1.5.4</version> <!-- must equal ${geniusweb.version} -->
+	<version>1.5.5</version> <!-- must equal ${geniusweb.version} -->
 	<packaging>jar</packaging>
 
@@ -17,5 +17,5 @@
 		<passwd>${env.ARTIFACTORY_PASS}</passwd>
 		<jackson-2-version>2.9.10</jackson-2-version>
-		<geniusweb.version>1.5.4</geniusweb.version>
+		<geniusweb.version>1.5.5</geniusweb.version>
 	</properties>
 
Index: /exampleparties/timedependentparty/src/main/java/geniusweb/exampleparties/timedependentparty/TimeDependentParty.java
===================================================================
--- /exampleparties/timedependentparty/src/main/java/geniusweb/exampleparties/timedependentparty/TimeDependentParty.java	(revision 25)
+++ /exampleparties/timedependentparty/src/main/java/geniusweb/exampleparties/timedependentparty/TimeDependentParty.java	(revision 26)
@@ -7,6 +7,6 @@
 import java.util.Arrays;
 import java.util.HashSet;
-import java.util.List;
 import java.util.Random;
+import java.util.Set;
 import java.util.logging.Level;
 import java.util.stream.Collectors;
@@ -277,8 +277,8 @@
 				: Integer.MAX_VALUE;
 
-		List<Vote> votes = voting.getBids().stream().distinct()
-				.filter(bid -> isGood(bid))
-				.map(bid -> new Vote(me, bid, minpower, maxpower))
-				.collect(Collectors.toList());
+		Set<Vote> votes = voting.getBids().stream().distinct()
+				.filter(offer -> isGood(offer.getBid()))
+				.map(offer -> new Vote(me, offer.getBid(), minpower, maxpower))
+				.collect(Collectors.toSet());
 		return new Votes(me, votes);
 	}
Index: /exampleparties/timedependentparty/src/test/java/geniusweb/exampleparties/timedependentparty/TimeDependentPartyMOPACTest.java
===================================================================
--- /exampleparties/timedependentparty/src/test/java/geniusweb/exampleparties/timedependentparty/TimeDependentPartyMOPACTest.java	(revision 25)
+++ /exampleparties/timedependentparty/src/test/java/geniusweb/exampleparties/timedependentparty/TimeDependentPartyMOPACTest.java	(revision 26)
@@ -13,4 +13,5 @@
 import java.nio.file.Paths;
 import java.util.Arrays;
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.Map;
@@ -135,5 +136,6 @@
 		// this is better than party's firstBid
 
-		party.notifyChange(new Voting(Arrays.asList(bestBid), powers));
+		party.notifyChange(new Voting(
+				Arrays.asList(new Offer(otherparty, bestBid)), powers));
 		assertEquals(2, connection.getActions().size());
 
@@ -142,5 +144,5 @@
 		assertEquals(
 				new Votes(me,
-						Arrays.asList(
+						Collections.singleton(
 								new Vote(me, bestBid, 1, Integer.MAX_VALUE))),
 				lastAction);
@@ -159,5 +161,6 @@
 		// this is better than party's firstBid
 
-		party.notifyChange(new Voting(Arrays.asList(bestBid, bestBid), powers));
+		party.notifyChange(new Voting(Arrays.asList(new Offer(me, bestBid),
+				new Offer(otherparty, bestBid)), powers));
 		assertEquals(2, connection.getActions().size());
 
Index: /issuevalue/pom.xml
===================================================================
--- /issuevalue/pom.xml	(revision 25)
+++ /issuevalue/pom.xml	(revision 26)
@@ -6,5 +6,5 @@
 	<groupId>geniusweb</groupId>
 	<artifactId>issuevalue</artifactId>
-	<version>1.5.4</version> <!-- must equal ${geniusweb.version} -->
+	<version>1.5.5</version> <!-- must equal ${geniusweb.version} -->
 	<packaging>jar</packaging>
 
@@ -17,5 +17,5 @@
 		<passwd>${env.ARTIFACTORY_PASS}</passwd>
 		<jackson-2-version>2.9.10</jackson-2-version>
-		<geniusweb.version>1.5.4</geniusweb.version>
+		<geniusweb.version>1.5.5</geniusweb.version>
 	</properties>
 
Index: /opponentmodel/pom.xml
===================================================================
--- /opponentmodel/pom.xml	(revision 25)
+++ /opponentmodel/pom.xml	(revision 26)
@@ -6,5 +6,5 @@
 	<groupId>geniusweb</groupId>
 	<artifactId>opponentmodel</artifactId>
-	<version>1.5.4</version> <!-- must equal ${geniusweb.version} -->
+	<version>1.5.5</version> <!-- must equal ${geniusweb.version} -->
 	<packaging>jar</packaging>
 
@@ -17,5 +17,5 @@
 		<passwd>${env.ARTIFACTORY_PASS}</passwd>
 		<jackson-2-version>2.9.10</jackson-2-version>
-		<geniusweb.version>1.5.4</geniusweb.version>
+		<geniusweb.version>1.5.5</geniusweb.version>
 	</properties>
 
Index: /party/pom.xml
===================================================================
--- /party/pom.xml	(revision 25)
+++ /party/pom.xml	(revision 26)
@@ -6,5 +6,5 @@
 	<groupId>geniusweb</groupId>
 	<artifactId>party</artifactId>
-	<version>1.5.4</version> <!-- must equal ${geniusweb.version} -->
+	<version>1.5.5</version> <!-- must equal ${geniusweb.version} -->
 	<packaging>jar</packaging>
 
@@ -17,5 +17,5 @@
 		<passwd>${env.ARTIFACTORY_PASS}</passwd>
 		<jackson-2-version>2.9.10</jackson-2-version>
-		<geniusweb.version>1.5.4</geniusweb.version>
+		<geniusweb.version>1.5.5</geniusweb.version>
 	</properties>
 
Index: /party/src/test/java/geniusweb/party/CapabilitiesTest.java
===================================================================
--- /party/src/test/java/geniusweb/party/CapabilitiesTest.java	(revision 25)
+++ /party/src/test/java/geniusweb/party/CapabilitiesTest.java	(revision 26)
@@ -69,3 +69,8 @@
 	}
 
+	@Test
+	public void behaviours() {
+		assertEquals(Sets.newSet("SEB", "SAOP"), capabilities3.getBehaviours());
+	}
+
 }
Index: /party/src/test/java/geniusweb/party/DefaultPartyTest.java
===================================================================
--- /party/src/test/java/geniusweb/party/DefaultPartyTest.java	(revision 26)
+++ /party/src/test/java/geniusweb/party/DefaultPartyTest.java	(revision 26)
@@ -0,0 +1,103 @@
+package geniusweb.party;
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import geniusweb.actions.Action;
+import geniusweb.connection.ConnectionEnd;
+import geniusweb.inform.Inform;
+import tudelft.utilities.listener.Listener;
+
+public class DefaultPartyTest {
+
+	private DefaultParty party;
+
+	@Before
+	public void before() {
+		party = new DefaultParty() {
+
+			@Override
+			public void notifyChange(Inform data) {
+				// TODO Auto-generated method stub
+
+			}
+
+			@Override
+			public String getDescription() {
+				// TODO Auto-generated method stub
+				return null;
+			}
+
+			@Override
+			public Capabilities getCapabilities() {
+				// TODO Auto-generated method stub
+				return null;
+			}
+		};
+
+	}
+
+	@Test
+	public void smoke() {
+	}
+
+	@Test
+	public void getReporter() {
+		assertNotNull(party.getReporter());
+	}
+
+	@SuppressWarnings("unchecked")
+	@Test
+	public void connect() {
+
+		ConnectionEnd<Inform, Action> connection = mock(ConnectionEnd.class);
+		party.connect(connection);
+
+		verify(connection, times(1)).addListener(any(Listener.class));
+		assertNotNull(party.getConnection());
+	}
+
+	@SuppressWarnings("unchecked")
+	@Test
+	public void disconnect() {
+
+		ConnectionEnd<Inform, Action> connection = mock(ConnectionEnd.class);
+		party.connect(connection);
+
+		party.disconnect();
+		verify(connection, times(1)).removeListener(any(Listener.class));
+		assertNull(party.getConnection());
+
+		// check second disconnect is ignored
+		party.disconnect();
+		verify(connection, times(1)).removeListener(any(Listener.class));
+		assertNull(party.getConnection());
+
+	}
+
+	@SuppressWarnings("unchecked")
+	@Test
+	public void terminate() {
+
+		ConnectionEnd<Inform, Action> connection = mock(ConnectionEnd.class);
+		party.connect(connection);
+
+		party.terminate();
+		verify(connection, times(1)).removeListener(any(Listener.class));
+		assertNull(party.getConnection());
+
+		// check second terminate is ignored
+		party.terminate();
+		verify(connection, times(1)).removeListener(any(Listener.class));
+		assertNull(party.getConnection());
+
+	}
+
+}
Index: ofile/.classpath
===================================================================
--- /profile/.classpath	(revision 25)
+++ 	(revision )
@@ -1,27 +1,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<classpath>
-	<classpathentry kind="src" output="target/classes" path="src/main/java">
-		<attributes>
-			<attribute name="optional" value="true"/>
-			<attribute name="maven.pomderived" value="true"/>
-		</attributes>
-	</classpathentry>
-	<classpathentry kind="src" output="target/test-classes" path="src/test/java">
-		<attributes>
-			<attribute name="optional" value="true"/>
-			<attribute name="maven.pomderived" value="true"/>
-			<attribute name="test" value="true"/>
-		</attributes>
-	</classpathentry>
-	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8">
-		<attributes>
-			<attribute name="maven.pomderived" value="true"/>
-		</attributes>
-	</classpathentry>
-	<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
-		<attributes>
-			<attribute name="maven.pomderived" value="true"/>
-		</attributes>
-	</classpathentry>
-	<classpathentry kind="output" path="target/classes"/>
-</classpath>
Index: ofile/.project
===================================================================
--- /profile/.project	(revision 25)
+++ 	(revision )
@@ -1,23 +1,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<projectDescription>
-	<name>profile</name>
-	<comment></comment>
-	<projects>
-	</projects>
-	<buildSpec>
-		<buildCommand>
-			<name>org.eclipse.jdt.core.javabuilder</name>
-			<arguments>
-			</arguments>
-		</buildCommand>
-		<buildCommand>
-			<name>org.eclipse.m2e.core.maven2Builder</name>
-			<arguments>
-			</arguments>
-		</buildCommand>
-	</buildSpec>
-	<natures>
-		<nature>org.eclipse.jdt.core.javanature</nature>
-		<nature>org.eclipse.m2e.core.maven2Nature</nature>
-	</natures>
-</projectDescription>
Index: /profile/pom.xml
===================================================================
--- /profile/pom.xml	(revision 25)
+++ /profile/pom.xml	(revision 26)
@@ -6,5 +6,5 @@
 	<groupId>geniusweb</groupId>
 	<artifactId>profile</artifactId>
-	<version>1.5.4</version> <!-- must equal ${geniusweb.version} -->
+	<version>1.5.5</version> <!-- must equal ${geniusweb.version} -->
 	<packaging>jar</packaging>
 
@@ -17,5 +17,5 @@
 		<passwd>${env.ARTIFACTORY_PASS}</passwd>
 		<jackson-2-version>2.9.10</jackson-2-version>
-		<geniusweb.version>1.5.4</geniusweb.version>
+		<geniusweb.version>1.5.5</geniusweb.version>
 	</properties>
 
Index: /profileconnection/pom.xml
===================================================================
--- /profileconnection/pom.xml	(revision 25)
+++ /profileconnection/pom.xml	(revision 26)
@@ -6,5 +6,5 @@
 	<groupId>geniusweb</groupId>
 	<artifactId>profileconnection</artifactId>
-	<version>1.5.4</version> <!-- must equal ${geniusweb.version} -->
+	<version>1.5.5</version> <!-- must equal ${geniusweb.version} -->
 	<packaging>jar</packaging>
 
@@ -17,5 +17,5 @@
 		<passwd>${env.ARTIFACTORY_PASS}</passwd>
 		<jackson-2-version>2.9.10</jackson-2-version>
-		<geniusweb.version>1.5.4</geniusweb.version>
+		<geniusweb.version>1.5.5</geniusweb.version>
 	</properties>
 
Index: /protocol/pom.xml
===================================================================
--- /protocol/pom.xml	(revision 25)
+++ /protocol/pom.xml	(revision 26)
@@ -6,5 +6,5 @@
 	<groupId>geniusweb</groupId>
 	<artifactId>protocol</artifactId>
-	<version>1.5.4</version> <!-- must equal ${geniusweb.version} -->
+	<version>1.5.5</version> <!-- must equal ${geniusweb.version} -->
 	<packaging>jar</packaging>
 
@@ -17,5 +17,5 @@
 		<passwd>${env.ARTIFACTORY_PASS}</passwd>
 		<jackson-2-version>2.9.10</jackson-2-version>
-		<geniusweb.version>1.5.4</geniusweb.version>
+		<geniusweb.version>1.5.5</geniusweb.version>
 	</properties>
 
Index: otocol/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: otocol/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: otocol/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: otocol/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: otocol/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: otocol/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;
Index: otocol/src/test/java/geniusweb/protocol/WillBeCalledTest.java
===================================================================
--- /protocol/src/test/java/geniusweb/protocol/WillBeCalledTest.java	(revision 25)
+++ 	(revision )
@@ -1,37 +1,0 @@
-package geniusweb.protocol;
-
-import static org.junit.Assert.assertEquals;
-
-import org.junit.Test;
-
-public class WillBeCalledTest {
-	int counter;
-
-	@Test
-	public void testDeadline() throws InterruptedException {
-		counter = 0;
-		new WillBeCalled(() -> {
-			counter++;
-		}, 100l);
-		assertEquals(0, counter);
-		Thread.sleep(200);
-		assertEquals(1, counter);
-		Thread.sleep(200);
-		assertEquals(1, counter);
-
-	}
-
-	@Test
-	public void testManual() throws InterruptedException {
-		counter = 0;
-		WillBeCalled w = new WillBeCalled(() -> {
-			counter++;
-		}, 100l);
-		assertEquals(0, counter);
-		w.complete();
-		assertEquals(1, counter);
-		Thread.sleep(200);
-		assertEquals(1, counter);
-
-	}
-}
Index: /protocol/src/test/java/geniusweb/protocol/session/SessionResultTest.java
===================================================================
--- /protocol/src/test/java/geniusweb/protocol/session/SessionResultTest.java	(revision 25)
+++ /protocol/src/test/java/geniusweb/protocol/session/SessionResultTest.java	(revision 26)
@@ -67,6 +67,6 @@
 		issuevalues1.put(ISSUE1, new DiscreteValue("a"));
 		Bid bid1 = new Bid(issuevalues1);
-		Agreements agreement1 = new Agreements().with(bid1,
-				new HashSet<>(Arrays.asList(PARTY1, PARTY2)));
+		Agreements agreement1 = new Agreements().with(new Agreements(bid1,
+				new HashSet<>(Arrays.asList(PARTY1, PARTY2))));
 
 		// different order but that shouldn't matter
@@ -74,6 +74,6 @@
 		issuevalues2.put(ISSUE1, new DiscreteValue("b"));
 		Bid bid2 = new Bid(issuevalues2);
-		Agreements agreement2 = new Agreements().with(bid2,
-				new HashSet<>(Arrays.asList(PARTY1, PARTY3)));
+		Agreements agreement2 = new Agreements().with(new Agreements(bid2,
+				new HashSet<>(Arrays.asList(PARTY1, PARTY3))));
 
 		Map<PartyId, PartyWithProfile> partiesmap = new HashMap<>();
Index: /protocol/src/test/java/geniusweb/protocol/session/amop/AMOPStateTest.java
===================================================================
--- /protocol/src/test/java/geniusweb/protocol/session/amop/AMOPStateTest.java	(revision 25)
+++ /protocol/src/test/java/geniusweb/protocol/session/amop/AMOPStateTest.java	(revision 26)
@@ -275,6 +275,6 @@
 	@Test
 	public void activePartiesAgreedTest() {
-		Agreements agreements = new Agreements().with(bid1,
-				new HashSet<>(Arrays.asList(party1, party2)));
+		Agreements agreements = new Agreements().with(new Agreements(bid1,
+				new HashSet<>(Arrays.asList(party1, party2))));
 		AMOPState state = new AMOPState(Phase.INIT, actions, connections3,
 				progressrounds, settings, partyprofiles1, agreements,
@@ -376,12 +376,12 @@
 	@Test
 	public void testCollectVotes() {
-		Votes vote1AB = new Votes(party1, Arrays
-				.asList(new Vote(party1, a, 2, 9), new Vote(party1, b, 2, 9)));
-		Votes vote2AB = new Votes(party2, Arrays
-				.asList(new Vote(party2, a, 2, 9), new Vote(party2, b, 2, 9)));
+		Votes vote1AB = new Votes(party1, new HashSet<>(Arrays
+				.asList(new Vote(party1, a, 2, 9), new Vote(party1, b, 2, 9))));
+		Votes vote2AB = new Votes(party2, new HashSet<>(Arrays
+				.asList(new Vote(party2, a, 2, 9), new Vote(party2, b, 2, 9))));
 		Votes vote3C = new Votes(party3,
-				Arrays.asList(new Vote(party3, c, 2, 9)));
-		Votes vote4AC = new Votes(party4, Arrays
-				.asList(new Vote(party4, a, 2, 9), new Vote(party4, c, 2, 9)));
+				Collections.singleton(new Vote(party3, c, 2, 9)));
+		Votes vote4AC = new Votes(party4, new HashSet<>(Arrays
+				.asList(new Vote(party4, a, 2, 9), new Vote(party4, c, 2, 9))));
 		// party 1,2,4 vote for A, party 1,2 vote for B, party 3,4 vote for C.
 		// the biggest vote is P,Q,S
@@ -409,12 +409,12 @@
 	public void testNextPhase() {
 		// copy of above. todo cleanup
-		Votes vote1AB = new Votes(party1, Arrays
-				.asList(new Vote(party1, a, 2, 9), new Vote(party1, b, 2, 9)));
-		Votes vote2AB = new Votes(party2, Arrays
-				.asList(new Vote(party2, a, 2, 9), new Vote(party2, b, 2, 9)));
+		Votes vote1AB = new Votes(party1, new HashSet<>(Arrays
+				.asList(new Vote(party1, a, 2, 9), new Vote(party1, b, 2, 9))));
+		Votes vote2AB = new Votes(party2, new HashSet<>(Arrays
+				.asList(new Vote(party2, a, 2, 9), new Vote(party2, b, 2, 9))));
 		Votes vote3C = new Votes(party3,
-				Arrays.asList(new Vote(party3, c, 2, 9)));
-		Votes vote4AC = new Votes(party4, Arrays
-				.asList(new Vote(party4, a, 2, 9), new Vote(party4, c, 2, 9)));
+				Collections.singleton(new Vote(party3, c, 2, 9)));
+		Votes vote4AC = new Votes(party4, new HashSet<>(Arrays
+				.asList(new Vote(party4, a, 2, 9), new Vote(party4, c, 2, 9))));
 		// party 1,2,4 vote for A, party 1,2 vote for B, party 3,4 vote for C.
 		// the biggest vote is P,Q,S
Index: /protocol/src/test/java/geniusweb/protocol/session/mopac/phase/OfferPhaseTest.java
===================================================================
--- /protocol/src/test/java/geniusweb/protocol/session/mopac/phase/OfferPhaseTest.java	(revision 25)
+++ /protocol/src/test/java/geniusweb/protocol/session/mopac/phase/OfferPhaseTest.java	(revision 26)
@@ -135,6 +135,5 @@
 	@Test(expected = ProtocolException.class)
 	public void checkNotAllowedActionTest() throws ProtocolException {
-		phase.checkAction(party1, new Votes(party2, Collections.emptyList()),
-				1);
+		phase.checkAction(party1, new Votes(party2, Collections.emptySet()), 1);
 	}
 
@@ -241,6 +240,7 @@
 	public void getOffersTest() {
 		assertEquals(Collections.emptyList(), phase.getOffers());
-		List<Bid> offs = phase.with(party1, offer, 1).getOffers();
-		assertEquals(Arrays.asList(bid), offs);
+		List<Offer> offs = phase.with(party1, offer, 1).getOffers();
+		assertEquals(1, offs.size());
+		assertEquals(bid, offs.get(0).getBid());
 	}
 
Index: /protocol/src/test/java/geniusweb/protocol/session/mopac/phase/OptInPhaseTest.java
===================================================================
--- /protocol/src/test/java/geniusweb/protocol/session/mopac/phase/OptInPhaseTest.java	(revision 25)
+++ /protocol/src/test/java/geniusweb/protocol/session/mopac/phase/OptInPhaseTest.java	(revision 26)
@@ -50,5 +50,5 @@
 	private final Bid bid = new Bid("issue", new DiscreteValue("yes"));
 	private final Vote vote = new Vote(party1, bid, 2, 3);
-	private final Votes votes = new Votes(party1, Arrays.asList(vote));
+	private final Votes votes = new Votes(party1, Collections.singleton(vote));
 
 	private final List<Votes> prevVotes = Arrays.asList(votes);
@@ -135,6 +135,5 @@
 	@Test(expected = ProtocolException.class)
 	public void checkNotAllowedActionTest() throws ProtocolException {
-		phase.checkAction(party1, new Votes(party2, Collections.emptyList()),
-				1);
+		phase.checkAction(party1, new Votes(party2, Collections.emptySet()), 1);
 	}
 
@@ -175,5 +174,5 @@
 		// so this is an illegal narrowing of the previous vote
 		Vote newVote = new Vote(party1, bid, 2, 2);
-		Votes newVotes = new Votes(party1, Arrays.asList(newVote));
+		Votes newVotes = new Votes(party1, Collections.singleton(newVote));
 
 		// when(prevPhase.getVotes()).thenReturn(Arrays.asList(votes));
Index: /protocol/src/test/java/geniusweb/protocol/session/mopac/phase/VotingPhaseTest.java
===================================================================
--- /protocol/src/test/java/geniusweb/protocol/session/mopac/phase/VotingPhaseTest.java	(revision 25)
+++ /protocol/src/test/java/geniusweb/protocol/session/mopac/phase/VotingPhaseTest.java	(revision 26)
@@ -16,4 +16,5 @@
 
 import geniusweb.actions.EndNegotiation;
+import geniusweb.actions.Offer;
 import geniusweb.actions.PartyId;
 import geniusweb.actions.Vote;
@@ -50,7 +51,7 @@
 	private final Bid bid = new Bid("issue", new DiscreteValue("yes"));
 	private final Vote vote = new Vote(party1, bid, 2, 3);
-	private final Votes votes = new Votes(party1, Arrays.asList(vote));
+	private final Votes votes = new Votes(party1, Collections.singleton(vote));
 
-	private final List<Bid> prevPhase = Arrays.asList(bid);
+	private final List<Offer> prevPhase = Arrays.asList(new Offer(party1, bid));
 
 	public VotingPhaseTest() {
@@ -101,5 +102,6 @@
 	public void testInform() {
 		// when(prevPhase.getOffers()).thenReturn(Arrays.asList(bid));
-		assertEquals(new Voting(Arrays.asList(bid), powers), phase.getInform());
+		assertEquals(new Voting(Arrays.asList(new Offer(party1, bid)), powers),
+				phase.getInform());
 
 	}
@@ -135,6 +137,5 @@
 	@Test(expected = ProtocolException.class)
 	public void checkNotAllowedActionTest() throws ProtocolException {
-		phase.checkAction(party1, new Votes(party2, Collections.emptyList()),
-				1);
+		phase.checkAction(party1, new Votes(party2, Collections.emptySet()), 1);
 	}
 
Index: otocol/src/test/java/geniusweb/protocol/tournament/AllPermutationsProtocolTest.java
===================================================================
--- /protocol/src/test/java/geniusweb/protocol/tournament/AllPermutationsProtocolTest.java	(revision 25)
+++ 	(revision )
@@ -1,181 +1,0 @@
-package geniusweb.protocol.tournament;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.anyLong;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import java.math.BigInteger;
-import java.util.LinkedList;
-import java.util.List;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.mockito.ArgumentCaptor;
-
-import geniusweb.events.ProtocolEvent;
-import geniusweb.issuevalue.Bid;
-import geniusweb.protocol.CurrentNegoState;
-import geniusweb.protocol.NegoState;
-import geniusweb.protocol.SessionResult;
-import geniusweb.protocol.partyconnection.ProtocolToPartyConnFactory;
-import geniusweb.protocol.session.SessionProtocol;
-import geniusweb.protocol.session.SessionSettings;
-import geniusweb.protocol.session.SessionState;
-import geniusweb.protocol.tournament.allpermutations.AllPermutationsProtocol;
-import geniusweb.protocol.tournament.allpermutations.AllPermutationsState;
-import geniusweb.references.PartyWithProfile;
-import geniusweb.references.ProtocolRef;
-import tudelft.utilities.listener.Listener;
-import tudelft.utilities.logging.ReportToLogger;
-
-public class AllPermutationsProtocolTest {
-
-	private final AllPermutationsState state = mock(AllPermutationsState.class),
-			newstate = mock(AllPermutationsState.class);
-	private final ReportToLogger log = new ReportToLogger("test");
-	private final AllPermutationsProtocol app = new AllPermutationsProtocol(
-			state, log);
-	private final ProtocolToPartyConnFactory factory = mock(
-			ProtocolToPartyConnFactory.class);
-	private final SessionSettings settings = mock(SessionSettings.class);
-	private final SessionState finalsessionstate = mock(SessionState.class);
-	private Bid agreement = mock(Bid.class);
-	private final long NOW = 1000;
-
-	@Before
-	public void before() {
-		when(state.getSize()).thenReturn(BigInteger.ZERO);
-		when(finalsessionstate.isFinal(anyLong())).thenReturn(true);
-		when(finalsessionstate.getSettings()).thenReturn(settings);
-		when(finalsessionstate.getAgreement()).thenReturn(agreement);
-		when(state.with(any())).thenReturn(newstate);
-	}
-
-	@Test
-	public void smokeTest() {
-	}
-
-	@Test
-	public void startTestNoSessions() {
-		AllPermutationsProtocol app = new AllPermutationsProtocol(state, log);
-		app.start(factory);
-
-	}
-
-	@Test
-	public void getDescrTest() {
-		assertNotNull(app.getDescription());
-	}
-
-	@Test
-	public void getStateTest() {
-		assertEquals(state, app.getState());
-	}
-
-	@Test
-	public void getRefTest() {
-		assertEquals("APP", app.getRef().getURI().toString());
-	}
-
-	@Test
-	public void runOneSessionTest() throws InterruptedException {
-		MockSessionProtocol sessionprotocol = startSession();
-		sessionprotocol.getListener();
-	}
-
-	@Test
-	public void runOneSessionAndUnhandledEvent() throws InterruptedException {
-		MockSessionProtocol sessionprotocol = startSession();
-		sessionprotocol.getListener().notifyChange(mock(ProtocolEvent.class));
-		verify(state, times(0)).with(any());
-	}
-
-	/**
-	 * Check that a started session correctly handles a session event.
-	 */
-	@Test
-	public void CurrentNegoStateEventTest() throws InterruptedException {
-		MockSessionProtocol sessionprotocol = startSession();
-
-		CurrentNegoState evt = mock(CurrentNegoState.class);
-		when(evt.getState()).thenReturn(finalsessionstate);
-		sessionprotocol.getListener().notifyChange(evt);
-
-		ArgumentCaptor<SessionResult> argument = ArgumentCaptor
-				.forClass(SessionResult.class);
-		verify(state, times(1)).with(argument.capture());
-		assertEquals(agreement, argument.getValue().getAgreement());
-		assertNull(argument.getValue().getError());
-	}
-
-	private MockSessionProtocol startSession() throws InterruptedException {
-		SessionSettings setting = mock(SessionSettings.class);
-		MockSessionProtocol sessionprotocol = new MockSessionProtocol();
-		when(setting.getProtocol(log)).thenReturn(sessionprotocol);
-		when(state.getNextSettings()).thenReturn(setting);
-
-		app.start(factory);
-		Thread.sleep(500); // allow app to start session
-		// this call should return fine, and have listener registered to our
-		// protocol. app now waits for a notification
-		return sessionprotocol;
-	}
-
-}
-
-/**
- * 
- * The protocol needs to record the listners, we need a listener to trigger
- * further protocol actions. Mockito can't handle this, we mneed our own mock...
- *
- */
-class MockSessionProtocol implements SessionProtocol {
-	private final List<Listener<ProtocolEvent>> listeners = new LinkedList<>();
-
-	@Override
-	public void start(ProtocolToPartyConnFactory connectionfactory) {
-
-	}
-
-	@Override
-	public String getDescription() {
-		return null;
-	}
-
-	@Override
-	public NegoState getState() {
-		return null;
-	}
-
-	@Override
-	public ProtocolRef getRef() {
-		return null;
-	}
-
-	@Override
-	public void addParticipant(PartyWithProfile party) {
-	}
-
-	@Override
-	public void addListener(Listener<ProtocolEvent> l) {
-		listeners.add(l);
-	}
-
-	@Override
-	public void removeListener(Listener<ProtocolEvent> l) {
-	}
-
-	public Listener<ProtocolEvent> getListener() {
-		if (listeners.size() != 1) {
-			throw new IllegalStateException("Not having exactly 1 listener");
-		}
-		return listeners.get(0);
-	}
-
-}
Index: otocol/src/test/java/geniusweb/protocol/tournament/AllPermutationsSettingsTest.java
===================================================================
--- /protocol/src/test/java/geniusweb/protocol/tournament/AllPermutationsSettingsTest.java	(revision 25)
+++ 	(revision )
@@ -1,180 +1,0 @@
-package geniusweb.protocol.tournament;
-
-import static org.junit.Assert.assertEquals;
-
-import java.io.IOException;
-import java.math.BigInteger;
-import java.net.URISyntaxException;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
-
-import org.junit.Before;
-import org.junit.Test;
-
-import com.fasterxml.jackson.core.JsonProcessingException;
-import com.fasterxml.jackson.databind.ObjectMapper;
-
-import geniusweb.deadline.DeadlineTime;
-import geniusweb.protocol.session.saop.SAOPSettings;
-import geniusweb.protocol.tournament.allpermutations.AllPermutationsSettings;
-import geniusweb.references.Parameters;
-import geniusweb.references.PartyRef;
-import geniusweb.references.PartyWithParameters;
-import geniusweb.references.ProfileRef;
-import tudelft.utilities.junit.GeneralTests;
-import tudelft.utilities.logging.ReportToLogger;
-
-public class AllPermutationsSettingsTest
-		extends GeneralTests<AllPermutationsSettings> {
-
-	private final ObjectMapper jackson = new ObjectMapper();
-
-	private final String serialized = "{\"AllPermutationsSettings\":{\"parties\":[{\"partyref\":\"party1\",\"parameters\":{}},{\"partyref\":\"party2\",\"parameters\":{}}],\"reuseParties\":false,\"profiles\":[\"profile1\",\"profile2\",\"profile3\"],\"partiesPerSession\":2,\"sessionsettings\":{\"SAOPSettings\":{\"participants\":[],\"deadline\":{\"deadlinetime\":{\"durationms\":10000}}}}}}";
-	private AllPermutationsSettings settings, settings1a, settings2, settings3,
-			settings4;
-
-	private SAOPSettings saopsettings;
-
-	private ProfileRef profile1, profile2, profile3;
-
-	private List<PartyWithParameters> parties;
-
-	@Before
-	public void before() throws URISyntaxException {
-		PartyRef partyref1 = new PartyRef("party1");
-		PartyRef partyref2 = new PartyRef("party2");
-		PartyRef partyref3 = new PartyRef("party3");
-
-		Parameters params1 = new Parameters();
-		Parameters params2 = new Parameters();
-		Parameters params3 = new Parameters();
-
-		PartyWithParameters partywithparams1 = new PartyWithParameters(
-				partyref1, params1);
-		PartyWithParameters partywithparams2 = new PartyWithParameters(
-				partyref2, params2);
-		PartyWithParameters partywithparams3 = new PartyWithParameters(
-				partyref3, params3);
-
-		parties = Arrays.asList(partywithparams1, partywithparams2);
-		DeadlineTime deadline = new DeadlineTime(10000);
-
-		saopsettings = new SAOPSettings(Collections.emptyList(), deadline);
-
-		profile1 = new ProfileRef("profile1");
-		profile2 = new ProfileRef("profile2");
-		profile3 = new ProfileRef("profile3");
-
-		List<ProfileRef> profiles = Arrays.asList(profile1, profile2, profile3);
-
-		settings = new AllPermutationsSettings(parties, false, profiles, 2,
-				saopsettings);
-
-		settings1a = new AllPermutationsSettings(parties, false, profiles, 2,
-				saopsettings);
-
-		settings2 = new AllPermutationsSettings(Arrays.asList(partywithparams1,
-				partywithparams2, partywithparams3), false, profiles, 2,
-				saopsettings);
-
-		settings3 = new AllPermutationsSettings(parties, true, profiles, 2,
-				saopsettings);
-
-		settings4 = new AllPermutationsSettings(parties, false,
-				Arrays.asList(profile1, profile2, profile3, profile1), 2,
-				saopsettings);
-
-	}
-
-	@Override
-	public List<List<AllPermutationsSettings>> getGeneralTestData() {
-		return Arrays.asList(Arrays.asList(settings, settings1a),
-				Arrays.asList(settings2), Arrays.asList(settings3),
-				Arrays.asList(settings4));
-	}
-
-	@Override
-	public List<String> getGeneralTestStrings() {
-		return Arrays.asList(
-				"AllPermutationsSettings.*party1.*party2.*,false,.*profile1.*profile2.*profile3.*,2,SAOPSettings.*",
-				"AllPermutationsSettings.*party1.*party2.*party3.*,false,.*profile1.*profile2.*profile3.*,2,SAOPSettings.*",
-				"AllPermutationsSettings.*party1.*party2.*,true,.*profile1.*profile2.*profile3.*,2,SAOPSettings.*",
-				"AllPermutationsSettings.*party1.*party2.*,false,.*profile1.*profile2.*profile3.*profile1.*,2,SAOPSettings.*");
-	}
-
-	@Test
-	public void getProtocolTest() {
-		assertEquals("APP", settings.getProtocol(new ReportToLogger("test"))
-				.getRef().getURI().toString());
-	}
-
-	@Test
-	public void testDeserialize() throws IOException {
-		TournamentSettings obj = jackson.readValue(serialized,
-				TournamentSettings.class);
-		System.out.println(obj);
-		assertEquals(settings, obj);
-	}
-
-	@Test
-	public void testSerialize()
-			throws JsonProcessingException, URISyntaxException {
-
-		String string = jackson.writeValueAsString(settings);
-		System.out.println(string);
-		assertEquals(serialized, string);
-	}
-
-	@Test(expected = IllegalArgumentException.class)
-	public void testNullParties() {
-		new AllPermutationsSettings(null, true,
-				Arrays.asList(profile1, profile2, profile3, profile1), 2,
-				saopsettings);
-
-	}
-
-	@Test(expected = IllegalArgumentException.class)
-	public void testNoParties() {
-		new AllPermutationsSettings(Collections.emptyList(), true,
-				Arrays.asList(profile1, profile2, profile3, profile1), 2,
-				saopsettings);
-
-	}
-
-	@Test(expected = IllegalArgumentException.class)
-	public void testNullProfiles() {
-		new AllPermutationsSettings(parties, true, null, 2, saopsettings);
-
-	}
-
-	@Test(expected = IllegalArgumentException.class)
-	public void testInsufficientProfiles() {
-		new AllPermutationsSettings(parties, true,
-				Arrays.asList(profile1, profile2, profile3, profile1), 4,
-				saopsettings);
-
-	}
-
-	@Test(expected = IllegalArgumentException.class)
-	public void testNullSessionSettings() {
-		new AllPermutationsSettings(parties, true,
-				Arrays.asList(profile1, profile2, profile3, profile1), 4, null);
-
-	}
-
-	@Test(expected = IllegalArgumentException.class)
-	public void testOnePartyPerSession() {
-		new AllPermutationsSettings(parties, true,
-				Arrays.asList(profile1, profile2, profile3, profile1), 1,
-				saopsettings);
-
-	}
-
-	@Test
-	public void getMaxRuntimeTest() {
-		assertEquals(BigInteger.valueOf(6), settings.permutations().size());
-		assertEquals((Double) (6d * 12), settings.getMaxRunTime());
-	}
-
-}
Index: otocol/src/test/java/geniusweb/protocol/tournament/AllPermutationsStateTest.java
===================================================================
--- /protocol/src/test/java/geniusweb/protocol/tournament/AllPermutationsStateTest.java	(revision 25)
+++ 	(revision )
@@ -1,96 +1,0 @@
-package geniusweb.protocol.tournament;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
-import java.math.BigInteger;
-import java.util.ArrayList;
-import java.util.List;
-
-import org.junit.Test;
-
-import geniusweb.protocol.SessionResult;
-import geniusweb.protocol.session.SessionSettings;
-import geniusweb.protocol.tournament.allpermutations.AllPermutationsSettings;
-import geniusweb.protocol.tournament.allpermutations.AllPermutationsState;
-import geniusweb.references.PartyWithProfile;
-import tudelft.utilities.immutablelist.ImmutableList;
-
-public class AllPermutationsStateTest {
-
-	private final AllPermutationsSettings toursettings = mock(
-			AllPermutationsSettings.class);;
-	@SuppressWarnings("unchecked")
-	private final List<SessionResult> results = mock(List.class);
-	@SuppressWarnings("unchecked")
-	private final ImmutableList<SessionSettings> settings = mock(
-			ImmutableList.class);
-	private final AllPermutationsState state = new AllPermutationsState(
-			toursettings, settings, results);
-	private final SessionSettings session7settings = mock(
-			SessionSettings.class);
-	private final long NOW = 1000;
-
-	@SuppressWarnings("unchecked")
-	private final List<PartyWithProfile> participants = mock(List.class);
-
-	@Test
-	public void getResultsTest() {
-		assertEquals(results, state.getResults());
-	}
-
-	@Test
-	public void isFinalTestFalse() {
-		when(settings.size()).thenReturn(BigInteger.TEN);
-		when(results.size()).thenReturn(11);
-		assertFalse(state.isFinal(NOW));
-	}
-
-	@Test
-	public void isFinalTestTrue() {
-		when(settings.size()).thenReturn(BigInteger.TEN);
-		when(results.size()).thenReturn(10);
-		assertTrue(state.isFinal(NOW));
-	}
-
-	@Test
-	public void getNextSetting() {
-		prepareNextSettings();
-		assertEquals(session7settings, state.getNextSettings());
-	}
-
-	private void prepareNextSettings() {
-		when(results.size()).thenReturn(7); // result 0..6
-		when(settings.size()).thenReturn(BigInteger.TEN);
-		when(session7settings.getParticipants()).thenReturn(participants);
-		when(settings.get(BigInteger.valueOf(7))).thenReturn(session7settings);
-
-	}
-
-	@Test
-	public void withTest() {
-		prepareNextSettings();
-		ArrayList<SessionResult> results1 = new ArrayList<>();
-		for (int n = 0; n < 7; n++) {
-			results1.add(mock(SessionResult.class));
-		}
-		// use state with "real" results... to allow array copy in with
-		AllPermutationsState state = new AllPermutationsState(toursettings,
-				settings, results1);
-
-		when(settings.size()).thenReturn(BigInteger.TEN);
-		when(settings.get(BigInteger.valueOf(7))).thenReturn(session7settings);
-
-		SessionResult result = mock(SessionResult.class);
-		when(result.getParticipants()).thenReturn(participants);
-		AllPermutationsState state1 = state.with(result);
-
-		assertEquals(null, state1.getError());
-		assertEquals(8, state1.getResults().size());
-		assertEquals(toursettings, state1.getSettings());
-
-	}
-}
Index: /pythonadapter/pom.xml
===================================================================
--- /pythonadapter/pom.xml	(revision 25)
+++ /pythonadapter/pom.xml	(revision 26)
@@ -6,5 +6,5 @@
 	<groupId>geniusweb</groupId>
 	<artifactId>pythonadapter</artifactId>
-	<version>1.5.4</version> <!-- must equal ${geniusweb.version} -->
+	<version>1.5.5</version> <!-- must equal ${geniusweb.version} -->
 	<packaging>jar</packaging>
 
@@ -17,5 +17,5 @@
 		<passwd>${env.ARTIFACTORY_PASS}</passwd>
 		<jackson-2-version>2.9.10</jackson-2-version>
-		<geniusweb.version>1.5.4</geniusweb.version>
+		<geniusweb.version>1.5.5</geniusweb.version>
 	</properties>
 
Index: /references/pom.xml
===================================================================
--- /references/pom.xml	(revision 25)
+++ /references/pom.xml	(revision 26)
@@ -6,5 +6,5 @@
 	<groupId>geniusweb</groupId>
 	<artifactId>references</artifactId>
-	<version>1.5.4</version> <!-- must equal ${geniusweb.version} -->
+	<version>1.5.5</version> <!-- must equal ${geniusweb.version} -->
 	<packaging>jar</packaging>
 
@@ -17,5 +17,5 @@
 		<passwd>${env.ARTIFACTORY_PASS}</passwd>
 		<jackson-2-version>2.9.10</jackson-2-version>
-		<geniusweb.version>1.5.4</geniusweb.version>
+		<geniusweb.version>1.5.5</geniusweb.version>
 	</properties>
 
Index: ferences/src/main/java/geniusweb/connection/Connection.java
===================================================================
--- /references/src/main/java/geniusweb/connection/Connection.java	(revision 25)
+++ 	(revision )
@@ -1,65 +1,0 @@
-package geniusweb.connection;
-
-import java.io.IOException;
-import java.net.SocketException;
-import java.net.URI;
-
-import geniusweb.references.Reference;
-import tudelft.utilities.listener.Listenable;
-
-/**
- * A general two-way connection. incoming data is reported through the
- * {@link Listenable} channel, sending events of the INTYPE.
- * <p>
- * If an internal error occurs, eg a socket failure, timeout, or parser error, a
- * null event is sent into the Listenable and {@link #getError()} can be called
- * to find out about the error.
- *
- * @param <INTYPE>  the type of incoming messages. Incoming messages are
- *                  received through Listener#not. Incoming messages are usually
- *                  asynchronous.
- * @param <OUTTYPE> the type of outgoing messages. Outgoing messages can be sent
- *                  directly with #send.
- * 
- */
-public interface Connection<INTYPE, OUTTYPE> extends Listenable<INTYPE> {
-
-	/**
-	 * Send data out (and flush the output so that there are no excessive delays
-	 * in sending the data). This call is assumed to return immediately (never
-	 * block, eg on synchronized, Thread.sleep, IO, etc). When this is called
-	 * multiple times in sequence, the data should arrive at the receiver end in
-	 * the same order.
-	 * 
-	 * @param data the data to be sent.
-	 * @throws IOException if the data failed to be sent.
-	 */
-	void send(OUTTYPE data) throws IOException;
-
-	/**
-	 * @return Reference that was used to create this connection
-	 */
-	Reference getReference();
-
-	/**
-	 * @return the URI of the remote endpoint that makes up the connection. This
-	 *         is a URI that uniquely identifies the remote object
-	 */
-	URI getRemoteURI();
-
-	/**
-	 * Close the connection. Should return immediately (not block). Before
-	 * really closing, this should attempt to send out possibly cached messages
-	 * before closing the connection.
-	 * 
-	 */
-	void close();
-
-	/**
-	 * @return the latest internal error, or null if no error occured. If the
-	 *         channel is closed, this is set to {@link SocketException} "Socket
-	 *         closed", even if the close was a "normal" termination eg when
-	 *         {@link #close()} was called.
-	 */
-	Throwable getError();
-}
Index: /simplerunner/pom.xml
===================================================================
--- /simplerunner/pom.xml	(revision 25)
+++ /simplerunner/pom.xml	(revision 26)
@@ -6,5 +6,5 @@
 	<groupId>geniusweb</groupId>
 	<artifactId>simplerunner</artifactId>
-	<version>1.5.4</version> <!-- must equal ${geniusweb.version} -->
+	<version>1.5.5</version> <!-- must equal ${geniusweb.version} -->
 	<packaging>jar</packaging>
 
@@ -17,5 +17,5 @@
 		<passwd>${env.ARTIFACTORY_PASS}</passwd>
 		<jackson-2-version>2.9.10</jackson-2-version>
-		<geniusweb.version>1.5.4</geniusweb.version>
+		<geniusweb.version>1.5.5</geniusweb.version>
 	</properties>
 
Index: mplerunner/troep.log
===================================================================
--- /simplerunner/troep.log	(revision 25)
+++ 	(revision )
@@ -1,5 +1,0 @@
-INFO:SAOP connect [PartyRef[classpath:geniusweb.exampleparties.randomparty.RandomParty], PartyRef[classpath:geniusweb.exampleparties.randomparty.RandomParty]]
-Connecting with party 'geniusweb.exampleparties.randomparty.RandomParty'
-Connecting with party 'geniusweb.exampleparties.randomparty.RandomParty'
-INFO:SAOP deadline set to 2020/06/08 17:06:53
-INFO:protocol ended normally: {"SAOPState":{"actions":[{"offer":{"actor":"geniusweb_exampleparties_randomparty_RandomParty_1","bid":{"issuevalues":{"lease car":"yes","permanent contract":"yes","career development opportunities":"low","salary":"4000","fte":"0.8"}}}},{"offer":{"actor":"geniusweb_exampleparties_randomparty_RandomParty_2","bid":{"issuevalues":{"permanent contract":"no","career development opportunities":"low","salary":"2000","work from home":"0","fte":"1.0"}}}},{"offer":{"actor":"geniusweb_exampleparties_randomparty_RandomParty_1","bid":{"issuevalues":{"lease car":"yes","permanent contract":"yes","salary":"4000","fte":"0.8"}}}},{"offer":{"actor":"geniusweb_exampleparties_randomparty_RandomParty_2","bid":{"issuevalues":{"lease car":"yes","permanent contract":"no","career development opportunities":"low","fte":"1.0","salary":"3000","work from home":"0"}}}},{"offer":{"actor":"geniusweb_exampleparties_randomparty_RandomParty_1","bid":{"issuevalues":{"lease car":"no","permanent contract":"yes","career development opportunities":"high","salary":"3500","fte":"1.0"}}}},{"offer":{"actor":"geniusweb_exampleparties_randomparty_RandomParty_2","bid":{"issuevalues":{"lease car":"yes","permanent contract":"yes","career development opportunities":"medium","fte":"1.0","salary":"2000","work from home":"0"}}}},{"offer":{"actor":"geniusweb_exampleparties_randomparty_RandomParty_1","bid":{"issuevalues":{"lease car":"yes","permanent contract":"yes","salary":"4000","work from home":"0","fte":"1.0"}}}},{"offer":{"actor":"geniusweb_exampleparties_randomparty_RandomParty_2","bid":{"issuevalues":{"lease car":"no","permanent contract":"no","career development opportunities":"low","fte":"0.8","salary":"2500","work from home":"1"}}}},{"offer":{"actor":"geniusweb_exampleparties_randomparty_RandomParty_1","bid":{"issuevalues":{"permanent contract":"no","career development opportunities":"high","salary":"4000","work from home":"2","fte":"1.0"}}}},{"offer":{"actor":"geniusweb_exampleparties_randomparty_RandomParty_2","bid":{"issuevalues":{"lease car":"no","permanent contract":"no","career development opportunities":"low","fte":"0.6","salary":"3000","work from home":"0"}}}},{"offer":{"actor":"geniusweb_exampleparties_randomparty_RandomParty_1","bid":{"issuevalues":{"permanent contract":"yes","career development opportunities":"low","salary":"2500","work from home":"1","fte":"0.6"}}}},{"offer":{"actor":"geniusweb_exampleparties_randomparty_RandomParty_2","bid":{"issuevalues":{"lease car":"yes","career development opportunities":"high","salary":"3500","work from home":"1"}}}},{"offer":{"actor":"geniusweb_exampleparties_randomparty_RandomParty_1","bid":{"issuevalues":{"lease car":"yes","permanent contract":"yes","career development opportunities":"low","fte":"1.0","salary":"3000","work from home":"2"}}}},{"offer":{"actor":"geniusweb_exampleparties_randomparty_RandomParty_2","bid":{"issuevalues":{"permanent contract":"no","salary":"2000","work from home":"0"}}}},{"offer":{"actor":"geniusweb_exampleparties_randomparty_RandomParty_1","bid":{"issuevalues":{"lease car":"yes","permanent contract":"no","career development opportunities":"high","fte":"1.0","salary":"3500","work from home":"0"}}}},{"offer":{"actor":"geniusweb_exampleparties_randomparty_RandomParty_2","bid":{"issuevalues":{"permanent contract":"yes","career development opportunities":"low","salary":"2000","work from home":"0","fte":"0.8"}}}},{"offer":{"actor":"geniusweb_exampleparties_randomparty_RandomParty_1","bid":{"issuevalues":{"lease car":"no","permanent contract":"yes","career development opportunities":"high","fte":"1.0","salary":"4000","work from home":"0"}}}},{"offer":{"actor":"geniusweb_exampleparties_randomparty_RandomParty_2","bid":{"issuevalues":{"permanent contract":"no","salary":"2000","work from home":"0"}}}},{"offer":{"actor":"geniusweb_exampleparties_randomparty_RandomParty_1","bid":{"issuevalues":{"lease car":"no","permanent contract":"no","career development opportunities":"medium","fte":"1.0","salary":"4000","work from home":"2"}}}},{"offer":{"actor":"geniusweb_exampleparties_randomparty_RandomParty_2","bid":{"issuevalues":{"lease car":"no","permanent contract":"no","salary":"2000","work from home":"0"}}}},{"offer":{"actor":"geniusweb_exampleparties_randomparty_RandomParty_1","bid":{"issuevalues":{"lease car":"yes","permanent contract":"yes","career development opportunities":"low","fte":"0.8","salary":"4000","work from home":"1"}}}},{"offer":{"actor":"geniusweb_exampleparties_randomparty_RandomParty_2","bid":{"issuevalues":{"lease car":"no","permanent contract":"no","career development opportunities":"low","fte":"0.8","salary":"2000","work from home":"2"}}}},{"offer":{"actor":"geniusweb_exampleparties_randomparty_RandomParty_1","bid":{"issuevalues":{"lease car":"yes","permanent contract":"yes","career development opportunities":"medium","salary":"3500","fte":"1.0"}}}},{"offer":{"actor":"geniusweb_exampleparties_randomparty_RandomParty_2","bid":{"issuevalues":{"lease car":"no","permanent contract":"no","career development opportunities":"medium","fte":"0.6","salary":"2000","work from home":"0"}}}},{"offer":{"actor":"geniusweb_exampleparties_randomparty_RandomParty_1","bid":{"issuevalues":{"lease car":"yes","permanent contract":"yes","career development opportunities":"low","fte":"0.6","salary":"4000","work from home":"2"}}}},{"offer":{"actor":"geniusweb_exampleparties_randomparty_RandomParty_2","bid":{"issuevalues":{"lease car":"yes","permanent contract":"no","career development opportunities":"medium","salary":"2500","work from home":"0"}}}},{"offer":{"actor":"geniusweb_exampleparties_randomparty_RandomParty_1","bid":{"issuevalues":{"permanent contract":"yes","career development opportunities":"medium","salary":"4000","work from home":"2","fte":"1.0"}}}},{"offer":{"actor":"geniusweb_exampleparties_randomparty_RandomParty_2","bid":{"issuevalues":{"lease car":"no","permanent contract":"yes","career development opportunities":"low","fte":"1.0","salary":"2000","work from home":"0"}}}},{"offer":{"actor":"geniusweb_exampleparties_randomparty_RandomParty_1","bid":{"issuevalues":{"lease car":"yes","permanent contract":"yes","career development opportunities":"low","salary":"2000","work from home":"2"}}}},{"offer":{"actor":"geniusweb_exampleparties_randomparty_RandomParty_2","bid":{"issuevalues":{"lease car":"no","permanent contract":"no","career development opportunities":"high","fte":"1.0","salary":"2000","work from home":"1"}}}},{"offer":{"actor":"geniusweb_exampleparties_randomparty_RandomParty_1","bid":{"issuevalues":{"lease car":"yes","permanent contract":"yes","career development opportunities":"medium","fte":"1.0","salary":"3000","work from home":"1"}}}},{"offer":{"actor":"geniusweb_exampleparties_randomparty_RandomParty_2","bid":{"issuevalues":{"lease car":"yes","permanent contract":"no","salary":"2000","work from home":"0","fte":"1.0"}}}},{"offer":{"actor":"geniusweb_exampleparties_randomparty_RandomParty_1","bid":{"issuevalues":{"lease car":"yes","permanent contract":"yes","career development opportunities":"low","fte":"1.0","salary":"2500","work from home":"1"}}}},{"offer":{"actor":"geniusweb_exampleparties_randomparty_RandomParty_2","bid":{"issuevalues":{"lease car":"yes","permanent contract":"no","career development opportunities":"medium","fte":"1.0","salary":"2000","work from home":"1"}}}},{"offer":{"actor":"geniusweb_exampleparties_randomparty_RandomParty_1","bid":{"issuevalues":{"lease car":"yes","permanent contract":"no","career development opportunities":"high","fte":"1.0","salary":"3500","work from home":"1"}}}},{"offer":{"actor":"geniusweb_exampleparties_randomparty_RandomParty_2","bid":{"issuevalues":{"permanent contract":"no","career development opportunities":"low","salary":"2500","work from home":"0","fte":"0.8"}}}},{"offer":{"actor":"geniusweb_exampleparties_randomparty_RandomParty_1","bid":{"issuevalues":{"lease car":"yes","permanent contract":"yes","salary":"3500","work from home":"0","fte":"1.0"}}}},{"offer":{"actor":"geniusweb_exampleparties_randomparty_RandomParty_2","bid":{"issuevalues":{"permanent contract":"no","salary":"3000","work from home":"2"}}}},{"offer":{"actor":"geniusweb_exampleparties_randomparty_RandomParty_1","bid":{"issuevalues":{"permanent contract":"yes","salary":"3500","work from home":"1","fte":"1.0"}}}},{"offer":{"actor":"geniusweb_exampleparties_randomparty_RandomParty_2","bid":{"issuevalues":{"permanent contract":"yes","career development opportunities":"low","salary":"2000","work from home":"0","fte":"0.8"}}}},{"offer":{"actor":"geniusweb_exampleparties_randomparty_RandomParty_1","bid":{"issuevalues":{"lease car":"yes","career development opportunities":"high","salary":"2000","work from home":"2"}}}},{"offer":{"actor":"geniusweb_exampleparties_randomparty_RandomParty_2","bid":{"issuevalues":{"lease car":"no","permanent contract":"no","career development opportunities":"medium","salary":"2500","work from home":"0"}}}},{"offer":{"actor":"geniusweb_exampleparties_randomparty_RandomParty_1","bid":{"issuevalues":{"lease car":"yes","career development opportunities":"medium","salary":"3500","work from home":"2","fte":"1.0"}}}},{"offer":{"actor":"geniusweb_exampleparties_randomparty_RandomParty_2","bid":{"issuevalues":{"lease car":"no","permanent contract":"yes","career development opportunities":"medium","fte":"1.0","salary":"3500","work from home":"1"}}}},{"accept":{"actor":"geniusweb_exampleparties_randomparty_RandomParty_1","bid":{"issuevalues":{"lease car":"no","permanent contract":"yes","career development opportunities":"medium","fte":"1.0","salary":"3500","work from home":"1"}}}}],"progress":{"time":{"duration":100,"start":1591628813120}},"settings":{"SAOPSettings":{"participants":[{"party":{"partyref":"classpath:geniusweb.exampleparties.randomparty.RandomParty","parameters":{}},"profile":"file:src/test/resources/jobs/jobs1.json"},{"party":{"partyref":"classpath:geniusweb.exampleparties.randomparty.RandomParty","parameters":{}},"profile":"file:src/test/resources/jobs/jobs2.json"}],"deadline":{"deadlinetime":{"durationms":100}}}},"error":null,"partyprofiles":{"geniusweb_exampleparties_randomparty_RandomParty_1":{"party":{"partyref":"classpath:geniusweb.exampleparties.randomparty.RandomParty","parameters":{}},"profile":"file:src/test/resources/jobs/jobs1.json"},"geniusweb_exampleparties_randomparty_RandomParty_2":{"party":{"partyref":"classpath:geniusweb.exampleparties.randomparty.RandomParty","parameters":{}},"profile":"file:src/test/resources/jobs/jobs2.json"}}}}
Index: /timeline/pom.xml
===================================================================
--- /timeline/pom.xml	(revision 25)
+++ /timeline/pom.xml	(revision 26)
@@ -6,5 +6,5 @@
 	<groupId>geniusweb</groupId>
 	<artifactId>timeline</artifactId>
-	<version>1.5.4</version> <!-- must equal ${geniusweb.version} -->
+	<version>1.5.5</version> <!-- must equal ${geniusweb.version} -->
 	<packaging>jar</packaging>
 
@@ -16,5 +16,5 @@
 		<passwd>${env.ARTIFACTORY_PASS}</passwd>
 		<jackson-2-version>2.9.10</jackson-2-version>
-		<geniusweb.version>1.5.4</geniusweb.version>
+		<geniusweb.version>1.5.5</geniusweb.version>
 	</properties>
 
Index: /timeline/src/main/java/geniusweb/progress/ProgressTime.java
===================================================================
--- /timeline/src/main/java/geniusweb/progress/ProgressTime.java	(revision 25)
+++ /timeline/src/main/java/geniusweb/progress/ProgressTime.java	(revision 26)
@@ -29,10 +29,4 @@
 	 */
 	private final Long duration;
-
-	@SuppressWarnings("unused") // for deserializer
-	private ProgressTime() {
-		start = null;
-		duration = null;
-	}
 
 	/**
Index: /timeline/src/test/java/geniusweb/deadline/DeadlineTest.java
===================================================================
--- /timeline/src/test/java/geniusweb/deadline/DeadlineTest.java	(revision 25)
+++ /timeline/src/test/java/geniusweb/deadline/DeadlineTest.java	(revision 26)
@@ -80,3 +80,8 @@
 	}
 
+	@Test
+	public void getRounds() {
+		assertEquals((Integer) 11, new DeadlineRounds(11, 20).getRounds());
+	}
+
 }
Index: /timeline/src/test/java/geniusweb/progress/ProgressRoundsTest.java
===================================================================
--- /timeline/src/test/java/geniusweb/progress/ProgressRoundsTest.java	(revision 25)
+++ /timeline/src/test/java/geniusweb/progress/ProgressRoundsTest.java	(revision 26)
@@ -2,4 +2,6 @@
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
@@ -24,4 +26,6 @@
 public class ProgressRoundsTest extends GeneralTests<Progress> {
 	private DeadlineRounds deadline = mock(DeadlineRounds.class);
+	private final static Integer TESTROUNDS = 10;
+	private final static long TESTTIME = 10; // milliseconds!
 
 	private final Date date = new Date(999l);
@@ -34,7 +38,10 @@
 	private final Progress deadline5 = new ProgressTime(20l, date);
 	private ProgressRounds progress;
-	private final static Integer TESTROUNDS = 10;
 	private final ObjectMapper jackson = new ObjectMapper();
 	private final String progressstring = "{\"rounds\":{\"duration\":10,\"currentRound\":0,\"endtime\":999}}";
+
+	private final long start = 1234;
+	private final Date end = new Date(start + TESTTIME);
+	private final ProgressRounds pr = new ProgressRounds(TESTROUNDS, 4, end);
 
 	@Before
@@ -105,4 +112,5 @@
 	}
 
+	@SuppressWarnings("unused")
 	@Test(expected = IllegalArgumentException.class)
 	public void testIllegalArg1() {
@@ -110,4 +118,5 @@
 	}
 
+	@SuppressWarnings("unused")
 	@Test(expected = IllegalArgumentException.class)
 	public void testIllegalArg2() {
@@ -115,3 +124,37 @@
 	}
 
+	@Test
+	public void pastDeadline() {
+		assertFalse(pr.isPastDeadline(start));
+		assertTrue(pr.isPastDeadline(start + TESTTIME + 1));
+		assertFalse(pr.isPastDeadline(start + TESTTIME - 1));
+		assertTrue(new ProgressRounds(TESTROUNDS, TESTROUNDS, end)
+				.isPastDeadline(start + TESTTIME + 1));
+	}
+
+	@Test
+	public void terminationTime() {
+		assertEquals(start + TESTTIME, pr.getTerminationTime().getTime());
+	}
+
+	@Test
+	public void get() {
+		// time does not matter for rounds-based deadline
+		assertEquals((Double) 0.4d, pr.get(start));
+		assertEquals((Double) 0.4d, pr.get(start + TESTTIME + 1));
+		assertEquals((Double) 0.4d, pr.get(start + TESTTIME));
+		assertEquals((Double) 0.4d, pr.get(start + TESTTIME / 2));
+		assertEquals((Double) 0.4d, pr.get(start - 10));
+		assertEquals((Double) 0.4d, pr.get(start + TESTTIME + 10));
+
+		assertEquals((Double) 0.1d,
+				new ProgressRounds(TESTROUNDS, 1, end).get(start));
+		assertEquals((Double) 1d,
+				new ProgressRounds(TESTROUNDS, TESTROUNDS, end).get(start));
+	}
+
+	@Test
+	public void totalRounds() {
+		assertEquals((Integer) 10, pr.getTotalRounds());
+	}
 }
Index: /timeline/src/test/java/geniusweb/progress/ProgressTimeTest.java
===================================================================
--- /timeline/src/test/java/geniusweb/progress/ProgressTimeTest.java	(revision 25)
+++ /timeline/src/test/java/geniusweb/progress/ProgressTimeTest.java	(revision 26)
@@ -2,4 +2,6 @@
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
 
 import java.io.IOException;
@@ -16,6 +18,4 @@
 import com.fasterxml.jackson.databind.ObjectMapper;
 
-import geniusweb.progress.Progress;
-import geniusweb.progress.ProgressTime;
 import tudelft.utilities.junit.GeneralTests;
 
@@ -30,4 +30,7 @@
 	private final ObjectMapper jackson = new ObjectMapper();
 	private final String progressstring = "{\"time\":{\"duration\":10,\"start\":0}}";
+
+	private final long start = 1234;
+	private final ProgressTime pr = new ProgressTime(TESTTIME, new Date(start));
 
 	@Override
@@ -83,3 +86,25 @@
 	}
 
+	@Test
+	public void pastDeadline() {
+		assertTrue(pr.isPastDeadline(start + TESTTIME + 1));
+		assertFalse(pr.isPastDeadline(start + TESTTIME - 1));
+
+	}
+
+	@Test
+	public void terminationTime() {
+		assertEquals(start + TESTTIME, pr.getTerminationTime().getTime());
+	}
+
+	@Test
+	public void get() {
+		assertEquals((Double) 0d, pr.get(start));
+		assertEquals((Double) 1d, pr.get(start + TESTTIME));
+		assertEquals((Double) 0.5d, pr.get(start + TESTTIME / 2));
+		assertEquals((Double) 0d, pr.get(start - 10));
+		assertEquals((Double) 1d, pr.get(start + TESTTIME + 10));
+
+	}
+
 }
Index: /voting/pom.xml
===================================================================
--- /voting/pom.xml	(revision 25)
+++ /voting/pom.xml	(revision 26)
@@ -6,5 +6,5 @@
 	<groupId>geniusweb</groupId>
 	<artifactId>voting</artifactId>
-	<version>1.5.4</version> <!-- must equal ${geniusweb.version} -->
+	<version>1.5.5</version> <!-- must equal ${geniusweb.version} -->
 	<packaging>jar</packaging>
 
@@ -17,5 +17,5 @@
 		<passwd>${env.ARTIFACTORY_PASS}</passwd>
 		<jackson-2-version>2.9.10</jackson-2-version>
-		<geniusweb.version>1.5.4</geniusweb.version>
+		<geniusweb.version>1.5.5</geniusweb.version>
 	</properties>
 
Index: /voting/src/main/java/geniusweb/voting/votingevaluators/LargestAgreement.java
===================================================================
--- /voting/src/main/java/geniusweb/voting/votingevaluators/LargestAgreement.java	(revision 25)
+++ /voting/src/main/java/geniusweb/voting/votingevaluators/LargestAgreement.java	(revision 26)
@@ -73,5 +73,5 @@
 				.max(Comparator.comparingInt(bid -> agrees.get(bid).size()))
 				.get();
-		agreement = agreement.with(maxbid, agrees.get(maxbid));
+		agreement = agreement.with(new Agreements(maxbid, agrees.get(maxbid)));
 		return agreement;
 	}
Index: /voting/src/main/java/geniusweb/voting/votingevaluators/LargestAgreementsLoop.java
===================================================================
--- /voting/src/main/java/geniusweb/voting/votingevaluators/LargestAgreementsLoop.java	(revision 25)
+++ /voting/src/main/java/geniusweb/voting/votingevaluators/LargestAgreementsLoop.java	(revision 26)
@@ -82,5 +82,6 @@
 					.get();
 			Set<PartyId> maxparties = agrees.get(maxbid);
-			newagreements = newagreements.with(maxbid, maxparties);
+			newagreements = newagreements
+					.with(new Agreements(maxbid, maxparties));
 			remainingvotes = remainingvotes.without(maxparties);
 		}
Index: /voting/src/test/java/geniusweb/voting/CollectedVotesTest.java
===================================================================
--- /voting/src/test/java/geniusweb/voting/CollectedVotesTest.java	(revision 25)
+++ /voting/src/test/java/geniusweb/voting/CollectedVotesTest.java	(revision 26)
@@ -54,5 +54,5 @@
 			Collections.emptyMap());
 
-	private Votes votes = new Votes(partyP, Arrays.asList(votePA2));
+	private Votes votes = new Votes(partyP, Collections.singleton(votePA2));
 	private CollectedVotes cv2 = new CollectedVotes(
 			Collections.singletonMap(partyP, votes),
@@ -81,7 +81,7 @@
 	public void testGetAllBids() {
 		Map<PartyId, Votes> allvotes = new HashMap<>();
-		allvotes.put(partyP, new Votes(partyP, Arrays.asList(votePA2)));
-		allvotes.put(partyQ,
-				new Votes(partyQ, Arrays.asList(voteQA2, voteQB3)));
+		allvotes.put(partyP, new Votes(partyP, Collections.singleton(votePA2)));
+		allvotes.put(partyQ, new Votes(partyQ,
+				new HashSet<>(Arrays.asList(voteQA2, voteQB3))));
 
 		Map<Bid, Set<Vote>> allbids = new CollectedVotes(allvotes, allpowers)
@@ -129,9 +129,9 @@
 	public void testGetMaxAgreements() {
 		Map<PartyId, Votes> allvotes = new HashMap<>();
-		allvotes.put(partyP, new Votes(partyP, Arrays.asList(votePA2)));
-		allvotes.put(partyQ,
-				new Votes(partyQ, Arrays.asList(voteQA2, voteQB2)));
-		allvotes.put(partyR,
-				new Votes(partyR, Arrays.asList(voteRA4, voteRB2)));
+		allvotes.put(partyP, new Votes(partyP, Collections.singleton(votePA2)));
+		allvotes.put(partyQ, new Votes(partyQ,
+				new HashSet<>(Arrays.asList(voteQA2, voteQB2))));
+		allvotes.put(partyR, new Votes(partyR,
+				new HashSet<>(Arrays.asList(voteRA4, voteRB2))));
 
 		Map<Bid, Set<PartyId>> allagrees = new CollectedVotes(allvotes,
@@ -147,5 +147,5 @@
 	public void testGetNoAgreements() {
 		Map<PartyId, Votes> allvotes = new HashMap<>();
-		allvotes.put(partyP, new Votes(partyP, Arrays.asList(votePA2)));
+		allvotes.put(partyP, new Votes(partyP, Collections.singleton(votePA2)));
 		Map<Bid, Set<PartyId>> allagrees = new CollectedVotes(allvotes,
 				allpowers).getMaxAgreements();
@@ -216,8 +216,8 @@
 	public void testWith() {
 		Map<PartyId, Votes> allvotes = new HashMap<>();
-		allvotes.put(partyP, new Votes(partyP, Arrays.asList(votePA2)));
+		allvotes.put(partyP, new Votes(partyP, Collections.singleton(votePA2)));
 		CollectedVotes cv = new CollectedVotes(allvotes, allpowers);
 		assertEquals(1, cv.getVotes().keySet().size());
-		cv = cv.with(new Votes(partyQ, Arrays.asList(voteQA2)), 2);
+		cv = cv.with(new Votes(partyQ, Collections.singleton(voteQA2)), 2);
 		assertEquals(2, cv.getVotes().keySet().size());
 	}
@@ -226,9 +226,9 @@
 	public void testWithout() {
 		Map<PartyId, Votes> allvotes = new HashMap<>();
-		allvotes.put(partyP, new Votes(partyP, Arrays.asList(votePA2)));
-		allvotes.put(partyQ,
-				new Votes(partyQ, Arrays.asList(voteQA2, voteQB2)));
-		allvotes.put(partyR,
-				new Votes(partyR, Arrays.asList(voteRA4, voteRB2)));
+		allvotes.put(partyP, new Votes(partyP, Collections.singleton(votePA2)));
+		allvotes.put(partyQ, new Votes(partyQ,
+				new HashSet<>(Arrays.asList(voteQA2, voteQB2))));
+		allvotes.put(partyR, new Votes(partyR,
+				new HashSet<>(Arrays.asList(voteRA4, voteRB2))));
 
 		// give R extra power to reach the 4 if other 2 join
@@ -254,8 +254,8 @@
 		Vote S = new Vote(partyS, bidA, 2, 3);
 		Map<PartyId, Votes> allvotes = new HashMap<>();
-		allvotes.put(partyP, new Votes(partyP, Arrays.asList(P)));
-		allvotes.put(partyQ, new Votes(partyQ, Arrays.asList(Q)));
-		allvotes.put(partyR, new Votes(partyR, Arrays.asList(R)));
-		allvotes.put(partyS, new Votes(partyS, Arrays.asList(S)));
+		allvotes.put(partyP, new Votes(partyP, Collections.singleton(P)));
+		allvotes.put(partyQ, new Votes(partyQ, Collections.singleton(Q)));
+		allvotes.put(partyR, new Votes(partyR, Collections.singleton(R)));
+		allvotes.put(partyS, new Votes(partyS, Collections.singleton(S)));
 
 		CollectedVotes cv = new CollectedVotes(allvotes, allpowers);
@@ -277,7 +277,7 @@
 		Vote R = new Vote(partyR, bidA, 2, 3);
 		Map<PartyId, Votes> allvotes = new HashMap<>();
-		allvotes.put(partyP, new Votes(partyP, Arrays.asList(P)));
-		allvotes.put(partyQ, new Votes(partyQ, Arrays.asList(Q)));
-		allvotes.put(partyR, new Votes(partyR, Arrays.asList(R)));
+		allvotes.put(partyP, new Votes(partyP, Collections.singleton(P)));
+		allvotes.put(partyQ, new Votes(partyQ, Collections.singleton(Q)));
+		allvotes.put(partyR, new Votes(partyR, Collections.singleton(R)));
 
 		Map<PartyId, Integer> powers = new HashMap<PartyId, Integer>();
Index: /voting/src/test/java/geniusweb/voting/votingevaluators/LargestAgreementsLoopTest.java
===================================================================
--- /voting/src/test/java/geniusweb/voting/votingevaluators/LargestAgreementsLoopTest.java	(revision 25)
+++ /voting/src/test/java/geniusweb/voting/votingevaluators/LargestAgreementsLoopTest.java	(revision 26)
@@ -74,12 +74,12 @@
 	@Test
 	public void testCollectVotes() {
-		Votes vote1AB = new Votes(party1, Arrays
-				.asList(new Vote(party1, a, 2, 9), new Vote(party1, b, 2, 9)));
-		Votes vote2AB = new Votes(party2, Arrays
-				.asList(new Vote(party2, a, 2, 9), new Vote(party2, b, 2, 9)));
+		Votes vote1AB = new Votes(party1, new HashSet<>(Arrays
+				.asList(new Vote(party1, a, 2, 9), new Vote(party1, b, 2, 9))));
+		Votes vote2AB = new Votes(party2, new HashSet<>(Arrays
+				.asList(new Vote(party2, a, 2, 9), new Vote(party2, b, 2, 9))));
 		Votes vote3C = new Votes(party3,
-				Arrays.asList(new Vote(party3, c, 2, 9)));
-		Votes vote4AC = new Votes(party4, Arrays
-				.asList(new Vote(party4, a, 2, 9), new Vote(party4, c, 2, 9)));
+				Collections.singleton(new Vote(party3, c, 2, 9)));
+		Votes vote4AC = new Votes(party4, new HashSet<>(Arrays
+				.asList(new Vote(party4, a, 2, 9), new Vote(party4, c, 2, 9))));
 		// party 1,2,4 vote for A, party 1,2 vote for B, party 3,4 vote for C.
 		// the biggest vote is P,Q,S
