Index: src/main/java/geniusweb/runserver/Info.java
===================================================================
--- src/main/java/geniusweb/runserver/Info.java	(revision 45)
+++ 	(revision )
@@ -1,41 +1,0 @@
-package geniusweb.runserver;
-
-import java.io.IOException;
-import java.util.HashMap;
-import java.util.Map;
-
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import geniusweb.protocol.NegoSettings;
-
-/**
- * Contains incoming connection to run a Nego. runserver/runsession with the
- * JSON {@link NegoSettings} in the request header. After the session is
- * started, the new Nego ID is returned. This can be used to find back the log
- * files..
- */
-@SuppressWarnings("serial")
-public class Info extends HttpServlet {
-
-	/**
-	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse
-	 *      response).
-	 * 
-	 * @return the ID of the new started run. Or SC_BAD_REQUEST if the request
-	 *         can not be processed.
-	 */
-	@Override
-	protected void doGet(HttpServletRequest request,
-			HttpServletResponse response) throws ServletException, IOException {
-		response.setContentType("text/plain");
-		// HACK but should be generizable easy in the future.
-		Map<String, Object> info = new HashMap<>();
-		info.put("version", getClass().getPackage().getImplementationVersion());
-		response.getWriter()
-				.append(Jackson.instance().writeValueAsString(info));
-	}
-
-}
Index: src/main/java/geniusweb/runserver/Jackson.java
===================================================================
--- src/main/java/geniusweb/runserver/Jackson.java	(revision 45)
+++ 	(revision )
@@ -1,22 +1,0 @@
-package geniusweb.runserver;
-
-import com.fasterxml.jackson.databind.ObjectMapper;
-
-/**
- * A central generator for the object mapper, so that we can extend the
- * objectmapper (with custom classes) centrally. Also allows us to cache the
- * objectmapper.
- * 
- * <b> This class should is private to the run server and should not be used by
- * others.</b>
- */
-public class Jackson {
-	private static ObjectMapper jackson;
-
-	public static ObjectMapper instance() {
-		if (jackson == null) {
-			jackson = new ObjectMapper();
-		}
-		return jackson;
-	}
-}
Index: src/main/java/geniusweb/runserver/PartyConnection.java
===================================================================
--- src/main/java/geniusweb/runserver/PartyConnection.java	(revision 1)
+++ src/main/java/geniusweb/runserver/PartyConnection.java	(revision 1)
@@ -0,0 +1,226 @@
+package geniusweb.runserver;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.net.HttpURLConnection;
+import java.net.SocketException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.logging.Level;
+
+import javax.websocket.ClientEndpoint;
+import javax.websocket.CloseReason;
+import javax.websocket.ContainerProvider;
+import javax.websocket.DeploymentException;
+import javax.websocket.OnClose;
+import javax.websocket.OnError;
+import javax.websocket.OnMessage;
+import javax.websocket.OnOpen;
+import javax.websocket.Session;
+import javax.websocket.WebSocketContainer;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+import geniusweb.actions.Action;
+import geniusweb.actions.PartyId;
+import geniusweb.party.inform.Inform;
+import geniusweb.protocol.partyconnection.ConnectionWithParty;
+import geniusweb.references.Reference;
+import tudelft.utilities.listener.DefaultListenable;
+import tudelft.utilities.logging.ReportToLogger;
+import tudelft.utilities.logging.Reporter;
+
+/**
+ * A websocket based {@link ConnectionWithParty}. Must be public so that it can
+ * be accessed as ClientEndpoint by apache tomcat
+ */
+@ClientEndpoint
+public class PartyConnection extends DefaultListenable<Action>
+		implements ConnectionWithParty {
+	private final static ObjectMapper jackson = new ObjectMapper();
+	private final Reporter log;
+
+	private final Reference reference;
+
+	private WebSocketContainer container;
+	private Session session = null;
+	private URI partyuri;
+	private Throwable error = null;
+
+	/**
+	 * Constructor that uses default {@link Reporter}
+	 * 
+	 * @param reference the address to to a http GET to get a websocket to a new
+	 *                  running party.
+	 */
+	public PartyConnection(Reference reference) {
+		this(reference, new ReportToLogger("runserver"));
+	}
+
+	/**
+	 * 
+	 * @param reference the address to to a http GET to get a websocket to a new
+	 *                  running party.
+	 * @param reporter  the {@link Reporter} used for logging important
+	 *                  events/issues
+	 * @throws IOException if the party does not start properly.
+	 */
+	public PartyConnection(Reference reference, Reporter reporter) {
+		this.reference = reference;
+		this.log = reporter;
+
+	}
+
+	public PartyConnection init() throws IOException {
+		log.log(Level.INFO, "Trying to start up party " + reference);
+		URI partyuri = startParty(reference);
+
+		container = ContainerProvider.getWebSocketContainer();
+		log.log(Level.INFO,
+				"Trying to make websocket connection to running party "
+						+ partyuri);
+		try {
+			container.connectToServer(this, partyuri);
+		} catch (DeploymentException e) {
+			throw new IOException(
+					"Failed to connect with running party at " + partyuri, e);
+		}
+		log.log(Level.INFO, "Created websocket connection at  " + partyuri);
+		return this;
+	}
+
+	/**
+	 * 
+	 * @param reference the address to to a http GET to get a websocket to a new
+	 *                  running party.
+	 * @return URI of websocket behind which is a running party
+	 * @throws IOException if party did not start correctly
+	 */
+	private URI startParty(Reference reference) throws IOException {
+		HttpURLConnection conn = (HttpURLConnection) reference.getURI().toURL()
+				.openConnection();
+		// if this throws, the IOException seems to contain the "retry later"
+		// message
+		// already
+		conn.setRequestMethod("GET"); // TODO timeout
+		BufferedReader rd;
+		try {
+			rd = new BufferedReader(
+					new InputStreamReader(conn.getInputStream()));
+		} catch (IOException e) {
+			// read the detail message from the error stream
+			rd = new BufferedReader(
+					new InputStreamReader(conn.getErrorStream()));
+			throw new IOException(rd.readLine(), e);
+		}
+		String partysocketaddress = rd.readLine();
+		log.log(Level.INFO, "startparty returned " + partysocketaddress);
+		if (conn.getResponseCode() != HttpURLConnection.HTTP_OK) {
+			throw new IOException(
+					"Something went wrong connecting to the party:"
+							+ conn.getResponseCode());
+		}
+		try {
+			this.partyuri = new URI(partysocketaddress);
+		} catch (URISyntaxException e1) {
+			throw new IOException("Failed to start party at " + reference, e1);
+		}
+		return partyuri;
+	}
+
+	/************* implements {@link ConnectionWithParty} ***************/
+	@Override
+	public void send(Inform info) throws IOException {
+		if (session == null)
+			return;
+		session.getBasicRemote().sendText(jackson.writeValueAsString(info));
+	}
+
+	@Override
+	public Reference getReference() {
+		return this.reference;
+	}
+
+	@Override
+	public PartyId getParty() {
+		String name = partyuri.getPath();
+		return new PartyId(name.substring(name.lastIndexOf('/') + 1));
+	}
+
+	@Override
+	public void close() {
+		log.log(Level.INFO, "Party close called");
+		setError(new SocketException("socket is closed"));
+		try {
+			session.close();
+			this.session = null;
+		} catch (IOException e) {
+			log.log(Level.SEVERE, "failed to close websocket", e);
+		}
+	}
+
+	/************* implements ClientEndpoint ***************/
+
+	@OnOpen
+	public void onOpen(Session session) {
+		log.log(Level.INFO, "Party is being connected: " + session);
+		this.session = session;
+	}
+
+	@OnClose
+	public void onClose(Session userSession, CloseReason reason) {
+		log.log(Level.INFO, "closing websocket " + reference + ":" + reason);
+		setError(new SocketException("socket has been closed"));
+
+	}
+
+	@OnMessage
+	public void processMessage(String message) {
+		try {
+			Action act = jackson.readValue(message, Action.class);
+			notifyChange(act);
+		} catch (IOException e) {
+			log.log(Level.WARNING,
+					"received bad message from client " + reference, e);
+			setError(e);
+			close();
+		}
+	}
+
+	@OnError
+	public void processError(Throwable t) {
+		log.log(Level.SEVERE, "Something went wrong internally!", t);
+		setError(t);
+	}
+
+	@Override
+	public URI getRemoteURI() {
+		return partyuri;
+	}
+
+	@Override
+	public Throwable getError() {
+		return error;
+	}
+
+	/**
+	 * Sets the connection to final error state and report null to listeners.
+	 * Only the first error is reported, the rest is ignored.
+	 * 
+	 * @param err the error that occurred.
+	 */
+	private void setError(Throwable err) {
+		boolean isSet = false;
+		synchronized (this) {
+			if (this.error == null) {
+				this.error = err;
+				isSet = true;
+			}
+		}
+		if (isSet) {
+			notifyChange(null);
+		}
+	}
+
+}
Index: src/main/java/geniusweb/runserver/PartyConnectionFactory.java
===================================================================
--- src/main/java/geniusweb/runserver/PartyConnectionFactory.java	(revision 45)
+++ src/main/java/geniusweb/runserver/PartyConnectionFactory.java	(revision 1)
@@ -12,6 +12,6 @@
 import java.util.logging.Level;
 
-import geniusweb.protocol.partyconnection.ProtocolToPartyConn;
-import geniusweb.protocol.partyconnection.ProtocolToPartyConnFactory;
+import geniusweb.protocol.partyconnection.ConnectionWithParty;
+import geniusweb.protocol.partyconnection.ConnectionWithPartyFactory;
 import geniusweb.references.PartyRef;
 import geniusweb.references.Reference;
@@ -23,5 +23,5 @@
  * following the partiesserver protocols.
  */
