Index: /exampleparties/anac2019/agentgg/pom.xml
===================================================================
--- /exampleparties/anac2019/agentgg/pom.xml	(revision 12)
+++ /exampleparties/anac2019/agentgg/pom.xml	(revision 12)
@@ -0,0 +1,293 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+	<modelVersion>4.0.0</modelVersion>
+
+	<groupId>geniusweb.exampleparties.anac2019</groupId>
+	<artifactId>agentgg</artifactId>
+	<version>1.2.0</version>
+	<packaging>jar</packaging>
+
+
+	<properties>
+		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+		<maven.compiler.target>1.8</maven.compiler.target>
+		<maven.compiler.source>1.8</maven.compiler.source>
+		<basedir>.</basedir>
+		<passwd>${env.ARTIFACTORY_PASS}</passwd>
+		<jackson-2-version>2.9.6</jackson-2-version>
+	</properties>
+
+	<distributionManagement>
+		<repository>
+			<id>artifactory.ewi.tudelft.nl</id>
+			<url>http://artifactory.ewi.tudelft.nl/artifactory/libs-release</url>
+		</repository>
+	</distributionManagement>
+
+
+	<dependencies>
+
+		<dependency>
+			<groupId>geniusweb</groupId>
+			<artifactId>issuevalue</artifactId>
+			<version>1.2.0</version>
+		</dependency>
+
+		<dependency>
+			<groupId>geniusweb</groupId>
+			<artifactId>party</artifactId>
+			<version>1.2.0</version>
+		</dependency>
+
+		<dependency>
+			<groupId>geniusweb</groupId>
+			<artifactId>bidspace</artifactId>
+			<version>1.2.0</version>
+		</dependency>
+		<dependency>
+			<groupId>geniusweb</groupId>
+			<artifactId>profileconnection</artifactId>
+			<version>1.2.0</version>
+		</dependency>
+		<dependency>
+			<groupId>tudelft.utilities</groupId>
+			<artifactId>logging</artifactId>
+			<version>1.0.0</version>
+		</dependency>
+		<dependency>
+			<groupId>tudelft.utilities</groupId>
+			<artifactId>immutablelist</artifactId>
+			<version>1.0.1</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>
+			<scope>test</scope>
+		</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>
+			<scope>test</scope>
+		</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>
+			<scope>test</scope>
+		</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>
+			<scope>test</scope>
+		</dependency>
+		<!-- JAX-RS provider -->
+		<dependency>
+			<groupId>com.fasterxml.jackson.jaxrs</groupId>
+			<artifactId>jackson-jaxrs-json-provider</artifactId>
+			<version>${jackson-2-version}</version>
+			<scope>test</scope>
+		</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>
+			<scope>test</scope>
+		</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.1</version>
+			<scope>test</scope>
+		</dependency>
+
+	</dependencies>
+
+
+	<repositories>
+		<repository>
+			<id>artifactory.ewi.tudelft.nl</id>
+			<url>http://artifactory.ewi.tudelft.nl/artifactory/libs-release</url>
+			<snapshots>
+				<enabled>false</enabled>
+			</snapshots>
+		</repository>
+
+	</repositories>
+
+	<pluginRepositories>
+		<pluginRepository>
+			<id>jcenter</id>
+			<url>http://jcenter.bintray.com</url>
+		</pluginRepository>
+	</pluginRepositories>
+
+
+	<build>
+
+		<plugins>
+			<plugin>
+				<groupId>org.apache.maven.plugins</groupId>
+				<artifactId>maven-compiler-plugin</artifactId>
+				<version>3.8.0</version>
+				<configuration>
+					<source>1.8</source>
+					<target>1.8</target>
+				</configuration>
+			</plugin>
+			<plugin>
+				<groupId>org.apache.maven.plugins</groupId>
+				<artifactId>maven-source-plugin</artifactId>
+				<version>3.1.0</version>
+				<executions>
+					<execution>
+						<id>attach-sources</id>
+						<goals>
+							<goal>jar</goal>
+						</goals>
+					</execution>
+				</executions>
+			</plugin>
+
+			<plugin>
+				<groupId>org.apache.maven.plugins</groupId>
+				<artifactId>maven-jar-plugin</artifactId>
+				<configuration>
+					<archive>
+						<manifest>
+							<mainClass>geniusweb.exampleparties.agentgg.AgentGG</mainClass>
+						</manifest>
+					</archive>
+				</configuration>
+			</plugin>
+
+			<plugin>
+				<groupId>org.apache.maven.plugins</groupId>
+				<artifactId>maven-javadoc-plugin</artifactId>
+				<version>2.10.1</version>
+				<executions>
+					<execution>
+						<id>attach-javadocs</id>
+						<goals>
+							<goal>jar</goal>
+						</goals>
+						<configuration>
+							<additionalparam>${javadoc.opts}</additionalparam>
+							<additionalparam>-Xdoclint:none</additionalparam>
+						</configuration>
+					</execution>
+				</executions>
+			</plugin>
+
+			<plugin>
+				<groupId>org.jfrog.buildinfo</groupId>
+				<artifactId>artifactory-maven-plugin</artifactId>
+				<version>2.6.1</version>
+				<executions>
+					<execution>
+						<id>build-info</id>
+						<goals>
+							<goal>publish</goal>
+						</goals>
+						<configuration>
+							<publisher>
+								<contextUrl>http://artifactory.ewi.tudelft.nl/artifactory</contextUrl>
+								<repoKey>libs-release</repoKey>
+								<username>wouter</username>
+								<password>${passwd}</password>
+							</publisher>
+						</configuration>
+					</execution>
+				</executions>
+			</plugin>
+
+			<plugin>
+				<groupId>org.apache.maven.plugins</groupId>
+				<artifactId>maven-assembly-plugin</artifactId>
+				<version>2.4.1</version>
+				<configuration>
+					<!-- get all project dependencies -->
+					<descriptorRefs>
+						<descriptorRef>jar-with-dependencies</descriptorRef>
+					</descriptorRefs>
+					<archive>
+						<manifest>
+							<addDefaultImplementationEntries>true</addDefaultImplementationEntries>
+							<addDefaultSpecificationEntries>true</addDefaultSpecificationEntries>
+							<mainClass>geniusweb.exampleparties.agentgg.AgentGG</mainClass>
+						</manifest>
+					</archive>
+				</configuration>
+				<executions>
+					<execution>
+						<id>make-assembly</id>
+						<!-- bind to the packaging phase -->
+						<phase>package</phase>
+						<goals>
+							<goal>single</goal>
+						</goals>
+					</execution>
+				</executions>
+			</plugin>
+
+
+		</plugins>
+
+		<pluginManagement>
+			<plugins>
+				<plugin>
+					<groupId>org.eclipse.m2e</groupId>
+					<artifactId>lifecycle-mapping</artifactId>
+					<version>1.0.0</version>
+					<configuration>
+						<lifecycleMappingMetadata>
+							<pluginExecutions>
+								<pluginExecution>
+									<pluginExecutionFilter>
+										<groupId>org.jfrog.buildinfo</groupId>
+										<artifactId>artifactory-maven-plugin</artifactId>
+										<versionRange>[1.0.0,)</versionRange>
+										<goals>
+											<goal>publish</goal>
+										</goals>
+									</pluginExecutionFilter>
+									<action>
+										<ignore />
+									</action>
+								</pluginExecution>
+							</pluginExecutions>
+						</lifecycleMappingMetadata>
+					</configuration>
+				</plugin>
+			</plugins>
+		</pluginManagement>
+
+
+	</build>
+</project>
Index: /exampleparties/anac2019/agentgg/src/main/java/geniusweb/exampleparties/agentgg/AgentGG.java
===================================================================
--- /exampleparties/anac2019/agentgg/src/main/java/geniusweb/exampleparties/agentgg/AgentGG.java	(revision 12)
+++ /exampleparties/anac2019/agentgg/src/main/java/geniusweb/exampleparties/agentgg/AgentGG.java	(revision 12)
@@ -0,0 +1,464 @@
+package geniusweb.exampleparties.agentgg;
+
+import static java.lang.Math.max;
+
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Random;
+import java.util.logging.Level;
+
+import javax.websocket.DeploymentException;
+
+import geniusweb.actions.Accept;
+import geniusweb.actions.Action;
+import geniusweb.actions.Offer;
+import geniusweb.actions.PartyId;
+import geniusweb.bidspace.AllBidsList;
+import geniusweb.issuevalue.Bid;
+import geniusweb.issuevalue.Value;
+import geniusweb.party.Capabilities;
+import geniusweb.party.DefaultParty;
+import geniusweb.party.inform.ActionDone;
+import geniusweb.party.inform.Finished;
+import geniusweb.party.inform.Inform;
+import geniusweb.party.inform.Settings;
+import geniusweb.party.inform.YourTurn;
+import geniusweb.profile.PartialOrdering;
+import geniusweb.profileconnection.ProfileConnectionFactory;
+import geniusweb.profileconnection.ProfileInterface;
+import geniusweb.progress.Progress;
+import geniusweb.progress.ProgressRounds;
+import tudelft.utilities.logging.Reporter;
+
+/**
+ * Translated version of Genius ANAC 2019 AgentGG originally written by Shaobo
+ * Xu and Peihao Ren of University of Southampton. This party requires a partial
+ * ordering as input (notice that most profiles are also partial ordering
+ * anyway).
+ */
+public class AgentGG extends DefaultParty {
+
+	private ImpMap impMap;
+	private ImpMap opponentImpMap;
+	private double offerLowerRatio = 1.0;
+	private double offerHigherRatio = 1.1;
+	private double MAX_IMPORTANCE;
+	private double MIN_IMPORTANCE;
+	private double MEDIAN_IMPORTANCE;
+	private Bid MAX_IMPORTANCE_BID;
+	private Bid MIN_IMPORTANCE_BID;
+	private Bid receivedBid;
+	private double reservationImportanceRatio;
+	private boolean offerRandomly = true;
+
+	private double startTime;
+	private boolean maxOppoBidImpForMeGot = false;
+	private double maxOppoBidImpForMe;
+	private double estimatedNashPoint;
+	private Bid lastReceivedBid;
+	private boolean initialTimePass = false;
+
+	// new for GeniusWeb
+	private ProfileInterface profileint;
+	private PartyId me;
+	private Progress progress;
+	private Action lastReceivedAction = null;
+	private final Random rand = new Random();
+	private AllBidsList allbids; // all bids in domain.
+
+	public AgentGG() {
+		super();
+	}
+
+	public AgentGG(Reporter reporter) {
+		super(reporter);
+	}
+
+	@Override
+	public void notifyChange(Inform info) {
+		try {
+			if (info instanceof Settings) {
+				init((Settings) info);
+			} else if (info instanceof ActionDone) {
+				lastReceivedAction = ((ActionDone) info).getAction();
+				if (lastReceivedAction instanceof Offer) {
+					this.receivedBid = ((Offer) lastReceivedAction).getBid();
+				}
+			} else if (info instanceof YourTurn) {
+				Action action = chooseAction();
+				getConnection().send(action);
+				if (progress instanceof ProgressRounds) {
+					progress = ((ProgressRounds) progress).advance();
+				}
+			} else if (info instanceof Finished) {
+				getReporter().log(Level.INFO, "Final ourcome:" + info);
+			}
+		} catch (Exception e) {
+			throw new RuntimeException("Failed to handle info", e);
+		}
+	}
+
+	@Override
+	public Capabilities getCapabilities() {
+		return new Capabilities(new HashSet<>(Arrays.asList("SAOP")));
+	}
+
+	@Override
+	public String getDescription() {
+		return "ANAC 2019 AgentGG translated to GeniusWeb. Requires partial profile. Use frequency counting to estimate important opponent values. ";
+	}
+
+	/***************
+	 * private
+	 * 
+	 * @throws DeploymentException
+	 *********************/
+
+	private void init(Settings info) throws IOException, DeploymentException {
+		this.me = info.getID();
+		this.progress = info.getProgress();
+
+		this.profileint = ProfileConnectionFactory
+				.create(info.getProfile().getURI(), getReporter());
+		PartialOrdering partialprofile = (PartialOrdering) profileint
+				.getProfile();
+		allbids = new AllBidsList(partialprofile.getDomain());
+
+		// Create empty my import map
+		this.impMap = new ImpMap(partialprofile);
+		// and opponent's value map. CHECK why is the opponent map not initially
+		// empty?
+		this.opponentImpMap = new ImpMap(partialprofile);
+
+		// Wouter we use SimpleLinearOrdering (from shaop party) to get sorted
+		// bids from our profile.
+		List<Bid> orderedbids = new SimpleLinearOrdering(
+				profileint.getProfile()).getBids();
+
+		// Update my importance map
+		this.impMap.self_update(orderedbids);
+
+		// Get maximum, minimum, median bid
+		this.getMaxAndMinBid();
+		this.getMedianBid(orderedbids);
+
+		// Get the reservation value, converted to the percentage of importance
+		this.reservationImportanceRatio = this.getReservationRatio();
+
+		getReporter().log(Level.INFO,
+				"reservation ratio: " + this.reservationImportanceRatio);
+		getReporter().log(Level.INFO,
+				"my max importance bid: " + this.MAX_IMPORTANCE_BID);
+		getReporter().log(Level.INFO,
+				"my max importance: " + this.MAX_IMPORTANCE);
+		getReporter().log(Level.INFO,
+				"my min importance bid: " + this.MIN_IMPORTANCE_BID);
+		getReporter().log(Level.INFO,
+				"my min importance: " + this.MIN_IMPORTANCE);
+		getReporter().log(Level.INFO,
+				"my median importance: " + this.MEDIAN_IMPORTANCE);
+		getReporter().log(Level.INFO,
+				"Party " + me + " has finished initialization");
+	}
+
+	private Action chooseAction() {
+		double time = progress.get(System.currentTimeMillis());
+
+		// Start competition
+		if (!(this.lastReceivedAction instanceof Offer))
+			return new Offer(me, this.MAX_IMPORTANCE_BID);
+
+		// The ratio of the other party's offer to me
+		double impRatioForMe = (this.impMap.getImportance(this.receivedBid)
+				- this.MIN_IMPORTANCE)
+				/ (this.MAX_IMPORTANCE - this.MIN_IMPORTANCE);
+
+		// Accept the terms of the offer, which is higher than my threshold
+		if (impRatioForMe >= this.offerLowerRatio) {
+			getReporter().log(Level.INFO, "\n\naccepted agent: Agent" + me);
+			getReporter().log(Level.INFO, "last bid: " + this.receivedBid);
+			getReporter().log(Level.INFO,
+					"\ncurrent threshold: " + this.offerLowerRatio);
+			getReporter().log(Level.INFO, "\n\n");
+			return new Accept(me, this.receivedBid);
+		}
+
+		// When the opponent's importance is around 1.0, how much can he get.
+		// Finding the endpoints of the Pareto boundary
+		if (!maxOppoBidImpForMeGot)
+			this.getMaxOppoBidImpForMe(time, 3.0 / 1000.0);
+
+		// Update opponent importance table
+		if (time < 0.3)
+			this.opponentImpMap.opponent_update(this.receivedBid);
+
+		// Strategy
+		this.getThreshold(time);
+
+		// Last round
+		if (time >= 0.9989) {
+			double ratio = (this.impMap.getImportance(this.receivedBid)
+					- this.MIN_IMPORTANCE)
+					/ (this.MAX_IMPORTANCE - this.MIN_IMPORTANCE);
+			if (ratio > this.reservationImportanceRatio + 0.2) {
+				return new Accept(me, receivedBid);
+			}
+		}
+
+		getReporter().log(Level.INFO,
+				"high threshold: " + this.offerHigherRatio);
+		getReporter().log(Level.INFO, "low threshold: " + this.offerLowerRatio);
+		getReporter().log(Level.INFO,
+				"estimated nash: " + this.estimatedNashPoint);
+		getReporter().log(Level.INFO,
+				"reservation: " + this.reservationImportanceRatio);
+
+		Bid bid = getNeededRandomBid(this.offerLowerRatio,
+				this.offerHigherRatio);
+		this.lastReceivedBid = this.receivedBid;
+		return new Offer(me, bid);
+	}
+
+	/**
+	 * Get our optimal value (Pareto optimal boundary point) when the utility of
+	 * the other party is around 1.0 The opponent may first report the same bid
+	 * several times, ignore it, and start timing at different times. For
+	 * durations (such as 20 rounds), choose the bid with the highest importance
+	 * for me. Since the bid of the other party must be very important to the
+	 * other party at this time, it can meet our requirements.
+	 */
+	private void getMaxOppoBidImpForMe(double time, double timeLast) {
+		double thisBidImp = this.impMap.getImportance(this.receivedBid);
+		if (thisBidImp > this.maxOppoBidImpForMe)
+			this.maxOppoBidImpForMe = thisBidImp;
+
+		if (this.initialTimePass) {
+			if (time - this.startTime > timeLast) {
+				double maxOppoBidRatioForMe = (this.maxOppoBidImpForMe
+						- this.MIN_IMPORTANCE)
+						/ (this.MAX_IMPORTANCE - this.MIN_IMPORTANCE);
+				this.estimatedNashPoint = (1 - maxOppoBidRatioForMe) / 1.7
+						+ maxOppoBidRatioForMe; // 1.414 是圆，2是直线
+				this.maxOppoBidImpForMeGot = true;
+			}
+		} else {
+			if (this.lastReceivedBid != this.receivedBid) {
+				this.initialTimePass = true;
+				this.startTime = time;
+			}
+		}
+	}
+
+	/**
+	 * Get upper and lower thresholds based on time
+	 */
+	private void getThreshold(double time) {
+		if (time < 0.01) {
+			// The first 10 rounds of 0.9999, in order to adapt to some special
+			// domains
+			this.offerLowerRatio = 0.9999;
+		} else if (time < 0.02) {
+			// 10 ~ 20 rounds of 0.99, in order to adapt to some special domains
+			this.offerLowerRatio = 0.99;
+		} else if (time < 0.2) {
+			// 20 ~ 200 rounds reported high price, dropped to 0.9
+			this.offerLowerRatio = 0.99 - 0.5 * (time - 0.02);
+		} else if (time < 0.5) {
+			this.offerRandomly = false;
+			// 200 ~ 500 rounds gradually reduce the threshold to 0.5 from the
+			// estimated Nash point
+			double p2 = 0.3 * (1 - this.estimatedNashPoint)
+					+ this.estimatedNashPoint;
+			this.offerLowerRatio = 0.9
+					- (0.9 - p2) / (0.5 - 0.2) * (time - 0.2);
+		} else if (time < 0.9) {
+			// 500 ~ 900 rounds quickly decrease the threshold to 0.2 from the
+			// estimated Nash point
+			double p1 = 0.3 * (1 - this.estimatedNashPoint)
+					+ this.estimatedNashPoint;
+			double p2 = 0.15 * (1 - this.estimatedNashPoint)
+					+ this.estimatedNashPoint;
+			this.offerLowerRatio = p1 - (p1 - p2) / (0.9 - 0.5) * (time - 0.5);
+		} else if (time < 0.98) {
+			// Compromise 1
+			double p1 = 0.15 * (1 - this.estimatedNashPoint)
+					+ this.estimatedNashPoint;
+			double p2 = 0.05 * (1 - this.estimatedNashPoint)
+					+ this.estimatedNashPoint;
+			double possibleRatio = p1 - (p1 - p2) / (0.98 - 0.9) * (time - 0.9);
+			this.offerLowerRatio = max(possibleRatio,
+					this.reservationImportanceRatio + 0.3);
+		} else if (time < 0.995) {
+			// Compromise 2 980 ~ 995 rounds
+			double p1 = 0.05 * (1 - this.estimatedNashPoint)
+					+ this.estimatedNashPoint;
+			double p2 = 0.0 * (1 - this.estimatedNashPoint)
+					+ this.estimatedNashPoint;
+			double possibleRatio = p1
+					- (p1 - p2) / (0.995 - 0.98) * (time - 0.98);
+			this.offerLowerRatio = max(possibleRatio,
+					this.reservationImportanceRatio + 0.25);
+		} else if (time < 0.999) {
+			// Compromise 3 995 ~ 999 rounds
+			double p1 = 0.0 * (1 - this.estimatedNashPoint)
+					+ this.estimatedNashPoint;
+			double p2 = -0.35 * (1 - this.estimatedNashPoint)
+					+ this.estimatedNashPoint;
+			double possibleRatio = p1
+					- (p1 - p2) / (0.9989 - 0.995) * (time - 0.995);
+			this.offerLowerRatio = max(possibleRatio,
+					this.reservationImportanceRatio + 0.25);
+		} else {
+			double possibleRatio = -0.4 * (1 - this.estimatedNashPoint)
+					+ this.estimatedNashPoint;
+			this.offerLowerRatio = max(possibleRatio,
+					this.reservationImportanceRatio + 0.2);
+		}
+		this.offerHigherRatio = this.offerLowerRatio + 0.1;
+	}
+
+	/**
+	 * Get the ratio of the reservation value to the importance matrix. ASSUMES
+	 * The imgMap has been initialized.
+	 * 
+	 */
+	private double getReservationRatio() throws IOException {
+		double medianBidRatio = (this.MEDIAN_IMPORTANCE - this.MIN_IMPORTANCE)
+				/ (this.MAX_IMPORTANCE - this.MIN_IMPORTANCE);
+		Bid resBid = this.profileint.getProfile().getReservationBid();
+		double resValue = 0.1;
+		if (resBid != null) {
+			resValue = this.impMap.getImportance(resBid);
+		}
+		return resValue * medianBidRatio / 0.5;
+	}
+
+	/**
+	 * Get the maximum and minimum importance values and corresponding offers
+	 */
+	private void getMaxAndMinBid() {
+		HashMap<String, Value> lValues1 = new HashMap<>();
+		HashMap<String, Value> lValues2 = new HashMap<>();
+		for (Map.Entry<String, List<impUnit>> entry : this.impMap.entrySet()) {
+			Value value1 = entry.getValue().get(0).valueOfIssue;
+			Value value2 = entry.getValue()
+					.get(entry.getValue().size() - 1).valueOfIssue;
+			String issue = entry.getKey();
+			lValues1.put(issue, value1);
+			lValues2.put(issue, value2);
+		}
+		this.MAX_IMPORTANCE_BID = new Bid(lValues1);
+		this.MIN_IMPORTANCE_BID = new Bid(lValues2);
+		this.MAX_IMPORTANCE = this.impMap
+				.getImportance(this.MAX_IMPORTANCE_BID);
+		this.MIN_IMPORTANCE = this.impMap
+				.getImportance(this.MIN_IMPORTANCE_BID);
+	}
+
+	/**
+	 * Get the import value corresponding to the median bid in bid ranking
+	 * 
+	 * @param orderedbids a list of bids, ordered from low to high utility.
+	 */
+	private void getMedianBid(List<Bid> orderedbids) {
+
+		int median = (orderedbids.size() - 1) / 2;
+		int median2 = -1;
+		if (orderedbids.size() % 2 == 0) {
+			median2 = median + 1;
+		}
+		int current = 0;
+		for (Bid bid : orderedbids) {
+			current += 1;
+			if (current == median) {
+				this.MEDIAN_IMPORTANCE = this.impMap.getImportance(bid);
+				if (median2 == -1)
+					break;
+			}
+			if (current == median2) {
+				this.MEDIAN_IMPORTANCE += this.impMap.getImportance(bid);
+				break;
+			}
+		}
+		if (median2 != -1)
+			this.MEDIAN_IMPORTANCE /= 2;
+	}
+
+//    /**
+//     * 更新对手的最大及最小Importance的值及对应OFFER
+//     */
+//    private void getOpponentMaxAndMinBid() {
+//        HashMap<Integer, Value> lValues1 = new HashMap<>();
+//        HashMap<Integer, Value> lValues2 = new HashMap<>();
+//        for (Map.Entry<Issue, List<impUnit>> entry : this.opponentImpMap.entrySet()) {
+//            Value value1 = entry.getValue().get(0).valueOfIssue;
+//            Value value2 = entry.getValue().get(entry.getValue().size() - 1).valueOfIssue;
+//            int issueNumber = entry.getKey().getNumber();
+//            lValues1.put(issueNumber, value1);
+//            lValues2.put(issueNumber, value2);
+//        }
+//        Bid OPPONENT_MAX_IMPORTANCE_BID = new Bid(this.getDomain(), lValues1);
+//        Bid OPPONENT_MIN_IMPORTANCE_BID = new Bid(this.getDomain(), lValues2);
+//        this.OPPONENT_MAX_IMPORTANCE = this.opponentImpMap.getImportance(OPPONENT_MAX_IMPORTANCE_BID);
+//        this.OPPONENT_MIN_IMPORTANCE = this.opponentImpMap.getImportance(OPPONENT_MIN_IMPORTANCE_BID);
+//    }
+
+	/**
+	 * Get eligible random bids. Generate k bids randomly, select bids within
+	 * the threshold range, and return the bid with the highest opponent import.
+	 *
+	 * @param lowerRatio Generate a lower limit for the random bid
+	 * @param upperRatio Generate random bid upper limit
+	 * @return Bid
+	 * @throws IOException
+	 */
+	private Bid getNeededRandomBid(double lowerRatio, double upperRatio) {
+		final long k = 2 * this.allbids.size().longValue();
+		double lowerThreshold = lowerRatio
+				* (this.MAX_IMPORTANCE - this.MIN_IMPORTANCE)
+				+ this.MIN_IMPORTANCE;
+		double upperThreshold = upperRatio
+				* (this.MAX_IMPORTANCE - this.MIN_IMPORTANCE)
+				+ this.MIN_IMPORTANCE;
+
+		for (int t = 0; t < 3; t++) {
+			double highest_opponent_importance = 0.0;
+			Bid returnedBid = null;
+			for (int i = 0; i < k; i++) {
+				Bid bid = generateRandomBid();
+				double bidImportance = this.impMap.getImportance(bid);
+				double bidOpponentImportance = this.opponentImpMap
+						.getImportance(bid);
+				if (bidImportance >= lowerThreshold
+						&& bidImportance <= upperThreshold) {
+					if (this.offerRandomly)
+						return bid; // Randomly bid for the first 0.2 time
+					if (bidOpponentImportance > highest_opponent_importance) {
+						highest_opponent_importance = bidOpponentImportance;
+						returnedBid = bid;
+					}
+				}
+			}
+			if (returnedBid != null) {
+				return returnedBid;
+			}
+		}
+		// If something goes wrong and no suitable bid is found, then a higher
+		// than the lower limit
+		while (true) {
+			Bid bid = generateRandomBid();
+			if (this.impMap.getImportance(bid) >= lowerThreshold) {
+				return bid;
+			}
+		}
+	}
+
+	private Bid generateRandomBid() {
+		return allbids.get(rand.nextInt(allbids.size().intValue()));
+	}
+
+}
Index: /exampleparties/anac2019/agentgg/src/main/java/geniusweb/exampleparties/agentgg/ImpMap.java
===================================================================
--- /exampleparties/anac2019/agentgg/src/main/java/geniusweb/exampleparties/agentgg/ImpMap.java	(revision 12)
+++ /exampleparties/anac2019/agentgg/src/main/java/geniusweb/exampleparties/agentgg/ImpMap.java	(revision 12)
@@ -0,0 +1,134 @@
+package geniusweb.exampleparties.agentgg;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import geniusweb.issuevalue.Bid;
+import geniusweb.issuevalue.Domain;
+import geniusweb.issuevalue.Value;
+import geniusweb.issuevalue.ValueSet;
+import geniusweb.profile.PartialOrdering;
+
+/**
+ * Importance map. One is created for each party. The key (String) is the issue
+ * and value is list of Importances of the values.
+ *
+ */
+@SuppressWarnings("serial")
+public class ImpMap extends HashMap<String, List<impUnit>> {
+	private Domain domain;
+
+	// importance map
+	public ImpMap(PartialOrdering profile) {
+		super();
+		this.domain = profile.getDomain();
+		// Create empty my import map and opponent's value map
+		for (String issue : domain.getIssues()) {
+			ValueSet values = domain.getValues(issue);
+			List<impUnit> issueImpUnit = new ArrayList<>();
+			for (Value value : values) {
+				issueImpUnit.add(new impUnit(value));
+			}
+			this.put(issue, issueImpUnit);
+		}
+	}
+
+	/**
+	 * Update opponent map. Increases the meanWeightSum of the values of this
+	 * bid.
+	 * 
+	 * @param receivedOfferBid tbe received opponent bid.
+	 */
+	public void opponent_update(Bid receivedOfferBid) {
+		for (String issue : receivedOfferBid.getIssues()) {
+			ValueSet values = domain.getValues(issue);
+			List<impUnit> currentIssueList = this.get(issue);
+			for (impUnit currentUnit : currentIssueList) {
+				if (currentUnit.valueOfIssue
+						.equals(receivedOfferBid.getValue(issue))) {
+					currentUnit.meanWeightSum += 1;
+					break;
+				}
+			}
+		}
+		for (List<impUnit> impUnitList : this.values()) {
+			impUnitList.sort(new impUnit.meanWeightSumComparator());
+		}
+	}
+
+	/**
+	 * Update your own importance map Traverse the known bidOrder and update the
+	 * "weight sum" and "number of times" in the import table.
+	 * 
+	 * @param bids a list of ordered bids, worst bid first, best bid last
+	 */
+	public void self_update(List<Bid> bidOrdering) {
+		int currentWeight = 0;
+		for (Bid bid : bidOrdering) {
+			currentWeight += 1;
+			for (String issue : bid.getIssues()) {
+				List<impUnit> currentIssueList = this.get(issue);
+				for (impUnit currentUnit : currentIssueList) {
+					if (currentUnit.valueOfIssue.toString()
+							.equals(bid.getValue(issue).toString())) {
+						currentUnit.weightSum += currentWeight;
+						currentUnit.count += 1;
+						break;
+					}
+				}
+			}
+		}
+		// Calculate weights
+		for (List<impUnit> impUnitList : this.values()) {
+			for (impUnit currentUnit : impUnitList) {
+				if (currentUnit.count == 0) {
+					currentUnit.meanWeightSum = 0.0;
+				} else {
+					currentUnit.meanWeightSum = (double) currentUnit.weightSum
+							/ (double) currentUnit.count;
+				}
+			}
+		}
+		// Sort
+		for (List<impUnit> impUnitList : this.values()) {
+			impUnitList.sort(new impUnit.meanWeightSumComparator());
+		}
+		// Find the minimum
+		double minMeanWeightSum = Double.POSITIVE_INFINITY;
+		for (Map.Entry<String, List<impUnit>> entry : this.entrySet()) {
+			double tempMeanWeightSum = entry.getValue()
+					.get(entry.getValue().size() - 1).meanWeightSum;
+			if (tempMeanWeightSum < minMeanWeightSum) {
+				minMeanWeightSum = tempMeanWeightSum;
+			}
+		}
+		// Minus all values
+		for (List<impUnit> impUnitList : this.values()) {
+			for (impUnit currentUnit : impUnitList) {
+				currentUnit.meanWeightSum -= minMeanWeightSum;
+			}
+		}
+	}
+
+	/**
+	 * @param bid the bid to get the importance (utility?) of.
+	 * @return the importance value of bid. CHECK is this inside [0,1]?
+	 */
+	public double getImportance(Bid bid) {
+		double bidImportance = 0.0;
+		for (String issue : bid.getIssues()) {
+			Value value = bid.getValue(issue);
+			double valueImportance = 0.0;
+			for (impUnit i : this.get(issue)) {
+				if (i.valueOfIssue.equals(value)) {
+					valueImportance = i.meanWeightSum;
+					break;
+				}
+			}
+			bidImportance += valueImportance;
+		}
+		return bidImportance;
+	}
+}
Index: /exampleparties/anac2019/agentgg/src/main/java/geniusweb/exampleparties/agentgg/SimpleLinearOrdering.java
===================================================================
--- /exampleparties/anac2019/agentgg/src/main/java/geniusweb/exampleparties/agentgg/SimpleLinearOrdering.java	(revision 12)
+++ /exampleparties/anac2019/agentgg/src/main/java/geniusweb/exampleparties/agentgg/SimpleLinearOrdering.java	(revision 12)
@@ -0,0 +1,125 @@
+package geniusweb.exampleparties.agentgg;
+
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.LinkedList;
+import java.util.List;
+
+import geniusweb.issuevalue.Bid;
+import geniusweb.issuevalue.Domain;
+import geniusweb.profile.DefaultPartialOrdering;
+import geniusweb.profile.Profile;
+import geniusweb.profile.utilityspace.UtilitySpace;
+
+/**
+ * A simple list of bids, but all bids are fully ordered (better or worse than
+ * other bids in the list).
+ */
+public class SimpleLinearOrdering implements UtilitySpace {
+
+	private final Domain domain;
+	private final List<Bid> bids; // worst bid first, best bid last.
+
+	SimpleLinearOrdering(Profile profile) {
+		this(profile.getDomain(), getSortedBids(profile));
+	}
+
+	/**
+	 * 
+	 * @param domain
+	 * @param bids   a list of bids, ordered from lowest to highest util. The
+	 *               first bid will have utility 0, the last utility 1. If only
+	 *               0 or 1 bid in the list, or if the bid is not known, it will
+	 *               have utility 0.
+	 */
+	SimpleLinearOrdering(Domain domain, List<Bid> bids) {
+		this.domain = domain;
+		this.bids = bids;
+	}
+
+	@Override
+	public String getName() {
+		throw new UnsupportedOperationException();
+	}
+
+	@Override
+	public Domain getDomain() {
+		return domain;
+	}
+
+	@Override
+	public Bid getReservationBid() {
+		throw new UnsupportedOperationException();
+	}
+
+	@Override
+	public BigDecimal getUtility(Bid bid) {
+		if (bids.size() < 2 || !bids.contains(bid)) {
+			return BigDecimal.ZERO;
+		}
+		// using 8 decimals, we have to pick something here
+		return new BigDecimal(bids.indexOf(bid)).divide(
+				new BigDecimal((bids.size() - 1)), 8, RoundingMode.HALF_UP);
+	}
+
+	/**
+	 * 
+	 * @param bid
+	 * @return true iff bid is contained in this ordering
+	 */
+	public boolean contains(Bid bid) {
+		return bids.contains(bid);
+	}
+
+	/**
+	 * 
+	 * @return list of all bids in the current ordering.
+	 */
+	public List<Bid> getBids() {
+		return Collections.unmodifiableList(bids);
+	}
+
+	/**
+	 * 
+	 * @param profile
+	 * @return a list of bids in the profile sorted from low to high utility.
+	 */
+	private static List<Bid> getSortedBids(Profile profile) {
+		if (!(profile instanceof DefaultPartialOrdering)) {
+			throw new UnsupportedOperationException(
+					"Only DefaultPartialOrdering supported");
+		}
+		DefaultPartialOrdering prof = (DefaultPartialOrdering) profile;
+		List<Bid> bidslist = prof.getBids();
+		// NOTE sort defaults to ascending order, this is missing in docs.
+		Collections.sort(bidslist, new Comparator<Bid>() {
+
+			@Override
+			public int compare(Bid b1, Bid b2) {
+				return prof.isPreferredOrEqual(b1, b2) ? 1 : -1;
+			}
+
+		});
+
+		return bidslist;
+	}
+
+	/**
+	 * @param bid       a new bid to be inserted
+	 * @param worseBids all bids that are worse than this bid.
+	 * @return a SimpleLinearOrdering, updated with the given comparison. Thee
+	 *         bid will be inserted after the first bid that is not worse than
+	 *         bid.
+	 */
+	public SimpleLinearOrdering with(Bid bid, List<Bid> worseBids) {
+		int n = 0;
+		while (n < bids.size() && worseBids.contains(bids.get(n)))
+			n++;
+		LinkedList<Bid> newbids = new LinkedList<Bid>(bids);
+		newbids.add(n, bid);
+		return new SimpleLinearOrdering(domain, newbids);
+	}
+
+}
Index: /exampleparties/anac2019/agentgg/src/main/java/geniusweb/exampleparties/agentgg/impUnit.java
===================================================================
--- /exampleparties/anac2019/agentgg/src/main/java/geniusweb/exampleparties/agentgg/impUnit.java	(revision 12)
+++ /exampleparties/anac2019/agentgg/src/main/java/geniusweb/exampleparties/agentgg/impUnit.java	(revision 12)
@@ -0,0 +1,37 @@
+package geniusweb.exampleparties.agentgg;
+
+import java.util.Comparator;
+
+import geniusweb.issuevalue.Value;
+
+/**
+ * importance unit . Contains importance of a {@link Value} of some issue. The
+ * values in this class are hard referenced and changed by the {@link ImpMap}.
+ */
+public class impUnit {
+	public Value valueOfIssue;
+	public int weightSum = 0;
+	public int count = 0;
+	public double meanWeightSum = 0.0f; // counts #occurences of this value.
+
+	public impUnit(Value value) {
+		this.valueOfIssue = value;
+	}
+
+	public String toString() {
+		return String.format("%s %f", valueOfIssue, meanWeightSum);
+	}
+
+	// Overriding the comparator interface
+	static class meanWeightSumComparator implements Comparator<impUnit> {
+		public int compare(impUnit o1, impUnit o2) {
+			if (o1.meanWeightSum < o2.meanWeightSum) {
+				return 1;
+			} else if (o1.meanWeightSum > o2.meanWeightSum) {
+				return -1;
+			}
+			return 0;
+		}
+	}
+
+}
Index: /exampleparties/anac2019/agentgg/src/test/java/geniusweb/exampleparties/agentgg/AgentGGTest.java
===================================================================
--- /exampleparties/anac2019/agentgg/src/test/java/geniusweb/exampleparties/agentgg/AgentGGTest.java	(revision 12)
+++ /exampleparties/anac2019/agentgg/src/test/java/geniusweb/exampleparties/agentgg/AgentGGTest.java	(revision 12)
@@ -0,0 +1,244 @@
+package geniusweb.exampleparties.agentgg;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Matchers.anyLong;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import java.io.IOException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.logging.Level;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import com.fasterxml.jackson.core.JsonParseException;
+import com.fasterxml.jackson.databind.JsonMappingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+import geniusweb.actions.Accept;
+import geniusweb.actions.Action;
+import geniusweb.actions.EndNegotiation;
+import geniusweb.actions.Offer;
+import geniusweb.actions.PartyId;
+import geniusweb.connection.ConnectionEnd;
+import geniusweb.issuevalue.Bid;
+import geniusweb.party.Capabilities;
+import geniusweb.party.inform.ActionDone;
+import geniusweb.party.inform.Finished;
+import geniusweb.party.inform.Inform;
+import geniusweb.party.inform.Settings;
+import geniusweb.party.inform.YourTurn;
+import geniusweb.profile.DefaultPartialOrdering;
+import geniusweb.profile.PartialOrdering;
+import geniusweb.profile.Profile;
+import geniusweb.progress.ProgressRounds;
+import geniusweb.references.Parameters;
+import geniusweb.references.ProfileRef;
+import geniusweb.references.ProtocolRef;
+import geniusweb.references.Reference;
+import tudelft.utilities.listener.DefaultListenable;
+import tudelft.utilities.logging.Reporter;
+
+public class AgentGGTest {
+
+	private static final String SAOP = "SAOP";
+	private static final PartyId otherparty = new PartyId("other");
+	private static final String PROFILE = "src/test/resources/jobs1partial20.json";
+	private final static ObjectMapper jackson = new ObjectMapper();
+
+	private AgentGG party;
+	private final TestConnection connection = new TestConnection();
+	private final ProtocolRef protocol = mock(ProtocolRef.class);
+	private ProgressRounds progress = mock(ProgressRounds.class);
+	private Settings settings;
+	private PartialOrdering profile;
+	private final Parameters parameters = new Parameters();
+
+	@Before
+	public void before() throws JsonParseException, JsonMappingException,
+			IOException, URISyntaxException {
+		when(progress.get(anyLong())).thenReturn(0.4);
+		when(progress.advance()).thenReturn(progress);
+		party = new AgentGG();
+		settings = new Settings(new PartyId("party1"),
+				new ProfileRef(new URI("file:" + PROFILE)), protocol, progress,
+				parameters);
+
+		String serialized = new String(Files.readAllBytes(Paths.get(PROFILE)),
+				StandardCharsets.UTF_8);
+		profile = (PartialOrdering) jackson.readValue(serialized,
+				Profile.class);
+
+	}
+
+	@Test
+	public void smokeTest() {
+	}
+
+	@Test
+	public void getDescriptionTest() {
+		assertNotNull(party.getDescription());
+	}
+
+	@Test
+	public void getCapabilitiesTest() {
+		Capabilities capabilities = party.getCapabilities();
+		assertFalse("party does not define protocols",
+				capabilities.getBehaviours().isEmpty());
+	}
+
+	@Test
+	public void testInformConnection() {
+		party.connect(connection);
+		// agent should not start acting just after an inform
+		assertEquals(0, connection.getActions().size());
+	}
+
+	@Test
+	public void testInformSettings() {
+		party.connect(connection);
+		connection.notifyListeners(settings);
+		assertEquals(0, connection.getActions().size());
+	}
+
+	@Test
+	public void testInformAndConnection() {
+		party.connect(connection);
+		party.notifyChange(settings);
+		assertEquals(0, connection.getActions().size());
+	}
+
+	@Test
+	public void testOtherWalksAway() {
+		party.connect(connection);
+		party.notifyChange(settings);
+
+		party.notifyChange(new ActionDone(new EndNegotiation(otherparty)));
+
+		// party should not act at this point
+		assertEquals(0, connection.getActions().size());
+	}
+
+	@Test
+	public void testAgentHasFirstTurn() {
+		party.connect(connection);
+		party.notifyChange(settings);
+
+		party.notifyChange(new YourTurn());
+		assertEquals(1, connection.getActions().size());
+		assertTrue(connection.getActions().get(0) instanceof Offer);
+	}
+
+	@Test
+	public void testAgentAccepts() {
+		party.connect(connection);
+		party.notifyChange(settings);
+
+		Bid bid = findGoodBid();
+
+		// agent generally does not accept in round 1. But it should accept
+		// soon. Also we have progress=40% so it's not a blank atart.
+		int round = 1;
+		boolean accept = false;
+		while (round < 10 && !accept) {
+			party.notifyChange(new ActionDone(new Offer(otherparty, bid)));
+			party.notifyChange(new YourTurn());
+			assertEquals(round, connection.getActions().size());
+			accept = connection.getActions().get(round - 1) instanceof Accept;
+			round++;
+		}
+		assertTrue("Party did not accept good offer at all", accept);
+
+	}
+
+	@Test
+	public void testAgentLogsFinal() {
+		// this log output is optional, this is to show how to check log
+		Reporter reporter = mock(Reporter.class);
+		party = new AgentGG(reporter);
+		party.connect(connection);
+		party.notifyChange(settings);
+		party.notifyChange(new Finished(null));
+
+		verify(reporter).log(eq(Level.INFO),
+				eq("Final ourcome:Finished[null]"));
+	}
+
+	@Test
+	public void testAgentsUpdatesProgress() {
+		party.connect(connection);
+		party.notifyChange(settings);
+
+		party.notifyChange(new YourTurn());
+		verify(progress).advance();
+	}
+
+	@Test
+	public void testGetCapabilities() {
+		assertTrue(party.getCapabilities().getBehaviours().contains(SAOP));
+	}
+
+	private Bid findGoodBid() {
+		// assumes that profile is a DefaultPartial. The top 30% bids should be
+		// good.
+		if (!(profile instanceof DefaultPartialOrdering))
+			throw new IllegalStateException(
+					"Test can not be done: there is no good bid with utility>0.7");
+		List<Bid> bids = ((DefaultPartialOrdering) profile).getBids();
+		return bids.get(bids.size() - 2);
+	}
+
+}
+
+/**
+ * A "real" connection object, because the party is going to subscribe etc, and
+ * without a real connection we would have to do a lot of mocks that would make
+ * the test very hard to read.
+ *
+ */
+class TestConnection extends DefaultListenable<Inform>
+		implements ConnectionEnd<Inform, Action> {
+	private List<Action> actions = new LinkedList<>();
+
+	@Override
+	public void send(Action action) throws IOException {
+		actions.add(action);
+	}
+
+	@Override
+	public Reference getReference() {
+		return null;
+	}
+
+	@Override
+	public URI getRemoteURI() {
+		return null;
+	}
+
+	@Override
+	public void close() {
+
+	}
+
+	@Override
+	public Error getError() {
+		return null;
+	}
+
+	public List<Action> getActions() {
+		return actions;
+	}
+
+}
Index: /exampleparties/anac2019/agentgg/src/test/resources/jobs1partial20.json
===================================================================
--- /exampleparties/anac2019/agentgg/src/test/resources/jobs1partial20.json	(revision 12)
+++ /exampleparties/anac2019/agentgg/src/test/resources/jobs1partial20.json	(revision 12)
@@ -0,0 +1,1018 @@
+{
+	"DefaultPartialOrdering": {
+		"name": "jobs1-partial-20",
+		"domain": {
+			"name": "jobs",
+			"issuesValues": {
+				"lease car": {
+					"values": [
+						"yes",
+						"no"
+					]
+				},
+				"permanent contract": {
+					"values": [
+						"yes",
+						"no"
+					]
+				},
+				"career development opportunities": {
+					"values": [
+						"low",
+						"medium",
+						"high"
+					]
+				},
+				"fte": {
+					"values": [
+						"0.6",
+						"0.8",
+						"1.0"
+					]
+				},
+				"salary": {
+					"values": [
+						"2000",
+						"2500",
+						"3000",
+						"3500",
+						"4000"
+					]
+				},
+				"work from home": {
+					"values": [
+						"0",
+						"1",
+						"2"
+					]
+				}
+			}
+		},
+		"reservationBid": {
+			"issuevalues": {
+				"lease car": "no",
+				"permanent contract": "no",
+				"career development opportunities": "medium",
+				"fte": "0.8",
+				"salary": "300",
+				"work from home": "0"
+			}
+		},
+		"bids": [
+			{
+				"issuevalues": {
+					"lease car": "no",
+					"permanent contract": "no",
+					"career development opportunities": "low",
+					"fte": "1.0",
+					"salary": "3000",
+					"work from home": "1"
+				}
+			},
+			{
+				"issuevalues": {
+					"lease car": "yes",
+					"permanent contract": "no",
+					"career development opportunities": "high",
+					"fte": "0.6",
+					"salary": "3500",
+					"work from home": "0"
+				}
+			},
+			{
+				"issuevalues": {
+					"lease car": "no",
+					"permanent contract": "no",
+					"career development opportunities": "high",
+					"fte": "0.8",
+					"salary": "3000",
+					"work from home": "0"
+				}
+			},
+			{
+				"issuevalues": {
+					"lease car": "yes",
+					"permanent contract": "no",
+					"career development opportunities": "low",
+					"fte": "0.6",
+					"salary": "3500",
+					"work from home": "0"
+				}
+			},
+			{
+				"issuevalues": {
+					"lease car": "no",
+					"permanent contract": "yes",
+					"career development opportunities": "low",
+					"fte": "0.6",
+					"salary": "3000",
+					"work from home": "1"
+				}
+			},
+			{
+				"issuevalues": {
+					"lease car": "yes",
+					"permanent contract": "yes",
+					"career development opportunities": "low",
+					"fte": "1.0",
+					"salary": "2000",
+					"work from home": "2"
+				}
+			},
+			{
+				"issuevalues": {
+					"lease car": "no",
+					"permanent contract": "yes",
+					"career development opportunities": "low",
+					"fte": "0.8",
+					"salary": "2500",
+					"work from home": "1"
+				}
+			},
+			{
+				"issuevalues": {
+					"lease car": "no",
+					"permanent contract": "yes",
+					"career development opportunities": "low",
+					"fte": "0.6",
+					"salary": "2000",
+					"work from home": "2"
+				}
+			},
+			{
+				"issuevalues": {
+					"lease car": "yes",
+					"permanent contract": "no",
+					"career development opportunities": "medium",
+					"fte": "0.6",
+					"salary": "3500",
+					"work from home": "1"
+				}
+			},
+			{
+				"issuevalues": {
+					"lease car": "yes",
+					"permanent contract": "yes",
+					"career development opportunities": "low",
+					"fte": "0.6",
+					"salary": "2000",
+					"work from home": "2"
+				}
+			},
+			{
+				"issuevalues": {
+					"lease car": "yes",
+					"permanent contract": "yes",
+					"career development opportunities": "medium",
+					"fte": "0.6",
+					"salary": "2000",
+					"work from home": "0"
+				}
+			},
+			{
+				"issuevalues": {
+					"lease car": "yes",
+					"permanent contract": "yes",
+					"career development opportunities": "medium",
+					"fte": "0.8",
+					"salary": "3500",
+					"work from home": "2"
+				}
+			},
+			{
+				"issuevalues": {
+					"lease car": "no",
+					"permanent contract": "no",
+					"career development opportunities": "low",
+					"fte": "0.6",
+					"salary": "2000",
+					"work from home": "0"
+				}
+			},
+			{
+				"issuevalues": {
+					"lease car": "no",
+					"permanent contract": "no",
+					"career development opportunities": "high",
+					"fte": "1.0",
+					"salary": "4000",
+					"work from home": "2"
+				}
+			},
+			{
+				"issuevalues": {
+					"lease car": "yes",
+					"permanent contract": "yes",
+					"career development opportunities": "low",
+					"fte": "0.8",
+					"salary": "4000",
+					"work from home": "2"
+				}
+			},
+			{
+				"issuevalues": {
+					"lease car": "yes",
+					"permanent contract": "no",
+					"career development opportunities": "medium",
+					"fte": "1.0",
+					"salary": "3500",
+					"work from home": "2"
+				}
+			},
+			{
+				"issuevalues": {
+					"lease car": "no",
+					"permanent contract": "yes",
+					"career development opportunities": "high",
+					"fte": "0.8",
+					"salary": "2000",
+					"work from home": "1"
+				}
+			},
+			{
+				"issuevalues": {
+					"lease car": "yes",
+					"permanent contract": "yes",
+					"career development opportunities": "low",
+					"fte": "1.0",
+					"salary": "2500",
+					"work from home": "1"
+				}
+			},
+			{
+				"issuevalues": {
+					"lease car": "yes",
+					"permanent contract": "yes",
+					"career development opportunities": "high",
+					"fte": "1.0",
+					"salary": "4000",
+					"work from home": "2"
+				}
+			},
+			{
+				"issuevalues": {
+					"lease car": "no",
+					"permanent contract": "yes",
+					"career development opportunities": "medium",
+					"fte": "0.8",
+					"salary": "2500",
+					"work from home": "1"
+				}
+			}
+		],
+		"better": [
+			[
+				0,
+				12
+			],
+			[
+				0,
+				2
+			],
+			[
+				0,
+				3
+			],
+			[
+				0,
+				7
+			],
+			[
+				0,
+				10
+			],
+			[
+				1,
+				0
+			],
+			[
+				1,
+				12
+			],
+			[
+				1,
+				2
+			],
+			[
+				1,
+				3
+			],
+			[
+				1,
+				4
+			],
+			[
+				1,
+				7
+			],
+			[
+				1,
+				10
+			],
+			[
+				2,
+				12
+			],
+			[
+				3,
+				12
+			],
+			[
+				3,
+				2
+			],
+			[
+				3,
+				7
+			],
+			[
+				4,
+				12
+			],
+			[
+				4,
+				2
+			],
+			[
+				4,
+				3
+			],
+			[
+				4,
+				7
+			],
+			[
+				4,
+				10
+			],
+			[
+				5,
+				0
+			],
+			[
+				5,
+				1
+			],
+			[
+				5,
+				2
+			],
+			[
+				5,
+				3
+			],
+			[
+				5,
+				4
+			],
+			[
+				5,
+				6
+			],
+			[
+				5,
+				7
+			],
+			[
+				5,
+				8
+			],
+			[
+				5,
+				9
+			],
+			[
+				5,
+				10
+			],
+			[
+				5,
+				12
+			],
+			[
+				5,
+				16
+			],
+			[
+				5,
+				19
+			],
+			[
+				6,
+				0
+			],
+			[
+				6,
+				1
+			],
+			[
+				6,
+				12
+			],
+			[
+				6,
+				2
+			],
+			[
+				6,
+				3
+			],
+			[
+				6,
+				4
+			],
+			[
+				6,
+				16
+			],
+			[
+				6,
+				7
+			],
+			[
+				6,
+				8
+			],
+			[
+				6,
+				9
+			],
+			[
+				6,
+				10
+			],
+			[
+				7,
+				12
+			],
+			[
+				7,
+				2
+			],
+			[
+				8,
+				0
+			],
+			[
+				8,
+				1
+			],
+			[
+				8,
+				12
+			],
+			[
+				8,
+				2
+			],
+			[
+				8,
+				3
+			],
+			[
+				8,
+				4
+			],
+			[
+				8,
+				7
+			],
+			[
+				8,
+				9
+			],
+			[
+				8,
+				10
+			],
+			[
+				9,
+				0
+			],
+			[
+				9,
+				1
+			],
+			[
+				9,
+				12
+			],
+			[
+				9,
+				2
+			],
+			[
+				9,
+				3
+			],
+			[
+				9,
+				4
+			],
+			[
+				9,
+				7
+			],
+			[
+				9,
+				10
+			],
+			[
+				10,
+				12
+			],
+			[
+				10,
+				2
+			],
+			[
+				10,
+				7
+			],
+			[
+				11,
+				0
+			],
+			[
+				11,
+				1
+			],
+			[
+				11,
+				2
+			],
+			[
+				11,
+				3
+			],
+			[
+				11,
+				5
+			],
+			[
+				11,
+				4
+			],
+			[
+				11,
+				6
+			],
+			[
+				11,
+				7
+			],
+			[
+				11,
+				8
+			],
+			[
+				11,
+				9
+			],
+			[
+				11,
+				10
+			],
+			[
+				11,
+				12
+			],
+			[
+				11,
+				13
+			],
+			[
+				11,
+				15
+			],
+			[
+				11,
+				16
+			],
+			[
+				11,
+				17
+			],
+			[
+				11,
+				19
+			],
+			[
+				13,
+				0
+			],
+			[
+				13,
+				1
+			],
+			[
+				13,
+				2
+			],
+			[
+				13,
+				3
+			],
+			[
+				13,
+				5
+			],
+			[
+				13,
+				4
+			],
+			[
+				13,
+				6
+			],
+			[
+				13,
+				7
+			],
+			[
+				13,
+				8
+			],
+			[
+				13,
+				9
+			],
+			[
+				13,
+				10
+			],
+			[
+				13,
+				12
+			],
+			[
+				13,
+				15
+			],
+			[
+				13,
+				16
+			],
+			[
+				13,
+				17
+			],
+			[
+				13,
+				19
+			],
+			[
+				14,
+				0
+			],
+			[
+				14,
+				1
+			],
+			[
+				14,
+				2
+			],
+			[
+				14,
+				3
+			],
+			[
+				14,
+				5
+			],
+			[
+				14,
+				4
+			],
+			[
+				14,
+				6
+			],
+			[
+				14,
+				7
+			],
+			[
+				14,
+				8
+			],
+			[
+				14,
+				9
+			],
+			[
+				14,
+				10
+			],
+			[
+				14,
+				11
+			],
+			[
+				14,
+				12
+			],
+			[
+				14,
+				13
+			],
+			[
+				14,
+				15
+			],
+			[
+				14,
+				16
+			],
+			[
+				14,
+				17
+			],
+			[
+				14,
+				19
+			],
+			[
+				15,
+				0
+			],
+			[
+				15,
+				1
+			],
+			[
+				15,
+				2
+			],
+			[
+				15,
+				3
+			],
+			[
+				15,
+				5
+			],
+			[
+				15,
+				4
+			],
+			[
+				15,
+				6
+			],
+			[
+				15,
+				7
+			],
+			[
+				15,
+				8
+			],
+			[
+				15,
+				9
+			],
+			[
+				15,
+				10
+			],
+			[
+				15,
+				12
+			],
+			[
+				15,
+				16
+			],
+			[
+				15,
+				17
+			],
+			[
+				15,
+				19
+			],
+			[
+				16,
+				0
+			],
+			[
+				16,
+				1
+			],
+			[
+				16,
+				12
+			],
+			[
+				16,
+				2
+			],
+			[
+				16,
+				3
+			],
+			[
+				16,
+				4
+			],
+			[
+				16,
+				7
+			],
+			[
+				16,
+				8
+			],
+			[
+				16,
+				9
+			],
+			[
+				16,
+				10
+			],
+			[
+				17,
+				0
+			],
+			[
+				17,
+				1
+			],
+			[
+				17,
+				2
+			],
+			[
+				17,
+				3
+			],
+			[
+				17,
+				5
+			],
+			[
+				17,
+				4
+			],
+			[
+				17,
+				6
+			],
+			[
+				17,
+				7
+			],
+			[
+				17,
+				8
+			],
+			[
+				17,
+				9
+			],
+			[
+				17,
+				10
+			],
+			[
+				17,
+				12
+			],
+			[
+				17,
+				16
+			],
+			[
+				17,
+				19
+			],
+			[
+				18,
+				0
+			],
+			[
+				18,
+				1
+			],
+			[
+				18,
+				2
+			],
+			[
+				18,
+				3
+			],
+			[
+				18,
+				5
+			],
+			[
+				18,
+				4
+			],
+			[
+				18,
+				6
+			],
+			[
+				18,
+				7
+			],
+			[
+				18,
+				8
+			],
+			[
+				18,
+				9
+			],
+			[
+				18,
+				10
+			],
+			[
+				18,
+				11
+			],
+			[
+				18,
+				12
+			],
+			[
+				18,
+				13
+			],
+			[
+				18,
+				14
+			],
+			[
+				18,
+				15
+			],
+			[
+				18,
+				16
+			],
+			[
+				18,
+				17
+			],
+			[
+				18,
+				19
+			],
+			[
+				19,
+				0
+			],
+			[
+				19,
+				1
+			],
+			[
+				19,
+				12
+			],
+			[
+				19,
+				2
+			],
+			[
+				19,
+				3
+			],
+			[
+				19,
+				4
+			],
+			[
+				19,
+				6
+			],
+			[
+				19,
+				16
+			],
+			[
+				19,
+				7
+			],
+			[
+				19,
+				8
+			],
+			[
+				19,
+				9
+			],
+			[
+				19,
+				10
+			]
+		]
+	}
+}
Index: /exampleparties/anac2019/pom.xml
===================================================================
--- /exampleparties/anac2019/pom.xml	(revision 12)
+++ /exampleparties/anac2019/pom.xml	(revision 12)
@@ -0,0 +1,21 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+	<modelVersion>4.0.0</modelVersion>
+
+	<groupId>geniusweb.exampleparties</groupId>
+	<artifactId>anac2019</artifactId>
+	<version>-</version>
+	<packaging>pom</packaging>
+
+
+	<properties>
+		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+		<jackson-2-version>2.9.6</jackson-2-version>
+	</properties>
+
+	<modules>
+		<module>agentgg</module>
+		<module>winkyagent</module>
+	</modules>
+</project>
Index: /exampleparties/anac2019/winkyagent/pom.xml
===================================================================
--- /exampleparties/anac2019/winkyagent/pom.xml	(revision 12)
+++ /exampleparties/anac2019/winkyagent/pom.xml	(revision 12)
@@ -0,0 +1,293 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+	<modelVersion>4.0.0</modelVersion>
+
+	<groupId>geniusweb.exampleparties.anac2019</groupId>
+	<artifactId>winkyagent</artifactId>
+	<version>1.2.0</version>
+	<packaging>jar</packaging>
+
+
+	<properties>
+		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+		<maven.compiler.target>1.8</maven.compiler.target>
+		<maven.compiler.source>1.8</maven.compiler.source>
+		<basedir>.</basedir>
+		<passwd>${env.ARTIFACTORY_PASS}</passwd>
+		<jackson-2-version>2.9.6</jackson-2-version>
+	</properties>
+
+	<distributionManagement>
+		<repository>
+			<id>artifactory.ewi.tudelft.nl</id>
+			<url>http://artifactory.ewi.tudelft.nl/artifactory/libs-release</url>
+		</repository>
+	</distributionManagement>
+
+
+	<dependencies>
+
+		<dependency>
+			<groupId>geniusweb</groupId>
+			<artifactId>issuevalue</artifactId>
+			<version>1.2.0</version>
+		</dependency>
+
+		<dependency>
+			<groupId>geniusweb</groupId>
+			<artifactId>party</artifactId>
+			<version>1.2.0</version>
+		</dependency>
+
+		<dependency>
+			<groupId>geniusweb</groupId>
+			<artifactId>bidspace</artifactId>
+			<version>1.2.0</version>
+		</dependency>
+		<dependency>
+			<groupId>geniusweb</groupId>
+			<artifactId>profileconnection</artifactId>
+			<version>1.2.0</version>
+		</dependency>
+		<dependency>
+			<groupId>tudelft.utilities</groupId>
+			<artifactId>logging</artifactId>
+			<version>1.0.0</version>
+		</dependency>
+		<dependency>
+			<groupId>tudelft.utilities</groupId>
+			<artifactId>immutablelist</artifactId>
+			<version>1.0.1</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>
+			<scope>test</scope>
+		</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>
+			<scope>test</scope>
+		</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>
+			<scope>test</scope>
+		</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>
+			<scope>test</scope>
+		</dependency>
+		<!-- JAX-RS provider -->
+		<dependency>
+			<groupId>com.fasterxml.jackson.jaxrs</groupId>
+			<artifactId>jackson-jaxrs-json-provider</artifactId>
+			<version>${jackson-2-version}</version>
+			<scope>test</scope>
+		</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>
+			<scope>test</scope>
+		</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.1</version>
+			<scope>test</scope>
+		</dependency>
+
+	</dependencies>
+
+
+	<repositories>
+		<repository>
+			<id>artifactory.ewi.tudelft.nl</id>
+			<url>http://artifactory.ewi.tudelft.nl/artifactory/libs-release</url>
+			<snapshots>
+				<enabled>false</enabled>
+			</snapshots>
+		</repository>
+
+	</repositories>
+
+	<pluginRepositories>
+		<pluginRepository>
+			<id>jcenter</id>
+			<url>http://jcenter.bintray.com</url>
+		</pluginRepository>
+	</pluginRepositories>
+
+
+	<build>
+
+		<plugins>
+			<plugin>
+				<groupId>org.apache.maven.plugins</groupId>
+				<artifactId>maven-compiler-plugin</artifactId>
+				<version>3.8.0</version>
+				<configuration>
+					<source>1.8</source>
+					<target>1.8</target>
+				</configuration>
+			</plugin>
+			<plugin>
+				<groupId>org.apache.maven.plugins</groupId>
+				<artifactId>maven-source-plugin</artifactId>
+				<version>3.1.0</version>
+				<executions>
+					<execution>
+						<id>attach-sources</id>
+						<goals>
+							<goal>jar</goal>
+						</goals>
+					</execution>
+				</executions>
+			</plugin>
+
+			<plugin>
+				<groupId>org.apache.maven.plugins</groupId>
+				<artifactId>maven-jar-plugin</artifactId>
+				<configuration>
+					<archive>
+						<manifest>
+							<mainClass>geniusweb.exampleparties.anac2019.winkyagent.WinkyAgent</mainClass>
+						</manifest>
+					</archive>
+				</configuration>
+			</plugin>
+
+			<plugin>
+				<groupId>org.apache.maven.plugins</groupId>
+				<artifactId>maven-javadoc-plugin</artifactId>
+				<version>2.10.1</version>
+				<executions>
+					<execution>
+						<id>attach-javadocs</id>
+						<goals>
+							<goal>jar</goal>
+						</goals>
+						<configuration>
+							<additionalparam>${javadoc.opts}</additionalparam>
+							<additionalparam>-Xdoclint:none</additionalparam>
+						</configuration>
+					</execution>
+				</executions>
+			</plugin>
+
+			<plugin>
+				<groupId>org.jfrog.buildinfo</groupId>
+				<artifactId>artifactory-maven-plugin</artifactId>
+				<version>2.6.1</version>
+				<executions>
+					<execution>
+						<id>build-info</id>
+						<goals>
+							<goal>publish</goal>
+						</goals>
+						<configuration>
+							<publisher>
+								<contextUrl>http://artifactory.ewi.tudelft.nl/artifactory</contextUrl>
+								<repoKey>libs-release</repoKey>
+								<username>wouter</username>
+								<password>${passwd}</password>
+							</publisher>
+						</configuration>
+					</execution>
+				</executions>
+			</plugin>
+
+			<plugin>
+				<groupId>org.apache.maven.plugins</groupId>
+				<artifactId>maven-assembly-plugin</artifactId>
+				<version>2.4.1</version>
+				<configuration>
+					<!-- get all project dependencies -->
+					<descriptorRefs>
+						<descriptorRef>jar-with-dependencies</descriptorRef>
+					</descriptorRefs>
+					<archive>
+						<manifest>
+							<addDefaultImplementationEntries>true</addDefaultImplementationEntries>
+							<addDefaultSpecificationEntries>true</addDefaultSpecificationEntries>
+							<mainClass>geniusweb.exampleparties.anac2019.winkyagent.WinkyAgent</mainClass>
+						</manifest>
+					</archive>
+				</configuration>
+				<executions>
+					<execution>
+						<id>make-assembly</id>
+						<!-- bind to the packaging phase -->
+						<phase>package</phase>
+						<goals>
+							<goal>single</goal>
+						</goals>
+					</execution>
+				</executions>
+			</plugin>
+
+
+		</plugins>
+
+		<pluginManagement>
+			<plugins>
+				<plugin>
+					<groupId>org.eclipse.m2e</groupId>
+					<artifactId>lifecycle-mapping</artifactId>
+					<version>1.0.0</version>
+					<configuration>
+						<lifecycleMappingMetadata>
+							<pluginExecutions>
+								<pluginExecution>
+									<pluginExecutionFilter>
+										<groupId>org.jfrog.buildinfo</groupId>
+										<artifactId>artifactory-maven-plugin</artifactId>
+										<versionRange>[1.0.0,)</versionRange>
+										<goals>
+											<goal>publish</goal>
+										</goals>
+									</pluginExecutionFilter>
+									<action>
+										<ignore />
+									</action>
+								</pluginExecution>
+							</pluginExecutions>
+						</lifecycleMappingMetadata>
+					</configuration>
+				</plugin>
+			</plugins>
+		</pluginManagement>
+
+
+	</build>
+</project>
Index: /exampleparties/anac2019/winkyagent/src/main/java/geniusweb/exampleparties/anac2019/winkyagent/SimpleLinearOrdering.java
===================================================================
--- /exampleparties/anac2019/winkyagent/src/main/java/geniusweb/exampleparties/anac2019/winkyagent/SimpleLinearOrdering.java	(revision 12)
+++ /exampleparties/anac2019/winkyagent/src/main/java/geniusweb/exampleparties/anac2019/winkyagent/SimpleLinearOrdering.java	(revision 12)
@@ -0,0 +1,125 @@
+package geniusweb.exampleparties.anac2019.winkyagent;
+
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.LinkedList;
+import java.util.List;
+
+import geniusweb.issuevalue.Bid;
+import geniusweb.issuevalue.Domain;
+import geniusweb.profile.DefaultPartialOrdering;
+import geniusweb.profile.Profile;
+import geniusweb.profile.utilityspace.UtilitySpace;
+
+/**
+ * A simple list of bids, but all bids are fully ordered (better or worse than
+ * other bids in the list).
+ */
+public class SimpleLinearOrdering implements UtilitySpace {
+
+	private final Domain domain;
+	private final List<Bid> bids; // worst bid first, best bid last.
+
+	SimpleLinearOrdering(Profile profile) {
+		this(profile.getDomain(), getSortedBids(profile));
+	}
+
+	/**
+	 * 
+	 * @param domain
+	 * @param bids   a list of bids, ordered from lowest to highest util. The
+	 *               first bid will have utility 0, the last utility 1. If only
+	 *               0 or 1 bid in the list, or if the bid is not known, it will
+	 *               have utility 0.
+	 */
+	SimpleLinearOrdering(Domain domain, List<Bid> bids) {
+		this.domain = domain;
+		this.bids = bids;
+	}
+
+	@Override
+	public String getName() {
+		throw new UnsupportedOperationException();
+	}
+
+	@Override
+	public Domain getDomain() {
+		return domain;
+	}
+
+	@Override
+	public Bid getReservationBid() {
+		throw new UnsupportedOperationException();
+	}
+
+	@Override
+	public BigDecimal getUtility(Bid bid) {
+		if (bids.size() < 2 || !bids.contains(bid)) {
+			return BigDecimal.ZERO;
+		}
+		// using 8 decimals, we have to pick something here
+		return new BigDecimal(bids.indexOf(bid)).divide(
+				new BigDecimal((bids.size() - 1)), 8, RoundingMode.HALF_UP);
+	}
+
+	/**
+	 * 
+	 * @param bid
+	 * @return true iff bid is contained in this ordering
+	 */
+	public boolean contains(Bid bid) {
+		return bids.contains(bid);
+	}
+
+	/**
+	 * 
+	 * @return list of all bids in the current ordering.
+	 */
+	public List<Bid> getBids() {
+		return Collections.unmodifiableList(bids);
+	}
+
+	/**
+	 * 
+	 * @param profile
+	 * @return a list of bids in the profile sorted from low to high utility.
+	 */
+	private static List<Bid> getSortedBids(Profile profile) {
+		if (!(profile instanceof DefaultPartialOrdering)) {
+			throw new UnsupportedOperationException(
+					"Only DefaultPartialOrdering supported");
+		}
+		DefaultPartialOrdering prof = (DefaultPartialOrdering) profile;
+		List<Bid> bidslist = prof.getBids();
+		// NOTE sort defaults to ascending order, this is missing in docs.
+		Collections.sort(bidslist, new Comparator<Bid>() {
+
+			@Override
+			public int compare(Bid b1, Bid b2) {
+				return prof.isPreferredOrEqual(b1, b2) ? 1 : -1;
+			}
+
+		});
+
+		return bidslist;
+	}
+
+	/**
+	 * @param bid       a new bid to be inserted
+	 * @param worseBids all bids that are worse than this bid.
+	 * @return a SimpleLinearOrdering, updated with the given comparison. Thee
+	 *         bid will be inserted after the first bid that is not worse than
+	 *         bid.
+	 */
+	public SimpleLinearOrdering with(Bid bid, List<Bid> worseBids) {
+		int n = 0;
+		while (n < bids.size() && worseBids.contains(bids.get(n)))
+			n++;
+		LinkedList<Bid> newbids = new LinkedList<Bid>(bids);
+		newbids.add(n, bid);
+		return new SimpleLinearOrdering(domain, newbids);
+	}
+
+}
Index: /exampleparties/anac2019/winkyagent/src/main/java/geniusweb/exampleparties/anac2019/winkyagent/WinkyAgent.java
===================================================================
--- /exampleparties/anac2019/winkyagent/src/main/java/geniusweb/exampleparties/anac2019/winkyagent/WinkyAgent.java	(revision 12)
+++ /exampleparties/anac2019/winkyagent/src/main/java/geniusweb/exampleparties/anac2019/winkyagent/WinkyAgent.java	(revision 12)
@@ -0,0 +1,435 @@
+package geniusweb.exampleparties.anac2019.winkyagent;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Random;
+import java.util.logging.Level;
+
+import javax.websocket.DeploymentException;
+
+import geniusweb.actions.Accept;
+import geniusweb.actions.Action;
+import geniusweb.actions.Offer;
+import geniusweb.actions.PartyId;
+import geniusweb.bidspace.AllBidsList;
+import geniusweb.issuevalue.Bid;
+import geniusweb.issuevalue.DiscreteValue;
+import geniusweb.issuevalue.DiscreteValueSet;
+import geniusweb.issuevalue.Domain;
+import geniusweb.issuevalue.Value;
+import geniusweb.party.Capabilities;
+import geniusweb.party.DefaultParty;
+import geniusweb.party.inform.ActionDone;
+import geniusweb.party.inform.Finished;
+import geniusweb.party.inform.Inform;
+import geniusweb.party.inform.Settings;
+import geniusweb.party.inform.YourTurn;
+import geniusweb.profile.PartialOrdering;
+import geniusweb.profileconnection.ProfileConnectionFactory;
+import geniusweb.profileconnection.ProfileInterface;
+import geniusweb.progress.ProgressRounds;
+import tudelft.utilities.logging.Reporter;
+
+/**
+ * This is translated version of WinkyAgent, winner from ANAC2019. Authors Siqi
+ * Chen and Jie Lin Tianjin University China.
+ * 
+ * <p>
+ * IMPORTANT This party requires a {@link ProgressRounds}, and the domain must
+ * contain only {@link DiscreteValue}s.
+ * <p>
+ * WARNING this contains poor code and is here just for comparison and testing.
+ */
+public class WinkyAgent extends DefaultParty {
+
+	private Bid lastReceivedBid = null;
+	private Map<Bid, Double> receiveBids = new HashMap<Bid, Double>();
+	private List<Bid> bidOrder = null;
+	int utilitySize = 0;
+	int ranklistSize = 0;
+	double receivehighestUtility = 0.0;// 接收过的最高出价的效用
+	List<String> issueList = null;// issue列表
+	int issueSize = 0;// issue个数
+	int valueSum = 0;// value个数
+	double initUtility = 0.0;// value初始效用
+	Map<DiscreteValue, Double> valueCorrespond = new HashMap<DiscreteValue, Double>();// value和对应效用
+	DiscreteValue[] values = null;// value数组
+	double learningRate;
+	List<Map.Entry<Bid, Double>> list = new ArrayList<>();// 对receiveBids按照效用进行排序后得到的list
+	boolean listSort = true;
+	boolean lastBidTag = true;
+
+	// new fields
+	private PartyId me;
+	private ProgressRounds progress;
+	private PartialOrdering partialprofile;
+	private AllBidsList allbids; // all bids in the domain.
+	private final Random rand = new Random();
+	private SimpleLinearOrdering simpleOrdering;
+
+	public WinkyAgent() {
+		super();
+	}
+
+	public WinkyAgent(Reporter reporter) {
+		super(reporter);
+	}
+
+	@Override
+	public void notifyChange(Inform info) {
+		try {
+			if (info instanceof Settings) {
+				init((Settings) info);
+			} else if (info instanceof ActionDone) {
+				Action lastReceivedAction = ((ActionDone) info).getAction();
+				if (lastReceivedAction instanceof Offer) {
+					receivOffer((Offer) lastReceivedAction);
+				}
+			} else if (info instanceof YourTurn) {
+				Action action = chooseAction();
+				getConnection().send(action);
+				progress = progress.advance();
+			} else if (info instanceof Finished) {
+				getReporter().log(Level.INFO, "Final ourcome:" + info);
+			}
+		} catch (Exception e) {
+			throw new RuntimeException("Failed to handle info", e);
+		}
+	}
+
+	@Override
+	public Capabilities getCapabilities() {
+		return new Capabilities(new HashSet<>(Arrays.asList("SAOP")));
+	}
+
+	@Override
+	public String getDescription() {
+		return "ANAC 2019 WinkyAgent translated to GeniusWeb. Requires partial profile. ";
+	}
+
+	private void receivOffer(Offer action) {
+		lastReceivedBid = action.getBid();
+		double lastReceivedBidUtility = linearEstUtility(lastReceivedBid);
+		receiveBids.put(lastReceivedBid, lastReceivedBidUtility);
+		if (lastReceivedBidUtility > receivehighestUtility) {
+			receivehighestUtility = lastReceivedBidUtility;
+		}
+
+	}
+
+	private void init(Settings info) throws IOException, DeploymentException {
+		this.me = info.getID();
+		this.progress = (ProgressRounds) info.getProgress();
+
+		ProfileInterface profileint = ProfileConnectionFactory
+				.create(info.getProfile().getURI(), getReporter());
+		partialprofile = (PartialOrdering) profileint.getProfile();
+		Domain domain = partialprofile.getDomain();
+		allbids = new AllBidsList(domain);
+
+		utilitySize = allbids.size().intValue();// 一共可能有多少种出价
+		simpleOrdering = new SimpleLinearOrdering(partialprofile);
+		bidOrder = simpleOrdering.getBids();
+		ranklistSize = bidOrder.size();
+		// THIS FIXES THE ORDER OF THE ISSUES, BACKCOMPATIBILITY issue numbers
+		issueList = new ArrayList<String>(domain.getIssues());
+		issueSize = issueList.size();
+		double[] results = new double[ranklistSize];// Array of given utility
+		for (int i = 0; i < ranklistSize; i++) { // results array initialization
+			results[i] = getBidOrderUtility(bidOrder.get(i));
+		}
+
+		int[] valueSize = new int[issueSize];// 第i个问题有j种选择
+		for (int i = 0; i < issueSize; i++) {
+			String issued = issueList.get(i);
+			valueSize[i] = domain.getValues(issued).size().intValue();
+			valueSum += valueSize[i];
+		}
+		initUtility = 1.0 / valueSum; // value初始化的值
+		learningRate = initUtility / 10.0;
+
+		values = new DiscreteValue[valueSum];// value数组
+		int valuesIndexCnt = 0;
+		while (valuesIndexCnt < valueSum) { // 初始化values数组和map valueCorrespond
+			for (int i = 0; i < issueSize; i++) {
+				String issued = issueList.get(i);
+				DiscreteValueSet availableVals = (DiscreteValueSet) domain
+						.getValues(issued);
+				for (int j = 0; j < availableVals.size().intValue(); j++) {
+					values[valuesIndexCnt] = availableVals.getValues().get(j); // 初始化values数组
+					valueCorrespond.put(values[valuesIndexCnt], initUtility); // 初始化map
+																				// valueCorrespond
+					valuesIndexCnt++;
+				}
+			}
+		}
+
+		// bidOrder training set
+		// makes a flat list 2D list
+		// each element is for one of the bids.
+		// valueSum values, in order
+		// of iss1val1, iss1val2,...,iss2val1,iss2val2,...,
+		// issNval1,...,isNvalM.
+		// this fills the features array with 1's
+		// if the bid contains that particular value.
+		int[][] features = new int[ranklistSize][valueSum];
+
+		// Wouter: original code was bugged. #1766. Putting a fix here.
+		for (int bidnr = 0; bidnr < ranklistSize; bidnr++) {
+			Bid bid = bidOrder.get(bidnr);
+			int featurenr = 0;
+			for (String issue : issueList) {
+				Value thisbidvalue = bid.getValue(issue);
+				for (Value value : domain.getValues(issue)) {
+					features[bidnr][featurenr++] = thisbidvalue.equals(value)
+							? 1
+							: 0;
+				}
+			}
+
+		}
+
+		double[] parameters = new double[valueSum];// Training value
+		for (int i = 0; i < valueSum; i++) {
+			parameters[i] = initUtility;
+		}
+
+		for (int i = 0; i < ranklistSize * valueSum; i++) { // training
+			BGD(features, results, learningRate, parameters);
+		}
+	}
+
+	private void BGD(int[][] features, double[] results, double learningRate,
+			double[] parameters) {
+		for (int t = 0; t < valueSum; t++) {
+			double sum = 0.0;
+			double parametersSum = 0.0;
+			for (int j = 0; j < results.length; j++) {
+				for (int i = 0; i < valueSum; i++) {
+					parametersSum += parameters[i] * features[j][i];
+				}
+				parametersSum = parametersSum - results[j];
+				parametersSum = parametersSum * features[j][t];
+				sum += parametersSum;
+			}
+			double updateValue = 2 * learningRate * sum / results.length;
+			parameters[t] = parameters[t] - updateValue;
+			/**
+			 * ValueCorrespond is bugged, because it uses issuevalues as key
+			 * while issuevalues may be not unique (multiple issues may have the
+			 * same value, eg "yes" and "no".
+			 */
+			valueCorrespond.put(values[t], parameters[t]);
+
+		}
+
+	}
+
+	private double linearEstUtility(Bid bid) {
+		double linearUtility = 0.0;
+
+		// Wouter the original code was buggy. Replaced with this better
+		// version. This code is still buggy because of the valueCorrespond
+		// issue.
+		// that issue was not fixed.
+		int featurenr = 0;
+		for (String issue : issueList) {
+			Value thisbidvalue = bid.getValue(issue);
+			for (Value value : partialprofile.getDomain().getValues(issue)) {
+				if (thisbidvalue != null && thisbidvalue.equals(value)) {
+					linearUtility += valueCorrespond.get(value);
+				}
+				featurenr++;
+			}
+		}
+		return linearUtility;
+	}
+
+	/**
+	 * 
+	 * @param bid
+	 * @return Estimate known bid utility, equally divided. Seems equal to
+	 *         {@link SimpleLinearOrdering#getUtility(Bid)}
+	 */
+	private double getBidOrderUtility(Bid bid) {
+		return simpleOrdering.getUtility(bid).doubleValue();
+	}
+
+	private Action chooseAction() {
+		int round = progress.getCurrentRound();
+		int tround = progress.getTotalRounds();
+		double receiveBidUtility = 0.0;
+		double bidOrderMax = 1;// getHighUtility();
+		Bid bid;
+		if (round < tround * 0.7) {
+			if (round > 10 && receiveBids.size() < 7) {
+				int temp = (int) Math.ceil(ranklistSize * 0.1);
+				int randz = rand.nextInt(temp);
+				bid = bidOrder.get(ranklistSize - 1 - randz);
+				log("receiveBid<7,bidOrder: " + getBidOrderUtility(bid));
+				return new Offer(me, bid);
+			}
+			bid = generateBid(7, bidOrderMax);
+			return new Offer(me, bid);
+		} else if (round < tround * 0.98) {
+			if (receiveBids.size() < 10) {
+				int temp = (int) Math.ceil(ranklistSize * 0.15);
+				int randz = rand.nextInt(temp);
+				bid = bidOrder.get(ranklistSize - 1 - randz);
+				log("receiveBid<10,bidOrder: " + getBidOrderUtility(bid));
+				return new Offer(me, bid);
+			}
+			bid = generateBid(9, bidOrderMax);
+			return new Offer(me, bid);
+		} else if (round < tround * 0.99) {
+			receiveBidUtility = linearEstUtility(lastReceivedBid);
+			if (listSort) {
+				sortReceive();
+				listSort = false;
+				for (Map.Entry<Bid, Double> entry : list) {
+					System.out.println(entry);
+				}
+				log(receivehighestUtility + "\n");
+			}
+			if (receiveBidUtility > (receivehighestUtility - 0.03)) {
+				return new Accept(me, lastReceivedBid);
+			}
+			bid = generateReceiveBid();
+			log("receive bid Utility: " + linearEstUtility(lastReceivedBid)
+					+ " accept阈值: " + (receivehighestUtility - 0.07) + "\n");
+			return new Offer(me, bid);
+		} else if (round < tround * 0.995) {
+			receiveBidUtility = linearEstUtility(lastReceivedBid);
+			if (receiveBidUtility > (receivehighestUtility - 0.07)) {
+				return new Accept(me, lastReceivedBid);
+			}
+			bid = generateReceiveBid();
+			log("receive bid Utility: " + linearEstUtility(lastReceivedBid)
+					+ " accept阈值: " + (receivehighestUtility - 0.11) + "\n");
+			return new Offer(me, bid);
+		} else if (round == (tround - 1)) {
+			return new Accept(me, lastReceivedBid);
+
+		} else {
+			receiveBidUtility = linearEstUtility(lastReceivedBid);
+			if (receiveBidUtility > (receivehighestUtility - 0.1)) {
+				return new Accept(me, lastReceivedBid);
+			}
+			bid = generateReceiveBid();
+			log("receive bid Utility: " + linearEstUtility(lastReceivedBid)
+					+ " accept阈值: " + (receivehighestUtility - 0.15) + "\n");
+			return new Offer(me, bid);
+		}
+	}
+
+	public Bid generateBid(int zcnt, double bidOrderMax) {
+		Bid randomBid = null;
+		if (lastReceivedBid == null) {
+			List<Bid> b = simpleOrdering.getBids();
+			randomBid = b.get(b.size() - 1);// max bid
+		} else if (zcnt == 7) {
+			if (bidOrderMax > 0.9) {
+				do {
+					randomBid = generateRandomBid();
+				} while (linearEstUtility(randomBid) < 0.82);
+			} else if (bidOrderMax > 0.8) {
+				do {
+					randomBid = generateRandomBid();
+				} while (linearEstUtility(randomBid) < 0.75);
+			} else {
+				do {
+					randomBid = generateRandomBid();
+				} while (linearEstUtility(randomBid) < 0.7);
+			}
+		} else if (zcnt == 9) {
+			if (bidOrderMax > 0.9) {
+				do {
+					randomBid = generateRandomBid();
+				} while (linearEstUtility(randomBid) < 0.8);
+			} else if (bidOrderMax > 0.8) {
+				do {
+					randomBid = generateRandomBid();
+				} while (linearEstUtility(randomBid) < 0.7);
+			} else {
+				do {
+					randomBid = generateRandomBid();
+				} while (linearEstUtility(randomBid) < 0.68);
+			}
+		}
+
+		log(progress.getCurrentRound() + "generateBid: "
+				+ linearEstUtility(randomBid));
+		return randomBid;
+	}
+
+	private Bid generateReceiveBid() {
+		Bid bid;
+
+		int listSelectUtility = (int) Math.ceil(list.size() * 0.03);
+		double temp = list.get(listSelectUtility - 1).getValue();
+
+		if (temp < 0.7) {
+			temp = 0.7;
+			do {
+				bid = generateRandomBid();
+			} while (linearEstUtility(bid) < temp);
+			log(progress.getCurrentRound() + " generateRandomBid: "
+					+ linearEstUtility(bid) + " temp:" + temp);
+			return bid;
+		} else {
+			if (lastBidTag) {
+				int rand1 = rand.nextInt(listSelectUtility);
+				bid = list.get(rand1).getKey();
+				lastBidTag = false;
+				log(progress.getCurrentRound() + " generateReceiveBid: "
+						+ linearEstUtility(bid) + " temp:" + temp);
+				return bid;
+			} else {
+				do {
+					bid = generateRandomBid();
+				} while (linearEstUtility(bid) < temp);
+				lastBidTag = true;
+				log(progress.getCurrentRound() + " generateRandomBid: "
+						+ linearEstUtility(bid) + " temp:" + temp);
+				return bid;
+			}
+		}
+
+	}
+
+	private void sortReceive() { // 将收到的出价进行排序
+		for (Map.Entry<Bid, Double> entry : receiveBids.entrySet()) {
+			list.add(entry); // 将map中的元素放入list中
+		}
+
+		list.sort(new Comparator<Map.Entry<Bid, Double>>() {
+			@Override
+			public int compare(Map.Entry<Bid, Double> o1,
+					Map.Entry<Bid, Double> o2) {
+				double result = o2.getValue() - o1.getValue();
+				if (result > 0)
+					return 1;
+				else if (result == 0)
+					return 0;
+				else
+					return -1;
+			}
+			// 逆序（从大到小）排列，正序为“return o1.getValue()-o2.getValue”
+		});
+	}
+
+	private void log(String s) {
+		getReporter().log(Level.INFO, s);
+	}
+
+	private Bid generateRandomBid() {
+		return allbids.get(rand.nextInt(allbids.size().intValue()));
+	}
+
+}
Index: /exampleparties/anac2019/winkyagent/src/test/java/geniusweb/exampleparties/anac2019/winkyagent/WinkyAgentTest.java
===================================================================
--- /exampleparties/anac2019/winkyagent/src/test/java/geniusweb/exampleparties/anac2019/winkyagent/WinkyAgentTest.java	(revision 12)
+++ /exampleparties/anac2019/winkyagent/src/test/java/geniusweb/exampleparties/anac2019/winkyagent/WinkyAgentTest.java	(revision 12)
@@ -0,0 +1,247 @@
+package geniusweb.exampleparties.anac2019.winkyagent;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import java.io.IOException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.logging.Level;
+
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Test;
+
+import com.fasterxml.jackson.core.JsonParseException;
+import com.fasterxml.jackson.databind.JsonMappingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+import geniusweb.actions.Accept;
+import geniusweb.actions.Action;
+import geniusweb.actions.EndNegotiation;
+import geniusweb.actions.Offer;
+import geniusweb.actions.PartyId;
+import geniusweb.connection.ConnectionEnd;
+import geniusweb.issuevalue.Bid;
+import geniusweb.party.Capabilities;
+import geniusweb.party.inform.ActionDone;
+import geniusweb.party.inform.Finished;
+import geniusweb.party.inform.Inform;
+import geniusweb.party.inform.Settings;
+import geniusweb.party.inform.YourTurn;
+import geniusweb.profile.DefaultPartialOrdering;
+import geniusweb.profile.PartialOrdering;
+import geniusweb.profile.Profile;
+import geniusweb.progress.ProgressRounds;
+import geniusweb.references.Parameters;
+import geniusweb.references.ProfileRef;
+import geniusweb.references.ProtocolRef;
+import geniusweb.references.Reference;
+import tudelft.utilities.listener.DefaultListenable;
+import tudelft.utilities.logging.Reporter;
+
+public class WinkyAgentTest {
+
+	private static final String SAOP = "SAOP";
+	private static final PartyId otherparty = new PartyId("other");
+	private static final String PROFILE = "src/test/resources/jobs1partial20.json";
+	private final static ObjectMapper jackson = new ObjectMapper();
+
+	private WinkyAgent party;
+	private final TestConnection connection = new TestConnection();
+	private final ProtocolRef protocol = mock(ProtocolRef.class);
+	private ProgressRounds progress = mock(ProgressRounds.class);
+	private Settings settings;
+	private PartialOrdering profile;
+	private final Parameters parameters = new Parameters();
+
+	@Before
+	public void before() throws JsonParseException, JsonMappingException,
+			IOException, URISyntaxException {
+		when(progress.advance()).thenReturn(progress);
+		when(progress.getCurrentRound()).thenReturn(4);
+		when(progress.getTotalRounds()).thenReturn(10);
+
+		party = new WinkyAgent();
+		settings = new Settings(new PartyId("party1"),
+				new ProfileRef(new URI("file:" + PROFILE)), protocol, progress,
+				parameters);
+
+		String serialized = new String(Files.readAllBytes(Paths.get(PROFILE)),
+				StandardCharsets.UTF_8);
+		profile = (PartialOrdering) jackson.readValue(serialized,
+				Profile.class);
+
+	}
+
+	@Test
+	public void smokeTest() {
+	}
+
+	@Test
+	public void getDescriptionTest() {
+		assertNotNull(party.getDescription());
+	}
+
+	@Test
+	public void getCapabilitiesTest() {
+		Capabilities capabilities = party.getCapabilities();
+		assertFalse("party does not define protocols",
+				capabilities.getBehaviours().isEmpty());
+	}
+
+	@Test
+	public void testInformConnection() {
+		party.connect(connection);
+		// agent should not start acting just after an inform
+		assertEquals(0, connection.getActions().size());
+	}
+
+	@Test
+	public void testInformSettings() {
+		party.connect(connection);
+		connection.notifyListeners(settings);
+		assertEquals(0, connection.getActions().size());
+	}
+
+	@Test
+	public void testInformAndConnection() {
+		party.connect(connection);
+		party.notifyChange(settings);
+		assertEquals(0, connection.getActions().size());
+	}
+
+	@Test
+	public void testOtherWalksAway() {
+		party.connect(connection);
+		party.notifyChange(settings);
+
+		party.notifyChange(new ActionDone(new EndNegotiation(otherparty)));
+
+		// party should not act at this point
+		assertEquals(0, connection.getActions().size());
+	}
+
+	@Test
+	public void testAgentHasFirstTurn() {
+		party.connect(connection);
+		party.notifyChange(settings);
+
+		party.notifyChange(new YourTurn());
+		assertEquals(1, connection.getActions().size());
+		assertTrue(connection.getActions().get(0) instanceof Offer);
+	}
+
+	@Ignore // the party does not seem to accept properly. because bug?
+	@Test
+	public void testAgentAccepts() {
+		party.connect(connection);
+		party.notifyChange(settings);
+
+		Bid bid = findGoodBid();
+
+		// agent generally does not accept in round 1. But it should accept
+		// soon. Also we have progress=40% so it's not a blank atart.
+		int round = 1;
+		boolean accept = false;
+		while (round < 10 && !accept) {
+			party.notifyChange(new ActionDone(new Offer(otherparty, bid)));
+			party.notifyChange(new YourTurn());
+			assertEquals(round, connection.getActions().size());
+			accept = connection.getActions().get(round - 1) instanceof Accept;
+			round++;
+		}
+		assertTrue("Party did not accept good offer at all", accept);
+
+	}
+
+	@Test
+	public void testAgentLogsFinal() {
+		// this log output is optional, this is to show how to check log
+		Reporter reporter = mock(Reporter.class);
+		party = new WinkyAgent(reporter);
+		party.connect(connection);
+		party.notifyChange(settings);
+		party.notifyChange(new Finished(null));
+
+		verify(reporter).log(eq(Level.INFO),
+				eq("Final ourcome:Finished[null]"));
+	}
+
+	@Test
+	public void testAgentsUpdatesProgress() {
+		party.connect(connection);
+		party.notifyChange(settings);
+
+		party.notifyChange(new YourTurn());
+		verify(progress).advance();
+	}
+
+	@Test
+	public void testGetCapabilities() {
+		assertTrue(party.getCapabilities().getBehaviours().contains(SAOP));
+	}
+
+	private Bid findGoodBid() {
+		// assumes that profile is a DefaultPartial. The top 30% bids should be
+		// good.
+		if (!(profile instanceof DefaultPartialOrdering))
+			throw new IllegalStateException(
+					"Test can not be done: there is no good bid with utility>0.7");
+		List<Bid> bids = ((DefaultPartialOrdering) profile).getBids();
+		return bids.get(bids.size() - 2);
+	}
+
+}
+
+/**
+ * A "real" connection object, because the party is going to subscribe etc, and
+ * without a real connection we would have to do a lot of mocks that would make
+ * the test very hard to read.
+ *
+ */
+class TestConnection extends DefaultListenable<Inform>
+		implements ConnectionEnd<Inform, Action> {
+	private List<Action> actions = new LinkedList<>();
+
+	@Override
+	public void send(Action action) throws IOException {
+		actions.add(action);
+	}
+
+	@Override
+	public Reference getReference() {
+		return null;
+	}
+
+	@Override
+	public URI getRemoteURI() {
+		return null;
+	}
+
+	@Override
+	public void close() {
+
+	}
+
+	@Override
+	public Error getError() {
+		return null;
+	}
+
+	public List<Action> getActions() {
+		return actions;
+	}
+
+}
Index: /exampleparties/anac2019/winkyagent/src/test/resources/jobs1partial20.json
===================================================================
--- /exampleparties/anac2019/winkyagent/src/test/resources/jobs1partial20.json	(revision 12)
+++ /exampleparties/anac2019/winkyagent/src/test/resources/jobs1partial20.json	(revision 12)
@@ -0,0 +1,1018 @@
+{
+	"DefaultPartialOrdering": {
+		"name": "jobs1-partial-20",
+		"domain": {
+			"name": "jobs",
+			"issuesValues": {
+				"lease car": {
+					"values": [
+						"yes",
+						"no"
+					]
+				},
+				"permanent contract": {
+					"values": [
+						"yes",
+						"no"
+					]
+				},
+				"career development opportunities": {
+					"values": [
+						"low",
+						"medium",
+						"high"
+					]
+				},
+				"fte": {
+					"values": [
+						"0.6",
+						"0.8",
+						"1.0"
+					]
+				},
+				"salary": {
+					"values": [
+						"2000",
+						"2500",
+						"3000",
+						"3500",
+						"4000"
+					]
+				},
+				"work from home": {
+					"values": [
+						"0",
+						"1",
+						"2"
+					]
+				}
+			}
+		},
+		"reservationBid": {
+			"issuevalues": {
+				"lease car": "no",
+				"permanent contract": "no",
+				"career development opportunities": "medium",
+				"fte": "0.8",
+				"salary": "300",
+				"work from home": "0"
+			}
+		},
+		"bids": [
+			{
+				"issuevalues": {
+					"lease car": "no",
+					"permanent contract": "no",
+					"career development opportunities": "low",
+					"fte": "1.0",
+					"salary": "3000",
+					"work from home": "1"
+				}
+			},
+			{
+				"issuevalues": {
+					"lease car": "yes",
+					"permanent contract": "no",
+					"career development opportunities": "high",
+					"fte": "0.6",
+					"salary": "3500",
+					"work from home": "0"
+				}
+			},
+			{
+				"issuevalues": {
+					"lease car": "no",
+					"permanent contract": "no",
+					"career development opportunities": "high",
+					"fte": "0.8",
+					"salary": "3000",
+					"work from home": "0"
+				}
+			},
+			{
+				"issuevalues": {
+					"lease car": "yes",
+					"permanent contract": "no",
+					"career development opportunities": "low",
+					"fte": "0.6",
+					"salary": "3500",
+					"work from home": "0"
+				}
+			},
+			{
+				"issuevalues": {
+					"lease car": "no",
+					"permanent contract": "yes",
+					"career development opportunities": "low",
+					"fte": "0.6",
+					"salary": "3000",
+					"work from home": "1"
+				}
+			},
+			{
+				"issuevalues": {
+					"lease car": "yes",
+					"permanent contract": "yes",
+					"career development opportunities": "low",
+					"fte": "1.0",
+					"salary": "2000",
+					"work from home": "2"
+				}
+			},
+			{
+				"issuevalues": {
+					"lease car": "no",
+					"permanent contract": "yes",
+					"career development opportunities": "low",
+					"fte": "0.8",
+					"salary": "2500",
+					"work from home": "1"
+				}
+			},
+			{
+				"issuevalues": {
+					"lease car": "no",
+					"permanent contract": "yes",
+					"career development opportunities": "low",
+					"fte": "0.6",
+					"salary": "2000",
+					"work from home": "2"
+				}
+			},
+			{
+				"issuevalues": {
+					"lease car": "yes",
+					"permanent contract": "no",
+					"career development opportunities": "medium",
+					"fte": "0.6",
+					"salary": "3500",
+					"work from home": "1"
+				}
+			},
+			{
+				"issuevalues": {
+					"lease car": "yes",
+					"permanent contract": "yes",
+					"career development opportunities": "low",
+					"fte": "0.6",
+					"salary": "2000",
+					"work from home": "2"
+				}
+			},
+			{
+				"issuevalues": {
+					"lease car": "yes",
+					"permanent contract": "yes",
+					"career development opportunities": "medium",
+					"fte": "0.6",
+					"salary": "2000",
+					"work from home": "0"
+				}
+			},
+			{
+				"issuevalues": {
+					"lease car": "yes",
+					"permanent contract": "yes",
+					"career development opportunities": "medium",
+					"fte": "0.8",
+					"salary": "3500",
+					"work from home": "2"
+				}
+			},
+			{
+				"issuevalues": {
+					"lease car": "no",
+					"permanent contract": "no",
+					"career development opportunities": "low",
+					"fte": "0.6",
+					"salary": "2000",
+					"work from home": "0"
+				}
+			},
+			{
+				"issuevalues": {
+					"lease car": "no",
+					"permanent contract": "no",
+					"career development opportunities": "high",
+					"fte": "1.0",
+					"salary": "4000",
+					"work from home": "2"
+				}
+			},
+			{
+				"issuevalues": {
+					"lease car": "yes",
+					"permanent contract": "yes",
+					"career development opportunities": "low",
+					"fte": "0.8",
+					"salary": "4000",
+					"work from home": "2"
+				}
+			},
+			{
+				"issuevalues": {
+					"lease car": "yes",
+					"permanent contract": "no",
+					"career development opportunities": "medium",
+					"fte": "1.0",
+					"salary": "3500",
+					"work from home": "2"
+				}
+			},
+			{
+				"issuevalues": {
+					"lease car": "no",
+					"permanent contract": "yes",
+					"career development opportunities": "high",
+					"fte": "0.8",
+					"salary": "2000",
+					"work from home": "1"
+				}
+			},
+			{
+				"issuevalues": {
+					"lease car": "yes",
+					"permanent contract": "yes",
+					"career development opportunities": "low",
+					"fte": "1.0",
+					"salary": "2500",
+					"work from home": "1"
+				}
+			},
+			{
+				"issuevalues": {
+					"lease car": "yes",
+					"permanent contract": "yes",
+					"career development opportunities": "high",
+					"fte": "1.0",
+					"salary": "4000",
+					"work from home": "2"
+				}
+			},
+			{
+				"issuevalues": {
+					"lease car": "no",
+					"permanent contract": "yes",
+					"career development opportunities": "medium",
+					"fte": "0.8",
+					"salary": "2500",
+					"work from home": "1"
+				}
+			}
+		],
+		"better": [
+			[
+				0,
+				12
+			],
+			[
+				0,
+				2
+			],
+			[
+				0,
+				3
+			],
+			[
+				0,
+				7
+			],
+			[
+				0,
+				10
+			],
+			[
+				1,
+				0
+			],
+			[
+				1,
+				12
+			],
+			[
+				1,
+				2
+			],
+			[
+				1,
+				3
+			],
+			[
+				1,
+				4
+			],
+			[
+				1,
+				7
+			],
+			[
+				1,
+				10
+			],
+			[
+				2,
+				12
+			],
+			[
+				3,
+				12
+			],
+			[
+				3,
+				2
+			],
+			[
+				3,
+				7
+			],
+			[
+				4,
+				12
+			],
+			[
+				4,
+				2
+			],
+			[
+				4,
+				3
+			],
+			[
+				4,
+				7
+			],
+			[
+				4,
+				10
+			],
+			[
+				5,
+				0
+			],
+			[
+				5,
+				1
+			],
+			[
+				5,
+				2
+			],
+			[
+				5,
+				3
+			],
+			[
+				5,
+				4
+			],
+			[
+				5,
+				6
+			],
+			[
+				5,
+				7
+			],
+			[
+				5,
+				8
+			],
+			[
+				5,
+				9
+			],
+			[
+				5,
+				10
+			],
+			[
+				5,
+				12
+			],
+			[
+				5,
+				16
+			],
+			[
+				5,
+				19
+			],
+			[
+				6,
+				0
+			],
+			[
+				6,
+				1
+			],
+			[
+				6,
+				12
+			],
+			[
+				6,
+				2
+			],
+			[
+				6,
+				3
+			],
+			[
+				6,
+				4
+			],
+			[
+				6,
+				16
+			],
+			[
+				6,
+				7
+			],
+			[
+				6,
+				8
+			],
+			[
+				6,
+				9
+			],
+			[
+				6,
+				10
+			],
+			[
+				7,
+				12
+			],
+			[
+				7,
+				2
+			],
+			[
+				8,
+				0
+			],
+			[
+				8,
+				1
+			],
+			[
+				8,
+				12
+			],
+			[
+				8,
+				2
+			],
+			[
+				8,
+				3
+			],
+			[
+				8,
+				4
+			],
+			[
+				8,
+				7
+			],
+			[
+				8,
+				9
+			],
+			[
+				8,
+				10
+			],
+			[
+				9,
+				0
+			],
+			[
+				9,
+				1
+			],
+			[
+				9,
+				12
+			],
+			[
+				9,
+				2
+			],
+			[
+				9,
+				3
+			],
+			[
+				9,
+				4
+			],
+			[
+				9,
+				7
+			],
+			[
+				9,
+				10
+			],
+			[
+				10,
+				12
+			],
+			[
+				10,
+				2
+			],
+			[
+				10,
+				7
+			],
+			[
+				11,
+				0
+			],
+			[
+				11,
+				1
+			],
+			[
+				11,
+				2
+			],
+			[
+				11,
+				3
+			],
+			[
+				11,
+				5
+			],
+			[
+				11,
+				4
+			],
+			[
+				11,
+				6
+			],
+			[
+				11,
+				7
+			],
+			[
+				11,
+				8
+			],
+			[
+				11,
+				9
+			],
+			[
+				11,
+				10
+			],
+			[
+				11,
+				12
+			],
+			[
+				11,
+				13
+			],
+			[
+				11,
+				15
+			],
+			[
+				11,
+				16
+			],
+			[
+				11,
+				17
+			],
+			[
+				11,
+				19
+			],
+			[
+				13,
+				0
+			],
+			[
+				13,
+				1
+			],
+			[
+				13,
+				2
+			],
+			[
+				13,
+				3
+			],
+			[
+				13,
+				5
+			],
+			[
+				13,
+				4
+			],
+			[
+				13,
+				6
+			],
+			[
+				13,
+				7
+			],
+			[
+				13,
+				8
+			],
+			[
+				13,
+				9
+			],
+			[
+				13,
+				10
+			],
+			[
+				13,
+				12
+			],
+			[
+				13,
+				15
+			],
+			[
+				13,
+				16
+			],
+			[
+				13,
+				17
+			],
+			[
+				13,
+				19
+			],
+			[
+				14,
+				0
+			],
+			[
+				14,
+				1
+			],
+			[
+				14,
+				2
+			],
+			[
+				14,
+				3
+			],
+			[
+				14,
+				5
+			],
+			[
+				14,
+				4
+			],
+			[
+				14,
+				6
+			],
+			[
+				14,
+				7
+			],
+			[
+				14,
+				8
+			],
+			[
+				14,
+				9
+			],
+			[
+				14,
+				10
+			],
+			[
+				14,
+				11
+			],
+			[
+				14,
+				12
+			],
+			[
+				14,
+				13
+			],
+			[
+				14,
+				15
+			],
+			[
+				14,
+				16
+			],
+			[
+				14,
+				17
+			],
+			[
+				14,
+				19
+			],
+			[
+				15,
+				0
+			],
+			[
+				15,
+				1
+			],
+			[
+				15,
+				2
+			],
+			[
+				15,
+				3
+			],
+			[
+				15,
+				5
+			],
+			[
+				15,
+				4
+			],
+			[
+				15,
+				6
+			],
+			[
+				15,
+				7
+			],
+			[
+				15,
+				8
+			],
+			[
+				15,
+				9
+			],
+			[
+				15,
+				10
+			],
+			[
+				15,
+				12
+			],
+			[
+				15,
+				16
+			],
+			[
+				15,
+				17
+			],
+			[
+				15,
+				19
+			],
+			[
+				16,
+				0
+			],
+			[
+				16,
+				1
+			],
+			[
+				16,
+				12
+			],
+			[
+				16,
+				2
+			],
+			[
+				16,
+				3
+			],
+			[
+				16,
+				4
+			],
+			[
+				16,
+				7
+			],
+			[
+				16,
+				8
+			],
+			[
+				16,
+				9
+			],
+			[
+				16,
+				10
+			],
+			[
+				17,
+				0
+			],
+			[
+				17,
+				1
+			],
+			[
+				17,
+				2
+			],
+			[
+				17,
+				3
+			],
+			[
+				17,
+				5
+			],
+			[
+				17,
+				4
+			],
+			[
+				17,
+				6
+			],
+			[
+				17,
+				7
+			],
+			[
+				17,
+				8
+			],
+			[
+				17,
+				9
+			],
+			[
+				17,
+				10
+			],
+			[
+				17,
+				12
+			],
+			[
+				17,
+				16
+			],
+			[
+				17,
+				19
+			],
+			[
+				18,
+				0
+			],
+			[
+				18,
+				1
+			],
+			[
+				18,
+				2
+			],
+			[
+				18,
+				3
+			],
+			[
+				18,
+				5
+			],
+			[
+				18,
+				4
+			],
+			[
+				18,
+				6
+			],
+			[
+				18,
+				7
+			],
+			[
+				18,
+				8
+			],
+			[
+				18,
+				9
+			],
+			[
+				18,
+				10
+			],
+			[
+				18,
+				11
+			],
+			[
+				18,
+				12
+			],
+			[
+				18,
+				13
+			],
+			[
+				18,
+				14
+			],
+			[
+				18,
+				15
+			],
+			[
+				18,
+				16
+			],
+			[
+				18,
+				17
+			],
+			[
+				18,
+				19
+			],
+			[
+				19,
+				0
+			],
+			[
+				19,
+				1
+			],
+			[
+				19,
+				12
+			],
+			[
+				19,
+				2
+			],
+			[
+				19,
+				3
+			],
+			[
+				19,
+				4
+			],
+			[
+				19,
+				6
+			],
+			[
+				19,
+				16
+			],
+			[
+				19,
+				7
+			],
+			[
+				19,
+				8
+			],
+			[
+				19,
+				9
+			],
+			[
+				19,
+				10
+			]
+		]
+	}
+}
Index: /exampleparties/pom.xml
===================================================================
--- /exampleparties/pom.xml	(revision 11)
+++ /exampleparties/pom.xml	(revision 12)
@@ -26,4 +26,5 @@
 		<module>simpleshaop</module>
 		<module>comparebids</module>
