Index: /boa/pom.xml
===================================================================
--- /boa/pom.xml	(revision 16)
+++ /boa/pom.xml	(revision 16)
@@ -0,0 +1,229 @@
+<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</groupId>
+	<artifactId>boa</artifactId>
+	<version>1.4.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.10</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>party</artifactId>
+			<version>1.4.0</version>
+		</dependency>
+		<dependency>
+			<groupId>geniusweb</groupId>
+			<artifactId>profile</artifactId>
+			<version>1.4.0</version>
+		</dependency>
+		<dependency>
+			<groupId>geniusweb</groupId>
+			<artifactId>events</artifactId>
+			<version>1.4.0</version>
+		</dependency>
+		<dependency>
+			<groupId>geniusweb</groupId>
+			<artifactId>timeline</artifactId>
+			<version>1.4.0</version>
+		</dependency>
+		<dependency>
+			<groupId>geniusweb</groupId>
+			<artifactId>profileconnection</artifactId>
+			<version>1.4.0</version>
+		</dependency>
+		<dependency>
+			<groupId>geniusweb</groupId>
+			<artifactId>bidspace</artifactId>
+			<version>1.4.0</version>
+		</dependency>
+
+		<dependency>
+			<groupId>tudelft.utilities</groupId>
+			<artifactId>logging</artifactId>
+			<version>1.0.0</version>
+		</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>https://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>
+				<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.linear.Linear</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.linear.Linear</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: /boa/src/main/java/geniusweb/boa/BoaParty.java
===================================================================
--- /boa/src/main/java/geniusweb/boa/BoaParty.java	(revision 16)
+++ /boa/src/main/java/geniusweb/boa/BoaParty.java	(revision 16)
@@ -0,0 +1,130 @@
+package geniusweb.boa;
+
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.Date;
+import java.util.HashSet;
+import java.util.Timer;
+import java.util.TimerTask;
+import java.util.logging.Level;
+
+import javax.websocket.DeploymentException;
+
+import geniusweb.actions.Action;
+import geniusweb.boa.acceptancestrategy.AcceptanceStrategy;
+import geniusweb.boa.biddingstrategy.BiddingStrategy;
+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.profileconnection.ProfileConnectionFactory;
+import geniusweb.profileconnection.ProfileInterface;
+
+/**
+ * Determines the next {@link Action} given our profile, the opponent model and
+ * the acceptance strategy Could also be called OfferingStrategy, but we use
+ * BiddingStrategy because of the name "BOA".
+ * <p>
+ * The BiddingStrategy must handle the connection, so it has to connect with the
+ * profile when the {@link Settings} come in , and create the subcomponents.
+ * 
+ * The settings are assumed to contain also parameters "as" containing the
+ * full.class.path to the {@link AcceptanceStrategy} clas, and "os" containing
+ * the full.class.path to the   {@link OpponentModel} class and "bs" containing
+ * the full.class.path to the   {@link BiddingStrategy} class.
+ * 
+ */
+public class BoaParty extends DefaultParty {
+	/**
+	 * This only supports SAOP protocol because it is not clear how the
+	 * BiddingStrategy could be made more general without basically becoming a
+	 * full Party.
+	 * 
+	 */
+	private ProfileInterface profileint;
+	private NegoState negoState = new NegoState();
+	private BiddingStrategy biddingStrategy;
+
+	@Override
+	public Capabilities getCapabilities() {
+		return new Capabilities(new HashSet<>(Arrays.asList("SAOP")));
+	}
+
+	@Override
+	public String getDescription() {
+		return "Takes parameters om=OpponentModel full.class.path,  as=AcceptanceStrategy full.class.path "
+				+ "and bs=BiddingStrategy full.class.path. "
+				+ "Builds a BOA party running on SAOP.";
+	}
+
+	@SuppressWarnings("unchecked")
+	@Override
+	public void notifyChange(Inform info) {
+		try {
+			if (info instanceof Settings) {
+				Settings settings = (Settings) info;
+				this.profileint = ProfileConnectionFactory
+						.create(settings.getProfile().getURI(), getReporter());
+				Class<BiddingStrategy> bsClass = (Class<BiddingStrategy>) Class
+						.forName((String) settings.getParemeters().get("bs"));
+				Class<AcceptanceStrategy> asClass = (Class<AcceptanceStrategy>) Class
+						.forName((String) settings.getParemeters().get("as"));
+				Class<OpponentModel> omClass = (Class<OpponentModel>) Class
+						.forName((String) settings.getParemeters().get("om"));
+				;
+				biddingStrategy = bsClass.newInstance();
+				negoState = negoState.with(settings.getProgress(),
+						settings.getID(), asClass, omClass, reporter);
+				return;
+			}
+
+			// Beyond this point the biddingStrategy should contain profile
+			if (negoState.getProfile() == null) {
+				negoState = negoState.with(profileint.getProfile());
+			}
+
+			if (info instanceof ActionDone) {
+				negoState = negoState.with(((ActionDone) info).getAction());
+			} else if (info instanceof YourTurn) {
+				waitAndAct();
+			} else if (info instanceof Finished) {
+				getReporter().log(Level.INFO, "Final ourcome:" + info);
+			}
+		} catch (DeploymentException | IOException | ClassNotFoundException
+				| InstantiationFailedException | InstantiationException
+				| IllegalAccessException e) {
+			throw new RuntimeException("Failed to handle info", e);
+		}
+
+	}
+
+	/**
+	 * If current time > {@link BiddingStrategy#getActionTime()} then execute
+	 * the action of the biddingStrategy. Otherwise, wait the specified time and
+	 * retry.
+	 */
+	private void waitAndAct() {
+		Long actionTime = biddingStrategy.getActionTime(negoState);
+		if (System.currentTimeMillis() > actionTime) {
+			try {
+				getConnection().send(biddingStrategy.getAction(negoState));
+			} catch (IOException e) {
+				getReporter().log(Level.SEVERE,
+						"Failed to execute action, connection may be broken?");
+				e.printStackTrace();
+			}
+		} else {
+			// wait specified time and retry
+			new Timer().schedule(new TimerTask() {
+				@Override
+				public void run() {
+					waitAndAct();
+				}
+			}, new Date(actionTime));
+		}
+	}
+
+}
Index: /boa/src/main/java/geniusweb/boa/InstantiationFailedException.java
===================================================================
--- /boa/src/main/java/geniusweb/boa/InstantiationFailedException.java	(revision 16)
+++ /boa/src/main/java/geniusweb/boa/InstantiationFailedException.java	(revision 16)
@@ -0,0 +1,15 @@
+package geniusweb.boa;
+
+/**
+ * Failed to create instance of some class
+ *
+ */
+public class InstantiationFailedException extends Exception {
+
+	private static final long serialVersionUID = -3368583000286378339L;
+
+	public InstantiationFailedException(String string, Throwable e) {
+		super(string, e);
+	}
+
+}
Index: /boa/src/main/java/geniusweb/boa/NegoState.java
===================================================================
--- /boa/src/main/java/geniusweb/boa/NegoState.java	(revision 16)
+++ /boa/src/main/java/geniusweb/boa/NegoState.java	(revision 16)
@@ -0,0 +1,185 @@
+package geniusweb.boa;
+
+import java.lang.reflect.Parameter;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.logging.Level;
+
+import geniusweb.actions.Action;
+import geniusweb.actions.ActionWithBid;
+import geniusweb.actions.PartyId;
+import geniusweb.boa.acceptancestrategy.AcceptanceStrategy;
+import geniusweb.boa.biddingstrategy.BiddingStrategy;
+import geniusweb.issuevalue.Bid;
+import geniusweb.party.inform.Settings;
+import geniusweb.profile.Profile;
+import geniusweb.progress.Progress;
+import tudelft.utilities.logging.Reporter;
+
+/**
+ * Stores the current state of the negotiation for a {@link BoaParty}, including
+ * the state of the opponent models
+ *
+ */
+public class NegoState {
+	private final Settings settings;
+	private final Profile profile;
+	private final Progress progress;
+	private final Class<OpponentModel> opponentModelClass;
+	private final AcceptanceStrategy acceptanceStrat;
+	private final Bid lastReceivedBid;
+	private final Map<PartyId, OpponentModel> opponentModels;
+	private final Reporter reporter;
+
+	public NegoState() {
+		this(null, null, null, null, null, null, new HashMap<>(), null);
+	}
+
+	public NegoState(Settings settings, Profile profile, Progress progr,
+			Class<OpponentModel> omClass, AcceptanceStrategy as, Bid lastRcBid,
+			Map<PartyId, OpponentModel> oppMods, Reporter reporter) {
+		this.settings = settings;
+		this.profile = profile;
+		this.progress = progr;
+		this.opponentModelClass = omClass;
+		this.acceptanceStrat = as;
+		this.lastReceivedBid = lastRcBid;
+		this.opponentModels = oppMods;
+		this.reporter = reporter;
+	}
+
+	/**
+	 * Initialize the component. Must be called first.
+	 * 
+	 * @param progress the progress to use
+	 * @param myId     the Id of this party
+	 * @param as       the acceptance strategy class
+	 * @param om       the Class of the OpponentModels
+	 * @param reporter a {@link Reporter} to log messages and errors to
+	 * @return initialized {@link BiddingStrategy}
+	 * @throws InstantiationFailedException if one of provided classes can not
+	 *                                      be instantiated.
+	 */
+
+	public NegoState with(Progress progr, PartyId myId,
+			Class<AcceptanceStrategy> asClass, Class<OpponentModel> omClass,
+			Reporter reporter) throws InstantiationFailedException {
+		AcceptanceStrategy as;
+		try {
+			as = asClass.newInstance();
+		} catch (InstantiationException | IllegalAccessException e) {
+			throw new InstantiationFailedException(
+					"Failed to create " + asClass, e);
+		}
+		return new NegoState(settings, profile, progr, omClass, as,
+				lastReceivedBid, opponentModels, reporter);
+	}
+
+	/**
+	 * 
+	 * @param profile the profile that we use. Must be called second (after the
+	 *                init call above). Can be called multiple times, if a
+	 *                profile changes
+	 * @throws InstantiationFailedException if one of provided classes can not
+	 *                                      be instantiated.
+	 */
+	public NegoState with(Profile prof) {
+		if (profile != null)
+			reporter.log(Level.WARNING,
+					"DefaultBiddingStrategy does not support profile changes. Ignored the change.");
+		return new NegoState(settings, prof, progress, opponentModelClass,
+				acceptanceStrat, lastReceivedBid, opponentModels, reporter);
+	}
+
+	/**
+	 * 
+	 * @return the settings for this negotiation, includes my {@link PartyId},
+	 *         {@link Parameter}, {@link Profile} etc.
+	 */
+	public Settings getSettings() {
+		return settings;
+	}
+
+	/**
+	 * 
+	 * @return the {@link Profile} as fetched from the profiles server, or null
+	 *         if no profile was received yet.
+	 */
+	public Profile getProfile() {
+		return profile;
+	}
+
+	/**
+	 * 
+	 * @param action the action that was done by some participant.
+	 * @return new BoaState that includes action.getBid as last bid (if action
+	 *         contains a bid), and with updated opponentmodel of that
+	 *         participant.
+	 * @throws InstantiationFailedException if one of provided classes can not
+	 *                                      be instantiated.
+	 */
+	public NegoState with(Action action) throws InstantiationFailedException {
+		try {
+			Map<PartyId, OpponentModel> newmodels = updateModels(action);
+		} catch (InstantiationException | IllegalAccessException e) {
+			throw new InstantiationFailedException("Updating the models failed:"
+					+ e.getMessage() + ". Ignoring the action", e);
+		}
+		Bid lastbid = action instanceof ActionWithBid
+				? ((ActionWithBid) action).getBid()
+				: lastReceivedBid;
+		return new NegoState(settings, profile, progress, opponentModelClass,
+				acceptanceStrat, lastbid, opponentModels, reporter);
+	}
+
+	/**
+	 * Must be called every time a 'round' as been made and the progress needs
+	 * to be incremented.
+	 * 
+	 * @param progress the new value of the progress
+	 * @return new state
+	 * @throws InstantiationFailedException if one of provided classes can not
+	 *                                      be instantiated.
+	 */
+	public NegoState with(Progress prog) {
+		return new NegoState(settings, profile, prog, opponentModelClass,
+				acceptanceStrat, lastReceivedBid, opponentModels, reporter);
+	}
+
+	/**
+	 * @param action
+	 * @return the map with the opponentmodels, with the party that did the
+	 *         action updated.
+	 * @throws InstantiationException
+	 * @throws IllegalAccessException
+	 */
+	private Map<PartyId, OpponentModel> updateModels(Action action)
+			throws InstantiationException, IllegalAccessException {
+		PartyId actor = action.getActor();
+		Map<PartyId, OpponentModel> updated = extendedOpponentModels(actor);
+		updated.put(actor, updated.get(actor).with(action, progress));
+		return updated;
+	}
+
+	/**
+	 * Get the current opponent model, extended with newparty if there is no
+	 * model yet for newparty.
+	 * 
+	 * @param newparty a possibly new party
+	 * @return a (possibly new) opponentModels map
+	 * @throws InstantiationException
+	 * @throws IllegalAccessException
+	 */
+	private Map<PartyId, OpponentModel> extendedOpponentModels(PartyId newparty)
+			throws InstantiationException, IllegalAccessException {
+		// check if this is new party
+		if (opponentModels.containsKey(newparty))
+			return opponentModels;
+
+		Map<PartyId, OpponentModel> newmodels = new HashMap<>(opponentModels);
+		OpponentModel newmodel = opponentModelClass.newInstance();
+		newmodel = newmodel.with(profile.getDomain());
+		newmodels.put(newparty, newmodel);
+		return newmodels;
+	}
+}
Index: /boa/src/main/java/geniusweb/boa/OpponentModel.java
===================================================================
--- /boa/src/main/java/geniusweb/boa/OpponentModel.java	(revision 16)
+++ /boa/src/main/java/geniusweb/boa/OpponentModel.java	(revision 16)
@@ -0,0 +1,32 @@
+package geniusweb.boa;
+
+import geniusweb.actions.Action;
+import geniusweb.issuevalue.Domain;
+import geniusweb.profile.Profile;
+import geniusweb.progress.Progress;
+
+/**
+ * An opponent model for use in the BOA system. Implementations should be
+ * immutable
+ */
+public interface OpponentModel extends Profile {
+	/**
+	 * 
+	 * @param domain
+	 * @return sets or changes the domain.
+	 */
+	OpponentModel with(Domain domain);
+
+	/**
+	 * Update this with a new action that was done by the opponent that this
+	 * model is modeling. {@link #with(Domain)} must be called before calling
+	 * this.
+	 * 
+	 * @param action   the new incoming action.
+	 * @param progress the current progress of the negotiation. Calls to this
+	 *                 must be done with increasing progress.
+	 * @return the updated {@link OpponentModel}
+	 */
+	OpponentModel with(Action action, Progress progress);
+
+}
Index: /boa/src/main/java/geniusweb/boa/acceptancestrategy/AcceptanceStrategy.java
===================================================================
--- /boa/src/main/java/geniusweb/boa/acceptancestrategy/AcceptanceStrategy.java	(revision 16)
+++ /boa/src/main/java/geniusweb/boa/acceptancestrategy/AcceptanceStrategy.java	(revision 16)
@@ -0,0 +1,15 @@
+package geniusweb.boa.acceptancestrategy;
+
+import geniusweb.boa.NegoState;
+import geniusweb.issuevalue.Bid;
+
+public interface AcceptanceStrategy {
+
+	/**
+	 * 
+	 * @param bid       the bid to be checked
+	 * @param negoState the current {@link NegoState}
+	 * @return true iff current bid is acceptable at this moment
+	 */
+	Boolean isAcceptable(Bid bid, NegoState negoState);
+}
Index: /boa/src/main/java/geniusweb/boa/biddingstrategy/BiddingStrategy.java
===================================================================
--- /boa/src/main/java/geniusweb/boa/biddingstrategy/BiddingStrategy.java	(revision 16)
+++ /boa/src/main/java/geniusweb/boa/biddingstrategy/BiddingStrategy.java	(revision 16)
@@ -0,0 +1,55 @@
+package geniusweb.boa.biddingstrategy;
+
+import geniusweb.actions.Action;
+import geniusweb.actions.PartyId;
+import geniusweb.boa.BoaParty;
+import geniusweb.boa.NegoState;
+import geniusweb.boa.OpponentModel;
+import geniusweb.boa.acceptancestrategy.AcceptanceStrategy;
+import geniusweb.party.Party;
+import geniusweb.progress.Progress;
+import tudelft.utilities.logging.Reporter;
+
+/**
+ * Interface to objects that can determines when to bid what. Implementors are
+ * assumed to model all opponents using the provided {@link OpponentModel}, and
+ * to evaluate the offered bids using the provided {@link AcceptanceStrategy}.
+ * <p>
+ * To avoid the need for the event handling as in {@link Party}, this class
+ * interfaces through different classes than Party:
+ * <ul>
+ * <li>Incoming "Settings" events are now
+ * {@link #with(Progress, PartyId, Class, Class, Reporter)}
+ * <li>Incoming notifications now {@link #with(Action)}
+ * <li>Progress advancing is now triggered with {@link #with(Progress)}
+ * <li>Outgoing actions are replaced with {@link #getAction()} and
+ * {@link #getActionTime()}.
+ * </ul>
+ * <p>
+ * Usually part of a {@link BoaParty}.
+ * 
+ * <p>
+ * MUST * have an empty constructor. Implementations are supposed to be
+ * immutable.
+ */
+public interface BiddingStrategy {
+
+	/**
+	 * @return unix time (ms since 1970 ) at which the value from
+	 *         {@link #getAction()} becomes valid. This allows the strategy to
+	 *         delay actions after it has got the turn, or to wait for other
+	 *         events to happen. Action will be executed as soon as possible
+	 *         after the indicated time.
+	 */
+	default Long getActionTime(NegoState state) {
+		return 0l;
+	}
+
+	/**
+	 * 
+	 * @return the suggested next Action. Valid only after
+	 *         {@link #getActionTime()} > System.currentTimeMillis().
+	 */
+	Action getAction(NegoState state);
+
+}
Index: /boa/src/main/java/geniusweb/boa/biddingstrategy/TimeDepemdentBiddingStrategy.java
===================================================================
--- /boa/src/main/java/geniusweb/boa/biddingstrategy/TimeDepemdentBiddingStrategy.java	(revision 16)
+++ /boa/src/main/java/geniusweb/boa/biddingstrategy/TimeDepemdentBiddingStrategy.java	(revision 16)
@@ -0,0 +1,122 @@
+package geniusweb.boa.biddingstrategy;
+
+import java.util.HashMap;
+
+import geniusweb.actions.Action;
+import geniusweb.bidspace.BidsWithUtility;
+import geniusweb.boa.NegoState;
+import geniusweb.profile.Profile;
+import geniusweb.profile.utilityspace.LinearAdditive;
+
+/**
+ * * This is an abstract class used to implement a TimeDependentAgent Strategy
+ * adapted from S. Shaheen Fatima Michael Wooldridge Nicholas R. Jennings
+ * Optimal Negotiation Strategies for Agents with Incomplete Information
+ * http://eprints.ecs.soton.ac.uk/6151/1/atal01.pdf
+ * <p>
+ * The default strategy was extended to enable the usage of opponent models.
+ * <p>
+ * Note that this agent is not fully equivalent to the theoretical model,
+ * loading the domain may take some time, which may lead to the agent skipping
+ * the first bid. A better implementation is GeniusTimeDependent_Offering.
+ * <p>
+ * The time-dependent utility target function is u(t) = k + (1.0 - k) *
+ * Math.pow((t - startTime) / (1.0 - startTime), 1.0 / e)
+ * <p>
+ * 
+ * Parameters:
+ * <ul>
+ * <li>e: the Concession factor e in the time-dependent utility target function.
+ * Must be in [0,100]. Default is 1.
+ * <li>k: the initial utility k in the time-dependent utility target function.
+ * Must be in [0,1]. For default k = 0 the agent starts with a bid of maximum
+ * utility
+ * </ul>
+ * <p>
+ * Translation from Genius
+ * negotiator.boaframework.offeringstrategy.other.GeniusTimeDependent_Offering
+ * 
+ * 
+ */
+public class TimeDepemdentBiddingStrategy implements BiddingStrategy {
+	private boolean initialized = false;
+	private Float e = 1f;
+	private Float k = 0f;
+	private BidsWithUtility bidSpace;
+	private Float min;
+	private float max;
+
+	@Override
+	public Action getAction(NegoState state) {
+		if (!initialized) {
+			init(state);
+			initialized = true;
+		}
+
+		double time = state.getProgress();
+		double utilityGoal;
+		utilityGoal = p(time);
+
+		// if there is no opponent model available
+		if (opponentModel instanceof NoModel) {
+			nextBid = negotiationSession.getOutcomeSpace()
+					.getBidNearUtility(utilityGoal);
+		} else {
+			nextBid = omStrategy.getBid(outcomespace, utilityGoal);
+		}
+		return nextBid;
+
+	}
+
+	private void init(NegoState state) {
+		HashMap<String, Object> params = state.getSettings().getParemeters();
+		Profile profile = state.getProfile();
+		if (!(profile instanceof LinearAdditive))
+			throw new IllegalArgumentException(
+					"Requires a LinearAdditive space but got "
+							+ profile.getClass());
+
+		this.bidSpace = new BidsWithUtility((LinearAdditive) profile);
+		if (params.containsKey("e")) {
+			this.e = (Float) params.get("e");
+			if (this.e < 0 || this.k > 1)
+				throw new IllegalArgumentException(
+						"e must be in [0,100] but got " + this.e);
+		}
+		if (params.containsKey("k")) {
+			this.k = (Float) params.get("k");
+			if (this.k < 0 || this.k > 1)
+				throw new IllegalArgumentException(
+						"K must be in [0,1] but got " + this.k);
+
+		}
+		this.min = bidSpace.getRange().getMin().floatValue();
+		this.max = bidSpace.getRange().getMax().floatValue();
+		if (params.containsKey("min")) {
+			this.min = (Float) params.get("min");
+			// FIXME this value might be illegal
+		}
+		if (params.containsKey("max")) {
+			this.max = (Float) params.get("max");
+			// FIXME this value might be illegal
+		}
+	}
+
+	/**
+	 * From the paper:
+	 * 
+	 * A wide range of time dependent functions can be defined by varying the
+	 * way in which f(t) is computed. However, functions must ensure that 0 <=
+	 * f(t) <= 1, f(0) = k, and f(1) = 1.
+	 * 
+	 * That is, the offer will always be between the value range, at the
+	 * beginning it will give the initial constant and when the deadline is
+	 * reached, it will offer the reservation value.
+	 */
+	public double f(double t) {
+		double ft = k + (1.0 - k)
+				* Math.pow((t - startTime) / (1.0 - startTime), 1.0 / e);
+		return ft;
+	}
+
+}
Index: /protocol/src/main/java/geniusweb/protocol/tournament/allpermutations/AllPermutationsSettings.java
===================================================================
--- /protocol/src/main/java/geniusweb/protocol/tournament/allpermutations/AllPermutationsSettings.java	(revision 15)
+++ /protocol/src/main/java/geniusweb/protocol/tournament/allpermutations/AllPermutationsSettings.java	(revision 16)
@@ -46,15 +46,11 @@
  * then these parties would be present in every session in the tournament.
  * <p>