-class PartyConnectionFactory implements ProtocolToPartyConnFactory {
+class PartyConnectionFactory implements ConnectionWithPartyFactory {
 	private final Reporter log;
 
@@ -35,8 +35,8 @@
 
 	@Override
-	public WebSocketProtToPartyConn connect(Reference reference)
+	public PartyConnection connect(Reference reference)
 			throws IOException, NoResourcesNowException {
 		try {
-			return new WebSocketProtToPartyConn(reference, log).init();
+			return new PartyConnection(reference, log).init();
 		} catch (IOException e) {
 			Date date = getWaitingTime(e);
@@ -60,5 +60,5 @@
 
 	@Override
-	public List<ProtocolToPartyConn> connect(List<Reference> references)
+	public List<ConnectionWithParty> connect(List<Reference> references)
 			throws IOException, NoResourcesNowException {
 		/*
@@ -70,8 +70,8 @@
 		 */
 		log.log(Level.INFO, "attempting to connect " + references);
-		List<ProtocolToPartyConn> connections = new LinkedList<>();
+		List<ConnectionWithParty> connections = new LinkedList<>();
 		try {
 			for (Reference partyref : references) {
-				ProtocolToPartyConn conn = null;
+				ConnectionWithParty conn = null;
 				while (conn == null) {
 					try {
@@ -87,5 +87,5 @@
 		} catch (IOException | NoResourcesNowException e) {
 			// free all already created connections
-			for (ProtocolToPartyConn conn : connections) {
+			for (ConnectionWithParty conn : connections) {
 				conn.close();
 			}
Index: src/main/java/geniusweb/runserver/RunNego.java
===================================================================
--- src/main/java/geniusweb/runserver/RunNego.java	(revision 45)
+++ src/main/java/geniusweb/runserver/RunNego.java	(revision 1)
@@ -9,4 +9,6 @@
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
 
 import geniusweb.protocol.NegoSettings;
@@ -23,4 +25,5 @@
 public class RunNego extends HttpServlet {
 	private final Reporter log;
+	private final static ObjectMapper jackson = new ObjectMapper();
 
 	public RunNego() {
@@ -35,8 +38,14 @@
 	/**
 	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse
-	 *      response).
-	 * 
-	 * @return the ID of the new started run. Or SC_BAD_REQUEST if the request
-	 *         can not be processed.
+	 *      response). Returns
+	 *      <ul>
+	 *      <li>URL with websocket address to contact the now running party.
+	 *      <li>SC_NOT_FOUND (404) if attempt is made to access non-running
+	 *      party.
+	 *      <li>SC_SERVICE_UNAVAILABLE (503) if there are no free slots to run
+	 *      the party.
+	 *      <li>SC_EXPECTATION_FAILED (417) if something else goes wrong during
+	 *      instantiating the party (then see logs for more details)
+	 *      </ul>
 	 */
 	@Override
@@ -47,21 +56,15 @@
 		NegoSettings settings;
 		try {
-			settings = Jackson.instance().readValue(reqstring,
-					NegoSettings.class);
+			settings = jackson.readValue(reqstring, NegoSettings.class);
 		} catch (IOException e) {
 			response.sendError(HttpServletResponse.SC_BAD_REQUEST,
 					e.getMessage());
-			System.err.println("Run request failed " + reqstring);
-			e.printStackTrace(); // helpful for debugging run requests
 			return;
 		}
 		log.log(Level.INFO, "request to run Nego: " + settings);
-		RunningNego running = new RunningNego(settings,
+		RunningNego session = new RunningNego(settings,
 				RunningNegotiationsRepo.instance(), log);
-		running.start();
-		// set content type to prevent some browsers
-		// trying to parse this (eg as XML)
-		response.setContentType("application/json");
-		response.getWriter().append(running.getID());
+		RunningNegotiationsRepo.instance().put(session);
+		response.getWriter().append(session.getID());
 	}
 
Index: src/main/java/geniusweb/runserver/RunningNego.java
===================================================================
--- src/main/java/geniusweb/runserver/RunningNego.java	(revision 45)
+++ src/main/java/geniusweb/runserver/RunningNego.java	(revision 1)
@@ -8,4 +8,6 @@
 import java.nio.file.Paths;
 import java.util.logging.Level;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
 
 import geniusweb.events.ProtocolEvent;
@@ -25,5 +27,6 @@
 	private static final String LOGDIRNAME = "log";
 	private static final Path logdir = getLogDir();
-	private static long negoNr = System.currentTimeMillis(); // generate unique IDs.
+	private static int negoNr = 1; // generate unique IDs.
+	private static final ObjectMapper jackson = new ObjectMapper();
 
 	private final String sessionid;
@@ -33,6 +36,5 @@
 
 	/**
-	 * Create new session wth unique ID. You should call {@link #start()} to
-	 * actually start this.
+	 * Create new session wth unique ID.
 	 * 
 	 * @param settings the settings to use for this session
@@ -46,14 +48,10 @@
 			Reporter logger) {
 		this.log = logger;
-		this.protocol = settings.getProtocol(logger);
+		protocol = settings.getProtocol(logger);
 		this.sessionid = "" + protocol.getRef().getURI() + (negoNr++);
 		this.repo = repo;
-	}
-
-	public void start() {
-		log.log(Level.INFO, "new negotiation session. logging to " + logdir);
-		repo.put(this);
+		System.out.println("new session. logging to " + logdir);
 		protocol.addListener(evt -> handle(evt));
-		protocol.start(new PartyConnectionFactory(log));
+		protocol.start(new PartyConnectionFactory(logger));
 	}
 
@@ -78,7 +76,7 @@
 			PrintWriter out = new PrintWriter(
 					logdir.resolve(sessionid + ".json").toFile());
-			out.print(Jackson.instance().writeValueAsString(sessionState));
+			out.print(jackson.writeValueAsString(sessionState));
 			out.close();
-		} catch (Throwable e) { // also catch outOfMem etc.
+		} catch (IOException e) {
 			log.log(Level.SEVERE, "Failed to write log file for " + sessionid,
 					e);
Index: src/main/java/geniusweb/runserver/RunningNegotiationsRepo.java
===================================================================
--- src/main/java/geniusweb/runserver/RunningNegotiationsRepo.java	(revision 45)
+++ src/main/java/geniusweb/runserver/RunningNegotiationsRepo.java	(revision 1)
@@ -55,5 +55,5 @@
 		}
 		negotiations.put(entity.getID(), entity);
-		notifyListeners(entity.getID());
+		notifyChange(entity.getID());
 		log.log(Level.FINEST, "started " + entity.getID());
 	}
@@ -62,5 +62,5 @@
 	public void remove(String id) {
 		negotiations.remove(id);
-		notifyListeners(id);
+		notifyChange(id);
 		log.log(Level.FINEST, "stopped negotiation " + id);
 	}
@@ -73,5 +73,5 @@
 		}
 		negotiations.put(entity.getID(), entity);
-		notifyListeners(entity.getID());
+		notifyChange(entity.getID());
 		log.log(Level.FINEST, "replaced " + entity.getID());
 
Index: src/main/java/geniusweb/runserver/WebSocketProtToPartyConn.java
===================================================================
--- src/main/java/geniusweb/runserver/WebSocketProtToPartyConn.java	(revision 45)
+++ 	(revision )
@@ -1,278 +1,0 @@
-package geniusweb.runserver;
-
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.InputStreamReader;
-import java.net.HttpURLConnection;
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.util.logging.Level;
-
-import javax.websocket.ClientEndpoint;
-import javax.websocket.CloseReason;
-import javax.websocket.ContainerProvider;
-import javax.websocket.DeploymentException;
-import javax.websocket.OnClose;
-import javax.websocket.OnError;
-import javax.websocket.OnMessage;
-import javax.websocket.OnOpen;
-import javax.websocket.Session;
-import javax.websocket.WebSocketContainer;
-
-import geniusweb.actions.Action;
-import geniusweb.actions.PartyId;
-import geniusweb.inform.Inform;
-import geniusweb.protocol.partyconnection.ProtocolToPartyConn;
-import geniusweb.references.Reference;
-import tudelft.utilities.listener.DefaultListenable;
-import tudelft.utilities.logging.ReportToLogger;
-import tudelft.utilities.logging.Reporter;
-
-/**
- * A websocket based {@link ProtocolToPartyConn}. it contains a websocket
- * connection to a party (that will be started using the partyserver
- * start-new-party protocol). Must be public so that it can be accessed as
- * ClientEndpoint by apache tomcat. This is internally used.
- * 
- * <p>
- * The @ClientEndpoint annotation is important, the runserver is creating these
- * sockets programatically, from a received ws: URL.
- */
-@ClientEndpoint
-public class WebSocketProtToPartyConn extends DefaultListenable<Action>
-		implements ProtocolToPartyConn {
-	// 20MB seems reasonable limit?
-	private static final int MAX_MESSAGE_SIZE = 20 * 1024 * 1024;
-	private final Reporter log;
-
-	private final Reference reference;
-
-	private WebSocketContainer container;
-	private Session session = null;
-	private URI partyuri;
-	private Throwable error = null;
-
-	/**
-	 * Buffers incoming text.
-	 */
-	private StringBuffer buffer = new StringBuffer();
-
-	/**
-	 * Constructor that uses default {@link Reporter}
-	 * 
-	 * @param reference the address to to a http GET to get a websocket to a new
-	 *                  running party.
-	 */
-	public WebSocketProtToPartyConn(Reference reference) {
-		this(reference, new ReportToLogger("runserver"));
-	}
-
-	/**
-	 * 
-	 * @param reference the address to to a http GET to get a websocket to a new
-	 *                  running party.
-	 * @param reporter  the {@link Reporter} used for logging important
-	 *                  events/issues
-	 * @throws IOException if the party does not start properly.
-	 */
-	public WebSocketProtToPartyConn(Reference reference, Reporter reporter) {
-		this.reference = reference;
-		this.log = reporter;
-
-	}
-
-	public WebSocketProtToPartyConn init() throws IOException {
-		log.log(Level.INFO, "Trying to start up party " + reference);
-		URI partyuri = startParty(reference);
-
-		container = ContainerProvider.getWebSocketContainer();
-		// #50 disable: might cause large buffer. And why is this a good limit
-		// anyway
-		// container.setDefaultMaxTextMessageBufferSize(200000);
-
-		log.log(Level.INFO,
-				"Trying to make websocket connection to running party "
-						+ partyuri);
-		try {
-			container.connectToServer(this, partyuri);
-		} catch (DeploymentException e) {
-			throw new IOException(
-					"Failed to connect with running party at " + partyuri, e);
-		}
-		log.log(Level.INFO, "Created websocket connection at  " + partyuri);
-		return this;
-	}
-
-	/**
-	 * 
-	 * @param reference the address to to a http GET to get a websocket to a new
-	 *                  running party.
-	 * @return URI of websocket behind which is a running party
-	 * @throws IOException if party did not start correctly
-	 */
-	private URI startParty(Reference reference) throws IOException {
-		HttpURLConnection conn = (HttpURLConnection) reference.getURI().toURL()
-				.openConnection();
-		// if this throws, the IOException seems to contain the "retry later"
-		// message already
-		conn.setRequestMethod("GET");
-		conn.setReadTimeout(20000);
-		conn.connect();
-		BufferedReader rd;
-		try {
-			rd = new BufferedReader(
-					new InputStreamReader(conn.getInputStream()));
-		} catch (IOException e) {
-			if (conn.getErrorStream() == null) {
-				throw new IOException("Failed to connect " + reference
-						+ ", no server error message", e);
-			}
-			// read the detail message from the error stream
-			rd = new BufferedReader(
-					new InputStreamReader(conn.getErrorStream()));
-			throw new IOException(rd.readLine(), e);
-		}
-		String partysocketaddress = rd.readLine();
-		log.log(Level.INFO, "startparty returned " + partysocketaddress);
-		if (conn.getResponseCode() != HttpURLConnection.HTTP_OK) {
-			throw new IOException(
-					"Something went wrong connecting to the party:"
-							+ conn.getResponseCode());
-		}
-		try {
-			this.partyuri = new URI(partysocketaddress);
-		} catch (URISyntaxException e1) {
-			throw new IOException("Failed to start party at " + reference, e1);
-		}
-		return partyuri;
-	}
-
-	/************* implements {@link ConnectionWithParty} ***************/
-	@Override
-	public void send(Inform info) throws IOException {
-		if (session == null)
-			return;
-		session.getBasicRemote()
-				.sendText(Jackson.instance().writeValueAsString(info));
-	}
-
-	@Override
-	public Reference getReference() {
-		return this.reference;
-	}
-
-	@Override
-	public PartyId getParty() {
-		String name = partyuri.getPath();
-		return new PartyId(name.substring(name.lastIndexOf('/') + 1));
-	}
-
-	@Override
-	public void close() {
-		log.log(Level.INFO, "Party close called");
-		// a close event is not necessarily a bug?
-		// setError(new SocketException("socket is closed"));
-		try {
-			session.close();
-			this.session = null;
-		} catch (IOException e) {
-			log.log(Level.SEVERE, "failed to close websocket", e);
-		}
-	}
-
-	/************* implements ClientEndpoint ***************/
-
-	@OnOpen
-	public void onOpen(Session session) {
-		log.log(Level.INFO, "Party is being connected: " + session);
-// #50 we now buffer partial messages
-//		session.setMaxTextMessageBufferSize(MAX_MESSAGE_SIZE);
-//		session.setMaxBinaryMessageBufferSize(MAX_MESSAGE_SIZE);
-		this.session = session;
-	}
-
-	@OnClose
-	public void onClose(Session userSession, CloseReason reason) {
-		log.log(Level.INFO, "closing websocket " + reference + ":" + reason);
-		if (reason.getReasonPhrase() != null
-				&& !reason.getReasonPhrase().isEmpty()) {
-			setError(new RemoteException("Session " + reference
-					+ " closed abnormally (see party server for more details) "
-					+ reason.getReasonPhrase()));
-		}
-		// seems NOT an error. Unless the party deliberately and silently
-		// closes its connection.
-		// Setting error will cause a print of stacktrace that is disturbing.
-		// It seems we can not check at this point if session was finished.
-		// setError(new SocketException("socket has been closed"));
-	}
-
-	@OnMessage
-	public void processMessage(String message, boolean islast) {
-		// #50 avoid fixed (large) buffers
-		buffer.append(message);
-		if (islast) {
-			String msg = buffer.toString();
-			buffer = new StringBuffer();
-			try {
-				Action act = Jackson.instance().readValue(msg, Action.class);
-				notifyListeners(act);
-			} catch (IOException e) {
-				log.log(Level.WARNING,
-						"received bad message from client " + reference, e);
-				setError(e);
-				close();
-			}
-		}
-	}
-
-	@OnError
-	public void processError(Throwable t) {
-		log.log(Level.SEVERE, "Something went wrong internally!", t);
-		setError(t);
-	}
-
-	@Override
-	public URI getRemoteURI() {
-		return partyuri;
-	}
-
-	@Override
-	public Throwable getError() {
-		return error;
-	}
-
-	/**
-	 * Sets the connection to final error state and report null to listeners.
-	 * Only the first error is reported, the rest is ignored.
-	 * 
-	 * @param err the error that occurred.
-	 */
-	private void setError(Throwable err) {
-		boolean isSet = false;
-		synchronized (this) {
-			if (this.error == null) {
-				this.error = err;
-				isSet = true;
-			}
-		}
-		if (isSet) {
-			// special event that tells protocol that we're probably in error
-			// state.
-			notifyListeners(null);
-		}
-	}
-
-}
-
-/**
- * Indicates an exceeption occured on a remote machine. The remote machine did
- * not pass a stacktrace (because it does not fit into a websocket close call).
- *
- */
-class RemoteException extends Exception {
-	public RemoteException(String message) {
-		super(message, null, false, false);
-
-	}
-}
Index: src/main/webapp/WEB-INF/web.xml
===================================================================
--- src/main/webapp/WEB-INF/web.xml	(revision 45)
+++ src/main/webapp/WEB-INF/web.xml	(revision 1)
@@ -5,21 +5,4 @@
 <web-app>
 	<display-name>GeniusWeb Run Server</display-name>
-
-	<filter>
-		<filter-name>CorsFilter</filter-name>
-		<filter-class>org.apache.catalina.filters.CorsFilter</filter-class>
-		<init-param>
-			<param-name>cors.allowed.origins</param-name>
-			<param-value>*</param-value>
-		</init-param>
-		<init-param>
-			<param-name>cors.exposed.headers</param-name>
-			<param-value>Access-Control-Allow-Origin</param-value>
-		</init-param>
-	</filter>
-	<filter-mapping>
-		<filter-name>CorsFilter</filter-name>
-		<url-pattern>/*</url-pattern>
-	</filter-mapping>
 
 	<servlet>
@@ -44,12 +27,5 @@
 		<servlet-class>geniusweb.runserver.RunNego</servlet-class>
 	</servlet>
-
-	<servlet>
-		<servlet-name>Info</servlet-name>
-		<display-name>Info</display-name>
-		<description>get info</description>
-		<servlet-class>geniusweb.runserver.Info</servlet-class>
-	</servlet>
-
+	
 
 	<servlet-mapping>
@@ -61,8 +37,5 @@
 		<url-pattern>/run</url-pattern>
 	</servlet-mapping>
-	<servlet-mapping>
-		<servlet-name>Info</servlet-name>
-		<url-pattern>/info</url-pattern>
-	</servlet-mapping>
+
 
 </web-app>
Index: src/main/webapp/index.jsp
===================================================================
--- src/main/webapp/index.jsp	(revision 45)
+++ src/main/webapp/index.jsp	(revision 1)
@@ -1,21 +1,14 @@
 <html>
-<head>
-<link rel="stylesheet" type="text/css" href="style.css" />
-</head>
 <body>
-	<h1>GeniusWeb Run Server</h1>
+<h1>Genius 2 Run Server</h1>
 
-	<!-- the onclick construct is to pass through the search term in the URL  -->
-	<aa onclick="window.location='newsession.xhtml'+window.location.search;" >new session</aa>
-	<br>
-	<aa onclick="window.location='newtournament.xhtml'+window.location.search;" >new tournament</aa>
-	<br>
-	<aa onclick="window.location='running.xhtml'+window.location.search;" >view currently running negotiations</aa>
-	<br>
-	<a href="log">view logs</a>
-	<p>
-		For help and more info, please refer to the <a
-			href="https://tracinsy.ewi.tudelft.nl/pubtrac/GeniusWebRunServer">
-			run server page</a>.
+<a href="newsession.xhtml">new session</a>
+<br>
+<a href="newtournament.xhtml">new tournament</a>
+<br>
+<a href="running.xhtml">view currently running negotiations</a>
+<br>
+<a href="log">view logs</a>
+<br>
 </body>
 </html>
Index: src/main/webapp/newsession.xhtml
===================================================================
--- src/main/webapp/newsession.xhtml	(revision 45)
+++ src/main/webapp/newsession.xhtml	(revision 1)
@@ -4,4 +4,5 @@
 <title>Profiles and Domains list</title>
 <link rel="stylesheet" type="text/css" href="style.css" />
+
 </head>
 <body onload="init()">
@@ -12,51 +13,26 @@
 
 	<br /> Protocol:
-	<select id="selectedprotocol" onchange="selectProtocol()">
-		<option value="SAOP">SAOP ( Stacked Alternating Offers
-			Protocol )</option>
-		<option value="MOPAC">MOPAC (Multiple Offers Partial
-			Consensus)</option>
-		<option value="MOPAC2">MOPAC2 (MOPAC but with values for each vote)</option>
-		<option value="AMOP">AMOP (Alternating Multiple Offers
-			Protocol)</option>
-		<option value="SHAOP">SHAOP (Stacked Human Alternating Offers
-			Protocol)</option>
-		<option value="Learn">Learn</option>
-			
+	<select>
+		<option value="SAOP">SAOP</option>
 	</select>
 
-	<div id="votingevaluator">
-		<br /> Voting Evaluator: <select id="selectedevaluator">
-			<option value="LargestAgreement">Largest Agreement</option>
-			<option value="LargestAgreementsLoop">Largest Agreements and Repeat</option>
-		</select>
-	</div>
-	<div id="votingevaluator2">
-		<br /> Voting Evaluator: <select id="selectedevaluator2">
-			<option value="LargestAgreementWithValue">Largest Agreement with Values</option>
-		</select>
-	</div>
-
-	
 	<br /> Deadline:
 	<input type="number" id="deadlinevalue" name="deadline" min="1"
 		max="10000" value="10" />
 	<select id="deadlinetype">
+		<option value="TIME">seconds</option>
 		<option value="ROUNDS">rounds</option>
-		<option value="TIME">seconds</option>
 	</select>
 
-	<div id="profserverselector">
 	<br /> Domain/Profile Server:
 	<input type="url" name="url" id="profilesserverurl"
-		value="localhost:8080/profilesserver-2.1.6"
-		pattern=".*:[0-9]+/profilesserver.*" size="30"
+		value="localhost:8080/profilesserver-1.0.0"
+		pattern=".*:[0-9]+/profilesserver" size="30"
 		onchange="connectDomain()"> </input>
 	<br /> Domain:
-	<select id="domainselection" onchange="selectDomain()">
+	<select id="domainselection" onclick="selectDomain()">
 		<!-- <option>Waiting for profiles server</option> -->
 	</select>
-	</div>
-	
+
 	<br />
 	<br />
@@ -64,35 +40,10 @@
 	<div id="box" class="box">
 		<br /> <b>Participants</b> <br /> Parties Server: <input type="url"
-			name="url" id="partiesserverurl"
-			value="localhost:8080/partiesserver-2.1.6"
-			pattern=".*:[0-9]+/partiesserver.*" size="30"
-			onchange="connectParties()"> </input> <br /> <br /> <b>Party
-			settings</b> <br /> Party : <select id="partyselection">
-		</select> <br /> 
-		
-		<div id="profileselector">
-		Profile: <select id="profileselection"></select> Filter: <input
-			type="text" id="filter" value="" maxlength="40" /> <br />
-		</div>
-		Parameters: {
-		<textarea id="parameters" rows="2" cols="70"
-			onchange="updateParameters()" value="" />
-		} <br /> <br />
-
-		<div id="cobsetting">
-			<input type="checkbox" id="advancedCobSettings"
-				onchange="advancedCobSet()"></input> Advanced COB settings<br />
-			<div id="advancedsettings" style="display: none">
-				<b>COB party settings</b> <br /> Party : <select
-					id="cobpartyselection">
-				</select> <br /> Profile: <select id="cobprofileselection"></select> Filter:
-				<input type="text" id="cobfilter" value="" maxlength="40" /> <br />
-				<!--  -->
-				Parameters: {
-				<textarea id="cobparameters" rows="2" cols="70"
-					onchange="updateCobParameters()" value="" />
-				} <br /> <br />
-			</div>
-		</div>
+			name="url" id="partiesserverurl" value="localhost:8080/partiesserver-1.0.0"
+			pattern=".*:[0-9]+/partiesserver" size="30"
+			onchange="connectParties()"> </input> <br />
+		<br /> <b>Edit next party</b> <br /> Party: <select id="partyselection">
+		</select> <br /> Profile: <select id="profileselection">
+		</select> <br />
 
 		<button onclick="addParty()">Add</button>
@@ -100,25 +51,13 @@
 
 		<br /> <br /> <b>Selected Profiles, Parties for the session</b>
-		<table id="selectedpartiestable" width="100%">
-			<colgroup>
-				<col />
-				<col />
-				<col />
-				<col />
-				<col />
-				<col />
-			</colgroup>
+		<table>
 			<thead>
-				<tr>
-					<th align="center">Party</th>
-					<th align="center">Parameters</th>
-					<th align="center">Profile</th>
-
-					<th align="center">COB Party</th>
-					<th align="center">COB Parameters</th>
-					<th align="center">COB Profile</th>
-				</tr>
+				<th align="left" width='40%'>Party</th>
+				<th align="left" width='40%'>Profile</th>
 			</thead>
 			<tbody id="partiesList">
+				<tr id="partiesList">
+				</tr>
+
 			</tbody>
 		</table>
@@ -132,10 +71,7 @@
 
 	<div id="started" style="visibility: hidden">
-		Your session started. Waiting for the results. <br />
+		Your session started.<br /> <a href="" id="logref">view the log
+			file</a> <br /> <a href="" id="plotref">render a utilities plot</a>.
 	</div>
-	<div id="results" style="visibility: hidden">
-		Session completed. <a href="" id="logref">view the log file</a> <br />
-		<a href="" id="plotref">render a utilities plot</a>.
-	</div>
 
 </body>
@@ -144,28 +80,15 @@
 	
 	
-	
-	
-	
-	
-	
-	
-	
-	
-	
 	// FIXME quick and dirty code. No clean MVC
 	
 	
 	<![CDATA[
-        //"use strict";	
+        "use strict";	
         
         var domainwebsocket = null;
-        var partieslistlistener=null;
-        // current setting of parameters
-        var parameters = {};
-
+        var partieswebsocket=null;
         // currently known domains (and profiles) as coming from domainwebsocket.
         // keys are domain names, values are list of profile names
         var knowndomains={};
-        
         
         /**
@@ -178,72 +101,6 @@
 		*/
         var partyprofiles=[];
-        
-        var cobpartyprofiles=[];
-
-	/** from http://fitzgeraldnick.com/2010/08/10/settimeout-patterns.html */
-    
-	function getAdvancedCobSettings() {
-		return document.getElementById('advancedCobSettings').checked;
-	}
-	
-	function advancedCobSet() {
-	    document.getElementById('advancedsettings').style.display=(getAdvancedCobSettings()?'':'none');
-	}
-	
-    function async (fn) {
-        setTimeout(fn, 1000);
-    }
-
-    function sometimeWhen (test, then) {
-        async(function () {
-            if ( test() ) {
-                then();
-            } else {
-                async(arguments.callee);
-            }
-        });
-    }
-
-    /**
-    Called when user changes the protocol */
-    function selectProtocol() {
-    	var visible=getSelectedProtocol() == "SHAOP";
-		
-    	document.getElementById("cobsetting").style.display=(visible ? 'block': 'none');
-	    var tbl = document.getElementById('selectedpartiestable');
-	    tbl.getElementsByTagName('col')[3].style.visibility=(visible?'':'collapse');
-	    tbl.getElementsByTagName('col')[4].style.visibility=(visible?'':'collapse');
-	    tbl.getElementsByTagName('col')[5].style.visibility=(visible?'':'collapse');
-	    
-    	var evaluatorvisible=getSelectedProtocol() == "MOPAC";
-    	document.getElementById("votingevaluator").style.display=(evaluatorvisible ? 'block': 'none');
-		
-    	var evaluator2visible=getSelectedProtocol() == "MOPAC2";
-    	document.getElementById("votingevaluator2").style.display=(evaluator2visible ? 'block': 'none');
-
-    	
-    	var profileselectorvisible=!isUsingFakeProfile();
-    	document.getElementById("profserverselector").style.display=(profileselectorvisible ? 'block': 'none');
-    	document.getElementById("profileselector").style.display=(profileselectorvisible ? 'block': 'none');
-    	if (getSelectedProtocol() == "Learn") {
-    		params = {"persistentstate":createUUID(), "negotiationdata":[ createUUID() ] };
-    		str=JSON.stringify(params);
-    		// remove outer brackets from the text in the box
-        	document.getElementById("parameters").value=str.substring(1, str.length-1);
-    		updateParameters();
-    	}
-    }
-
-    /**
-    @return true iff we need to use a fake profile.
-    */
-    function isUsingFakeProfile() {
-    	return  getSelectedProtocol() == "Learn";
-    }
-    
-    function isUsingCobParty() {
-    	return getSelectedProtocol() == "SHAOP";
-    }
-    
+
+ 	
 	/**
 	Refresh known domains using given profilesserver URL. 
@@ -255,7 +112,6 @@
     		domainwebsocket=null;
     	}
-		var url=new URL("http:"+document.getElementById("profilesserverurl").value);
-		// insert the liststream to the path
-        var target = "ws://"+url.host+url.pathname+"/websocket/liststream"+window.location.search+url.hash;
+		var url=document.getElementById("profilesserverurl").value;
+        var target = "ws://"+url+"/websocket/liststream";
         if ('WebSocket' in window) {
         	domainwebsocket = new WebSocket(target);
@@ -297,46 +153,4 @@
     	selectDomain();
     }
-    
-    /**
-    Connects to partieslist service on partiesserver and 
-    forwards reported parties into the updateParties() call.
-    */
-    class PartiesListWebsocket {
-    	constructor(target) {
-    		this.isopen=false
-    		var that=this
-            if ('WebSocket' in window) {
-            	this.partieswebsocket = new WebSocket(target);
-            } else if ('MozWebSocket' in window) {
-            	this.partieswebsocket = new MozWebSocket(target);
-            } else {
-                alert('WebSocket is not supported by this browser. Please use a newer browser');
-                return;
-            }
-            this.partieswebsocket.onopen = function () {
-            	console.log("new websocket conn made")
-            	that.isopen=true
-            };
-            this.partieswebsocket.onmessage = function (event) {
-            	console.log("new parties data came in")
-            	updateParties(JSON.parse(event.data));
-            };
-            this.partieswebsocket.onclose = function (event) {
-                if (that.isopen) {
-                    alert('Info: Server closed connection. Code: ' + event.code + 
-                    		(event.reason == "" ? "" : ", Reason: " + event.reason));
-                	that.isopen=false;
-                	updateParties({});
-                }
-            };
-    	}
-    	close() {
-    		if (this.isopen)
-    			console.log("closing parties listener")
-	    		this.isopen=false;
-				this.partieswebsocket.close()
-    	}
-    }
-    
 	/**
 	Refresh known parties using given partiesserver URL. 
@@ -344,10 +158,30 @@
 	*/
     function connectParties() {
-    	if (partieslistlistener!=null) {
-    		partieslistlistener.close();
+    	if (partieswebsocket!=null) {
+    		partieswebsocket.close();
+    		partieswebsocket=null;
     	}
 		var url=document.getElementById("partiesserverurl").value;
         var target = "ws://"+url+"/available";
-        partieslistlistener = new PartiesListWebsocket(target)
+        if ('WebSocket' in window) {
+        	partieswebsocket = new WebSocket(target);
+        } else if ('MozWebSocket' in window) {
+        	partieswebsocket = new MozWebSocket(target);
+        } else {
+            alert('WebSocket is not supported by this browser. Please use a newer browser');
+            return;
+        }
+        partieswebsocket.onopen = function () {
+        	// whatever.
+        };
+        partieswebsocket.onmessage = function (event) {
+        	updateParties(JSON.parse(event.data));
+        };
+        partieswebsocket.onclose = function (event) {
+            alert('Info: Server closed connection. Code: ' + event.code + 
+            		(event.reason == "" ? "" : ", Reason: " + event.reason));
+            partieswebsocket=null;
+        	updateParties({});
+        };
     }
 
@@ -356,61 +190,23 @@
 	 refresh table: copy all parties elements in there.
 	 Typically parties is something like
-	 [{"uri":"http:130.161.180.1:8080/partiesserver/run/randomparty-2.1.6",
+	 [{"uri":"http:130.161.180.1:8080/partiesserver/run/randomparty-1.0.0",
 		 "capabilities":{"protocols":["SAOP"]},
 		 "description":"places random bids until it can accept an offer with utility >0.6",
-		 "id":"randomparty-2.1.6",
+		 "id":"randomparty-1.0.0",
 		 "partyClass":"geniusweb.exampleparties.randomparty.RandomParty"},
 		 		 ...]
 	 */
 	function updateParties(parties) {
-		 console.log("new parties set to "+parties)
-		 updatePartiesCombobox(parties, document.getElementById("partyselection"),['SAOP','AMOP','SHAOP','MOPAC', 'MOPAC2']);
-		 updatePartiesCombobox(parties, document.getElementById("cobpartyselection"),['COB']);
-	}
-    
-    /**
-    @param parties a list of parties r(as received from the server)
-    @param combobox a combobox element to put the party URLs in
-    @param behaviours a list of behaviours for the parties. Only these are put in the combobox.
-    */
-    function updatePartiesCombobox(parties, combobox, behaviours) {
+		var combobox = document.getElementById("partyselection");
 		combobox.options.length=0;
-    	for (var p in parties) {
-    		var party = parties[p];
-    		if (intersect(party.capabilities.behaviours, behaviours).length==0)  
-    			continue;
+    	for (var party in parties) {
             var option = document.createElement('option');
-            option.text = option.value = party.uri;
+            option.text = option.value = parties[party].uri;
             combobox.add(option, 0);
     	}
-
-    }
-
-    /**
-    @param a a list
-    @param b another list
-    @return intersection of a and b
-    */
-    function intersect(a, b) {
-        var t;
-        if (b.length > a.length) t = b, b = a, a = t; // indexOf to loop over shorter
-        return a.filter(function (e) {
-            return b.indexOf(e) > -1;
-        });
-    }
-
-
-    /**
-    updates parameters field to match the given text.
-    */
-	function updateParameters() {
-		var text="{"+document.getElementById("parameters").value+"}";
-    	try {
-			parameters=JSON.parse(text);
-    	} catch(e) {
-    		alert("Parameters can not be parsed. "+e);
-    		return;
-    	}
-	}
+	}
+    
+
+
 
 	/**
@@ -425,16 +221,11 @@
 		var domain = domaincombobox.options[domaincombobox.selectedIndex].value;
 		
-		updateProfileComboBox(document.getElementById("profileselection"), knowndomains[domain]);
-		updateProfileComboBox(document.getElementById("cobprofileselection"), knowndomains[domain]);
-	}
-	
-	function updateProfileComboBox(profilecombo, options) {
+		var profilecombo = document.getElementById("profileselection");
 		profilecombo.options.length=0;
-		for (var profile in options) {
+		for (var profile in knowndomains[domain]) {
             var option = document.createElement('option');
-            option.text = option.value = options[profile];
+            option.text = option.value = knowndomains[domain][profile];
             profilecombo.add(option, 0);
 		}
-
 	}
 	
@@ -443,76 +234,22 @@
 	*/
 	function addParty() {
-		addNormalParty();
-		if (isUsingCobParty()) {
-			addCobParty();
-		}
-		updatePartyProfileTable(); // what, MVC?
-	}
-	
-	function addNormalParty() {
 		var partycombo = document.getElementById("partyselection");
 		var profilecombo = document.getElementById("profileselection");
-		var filteroptions = document.getElementById("filter").value;
-		if (filteroptions!="") {
-			filteroptions="?"+filteroptions;
-		}
-		
-		var selectedprofile;
-		if (isUsingFakeProfile()) {
-			selectedprofile="not://valid";
-		} else {
-			if (partycombo.options.length==0) {
-				alert("Please set partier server and select a party");
-				return;
-			}
-			if (profilecombo.options.length==0) {
-				alert("Please set domain/profile server and select a domain and a profile");
-				return;
-			}
-			selectedprofile=profilecombo.options[profilecombo.selectedIndex].value +filteroptions;
-		}
-		
+		
+		if (partycombo.options.length==0) {
+			alert("Please set partier server and select a party");
+			return;
+		}
+		if (profilecombo.options.length==0) {
+			alert("Please set domain/profile server and select a domain and a profile");
+			return;
+		}
 		var newpartyprof = {};
-		newpartyprof["party"]={"partyref":partycombo.options[partycombo.selectedIndex].value , 
-				"parameters":parameters };
-		newpartyprof["profile"]=selectedprofile;
+		newpartyprof["party"]=partycombo.options[partycombo.selectedIndex].value;
+		newpartyprof["profile"]=profilecombo.options[profilecombo.selectedIndex].value;
 		
 		partyprofiles.push(newpartyprof)
-	}
-	
-	
-	function addCobParty() {
-		// we assume a sensible default has been loaded into the combo and set,
-		// regardless it being invisible
-		var partycombo = document.getElementById("cobpartyselection");
-		if (partycombo.options.length==0) {
-			alert("Please set cpb partier server and select a party");
-			return;
-		}
-
-		var newpartyprof = {};
-		if (getAdvancedCobSettings()) {
-			var profilecombo = document.getElementById("cobprofileselection");
-			var filteroptions = document.getElementById("cobfilter").value;
-
-			if (profilecombo.options.length==0) {
-				alert("Please set a cob profile");
-				return;
-			}
-			if (filteroptions!="") {
-				filteroptions="?"+filteroptions;
-			}
-			newpartyprof["party"]={"partyref":partycombo.options[partycombo.selectedIndex].value , 
-					"parameters":parameters };
-			newpartyprof["profile"]=profilecombo.options[profilecombo.selectedIndex].value +filteroptions;
-		} else {
-			var profilecombo = document.getElementById("profileselection");
-			newpartyprof["party"]={"partyref":partycombo.options[partycombo.selectedIndex].value , 
-					"parameters":{} };
-			newpartyprof["profile"]=profilecombo.options[profilecombo.selectedIndex].value;
-		}
-		cobpartyprofiles.push(newpartyprof)
-	}
-
+		updatePartyProfileTable(); // what, MVC?
+	}
 	
 	/** updates the party and profiles table, to match the #partyprofiles list.	 	*/
@@ -524,28 +261,10 @@
 			var cell1 = row.insertCell(-1);
 			var cell2 = row.insertCell(-1);
-			var cell3 = row.insertCell(-1);
-
-			cell1.innerHTML = partyprofiles[pp]["party"]["partyref"];
-			// help browser breaking too large strings 
-			cell2.innerHTML = JSON.stringify(partyprofiles[pp]["party"]["parameters"]).replace(/,/g,", ");
-			cell2.setAttribute("style","overflow-wrap: anywhere;");
-			cell3.innerHTML = partyprofiles[pp]["profile"];
-
-			if (isUsingCobParty()) {
-				var cell4 = row.insertCell(-1);
-				var cell5 = row.insertCell(-1);
-				var cell6 = row.insertCell(-1);
-				cell4.innerHTML = cobpartyprofiles[pp]["party"]["partyref"];
-				cell5.innerHTML = JSON.stringify(cobpartyprofiles[pp]["party"]["parameters"]).replace(/,/g,", ");
-				cell5.setAttribute("style","overflow-wrap: anywhere;");
-				cell6.innerHTML = cobpartyprofiles[pp]["profile"];
-
-			}
-			
-		}
-
-	}
-
-	var x=1;
+			cell1.innerHTML = partyprofiles[pp]["party"];
+			cell2.innerHTML = partyprofiles[pp]["profile"];
+		}
+
+	}
+
 	/**
 	start the session as currently set on this page.
@@ -555,6 +274,6 @@
 	{"SAOPSettings":
 	  {"participants":[
-		    {"party":{"partyref":"http://party1","parameters":{}},"profile":"ws://profile1"},
-		    {"party":{"partyref",}"http://party2","parameters":{}},"profile":"ws://profile2"}],
+		    {"party":"http://party1","profile":"ws://profile1"},
+		    {"party":"http://party2","profile":"ws://profile2"}],
 		    "deadline":{"deadlinetime":{"durationms":100}}}}
 	
@@ -562,26 +281,19 @@
 	*/
 	function start() {
-		var minParties = getSelectedProtocol() == "Learn" ? 1: 2;
-		if (Object.keys(partyprofiles).length < minParties) {
-			alert("At least "+minParties+" parties are needed to run a "+getSelectedProtocol()+" session.");
+		if (Object.keys(partyprofiles).length <2) {
+			alert("At least 2 parties are needed to run a session.");
 			return;
 		}
 
 		// see https://www.w3schools.com/xml/dom_httprequest.asp
-  		document.getElementById("startbutton").disabled=true;
-		document.getElementById("started").setAttribute("style","");
-
-		var xmlHttp = new XMLHttpRequest();
+	    var xmlHttp = new XMLHttpRequest();
 	    xmlHttp.onreadystatechange = function() { 
 	        if (this.readyState == 4) {
 	        	if (this.status == 200) {
-	        		var logurl="log/"+this.responseText+".json";
-	        		document.getElementById("logref").href=logurl;
-	        		document.getElementById("plotref").href="plotlog.xhtml"+
-	        		combineQuery("?id="+this.responseText,window.location.search);
+	        		document.getElementById("startbutton").disabled=true;
+	        		document.getElementById("started").setAttribute("style","");
+	        		document.getElementById("logref").href="log/"+this.responseText+".json";
+	        		document.getElementById("plotref").href="plotlog.xhtml?id="+this.responseText;
 	        		
-	        		sometimeWhen(function() { return urlExists(logurl) },
-	        				function() { document.getElementById("results").setAttribute("style",""); });
-
 	        	}
 	        	else 
@@ -594,140 +306,24 @@
 	}
 
-
-
-	/**
-	@param query1 a query string like &p=q (part of URL)
-	@param query2 another query string 
-	@return the combined querystring of query1 and query2 
-	*/
-	function combineQuery(query1, query2) {
-		if (query1=="") return query2;
-		if (query2=="") return query1;
-		return query1+"&"+query2.substring(1);
-	}
-
-	
-	/**
-	@return true iff the URL exists.
-	*/
-	function urlExists(urlToFile) {
-		// Warning. Synchronous XMLHttpRequest on the main thread is 
-		// deprecated because of its detrimental effects to the end user’s
-		// experience. For more help http://xhr.spec.whatwg.org/
-	    var xhr = new XMLHttpRequest();
-	    xhr.open('HEAD', urlToFile, false);
-	    xhr.send();
-	     
-		return (xhr.status == "200") 
-	}
-	
-	function getSelectedProtocol() {
-		var protocolcombo = document.getElementById("selectedprotocol");
-		return protocolcombo.options[protocolcombo.selectedIndex].value;
-	}
+	
 	/**
 	@return a json request package for the run server
 	*/
 	function makeRequest() {
-		switch(getSelectedProtocol()) {
-		case "SHAOP":
-			return makeShaopRequest();
-		case"SAOP":
-		case "AMOP":
-		case "Learn":
-			return makeStdRequest(getSelectedProtocol()+"Settings");
-		case "MOPAC":
-			return makeMopacRequest();			
-		case "MOPAC2":
-			return makeMopac2Request();			
-		} 
-	}
-	
-	/**
-	@return a SAOP/AMOP request
-	The header contains 'SAOSettings' or 'AMOPSettings'
-	*/
-	function makeStdRequest(header) {
-		return JSON.stringify({[header]: standardHeader() });
-	}
-	
-	/**
-	* @ereturn MOPAC request. Almost standard but extra 'votingEvaluator'.
-	*/
-	function makeMopacRequest() {
-		var extended = standardHeader();
-		var combo = document.getElementById("selectedevaluator");
-		var evaluator = combo.options[combo.selectedIndex].value;
-		extended['votingevaluator'] = { [evaluator]: {} };
-		return JSON.stringify({"MOPACSettings": extended });
-	}
-
-	/**
-	* @ereturn MOPAC2 request. Almost standard but extra 'votingEvaluator'.
-	*/
-	function makeMopac2Request() {
-		var extended = standardHeader();
-		var combo = document.getElementById("selectedevaluator2");
-		var evaluator = combo.options[combo.selectedIndex].value;
-		extended['votingevaluator'] = { [evaluator]: {} };
-		return JSON.stringify({"MOPAC2Settings": extended });
-	}
-	
-	/**
-	@return standard header with participants and deadline 
-	*/
-	function standardHeader() {
 		var deadline={};
 		var value = document.getElementById("deadlinevalue").value;
 		var dtypecombo  = document.getElementById("deadlinetype");
 		if (dtypecombo.options[dtypecombo.selectedIndex].value=="TIME") {
-			deadline["DeadlineTime"] = { "durationms": 1000*value};
+			deadline["deadlinetime"] = { "durationms": 1000*value};
 		} else {
 			// ROUNDS
-			deadline["DeadlineRounds"] = {"rounds": value, "durationms":10000};
-		}
-		var parties=[];
-		for (let i=0; i< partyprofiles.length; i++) {
-			parties.push( {"TeamInfo":{"parties": [ partyprofiles[i] ] }} );
-		}
-		return  { "participants": parties, "deadline":deadline }
-	}
-	
-	
-
-	/**
-	@return a SHAOP request
-	*/
-	function makeShaopRequest() {
-		var deadline={};
-		var value = document.getElementById("deadlinevalue").value;
-		var dtypecombo  = document.getElementById("deadlinetype");
-		if (dtypecombo.options[dtypecombo.selectedIndex].value=="TIME") {
-			deadline["DeadlineTime"] = { "durationms": 1000*value};
-		} else {
-			// ROUNDS
-			deadline["DeadlineRounds"] = {"rounds": value, "durationms":10000};
-		}
-		
-		var parties=[];
-		for (let i=0; i< partyprofiles.length; i++) {
-			var team=[ partyprofiles[i] , cobpartyprofiles[i]  ];
-			parties.push( {"TeamInfo":{"parties":  team }} );
-		}
-		return JSON.stringify({"SHAOPSettings": { "participants": parties, "deadline":deadline }});
-	}
-
-	/**
-	@return a random UUID. 
-	Note − This should not be used in production as GUID or UUID 
-	generated by Math.Random() may not be unique.
-	*/
-	function createUUID() {
-		   return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
-		      var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8);
-		      return v.toString(16);
-		   });
-	}
-
+			deadline["deadlinerounds"] = {"rounds": value, "durationms":10000};
+		}
+		
+		
+		return JSON.stringify({"SAOPSettings": { "participants": partyprofiles, "deadline":deadline }});
+
+	}
+	
 	
 	/**
@@ -735,7 +331,4 @@
 	*/
 	function init() {
-		selectProtocol();
-		document.getElementById("partiesserverurl").value =window.location.hostname+":8080/partiesserver-2.1.6"
-		document.getElementById("profilesserverurl").value =window.location.hostname+":8080/profilesserver-2.1.6"
 		connectDomain();
 		connectParties();
@@ -745,11 +338,4 @@
 
 
-
-
-
-
-
-
-
 </script>
 
Index: src/main/webapp/newtournament.xhtml
===================================================================
--- src/main/webapp/newtournament.xhtml	(revision 45)
+++ src/main/webapp/newtournament.xhtml	(revision 1)
@@ -4,4 +4,5 @@
 <title>Profiles and Domains list</title>
 <link rel="stylesheet" type="text/css" href="style.css" />
+
 </head>
 <body onload="init()">
@@ -13,81 +14,55 @@
 	<br />
 
-
+	<select>
+		<option value="APP">All Permutations Tournament Protocol
+			(APP)</option>
+	</select>
+	<br />
+	<br />
+	<input type="number" id="partiespersession" name="tentacles" min="2" max="10" value="2"/>
+	Number of parties in each session
+	<br />
+
+	<input type="checkbox" id="reuseparties"/> Pick
+	parties with return when creating sessions
+	<br />
+
+	<br />
 	<div id="box" class="box">
-		<h3>Tournament global settings</h3>
-		<select id="tourprotocol" onchange="updateTournamentProt()">
-			<option value="AllPermutations">All Permutations Tournament Protocol
-				(APP)</option>
-			<option value="AllPermutationsLearn">APP with learning</option>
-		</select> Tournament protocol <br />
-		<div id="learntimebox">
-			<input type="number" id="learntime" name="learntime" min="1"
-				max="10000" value="30" /> Learning time (s)
-		</div>
-
-		<br /> <input type="number" id="ntournaments" min="1" max="1000000"
-			value="1" /> Number of times to repeat the entire tournament <br />
-
-		<br /> <input type="number" id="teamspersession" min="2" max="10"
-			value="2" /> Number of teams in each session <br /> <input
-			type="checkbox" id="reuseteams" /> Pick teams with return when
-		creating sessions <br />
+		Session Protocol settings
+		<br />
+		Session Protocol: <select>
+			<option value="SAOP">SAOP</option>
+		</select>
+		<br />
+		Deadline: <input type="number" id="deadlinevalue" name="deadline"
+			min="1" max="10000" value="10" /> <select id="deadlinetype">
+			<option value="TIME">seconds</option>
+			<option value="ROUNDS">rounds</option>
+		</select>
 	</div>
-
-	<br />
+	<br />
+
 	<div id="box" class="box">
-		Session Protocol settings <br /> Session Protocol: <select
-			id="protocolselection" onchange="selectSessionProtocol()">
-			<option value="SAOP">SAOP</option>
-			<option value="MOPAC">MOPAC</option>
-			<option value="MOPAC2">MOPAC2</option>
-			<option value="AMOP">AMOP</option>
-			<option value="SHAOP">SHAOP</option>
-		</select>
-
-		<div id="votingevaluator">
-			<br /> Voting Evaluator: <select id="selectedevaluator">
-				<option value="LargestAgreement">Largest Agreement</option>
-				<option value="LargestAgreementsLoop">Largest Agreements
-					and Repeat</option>
-			</select>
-		</div>
-
-		<div id="votingevaluator2">
-			<br /> Voting Evaluator: <select id="selectedevaluator2">
-				<option value="LargestAgreementWithValue">Largest Agreement
-					with Value</option>
-			</select>
-		</div>
-
-		<br /> Deadline: <input type="number" id="deadlinevalue"
-			name="deadline" min="1" max="10000" value="10" /> <select
-			id="deadlinetype">
-			<option value="ROUNDS">rounds</option>
-			<option value="TIME">seconds</option>
-		</select>
-	</div>
-	<br />
-
-	<div id="box" class="box">
-		<h3>Profiles</h3>
+		<br />
 		Domain/Profile Server: <input type="url" name="url"
-			id="profilesserverurl" value="localhost:8080/profilesserver-1.3.1"
-			pattern=".*:[0-9]+/profilesserver.*" size="30"
-			onchange="connectDomain()"> </input> <br /> Domain: <select
-			id="domainselection" onchange="selectDomain()">
+			id="profilesserverurl" value="localhost:8080/profilesserver-1.0.0"
+			pattern=".*:[0-9]+/profilesserver" size="30"
+			onchange="connectDomain()"> </input>
+		<br />
+		Domain: <select id="domainselection" onclick="selectDomain()">
 			<!-- <option>Waiting for profiles server</option> -->
-		</select> <br /> <br />
-		<!--  first selected profile -->
-		Profile: <select id="profileselection1">
-		</select> Filter: <input type="text" id="filter1" value="" maxlength="40" /> <br />
-		<!--  second selected profile -->
-		<div class="onlySHAOP">
-			COB: <select id="profileselection2">
-			</select> Filter: <input type="text" id="filter2" value="" maxlength="40" />
-			<br />
-		</div>
-		<button onclick="addProfiles()">Add</button>
-		<br /> <br />
+		</select>
+
+		<br />
+		<br />
+		<button onclick="addProfile()">Add</button>
+		Profile: <select id="profileselection">
+			<!-- <option>Waiting for partiesserver</option> -->
+		</select>
+		<br />
+
+		<br />
+
 		<table id="profiles">
 			<thead>
@@ -104,40 +79,23 @@
 	<br />
 	<div id="box" class="box">
-		<h3>Teams</h3>
-		<br /> Parties Server: <input type="url" name="url"
-			id="partiesserverurl" value="localhost:8080/partiesserver-1.3.1"
-			pattern=".*:[0-9]+/partiesserver.*" size="30"
-			onchange="connectParties()"> </input> <br /> <br />
-		<!-- party  1 selection -->
+		<br />
+		Parties Server: <input type="url" name="url" id="partiesserverurl"
+			value="localhost:8080/partiesserver-1.0.0"
+			pattern=".*:[0-9]+/partiesserver" size="30"
+			onchange="connectParties()"> </input>
+		<br />
+		<br />
+		<button onclick="addParty()">Add</button>
 		Party: <select id="partyselection">
-		</select> <br /> Parameters: {
-		<textarea id="parameters" rows="2" cols="70"
-			onchange="getParameters('parameters')" value="" />
-		} <br />
-		<!-- party 2 selection -->
-		<div class="onlySHAOP">
-			COB: <select id="partyselection2">
-			</select> <br /> Parameters: {
-			<textarea id="parameters2" rows="2" cols="70"
-				onchange="getParameters('parameters2')" value="" />
-			}
-		</div>
-		<br />
-
-
-		<button onclick="addTeam()">Add</button>
-
-		<br /> <br />
+			<!-- <option>Waiting for partiesserver</option> -->
+		</select>
+
+		<br />
 		<table>
 			<thead>
-				<th align="left">Party</th>
-				<th align="left">Parameters</th>
-				<th align="left"><div class="onlySHAOP">Compare Bids
-						Party</div></th>
-				<th align="left"><div class="onlySHAOP">Compare Bids
-						Parameters</div></th>
+				<th align="left">Selected Parties</th>
 			</thead>
-			<tbody id="teamList">
-				<tr id="FIXME REMOVE">
+			<tbody id="partiesList">
+				<tr id="partiesList">
 				</tr>
 
@@ -148,10 +106,8 @@
 	<br />
 	<form>
-		<input id="startbutton" type="button" value="Start Tournament"
-			onclick="start()" />
+		<input id="startbutton" type="button" value="Start Tournament" onclick="start()" />
 	</form>
-	<div id="started" style="visibility: hidden">
-		Your tournament started. Click <a href="" id="logref">here</a> to view
-		the log file. <br /> <a href="" id="plotref">show results table.</a>.
+	<div id="started" style="visibility:hidden">
+	Your tournament started. Click <a href="" id="logref">here</a> to view the log file.
 	</div>
 
@@ -159,20 +115,4 @@
 
 <script type="application/javascript">
-	
-	
-	
-	
-	
-	
-	
-	
-	
-	
-	
-	
-	
-	
-	
-	
 	
 	
@@ -200,71 +140,13 @@
         
         var domainwebsocket = null;
-        var partieslistlistener=null;
+        var partieswebsocket=null;
         // currently known domains (and profiles) as coming from domainwebsocket.
         // keys are domain names, values are list of profile names
         var knowndomains={};
         
-        var teamslist=[];
+        var parties=[];
         var profiles=[]
 
-    /**
-    The tournament protocol was changed.
-    */
-    function updateTournamentProt() {
-       	updateParameters();
-        var tourprot = document.getElementById("tourprotocol").value;
-       	document.getElementById("learntimebox").style.display=(tourprot=="AllPermutationsLearn" ? 'block': 'none');
-       	
-    }
-        
-    /**
-    Parameters are needed if protocol is APP.
-    */
-    function updateParameters() {
-        var tourprot = document.getElementById("tourprotocol").value;
-   		if (tourprot=='AllPermutationsLearn') {
-    		var params = {"persistentstate":createUUID() };
-    		var str=JSON.stringify(params);
-    		// remove outer brackets from the text in the box
-        	document.getElementById("parameters").value=str.substring(1, str.length-1);
-   		}
-    }
-        
-        
- 	/**
- 	called when user changes the protocol.
- 	With SHAOP we show COB selectors and COB columns in the tables.
-    */
-    function selectSessionProtocol() {
-            const protocol = document.getElementById("protocolselection").value;
-        	setStyleSheet('.onlySHAOP','{ display: '+(protocol=="SHAOP"? '?':'none')+'; }')
-        	
-        	document.getElementById("votingevaluator").style.display=(protocol=="MOPAC" ? 'block': 'none');
-        	
-        	document.getElementById("votingevaluator2").style.display=(protocol=="MOPAC2" ? 'block': 'none');
-
-    }
-    
-    /**
-    Change style sheet to new value. Nothing happens if there is
-    no style sheet with given classname.
-    @param classname the name of the style definition, eg '.onlySHAOP'
-    @param style the new style for the class. eg  '{ max-width: 100px; }'
-    */
-    function setStyleSheet(classname, style) {
-    	for (var cssRulenr=0; cssRulenr< document.styleSheets.length; cssRulenr++) {
-    		var cssRule = document.styleSheets[cssRulenr];
-    		// there may be multple CSS definitions, check each.
-        	var rules = cssRule.cssRules;
-        	for (var rulenr=0;  rulenr<rules.length; rulenr++) {
-        		var rule = rules[rulenr];
-        		if ('selectorText' in rule && rule.selectorText==classname) {
-        			cssRule.deleteRule(rulenr);
-        			cssRule.insertRule(classname+ " "+style, rulenr);
-        		}
-        	}
-    	}
-    }
-        
+ 	
 	/**
 	Refresh known domains using given profilesserver URL. 
@@ -317,102 +199,50 @@
     	selectDomain();
     }
-        
-	/**
-	Connects to partieslist service on partiesserver and 
-	forwards reported parties into the updateParties() call.
-	*/
-	class PartiesListWebsocket {
-		constructor(target) {
-			this.isopen=false
-			var that=this
-	        if ('WebSocket' in window) {
-	        	this.partieswebsocket = new WebSocket(target);
-	        } else if ('MozWebSocket' in window) {
-	        	this.partieswebsocket = new MozWebSocket(target);
-	        } else {
-	            alert('WebSocket is not supported by this browser. Please use a newer browser');
-	            return;
-	        }
-	        this.partieswebsocket.onopen = function () {
-	        	console.log("new websocket conn made")
-	        	that.isopen=true
-	        };
-	        this.partieswebsocket.onmessage = function (event) {
-	        	console.log("new parties data came in")
-	        	updateParties(JSON.parse(event.data));
-	        };
-	        this.partieswebsocket.onclose = function (event) {
-	            if (that.isopen) {
-	                alert('Info: Server closed connection. Code: ' + event.code + 
-	                		(event.reason == "" ? "" : ", Reason: " + event.reason));
-	            	that.isopen=false;
-	            	updateParties({});
-	            }
-	        };
-		}
-		close() {
-			if (this.isopen)
-				console.log("closing parties listener")
-	 		this.isopen=false;
-			this.partieswebsocket.close()
-		}
-	}   
-	
-   	/**
-   	Refresh known parties using given partiesserver URL. 
-   	Called when user enters URL for parties server.
-   	*/
-       function connectParties() {
-       	if (partieslistlistener!=null) {
-       		partieslistlistener.close();
-       	}
-   		var url=document.getElementById("partiesserverurl").value;
-           var target = "ws://"+url+"/available";
-           partieslistlistener = new PartiesListWebsocket(target)
-       }
-
-
-	/**
-	@param parties a new list of parties available on the parties server
-	*/
+	/**
+	Refresh known parties using given partiesserver URL. 
+	Called when user enters URL for parties server.
+	*/
+    function connectParties() {
+    	if (partieswebsocket!=null) {
+    		partieswebsocket.close();
+    		partieswebsocket=null;
+    	}
+		var url=document.getElementById("partiesserverurl").value;
+        var target = "ws://"+url+"/available";
+        if ('WebSocket' in window) {
+        	partieswebsocket = new WebSocket(target);
+        } else if ('MozWebSocket' in window) {
+        	partieswebsocket = new MozWebSocket(target);
+        } else {
+            alert('WebSocket is not supported by this browser. Please use a newer browser');
+            return;
+        }
+        partieswebsocket.onopen = function () {
+        	// whatever.
+        };
+        partieswebsocket.onmessage = function (event) {
+        	updateParties(JSON.parse(event.data));
+        };
+        partieswebsocket.onclose = function (event) {
+            alert('Info: Server closed connection. Code: ' + event.code + 
+            		(event.reason == "" ? "" : ", Reason: " + event.reason));
+            partieswebsocket=null;
+        	updateParties({});
+        };
+    }
+
+	
 	function updateParties(parties) {
-		updatePartyCombo(document.getElementById("partyselection"), parties, 'shaop');
-		updatePartyCombo(document.getElementById("partyselection2"), parties, 'comparebids');
-	}
-	
-	/**
-	put the available parties in the party comboboxes.
-	@param combobox a document <select> element 
-	@param parties a dict of party information coming from the partiesserver
-	@param select a string that may be a substring of the part names. 
-	@return the combobox value that contains 'select' as substring, or undefined
-	*/
-	function updatePartyCombo(combobox, parties, select) {
-		var selection=undefined;
+		var combobox = document.getElementById("partyselection");
 		combobox.options.length=0;
     	for (var party in parties) {
             var option = document.createElement('option');
             option.text = option.value = parties[party].uri;
-            if (option.text.includes(select) ) option.selected=true;
             combobox.add(option, 0);
     	}
-    	return selection;
 	}
     
 
-    
-    /**
-    @param elementname eg "parameters", the ID of the element in the <input> element 
-    @return the JSON parsed object, or {} if empty or parsing fails.
-    */
-    function getParameters(elementname) {
-		var text="{"+document.getElementById(elementname).value+"}";
-    	try {
-			return JSON.parse(text);
-    	} catch(e) {
-    		alert("Parameters can not be parsed. Make sure you write correct JSON here."+e);
-    	}
-		return {};
-    }
+
 
 	/**
@@ -426,35 +256,19 @@
 		if (domaincombobox.options.length==0) return; // fixme clean profiles options?
 		var domain = domaincombobox.options[domaincombobox.selectedIndex].value;
-		updateProfiles(knowndomains[domain])
-	}
-	
-	function updateProfiles(profileslist) {
-		updateProfileCombo(document.getElementById("profileselection1"),profileslist);
-		updateProfileCombo(document.getElementById("profileselection2"),profileslist);
-	}
-	
-	/**
-	@param combobox the <select> element that should be udpated
-	@param profileslist the list of profile names to be put in the combbo
-	*/
-	function updateProfileCombo(profilecombo, profileslist) {
+		
+		var profilecombo = document.getElementById("profileselection");
 		profilecombo.options.length=0;
-		for (var profile in profileslist) {
+		for (var profile in knowndomains[domain]) {
             var option = document.createElement('option');
-            option.text = option.value = profileslist[profile];
+            option.text = option.value = knowndomains[domain][profile];
             profilecombo.add(option, 0);
 		}
 	}
 	
-	
 	/**
 	Called when user clicks "Add" 
 	*/
-	function addTeam() {
+	function addParty() {
 		var partycombo = document.getElementById("partyselection");
-		var partycombo2 = document.getElementById("partyselection2");
-		var param = getParameters("parameters");
-		var param2 = getParameters("parameters2");
-		
 		
 		if (partycombo.options.length==0) {
@@ -462,59 +276,31 @@
 			return;
 		}
-		var team = [];
-		team.push({"partyref":partycombo.options[partycombo.selectedIndex].value, "parameters":param});
-		team.push({"partyref":partycombo2.options[partycombo2.selectedIndex].value, "parameters":param2});
-
-		teamslist.push(team);
-		updateTeamsTable();
-		updateParameters(); // generate new UUID for next party
-	}
-	
-	/** updates the teams table, to match the #partyprofiles list.	 	*/
-	function updateTeamsTable() {
-		var table = document.getElementById("teamList");
+		parties.push(partycombo.options[partycombo.selectedIndex].value)
+		updatePartyTable();
+	}
+	
+	/** updates the party table, to match the #partyprofiles list.	 	*/
+	function updatePartyTable() {
+		var table = document.getElementById("partiesList");
 		table.innerHTML = ""; // clear table
-		for ( const team of teamslist) {
+		for ( var party in parties) {
 			var row = table.insertRow(-1);
-			for (const col in team) {
-				const party = team[col]
-				var cell1 = row.insertCell(-1);
-				var cell2 = row.insertCell(-1);
-				cell1.innerHTML = party["partyref"];
-				cell2.innerHTML = JSON.stringify(party["parameters"]).replace(/,/g,", ");;
-				cell2.setAttribute("style","overflow-wrap: anywhere;");
-				if (col>0) {
-					cell1.className = cell2.className = "onlySHAOP";
-				}
-
-			}
-		}
-		
-		selectSessionProtocol(); // HACK we need to KEEP onlySHAOP elements hidden
-	}
-
-	/**
-	@param profilenr the profile nr, 1 for normal , 2 for cob profile
-	*/
-	function getProfile(profilenr) {
-		var profilecombo = document.getElementById("profileselection"+profilenr);
+			var cell1 = row.insertCell(-1);
+			cell1.innerHTML = parties[party];
+		}
+
+	}
+
+	/**
+	Called when user clicks "Add" to add a profile
+	*/
+	function addProfile() {
+		var profilecombo = document.getElementById("profileselection");
+		
 		if (profilecombo.options.length==0) {
 			alert("Please set domain/profile server and select a domain and a profile");
-			throw "blabla";
-		}
-		var filteroptions = document.getElementById("filter"+profilenr).value;
-		if (filteroptions!="") {
-			filteroptions="?"+filteroptions;
-		}
-
-		//return profilecombo.options[profilecombo.selectedIndex].value + filteroptions
-		return profilecombo.value + filteroptions
-	}
-	
-	/**
-	Called when user clicks "Add" to add a profile set
-	*/
-	function addProfiles() {
-		profiles.push([getProfile(1), getProfile(2)]);
+			return;
+		}
+		profiles.push(profilecombo.options[profilecombo.selectedIndex].value)
 		updateProfileTable(); // what, MVC?
 	}
@@ -524,20 +310,17 @@
 		var table = document.getElementById("profilesList");
 		table.innerHTML = ""; // clear table
-		for ( const profileset of profiles) {
+		for ( var profile in profiles) {
 			var row = table.insertRow(-1);
-			for (var col in profileset) {
-				var profile = profileset[col];
-				var cell1 = row.insertCell(-1);
-				cell1.innerHTML = profile;
-				if (col>0) cell1.className = "onlySHAOP"
-			}			
-		}
-		selectSessionProtocol(); // HACK we need to KEEP onlySHAOP elements hidden
+			var cell1 = row.insertCell(-1);
+			cell1.innerHTML = profiles[profile];
+		}
+
 	}
 	
 	/**
 	start the tournament as currently set on this page.
-	We need to send a TournamentSettings object to the server, which typically looks like this with SAOP
-	<code>
+	We need to send a TournamentSettings object to the server, which typically looks like this
+	but is protocol dependent (currently we do SAOP)
+	
 	{"AllPermutationsSettings":{"parties":["party1","party2"],
 		"profiles":["profile1","profile2","profile3"],
@@ -545,32 +328,17 @@
 		"partiesPerSession":2,
 		"sessionsettings":{"SAOPSettings":{"participants":[],"deadline":{"deadlinetime":{"durationms":10}}}}}}
-	</code>
+	
 	participants are already in the global partyprofiles dictionary
-	
-	With SHAOP, it looks like this
-	<code>
-	{
-		"AllPermutationsSettings": {
-			"parties": [ { "partyref": "classpath:geniusweb.exampleparties.simpleshaop.ShaopParty", "parameters": { } },
-				{ "partyref": "classpath:geniusweb.exampleparties.randomparty.RandomParty",	"parameters": {	}}
-			],
-			"reuseParties": false,
-			"profiles": [ 	"prof1?partial=10", "prof2?partial=15"],
-			"partiesPerSession": 2,
-			"sessionsettings": { 	"SHAOPSettings": {
-					"participants": [ ], 
-					"deadline": { "deadlinerounds": {	"rounds": 10, "durationms": 10000	} } } } } }
-	</code>
 	*/
 	function start() {
-		const npersession = document.getElementById("teamspersession").value;
-		
-		if (teamslist.length < npersession) {
-			alert("At least "+npersession+" teams are needed.");
+		var npersession = document.getElementById("partiespersession").value;
+		
+		if (parties.length < npersession || npersession <2) {
+			alert("At least "+npersession+" parties are needed.");
 			return;
 		}
 		
 		if (profiles.length < npersession) {
-			alert("At least "+npersession+" profilesets are needed.");
+			alert("At least "+npersession+" profiles are needed.");
 			return;
 		}
@@ -584,5 +352,4 @@
 	        		document.getElementById("started").setAttribute("style","");
     	    		document.getElementById("logref").href="log/"+this.responseText+".json";
-	        		document.getElementById("plotref").href="utilstable.xhtml?"+this.responseText;
 	        	} else 
 	        		alert("request failed:"+this.statusText);
@@ -594,100 +361,28 @@
 	
 	/**
-	@return a json request package containing a AllPermutationsSettings.
-	It assumes that global vars parties and sessionSettings have been set properly.
+	@return a json request package containing a AllPermutationsSettings
 	*/
 	function makeRequest() {
-		const npersession = document.getElementById("teamspersession").value;
-		const ntournaments = document.getElementById("ntournaments").value;
-		const reuseTeams  = document.getElementById("reuseteams").checked;
-		const protocolcombobox = document.getElementById("protocolselection");
-		const protocol = protocolcombobox.options[protocolcombobox.selectedIndex].value;
-		const header=protocol+"Settings";
-
 		var deadline={};
-		const value = document.getElementById("deadlinevalue").value;
-		const dtypecombo  = document.getElementById("deadlinetype");
+		var value = document.getElementById("deadlinevalue").value;
+		var dtypecombo  = document.getElementById("deadlinetype");
 		if (dtypecombo.options[dtypecombo.selectedIndex].value=="TIME") {
-			deadline["DeadlineTime"] = { "durationms": 1000*value};
+			deadline["deadlinetime"] = { "durationms": 1000*value};
 		} else {
 			// ROUNDS
-			deadline["DeadlineRounds"] = {"rounds": value, "durationms": 10000};
-		}
-		
-		// create S(H)AOPSettings. [header] is a weird ECMA script workaround for javascript issue.
-		var settingvalues={"participants":[],"deadline":deadline};
-		if (protocol=="MOPAC") {
-			var combo = document.getElementById("selectedevaluator");
-			var evaluator = combo.options[combo.selectedIndex].value;
-			settingvalues['votingevaluator'] = { [evaluator]: {} };
-		} 
-		if (protocol=="MOPAC2") {
-			var combo = document.getElementById("selectedevaluator2");
-			var evaluator = combo.options[combo.selectedIndex].value;
-			settingvalues['votingevaluator'] = { [evaluator]: {} };
-		} 
-
-		const sessionSettings = { [header]:settingvalues};
-
-		var teamsFull = [];
-		for (const team of teamslist) {
-			if (protocol=="SHAOP") 
-				teamsFull.push({"Team":team});
-			else
-				teamsFull.push({"Team":[team[0]]}); // most protocols have just 1 member per team
-		}
-		var profilesFull = [] ;
-		for (const profileset of profiles) {
-			if (protocol=="SHAOP") // only first member of team is used.
-				profilesFull.push({"ProfileList":profileset});
-			else
-				profilesFull.push({"ProfileList":[profileset[0]]});
-		}
-
-   		var settings={"teams":teamsFull,"profileslists":profilesFull,
-   				"reuseTeams":reuseTeams,"teamsPerSession":npersession,
-   				"sessionsettings":sessionSettings,
-   				"numberTournaments":ntournaments};
-
-		// add the Learn settings if needed
-        var tourprot = document.getElementById("tourprotocol").value;
-        var learntime = 1000*document.getElementById("learntime").value;
-   		if (tourprot=='AllPermutationsLearn') {
-			settings["learnSettings"]={
-				"LearnSettings":{
-					"participants":[], 
-					"deadline": {"deadlinetime": { "durationms": learntime }}
-				}
-			} ;
-   		}
-   		
-   		var mainheader=tourprot+"Settings";
-		return JSON.stringify({[mainheader]:settings});
-	}
-		
-		
-	/**
-	@return a random UUID. 
-	Note − This should not be used in production as GUID or UUID 
-	generated by Math.Random() may not be unique.
-	*/
-	function createUUID() {
-		   return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
-		      var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8);
-		      return v.toString(16);
-		   });
-	}
-
+			deadline["deadlinerounds"] = {"rounds": value, "durationms": 10000};
+		}
+		
+		var reuseParties  = "on"== document.getElementById("reuseparties").value;
+		var sessionSettings = {"SAOPSettings":{"participants":[],"deadline":deadline}};
+		return JSON.stringify({"AllPermutationsSettings":{"parties":parties,"profiles":profiles,"reuseParties":reuseParties,"partiesPerSession":2,"sessionsettings":sessionSettings}});
+	}
+	
 	/**
 	Initialize the page after html is loaded. 
 	*/
 	function init() {
-		document.getElementById("partiesserverurl").value =window.location.hostname+":8080/partiesserver-2.1.6";
-		document.getElementById("profilesserverurl").value =window.location.hostname+":8080/profilesserver-2.1.6";
-
-		selectSessionProtocol();
 		connectDomain();
 		connectParties();
-		updateTournamentProt();
 	}
 
@@ -698,20 +393,4 @@
 
 
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
 </script>
 
Index: src/main/webapp/plotlog.xhtml
===================================================================
--- src/main/webapp/plotlog.xhtml	(revision 45)
+++ src/main/webapp/plotlog.xhtml	(revision 1)
@@ -4,5 +4,4 @@
 <title>Plot log results</title>
 <script src="Chart.min_2.8.0.js"></script>
-<script src="utils.js"></script>
 </head>
 <style>
@@ -24,15 +23,7 @@
 	<div id="progress">Waiting for log file name</div>
 	<br />
-	
-	<div>Graph shows utilities of bids in offers and accepts.
-	Points in the graph indicate the party that placed the offer. 
-	Plotted utilities do not include possible
-		elicitation costs.</div>
-	<div style="width: 100%;">
+	<div style="width: 75%;">
 		<canvas id="canvas"></canvas>
 	</div>
-
-	Agreement:
-	<div id="agreement" style="display: inline;">?</div>
 </body>
 
@@ -44,7 +35,4 @@
 	
 	
-	
-	
-	
 
 	
@@ -60,10 +48,8 @@
 
         function connect() {
-        	var query = new URLSearchParams(location.search);
-        	var id=query.get('id');
-            if (id==undefined) {
-            	alert("missing ?id=<logfile> in URL"); 
-            	return;
-           	}
+        	
+        	var id=document.location.search;
+            id = location.search.split('id=')[1]
+            if (id==undefined) return;
             
             // load the log file with given id
@@ -90,76 +76,34 @@
         */
         function processLogFile(json) {
-        	
-        	if (json['SAOPState']!=undefined) {
-        		processStandard(json['SAOPState'], 'SAOP');
-        	} else if (json['SHAOPState']!=undefined) {
-        		processSHAOP(json['SHAOPState']);
-        	} else if (json['MOPACState']!=undefined) {
-        		// just use the SAOP processor, which shows the
-        		// utilities of all Offers in sequence.
-        		processStandard(json['MOPACState'], 'MOPAC');
-        	} else{
+        	if (json['SAOPState']==undefined) {
             	setStatus("Unknown log file contents "+Object.keys(json));
-            }
-        }
-        
-        /**
-        Handle standard protocol result.
-        @param protocol either SAOP or MOPAC or another SAOP-like protocol
-        */
-        function processStandard(json, protocol) {
+            	return;
+        	}
+    		processSAOP(json['SAOPState']);
+        }
+        
+        /**
+        Handle SAOP protocol result.
+        */
+        function processSAOP(json) {
         	var partyprofiles={}
         	var profs=json['partyprofiles'];
         	for (var party in profs) {
-        		partyprofiles[party]=withoutPartial(profs[party]['profile']);
-        	}
-        	
-        	getProfiles(json, partyprofiles, protocol);
-        }
-        
-        
-        /**
-        Handle SHAOP protocol result. Get only SHAOP profiles. Remove all 'partial=XX' from relevant profiles.
-        */
-        function processSHAOP(json) {
-        	var partyprofiles={}
-        	var teams=json['settings']['SHAOPSettings']['participants'];
-        	for (var partyid in json['partyNumbers']) {
-        		var nr= json['partyNumbers'][partyid];
-        		if ( (nr & 1 != 0)) continue; // skip COB parties
-        		var shaop=teams[nr/2]['TeamInfo']['parties'][0];
-        		var profile = withoutPartial(shaop['profile']); // hacky, remove complete query.
-        		partyprofiles[partyid]=profile;
-        	}
-			
-        	
-        	getProfiles(json, partyprofiles, "SHAOP");
-        }
-
-
-        /**
-        @param uristr a string with an uri that may have ?partial=XX 
-        @return the given uristr   without the "partia=XXl" value 
-        */
-        function withoutPartial(uristr) {
-    		var profuri=new URL(uristr);
-    		var searchParams = new URLSearchParams(profuri.search);
-    		searchParams.delete("partial");
-    		profuri.search = searchParams.toString();
-    		return profuri.toString();
-
-        } 
+        		partyprofiles[party]=profs[party]['profile'];
+        	}
+        	
+        	getProfiles(json, partyprofiles);
+        }
         
         /**
         Get the partyprofiles.
-        @param json the json protocol result
-        @param partyprofileURIs dict with the websocket addresses for each party'as profile
-        @param partyprofiles dict with each party's profile. Initially should be {}
-        @param protocol protocolname, eg "SAOP"
-        */
-        function getProfiles(json, partyprofileURIs, protocol, partyprofiles={} ) {
+        @json the json protocol result
+        @partyprofileURIs dict with the websocket addresses for each party'as profile
+        @partyprofiles dict with each party's profile. Initially should be {}
+        */
+        function getProfiles(json, partyprofileURIs, partyprofiles={}) {
         	var keys = Object.keys(partyprofileURIs);
 			if (keys.length==0) {
-				plotResults(computeUtils(json, partyprofiles), isAgreement(json, protocol));
+				plotResults(computeUtils(json, partyprofiles));
 				return;
 			}
@@ -184,5 +128,5 @@
             	}
             	partyprofiles[party]=profile['LinearAdditiveUtilitySpace'];
-            	getProfiles(json, partyprofileURIs, protocol, partyprofiles);
+            	getProfiles(json, partyprofileURIs, partyprofiles);
             };
             ws.onerror=function(event) {
@@ -192,34 +136,6 @@
         
         /**
-        @param logfile the logfile content, but below the protocol header
-        @param protocol the protocol name, eg SAOP, SHAOP, MOPAC
-        @return 'Yes' if there is agreement, 'No' if there is no agreement at all, 
-        or 'Partial'  if part of the parties agreed and part did not.
-        or '?' if unsupported protocol
-        */
-        function isAgreement(logfile, protocol) {
-			switch (protocol) {
-				case "SAOP":
-				case "SHAOP":
-					var actions=logfile['actions'];
-					var lastact = actions[actions.length -1];
-					return 'Accept' in lastact ? 'Yes':'No';
-				case "MOPAC":
-					var finalstate=logfile['phase'][Object.keys(logfile['phase'])[0]]['partyStates'];
-					var nagrees=Object.keys(finalstate['agreements']).length;
-					var nparties=Object.keys(finalstate['powers']).length;
-					if (nagrees==nparties) return "Yes";
-					if (nagrees==0) return "No"
-					return "Partial";
-				default:
-					return "?";
-				}
-        }
-        /**
         @json the log file contents
         @param partyprofiles a dict with key=party id and value a the (linear additive) profile
-        @return a list [utilities, biddingparties] where utilities is a dict with keys: partyID
-        and value: list of utilities . biddingparties is a list [partyid] which is the 
-        bidding party for each round.
         */
         function computeUtils(json, partyprofiles) {
@@ -227,25 +143,18 @@
         	setStatus("Computing utilities.")
         	var utilities={};
-        	var biddingparties=[];
 			for (var party in partyprofiles) {
 				utilities[party]=[];
 			}
         	var actions = json['actions'];
-        	for (var n in actions) {
-        		var action = actions[n];
-        		var item;
-        		if ('Offer' in action) 
-        			action= action['Offer'];
-        		else if ('Accept' in action)
-        			action= action['Accept'];
-        		else 
+        	for (var action in actions) {
+        		var offer = actions[action];
+        		if (offer['offer']==undefined)
         			continue;
-        		var issueutilities = action['bid']['issuevalues']
+        		var issueutilities = offer['offer']['bid']['issuevalues']
 				for (var party in partyprofiles) {
 					utilities[party].push(utility(partyprofiles[party],issueutilities));
 				}
-        		biddingparties.push(action['actor']);
-        	}
-        	return [utilities, biddingparties];
+        	}
+        	return utilities;
         	
         	
@@ -267,13 +176,9 @@
         
         /**
-        @param [utilities, parties] utilities=the dict with key=party id  of the utilities of all steps for each party )
-        and parties a list of biddingparty for each value in utilities lists.
-        @param isAgreement either Yes, No, Partial or ?
-        */
-        
-        function plotResults( [utilities, biddingparties], isAgreement) {
+        @param utilities the dict with key=party id  of the utilities of all steps for each party )
+        */
+        
+        function plotResults( utilities) {
         	setStatus("Plotting" )
-        	
-            document.getElementById('agreement').innerHTML=isAgreement;
 
         	var parties=Object.keys(utilities);
@@ -284,8 +189,4 @@
         	var partynr=0;
         	for (var party in utilities) {
-        		var pointsizes=[];
-        		for (var p of biddingparties) {
-        			pointsizes.push(p==party ? 4:0); 
-        		}
         		var dataset={
    					label: party,
@@ -294,5 +195,4 @@
    					borderColor: color(partynr),
 					data: utilities[party],
-					pointRadius: pointsizes,
 					fill: false
         		};
@@ -326,5 +226,5 @@
     						scaleLabel: {
     							display: true,
-    							labelString: 'Offer'
+    							labelString: 'Turn'
     						}
     					}],
@@ -407,10 +307,10 @@
 	 			return 0;
 	 		}
-			if (utilfunc['NumberValueSetUtilities']!=undefined) {
+			if (utilfunc['numberutils']!=undefined) {
 				// it's numeric issue. Compute
-				var minval = utilfunc['NumberValueSetUtilities']['lowValue'];
-				var minutil = utilfunc['NumberValueSetUtilities']['lowUtility'];
-				var maxval = utilfunc['NumberValueSetUtilities']['highValue'];
-				var maxutil = utilfunc['NumberValueSetUtilities']['highUtility'];
+				var minval = utilfunc['numberutils']['lowValue'];
+				var minutil = utilfunc['numberutils']['lowUtility'];
+				var maxval = utilfunc['numberutils']['highValue'];
+				var maxutil = utilfunc['numberutils']['highUtility'];
 				
 				var alfa = (value-minval) / (maxval - minval) ;
@@ -418,7 +318,7 @@
 				return alfa * maxutil + (1-alfa) * minutil;   
 			}
-			if (utilfunc['DiscreteValueSetUtilities']!=undefined) {
+			if (utilfunc['discreteutils']!=undefined) {
 				// it's discrete issue. Compute
-				return utilfunc['DiscreteValueSetUtilities']['valueUtilities'][value];
+				return utilfunc['discreteutils']['valueUtilities'][value];
 			}
 	    	setStatus("Unknown utility function type "+Object.keys(utilfunc));
@@ -434,7 +334,4 @@
 
 
-
-
-
 </script>
 
@@ -442,7 +339,4 @@
 
 <script type="application/javascript">
-	
-	
-	
 	
 	
@@ -474,7 +368,4 @@
 
 
-
-
-
 </script>
 
Index: src/main/webapp/style.css
===================================================================
--- src/main/webapp/style.css	(revision 45)
+++ src/main/webapp/style.css	(revision 1)
@@ -6,5 +6,6 @@
 table {
 	border: 1px solid black;
-	#border-collapse: collapse;
+	border-collapse: collapse;
+	border: 1px solid black;
 }
 
@@ -19,12 +20,2 @@
 	  border: 1px solid black;
 }
-
-/* Used for elements that are visible only if SHAOP protocol selected.
-This css is programmatically changed when protocol changes */
-.onlySHAOP { }
-
-/* substitute for <a> as in <a href-..> */
-aa {
- 	color: blue;
-	text-decoration: underline;
-}
Index: src/main/webapp/utilstable.xhtml
===================================================================
--- src/main/webapp/utilstable.xhtml	(revision 45)
+++ 	(revision )
@@ -1,487 +1,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
-<head>
-<title>Show tournament results table</title>
-<link rel="stylesheet" type="text/css" href="style.css" />
-</head>
-<style>
-canvas {
-	-moz-user-select: none;
-	-webkit-user-select: none;
-	-ms-user-select: none;
-}
-</style>
-<body>
-	<div class="noscript">
-		<h2 style="color: #ff0000">Seems your browser doesn't support
-			Javascript! Websockets rely on Javascript being enabled. Please
-			enable Javascript and reload this page!</h2>
-	</div>
-	<h1 id="header">Tournament results</h1>
-
-	Progress:
-	<div id="progress">Waiting for log file name</div>
-	<br />
-
-	<table id="outcomes">
-		<thead>
-			<tr>
-				<th align="center">sess / agree</th>
-				<th align="center">accepted bid in session</th>
-				<th align="center">party utility - penalty</th>
-			</tr>
-		</thead>
-		<tbody id="outcomeslist">
-			<!--  one row for each session run added by script -->
-		</tbody>
-
-	</table>
-</body>
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-<!-- Script to get/update the  table using the query given in the URL. -->
-<script type="application/javascript">
-	
-	
-	
-	
-	
-	<![CDATA[
-        "use strict";
-
-
-        
-        var ws = null;
-        var SHAOP=false;
-        /* dict with key=profile URL and value = the downloaded (json) profile */
-        var profiles = {};
-
-        <!-- Most functions are reactive programming written out-->
-
-        /**
-        Called when the page opens.
-        */
-        function init() {
-        	
-        	var id=document.location.search;
-            id = location.search.split('?')[1]
-            if (id==undefined) return;
-            
-            // load the log file with given id
-            document.getElementById('header').innerHTML="Tournament results table of "+id;
-
-            var url = "log/"+id+".json";
-        	setStatus("Downloading file "+url);
-            var request=new XMLHttpRequest();
-            request.responseType = 'text';
-            request.open('Get', url)
-            request.onload=function() {
-            	if (request.status!=200) {
-            		setStatus("Failed to fetch "+url+":" +request.status+" "+request.statusText)
-            		return;
-            	}
-				processLogFile(JSON.parse(request.response));
-			}
-            request.send();
- 		}
-        
-        
-        /**
-        Figure out the protocol contents and parse accordingly.
-        */
-        function processLogFile(json) {
-        	if (json['AllPermutationsState']!=undefined) {
-        		processAPP(json['AllPermutationsState'], 'AllPermutationsSettings');
-        	} else if (json['AllPermutationsLearnState']!=undefined) {
-        		processAPP(json['AllPermutationsLearnState'],'AllPermutationsLearnSettings');
-        	} else    	
-        	{
-            	setStatus("Unknown log file contents "+Object.keys(json));
-            }
-        }
-        
-        /**
-        Handle AllPermutationsState protocol result.
-        @param json the json contents of the file inside the top level header
-        @param settingsname the name of the expected settings object inside, 
-        eg 'AllPermutationSettings'
-        */
-        function processAPP(json, settingsname) {
-        	setStatus("processing the log file");
-        	
-        	if (json['toursettings'][settingsname]['sessionsettings']['SHAOPSettings']!=undefined) {
-        		SHAOP=true;
-        	}
-        	
-        	// collect all profiles from all profileslists
-        	var profiles= [];
-        	for (const profilelist of json['toursettings'][settingsname]['profileslists']) {
-        		profiles = profiles.concat(profilelist['ProfileList']); 
-        	}
-        	getAllProfiles(json, profiles);
-        }
-        
-        /**
-         Step 1, get all profiles. Repeats recursiuvely till profileurls is empty.
-         Note just calling the function again without recurse would be better.
-         Problem is that we call this after we got the profile to ensure we 
-         have all profiles at the end.
-         @param profileurls the list of profile urls that need to be fetched.
-         @param profiles a dictionary of profiles . Key is profileurl, value the profile. Should
-         be initially {}
-         returns only after all profiles have been fetched.
-        */
-        function getAllProfiles(json, profileurls) {
-        	 for (var n in profileurls) {
-        		 getProfile(profileurls[n], function() {fillRows(json)} );
-        	 }
-        }
-         
-        /**
-        This function returns immediately and will add the profile to the profiles dictionary some time later.
-        @param profurl the  profile URL may have ?partial filter.
-        @param callwhendone function is called (without arguments) when profiles contains no pending anymore
-        */
-        function getProfile(profurl, callwhendone) {
-        	profiles[profurl]='pending'; // store ORIGINAL URL 
-    		var	profileurl = profurl.split('?',1)[0]; // hacky, remove complete query.
-
-			setStatus("fetching profile "+profileurl);
-			var ws;
-            if ('WebSocket' in window) {
-                ws = new WebSocket(profileurl);
-            } else if ('MozWebSocket' in window) {
-                ws = new MozWebSocket(profileurl);
-            } else {
-                setStatus('Fatal: WebSocket is not supported by this browser. Please use a newer browser');
-                return;
-            }
-            ws.onmessage = function (event) {
-                ws.close();
-            	var profile = JSON.parse(event.data);
-            	if (profile['LinearAdditiveUtilitySpace']==undefined) {
-                    setStatus('Fatal: profile '+profileurl+" does not contain a LinearAdditiveUtilitySpace.");
-                    return;
-            	}
-
-            	profiles[profurl]=profile['LinearAdditiveUtilitySpace'];
-            	
-            	checkAllProfiles(callwhendone);
-            };
-            ws.onerror=function(event) {
-                ws.close();
-                setStatus('Error fetching profile '+uri+':'+event);
-            } 
-        }
-        
-        /**
-        Check if there are still pending profiles. If not, callwhendone().
-        */
-        function checkAllProfiles(callwhendone) {
-        	for (var key in profiles) {
-        		if (profiles[key] == 'pending') return;
-        	}
-        	callwhendone();
-        }
-        
-        /**
-        Step 2, fill the table with util values
-        @param profiles a dictionary of profiles . Key is profileurl, value the profile. Should
-        be initially {}
-       */
-        function fillRows(json)
-        {
-    	   	setStatus("Computing utilities");
-	       	var table = document.getElementById("outcomeslist");
-	    	table.innerHTML="";
-	    	var results = json['results'];
-	    	
-	    	for (var nr in results) {
-	    		var result = results[nr];
-	        	fillBids(table, nr, result);
-	    	}
-    	   	setStatus("done");
-        }
-
-       /**
-       Add rows for all the bids in the result. Notice that some protocols allow multiple bids to be accepted per session.
-       @param table the table to add the bid results to
-       @param nr the session number
-       @param results the results for this sess. This is a dict with key: partyid (eg "party83+127_0_1_1)
-       and the value the accepted issuevalues (the bid contents). Parties that did not reach an agreement
-       are not in the list.
-       */
-       function fillBids(table, nr, result) {
-			// collect unique bids in agreements.
-			var agreements = result['agreements'];
-			
-			//if (Object.keys(agreements).length == 0)  {
-			//	fillRow(table.insertRow(-1), nr, result, {});
-			//	return;
-			//}
-
-			// collect all bids, plus "null" if there are parties without agreements.
-			var bids = [];
-        	const participants = result['participants'];
-        	for (var pid in participants) {
-        		if (pid in agreements) {
-    				bids=addSet(bids, agreements[pid]['issuevalues']);
-        		} else {
-        			bids=addSet(bids, null)
-        		}
-        	}
-	
-			var dealnr='A'.charCodeAt(0);
-			for (const bid of bids) {
-				fillRow(table.insertRow(-1), nr+String.fromCharCode(dealnr++), result, bid);
-			}
-       }
-       	
-
-      
-
-        /**
-        @param row  the table row object in the document
-        @param nr the row number
-        @param result a single json result from the APP results section. 
-        Contains participants, agreements and error
-        @param agreedbid the bid to show in this row. dict, with hte issuevalues from the bid. 
-        If null, this should show parties that did not reach an agreement.
-        */
-        function fillRow(row, nr, result, agreedbid) {
-        	row.insertCell(0).innerHTML = nr;
-        	
-        	if (result['error']!=null) {
-        		var errstr="session failed:";
-        		var err=result['error'];
-        		if ("geniusweb.protocol.ProtocolException" in err) {
-        			errstr=errstr+err["geniusweb.protocol.ProtocolException"]['cause']['message'];
-        		}
-        		row.insertCell(-1).innerHTML=errstr;
-        	} else {
-				if (agreedbid==null) {
-		        	row.insertCell(-1).innerHTML = "No deal";
-				} else {
-		        	row.insertCell(-1).innerHTML = JSON.stringify(agreedbid);
-	        	}
-        	}
-        	// fill in the columns. If SHAOP, only the even parties 
-        	// FIXME this can't be with a MAP
-        	const participants = result['participants'];
-        	for (var pid in participants) {
-        		var partyandprofile = result['participants'][pid];
-        		var profile =partyandprofile['profile'];
-            	var penalty=result['penalties'][pid];
-            	if (penalty==undefined) penalty=0;
-        		// make short name for readability
-        		var partyname = partyandprofile['party']['partyref'];
-        		partyname = partyname.split('/');
-        		partyname = partyname[partyname.length-1];
-        		
-        		// we set bid to agreedbid only if party accepted agreedbid.
-         		var bid = {};
-        		if (pid in result['agreements'] && agreedbid!=null && 
-        				deepEqual(agreedbid, result['agreements'][pid]['issuevalues'] ) )
-       				bid = agreedbid;
-         		addUtilityCell(row.insertCell(-1), bid, partyname, profile, penalty);
-        	}
-        }
-
-        /**
-        @param cell the table cell to put the result in
-        @param agreedbid the bid that was agreed on 
-        @param partyname the short name of the party
-        @param profileurl the profile url to use for the evaluation of the bid
-        @param bid the accepted bid, not null.
-        @param penalty costs made by the party, to be subtracted from total util.
-        	typically these are elicitation costs.
-        */
-        function addUtilityCell(cell, agreedbid, partyname, profileurl, penalty) {
-        	var util = utility(profiles[profileurl],agreedbid);
-        	var rUtil = Math.round(util*1000000)/1000000;
-        	var rPenalty = Math.round( (penalty )*1000000)/1000000 ;
-        	cell.innerHTML = rUtil + "-" + rPenalty + " :"+partyname;
-
-        }
-        
-
-
-
-        
-        /******************* Private support funcs****************/
-        
-        /**
-        Set the progress/status text
-        */
-        function setStatus(text) {
-            document.getElementById('progress').innerHTML=text;
-        }
-
-        /*
-        @param sessions a list of IDs (Strings).
-        */
-        function update(sessions) {
-			var table = document.getElementById("sessionsTable");
-        	table.innerHTML="";
-        	for(var  session of sessions) {
-        		var row = table.insertRow(-1); //-1 = end
-				row.insertCell(0).innerHTML = session;
-        	}
-        	
-        }
-        
-   
-    
-	 	
-		/**
-	 	Compute utilityes
-	 	@param profile the linear additive utility space
-	 	@param issueValues the bid containing dict with values for the issues
-	 	@param isResBidAlternative true if the reservation bid is usable as alternative bid
-	 	  . If true, and the issueValues list is empty/null, this returns the utility
-	 	  of the reservation bid instead.
-	 	@return utility of issueValues. Returns 0 if profile =null or no bid available
-	 	
-	 	*/
-	 	function utility(profile, issueValues, isResBidAlternative) {
-	 		if (profile==null) return 0;
-
-	 		// check if we need the reservationbid.
-			if (issueValues==null || Object.keys(issueValues).length==0) {
-	 			var resBid = profile['reservationBid'];
-	 			if (resBid==null) return 0;
-	 			issueValues = resBid['issuevalues'];
-	 		}
-	 		
-	 		if (issueValues==null) return 0;
-	 		
-			var util=0;
-			var weights = profile['issueWeights'];
-			
-			for (var issue in issueValues) {
-				util = util + weights[issue] * evaluate(profile['issueUtilities'][issue], issueValues[issue] );
-			}
-			return util;
-		}
-	
-	 	/**
-	 	Bit hacky, javascript version of evaluator of utility space. 
-	 	Would be much nicer if we could use java here
-	 	*/
-	 	function evaluate (utilfunc, value) {
-	 		if (utilfunc == undefined) {
-	 			return 0;
-	 		}
-			if (utilfunc['NumberValueSetUtilities']!=undefined) {
-				// it's numeric issue. Compute
-				var minval = utilfunc['NumberValueSetUtilities']['lowValue'];
-				var minutil = utilfunc['NumberValueSetUtilities']['lowUtility'];
-				var maxval = utilfunc['NumberValueSetUtilities']['highValue'];
-				var maxutil = utilfunc['NumberValueSetUtilities']['highUtility'];
-				
-				var alfa = (value-minval) / (maxval - minval) ;
-				alfa = Math.max(Math.min(alfa, 1),0);
-				return alfa * maxutil + (1-alfa) * minutil;   
-			}
-			if (utilfunc['DiscreteValueSetUtilities']!=undefined) {
-				// it's discrete issue. Compute
-				if (value in utilfunc['DiscreteValueSetUtilities']['valueUtilities']) 
-					return utilfunc['DiscreteValueSetUtilities']['valueUtilities'][value];
-				return 0;
-			}
-	    	setStatus("Unknown utility function type "+Object.keys(utilfunc));
-	
-	 	}
- 	
-	 	/************ util functions to compare dict objects **************/
-	 	/**
-        @return true if object1, object2 are 'deep equal'. That means,
-        if they are dicts then we check that the keys and their values are equal, 
-        recursively.
-        */
-       function deepEqual(object1, object2) {
-        	if (object1==null) {
-        		return object2==null;
-        	}
-        	if (object2==null) return false;
-    	   const keys1 = Object.keys(object1);
-    	   const keys2 = Object.keys(object2);
-
-    	   if (keys1.length !== keys2.length) {
-    	     return false;
-    	   }
-
-    	   for (const key of keys1) {
-    	     const val1 = object1[key];
-    	     const val2 = object2[key];
-    	     const areObjects = isObject(val1) && isObject(val2);
-    	     if (
-    	       areObjects && !deepEqual(val1, val2) ||      !areObjects && val1 !== val2
-    	     ) {
-    	       return false;
-    	     }
-    	   }
-
-    	   return true;
-    	 }
-
-    	 function isObject(object) {
-    	   return object != null && typeof object === 'object';
-    	 } 
-    	 
-    	 /**
-    	 @param list the list to add value to
-    	 @param value the value to add
-    	 @return list with the value added, but only if not already in list.
-    	 Uses deepEqual to check equality of list members 
-    	 */
-    	 function addSet(list, value) {
-    		 for (const v of list) {
-    			 if (deepEqual(v, value))
-    				 return list;
-    		 }
-    		 return list.concat(value);
-    	 }
- 	
-    ]]>
-
-
-
-	
-	<![CDATA[
-        "use strict";
-        /*
-        This is called when the window DOM is loaded. window.onload runs BEFORE the window is loaded
-        and therefore is too early to remove the noscript message.
-        */
-       document.addEventListener("DOMContentLoaded", function() {
-			// Remove elements with "noscript" class - <noscript> is not allowed in XHTML
-			var noscripts = document.getElementsByClassName("noscript");
-			for (var i = 0; i < noscripts.length; i++) {
-			    noscripts[i].parentNode.removeChild(noscripts[i]);
-			}
-       		init();
-
-         }, false);
-    ]]>
-
-
-
-</script>
-
-
-</html>
