Index: src/main/webapp/utilstable.xhtml
===================================================================
--- src/main/webapp/utilstable.xhtml	(revision 18)
+++ src/main/webapp/utilstable.xhtml	(revision 19)
@@ -27,6 +27,6 @@
 		<thead>
 			<tr>
-				<th align="center">run nr</th>
-				<th align="center">accepted bid(s)</th>
+				<th align="center">sess / agree</th>
+				<th align="center">accepted bid in session</th>
 				<th align="center">party utility - penalty</th>
 			</tr>
@@ -206,54 +206,37 @@
 	    	for (var nr in results) {
 	    		var result = results[nr];
-	        	var row = table.insertRow(-1); //-1 = end
-	        	fillRow(row, nr, results[nr]);
+	        	fillBids(table, nr, result);
 	    	}
     	   	setStatus("done");
         }
 
-        /**
-        @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) {
-    	   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);
-    	 }
+       /**
+       @param table the table to add the bid results to
+       @param nr the session number
+       @param results the results for this sess
+       Add rows for all the bids 
+       */
+       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;
+			}
+				
+			var bids = [];
+			for (const pid in agreements)  {
+				bids=addSet(bids, agreements[pid]['issuevalues']);
+			}
+	
+			var dealnr='A'.charCodeAt(0);
+			for (const bid of bids) {
+				fillRow(table.insertRow(-1), nr+String.fromCharCode(dealnr++), result, bid);
+			}
+       }
+       	
+
+      
 
         /**
@@ -262,6 +245,7 @@
         @param result a single json result from the APP results section. 
         Contains participants, agreements and error
-        */
-        function fillRow(row, nr, result) {
+        @param agreedbid the bid to show in this row. If {}, no agreement was reached.
+        */
+        function fillRow(row, nr, result, agreedbid) {
         	row.insertCell(0).innerHTML = nr;
         	
@@ -275,30 +259,26 @@
         		return;
         	}
-
-        	// collect unique bids in agreements.
-        	var agreements = result['agreements'];
-        	var bids = [];
-        	for (const pid in agreements) {
-        		bids=addSet(bids, agreements[pid]['issuevalues']);
-        	}
-        		
-        		
+	
         	// a dict, keys are party ids. 
-        	// FIXME this does not work ok with MOPAC.
-        	row.insertCell(-1).innerHTML = JSON.stringify(bids);
-        	var agreedbid={};
-        	if (bids.length>0) agreedbid = bids[0];
+        	row.insertCell(-1).innerHTML = JSON.stringify(agreedbid);
         	
         	// fill in the columns. If SHAOP, only the even parties 
-        	var stepsize = SHAOP? 2:1;
-        	for (var n=0; n<result['participants'].length; n=n+stepsize) {
-        		var party =  result['participants'][n]
-        		var profile =party['profile'];
-            	var penalty=result['penalties'][n];
+        	// 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 = party['party']['partyref'];
+        		var partyname = partyandprofile['party']['partyref'];
         		partyname = partyname.split('/');
         		partyname = partyname[partyname.length-1];
-        		addUtilityCell(row.insertCell(-1), agreedbid, partyname, profile,penalty);
+        		
+        		// we set bid to agreedbid only if party accepted agreedbid.
+         		var bid = {};
+        		if (pid in result['agreements'] && deepEqual(agreedbid, result['agreements'][pid]['issuevalues'] ) )
+        				bid = agreedbid;
+         		addUtilityCell(row.insertCell(-1), bid, partyname, profile, penalty);
         	}
         }
@@ -410,4 +390,49 @@
 	 	}
  	
+	 	/************ 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) {
+    	   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);
+    	 }
  	
     ]]>