- * If the tournament is used with a SHAOP sessionsettings, a number of rules are
- * used to generate the COB party from the settings.
- * 
- * The COB party is assumed to be the comparebids-1.0.0 party on the same server
- * as the party you provide. So if you provide http://server/../party1-1.2.3
- * then the cob party will be assumed to be at
- * http://server/../comparebids-1.0.0. The provided parties that you provide are
- * the SHAOP parties (you can also use SAOP parties). The provided profile is
- * also given to the SHAOP party. Be aware that you typically need a parameter
- * like partial=10. The COB party gets the profile as specified, but without the
- * query part. The COB and SHAOP party are thus a fixed pair.
+ * If the tournament is used with a SHAOP sessionsettings, the first member of
+ * each team is assumed to be the SHAOP party, the second the COB party. To
+ * match this, the first element of the ProfileList will have to be a partial
+ * profile to fit the needs of the SHAOP party. The second profile will have to
+ * be a normal profile, to fit the needs of the COB party. Note that you can
+ * generate a partial profile using the <code>partial=N</code> option of the
+ * profiles server.
  */
 public class AllPermutationsSettings implements TournamentSettings {
@@ -70,6 +66,6 @@
 	 * 
 	 * @param teams           a list of {@link Team}s. Must contain at least
-	 *                        <partiesPerSession> elements. The <teamsize> must
-	 *                        match the protocol: (SAOP:1, SHAOP:2)
+	 *                        {@link #teamsPerSession} elements. The <teamsize>
+	 *                        must match the protocol: (SAOP:1, SHAOP:2)
 	 * @param reuseTeams      if true, we use PermutationsWithReturn, if false
 	 *                        we use PermutationsWithoutReturn to create the