+		<module>anac2019</module>
 	</modules>
 </project>
Index: /exampleparties/simpleshaop/src/main/java/geniusweb/exampleparties/simpleshaop/ShaopParty.java
===================================================================
--- /exampleparties/simpleshaop/src/main/java/geniusweb/exampleparties/simpleshaop/ShaopParty.java	(revision 11)
+++ /exampleparties/simpleshaop/src/main/java/geniusweb/exampleparties/simpleshaop/ShaopParty.java	(revision 12)
@@ -95,5 +95,5 @@
 	@Override
 	public String getDescription() {
-		return "Communicates with COB party to figure out which bids are good. Accepts bids with utility > 0.9. Offers random bids.";
+		return "Communicates with COB party to figure out which bids are good. Accepts bids with utility > 0.9. Offers random bids. Requires partial profile";
 	}
 
Index: /timeline/src/main/java/geniusweb/progress/ProgressRounds.java
===================================================================
--- /timeline/src/main/java/geniusweb/progress/ProgressRounds.java	(revision 11)
+++ /timeline/src/main/java/geniusweb/progress/ProgressRounds.java	(revision 12)
@@ -45,4 +45,22 @@
 	public Date getTerminationTime() {
 		return endtime;
+	}
+
+	/**
+	 * 
+	 * @return the current round. First round is 0. It is not recommended to use
+	 *         this, as this may make your code working with rounds only.
+	 */
+	public Integer getCurrentRound() {
+		return currentRound;
+	}
+
+	/**
+	 * 
+	 * @return total number of rounds. It is not recommended to use this, as
+	 *         this may make your code working with rounds only.
+	 */
+	public Integer getTotalRounds() {
+		return duration;
 	}
 
Index: /timeline/src/test/java/geniusweb/progress/ProgressRoundsTest.java
===================================================================
--- /timeline/src/test/java/geniusweb/progress/ProgressRoundsTest.java	(revision 11)
+++ /timeline/src/test/java/geniusweb/progress/ProgressRoundsTest.java	(revision 12)
@@ -20,7 +20,4 @@
 
 import geniusweb.deadline.DeadlineRounds;
-import geniusweb.progress.Progress;
-import geniusweb.progress.ProgressRounds;
-import geniusweb.progress.ProgressTime;
 import tudelft.utilities.junit.GeneralTests;
 
@@ -71,4 +68,9 @@
 
 	@Test
+	public void testCurrentRound() {
+		assertEquals((Integer) 0, progress.getCurrentRound());
+	}
+
+	@Test
 	public void testAdvance() {
 		ProgressRounds p = progress;
