Index: /bidspace/pom.xml
===================================================================
--- /bidspace/pom.xml	(revision 33)
+++ /bidspace/pom.xml	(revision 34)
@@ -6,5 +6,5 @@
 	<groupId>geniusweb</groupId>
 	<artifactId>bidspace</artifactId>
-	<version>2.0.0</version> <!-- must equal ${geniusweb.version} -->
+	<version>2.0.1</version> <!-- must equal ${geniusweb.version} -->
 	<packaging>jar</packaging>
 
@@ -16,5 +16,5 @@
 		<passwd>${env.ARTIFACTORY_PASS}</passwd>
 		<jackson-2-version>2.12.3</jackson-2-version>
-		<geniusweb.version>2.0.0</geniusweb.version>
+		<geniusweb.version>2.0.1</geniusweb.version>
 	</properties>
 
@@ -96,6 +96,6 @@
 		<dependency>
 			<groupId>org.mockito</groupId>
-			<artifactId>mockito-all</artifactId>
-			<version>1.9.5</version>
+			<artifactId>mockito-core</artifactId>
+			<version>3.11.2</version>
 			<scope>test</scope>
 		</dependency>
@@ -125,4 +125,8 @@
 			<id>central</id>
 			<url>https://repo1.maven.org/maven2</url>
+		</pluginRepository>
+		<pluginRepository>
+			<id>artifactory.ewi.tudelft.nl</id>
+			<url>https://artifactory.ewi.tudelft.nl/artifactory/libs-release</url>
 		</pluginRepository>
 	</pluginRepositories>
Index: /boa/pom.xml
===================================================================
--- /boa/pom.xml	(revision 33)
+++ /boa/pom.xml	(revision 34)
@@ -6,5 +6,5 @@
 	<groupId>geniusweb</groupId>
 	<artifactId>boa</artifactId>
-	<version>2.0.0</version> <!-- must equal ${geniusweb.version} -->
+	<version>2.0.1</version> <!-- must equal ${geniusweb.version} -->
 	<packaging>jar</packaging>
 
@@ -17,5 +17,5 @@
 		<passwd>${env.ARTIFACTORY_PASS}</passwd>
 		<jackson-2-version>2.12.3</jackson-2-version>
-		<geniusweb.version>2.0.0</geniusweb.version>
+		<geniusweb.version>2.0.1</geniusweb.version>
 	</properties>
 
@@ -79,6 +79,6 @@
 		<dependency>
 			<groupId>org.mockito</groupId>
-			<artifactId>mockito-all</artifactId>
-			<version>1.9.5</version>
+			<artifactId>mockito-core</artifactId>
+			<version>3.11.2</version>
 			<scope>test</scope>
 		</dependency>
@@ -95,11 +95,14 @@
 			</snapshots>
 		</repository>
-
 	</repositories>
-
+	
 	<pluginRepositories>
 		<pluginRepository>
 			<id>central</id>
 			<url>https://repo1.maven.org/maven2</url>
+		</pluginRepository>
+		<pluginRepository>
+			<id>artifactory.ewi.tudelft.nl</id>
+			<url>https://artifactory.ewi.tudelft.nl/artifactory/libs-release</url>
 		</pluginRepository>
 	</pluginRepositories>
Index: /boa/src/main/java/geniusweb/boa/BoaState.java
===================================================================
--- /boa/src/main/java/geniusweb/boa/BoaState.java	(revision 33)
+++ /boa/src/main/java/geniusweb/boa/BoaState.java	(revision 34)
@@ -216,4 +216,5 @@
 		try {
 			newmodel = opponentModelClass.newInstance()
+					.with(settings.getParameters())
 					.with(profile.getDomain(), profile.getReservationBid());
 		} catch (Exception e) {
Index: /boa/src/test/java/geniusweb/boa/BoaPartyTest.java
===================================================================
--- /boa/src/test/java/geniusweb/boa/BoaPartyTest.java	(revision 33)
+++ /boa/src/test/java/geniusweb/boa/BoaPartyTest.java	(revision 34)
@@ -3,6 +3,6 @@
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.eq;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.spy;
@@ -173,5 +173,4 @@
 	@Override
 	public String getName() {
-		// TODO Auto-generated method stub
 		return null;
 	}
@@ -179,5 +178,4 @@
 	@Override
 	public Domain getDomain() {
-		// TODO Auto-generated method stub
 		return null;
 	}
@@ -185,5 +183,4 @@
 	@Override
 	public Bid getReservationBid() {
-		// TODO Auto-generated method stub
 		return null;
 	}
@@ -197,4 +194,9 @@
 	public OpponentModel with(Action action, Progress progress) {
 		return this;
+	}
+
+	@Override
+	public OpponentModel with(Parameters parameters) {
+		return this; // ignore
 	}
 
Index: /collectparties.sh
===================================================================
--- /collectparties.sh	(revision 33)
+++ /collectparties.sh	(revision 34)
@@ -7,5 +7,5 @@
 rm -rf collectedparties
 mkdir collectedparties
-VERSION=2.0.0
+VERSION=2.0.1
 
 cp "exampleparties/anac2019/agentgg/target/agentgg-${VERSION}-jar-with-dependencies.jar" collectedparties
Index: /events/pom.xml
===================================================================
--- /events/pom.xml	(revision 33)
+++ /events/pom.xml	(revision 34)
@@ -6,5 +6,5 @@
 	<groupId>geniusweb</groupId>
 	<artifactId>events</artifactId>
-	<version>2.0.0</version> <!-- must equal ${geniusweb.version} -->
+	<version>2.0.1</version> <!-- must equal ${geniusweb.version} -->
 	<packaging>jar</packaging>
 
@@ -17,5 +17,5 @@
 		<passwd>${env.ARTIFACTORY_PASS}</passwd>
 		<jackson-2-version>2.12.3</jackson-2-version>
-		<geniusweb.version>2.0.0</geniusweb.version>
+		<geniusweb.version>2.0.1</geniusweb.version>
 	</properties>
 
@@ -35,87 +35,5 @@
 			</snapshots>
 		</repository>
-
 	</repositories>
-
-
-	<dependencies>
-		<dependency>
-			<groupId>geniusweb</groupId>
-			<artifactId>timeline</artifactId>
-			<version>${geniusweb.version}</version>
-		</dependency>
-		<dependency>
-			<groupId>geniusweb</groupId>
-			<artifactId>issuevalue</artifactId>
-			<version>${geniusweb.version}</version>
-		</dependency>
-		<dependency>
-			<groupId>geniusweb</groupId>
-			<artifactId>references</artifactId>
-			<version>${geniusweb.version}</version>
-		</dependency>
-
-		<!-- the core, which includes Streaming API, shared low-level abstractions 
-			(but NOT data-binding) -->
-		<dependency>
-			<groupId>com.fasterxml.jackson.core</groupId>
-			<artifactId>jackson-core</artifactId>
-			<version>${jackson-2-version}</version>
-		</dependency>
-
-		<!-- Just the annotations; use this dependency if you want to attach annotations 
-			to classes without connecting them to the code. -->
-		<dependency>
-			<groupId>com.fasterxml.jackson.core</groupId>
-			<artifactId>jackson-annotations</artifactId>
-			<version>${jackson-2-version}</version>
-		</dependency>
-
-		<!-- databinding; ObjectMapper, JsonNode and related classes are here -->
-		<dependency>
-			<groupId>com.fasterxml.jackson.core</groupId>
-			<artifactId>jackson-databind</artifactId>
-			<version>${jackson-2-version}</version>
-		</dependency>
-
-		<!-- smile (binary JSON). Other artifacts in this group do other formats. -->
-		<dependency>
-			<groupId>com.fasterxml.jackson.dataformat</groupId>
-			<artifactId>jackson-dataformat-smile</artifactId>
-			<version>${jackson-2-version}</version>
-		</dependency>
-		<!-- JAX-RS provider -->
-		<dependency>
-			<groupId>com.fasterxml.jackson.jaxrs</groupId>
-			<artifactId>jackson-jaxrs-json-provider</artifactId>
-			<version>${jackson-2-version}</version>
-		</dependency>
-		<!-- Support for JAX-B annotations as additional configuration -->
-		<dependency>
-			<groupId>com.fasterxml.jackson.module</groupId>
-			<artifactId>jackson-module-jaxb-annotations</artifactId>
-			<version>${jackson-2-version}</version>
-		</dependency>
-		<dependency>
-			<groupId>junit</groupId>
-			<artifactId>junit</artifactId>
-			<version>4.12</version>
-			<scope>test</scope>
-		</dependency>
-		<dependency>
-			<groupId>org.mockito</groupId>
-			<artifactId>mockito-all</artifactId>
-			<version>1.9.5</version>
-			<scope>test</scope>
-		</dependency>
-
-		<dependency>
-			<groupId>tudelft.utilities</groupId>
-			<artifactId>junit</artifactId>
-			<version>1.0.5</version>
-			<scope>test</scope>
-		</dependency>
-	</dependencies>
-
 
 	<pluginRepositories>
@@ -124,7 +42,91 @@
 			<url>https://repo1.maven.org/maven2</url>
 		</pluginRepository>
+		<pluginRepository>
+			<id>artifactory.ewi.tudelft.nl</id>
+			<url>https://artifactory.ewi.tudelft.nl/artifactory/libs-release</url>
+		</pluginRepository>
 	</pluginRepositories>
 
 
+	<dependencies>
+		<dependency>
+			<groupId>geniusweb</groupId>
+			<artifactId>timeline</artifactId>
+			<version>${geniusweb.version}</version>
+		</dependency>
+		<dependency>
+			<groupId>geniusweb</groupId>
+			<artifactId>issuevalue</artifactId>
+			<version>${geniusweb.version}</version>
+		</dependency>
+		<dependency>
+			<groupId>geniusweb</groupId>
+			<artifactId>references</artifactId>
+			<version>${geniusweb.version}</version>
+		</dependency>
+
+		<!-- the core, which includes Streaming API, shared low-level abstractions 
+			(but NOT data-binding) -->
+		<dependency>
+			<groupId>com.fasterxml.jackson.core</groupId>
+			<artifactId>jackson-core</artifactId>
+			<version>${jackson-2-version}</version>
+		</dependency>
+
+		<!-- Just the annotations; use this dependency if you want to attach annotations 
+			to classes without connecting them to the code. -->
+		<dependency>
+			<groupId>com.fasterxml.jackson.core</groupId>
+			<artifactId>jackson-annotations</artifactId>
+			<version>${jackson-2-version}</version>
+		</dependency>
+
+		<!-- databinding; ObjectMapper, JsonNode and related classes are here -->
+		<dependency>
+			<groupId>com.fasterxml.jackson.core</groupId>
+			<artifactId>jackson-databind</artifactId>
+			<version>${jackson-2-version}</version>
+		</dependency>
+
+		<!-- smile (binary JSON). Other artifacts in this group do other formats. -->
+		<dependency>
+			<groupId>com.fasterxml.jackson.dataformat</groupId>
+			<artifactId>jackson-dataformat-smile</artifactId>
+			<version>${jackson-2-version}</version>
+		</dependency>
+		<!-- JAX-RS provider -->
+		<dependency>
+			<groupId>com.fasterxml.jackson.jaxrs</groupId>
+			<artifactId>jackson-jaxrs-json-provider</artifactId>
+			<version>${jackson-2-version}</version>
+		</dependency>
+		<!-- Support for JAX-B annotations as additional configuration -->
+		<dependency>
+			<groupId>com.fasterxml.jackson.module</groupId>
+			<artifactId>jackson-module-jaxb-annotations</artifactId>
+			<version>${jackson-2-version}</version>
+		</dependency>
+		<dependency>
+			<groupId>junit</groupId>
+			<artifactId>junit</artifactId>
+			<version>4.12</version>
+			<scope>test</scope>
+		</dependency>
+		<dependency>
+			<groupId>org.mockito</groupId>
+			<artifactId>mockito-core</artifactId>
+			<version>3.11.2</version>
+			<scope>test</scope>
+		</dependency>
+
+		<dependency>
+			<groupId>tudelft.utilities</groupId>
+			<artifactId>junit</artifactId>
+			<version>1.0.5</version>
+			<scope>test</scope>
+		</dependency>
+	</dependencies>
+
+	
 
 	<build>
Index: /events/src/main/java/geniusweb/actions/Vote.java
===================================================================
--- /events/src/main/java/geniusweb/actions/Vote.java	(revision 33)
+++ /events/src/main/java/geniusweb/actions/Vote.java	(revision 34)
@@ -15,5 +15,5 @@
 
 	/**
-	 * @param id       the {@link PartyId} that does the action
+	 * @param actor    the {@link PartyId} that does the action
 	 * @param bid      the bid that is voted on
 	 * @param minPower the minimum power this bid must get in order for the vote
@@ -26,8 +26,9 @@
 	 */
 	@JsonCreator
-	public Vote(@JsonProperty("actor") PartyId id, @JsonProperty("bid") Bid bid,
+	public Vote(@JsonProperty("actor") PartyId actor,
+			@JsonProperty("bid") Bid bid,
 			@JsonProperty("minPower") Integer minPower,
 			@JsonProperty("maxPower") Integer maxPower) {
-		super(id, bid);
+		super(actor, bid);
 		this.minPower = minPower;
 		this.maxPower = maxPower;
Index: /events/src/main/java/geniusweb/actions/Votes.java
===================================================================
--- /events/src/main/java/geniusweb/actions/Votes.java	(revision 33)
+++ /events/src/main/java/geniusweb/actions/Votes.java	(revision 34)
@@ -2,9 +2,8 @@
 
 import java.util.Collections;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Optional;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
 import java.util.Set;
-import java.util.stream.Collectors;
 
 import com.fasterxml.jackson.annotation.JsonCreator;
@@ -22,33 +21,30 @@
 	/**
 	 * 
-	 * @param id    party id
+	 * @param actor party id
 	 * @param votes the {@link Vote}s that the party can agree on, if the
 	 *              condition of the Vote holds. Every {@link Vote#getActor()}
-	 *              should equal the id
+	 *              should equal the id. There may be at most 1 vote per
+	 *              {@link Bid}.
 	 */
 	@JsonCreator
-	public Votes(@JsonProperty("actor") PartyId id,
+	public Votes(@JsonProperty("actor") PartyId actor,
 			@JsonProperty("votes") Set<Vote> votes) {
-		super(id);
-		this.votes = votes;
+		super(actor);
+		this.votes = new HashSet<>(votes);
 		if (votes == null)
 			throw new NullPointerException("votes must be not null");
+
+		List<Bid> votedBids = new LinkedList<>();
 		for (Vote vote : votes) {
-			if (!vote.getActor().equals(id)) {
+			if (!vote.getActor().equals(actor))
 				throw new IllegalArgumentException("All votes must come from "
-						+ id + " but found " + vote);
-			}
+						+ actor + " but found " + vote);
+
+			Bid bid = vote.getBid();
+			if (votedBids.contains(bid))
+				throw new IllegalArgumentException(
+						"Votes contains multiple Vote's for " + bid);
+			votedBids.add(bid);
 		}
-		// check for duplicate Vote's, possibly with different powers
-		Map<Bid, Long> counts = votes.stream().map(vote -> vote.getBid())
-				.collect(Collectors.groupingBy(bid -> bid,
-						Collectors.counting()));
-		Optional<Entry<Bid, Long>> nonunique = counts.entrySet().stream()
-				.filter(entry -> entry.getValue() > 1).findAny();
-		if (nonunique.isPresent())
-			throw new IllegalArgumentException(
-					"Votes contains multiple Vote's for "
-							+ nonunique.get().getKey());
-
 	}
 
Index: /events/src/main/java/geniusweb/events/CurrentState.java
===================================================================
--- /events/src/main/java/geniusweb/events/CurrentState.java	(revision 33)
+++ /events/src/main/java/geniusweb/events/CurrentState.java	(revision 34)
@@ -20,4 +20,9 @@
  */
 public abstract class CurrentState extends ProtocolEvent {
-	// all should implement NegoState getState();
+	public CurrentState() {
+	}
+
+	public CurrentState(Long now) {
+		super(now);
+	}
 }
Index: /events/src/main/java/geniusweb/inform/OptIn.java
===================================================================
--- /events/src/main/java/geniusweb/inform/OptIn.java	(revision 33)
+++ /events/src/main/java/geniusweb/inform/OptIn.java	(revision 34)
@@ -2,9 +2,6 @@
 
 import java.util.Collections;
+import java.util.LinkedList;
 import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Optional;
-import java.util.stream.Collectors;
 
 import com.fasterxml.jackson.annotation.JsonCreator;
@@ -28,14 +25,12 @@
 		this.votes = votes;
 
-		Map<PartyId, Long> counts = votes.stream().map(vote -> vote.getActor())
-				.collect(Collectors.groupingBy(actor -> actor,
-						Collectors.counting()));
-		Optional<Entry<PartyId, Long>> nonunique = counts.entrySet().stream()
-				.filter(entry -> entry.getValue() > 1).findAny();
-		if (nonunique.isPresent())
-			throw new IllegalArgumentException(
-					"OptIn contains multiple Votes for party "
-							+ nonunique.get().getKey());
-
+		List<PartyId> partyVotes = new LinkedList<>();
+		for (Votes vote : votes) {
+			PartyId party = vote.getActor();
+			if (partyVotes.contains(party))
+				throw new IllegalArgumentException(
+						"OptIn contains multiple Votes for party " + party);
+			partyVotes.add(party);
+		}
 	}
 
Index: /events/src/main/java/geniusweb/inform/Voting.java
===================================================================
--- /events/src/main/java/geniusweb/inform/Voting.java	(revision 33)
+++ /events/src/main/java/geniusweb/inform/Voting.java	(revision 34)
@@ -27,8 +27,13 @@
 
 	/**
-	 * @return list of bids to be voted on
+	 * @return list of offers to be voted on
 	 */
+	public List<Offer> getOffers() {
+		return Collections.unmodifiableList(offers);
+	}
+
+	@Deprecated
 	public List<Offer> getBids() {
-		return Collections.unmodifiableList(offers);
+		return getOffers();
 	}
 
Index: /exampleparties/anac2019/agentgg/pom.xml
===================================================================
--- /exampleparties/anac2019/agentgg/pom.xml	(revision 33)
+++ /exampleparties/anac2019/agentgg/pom.xml	(revision 34)
@@ -6,5 +6,5 @@
 	<groupId>geniusweb.exampleparties.anac2019</groupId>
 	<artifactId>agentgg</artifactId>
-	<version>2.0.0</version> <!-- must equal ${geniusweb.version} -->
+	<version>2.0.1</version> <!-- must equal ${geniusweb.version} -->
 	<packaging>jar</packaging>
 
@@ -17,5 +17,5 @@
 		<passwd>${env.ARTIFACTORY_PASS}</passwd>
 		<jackson-2-version>2.12.3</jackson-2-version>
-		<geniusweb.version>2.0.0</geniusweb.version>
+		<geniusweb.version>2.0.1</geniusweb.version>
 	</properties>
 
@@ -58,5 +58,5 @@
 		</dependency>
 		<dependency>
-			<groupId>tudelft.utilities</groupId> 
+			<groupId>tudelft.utilities</groupId>
 			<artifactId>utilities</artifactId>
 			<version>1.1.0</version>
@@ -118,6 +118,6 @@
 		<dependency>
 			<groupId>org.mockito</groupId>
-			<artifactId>mockito-all</artifactId>
-			<version>1.9.5</version>
+			<artifactId>mockito-core</artifactId>
+			<version>3.11.2</version>
 			<scope>test</scope>
 		</dependency>
@@ -147,4 +147,8 @@
 			<id>central</id>
 			<url>https://repo1.maven.org/maven2</url>
+		</pluginRepository>
+		<pluginRepository>
+			<id>artifactory.ewi.tudelft.nl</id>
+			<url>https://artifactory.ewi.tudelft.nl/artifactory/libs-release</url>
 		</pluginRepository>
 	</pluginRepositories>
Index: /exampleparties/anac2019/winkyagent/pom.xml
===================================================================
--- /exampleparties/anac2019/winkyagent/pom.xml	(revision 33)
+++ /exampleparties/anac2019/winkyagent/pom.xml	(revision 34)
@@ -6,5 +6,5 @@
 	<groupId>geniusweb.exampleparties.anac2019</groupId>
 	<artifactId>winkyagent</artifactId>
-	<version>2.0.0</version> <!-- must equal ${geniusweb.version} -->
+	<version>2.0.1</version> <!-- must equal ${geniusweb.version} -->
 	<packaging>jar</packaging>
 
@@ -17,5 +17,5 @@
 		<passwd>${env.ARTIFACTORY_PASS}</passwd>
 		<jackson-2-version>2.12.3</jackson-2-version>
-		<geniusweb.version>2.0.0</geniusweb.version>
+		<geniusweb.version>2.0.1</geniusweb.version>
 	</properties>
 
@@ -118,6 +118,6 @@
 		<dependency>
 			<groupId>org.mockito</groupId>
-			<artifactId>mockito-all</artifactId>
-			<version>1.9.5</version>
+			<artifactId>mockito-core</artifactId>
+			<version>3.11.2</version>
 			<scope>test</scope>
 		</dependency>
@@ -146,4 +146,8 @@
 			<id>central</id>
 			<url>https://repo1.maven.org/maven2</url>
+		</pluginRepository>
+		<pluginRepository>
+			<id>artifactory.ewi.tudelft.nl</id>
+			<url>https://artifactory.ewi.tudelft.nl/artifactory/libs-release</url>
 		</pluginRepository>
 	</pluginRepositories>
Index: /exampleparties/boulware/pom.xml
===================================================================
--- /exampleparties/boulware/pom.xml	(revision 33)
+++ /exampleparties/boulware/pom.xml	(revision 34)
@@ -6,5 +6,5 @@
 	<groupId>geniusweb.exampleparties</groupId>
 	<artifactId>boulware</artifactId>
-	<version>2.0.0</version> <!-- must equal ${geniusweb.version} -->
+	<version>2.0.1</version> <!-- must equal ${geniusweb.version} -->
 	<packaging>jar</packaging>
 
@@ -17,5 +17,5 @@
 		<passwd>${env.ARTIFACTORY_PASS}</passwd>
 		<jackson-2-version>2.12.3</jackson-2-version>
-		<geniusweb.version>2.0.0</geniusweb.version>
+		<geniusweb.version>2.0.1</geniusweb.version>
 	</properties>
 
@@ -29,6 +29,4 @@
 
 	<dependencies>
-
-
 		<dependency>
 			<groupId>geniusweb.exampleparties</groupId>
@@ -54,5 +52,5 @@
 		</repository>
 	</repositories>
-
+	
 	<pluginRepositories>
 		<pluginRepository>
@@ -60,6 +58,9 @@
 			<url>https://repo1.maven.org/maven2</url>
 		</pluginRepository>
+		<pluginRepository>
+			<id>artifactory.ewi.tudelft.nl</id>
+			<url>https://artifactory.ewi.tudelft.nl/artifactory/libs-release</url>
+		</pluginRepository>
 	</pluginRepositories>
-
 
 
Index: /exampleparties/comparebids/pom.xml
===================================================================
--- /exampleparties/comparebids/pom.xml	(revision 33)
+++ /exampleparties/comparebids/pom.xml	(revision 34)
@@ -6,5 +6,5 @@
 	<groupId>geniusweb.exampleparties</groupId>
 	<artifactId>comparebids</artifactId>
-	<version>2.0.0</version> <!-- must equal ${geniusweb.version} -->
+	<version>2.0.1</version> <!-- must equal ${geniusweb.version} -->
 	<packaging>jar</packaging>
 
@@ -17,5 +17,5 @@
 		<passwd>${env.ARTIFACTORY_PASS}</passwd>
 		<jackson-2-version>2.12.3</jackson-2-version>
-		<geniusweb.version>2.0.0</geniusweb.version>
+		<geniusweb.version>2.0.1</geniusweb.version>
 	</properties>
 
@@ -29,6 +29,4 @@
 
 	<dependencies>
-
-
 		<dependency>
 			<groupId>geniusweb</groupId>
@@ -113,6 +111,6 @@
 		<dependency>
 			<groupId>org.mockito</groupId>
-			<artifactId>mockito-all</artifactId>
-			<version>1.9.5</version>
+			<artifactId>mockito-core</artifactId>
+			<version>3.11.2</version>
 			<scope>test</scope>
 		</dependency>
@@ -136,5 +134,5 @@
 		</repository>
 	</repositories>
-
+	
 	<pluginRepositories>
 		<pluginRepository>
@@ -142,7 +140,9 @@
 			<url>https://repo1.maven.org/maven2</url>
 		</pluginRepository>
+		<pluginRepository>
+			<id>artifactory.ewi.tudelft.nl</id>
+			<url>https://artifactory.ewi.tudelft.nl/artifactory/libs-release</url>
+		</pluginRepository>
 	</pluginRepositories>
-
-
 
 	<build>
Index: /exampleparties/conceder/pom.xml
===================================================================
--- /exampleparties/conceder/pom.xml	(revision 33)
+++ /exampleparties/conceder/pom.xml	(revision 34)
@@ -6,5 +6,5 @@
 	<groupId>geniusweb.exampleparties</groupId>
 	<artifactId>conceder</artifactId>
-	<version>2.0.0</version> <!-- must equal ${geniusweb.version} -->
+	<version>2.0.1</version> <!-- must equal ${geniusweb.version} -->
 	<packaging>jar</packaging>
 
@@ -17,5 +17,5 @@
 		<passwd>${env.ARTIFACTORY_PASS}</passwd>
 		<jackson-2-version>2.12.3</jackson-2-version>
-		<geniusweb.version>2.0.0</geniusweb.version>
+		<geniusweb.version>2.0.1</geniusweb.version>
 	</properties>
 
@@ -29,6 +29,4 @@
 
 	<dependencies>
-
-
 		<dependency>
 			<groupId>geniusweb.exampleparties</groupId>
@@ -54,5 +52,5 @@
 		</repository>
 	</repositories>
-
+	
 	<pluginRepositories>
 		<pluginRepository>
@@ -60,7 +58,9 @@
 			<url>https://repo1.maven.org/maven2</url>
 		</pluginRepository>
+		<pluginRepository>
+			<id>artifactory.ewi.tudelft.nl</id>
+			<url>https://artifactory.ewi.tudelft.nl/artifactory/libs-release</url>
+		</pluginRepository>
 	</pluginRepositories>
-
-
 
 	<build>
Index: /exampleparties/hardliner/pom.xml
===================================================================
--- /exampleparties/hardliner/pom.xml	(revision 33)
+++ /exampleparties/hardliner/pom.xml	(revision 34)
@@ -6,5 +6,5 @@
 	<groupId>geniusweb.exampleparties</groupId>
 	<artifactId>hardliner</artifactId>
-	<version>2.0.0</version> <!-- must equal ${geniusweb.version} -->
+	<version>2.0.1</version> <!-- must equal ${geniusweb.version} -->
 	<packaging>jar</packaging>
 
@@ -17,5 +17,5 @@
 		<passwd>${env.ARTIFACTORY_PASS}</passwd>
 		<jackson-2-version>2.12.3</jackson-2-version>
-		<geniusweb.version>2.0.0</geniusweb.version>
+		<geniusweb.version>2.0.1</geniusweb.version>
 	</properties>
 
@@ -29,6 +29,4 @@
 
 	<dependencies>
-
-
 		<dependency>
 			<groupId>geniusweb.exampleparties</groupId>
@@ -60,7 +58,9 @@
 			<url>https://repo1.maven.org/maven2</url>
 		</pluginRepository>
+		<pluginRepository>
+			<id>artifactory.ewi.tudelft.nl</id>
+			<url>https://artifactory.ewi.tudelft.nl/artifactory/libs-release</url>
+		</pluginRepository>
 	</pluginRepositories>
-
-
 
 	<build>
Index: /exampleparties/humangui/pom.xml
===================================================================
--- /exampleparties/humangui/pom.xml	(revision 33)
+++ /exampleparties/humangui/pom.xml	(revision 34)
@@ -6,5 +6,5 @@
 	<groupId>geniusweb.exampleparties</groupId>
 	<artifactId>humangui</artifactId>
-	<version>2.0.0</version> <!-- must equal ${geniusweb.version} -->
+	<version>2.0.1</version> <!-- must equal ${geniusweb.version} -->
 	<packaging>jar</packaging>
 
@@ -17,5 +17,5 @@
 		<passwd>${env.ARTIFACTORY_PASS}</passwd>
 		<jackson-2-version>2.12.3</jackson-2-version>
-		<geniusweb.version>2.0.0</geniusweb.version>
+		<geniusweb.version>2.0.1</geniusweb.version>
 	</properties>
 
@@ -29,6 +29,4 @@
 
 	<dependencies>
-
-
 		<dependency>
 			<groupId>geniusweb</groupId>
@@ -108,6 +106,6 @@
 		<dependency>
 			<groupId>org.mockito</groupId>
-			<artifactId>mockito-all</artifactId>
-			<version>1.9.5</version>
+			<artifactId>mockito-core</artifactId>
+			<version>3.11.2</version>
 			<scope>test</scope>
 		</dependency>
@@ -135,4 +133,8 @@
 			<id>central</id>
 			<url>https://repo1.maven.org/maven2</url>
+		</pluginRepository>
+		<pluginRepository>
+			<id>artifactory.ewi.tudelft.nl</id>
+			<url>https://artifactory.ewi.tudelft.nl/artifactory/libs-release</url>
 		</pluginRepository>
 	</pluginRepositories>
Index: /exampleparties/linear/pom.xml
===================================================================
--- /exampleparties/linear/pom.xml	(revision 33)
+++ /exampleparties/linear/pom.xml	(revision 34)
@@ -6,5 +6,5 @@
 	<groupId>geniusweb.exampleparties</groupId>
 	<artifactId>linear</artifactId>
-	<version>2.0.0</version> <!-- must equal ${geniusweb.version} -->
+	<version>2.0.1</version> <!-- must equal ${geniusweb.version} -->
 	<packaging>jar</packaging>
 
@@ -17,5 +17,5 @@
 		<passwd>${env.ARTIFACTORY_PASS}</passwd>
 		<jackson-2-version>2.12.3</jackson-2-version>
-		<geniusweb.version>2.0.0</geniusweb.version>
+		<geniusweb.version>2.0.1</geniusweb.version>
 	</properties>
 
@@ -29,6 +29,4 @@
 
 	<dependencies>
-
-
 		<dependency>
 			<groupId>geniusweb.exampleparties</groupId>
@@ -59,4 +57,8 @@
 			<id>central</id>
 			<url>https://repo1.maven.org/maven2</url>
+		</pluginRepository>
+		<pluginRepository>
+			<id>artifactory.ewi.tudelft.nl</id>
+			<url>https://artifactory.ewi.tudelft.nl/artifactory/libs-release</url>
 		</pluginRepository>
 	</pluginRepositories>
Index: /exampleparties/randomparty/pom.xml
===================================================================
--- /exampleparties/randomparty/pom.xml	(revision 33)
+++ /exampleparties/randomparty/pom.xml	(revision 34)
@@ -6,5 +6,5 @@
 	<groupId>geniusweb.exampleparties</groupId>
 	<artifactId>randomparty</artifactId>
-	<version>2.0.0</version> <!-- must equal ${geniusweb.version} -->
+	<version>2.0.1</version> <!-- must equal ${geniusweb.version} -->
 	<packaging>jar</packaging>
 
@@ -17,5 +17,5 @@
 		<passwd>${env.ARTIFACTORY_PASS}</passwd>
 		<jackson-2-version>2.12.3</jackson-2-version>
-		<geniusweb.version>2.0.0</geniusweb.version>
+		<geniusweb.version>2.0.1</geniusweb.version>
 	</properties>
 
@@ -113,6 +113,6 @@
 		<dependency>
 			<groupId>org.mockito</groupId>
-			<artifactId>mockito-all</artifactId>
-			<version>1.9.5</version>
+			<artifactId>mockito-core</artifactId>
+			<version>3.11.2</version>
 			<scope>test</scope>
 		</dependency>
@@ -141,4 +141,8 @@
 			<id>central</id>
 			<url>https://repo1.maven.org/maven2</url>
+		</pluginRepository>
+		<pluginRepository>
+			<id>artifactory.ewi.tudelft.nl</id>
+			<url>https://artifactory.ewi.tudelft.nl/artifactory/libs-release</url>
 		</pluginRepository>
 	</pluginRepositories>
Index: /exampleparties/randomparty/src/main/java/geniusweb/exampleparties/randomparty/RandomParty.java
===================================================================
--- /exampleparties/randomparty/src/main/java/geniusweb/exampleparties/randomparty/RandomParty.java	(revision 33)
+++ /exampleparties/randomparty/src/main/java/geniusweb/exampleparties/randomparty/RandomParty.java	(revision 34)
@@ -93,6 +93,6 @@
 					getConnection().send(new LearningDone(me));
 				} else {
-					this.profileint = ProfileConnectionFactory.create(
-							sett.getProfile().getURI(), getReporter());
+					this.profileint = ProfileConnectionFactory
+							.create(sett.getProfile().getURI(), getReporter());
 				}
 			} else if (info instanceof ActionDone) {
@@ -242,5 +242,5 @@
 				: Integer.MAX_VALUE;
 
-		Set<Vote> votes = voting.getBids().stream().distinct()
+		Set<Vote> votes = voting.getOffers().stream().distinct()
 				.filter(offer -> isGood(offer.getBid()))
 				.map(offer -> new Vote(me, offer.getBid(), minpower, maxpower))
@@ -262,5 +262,5 @@
 				: Integer.MAX_VALUE;
 
-		List<Bid> goodbids = voting.getBids().stream().distinct()
+		List<Bid> goodbids = voting.getOffers().stream().distinct()
 				.filter(offer -> isGood(offer.getBid()))
 				.map(offer -> offer.getBid()).collect(Collectors.toList());
Index: /exampleparties/randompartypy/pom.xml
===================================================================
--- /exampleparties/randompartypy/pom.xml	(revision 33)
+++ /exampleparties/randompartypy/pom.xml	(revision 34)
@@ -6,5 +6,5 @@
 	<groupId>geniusweb.exampleparties</groupId>
 	<artifactId>randompyparty</artifactId>
-	<version>2.0.0</version> <!-- must equal ${geniusweb.version} -->
+	<version>2.0.1</version> <!-- must equal ${geniusweb.version} -->
 	<packaging>jar</packaging>
 
@@ -17,5 +17,5 @@
 		<passwd>${env.ARTIFACTORY_PASS}</passwd>
 		<jackson-2-version>2.12.3</jackson-2-version>
-		<geniusweb.version>2.0.0</geniusweb.version>
+		<geniusweb.version>2.0.1</geniusweb.version>
 	</properties>
 
@@ -105,6 +105,6 @@
 		<dependency>
 			<groupId>org.mockito</groupId>
-			<artifactId>mockito-all</artifactId>
-			<version>1.9.5</version>
+			<artifactId>mockito-core</artifactId>
+			<version>3.11.2</version>
 			<scope>test</scope>
 		</dependency>
@@ -133,6 +133,9 @@
 			<url>https://repo1.maven.org/maven2</url>
 		</pluginRepository>
+		<pluginRepository>
+			<id>artifactory.ewi.tudelft.nl</id>
+			<url>https://artifactory.ewi.tudelft.nl/artifactory/libs-release</url>
+		</pluginRepository>
 	</pluginRepositories>
-
 
 
Index: /exampleparties/simpleboa/pom.xml
===================================================================
--- /exampleparties/simpleboa/pom.xml	(revision 33)
+++ /exampleparties/simpleboa/pom.xml	(revision 34)
@@ -6,5 +6,5 @@
 	<groupId>geniusweb.exampleparties</groupId>
 	<artifactId>simpleboaparty</artifactId>
-	<version>2.0.0</version> <!-- must equal ${geniusweb.version} -->
+	<version>2.0.1</version> <!-- must equal ${geniusweb.version} -->
 	<packaging>jar</packaging>
 
@@ -17,5 +17,5 @@
 		<passwd>${env.ARTIFACTORY_PASS}</passwd>
 		<jackson-2-version>2.12.3</jackson-2-version>
-		<geniusweb.version>2.0.0</geniusweb.version>
+		<geniusweb.version>2.0.1</geniusweb.version>
 	</properties>
 
@@ -51,6 +51,6 @@
 		<dependency>
 			<groupId>org.mockito</groupId>
-			<artifactId>mockito-all</artifactId>
-			<version>1.9.5</version>
+			<artifactId>mockito-core</artifactId>
+			<version>3.11.2</version>
 			<scope>test</scope>
 		</dependency>
@@ -79,4 +79,8 @@
 			<id>central</id>
 			<url>https://repo1.maven.org/maven2</url>
+		</pluginRepository>
+		<pluginRepository>
+			<id>artifactory.ewi.tudelft.nl</id>
+			<url>https://artifactory.ewi.tudelft.nl/artifactory/libs-release</url>
 		</pluginRepository>
 	</pluginRepositories>
Index: /exampleparties/simpleshaop/pom.xml
===================================================================
--- /exampleparties/simpleshaop/pom.xml	(revision 33)
+++ /exampleparties/simpleshaop/pom.xml	(revision 34)
@@ -6,5 +6,5 @@
 	<groupId>geniusweb.exampleparties</groupId>
 	<artifactId>simpleshaop</artifactId>
-	<version>2.0.0</version> <!-- must equal ${geniusweb.version} -->
+	<version>2.0.1</version> <!-- must equal ${geniusweb.version} -->
 	<packaging>jar</packaging>
 
@@ -17,5 +17,5 @@
 		<passwd>${env.ARTIFACTORY_PASS}</passwd>
 		<jackson-2-version>2.12.3</jackson-2-version>
-		<geniusweb.version>2.0.0</geniusweb.version>
+		<geniusweb.version>2.0.1</geniusweb.version>
 	</properties>
 
@@ -29,6 +29,4 @@
 
 	<dependencies>
-
-
 		<dependency>
 			<groupId>geniusweb</groupId>
@@ -113,6 +111,6 @@
 		<dependency>
 			<groupId>org.mockito</groupId>
-			<artifactId>mockito-all</artifactId>
-			<version>1.9.5</version>
+			<artifactId>mockito-core</artifactId>
+			<version>3.11.2</version>
 			<scope>test</scope>
 		</dependency>
@@ -141,4 +139,8 @@
 			<id>central</id>
 			<url>https://repo1.maven.org/maven2</url>
+		</pluginRepository>
+		<pluginRepository>
+			<id>artifactory.ewi.tudelft.nl</id>
+			<url>https://artifactory.ewi.tudelft.nl/artifactory/libs-release</url>
 		</pluginRepository>
 	</pluginRepositories>
Index: /exampleparties/timedependentparty/pom.xml
===================================================================
--- /exampleparties/timedependentparty/pom.xml	(revision 33)
+++ /exampleparties/timedependentparty/pom.xml	(revision 34)
@@ -6,5 +6,5 @@
 	<groupId>geniusweb.exampleparties</groupId>
 	<artifactId>timedependentparty</artifactId>
-	<version>2.0.0</version> <!-- must equal ${geniusweb.version} -->
+	<version>2.0.1</version> <!-- must equal ${geniusweb.version} -->
 	<packaging>jar</packaging>
 
@@ -17,5 +17,5 @@
 		<passwd>${env.ARTIFACTORY_PASS}</passwd>
 		<jackson-2-version>2.12.3</jackson-2-version>
-		<geniusweb.version>2.0.0</geniusweb.version>
+		<geniusweb.version>2.0.1</geniusweb.version>
 	</properties>
 
@@ -29,6 +29,4 @@
 
 	<dependencies>
-
-
 		<dependency>
 			<groupId>geniusweb</groupId>
@@ -113,6 +111,6 @@
 		<dependency>
 			<groupId>org.mockito</groupId>
-			<artifactId>mockito-all</artifactId>
-			<version>1.9.5</version>
+			<artifactId>mockito-core</artifactId>
+			<version>3.11.2</version>
 			<scope>test</scope>
 		</dependency>
@@ -141,4 +139,8 @@
 			<id>central</id>
 			<url>https://repo1.maven.org/maven2</url>
+		</pluginRepository>
+		<pluginRepository>
+			<id>artifactory.ewi.tudelft.nl</id>
+			<url>https://artifactory.ewi.tudelft.nl/artifactory/libs-release</url>
 		</pluginRepository>
 	</pluginRepositories>
Index: /exampleparties/timedependentparty/src/main/java/geniusweb/exampleparties/timedependentparty/TimeDependentParty.java
===================================================================
--- /exampleparties/timedependentparty/src/main/java/geniusweb/exampleparties/timedependentparty/TimeDependentParty.java	(revision 33)
+++ /exampleparties/timedependentparty/src/main/java/geniusweb/exampleparties/timedependentparty/TimeDependentParty.java	(revision 34)
@@ -298,5 +298,5 @@
 				: Integer.MAX_VALUE;
 
-		Set<Vote> votes = voting.getBids().stream().distinct()
+		Set<Vote> votes = voting.getOffers().stream().distinct()
 				.filter(offer -> isGood(offer.getBid()))
 				.map(offer -> new Vote(me, offer.getBid(), minpower, maxpower))
Index: /ip/pom.xml
===================================================================
--- /ip/pom.xml	(revision 33)
+++ /ip/pom.xml	(revision 34)
@@ -6,5 +6,5 @@
 	<groupId>geniusweb</groupId>
 	<artifactId>ip</artifactId>
-	<version>2.0.0</version> <!-- must equal ${geniusweb.version} -->
+	<version>2.0.1</version> <!-- must equal ${geniusweb.version} -->
 	<packaging>jar</packaging>
 
@@ -17,5 +17,5 @@
 		<passwd>${env.ARTIFACTORY_PASS}</passwd>
 		<jackson-2-version>2.12.3</jackson-2-version>
-		<geniusweb.version>2.0.0</geniusweb.version>
+		<geniusweb.version>2.0.1</geniusweb.version>
 	</properties>
 
@@ -58,4 +58,8 @@
 			<id>central</id>
 			<url>https://repo1.maven.org/maven2</url>
+		</pluginRepository>
+		<pluginRepository>
+			<id>artifactory.ewi.tudelft.nl</id>
+			<url>https://artifactory.ewi.tudelft.nl/artifactory/libs-release</url>
 		</pluginRepository>
 	</pluginRepositories>
Index: /issuevalue/pom.xml
===================================================================
--- /issuevalue/pom.xml	(revision 33)
+++ /issuevalue/pom.xml	(revision 34)
@@ -6,5 +6,5 @@
 	<groupId>geniusweb</groupId>
 	<artifactId>issuevalue</artifactId>
-	<version>2.0.0</version> <!-- must equal ${geniusweb.version} -->
+	<version>2.0.1</version> <!-- must equal ${geniusweb.version} -->
 	<packaging>jar</packaging>
 
@@ -17,5 +17,5 @@
 		<passwd>${env.ARTIFACTORY_PASS}</passwd>
 		<jackson-2-version>2.12.3</jackson-2-version>
-		<geniusweb.version>2.0.0</geniusweb.version>
+		<geniusweb.version>2.0.1</geniusweb.version>
 	</properties>
 
@@ -78,6 +78,6 @@
 		<dependency>
 			<groupId>org.mockito</groupId>
-			<artifactId>mockito-all</artifactId>
-			<version>1.9.5</version>
+			<artifactId>mockito-core</artifactId>
+			<version>3.11.2</version>
 			<scope>test</scope>
 		</dependency>
@@ -113,4 +113,8 @@
 			<id>central</id>
 			<url>https://repo1.maven.org/maven2</url>
+		</pluginRepository>
+		<pluginRepository>
+			<id>artifactory.ewi.tudelft.nl</id>
+			<url>https://artifactory.ewi.tudelft.nl/artifactory/libs-release</url>
 		</pluginRepository>
 	</pluginRepositories>
Index: /issuevalue/src/test/java/geniusweb/issuevalue/DiscreteValueSetTest.java
===================================================================
--- /issuevalue/src/test/java/geniusweb/issuevalue/DiscreteValueSetTest.java	(revision 33)
+++ /issuevalue/src/test/java/geniusweb/issuevalue/DiscreteValueSetTest.java	(revision 34)
@@ -39,8 +39,8 @@
 	// parsed as discrete values.
 	private static final String discretenumbers = "{\"values\":[\"0\",\"1\"]}";
+	private static final ObjectMapper jackson = new ObjectMapper();
 
 	@Test
 	public void testSerialize() throws JsonProcessingException {
-		ObjectMapper jackson = new ObjectMapper();
 
 		String json = jackson.writeValueAsString(set);
@@ -52,5 +52,4 @@
 	public void testDeserialize()
 			throws JsonParseException, JsonMappingException, IOException {
-		ObjectMapper jackson = new ObjectMapper();
 		DiscreteValueSet p = jackson.readValue(asString,
 				DiscreteValueSet.class);
@@ -62,5 +61,4 @@
 	public void testDeserializeNumberValues()
 			throws JsonParseException, JsonMappingException, IOException {
-		ObjectMapper jackson = new ObjectMapper();
 		DiscreteValueSet p = jackson.readValue(discretenumbers,
 				DiscreteValueSet.class);
Index: /issuevalue/src/test/java/geniusweb/issuevalue/DiscreteValueTest.java
===================================================================
--- /issuevalue/src/test/java/geniusweb/issuevalue/DiscreteValueTest.java	(revision 33)
+++ /issuevalue/src/test/java/geniusweb/issuevalue/DiscreteValueTest.java	(revision 34)
@@ -13,17 +13,15 @@
 import com.fasterxml.jackson.databind.ObjectMapper;
 
-import geniusweb.issuevalue.DiscreteValue;
-import geniusweb.issuevalue.Value;
 import tudelft.utilities.junit.GeneralTests;
 
 public class DiscreteValueTest extends GeneralTests<DiscreteValue> {
-	private DiscreteValue value = new DiscreteValue("a");
-	private DiscreteValue value1 = new DiscreteValue("a");
-	private DiscreteValue valueb = new DiscreteValue("b");
-	private String serialized = "\"a\"";
+	private final DiscreteValue value = new DiscreteValue("a");
+	private final DiscreteValue value1 = new DiscreteValue("a");
+	private final DiscreteValue valueb = new DiscreteValue("b");
+	private final String serialized = "\"a\"";
+	private static final ObjectMapper jackson = new ObjectMapper();
 
 	@Test
 	public void testSerialize() throws JsonProcessingException {
-		ObjectMapper jackson = new ObjectMapper();
 		assertEquals(serialized, jackson.writeValueAsString(value));
 	}
@@ -31,5 +29,4 @@
 	@Test
 	public void testDeserialize() throws IOException {
-		ObjectMapper jackson = new ObjectMapper();
 		assertEquals(value, jackson.readValue(serialized, DiscreteValue.class));
 	}
@@ -37,5 +34,4 @@
 	@Test
 	public void testDeserializeFromValue() throws IOException {
-		ObjectMapper jackson = new ObjectMapper();
 		assertEquals(value, jackson.readValue(serialized, Value.class));
 	}
@@ -43,5 +39,4 @@
 	@Override
 	public List<List<DiscreteValue>> getGeneralTestData() {
-
 		List<List<DiscreteValue>> list = new LinkedList<>();
 		list.add(Arrays.asList(value, value1));
Index: /issuevalue/src/test/java/geniusweb/issuevalue/NumberValueTest.java
===================================================================
--- /issuevalue/src/test/java/geniusweb/issuevalue/NumberValueTest.java	(revision 33)
+++ /issuevalue/src/test/java/geniusweb/issuevalue/NumberValueTest.java	(revision 34)
@@ -7,5 +7,4 @@
 import java.util.ArrayList;
 import java.util.Arrays;
-import java.util.LinkedList;
 import java.util.List;
 
@@ -20,18 +19,17 @@
 
 public class NumberValueTest extends GeneralTests<NumberValue> {
-	private NumberValue value = new NumberValue("12.31");
-	private NumberValue value1 = new NumberValue("12.31");
-	private NumberValue valueb = new NumberValue("12.310000000000000001");
-	private String serialized = "12.31";
+	private final NumberValue value = new NumberValue("12.31");
+	private final NumberValue value1 = new NumberValue("12.31");
+	private final NumberValue valueb = new NumberValue("12.310000000000000001");
+	private final String serialized = "12.31";
 
-	private String bigserialized = "8748703924870439218876954320948372058";
-	private NumberValue bigvalue = new NumberValue(bigserialized);
+	private final String bigserialized = "8748703924870439218876954320948372058";
+	private final NumberValue bigvalue = new NumberValue(bigserialized);
+	private static final ObjectMapper jackson = new ObjectMapper();
 
 	@Override
 	public List<List<NumberValue>> getGeneralTestData() {
-		List<List<NumberValue>> list = new LinkedList<>();
-		list.add(Arrays.asList(value, value1));
-		list.add(Arrays.asList(valueb));
-		return list;
+		return Arrays.asList(Arrays.asList(value, value1),
+				Arrays.asList(valueb));
 	}
 
@@ -43,5 +41,4 @@
 	@Test
 	public void testSerialize() throws JsonProcessingException {
-		ObjectMapper jackson = new ObjectMapper();
 		assertEquals(serialized, jackson.writeValueAsString(value));
 	}
@@ -49,5 +46,4 @@
 	@Test
 	public void testDeserialize() throws IOException {
-		ObjectMapper jackson = new ObjectMapper();
 		assertEquals(value, jackson.readValue(serialized, NumberValue.class));
 
@@ -56,5 +52,4 @@
 	@Test
 	public void testDeserializeFromValue() throws IOException {
-		ObjectMapper jackson = new ObjectMapper();
 		assertEquals(value, jackson.readValue(serialized, Value.class));
 
@@ -63,5 +58,4 @@
 	@Test
 	public void testBigSerialize() throws JsonProcessingException {
-		ObjectMapper jackson = new ObjectMapper();
 		assertEquals(bigserialized, jackson.writeValueAsString(bigvalue));
 	}
@@ -69,5 +63,4 @@
 	@Test
 	public void testBigDeserialize() throws IOException {
-		ObjectMapper jackson = new ObjectMapper();
 		assertEquals(bigvalue,
 				jackson.readValue(bigserialized, NumberValue.class));
@@ -77,5 +70,4 @@
 	@Test
 	public void testSerializeShorts() throws IOException {
-		ObjectMapper jackson = new ObjectMapper();
 		System.out.println(
 				jackson.writeValueAsString(new short[] { 1, 2, 3, 4, 5 }));
@@ -85,5 +77,4 @@
 	@Test
 	public void testDeserializeShorts() throws IOException {
-		ObjectMapper jackson = new ObjectMapper();
 		@SuppressWarnings("unchecked")
 		ArrayList<Integer> list = jackson.readValue("[1,2,3,4,5]",
@@ -96,5 +87,4 @@
 	@Test
 	public void testDeserializeMix() throws IOException {
-		ObjectMapper jackson = new ObjectMapper();
 		@SuppressWarnings("unchecked")
 		ArrayList<Object> list = jackson.readValue("[\"short\",1,2,3,4,5]",
@@ -112,5 +102,4 @@
 	public void testDeserializePlainNumber()
 			throws JsonParseException, JsonMappingException, IOException {
-		ObjectMapper jackson = new ObjectMapper();
 		String valstr = "483958743698732691487326987569213874694328974329874328947320984372498327493827432987231874681273648127";
 		BigDecimal val = jackson.readValue(valstr, BigDecimal.class);
@@ -120,5 +109,4 @@
 	@Test
 	public void testNumberBlab() throws IOException {
-		ObjectMapper jackson = new ObjectMapper();
 		// jackson.enable(DeserializationFeature.USE_BIG_DECIMAL_FOR_FLOATS);
 		assertEquals(value, jackson.readValue("12.31", Value.class));
@@ -129,5 +117,4 @@
 	public void testDeserializeScientificNotation()
 			throws JsonParseException, JsonMappingException, IOException {
-		ObjectMapper jackson = new ObjectMapper();
 		String valstr = "9E+2";
 		Value val = jackson.readValue(valstr, Value.class);
Index: /opponentmodel/pom.xml
===================================================================
--- /opponentmodel/pom.xml	(revision 33)
+++ /opponentmodel/pom.xml	(revision 34)
@@ -6,5 +6,5 @@
 	<groupId>geniusweb</groupId>
 	<artifactId>opponentmodel</artifactId>
-	<version>2.0.0</version> <!-- must equal ${geniusweb.version} -->
+	<version>2.0.1</version> <!-- must equal ${geniusweb.version} -->
 	<packaging>jar</packaging>
 
@@ -17,5 +17,5 @@
 		<passwd>${env.ARTIFACTORY_PASS}</passwd>
 		<jackson-2-version>2.12.3</jackson-2-version>
-		<geniusweb.version>2.0.0</geniusweb.version>
+		<geniusweb.version>2.0.1</geniusweb.version>
 	</properties>
 
@@ -111,6 +111,6 @@
 		<dependency>
 			<groupId>org.mockito</groupId>
-			<artifactId>mockito-all</artifactId>
-			<version>1.9.5</version>
+			<artifactId>mockito-core</artifactId>
+			<version>3.11.2</version>
 			<scope>test</scope>
 		</dependency>
@@ -134,4 +134,8 @@
 			<id>central</id>
 			<url>https://repo1.maven.org/maven2</url>
+		</pluginRepository>
+		<pluginRepository>
+			<id>artifactory.ewi.tudelft.nl</id>
+			<url>https://artifactory.ewi.tudelft.nl/artifactory/libs-release</url>
 		</pluginRepository>
 	</pluginRepositories>
Index: /opponentmodel/src/main/java/geniusweb/opponentmodel/FrequencyOpponentModel.java
===================================================================
--- /opponentmodel/src/main/java/geniusweb/opponentmodel/FrequencyOpponentModel.java	(revision 33)
+++ /opponentmodel/src/main/java/geniusweb/opponentmodel/FrequencyOpponentModel.java	(revision 34)
@@ -16,4 +16,5 @@
 import geniusweb.profile.utilityspace.UtilitySpace;
 import geniusweb.progress.Progress;
+import geniusweb.references.Parameters;
 
 /**
@@ -31,6 +32,4 @@
 
 	private static final int DECIMALS = 4; // accuracy of our computations.
-	private static int serial = 1; // counter for auto name generation
-
 	private final Domain domain;
 	private final Map<String, Map<Value, Integer>> bidFrequencies;
@@ -71,13 +70,13 @@
 
 	@Override
-	public FrequencyOpponentModel with(Domain domain, Bid resBid) {
-		if (domain == null) {
+	public FrequencyOpponentModel with(Domain newDomain, Bid newResBid) {
+		if (newDomain == null) {
 			throw new NullPointerException("domain is not initialized");
 		}
 		// FIXME merge already available frequencies?
-		return new FrequencyOpponentModel(domain,
-				domain.getIssues().stream().collect(
+		return new FrequencyOpponentModel(newDomain,
+				newDomain.getIssues().stream().collect(
 						Collectors.toMap(iss -> iss, iss -> new HashMap<>())),
-				BigDecimal.ZERO, resBid);
+				BigDecimal.ZERO, newResBid);
 	}
 
@@ -106,5 +105,5 @@
 			throw new IllegalStateException("domain is not initialized");
 		}
-		return "FreqOppModel" + (serial++) + "For" + domain;
+		return "FreqOppModel" + this.hashCode() + "For" + domain;
 	}
 
@@ -158,4 +157,9 @@
 	}
 
+	@Override
+	public OpponentModel with(Parameters parameters) {
+		return this; // ignore parameters
+	}
+
 	/**
 	 * 
Index: /opponentmodel/src/main/java/geniusweb/opponentmodel/OpponentModel.java
===================================================================
--- /opponentmodel/src/main/java/geniusweb/opponentmodel/OpponentModel.java	(revision 33)
+++ /opponentmodel/src/main/java/geniusweb/opponentmodel/OpponentModel.java	(revision 34)
@@ -7,4 +7,5 @@
 import geniusweb.profile.utilityspace.UtilitySpace;
 import geniusweb.progress.Progress;
+import geniusweb.references.Parameters;
 
 /**
@@ -24,6 +25,6 @@
 	/**
 	 * Initializes the model. This function must be called first after
-	 * constructing an instance. It can also be called later, if there is a
-	 * change in the domain or resBid.
+	 * constructing an instance. It can also be called again later, if there is
+	 * a change in the domain or resBid.
 	 * <p>
 	 * This late-initialization is to support boa models that have late
@@ -37,4 +38,13 @@
 	 */
 	OpponentModel with(Domain domain, Bid resBid);
+
+	/**
+	 * 
+	 * @param parameters Opponent-model specific {@link Parameters}
+	 * @return an updated OpponentMode, with parameters used. Each
+	 *         implementation of OpponentModel is free to use parameters as it
+	 *         likes. For instance to set learning speed.
+	 */
+	OpponentModel with(Parameters parameters);
 
 	/**
Index: /opponentmodel/src/main/java/geniusweb/opponentmodel/bayesian/BayesianOpponentModel.java
===================================================================
--- /opponentmodel/src/main/java/geniusweb/opponentmodel/bayesian/BayesianOpponentModel.java	(revision 34)
+++ /opponentmodel/src/main/java/geniusweb/opponentmodel/bayesian/BayesianOpponentModel.java	(revision 34)
@@ -0,0 +1,554 @@
+package geniusweb.opponentmodel.bayesian;
+
+import java.math.BigDecimal;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+import geniusweb.actions.Action;
+import geniusweb.actions.Offer;
+import geniusweb.issuevalue.Bid;
+import geniusweb.issuevalue.DiscreteValue;
+import geniusweb.issuevalue.DiscreteValueSet;
+import geniusweb.issuevalue.Domain;
+import geniusweb.issuevalue.NumberValueSet;
+import geniusweb.issuevalue.Value;
+import geniusweb.issuevalue.ValueSet;
+import geniusweb.opponentmodel.FrequencyOpponentModel;
+import geniusweb.opponentmodel.OpponentModel;
+import geniusweb.profile.utilityspace.DiscreteValueSetUtilities;
+import geniusweb.profile.utilityspace.UtilitySpace;
+import geniusweb.profile.utilityspace.ValueSetUtilities;
+import geniusweb.progress.Progress;
+import geniusweb.references.Parameters;
+import tudelft.utilities.immutablelist.Range;
+
+/**
+ * <b>Warning</b>. This model is available for research and testing, and as
+ * example. Use of this is not recommended. We recommend using the
+ * {@link FrequencyOpponentModel} instead.
+ * <p>
+ * Implementation of the Bayesian Opponent Model. This model uses a set of
+ * {@link TriangleValueSetUtilities} (several for each issue) as hypotheses.
+ * Each hypothesis has a probability. Bayesian inference is used with each
+ * received bids to update these probabilities.
+ * <p>
+ * See: Opponent Modelling in Automated Multi-Issue Negotiation Using Bayesian
+ * Learning, Koen Hindriks, Dmytro Tykhonov, Proc. of 7th Int. Conf. on
+ * Autonomous Agentsand Multiagent Systems (AAMAS 2008), Padgham, Parkes,
+ * Müller and Parsons (eds.), May, 12-16., 2008, Estoril, Portugal, pp.
+ * 331-338.
+ * <h2>Parameters</h2>
+ * <ul>
+ * <li>sigma: see {@link #getSigma()}
+ * <li>decay: see {@link #getDecay()}
+ * </ul>
+ */
+public class BayesianOpponentModel implements UtilitySpace, OpponentModel {
+	private static final double DEFAULT_DECAY = 0.003;
+	private static final double DEFAULT_SIGMA = 0.25;
+	private static final int NWEIGHTS = 11; /* MAGIC NR OF WEIGHTS. */
+	private static final int NEVALUATORS = 6; // magic #numbervaluesetevaluators
+
+	/** Hypotheses are normalized PER ISSUE, so not in total. */
+	private final Map<String, List<WeightHypothesis>> weightHypoMap = new HashMap<>();
+	private final Map<String, List<EvaluatorHypothesis>> evaluatorHypoMap = new HashMap<>();
+	private final List<Bid> bidHistory = new LinkedList<>();
+	private final Domain domain;
+	private final double sigma;
+	private final double decay;
+	/**
+	 * Cached per-issue weights, computed from {@link #weightHypoMap} and scaled
+	 * to sum to 1
+	 */
+	private final transient Map<String, Double> normalizedWeightsMap = new HashMap<>();
+
+	/**
+	 * Empty constructor. If used, {@link #with(Domain, Bid)} must be called
+	 * before further use
+	 */
+	public BayesianOpponentModel() {
+		domain = null;
+		sigma = DEFAULT_SIGMA;
+		decay = DEFAULT_DECAY;
+	}
+
+	/**
+	 * Creates initial settings with default settings (sigma=0.25, decay=0.003).
+	 * 
+	 * @param domain the {@link Domain}
+	 */
+	public BayesianOpponentModel(final Domain domain) {
+		this(domain, initialEvaluators(domain), initialWeightHyps(domain),
+				Collections.emptyList(), DEFAULT_SIGMA, DEFAULT_DECAY);
+	}
+
+	/**
+	 * 
+	 * @param dom            the {@link Domain}
+	 * @param evaluatorHypos the hashmap with the evaluator hypotheses for all
+	 *                       issues. For each issue, the sum of the hypothesis P
+	 *                       values must be =1
+	 * @param weightHypos    the hashmap with the weight hypotheses for all
+	 *                       issues. For each issue, the sum of the hypothesis P
+	 *                       values must be =1
+	 * @param history        List with all previous bids, first bid is the
+	 *                       oldest. Used to check if bid is repeated and to
+	 *                       estimate bid utility
+	 * @param sigma          The spread σ of the conditional distribution. See
+	 *                       {@link #getSigma()} and {@link #DEFAULT_SIGMA}.
+	 *                       Must be in [0.00001, 100000] but these extremes
+	 *                       seem unusable in practice.
+	 * @param decay          The expected concession rate of the opponent
+	 *                       against time. see {@link #getDecay()} and
+	 *                       {@link #DEFAULT_DECAY}. Must be in [0,1] where 0
+	 *                       means no concession and 1 full concession in 1
+	 *                       timestep.
+	 */
+	public BayesianOpponentModel(final Domain dom,
+			final Map<String, List<EvaluatorHypothesis>> evaluatorHypos,
+			final Map<String, List<WeightHypothesis>> weightHypos,
+			final List<Bid> history, double sigma, double decay) {
+		if (dom == null || evaluatorHypos == null || weightHypos == null
+				|| history == null)
+			throw new IllegalArgumentException("Parameters must not be null");
+		checkNormalized(evaluatorHypos);
+		checkNormalized(weightHypos);
+		if (sigma < 0.00001 || sigma > 100000)
+			throw new IllegalArgumentException(
+					"sigma must be in [0.00001, 100000], got " + sigma);
+		if (decay < 0 || decay > 1)
+			throw new IllegalArgumentException(
+					"decay must be in [0,1] but got " + decay);
+
+		this.domain = dom;
+		this.bidHistory.addAll(history);
+		this.weightHypoMap.putAll(weightHypos);
+		this.evaluatorHypoMap.putAll(evaluatorHypos);
+		this.normalizedWeightsMap.putAll(getNormalizedWeights(weightHypos));
+		this.sigma = sigma;
+		this.decay = decay;
+	}
+
+	@Override
+	public String getName() {
+		if (domain == null)
+			throw new IllegalStateException("model is not initialized");
+
+		return "FreqOppModel" + this.hashCode() + "For" + domain;
+	}
+
+	@Override
+	public Domain getDomain() {
+		return domain;
+	}
+
+	@Override
+	public Bid getReservationBid() {
+		return null;
+	}
+
+	@Override
+	public BayesianOpponentModel with(Domain newDomain, Bid newResBid) {
+		if (newDomain == null) {
+			throw new NullPointerException("domain must not be null");
+		}
+		return new BayesianOpponentModel(newDomain);
+	}
+
+	@Override
+	public BayesianOpponentModel with(final Action action,
+			final Progress progress) {
+		if (!(action instanceof Offer))
+			return this;
+		Bid bid = ((Offer) action).getBid();
+		if (bidHistory.contains(bid))
+			return this;
+		List<Bid> newHistory = new LinkedList<>(bidHistory);
+		newHistory.add(bid);
+
+		Map<String, List<EvaluatorHypothesis>> newEvaluatorHyps = updatedEvaluationFns(
+				bid);
+		Map<String, List<WeightHypothesis>> newWeightHypos = weightHypoMap;
+		if (!(bidHistory.isEmpty()))
+			newWeightHypos = updatedWeights(bid);
+
+		return new BayesianOpponentModel(domain, newEvaluatorHyps,
+				newWeightHypos, newHistory, sigma, decay);
+	}
+
+	@Override
+	public BigDecimal getUtility(final Bid bid) {
+		return BigDecimal.valueOf(getPartialUtility(bid, null));
+	}
+
+	@Override
+	public int hashCode() {
+		final int prime = 31;
+		int result = 1;
+		result = prime * result
+				+ ((bidHistory == null) ? 0 : bidHistory.hashCode());
+		result = prime * result + ((domain == null) ? 0 : domain.hashCode());
+		result = prime * result + ((evaluatorHypoMap == null) ? 0
+				: evaluatorHypoMap.hashCode());
+		result = prime * result
+				+ ((weightHypoMap == null) ? 0 : weightHypoMap.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;
+		BayesianOpponentModel other = (BayesianOpponentModel) obj;
+		if (bidHistory == null) {
+			if (other.bidHistory != null)
+				return false;
+		} else if (!bidHistory.equals(other.bidHistory))
+			return false;
+		if (domain == null) {
+			if (other.domain != null)
+				return false;
+		} else if (!domain.equals(other.domain))
+			return false;
+		if (evaluatorHypoMap == null) {
+			if (other.evaluatorHypoMap != null)
+				return false;
+		} else if (!evaluatorHypoMap.equals(other.evaluatorHypoMap))
+			return false;
+		if (weightHypoMap == null) {
+			if (other.weightHypoMap != null)
+				return false;
+		} else if (!weightHypoMap.equals(other.weightHypoMap))
+			return false;
+		return true;
+	}
+
+	@Override
+	public String toString() {
+		return "BayesianOpponentModel[" + domain + "," + evaluatorHypoMap + ","
+				+ weightHypoMap + "]";
+	}
+
+	@Override
+	public OpponentModel with(Parameters parameters) {
+		double newsigma = parameters.getDouble("sigma", DEFAULT_SIGMA, 0.00001,
+				100000d);
+		double newdecay = parameters.getDouble("decay", DEFAULT_DECAY, 0d, 1d);
+		return new BayesianOpponentModel(domain, evaluatorHypoMap,
+				weightHypoMap, bidHistory, newsigma, newdecay);
+	}
+
+	/**
+	 * 
+	 * @return map with the estimated weights (values) of all issues (keys). The
+	 *         weights sum approximately to 1 (there may be rounding errors
+	 *         here).
+	 */
+	public Map<String, Double> getWeights() {
+		return Collections.unmodifiableMap(normalizedWeightsMap);
+	}
+
+	/**
+	 * 
+	 * @return list with {@link Bid}s received so far. Duplicates are excluded.
+	 */
+	public List<Bid> getBidHistory() {
+		return Collections.unmodifiableList(bidHistory);
+	}
+
+	/**
+	 * 
+	 * @return The spread σ of the conditional distribution. This defines the
+	 *         certainty of the agent about its opponent’s negotiation tactics.
+	 *         If an agent is certain about the utility of an opponent’s bid bt
+	 *         then σ can be set to a low value. A higher level of certainty
+	 *         increases the learning speed, since hypotheses predicting an
+	 *         incorrect utility value of a bid in that case would get assigned
+	 *         an increasingly lower probability, and vice versa. Overestimating
+	 *         the level of certainty, however, may lead to incorrect results,
+	 *         and some care should to be taken to assign the right value to σ.
+	 *         Value 0.25 is recommended. Must be in [0.00001, 100000] but these
+	 *         extremes seem unusable in practice.
+	 */
+	public double getSigma() {
+		return sigma;
+	}
+
+	/**
+	 * @return the decay value which is the expected concession rate of the
+	 *         opponent against time.. We use linear functions to estimate the
+	 *         predicted utility value: u’(bt) = 1- decay·t. This assumption
+	 *         allows us to compute the conditional probability P(bt|hj)
+	 *         representing the probability of a bid bt at time t.
+	 */
+	public double getDecay() {
+		return decay;
+	}
+
+	/*************** private *****************/
+	/**
+	 * @return initial weight hypotheses for each issue. weights are set to
+	 *         linearly increase from 0 for issue 1 to 1 for last issue.
+	 */
+	private static Map<String, List<WeightHypothesis>> initialWeightHyps(
+			final Domain domain) {
+
+		List<WeightHypothesis> WeightHyps = new ArrayList<>();
+		for (int j = 0; j < NWEIGHTS; j++) {
+			double weight = (double) j / (NWEIGHTS - 1);
+			WeightHypothesis lHyp = new WeightHypothesis(weight,
+					Math.exp(-0.4 * j));
+			WeightHyps.add(lHyp);
+		}
+		final List<WeightHypothesis> normalizedW = normalize(WeightHyps);
+
+		return domain.getIssues().stream()
+				.collect(Collectors.toMap(is -> is, is -> normalizedW));
+	}
+
+	/**
+	 * @param domain the {@link Domain}
+	 * @return the initial evaluators for the domain. This amounts to a set of
+	 *         triangle-shaped utility functions for each issue.
+	 */
+	protected static Map<String, List<EvaluatorHypothesis>> initialEvaluators(
+			final Domain domain) {
+		final List<String> issues = new ArrayList<String>(domain.getIssues());
+		final Map<String, List<EvaluatorHypothesis>> evaluatorHyposMap = new HashMap<>();
+
+		for (String issue : issues) {
+			List<EvaluatorHypothesis> hypos = new ArrayList<>();
+			ValueSet vals = domain.getValues(issue);
+
+			if (vals instanceof NumberValueSet) {
+				Range range = ((NumberValueSet) vals).getRange();
+				double P = 1d / NEVALUATORS;
+
+				double low = range.getLow().doubleValue();
+				double step = (range.getHigh().doubleValue()
+						- range.getLow().doubleValue()) / (NEVALUATORS - 1);
+				for (int k = 0; k < NEVALUATORS; k++) {
+					double midvalue;
+					if (k == NEVALUATORS - 1) // avoid round error
+						midvalue = range.getHigh().doubleValue();
+					else
+						midvalue = low + k * step;
+					ValueSetUtilities lHypEval = new TriangleValueSetUtilities(
+							range.getLow(), BigDecimal.ZERO,
+							BigDecimal.valueOf(midvalue), BigDecimal.ONE,
+							range.getHigh(), BigDecimal.ZERO);
+					hypos.add(new EvaluatorHypothesis(lHypEval, P));
+				}
+
+			} else if (vals instanceof DiscreteValueSet) {
+				int nvals = vals.size().intValue();
+				double P = 1d / nvals;
+
+				// add one triangle for each issuevalue, with peak at value
+				Map<DiscreteValue, BigDecimal> valueUtils = new HashMap<>();
+				for (int peakpos = 0; peakpos < nvals; peakpos++) {
+					for (int j = 0; j < nvals; j++) {
+						DiscreteValue val = ((DiscreteValueSet) vals).get(j);
+						if (peakpos != 0 && j <= peakpos) {
+							valueUtils.put(val,
+									BigDecimal.valueOf((double) j / peakpos));
+						} else {
+							valueUtils.put(val, BigDecimal.valueOf(
+									(nvals - j - 1) / (nvals - peakpos - 1)));
+						}
+					}
+					hypos.add(new EvaluatorHypothesis(
+							new DiscreteValueSetUtilities(valueUtils), P));
+				}
+			}
+
+			evaluatorHyposMap.put(issue, normalize(hypos));
+		}
+		return evaluatorHyposMap;
+	}
+
+	/**
+	 * @param util     utility of current bid
+	 * @param prevUtil utility of last received bid
+	 * @return a value in &lt; 0, 1 ]. Higher means that |util-prevUtil| is
+	 *         smaller.
+	 *         <p>
+	 *         NOTE: the paper calls for dividing this value by (sigma sqrt(2
+	 *         pi)). This just scales the distance to have a peak value of 1.59,
+	 *         which leads to P values >1 in the rest of the computation, Also
+	 *         the values are scaled down anyway after that by a normalization,
+	 *         which makes the entire scaling just a problem. This scale factor
+	 *         was therefore removed.
+	 */
+	private double distance(double util, double prevUtil) {
+		double x = (prevUtil - util) / prevUtil;
+		return Math.exp(-(x * x) / (2.0 * sigma * sigma));
+	}
+
+	/**
+	 * @param issue the name of the issue to test
+	 * @param value the value to evaluate. Should be a valid value for issue.
+	 * @return the current hypothezized utility of issues
+	 * @throws NullPointerException if value is not valid for issue
+	 */
+	private Double getHypoUtility(String issue, Value value) {
+		return evaluatorHypoMap.get(issue).stream()
+				.map(hypo -> hypo.getProbability()
+						* hypo.getEvaluator().getUtility(value).doubleValue())
+				.mapToDouble(f -> f).sum();
+	}
+
+	/**
+	 * 
+	 * @return map, with key=issue and value=expected weight of issue = sum of
+	 *         weightHyps[pIssueNumber].probability * weight/sum where sum is
+	 *         the sum of raw weights, such that sum of weights is 1.
+	 */
+	private static Map<String, Double> getNormalizedWeights(
+			Map<String, List<WeightHypothesis>> weightHypoMap) {
+		Map<String, Double> wmap = new HashMap<>();
+
+		for (String issue : weightHypoMap.keySet()) {
+			double w = weightHypoMap.get(issue).stream()
+					.map(hypo -> hypo.getProbability() * hypo.getWeight())
+					.mapToDouble(f -> f).sum();
+
+			wmap.put(issue, w);
+		}
+		// normalize the map.
+		double sum = wmap.values().stream().mapToDouble(f -> f).sum();
+		if (sum != 0) {
+			wmap = wmap.entrySet().stream().collect(Collectors.toMap(
+					entry -> entry.getKey(), entry -> entry.getValue() / sum));
+		}
+
+		return wmap;
+	}
+
+	/**
+	 * 
+	 * @param bid         the {@link Bid} to evaluate
+	 * @param ignoreIssue the issue in the bid to ignore. If null or issue is
+	 *                    not part of the domain, a full utility is computed.
+	 * @return the estimated utility of issue pIssueIndex, according to the
+	 *         standing hypotheses, but without issue.
+	 */
+	private double getPartialUtility(Bid bid, String ignoreIssue) {
+		// calculate partial utility w/o issue pIssueIndex
+		double u = 0;
+		for (String issue : bid.getIssues()) {
+			if (issue.equals(ignoreIssue))
+				continue;
+			u = u + normalizedWeightsMap.get(issue)
+					* getHypoUtility(issue, bid.getValue(issue));
+		}
+		return u;
+	}
+
+	/**
+	 * @param bid the bid that came in
+	 * @return Map of updated WeightHypotheses for all issues
+	 */
+	protected Map<String, List<WeightHypothesis>> updatedWeights(Bid bid) {
+		Map<String, List<WeightHypothesis>> newHypoMap = new HashMap<>();
+
+		for (String issue : domain.getIssues()) {
+			ArrayList<WeightHypothesis> weighHypos = new ArrayList<>();
+
+			for (WeightHypothesis hypo : weightHypoMap.get(issue)) {
+				double util = hypo.getWeight()
+						* getHypoUtility(issue, bid.getValue(issue))
+						+ getPartialUtility(bid, issue);
+
+				double p = hypo.getProbability()
+						* distance(util, getPrevBidUtility());
+				WeightHypothesis lHyp = hypo.with(p);
+				weighHypos.add(lHyp);
+			}
+
+			newHypoMap.put(issue, normalize(weighHypos));
+		}
+		return newHypoMap;
+	}
+
+	/**
+	 * @param lBid the bid that came in
+	 * @return a set of new {@link EvaluatorHypothesis}
+	 */
+	protected Map<String, List<EvaluatorHypothesis>> updatedEvaluationFns(
+			Bid lBid) {
+		Map<String, List<EvaluatorHypothesis>> evalHypoMap = new HashMap<>();
+
+		for (String issue : domain.getIssues()) {
+			List<EvaluatorHypothesis> hypos = new ArrayList<EvaluatorHypothesis>();
+
+			for (EvaluatorHypothesis lHyp : evaluatorHypoMap.get(issue)) {
+				// update P. This is the heart of the algorithm.
+				double p = (lHyp.getProbability()
+						* distance(
+								getPartialUtility(lBid, issue)
+										+ normalizedWeightsMap.get(issue) * lHyp
+												.getEvaluator()
+												.getUtility(
+														lBid.getValue(issue))
+												.doubleValue(),
+								getPrevBidUtility()));
+				hypos.add(lHyp.with(p));
+			}
+
+			evalHypoMap.put(issue, normalize(hypos));
+		}
+		return evalHypoMap;
+	}
+
+	/**
+	 * @param hypos the list of {@link Hypothesis} to be normalized (sum of P =
+	 *              1).
+	 * @return same list of hypotheses, but with all P scaled with same factor
+	 *         so that the sum of all {@link Hypothesis#getProbability()} = 1.
+	 */
+	@SuppressWarnings("unchecked")
+	private static <T extends Hypothesis> List<T> normalize(List<T> hypos) {
+		final double sum = hypos.stream().map(hypo -> hypo.getProbability())
+				.mapToDouble(f -> f).sum();
+		return hypos.stream()
+				.map(hypo -> (T) hypo.with(hypo.getProbability() / sum))
+				.collect(Collectors.toList());
+	}
+
+	/**
+	 * Check that the P's sum to 1 (with some allowance for round errors).
+	 * 
+	 * @param <T>     the type of {@link Hypothesis} in the map.
+	 * @param hypomap a map of {@link Hypothesis}
+	 */
+	private static <T extends Hypothesis> void checkNormalized(
+			Map<String, List<T>> hypomap) {
+		for (List<T> hypos : hypomap.values()) {
+			double sum = hypos.stream().map(hypo -> hypo.getProbability())
+					.mapToDouble(f -> f).sum();
+			if (Math.abs(sum - 1d) > 0.0000001)
+				throw new IllegalArgumentException(
+						"Sum of P's is not 1 " + hypos);
+		}
+	}
+
+	/**
+	 * @return estimated opponent utility of previous bid.. Assumes linear
+	 *         decreasing utility. See paper.
+	 */
+	private double getPrevBidUtility() {
+		// Notice the decay constant is mush maller than in the paper.
+		return Math.max(0d, 1d - decay * (bidHistory.size() - 1));
+	}
+
+}
Index: /opponentmodel/src/main/java/geniusweb/opponentmodel/bayesian/EvaluatorHypothesis.java
===================================================================
--- /opponentmodel/src/main/java/geniusweb/opponentmodel/bayesian/EvaluatorHypothesis.java	(revision 34)
+++ /opponentmodel/src/main/java/geniusweb/opponentmodel/bayesian/EvaluatorHypothesis.java	(revision 34)
@@ -0,0 +1,60 @@
+package geniusweb.opponentmodel.bayesian;
+
+import geniusweb.profile.utilityspace.ValueSetUtilities;
+
+/**
+ * EXPERIMENTAL. DO NOT USE THIS.
+ *
+ */
+class EvaluatorHypothesis extends Hypothesis {
+	@Override
+	public int hashCode() {
+		final int prime = 31;
+		int result = super.hashCode();
+		result = prime * result + ((utils == null) ? 0 : utils.hashCode());
+		return result;
+	}
+
+	@Override
+	public boolean equals(Object obj) {
+		if (this == obj)
+			return true;
+		if (!super.equals(obj))
+			return false;
+		if (getClass() != obj.getClass())
+			return false;
+		EvaluatorHypothesis other = (EvaluatorHypothesis) obj;
+		if (utils == null) {
+			if (other.utils != null)
+				return false;
+		} else if (!utils.equals(other.utils))
+			return false;
+		return true;
+	}
+
+	private final ValueSetUtilities utils;
+
+	/**
+	 * 
+	 * @param pEval the ValueSetUtilities utility function
+	 */
+	public EvaluatorHypothesis(ValueSetUtilities pEval, double p) {
+		super(p);
+		utils = pEval;
+	}
+
+	public ValueSetUtilities getEvaluator() {
+		return utils;
+	}
+
+	@Override
+	public EvaluatorHypothesis with(double p) {
+		return new EvaluatorHypothesis(utils, p);
+	}
+
+	@Override
+	public String toString() {
+		return "P(" + utils + ")=" + getProbability();
+	}
+
+}
Index: /opponentmodel/src/main/java/geniusweb/opponentmodel/bayesian/Hypothesis.java
===================================================================
--- /opponentmodel/src/main/java/geniusweb/opponentmodel/bayesian/Hypothesis.java	(revision 34)
+++ /opponentmodel/src/main/java/geniusweb/opponentmodel/bayesian/Hypothesis.java	(revision 34)
@@ -0,0 +1,63 @@
+package geniusweb.opponentmodel.bayesian;
+
+/**
+ * A hypothesis is a value with a probability attached to it.
+ * <p>
+ * DO NOT USE THIS. Private use for {@link BayesianOpponentModel}.
+ */
+
+abstract class Hypothesis {
+	final private double p;
+
+	/**
+	 * 
+	 * @param p the probability of the item
+	 */
+	public Hypothesis(double p) {
+		if (p < 0 || p > 1)
+			throw new IllegalArgumentException("p must be in [0,1], got " + p);
+		this.p = p;
+	}
+
+	/**
+	 * 
+	 * @return the probability that this hypothesis holds
+	 */
+	public double getProbability() {
+		return p;
+	}
+
+	/**
+	 * Subclasses implement this. We can not implement it here because
+	 * subclasses return a more specific class than Hypothesis.
+	 * 
+	 * @param p the new probability value.
+	 * @return new Hypothesis with p set to this value (and the rest unchanged).
+	 */
+	public abstract Hypothesis with(double p);
+
+	@Override
+	public int hashCode() {
+		final int prime = 31;
+		int result = 1;
+		long temp;
+		temp = Double.doubleToLongBits(p);
+		result = prime * result + (int) (temp ^ (temp >>> 32));
+		return result;
+	}
+
+	@Override
+	public boolean equals(Object obj) {
+		if (this == obj)
+			return true;
+		if (obj == null)
+			return false;
+		if (getClass() != obj.getClass())
+			return false;
+		Hypothesis other = (Hypothesis) obj;
+		if (Double.doubleToLongBits(p) != Double.doubleToLongBits(other.p))
+			return false;
+		return true;
+	}
+
+}
Index: /opponentmodel/src/main/java/geniusweb/opponentmodel/bayesian/TriangleValueSetUtilities.java
===================================================================
--- /opponentmodel/src/main/java/geniusweb/opponentmodel/bayesian/TriangleValueSetUtilities.java	(revision 34)
+++ /opponentmodel/src/main/java/geniusweb/opponentmodel/bayesian/TriangleValueSetUtilities.java	(revision 34)
@@ -0,0 +1,153 @@
+package geniusweb.opponentmodel.bayesian;
+
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+
+import geniusweb.issuevalue.NumberValue;
+import geniusweb.issuevalue.Value;
+import geniusweb.profile.utilityspace.NumberValueSetUtilities;
+import tudelft.utilities.immutablelist.Range;
+
+/**
+ * Similar to {@link NumberValueSetUtilities} but contains an extra mid point
+ * between low and high value. Utilities are linearly interpolated within the
+ * triangle and 0 outside. This is used by the {@link BayesianOpponentModel} and
+ * not json-serializable.
+ * <p>
+ * DO NOT USE THIS. Private use for {@link BayesianOpponentModel}.
+ */
+class TriangleValueSetUtilities extends NumberValueSetUtilities {
+
+	/**
+	 * The value and utility at mid point.
+	 */
+	private final BigDecimal midValue;
+	private final BigDecimal midUtility;
+
+	/**
+	 * 
+	 * @param lowValue    the low value of the {@link Range}
+	 * @param lowUtility  the utility of the {@link #lowValue}. must be &ge; 0
+	 * @param midValue    the mid value of the {@link Range}. must be
+	 *                    &ge;lowValue and &le;highValue.
+	 * @param midUtility  the utility of the {@link #midValue}.
+	 * @param highValue   the high value of the {@link Range}. Must be @le;1
+	 * @param highUtility the utility of the {@link #highValue}
+	 */
+	public TriangleValueSetUtilities(BigDecimal lowValue, BigDecimal lowUtility,
+			BigDecimal midValue, BigDecimal midUtility, BigDecimal highValue,
+			BigDecimal highUtility) {
+		super(lowValue, lowUtility, highValue, highUtility);
+		if (midValue == null || midUtility == null) {
+			throw new NullPointerException(
+					"arguments midValue, midUtility must be non-null");
+		}
+		// ensure 0 <= lowvalue <=midvalue <= highvalue <=1
+		if (midValue.compareTo(lowValue) < 0
+				|| midValue.compareTo(highValue) > 0)
+			throw new IllegalArgumentException(
+					"midvalue must be between lowValue and highValue");
+
+		this.midValue = midValue;
+		this.midUtility = midUtility;
+	}
+
+	/**
+	 * {@inheritDoc} <
+	 * <h2>Details</h2> Any value &ge; {@link #midValue} will be interpolated
+	 * from the mid-high interval; any value below the {@link #midValue} with
+	 * the low-mid interval. Any value outside low-high interval returns 0.
+	 * {@link #midUtility} is returned if value =midValue.
+	 */
+	@Override
+	public BigDecimal getUtility(Value value) {
+		if (!(value instanceof NumberValue)) {
+			return BigDecimal.ZERO;
+		}
+		BigDecimal x = ((NumberValue) value).getValue();
+		if (x.compareTo(getLowValue()) < 0 || x.compareTo(getHighValue()) > 0)
+			return BigDecimal.ZERO;
+
+		BigDecimal lowValue, highValue, lowUtility, highUtility;
+
+		if (x.compareTo(midValue) < 0) {
+			lowValue = getLowValue();
+			lowUtility = getLowUtility();
+			highValue = midValue;
+			highUtility = midUtility;
+		} else {
+			lowValue = midValue;
+			lowUtility = midUtility;
+			highValue = getHighValue();
+			highUtility = getHighUtility();
+		}
+		if (x.compareTo(midValue) == 0)
+			return midUtility;
+
+		// we need to be careful to avoid round errors from divides.
+		// so we return lowU + deltaU * (x-lowV) /deltaV
+		BigDecimal deltaU = highUtility.subtract(lowUtility);
+		BigDecimal deltaV = highValue.subtract(lowValue);
+		// deltaV can't be 0 because value!=midValue.
+
+		return lowUtility.add(deltaU.multiply(
+				x.subtract(lowValue).divide(deltaV, 8, RoundingMode.HALF_UP)));
+	}
+
+	/**
+	 * 
+	 * @return the mid value
+	 */
+	public BigDecimal getMidValue() {
+		return midValue;
+	}
+
+	/**
+	 * 
+	 * @return the utility of the mid value.
+	 */
+	public BigDecimal getMidUtility() {
+		return midUtility;
+	}
+
+	@Override
+	public String toString() {
+		return "TriangleValueSetUtilities(" + getLowValue() + "->"
+				+ getLowUtility() + "," + midValue + "->" + midUtility + ","
+				+ getHighValue() + "->" + getHighUtility() + ")";
+	}
+
+	@Override
+	public int hashCode() {
+		final int prime = 31;
+		int result = super.hashCode();
+		result = prime * result
+				+ ((midUtility == null) ? 0 : midUtility.hashCode());
+		result = prime * result
+				+ ((midValue == null) ? 0 : midValue.hashCode());
+		return result;
+	}
+
+	@Override
+	public boolean equals(Object obj) {
+		if (this == obj)
+			return true;
+		if (!super.equals(obj))
+			return false;
+		if (getClass() != obj.getClass())
+			return false;
+		TriangleValueSetUtilities other = (TriangleValueSetUtilities) obj;
+		if (midUtility == null) {
+			if (other.midUtility != null)
+				return false;
+		} else if (!midUtility.equals(other.midUtility))
+			return false;
+		if (midValue == null) {
+			if (other.midValue != null)
+				return false;
+		} else if (!midValue.equals(other.midValue))
+			return false;
+		return true;
+	}
+
+}
Index: /opponentmodel/src/main/java/geniusweb/opponentmodel/bayesian/WeightHypothesis.java
===================================================================
--- /opponentmodel/src/main/java/geniusweb/opponentmodel/bayesian/WeightHypothesis.java	(revision 34)
+++ /opponentmodel/src/main/java/geniusweb/opponentmodel/bayesian/WeightHypothesis.java	(revision 34)
@@ -0,0 +1,58 @@
+package geniusweb.opponentmodel.bayesian;
+
+/**
+ * Hypothesis on the weight of an issue.
+ * <p>
+ * DO NOT USE THIS. Private use for {@link BayesianOpponentModel}.
+ */
+class WeightHypothesis extends Hypothesis {
+	private final double weight;
+
+	public WeightHypothesis(double weight, double p) {
+		super(p);
+		this.weight = weight;
+	}
+
+	public WeightHypothesis withWeight(double value) {
+		return new WeightHypothesis(value, getProbability());
+	}
+
+	public double getWeight() {
+		return weight;
+	}
+
+	@Override
+	public String toString() {
+		return "P(" + weight + ")=" + getProbability();
+	}
+
+	@Override
+	public WeightHypothesis with(double p) {
+		return new WeightHypothesis(weight, p);
+	}
+
+	@Override
+	public int hashCode() {
+		final int prime = 31;
+		int result = super.hashCode();
+		long temp;
+		temp = Double.doubleToLongBits(weight);
+		result = prime * result + (int) (temp ^ (temp >>> 32));
+		return result;
+	}
+
+	@Override
+	public boolean equals(Object obj) {
+		if (this == obj)
+			return true;
+		if (!super.equals(obj))
+			return false;
+		if (getClass() != obj.getClass())
+			return false;
+		WeightHypothesis other = (WeightHypothesis) obj;
+		if (Double.doubleToLongBits(weight) != Double
+				.doubleToLongBits(other.weight))
+			return false;
+		return true;
+	}
+}
Index: /opponentmodel/src/test/java/geniusweb/opponentmodel/FrequencyOppModelTest.java
===================================================================
--- /opponentmodel/src/test/java/geniusweb/opponentmodel/FrequencyOppModelTest.java	(revision 33)
+++ /opponentmodel/src/test/java/geniusweb/opponentmodel/FrequencyOppModelTest.java	(revision 34)
@@ -2,4 +2,5 @@
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
 import static org.mockito.Mockito.mock;
@@ -239,3 +240,10 @@
 
 	}
+
+	@Test
+	public void testStableName() {
+		String name = oppModel1.getName();
+		assertNotNull(name);
+		assertEquals(name, oppModel1.getName());
+	}
 }
Index: /opponentmodel/src/test/java/geniusweb/opponentmodel/bayesian/BayesianOppModelTest.java
===================================================================
--- /opponentmodel/src/test/java/geniusweb/opponentmodel/bayesian/BayesianOppModelTest.java	(revision 34)
+++ /opponentmodel/src/test/java/geniusweb/opponentmodel/bayesian/BayesianOppModelTest.java	(revision 34)
@@ -0,0 +1,350 @@
+package geniusweb.opponentmodel.bayesian;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.mock;
+
+import java.io.IOException;
+import java.math.BigDecimal;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Random;
+import java.util.TreeMap;
+import java.util.stream.Collectors;
+
+import org.junit.Ignore;
+import org.junit.Test;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+import geniusweb.actions.Offer;
+import geniusweb.actions.PartyId;
+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 geniusweb.profile.utilityspace.UtilitySpace;
+import geniusweb.progress.Progress;
+import tudelft.utilities.immutablelist.ImmutableList;
+import tudelft.utilities.immutablelist.Outer;
+import tudelft.utilities.junit.GeneralTests;
+
+public class BayesianOppModelTest extends GeneralTests<BayesianOpponentModel> {
+	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 I2V1 = new DiscreteValue("i2v1");
+	private static final DiscreteValue I2V2 = new DiscreteValue("i2v2");
+	private static final DiscreteValue I1V2b = new DiscreteValue("i1v2b");
+	private static final Progress progress = mock(Progress.class);
+	private static final PartyId other = new PartyId("other");
+	private static final Random rnd = new Random();
+
+	private static Domain domain, domain2, domain3;
+	private static BayesianOpponentModel oppModel1, oppModel1b, oppModel2,
+			oppModel3;
+
+	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 BayesianOpponentModel(domain);
+		oppModel1b = new BayesianOpponentModel(domain);
+		oppModel2 = new BayesianOpponentModel(domain)
+				.with(new Offer(other, bid1), progress);
+		oppModel3 = new BayesianOpponentModel(domain)
+				.with(new Offer(other, bid2), progress);
+
+	}
+
+	private ObjectMapper jackson = new ObjectMapper();
+
+	@Override
+	public List<List<BayesianOpponentModel>> getGeneralTestData() {
+		return Arrays.asList(Arrays.asList(oppModel1, oppModel1b),
+				Arrays.asList(oppModel2), Arrays.asList(oppModel3));
+	}
+
+	@Override
+	public List<String> getGeneralTestStrings() {
+		// not much we can test. The internals are too detailed and situation
+		// specific
+		return Arrays.asList("BayesianOpponentModel.*",
+				"BayesianOpponentModel.*", "BayesianOpponentModel.*");
+	}
+
+	@Test(expected = NullPointerException.class)
+	public void smokeTestNull() {
+		new BayesianOpponentModel().with((Domain) null, null);
+	}
+
+	@Test
+	public void testNormalization() {
+		System.out.println(oppModel1.getWeights());
+	}
+
+	@SuppressWarnings("unused")
+	@Test
+	public void smokeTest() {
+		new BayesianOpponentModel(domain);
+	}
+
+	@Test
+	public void testEmptyModel() {
+		BayesianOpponentModel oppModel = new BayesianOpponentModel()
+				.with(domain, null);
+		// somewhere 0.4-0.6 should be fine.
+		// exact value varies with the exact hypotheses
+		assertEquals(0.5, oppModel.getUtility(bid1).doubleValue(), 0.1);
+		assertEquals(0.5, oppModel.getUtility(bid2).doubleValue(), 0.1);
+	}
+
+	@Test
+	public void testEmptyBid() {
+		Bid bid = new Bid(Collections.emptyMap());
+		assertEquals(0d, oppModel1.getUtility(bid).doubleValue(), 0.000001);
+	}
+
+	@Test
+	public void testUpdate() {
+
+		BayesianOpponentModel newOppModel = oppModel1
+				.with(new Offer(other, bid1), progress);
+		assertTrue(oppModel1.getUtility(bid1).doubleValue() < newOppModel
+				.getUtility(bid1).doubleValue());
+		assertTrue(newOppModel.getBidHistory().size() == 1);
+
+		// and if we continue with next bid, the first should still hold
+		// and the next bid should also improve
+		BayesianOpponentModel newOppModel2 = newOppModel
+				.with(new Offer(other, bid2), progress);
+		assertTrue(oppModel1.getUtility(bid1).doubleValue() < newOppModel2
+				.getUtility(bid1).doubleValue());
+		assertTrue(oppModel1.getUtility(bid2).doubleValue() < newOppModel2
+				.getUtility(bid2).doubleValue());
+
+		assertTrue(newOppModel2.getBidHistory().size() == 2);
+
+		// bid1= (i1v1, 1.2), bid2= (i1v1, 1.5)
+		// so bidding keeps ISS1 but changes ISS2.
+		// check that ISS1 increases weight and ISS2 decreases
+		assertTrue(oppModel1.getWeights().get(ISS1).doubleValue() < newOppModel2
+				.getWeights().get(ISS1).doubleValue());
+
+		// it may not work like this, due to renormalization steps.
+//		assertTrue(oppModel1.getWeights().get(ISS2).doubleValue() < newOppModel2
+//				.getWeights().get(ISS2).doubleValue());
+
+	}
+
+	@Test
+	public void testPartialBidUpdate() {
+		BayesianOpponentModel oppModel = oppModel1.with(new Offer(other, bid1),
+				progress);
+		Bid partialbid = new Bid(ISS1, I1V1);
+		oppModel.with(new Offer(other, partialbid), progress);
+	}
+
+	@Test
+	public void testStableName() {
+		String name = oppModel1.getName();
+		assertNotNull(name);
+		assertEquals(name, oppModel1.getName());
+	}
+
+	@Test
+	public void testWeightsNormalized() {
+		assertEquals(1d, oppModel1.getWeights().values().stream()
+				.mapToDouble(f -> f).sum(), 0.000001);
+	}
+
+	/**
+	 * duration/stress test with random bids
+	 */
+	@Test
+	public void testRepeatedRandomBidding() throws IOException {
+		// use japantrip as it has numbervalue as well
+		String profile = new String(
+				Files.readAllBytes(
+						Paths.get("src/test/resources/japantrip.json")),
+				StandardCharsets.UTF_8);
+		Domain dom = jackson.readValue(profile, Domain.class);
+		BayesianOpponentModel model = new BayesianOpponentModel(dom);
+
+		for (int time = 1; time < 100; time++) {
+			Bid bid = getRandomBid(dom, null, null);
+			double util = model.getUtility(bid).doubleValue();
+			System.out.println(util);
+			assertTrue(util > 0d && util < 1d);
+			model = model.with(new Offer(other, bid), null);
+		}
+	}
+
+	/**
+	 * duration/stress test with similar bids
+	 */
+
+	@Test
+	public void testRepeateSimilarBidding() throws IOException {
+		// use japantrip as it has numbervalue as well
+		String profile = new String(
+				Files.readAllBytes(
+						Paths.get("src/test/resources/japantrip.json")),
+				StandardCharsets.UTF_8);
+		Domain dom = jackson.readValue(profile, Domain.class);
+		BayesianOpponentModel model = new BayesianOpponentModel(dom);
+
+		for (int time = 1; time < 100; time++) {
+			Bid bid = getRandomBid(dom, "purpose",
+					new DiscreteValue("sightseeing"));
+			double util = model.getUtility(bid).doubleValue();
+			// System.out.println(util);
+			assertTrue(util > 0d && util < 1d);
+			model = model.with(new Offer(other, bid), null);
+		}
+	}
+
+	/**
+	 * 
+	 * @param dom          the {@link Domain}
+	 * @param specialissue an issue name. If not null, value is used for this
+	 *                     issue.
+	 * @param value        the value to use for specialissue.
+	 * 
+	 * @return random bid from domain. Notice that bidspace depends on profile
+	 *         so we should not be using bidspace. This makes this a bit clumsy
+	 */
+	private Bid getRandomBid(Domain dom, String specialissue, Value value) {
+		Map<String, Value> map = new HashMap<>();
+		for (String issue : dom.getIssues()) {
+			Value val = value;
+			if (!issue.equals(specialissue)) {
+				ValueSet values = dom.getValues(issue);
+				val = values.get(rnd.nextInt(values.size().intValue()));
+			}
+			map.put(issue, val);
+		}
+		return new Bid(map);
+	}
+
+	/**
+	 * Generate all bids from a space, sort to order, and pump them in that
+	 * order into Bayesian model. In the end the model should "match" with the
+	 * original space.
+	 * 
+	 * @return
+	 * @throws IOException
+	 */
+	@Ignore
+	@Test
+	public void testPumpBidsInOrder() throws IOException {
+		String profile = new String(
+				Files.readAllBytes(
+						Paths.get("src/test/resources/japantrip1.json")),
+				StandardCharsets.UTF_8);
+		UtilitySpace japantrip = jackson.readValue(profile, UtilitySpace.class);
+		BayesianOpponentModel model = new BayesianOpponentModel(
+				japantrip.getDomain());
+
+		Map<Double, Bid> sorted = getAllBids(japantrip);
+		for (Double val : sorted.keySet()) {
+			model = model.with(new Offer(other, sorted.get(val)), null);
+		}
+		System.out.println(model);
+
+		Map<String, Double> weights = model.getWeights();
+		System.out.println(weights);
+
+		// you would expect this result but in practice it doesn't
+		assertEquals(weights.get("place").doubleValue(), 0.57, 0.1);
+		assertEquals(weights.get("budget").doubleValue(), 0.09, 0.1);
+		assertEquals(weights.get("days").doubleValue(), 0.17, 0.1);
+		assertEquals(weights.get("purpose").doubleValue(), 0.17, 0.1);
+
+	}
+
+	/**
+	 * 
+	 * @param utllspace the {@link UtilitySpace} to be compiled
+	 * @return all bids, sorted from high to low utility. Notice, normally you
+	 *         would use AllBidsList but we can not import that module here.
+	 *         Warning, enumerating and sorting all bids in a space this way is
+	 *         too expensive for use in real time negotiation.
+	 */
+	private Map<Double, Bid> getAllBids(UtilitySpace utllspace) {
+		Domain dom = utllspace.getDomain();
+		List<String> issues = new ArrayList<String>(
+				utllspace.getDomain().getIssues());
+		List<ImmutableList<Value>> values = issues.stream()
+				.map(issue -> dom.getValues(issue))
+				.collect(Collectors.toList());
+
+		Outer<Value> allBidValues = new Outer<Value>(values);
+		Map<Double, Bid> bidmap = new TreeMap<>(Collections.reverseOrder());
+		for (ImmutableList<Value> bidvals : allBidValues) {
+			Map<String, Value> vals = new HashMap<>();
+			for (int n = 0; n < issues.size(); n++) {
+				vals.put(issues.get(n), bidvals.get(n));
+			}
+			Bid bid = new Bid(vals);
+			bidmap.put(utllspace.getUtility(bid).doubleValue(), bid);
+		}
+
+		return bidmap;
+	}
+}
Index: /opponentmodel/src/test/java/geniusweb/opponentmodel/bayesian/TriangleValueSetUtilTest.java
===================================================================
--- /opponentmodel/src/test/java/geniusweb/opponentmodel/bayesian/TriangleValueSetUtilTest.java	(revision 34)
+++ /opponentmodel/src/test/java/geniusweb/opponentmodel/bayesian/TriangleValueSetUtilTest.java	(revision 34)
@@ -0,0 +1,100 @@
+package geniusweb.opponentmodel.bayesian;
+
+import static org.junit.Assert.assertEquals;
+
+import java.math.BigDecimal;
+import java.util.Arrays;
+import java.util.List;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import geniusweb.issuevalue.NumberValue;
+import tudelft.utilities.junit.GeneralTests;
+
+public class TriangleValueSetUtilTest
+		extends GeneralTests<TriangleValueSetUtilities> {
+
+	private static final double MAXE = 0.00000001;
+	private static final BigDecimal N0 = BigDecimal.ZERO;
+	private static final BigDecimal N01 = new BigDecimal("0.1");
+	private static final BigDecimal N02 = new BigDecimal("0.2");
+	private static final BigDecimal N03 = new BigDecimal("0.3");
+	private static final BigDecimal N04 = new BigDecimal("0.4");
+	private static final BigDecimal N05 = new BigDecimal("0.5");
+	private static final BigDecimal N07 = new BigDecimal("0.7");
+	private static final BigDecimal N09 = new BigDecimal("0.9");
+	private static final BigDecimal N1 = BigDecimal.ONE;
+
+	private TriangleValueSetUtilities vset1, vset1a, vset2, vset3;
+
+	@Before
+	public void before() {
+		vset1 = new TriangleValueSetUtilities(N01, N02, N04, N05, N07, N09);
+		vset1a = new TriangleValueSetUtilities(N01, N02, N04, N05, N07, N09);
+		vset2 = new TriangleValueSetUtilities(N01, N02, N01, N05, N07, N09);
+		vset3 = new TriangleValueSetUtilities(N01, N02, N07, N05, N07, N09);
+	}
+
+	@Override
+	public List<List<TriangleValueSetUtilities>> getGeneralTestData() {
+		return Arrays.asList(Arrays.asList(vset1, vset1a), Arrays.asList(vset2),
+				Arrays.asList(vset3));
+	}
+
+	@Override
+	public List<String> getGeneralTestStrings() {
+		return Arrays.asList(
+				"TriangleValueSetUtilities.0.1->0.2,0.4->0.5,0.7->0.9.",
+				"TriangleValueSetUtilities.0.1->0.2,0.1->0.5,0.7->0.9.",
+				"TriangleValueSetUtilities.0.1->0.2,0.7->0.5,0.7->0.9.");
+	}
+
+	@Test
+	public void testInterpolation() {
+		assertEquals(0, vset1.getUtility(new NumberValue(N0)).doubleValue(),
+				MAXE);
+		assertEquals(0.2, vset1.getUtility(new NumberValue(N01)).doubleValue(),
+				MAXE);
+		assertEquals(0.3 /* 2 + 1/2*3 */,
+				vset1.getUtility(new NumberValue(N02)).doubleValue(), MAXE);
+		assertEquals(0.5, vset1.getUtility(new NumberValue(N04)).doubleValue(),
+				MAXE);
+		assertEquals(0.9, vset1.getUtility(new NumberValue(N07)).doubleValue(),
+				MAXE);
+		assertEquals(0, vset1.getUtility(new NumberValue(N09)).doubleValue(),
+				MAXE);
+
+	}
+
+	@Test
+	public void testMidEqualsLow() {
+		assertEquals(0, vset2.getUtility(new NumberValue(N0)).doubleValue(),
+				MAXE);
+		assertEquals(0.5, vset2.getUtility(new NumberValue(N01)).doubleValue(),
+				MAXE);
+		assertEquals(0.5 + 0.4 / 6,
+				vset2.getUtility(new NumberValue(N02)).doubleValue(), MAXE);
+		assertEquals(0.9, vset2.getUtility(new NumberValue(N07)).doubleValue(),
+				MAXE);
+		assertEquals(0, vset2.getUtility(new NumberValue(N09)).doubleValue(),
+				MAXE);
+
+	}
+
+	@Test
+	public void testMidEqualsHigh() {
+		assertEquals(0, vset3.getUtility(new NumberValue(N0)).doubleValue(),
+				MAXE);
+		assertEquals(0.2, vset3.getUtility(new NumberValue(N01)).doubleValue(),
+				MAXE);
+		assertEquals(0.2 + 2 * 0.3 / 6,
+				vset3.getUtility(new NumberValue(N03)).doubleValue(), MAXE);
+		assertEquals(0.5, vset3.getUtility(new NumberValue(N07)).doubleValue(),
+				MAXE);
+		assertEquals(0, vset3.getUtility(new NumberValue(N09)).doubleValue(),
+				MAXE);
+
+	}
+
+}
Index: /opponentmodel/src/test/resources/japantrip.json
===================================================================
--- /opponentmodel/src/test/resources/japantrip.json	(revision 34)
+++ /opponentmodel/src/test/resources/japantrip.json	(revision 34)
@@ -0,0 +1,32 @@
+{
+	"name": "japantrip",
+	"issuesValues": {
+		"place": {
+			"values": [
+				"Tokyo",
+				"Osaka",
+				"Negoya",
+				"Hokkaido"
+			]
+		},
+		"budget": {
+			"range":  { "low":900,"high":1800,"step":300 } 
+		},
+		"days": {
+			"values": [
+				"3",
+				"4",
+				"5",
+				"6"
+			]
+		},
+		"purpose": {
+			"values": [
+				"Sightseeing",
+				"Activity",
+				"Shopping"
+			]
+		}
+	}
+}
+	
Index: /opponentmodel/src/test/resources/japantrip1.json
===================================================================
--- /opponentmodel/src/test/resources/japantrip1.json	(revision 34)
+++ /opponentmodel/src/test/resources/japantrip1.json	(revision 34)
@@ -0,0 +1,93 @@
+{
+	"LinearAdditiveUtilitySpace": {
+		"issueUtilities": {
+			"place": {
+				"DiscreteValueSetUtilities": {
+					"valueUtilities": {
+						"Tokyo": 1.0,
+						"Osaka": 0.2,
+						"Negoya": 0.2,
+						"Hokkaido": 0.2
+					}
+				}
+			},
+			"budget": {
+				"NumberValueSetUtilities": {
+					"lowValue": 900,
+					"lowUtility": 1.0,
+					"highValue": 1800,
+					"highUtility": 0.15
+				}
+			},
+			"days": {
+				"DiscreteValueSetUtilities": {
+					"valueUtilities": {
+						"3": 1.0,
+						"4": 0.2,
+						"5": 0.2,
+						"6": 0.1
+					}
+				}
+			},
+			"purpose": {
+				"DiscreteValueSetUtilities": {
+					"valueUtilities": {
+						"Sightseeing": 0.6,
+						"Activity": 1.0,
+						"Shopping": 0.3
+					}
+				}
+			}
+		},
+		"issueWeights": {
+			"place": 0.57,
+			"budget": 0.09,
+			"days": 0.17,
+			"purpose": 0.17
+		},
+		"domain": {
+			"name": "japantrip",
+			"issuesValues": {
+				"place": {
+					"values": [
+						"Tokyo",
+						"Osaka",
+						"Negoya",
+						"Hokkaido"
+					]
+				},
+				"budget": {
+					"range": {
+						"low": 900,
+						"high": 1800,
+						"step": 300
+					}
+				},
+				"days": {
+					"values": [
+						"3",
+						"4",
+						"5",
+						"6"
+					]
+				},
+				"purpose": {
+					"values": [
+						"Sightseeing",
+						"Activity",
+						"Shopping"
+					]
+				}
+			}
+		},
+		"name": "japantrip1",
+		"reservationBid": {
+			"issuevalues": {
+				"place": "Osaka",
+				"budget": 1800,
+				"days": "6",
+				"purpose": "Shopping"
+			}
+		}
+	}
+}
Index: /party/pom.xml
===================================================================
--- /party/pom.xml	(revision 33)
+++ /party/pom.xml	(revision 34)
@@ -6,5 +6,5 @@
 	<groupId>geniusweb</groupId>
 	<artifactId>party</artifactId>
-	<version>2.0.0</version> <!-- must equal ${geniusweb.version} -->
+	<version>2.0.1</version> <!-- must equal ${geniusweb.version} -->
 	<packaging>jar</packaging>
 
@@ -17,5 +17,5 @@
 		<passwd>${env.ARTIFACTORY_PASS}</passwd>
 		<jackson-2-version>2.12.3</jackson-2-version>
-		<geniusweb.version>2.0.0</geniusweb.version>
+		<geniusweb.version>2.0.1</geniusweb.version>
 	</properties>
 
@@ -110,6 +110,6 @@
 		<dependency>
 			<groupId>org.mockito</groupId>
-			<artifactId>mockito-all</artifactId>
-			<version>1.9.5</version>
+			<artifactId>mockito-core</artifactId>
+			<version>3.11.2</version>
 			<scope>test</scope>
 		</dependency>
@@ -140,6 +140,9 @@
 			<url>https://repo1.maven.org/maven2</url>
 		</pluginRepository>
+		<pluginRepository>
+			<id>artifactory.ewi.tudelft.nl</id>
+			<url>https://artifactory.ewi.tudelft.nl/artifactory/libs-release</url>
+		</pluginRepository>
 	</pluginRepositories>
-
 
 	<build>
Index: /profile/pom.xml
===================================================================
--- /profile/pom.xml	(revision 33)
+++ /profile/pom.xml	(revision 34)
@@ -6,5 +6,5 @@
 	<groupId>geniusweb</groupId>
 	<artifactId>profile</artifactId>
-	<version>2.0.0</version> <!-- must equal ${geniusweb.version} -->
+	<version>2.0.1</version> <!-- must equal ${geniusweb.version} -->
 	<packaging>jar</packaging>
 
@@ -17,5 +17,5 @@
 		<passwd>${env.ARTIFACTORY_PASS}</passwd>
 		<jackson-2-version>2.12.3</jackson-2-version>
-		<geniusweb.version>2.0.0</geniusweb.version>
+		<geniusweb.version>2.0.1</geniusweb.version>
 	</properties>
 
@@ -101,6 +101,6 @@
 		<dependency>
 			<groupId>org.mockito</groupId>
-			<artifactId>mockito-all</artifactId>
-			<version>1.9.5</version>
+			<artifactId>mockito-core</artifactId>
+			<version>3.11.2</version>
 			<scope>test</scope>
 		</dependency>
@@ -124,4 +124,8 @@
 			<id>central</id>
 			<url>https://repo1.maven.org/maven2</url>
+		</pluginRepository>
+		<pluginRepository>
+			<id>artifactory.ewi.tudelft.nl</id>
+			<url>https://artifactory.ewi.tudelft.nl/artifactory/libs-release</url>
 		</pluginRepository>
 	</pluginRepositories>
Index: /profile/src/test/java/geniusweb/profile/utilityspace/LinearAdditiveTest.java
===================================================================
--- /profile/src/test/java/geniusweb/profile/utilityspace/LinearAdditiveTest.java	(revision 33)
+++ /profile/src/test/java/geniusweb/profile/utilityspace/LinearAdditiveTest.java	(revision 34)
@@ -2,4 +2,5 @@
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 import static org.mockito.Mockito.mock;
@@ -12,4 +13,5 @@
 import java.nio.file.Paths;
 import java.util.Arrays;
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
@@ -248,11 +250,13 @@
 		Bid bid1 = new Bid(issuevalues);
 		Map<String, Value> issuevalues1 = new HashMap<>();
-		issuevalues.put(ISS1, i1v2);
-		issuevalues.put(ISS2, i1v1);
+		issuevalues1.put(ISS1, i1v2);
+		issuevalues1.put(ISS2, i2v1);
 		Bid bid2 = new Bid(issuevalues1);
 		assertTrue(utilspace1.isPreferredOrEqual(bid1, bid2));
 		assertTrue(utilspace1.isPreferredOrEqual(bid1, bid1));
 		assertTrue(utilspace1.isPreferredOrEqual(bid2, bid2));
-		assertTrue(!utilspace1.isPreferredOrEqual(bid2, bid1));
+		assertFalse(utilspace1.isPreferredOrEqual(bid2, bid1));
+		assertFalse(utilspace1
+				.isPreferredOrEqual(new Bid(Collections.emptyMap()), bid1));
 	}
 
@@ -277,4 +281,14 @@
 	}
 
+	@Test
+	public void loadFullWithJsonNumber() throws IOException {
+		String profile = new String(
+				Files.readAllBytes(
+						Paths.get("src/test/resources/japantrip1.json")),
+				StandardCharsets.UTF_8);
+		UtilitySpace space = jackson.readValue(profile, UtilitySpace.class);
+
+	}
+
 	@Test(expected = IllegalArgumentException.class)
 	public void testResBidWithNonsenseIssue() {
Index: /profile/src/test/resources/japantrip1.json
===================================================================
--- /profile/src/test/resources/japantrip1.json	(revision 34)
+++ /profile/src/test/resources/japantrip1.json	(revision 34)
@@ -0,0 +1,93 @@
+{
+	"LinearAdditiveUtilitySpace": {
+		"issueUtilities": {
+			"place": {
+				"DiscreteValueSetUtilities": {
+					"valueUtilities": {
+						"Tokyo": 1.0,
+						"Osaka": 0.2,
+						"Negoya": 0.2,
+						"Hokkaido": 0.2
+					}
+				}
+			},
+			"budget": {
+				"NumberValueSetUtilities": {
+					"lowValue": 900,
+					"lowUtility": 1.0,
+					"highValue": 1800,
+					"highUtility": 0.15
+				}
+			},
+			"days": {
+				"DiscreteValueSetUtilities": {
+					"valueUtilities": {
+						"3": 1.0,
+						"4": 0.2,
+						"5": 0.2,
+						"6": 0.1
+					}
+				}
+			},
+			"purpose": {
+				"DiscreteValueSetUtilities": {
+					"valueUtilities": {
+						"Sightseeing": 0.6,
+						"Activity": 1.0,
+						"Shopping": 0.3
+					}
+				}
+			}
+		},
+		"issueWeights": {
+			"place": 0.57,
+			"budget": 0.09,
+			"days": 0.17,
+			"purpose": 0.17
+		},
+		"domain": {
+			"name": "japantrip",
+			"issuesValues": {
+				"place": {
+					"values": [
+						"Tokyo",
+						"Osaka",
+						"Negoya",
+						"Hokkaido"
+					]
+				},
+				"budget": {
+					"range": {
+						"low": 900,
+						"high": 1800,
+						"step": 300
+					}
+				},
+				"days": {
+					"values": [
+						"3",
+						"4",
+						"5",
+						"6"
+					]
+				},
+				"purpose": {
+					"values": [
+						"Sightseeing",
+						"Activity",
+						"Shopping"
+					]
+				}
+			}
+		},
+		"name": "japantrip1",
+		"reservationBid": {
+			"issuevalues": {
+				"place": "Osaka",
+				"budget": 1800,
+				"days": "6",
+				"purpose": "Shopping"
+			}
+		}
+	}
+}
Index: /profileconnection/pom.xml
===================================================================
--- /profileconnection/pom.xml	(revision 33)
+++ /profileconnection/pom.xml	(revision 34)
@@ -6,5 +6,5 @@
 	<groupId>geniusweb</groupId>
 	<artifactId>profileconnection</artifactId>
-	<version>2.0.0</version> <!-- must equal ${geniusweb.version} -->
+	<version>2.0.1</version> <!-- must equal ${geniusweb.version} -->
 	<packaging>jar</packaging>
 
@@ -17,5 +17,5 @@
 		<passwd>${env.ARTIFACTORY_PASS}</passwd>
 		<jackson-2-version>2.12.3</jackson-2-version>
-		<geniusweb.version>2.0.0</geniusweb.version>
+		<geniusweb.version>2.0.1</geniusweb.version>
 	</properties>
 
@@ -105,6 +105,6 @@
 		<dependency>
 			<groupId>org.mockito</groupId>
-			<artifactId>mockito-all</artifactId>
-			<version>1.9.5</version>
+			<artifactId>mockito-core</artifactId>
+			<version>3.11.2</version>
 			<scope>test</scope>
 		</dependency>
@@ -129,6 +129,9 @@
 			<url>https://repo1.maven.org/maven2</url>
 		</pluginRepository>
+		<pluginRepository>
+			<id>artifactory.ewi.tudelft.nl</id>
+			<url>https://artifactory.ewi.tudelft.nl/artifactory/libs-release</url>
+		</pluginRepository>
 	</pluginRepositories>
-
 
 	<build>
Index: /protocol/pom.xml
===================================================================
--- /protocol/pom.xml	(revision 33)
+++ /protocol/pom.xml	(revision 34)
@@ -6,5 +6,5 @@
 	<groupId>geniusweb</groupId>
 	<artifactId>protocol</artifactId>
-	<version>2.0.0</version> <!-- must equal ${geniusweb.version} -->
+	<version>2.0.1</version> <!-- must equal ${geniusweb.version} -->
 	<packaging>jar</packaging>
 
@@ -17,5 +17,5 @@
 		<passwd>${env.ARTIFACTORY_PASS}</passwd>
 		<jackson-2-version>2.12.3</jackson-2-version>
-		<geniusweb.version>2.0.0</geniusweb.version>
+		<geniusweb.version>2.0.1</geniusweb.version>
 	</properties>
 
@@ -120,6 +120,6 @@
 		<dependency>
 			<groupId>org.mockito</groupId>
-			<artifactId>mockito-all</artifactId>
-			<version>1.9.5</version>
+			<artifactId>mockito-core</artifactId>
+			<version>3.11.2</version>
 			<scope>test</scope>
 		</dependency>
@@ -144,6 +144,9 @@
 			<url>https://repo1.maven.org/maven2</url>
 		</pluginRepository>
+		<pluginRepository>
+			<id>artifactory.ewi.tudelft.nl</id>
+			<url>https://artifactory.ewi.tudelft.nl/artifactory/libs-release</url>
+		</pluginRepository>
 	</pluginRepositories>
-
 
 	<build>
Index: /protocol/src/main/java/geniusweb/protocol/CurrentNegoState.java
===================================================================
--- /protocol/src/main/java/geniusweb/protocol/CurrentNegoState.java	(revision 33)
+++ /protocol/src/main/java/geniusweb/protocol/CurrentNegoState.java	(revision 34)
@@ -14,6 +14,41 @@
 	}
 
+	public CurrentNegoState(NegoState state, Long now) {
+		super(now);
+		this.state = state;
+	}
+
 	public NegoState getState() {
 		return state;
 	}
+
+	@Override
+	public String toString() {
+		return "CurrentNegoState[" + getTime() + "," + state + "]";
+	}
+
+	@Override
+	public int hashCode() {
+		final int prime = 31;
+		int result = super.hashCode();
+		result = prime * result + ((state == null) ? 0 : state.hashCode());
+		return result;
+	}
+
+	@Override
+	public boolean equals(Object obj) {
+		if (this == obj)
+			return true;
+		if (!super.equals(obj))
+			return false;
+		if (getClass() != obj.getClass())
+			return false;
+		CurrentNegoState other = (CurrentNegoState) obj;
+		if (state == null) {
+			if (other.state != null)
+				return false;
+		} else if (!state.equals(other.state))
+			return false;
+		return true;
+	}
 }
Index: /protocol/src/main/java/geniusweb/protocol/ProtocolException.java
===================================================================
--- /protocol/src/main/java/geniusweb/protocol/ProtocolException.java	(revision 33)
+++ /protocol/src/main/java/geniusweb/protocol/ProtocolException.java	(revision 34)
@@ -14,5 +14,7 @@
 	 * @param message the error message
 	 * @param party   offending party, either the {@link PartyId} or a
-	 *                {@link PartyRef}
+	 *                {@link PartyRef}. In exceptional cases this can be null,
+	 *                eg if it can not be determined which party failed. Null
+	 *                should be avoided if possible at all.
 	 */
 	public ProtocolException(String message, PartyId party) {
@@ -29,5 +31,7 @@
 	 * 
 	 * @param message the error message
-	 * @param party   offending {@link PartyId}
+	 * @param party   offending {@link PartyId}. In exceptional cases this can
+	 *                be null, eg if it can not be determined which party
+	 *                failed. Null should be avoided if possible at all.
 	 * @param e       the cause of the error
 	 */
@@ -39,5 +43,6 @@
 	/**
 	 * 
-	 * @return offending party, either the {@link PartyId} or a {@link PartyRef}
+	 * @return offending party, either the {@link PartyId} or a
+	 *         {@link PartyRef}. In exceptional cases this can be null.
 	 */
 	public PartyId getParty() {
Index: /protocol/src/main/java/geniusweb/protocol/session/DefaultSessionState.java
===================================================================
--- /protocol/src/main/java/geniusweb/protocol/session/DefaultSessionState.java	(revision 33)
+++ /protocol/src/main/java/geniusweb/protocol/session/DefaultSessionState.java	(revision 34)
@@ -65,15 +65,15 @@
 			this.partyprofiles = Collections.emptyMap();
 		} else {
-			this.partyprofiles = partyprofiles;
+			this.partyprofiles = new HashMap<>(partyprofiles);
 		}
 		if (conns == null) {
 			this.connections = Collections.emptyList();
 		} else {
-			this.connections = conns;
+			this.connections = new LinkedList<>(conns);
 		}
 		if (actions == null) {
 			this.actions = new LinkedList<>();
 		} else {
-			this.actions = actions;
+			this.actions = new LinkedList<>(actions);
 		}
 
@@ -115,5 +115,5 @@
 	 */
 	public List<PartyId> getConnections() {
-		return connections;
+		return Collections.unmodifiableList(connections);
 	}
 
@@ -124,5 +124,5 @@
 	 */
 	public Map<PartyId, PartyWithProfile> getPartyProfiles() {
-		return partyprofiles;
+		return Collections.unmodifiableMap(partyprofiles);
 	}
 
Index: /protocol/src/main/java/geniusweb/protocol/session/SessionResult.java
===================================================================
--- /protocol/src/main/java/geniusweb/protocol/session/SessionResult.java	(revision 33)
+++ /protocol/src/main/java/geniusweb/protocol/session/SessionResult.java	(revision 34)
@@ -2,4 +2,5 @@
 
 import java.util.Collections;
+import java.util.HashMap;
 import java.util.Map;
 
@@ -49,7 +50,7 @@
 			@JsonProperty("penalties") Map<PartyId, Double> penalties,
 			@JsonProperty("error") Throwable error) {
-		this.participants = participants;
+		this.participants = new HashMap<>(participants);
 		this.agreements = agreements;
-		this.penalties = penalties;
+		this.penalties = new HashMap<>(penalties);
 		this.error = error;
 	}
Index: /protocol/src/main/java/geniusweb/protocol/session/SessionState.java
===================================================================
--- /protocol/src/main/java/geniusweb/protocol/session/SessionState.java	(revision 33)
+++ /protocol/src/main/java/geniusweb/protocol/session/SessionState.java	(revision 34)
@@ -60,7 +60,6 @@
 	/**
 	 * 
-	 * @return the current standing agreement, or null if there is no agreement
-	 *         at this point. An agreement does not necessarily mean
-	 *         {@link #isFinal(long)}.
+	 * @return the current standing {@link Agreements}. An agreement does not
+	 *         necessarily mean {@link #isFinal(long)}.
 	 */
 	Agreements getAgreements();
Index: /protocol/src/main/java/geniusweb/protocol/session/TeamInfo.java
===================================================================
--- /protocol/src/main/java/geniusweb/protocol/session/TeamInfo.java	(revision 33)
+++ /protocol/src/main/java/geniusweb/protocol/session/TeamInfo.java	(revision 34)
@@ -49,5 +49,5 @@
 	 *         teams combined.
 	 */
-	public List<PartyWithProfile> getAllParties() {
+	public List<PartyWithProfile> getParties() {
 		return Collections.unmodifiableList(parties);
 	}
Index: /protocol/src/main/java/geniusweb/protocol/session/amop/AMOPSettings.java
===================================================================
--- /protocol/src/main/java/geniusweb/protocol/session/amop/AMOPSettings.java	(revision 33)
+++ /protocol/src/main/java/geniusweb/protocol/session/amop/AMOPSettings.java	(revision 34)
@@ -70,5 +70,5 @@
 	public List<PartyWithProfile> getAllParties() {
 		return participants.stream()
-				.map(particip -> particip.getAllParties().get(0))
+				.map(particip -> particip.getParties().get(0))
 				.collect(Collectors.toList());
 	}
Index: /protocol/src/main/java/geniusweb/protocol/session/learn/LearnSettings.java
===================================================================
--- /protocol/src/main/java/geniusweb/protocol/session/learn/LearnSettings.java	(revision 33)
+++ /protocol/src/main/java/geniusweb/protocol/session/learn/LearnSettings.java	(revision 34)
@@ -119,5 +119,5 @@
 	public List<PartyWithProfile> getAllParties() {
 		return participants.stream()
-				.map(particip -> particip.getAllParties().get(0))
+				.map(particip -> particip.getParties().get(0))
 				.collect(Collectors.toList());
 	}
Index: /protocol/src/main/java/geniusweb/protocol/session/mopac/MOPACSettings.java
===================================================================
--- /protocol/src/main/java/geniusweb/protocol/session/mopac/MOPACSettings.java	(revision 33)
+++ /protocol/src/main/java/geniusweb/protocol/session/mopac/MOPACSettings.java	(revision 34)
@@ -74,5 +74,5 @@
 	public List<PartyWithProfile> getAllParties() {
 		return participants.stream()
-				.map(particip -> particip.getAllParties().get(0))
+				.map(particip -> particip.getParties().get(0))
 				.collect(Collectors.toList());
 	}
@@ -155,5 +155,5 @@
 				throw new IllegalArgumentException(
 						"All teams must be size 1 but found " + team);
-			PartyWithProfile party = team.getAllParties().get(0);
+			PartyWithProfile party = team.getParties().get(0);
 			Object power = party.getParty().getParameters().get("power");
 			if (power != null) {
Index: /protocol/src/main/java/geniusweb/protocol/session/mopac2/MOPAC2Settings.java
===================================================================
--- /protocol/src/main/java/geniusweb/protocol/session/mopac2/MOPAC2Settings.java	(revision 33)
+++ /protocol/src/main/java/geniusweb/protocol/session/mopac2/MOPAC2Settings.java	(revision 34)
@@ -75,5 +75,5 @@
 	public List<PartyWithProfile> getAllParties() {
 		return participants.stream()
-				.map(particip -> particip.getAllParties().get(0))
+				.map(particip -> particip.getParties().get(0))
 				.collect(Collectors.toList());
 	}
@@ -157,5 +157,5 @@
 				throw new IllegalArgumentException(
 						"All teams must be size 1 but found " + team);
-			PartyWithProfile party = team.getAllParties().get(0);
+			PartyWithProfile party = team.getParties().get(0);
 			Object power = party.getParty().getParameters().get("power");
 			if (power != null) {
Index: /protocol/src/main/java/geniusweb/protocol/session/saop/SAOP.java
===================================================================
--- /protocol/src/main/java/geniusweb/protocol/session/saop/SAOP.java	(revision 33)
+++ /protocol/src/main/java/geniusweb/protocol/session/saop/SAOP.java	(revision 34)
@@ -326,5 +326,6 @@
 	 * 
 	 * @param message The message to attach to the error
-	 * @param party   the party where the error occured
+	 * @param party   the party where the error occured. Can be null in
+	 *                exceptional cases.
 	 * @param e       the exception that occured.
 	 */
@@ -337,5 +338,6 @@
 			setState(state.with(new ProtocolException(message, party, e)));
 		}
-		setState(state.withoutParty(party));
+		if (party != null)
+			setState(state.withoutParty(party));
 		log.log(Level.WARNING, "SAOP protocol intercepted error due to party "
 				+ party + ":" + message, e);
Index: /protocol/src/main/java/geniusweb/protocol/session/saop/SAOPSettings.java
===================================================================
--- /protocol/src/main/java/geniusweb/protocol/session/saop/SAOPSettings.java	(revision 33)
+++ /protocol/src/main/java/geniusweb/protocol/session/saop/SAOPSettings.java	(revision 34)
@@ -67,5 +67,5 @@
 	public List<PartyWithProfile> getAllParties() {
 		return participants.stream()
-				.map(particip -> particip.getAllParties().get(0))
+				.map(particip -> particip.getParties().get(0))
 				.collect(Collectors.toList());
 	}
Index: /protocol/src/main/java/geniusweb/protocol/session/saop/SAOPState.java
===================================================================
--- /protocol/src/main/java/geniusweb/protocol/session/saop/SAOPState.java	(revision 33)
+++ /protocol/src/main/java/geniusweb/protocol/session/saop/SAOPState.java	(revision 34)
@@ -5,4 +5,7 @@
 import java.util.List;
 import java.util.Map;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonProperty;
 
 import geniusweb.actions.Accept;
@@ -28,5 +31,5 @@
 	 * 
 	 * @param actions       the actions done by the parties
-	 * @param conns         the existing party connections. If null, default
+	 * @param connections   the existing party connections. If null, default
 	 *                      empty list is used. Can be less than 2 parties in
 	 *                      the first phases of the setup or after parties
@@ -36,11 +39,15 @@
 	 * @param partyprofiles map with the {@link PartyWithProfile} for connected
 	 *                      parties. null is equivalent to an empty map.
-	 * @param e             the {@link ProtocolException}, or null if none
+	 * @param error         the {@link ProtocolException}, or null if none
 	 *                      occurred.
 	 */
-	public SAOPState(List<Action> actions, List<PartyId> conns,
-			Progress progress, SAOPSettings settings,
-			Map<PartyId, PartyWithProfile> partyprofiles, ProtocolException e) {
-		super(actions, conns, progress, settings, partyprofiles, e);
+	@JsonCreator
+	public SAOPState(@JsonProperty("actions") List<Action> actions,
+			@JsonProperty("connections") List<PartyId> connections,
+			@JsonProperty("progress") Progress progress,
+			@JsonProperty("settings") SAOPSettings settings,
+			@JsonProperty("partyprofiles") Map<PartyId, PartyWithProfile> partyprofiles,
+			@JsonProperty("error") ProtocolException error) {
+		super(actions, connections, progress, settings, partyprofiles, error);
 	}
 
Index: /protocol/src/main/java/geniusweb/protocol/session/shaop/SHAOP.java
===================================================================
--- /protocol/src/main/java/geniusweb/protocol/session/shaop/SHAOP.java	(revision 33)
+++ /protocol/src/main/java/geniusweb/protocol/session/shaop/SHAOP.java	(revision 34)
@@ -166,5 +166,5 @@
 			throws InterruptedException, IOException {
 		List<PartyWithProfile> participants = state.getSettings().getTeams()
-				.stream().map(team -> team.getAllParties())
+				.stream().map(team -> team.getParties())
 				.flatMap(List::stream).collect(Collectors.toList());
 		List<Reference> parties = participants.stream()
Index: /protocol/src/main/java/geniusweb/protocol/session/shaop/SHAOPSettings.java
===================================================================
--- /protocol/src/main/java/geniusweb/protocol/session/shaop/SHAOPSettings.java	(revision 33)
+++ /protocol/src/main/java/geniusweb/protocol/session/shaop/SHAOPSettings.java	(revision 34)
@@ -46,6 +46,6 @@
 				throw new IllegalArgumentException(
 						"Team must be size 2 but found " + team);
-			allParties.add(team.getAllParties().get(SHAOP));
-			allParties.add(team.getAllParties().get(COB));
+			allParties.add(team.getParties().get(SHAOP));
+			allParties.add(team.getParties().get(COB));
 		}
 	}
@@ -82,5 +82,5 @@
 	@Override
 	public List<PartyWithProfile> getAllParties() {
-		return participants.stream().map(team -> team.getAllParties())
+		return participants.stream().map(team -> team.getParties())
 				.flatMap(Collection::stream).collect(Collectors.toList());
 	}
Index: /protocol/src/test/java/geniusweb/protocol/CurrentNegoStateTest.java
===================================================================
--- /protocol/src/test/java/geniusweb/protocol/CurrentNegoStateTest.java	(revision 34)
+++ /protocol/src/test/java/geniusweb/protocol/CurrentNegoStateTest.java	(revision 34)
@@ -0,0 +1,50 @@
+package geniusweb.protocol;
+
+import static org.mockito.Mockito.mock;
+
+import java.util.Arrays;
+import java.util.LinkedList;
+import java.util.List;
+
+import geniusweb.actions.Action;
+import geniusweb.actions.PartyId;
+import geniusweb.progress.Progress;
+import geniusweb.progress.ProgressTime;
+import geniusweb.protocol.session.saop.SAOPSettings;
+import geniusweb.protocol.session.saop.SAOPState;
+import tudelft.utilities.junit.GeneralTests;
+
+public class CurrentNegoStateTest extends GeneralTests<CurrentNegoState> {
+	private PartyId party1 = new PartyId("party1");
+	private PartyId party2 = new PartyId("party2");
+	private List<Action> actions1 = new LinkedList<>();
+
+	private List<PartyId> connections = Arrays.asList(party1);
+	private List<PartyId> connections2 = Arrays.asList(party1, party2);
+
+	private Progress progresstime = mock(ProgressTime.class);
+	private SAOPSettings settings = mock(SAOPSettings.class);
+
+	SAOPState saop1 = new SAOPState(actions1, connections2, progresstime,
+			settings, null, null);
+	SAOPState saop2 = new SAOPState(actions1, connections, progresstime,
+			settings, null, null);
+
+	CurrentNegoState state1 = new CurrentNegoState(saop1);
+	CurrentNegoState state1a = new CurrentNegoState(saop1);
+	CurrentNegoState state2 = new CurrentNegoState(saop2);
+
+	@Override
+	public List<List<CurrentNegoState>> getGeneralTestData() {
+		return Arrays.asList(Arrays.asList(state1, state1a),
+				Arrays.asList(state2));
+	}
+
+	@Override
+	public List<String> getGeneralTestStrings() {
+		return Arrays.asList(
+				"CurrentNegoState.*SAOPState.*party1.*party2.*ProgressTime.*SAOPSettings.*",
+				"CurrentNegoState.*SAOPState.*party1.*ProgressTime.*SAOPSettings.*");
+	}
+
+}
Index: /protocol/src/test/java/geniusweb/protocol/ProtocolExceptionTest.java
===================================================================
--- /protocol/src/test/java/geniusweb/protocol/ProtocolExceptionTest.java	(revision 34)
+++ /protocol/src/test/java/geniusweb/protocol/ProtocolExceptionTest.java	(revision 34)
@@ -0,0 +1,52 @@
+package geniusweb.protocol;
+
+import static org.junit.Assert.assertEquals;
+
+import java.io.IOException;
+
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Test;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.util.ObjectBuffer;
+
+import geniusweb.actions.PartyId;
+
+public class ProtocolExceptionTest {
+	private ObjectBuffer jackson = new ObjectBuffer();
+	private Exception exception;
+	private String asString1 = "{\"cause\":null,\"stackTrace\":[],\"party\":\"party1\",\"message\":\"party1:test\",\"localizedMessage\":\"party1:test\",\"suppressed\":[]}";
+
+	@Before
+	public void before() {
+		try {
+			throw new ProtocolException("test", new PartyId("party1"));
+			// int x = 1 / 0;
+		} catch (Exception e) {
+			this.exception = e;
+			System.out.println(e);
+		}
+	}
+
+	@Test
+	public void testSerialize() throws JsonProcessingException {
+
+		ObjectMapper jackson = new ObjectMapper();
+		System.out.println(jackson.writeValueAsString(exception));
+		assertEquals(asString1, jackson.writeValueAsString(exception));
+
+	}
+
+	// ProtocolExceptions can not be deserialized now
+	@Ignore
+	@Test
+	public void testDeserialize() throws IOException {
+
+		ObjectMapper jackson = new ObjectMapper();
+		Exception read = jackson.readValue(asString1, ProtocolException.class);
+		assertEquals(exception, read);
+	}
+
+}
Index: /protocol/src/test/java/geniusweb/protocol/session/mopac/MOPACSettingsTest.java
===================================================================
--- /protocol/src/test/java/geniusweb/protocol/session/mopac/MOPACSettingsTest.java	(revision 33)
+++ /protocol/src/test/java/geniusweb/protocol/session/mopac/MOPACSettingsTest.java	(revision 34)
@@ -66,5 +66,5 @@
 		when(team.getSize()).thenReturn(1);
 		PartyWithParameters pwithp = mock(PartyWithParameters.class);
-		when(team.getAllParties()).thenReturn(Arrays
+		when(team.getParties()).thenReturn(Arrays
 				.asList(new PartyWithProfile(pwithp, mock(ProfileRef.class))));
 		when(team.toString()).thenReturn(partyname);
Index: /protocol/src/test/java/geniusweb/protocol/session/mopac/MOPACStateTest.java
===================================================================
--- /protocol/src/test/java/geniusweb/protocol/session/mopac/MOPACStateTest.java	(revision 33)
+++ /protocol/src/test/java/geniusweb/protocol/session/mopac/MOPACStateTest.java	(revision 34)
@@ -87,5 +87,5 @@
 		PartyWithParameters pwithp = mock(PartyWithParameters.class);
 		when(pwithp.getParameters()).thenReturn(new Parameters());
-		when(party.getAllParties()).thenReturn(Arrays
+		when(party.getParties()).thenReturn(Arrays
 				.asList(new PartyWithProfile(pwithp, mock(ProfileRef.class))));
 		when(party.getSize()).thenReturn(1);
Index: /protocol/src/test/java/geniusweb/protocol/session/mopac2/MOPAC2SettingsTest.java
===================================================================
--- /protocol/src/test/java/geniusweb/protocol/session/mopac2/MOPAC2SettingsTest.java	(revision 33)
+++ /protocol/src/test/java/geniusweb/protocol/session/mopac2/MOPAC2SettingsTest.java	(revision 34)
@@ -65,5 +65,5 @@
 		when(team.getSize()).thenReturn(1);
 		PartyWithParameters pwithp = mock(PartyWithParameters.class);
-		when(team.getAllParties()).thenReturn(Arrays
+		when(team.getParties()).thenReturn(Arrays
 				.asList(new PartyWithProfile(pwithp, mock(ProfileRef.class))));
 		when(team.toString()).thenReturn(partyname);
Index: /protocol/src/test/java/geniusweb/protocol/session/mopac2/MOPAC2StateTest.java
===================================================================
--- /protocol/src/test/java/geniusweb/protocol/session/mopac2/MOPAC2StateTest.java	(revision 33)
+++ /protocol/src/test/java/geniusweb/protocol/session/mopac2/MOPAC2StateTest.java	(revision 34)
@@ -91,5 +91,5 @@
 		PartyWithParameters pwithp = mock(PartyWithParameters.class);
 		when(pwithp.getParameters()).thenReturn(new Parameters());
-		when(party.getAllParties()).thenReturn(Arrays
+		when(party.getParties()).thenReturn(Arrays
 				.asList(new PartyWithProfile(pwithp, mock(ProfileRef.class))));
 		when(party.getSize()).thenReturn(1);
Index: /protocol/src/test/java/geniusweb/protocol/session/saop/SAOPStateTest.java
===================================================================
--- /protocol/src/test/java/geniusweb/protocol/session/saop/SAOPStateTest.java	(revision 33)
+++ /protocol/src/test/java/geniusweb/protocol/session/saop/SAOPStateTest.java	(revision 34)
@@ -9,4 +9,6 @@
 import static org.mockito.Mockito.when;
 
+import java.io.IOException;
+import java.net.URISyntaxException;
 import java.util.Arrays;
 import java.util.Date;
@@ -16,4 +18,7 @@
 import org.junit.Before;
 import org.junit.Test;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
 
 import geniusweb.actions.Accept;
@@ -22,11 +27,19 @@
 import geniusweb.actions.Offer;
 import geniusweb.actions.PartyId;
+import geniusweb.deadline.Deadline;
+import geniusweb.deadline.DeadlineTime;
 import geniusweb.issuevalue.Bid;
 import geniusweb.progress.Progress;
 import geniusweb.progress.ProgressRounds;
 import geniusweb.progress.ProgressTime;
+import geniusweb.protocol.NegoState;
 import geniusweb.protocol.ProtocolException;
 import geniusweb.protocol.partyconnection.ProtocolToPartyConn;
+import geniusweb.protocol.session.TeamInfo;
+import geniusweb.references.Parameters;
+import geniusweb.references.PartyRef;
+import geniusweb.references.PartyWithParameters;
 import geniusweb.references.PartyWithProfile;
+import geniusweb.references.ProfileRef;
 import tudelft.utilities.junit.GeneralTests;
 
@@ -37,5 +50,5 @@
 	private PartyId party2 = new PartyId("party2");
 	private PartyId party3 = new PartyId("party3");
-	private List<Action> actions = new LinkedList<>();
+	private List<Action> actions1 = new LinkedList<>();
 	private Action action = mock(Action.class);
 	private List<Action> actions2 = Arrays.asList(action);
@@ -53,5 +66,5 @@
 	private ProgressRounds progressrounds1 = mock(ProgressRounds.class);
 	private SAOPSettings settings = mock(SAOPSettings.class);
-	private SAOPState state1, state1a, state2, state3, state4;
+	private SAOPState state, state1, state1a, state2, state3, state4;
 
 	private Bid bid1 = mock(Bid.class);
@@ -63,6 +76,10 @@
 	private EndNegotiation endNegotiation1 = new EndNegotiation(party1);
 
+	private final ObjectMapper jackson = new ObjectMapper();
+
+	private String serialized = "{\"SAOPState\":{\"actions\":[],\"connections\":[\"party1\",\"party2\"],\"progress\":{\"ProgressTime\":{\"duration\":1000000,\"start\":2000000}},\"settings\":{\"SAOPSettings\":{\"participants\":[{\"TeamInfo\":{\"parties\":[{\"party\":{\"partyref\":\"party1ref\",\"parameters\":{}},\"profile\":\"prof1\"}]}}],\"deadline\":{\"DeadlineTime\":{\"durationms\":123000}}}},\"partyprofiles\":{},\"error\":null}}";
+
 	@Before
-	public void before() {
+	public void before() throws URISyntaxException {
 		when(party1conn.getParty()).thenReturn(party1);
 		when(party2conn.getParty()).thenReturn(party2);
@@ -79,14 +96,26 @@
 		when(progressrounds.advance()).thenReturn(progressrounds1);
 
-		state1 = new SAOPState(actions, connections, progresstime, settings,
-				null, null);
-		state1a = new SAOPState(actions, connections, progresstime, settings,
+		state1 = new SAOPState(actions1, connections, progresstime, settings,
+				null, null);
+		state1a = new SAOPState(actions1, connections, progresstime, settings,
 				null, null);
 		state2 = new SAOPState(actions2, connections, progresstime, settings,
 				null, null);
-		state3 = new SAOPState(actions, connections2, progresstime, settings,
-				null, null);
-		state4 = new SAOPState(actions, connections, progressrounds, settings,
-				null, null);
+		state3 = new SAOPState(actions1, connections2, progresstime, settings,
+				null, null);
+		state4 = new SAOPState(actions1, connections, progressrounds, settings,
+				null, null);
+
+		List<PartyId> conns = Arrays.asList(party1, party2);
+		PartyWithParameters pwithp = new PartyWithParameters(
+				new PartyRef("party1ref"), new Parameters());
+		List<PartyWithProfile> teams = Arrays
+				.asList(new PartyWithProfile(pwithp, new ProfileRef("prof1")));
+		List<TeamInfo> participants = Arrays.asList(new TeamInfo(teams));
+		Deadline deadline = new DeadlineTime(123000);
+		SAOPSettings setts = new SAOPSettings(participants, deadline);
+		state = new SAOPState(actions1, conns,
+				new ProgressTime(1000000l, new Date(2000000l)), setts, null,
+				null);
 
 	}
@@ -110,5 +139,5 @@
 	@Test
 	public void constructWith0Connection() {
-		new SAOPState(actions, Arrays.asList(), progresstime, settings, null,
+		new SAOPState(actions1, Arrays.asList(), progresstime, settings, null,
 				null);
 	}
@@ -116,5 +145,5 @@
 	@Test
 	public void constructWithNullConnection() {
-		SAOPState state = new SAOPState(actions, null, progresstime, settings,
+		SAOPState state = new SAOPState(actions1, null, progresstime, settings,
 				null, null);
 		assertEquals(0, state.getConnections().size());
@@ -129,5 +158,5 @@
 	public void testNextActor2() {
 		List<PartyId> conns = Arrays.asList(party2, party3);
-		SAOPState state = new SAOPState(actions, conns, progresstime, settings,
+		SAOPState state = new SAOPState(actions1, conns, progresstime, settings,
 				null, null);
 		assertEquals(party2, state.getNextActor());
@@ -153,5 +182,5 @@
 	public void isFinalTest() {
 		assertFalse(state1.isFinal(NOW));
-		SAOPState state = new SAOPState(actions, connections, progresstime,
+		SAOPState state = new SAOPState(actions1, connections, progresstime,
 				settings, null, mock(ProtocolException.class));
 		assertTrue(state.isFinal(NOW));
@@ -216,13 +245,4 @@
 
 	@Test(expected = IllegalArgumentException.class)
-	public void withWrongActionTest() {
-		// wrong because action has actor null which does not match party1
-		SAOPState state = state1.with(party1, action);
-//		assertEquals(1, state.getActions().size());
-//		assertEquals(action, state.getActions().get(0));
-//		assertTrue(state.isFinal(NOW));
-	}
-
-	@Test(expected = IllegalArgumentException.class)
 	public void withActionTest() {
 		when(action.getActor()).thenReturn(party1);
@@ -249,5 +269,5 @@
 	@Test
 	public void isProtocolErrorFinal() {
-		SAOPState state = new SAOPState(actions, connections3, progressrounds,
+		SAOPState state = new SAOPState(actions1, connections3, progressrounds,
 				settings, null,
 				new ProtocolException("test error", new PartyId("test")));
@@ -259,5 +279,5 @@
 	public void RefuseImmediateAccept() {
 		Accept nullaccept = new Accept(party1, null);
-		SAOPState state = state1.with(party1, nullaccept);
+		state1.with(party1, nullaccept);
 	}
 
@@ -320,3 +340,20 @@
 
 	}
+
+	@Test
+	public void testDeserialize() throws IOException {
+		NegoState obj = jackson.readValue(serialized, NegoState.class);
+		System.out.println(obj);
+		assertEquals(state, obj);
+	}
+
+	@Test
+	public void testSerialize()
+			throws JsonProcessingException, URISyntaxException {
+
+		String string = jackson.writeValueAsString(state);
+		System.out.println(string);
+		assertEquals(serialized, string);
+	}
+
 }
Index: /protocol/src/test/java/geniusweb/protocol/session/saop/SAOPTest.java
===================================================================
--- /protocol/src/test/java/geniusweb/protocol/session/saop/SAOPTest.java	(revision 33)
+++ /protocol/src/test/java/geniusweb/protocol/session/saop/SAOPTest.java	(revision 34)
@@ -3,8 +3,8 @@
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.anyLong;
-import static org.mockito.Matchers.eq;
-import static org.mockito.Matchers.isA;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyLong;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.ArgumentMatchers.isA;
 import static org.mockito.Mockito.doThrow;
 import static org.mockito.Mockito.mock;
@@ -17,4 +17,5 @@
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Collections;
 import java.util.Date;
 import java.util.HashMap;
@@ -27,5 +28,4 @@
 
 import geniusweb.actions.Accept;
-import geniusweb.actions.Action;
 import geniusweb.actions.EndNegotiation;
 import geniusweb.actions.Offer;
@@ -66,4 +66,5 @@
  */
 public class SAOPTest {
+
 	private final SAOPState state = mock(SAOPState.class),
 			connectedstate = mock(SAOPState.class),
@@ -71,5 +72,6 @@
 			finalstate = mock(SAOPState.class);
 
-	private ProtocolRef SAOP;
+	private static final long DEADLINE = 1000l;
+	private ProtocolRef SAOPPROTOCOL;
 	private static final PartyId PARTY2ID = new PartyId("party2");
 	private static final PartyId PARTY1ID = new PartyId("party1");
@@ -95,5 +97,5 @@
 	private final Parameters parameters = new Parameters();
 
-	private final long NOW = 1000;
+//	private final long NOW = 1000;
 	private final PartyWithParameters partywithparam1 = new PartyWithParameters(
 			party1ref, parameters);
@@ -103,8 +105,10 @@
 	private final Deadline deadlinetime = mock(DeadlineTime.class);
 
+	private Map<PartyId, PartyWithProfile> pwpmap;
+
 	@Before
 	public void before()
 			throws URISyntaxException, IOException, NoResourcesNowException {
-		SAOP = new ProtocolRef("SAOP");
+		SAOPPROTOCOL = new ProtocolRef("SAOP");
 
 		profile1 = mock(ProfileRef.class);
@@ -113,6 +117,6 @@
 		PartyWithProfile pwp1 = new PartyWithProfile(partywithparam1, profile1);
 		PartyWithProfile pwp2 = new PartyWithProfile(partywithparam2, profile2);
-		when(team1.getAllParties()).thenReturn(Arrays.asList(pwp1));
-		when(team2.getAllParties()).thenReturn(Arrays.asList(pwp2));
+		when(team1.getParties()).thenReturn(Arrays.asList(pwp1));
+		when(team2.getParties()).thenReturn(Arrays.asList(pwp2));
 
 		partyprofiles = new HashMap<>();
@@ -120,5 +124,9 @@
 		partyprofiles.put(PARTY2ID, team2);
 
-		when(deadlinetime.getDuration()).thenReturn(1000l);
+		pwpmap = new HashMap<>();
+		pwpmap.put(PARTY1ID, pwp1);
+		pwpmap.put(PARTY2ID, pwp2);
+
+		when(deadlinetime.getDuration()).thenReturn(DEADLINE);
 
 		List<TeamInfo> teams = new ArrayList<>();
@@ -139,9 +147,9 @@
 		when(conn2.getParty()).thenReturn(PARTY2ID);
 
-		mockState(connectedstate, "connected state");
-		mockState(state, "initial state");
-		mockState(finalstate, "final state");
+		mockState(connectedstate, "connected state", true);
+		mockState(state, "running state", true);
+		mockState(finalstate, "final state", true);
 		when(finalstate.isFinal(anyLong())).thenReturn(true);
-		mockState(failstate, "fail state");
+		mockState(failstate, "fail state", true);
 		when(failstate.isFinal(anyLong())).thenReturn(true);
 
@@ -171,17 +179,20 @@
 	 * 
 	 * @param state  the state to mock (must be already
-	 * @param asText
+	 * @param asText short name for the state, for debugging
+	 * @param bool   true if parties are connected
 	 */
-	private void mockState(SAOPState state, String asText) {
+	private void mockState(SAOPState state, String asText,
+			boolean isConnected) {
 		when(state.getSettings()).thenReturn(settings);
-		when(state.getConnections())
-				.thenReturn(Arrays.asList(PARTY1ID, PARTY2ID));
-		// when(state.getConnections()).thenReturn(connectionswithparties);
+		if (isConnected) {
+			when(state.getConnections())
+					.thenReturn(Arrays.asList(PARTY1ID, PARTY2ID));
+		} else {
+			when(state.getConnections()).thenReturn(Collections.emptyList());
+		}
 
 		when(state.getProgress()).thenReturn(progress);
 		when(state.with(any(PartyId.class), any(PartyWithProfile.class)))
 				.thenReturn(connectedstate);
-//		when(state.with(any(ProtocolToPartyConn.class),
-//				any(PartyWithProfile.class))).thenReturn(connectedstate);
 		when(state.getNextActor()).thenReturn(PARTY1ID);
 		when(state.with(any(PartyId.class), any(EndNegotiation.class)))
@@ -193,4 +204,5 @@
 		when(state.with(any(ProtocolException.class))).thenReturn(failstate);
 		when(state.getAgreements()).thenReturn(mock(Agreements.class));
+		when(state.getPartyProfiles()).thenReturn(pwpmap);
 	}
 
@@ -260,13 +272,11 @@
 				.forClass(Settings.class);
 		verify(conn1).send(actualsettings.capture());
-		assertEquals(
-				new Settings(PARTY1ID, profile1, SAOP, progress, parameters),
-				actualsettings.getValue());
+		assertEquals(new Settings(PARTY1ID, profile1, SAOPPROTOCOL, progress,
+				parameters), actualsettings.getValue());
 
 		verify(conn2, times(1)).send(any(Settings.class));
 		verify(conn2).send(actualsettings.capture());
-		assertEquals(
-				new Settings(PARTY2ID, profile2, SAOP, progress, parameters),
-				actualsettings.getValue());
+		assertEquals(new Settings(PARTY2ID, profile2, SAOPPROTOCOL, progress,
+				parameters), actualsettings.getValue());
 		verify(state, times(0)).with(any(ProtocolException.class));
 		verify(testlistener, times(0)).notifyChange(any(CurrentState.class));
@@ -283,13 +293,15 @@
 
 	@Test
-	public void testActionRequest() throws IOException {
+	public void testActionRequest() throws IOException, ProtocolException {
+		saop.nextTurn();
+
 		when(state.getNextActor()).thenReturn(PARTY1ID);
-		when(state.with(any(PartyId.class), any(Action.class)))
-				.thenReturn(state);
+		when(state.with(any(PartyId.class), any(EndNegotiation.class)))
+				.thenReturn(finalstate);
 
 		saop.actionRequest(conn1, mock(EndNegotiation.class));
 
 		verify(state, times(0)).with(any(ProtocolException.class));
-		verify(state, times(1)).with(eq(PARTY1ID), any(EndNegotiation.class));
+		verify(state, times(1)).with(eq(PARTY1ID), isA((EndNegotiation.class)));
 		// verify broadcast
 		verify(conn1, times(1)).send(isA(ActionDone.class));
@@ -299,5 +311,6 @@
 		verify(conn1, times(1)).send(isA(YourTurn.class));
 		verify(conn2, times(0)).send(isA(YourTurn.class));
-		verify(testlistener, times(0)).notifyChange(any(CurrentState.class));
+		// listener should be informed about final state.
+		verify(testlistener, times(1)).notifyChange(any(CurrentState.class));
 	}
 
@@ -374,3 +387,20 @@
 		saop.addParticipant(null);
 	}
+
+	@Test
+	public void testDeadlineTimer() throws InterruptedException, IOException {
+		SAOPState unconnectedstate = mock(SAOPState.class);
+		mockState(unconnectedstate, "unconnected state", false);
+		SAOP saopempty = new SAOP(unconnectedstate, new ReportToLogger("test"),
+				new ProtocolToPartyConnections(Collections.emptyList()));
+		saopempty.addListener(testlistener);
+
+		saopempty.start(factory);
+		verify(testlistener, times(0)).notifyChange(any(CurrentState.class));
+		verify(conn1, times(1)).send(isA(YourTurn.class));
+		Thread.sleep(DEADLINE + SAOP.TIME_MARGIN + 100);
+		verify(testlistener, times(1)).notifyChange(any(CurrentState.class));
+		verify(conn1, times(1)).send(isA(Finished.class));
+	}
+
 }
Index: /pythonadapter/pom.xml
===================================================================
--- /pythonadapter/pom.xml	(revision 33)
+++ /pythonadapter/pom.xml	(revision 34)
@@ -6,5 +6,5 @@
 	<groupId>geniusweb</groupId>
 	<artifactId>pythonadapter</artifactId>
-	<version>2.0.0</version> <!-- must equal ${geniusweb.version} -->
+	<version>2.0.1</version> <!-- must equal ${geniusweb.version} -->
 	<packaging>jar</packaging>
 
@@ -17,5 +17,5 @@
 		<passwd>${env.ARTIFACTORY_PASS}</passwd>
 		<jackson-2-version>2.12.3</jackson-2-version>
-		<geniusweb.version>2.0.0</geniusweb.version>
+		<geniusweb.version>2.0.1</geniusweb.version>
 	</properties>
 
@@ -28,5 +28,4 @@
 
 	<dependencies>
-
 		<dependency>
 			<groupId>geniusweb</groupId>
@@ -34,6 +33,4 @@
 			<version>${geniusweb.version}</version>
 		</dependency>
-
-
 
 		<dependency>
@@ -61,6 +58,9 @@
 			<url>https://repo1.maven.org/maven2</url>
 		</pluginRepository>
+		<pluginRepository>
+			<id>artifactory.ewi.tudelft.nl</id>
+			<url>https://artifactory.ewi.tudelft.nl/artifactory/libs-release</url>
+		</pluginRepository>
 	</pluginRepositories>
-
 
 	<build>
Index: /references/pom.xml
===================================================================
--- /references/pom.xml	(revision 33)
+++ /references/pom.xml	(revision 34)
@@ -6,5 +6,5 @@
 	<groupId>geniusweb</groupId>
 	<artifactId>references</artifactId>
-	<version>2.0.0</version> <!-- must equal ${geniusweb.version} -->
+	<version>2.0.1</version> <!-- must equal ${geniusweb.version} -->
 	<packaging>jar</packaging>
 
@@ -17,5 +17,5 @@
 		<passwd>${env.ARTIFACTORY_PASS}</passwd>
 		<jackson-2-version>2.12.3</jackson-2-version>
-		<geniusweb.version>2.0.0</geniusweb.version>
+		<geniusweb.version>2.0.1</geniusweb.version>
 	</properties>
 
@@ -83,6 +83,6 @@
 		<dependency>
 			<groupId>org.mockito</groupId>
-			<artifactId>mockito-all</artifactId>
-			<version>1.9.5</version>
+			<artifactId>mockito-core</artifactId>
+			<version>3.11.2</version>
 			<scope>test</scope>
 		</dependency>
@@ -111,5 +111,9 @@
 		<pluginRepository>
 			<id>central</id>
-			<url>https://repo1.maven.org/</url>
+			<url>https://repo1.maven.org/maven2</url>
+		</pluginRepository>
+		<pluginRepository>
+			<id>artifactory.ewi.tudelft.nl</id>
+			<url>https://artifactory.ewi.tudelft.nl/artifactory/libs-release</url>
 		</pluginRepository>
 	</pluginRepositories>
Index: /simplerunner/pom.xml
===================================================================
--- /simplerunner/pom.xml	(revision 33)
+++ /simplerunner/pom.xml	(revision 34)
@@ -6,5 +6,5 @@
 	<groupId>geniusweb</groupId>
 	<artifactId>simplerunner</artifactId>
-	<version>2.0.0</version> <!-- must equal ${geniusweb.version} -->
+	<version>2.0.1</version> <!-- must equal ${geniusweb.version} -->
 	<packaging>jar</packaging>
 
@@ -17,5 +17,5 @@
 		<passwd>${env.ARTIFACTORY_PASS}</passwd>
 		<jackson-2-version>2.12.3</jackson-2-version>
-		<geniusweb.version>2.0.0</geniusweb.version>
+		<geniusweb.version>2.0.1</geniusweb.version>
 	</properties>
 
@@ -75,6 +75,6 @@
 		<dependency>
 			<groupId>org.mockito</groupId>
-			<artifactId>mockito-all</artifactId>
-			<version>1.9.5</version>
+			<artifactId>mockito-core</artifactId>
+			<version>3.11.2</version>
 			<scope>test</scope>
 		</dependency>
@@ -98,4 +98,8 @@
 			<id>central</id>
 			<url>https://repo1.maven.org/maven2</url>
+		</pluginRepository>
+		<pluginRepository>
+			<id>artifactory.ewi.tudelft.nl</id>
+			<url>https://artifactory.ewi.tudelft.nl/artifactory/libs-release</url>
 		</pluginRepository>
 	</pluginRepositories>
Index: /simplerunner/src/main/java/geniusweb/simplerunner/BasicConnection.java
===================================================================
--- /simplerunner/src/main/java/geniusweb/simplerunner/BasicConnection.java	(revision 33)
+++ /simplerunner/src/main/java/geniusweb/simplerunner/BasicConnection.java	(revision 34)
@@ -82,5 +82,5 @@
 	 */
 	protected synchronized void setError(Throwable e) {
-		if (error != null) {
+		if (error == null) {
 			// maybe log instead?
 			e.printStackTrace();
@@ -137,8 +137,9 @@
 	/**
 	 * 
-	 * @return true iff this connection is open
+	 * @return true iff this connection is open. Returns false also when then
+	 *         handler is in the close-down process
 	 */
 	public boolean isOpen() {
-		return handler != null;
+		return handler != null && !messages.contains(EOS);
 	}
 
Index: /simplerunner/src/main/java/geniusweb/simplerunner/ClassPathConnectionFactory.java
===================================================================
--- /simplerunner/src/main/java/geniusweb/simplerunner/ClassPathConnectionFactory.java	(revision 33)
+++ /simplerunner/src/main/java/geniusweb/simplerunner/ClassPathConnectionFactory.java	(revision 34)
@@ -109,8 +109,11 @@
 		party2protocol = new BasicConnection<Inform, Action>(reference,
 				PROTOCOLURI) {
+
 			@Override
-			protected synchronized void setError(Throwable e) {
-				super.setError(e); // closes party2protocol
-				protocol2party.close();
+			public void close() {
+				if (isOpen()) {
+					super.close();
+					protocol2party.close();
+				}
 			}
 
@@ -123,7 +126,9 @@
 						+ "." + (serialcounter++))) {
 			@Override
-			protected synchronized void setError(Throwable e) {
-				super.setError(e); // closes protocol2party
-				party2protocol.close();
+			public void close() {
+				if (isOpen()) {
+					super.close();
+					party2protocol.close();
+				}
 			}
 
@@ -151,6 +156,13 @@
 	}
 
-	public ProtocolToPartyConn getProtocolToPartyConn() {
+	public BasicConnectionWithParty getProtocolToPartyConn() {
 		return protocol2party;
+	}
+
+	/**
+	 * Internal use for testing
+	 */
+	protected BasicConnection getPartyToProtocolConn() {
+		return party2protocol;
 	}
 
Index: /simplerunner/src/test/java/geniusweb/simplerunner/ClassPathConnectionFactoryTest.java
===================================================================
--- /simplerunner/src/test/java/geniusweb/simplerunner/ClassPathConnectionFactoryTest.java	(revision 33)
+++ /simplerunner/src/test/java/geniusweb/simplerunner/ClassPathConnectionFactoryTest.java	(revision 34)
@@ -1,4 +1,5 @@
 package geniusweb.simplerunner;
 
+import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
 
@@ -16,8 +17,11 @@
 public class ClassPathConnectionFactoryTest {
 	private ClassPathConnectionFactory factory;
+	private PartyRef PARTYREF;
 
 	@Before
-	public void before() {
+	public void before() throws URISyntaxException {
 		factory = new ClassPathConnectionFactory();
+		PARTYREF = new PartyRef(
+				"classpath:geniusweb.exampleparties.randomparty.RandomParty");
 
 	}
@@ -41,8 +45,51 @@
 	@Test
 	public void testRandomParty() throws IOException, URISyntaxException {
-		ConnectionEnd<Action, Inform> party = factory.connect(new PartyRef(
-				"classpath:geniusweb.exampleparties.randomparty.RandomParty"));
+		ConnectionEnd<Action, Inform> party = factory.connect(PARTYREF);
 		assertNotNull(party);
 	}
 
+	@Test
+	public void testConnectionPairProtocolClosesNormally()
+			throws InterruptedException {
+		ConnectionPair cpair = new ConnectionPair(PARTYREF);
+		assertEquals(2, cpair.getOpenConnections().size());
+		cpair.getProtocolToPartyConn().close();
+		Thread.sleep(100);
+
+		assertEquals(0, cpair.getOpenConnections().size());
+
+	}
+
+	@Test
+	public void testConnectionPairProtocolClosesWithExc()
+			throws InterruptedException {
+		ConnectionPair cpair = new ConnectionPair(PARTYREF);
+		assertEquals(2, cpair.getOpenConnections().size());
+		cpair.getProtocolToPartyConn().setError(new Error("test"));
+		Thread.sleep(100);
+		assertEquals(0, cpair.getOpenConnections().size());
+	}
+
+	@Test
+	public void testConnectionPairPartyClosesNormally()
+			throws InterruptedException {
+		ConnectionPair cpair = new ConnectionPair(PARTYREF);
+		assertEquals(2, cpair.getOpenConnections().size());
+		cpair.getPartyToProtocolConn().close();
+		Thread.sleep(100);
+
+		assertEquals(0, cpair.getOpenConnections().size());
+
+	}
+
+	@Test
+	public void testConnectionPairPartyClosesWithExc()
+			throws InterruptedException {
+		ConnectionPair cpair = new ConnectionPair(PARTYREF);
+		assertEquals(2, cpair.getOpenConnections().size());
+		cpair.getPartyToProtocolConn().setError(new Error("test"));
+		Thread.sleep(100);
+		assertEquals(0, cpair.getOpenConnections().size());
+	}
+
 }
Index: /timeline/pom.xml
===================================================================
--- /timeline/pom.xml	(revision 33)
+++ /timeline/pom.xml	(revision 34)
@@ -6,5 +6,5 @@
 	<groupId>geniusweb</groupId>
 	<artifactId>timeline</artifactId>
-	<version>2.0.0</version> <!-- must equal ${geniusweb.version} -->
+	<version>2.0.1</version> <!-- must equal ${geniusweb.version} -->
 	<packaging>jar</packaging>
 
@@ -16,5 +16,5 @@
 		<passwd>${env.ARTIFACTORY_PASS}</passwd>
 		<jackson-2-version>2.12.3</jackson-2-version>
-		<geniusweb.version>2.0.0</geniusweb.version>
+		<geniusweb.version>2.0.1</geniusweb.version>
 	</properties>
 
@@ -77,6 +77,6 @@
 		<dependency>
 			<groupId>org.mockito</groupId>
-			<artifactId>mockito-all</artifactId>
-			<version>1.9.5</version>
+			<artifactId>mockito-core</artifactId>
+			<version>3.11.2</version>
 			<scope>test</scope>
 		</dependency>
@@ -106,4 +106,8 @@
 			<id>central</id>
 			<url>https://repo1.maven.org/maven2</url>
+		</pluginRepository>
+		<pluginRepository>
+			<id>artifactory.ewi.tudelft.nl</id>
+			<url>https://artifactory.ewi.tudelft.nl/artifactory/libs-release</url>
 		</pluginRepository>
 	</pluginRepositories>
Index: /voting/pom.xml
===================================================================
--- /voting/pom.xml	(revision 33)
+++ /voting/pom.xml	(revision 34)
@@ -6,5 +6,5 @@
 	<groupId>geniusweb</groupId>
 	<artifactId>voting</artifactId>
-	<version>2.0.0</version> <!-- must equal ${geniusweb.version} -->
+	<version>2.0.1</version> <!-- must equal ${geniusweb.version} -->
 	<packaging>jar</packaging>
 
@@ -17,5 +17,5 @@
 		<passwd>${env.ARTIFACTORY_PASS}</passwd>
 		<jackson-2-version>2.12.3</jackson-2-version>
-		<geniusweb.version>2.0.0</geniusweb.version>
+		<geniusweb.version>2.0.1</geniusweb.version>
 	</properties>
 
@@ -100,9 +100,8 @@
 		<dependency>
 			<groupId>org.mockito</groupId>
-			<artifactId>mockito-all</artifactId>
-			<version>1.9.5</version>
+			<artifactId>mockito-core</artifactId>
+			<version>3.11.2</version>
 			<scope>test</scope>
 		</dependency>
-
 
 	</dependencies>
@@ -123,4 +122,8 @@
 			<id>central</id>
 			<url>https://repo1.maven.org/maven2</url>
+		</pluginRepository>
+		<pluginRepository>
+			<id>artifactory.ewi.tudelft.nl</id>
+			<url>https://artifactory.ewi.tudelft.nl/artifactory/libs-release</url>
 		</pluginRepository>
 	</pluginRepositories>
