source: src/main/webapp/plotlog.xhtml@ 12

Last change on this file since 12 was 10, checked in by bart, 5 years ago

Added ANAC2019 Example parties: Agentgg and WinkyAgent

File size: 10.6 KB
Line 
1<?xml version="1.0" encoding="UTF-8"?>
2<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
3<head>
4<title>Plot log results</title>
5<script src="Chart.min_2.8.0.js"></script>
6</head>
7<style>
8canvas {
9 -moz-user-select: none;
10 -webkit-user-select: none;
11 -ms-user-select: none;
12}
13</style>
14<body>
15 <div class="noscript">
16 <h2 style="color: #ff0000">Seems your browser doesn't support
17 Javascript! Websockets rely on Javascript being enabled. Please
18 enable Javascript and reload this page!</h2>
19 </div>
20 <h1 id="header">Graph of log results</h1>
21
22 Progress:
23 <div id="progress">Waiting for log file name</div>
24 <br />
25 <div style="width: 100%;">
26 <canvas id="canvas"></canvas>
27 </div>
28</body>
29
30<!-- Script to get/update the SESSIONS list and put it into the table. -->
31<script type="application/javascript">
32
33
34
35
36
37
38
39
40
41 <![CDATA[
42 "use strict";
43
44
45
46 var ws = null;
47
48 <!-- Most functions are reactive programming written out-->
49
50 function connect() {
51
52 var id=document.location.search;
53 id = location.search.split('id=')[1]
54 if (id==undefined) return;
55
56 // load the log file with given id
57 document.getElementById('header').innerHTML="Graph of log "+id;
58
59 var url = "log/"+id+".json";
60 setStatus("Downloading file "+url);
61 var request=new XMLHttpRequest();
62 request.responseType = 'text';
63 request.open('Get', url)
64 request.onload=function() {
65 if (request.status!=200) {
66 setStatus("Failed to fetch "+url+":" +request.status+" "+request.statusText)
67 return;
68 }
69 processLogFile(JSON.parse(request.response));
70 }
71 request.send();
72 }
73
74
75 /**
76 Figure out the protocol contents and parse accordingly.
77 */
78 function processLogFile(json) {
79 if (json['SAOPState']!=undefined) {
80 processSAOP(json['SAOPState']);
81 } else if (json['SHAOPState']!=undefined) {
82 processSHAOP(json['SHAOPState']);
83 } else {
84 setStatus("Unknown log file contents "+Object.keys(json));
85 }
86 }
87
88 /**
89 Handle SAOP protocol result.
90 */
91 function processSAOP(json) {
92 var partyprofiles={}
93 var profs=json['partyprofiles'];
94 for (var party in profs) {
95 partyprofiles[party]=profs[party]['profile'].split('?',1)[0]; // hacky, remove complete query.
96 }
97
98 getProfiles(json, partyprofiles);
99 }
100
101 /**
102 Handle SHAOP protocol result. Get only SHAOP profiles. Remove all 'partial=XX' from relevant profiles.
103 */
104 function processSHAOP(json) {
105 var partyprofiles={}
106 var teams=json['settings']['SHAOPSettings']['participants'];
107 for (var partyid in json['partyNumbers']) {
108 var nr= json['partyNumbers'][partyid];
109 if ( (nr & 1 != 0)) continue; // skip COB parties
110 var shaop=teams[nr/2]['shaop'];
111 var profile = shaop['profile'].split('?',1)[0]; // hacky, remove complete query.
112 partyprofiles[partyid]=profile;
113 }
114
115
116 getProfiles(json, partyprofiles);
117 }
118
119
120 /**
121 Get the partyprofiles.
122 @json the json protocol result
123 @partyprofileURIs dict with the websocket addresses for each party'as profile
124 @partyprofiles dict with each party's profile. Initially should be {}
125 */
126 function getProfiles(json, partyprofileURIs, partyprofiles={}) {
127 var keys = Object.keys(partyprofileURIs);
128 if (keys.length==0) {
129 plotResults(computeUtils(json, partyprofiles));
130 return;
131 }
132 var party = keys[0];
133 var uri=partyprofileURIs[party];
134 delete partyprofileURIs[party];
135
136 setStatus("fetching profile "+uri);
137 if ('WebSocket' in window) {
138 ws = new WebSocket(uri);
139 } else if ('MozWebSocket' in window) {
140 ws = new MozWebSocket(uri);
141 } else {
142 setStatus('Fatal: WebSocket is not supported by this browser. Please use a newer browser');
143 return;
144 }
145 ws.onmessage = function (event) {
146 var profile = JSON.parse(event.data);
147 if (profile['LinearAdditiveUtilitySpace']==undefined) {
148 setStatus('Fatal: profile '+uri+" does not contain a LinearAdditiveUtilitySpace.");
149 return;
150 }
151 partyprofiles[party]=profile['LinearAdditiveUtilitySpace'];
152 getProfiles(json, partyprofileURIs, partyprofiles);
153 };
154 ws.onerror=function(event) {
155 setStatus('Error fetching profile '+uri+':'+event);
156 }
157 }
158
159 /**
160 @json the log file contents
161 @param partyprofiles a dict with key=party id and value a the (linear additive) profile
162 */
163 function computeUtils(json, partyprofiles) {
164
165 setStatus("Computing utilities.")
166 var utilities={};
167 for (var party in partyprofiles) {
168 utilities[party]=[];
169 }
170 var actions = json['actions'];
171 for (var action in actions) {
172 var offer = actions[action];
173 if (offer['offer']==undefined)
174 continue;
175 var issueutilities = offer['offer']['bid']['issuevalues']
176 for (var party in partyprofiles) {
177 utilities[party].push(utility(partyprofiles[party],issueutilities));
178 }
179 }
180 return utilities;
181
182
183 }
184
185 var chartColors = [
186 'rgb(255, 99, 132)',
187 'rgb(3, 192, 12)',
188 'rgb(54, 162, 235)',
189 'rgb(153, 102, 255)',
190 'rgb(201, 203, 207)',
191 'rgb(255, 159, 64)',
192 'rgb(255, 205, 86)'
193 ];
194
195 function color(i) {
196 return chartColors[i % chartColors.length];
197 }
198
199 /**
200 @param utilities the dict with key=party id of the utilities of all steps for each party )
201 */
202
203 function plotResults( utilities) {
204 setStatus("Plotting" )
205
206 var parties=Object.keys(utilities);
207 var thelabels=[];
208 for (var i=1; i<=utilities[parties[0]].length; i++) { thelabels.push(i); }
209
210 var thedatasets=[];
211 var partynr=0;
212 for (var party in utilities) {
213 var dataset={
214 label: party,
215 lineTension:0, // straight lines between the points
216 backgroundColor: color(partynr),
217 borderColor: color(partynr),
218 data: utilities[party],
219 fill: false
220 };
221 thedatasets.push(dataset);
222 partynr++;
223 }
224
225 var config = {
226 type: 'line',
227 data: {
228 labels: thelabels,
229 datasets: thedatasets
230 },
231 options: {
232 responsive: true,
233 title: {
234 display: true,
235 text: 'Per-turn utility plot'
236 },
237 tooltips: {
238 mode: 'index',
239 intersect: false,
240 },
241 hover: {
242 mode: 'nearest',
243 intersect: true
244 },
245 scales: {
246 xAxes: [{
247 display: true,
248 scaleLabel: {
249 display: true,
250 labelString: 'Turn'
251 }
252 }],
253 yAxes: [{
254 display: true,
255 scaleLabel: {
256 display: true,
257 labelString: 'Utility'
258 }
259 }]
260 }
261 }
262 };
263
264 var ctx = document.getElementById('canvas').getContext('2d');
265 window.myLine = new Chart(ctx, config);
266
267 setStatus("Plot ready." )
268
269 }
270
271 /**
272 keys are STRING objects 0,1,2... values are utility values (double)
273 */
274 function makeJxPolyline(pointslist) {
275 var jxpoints = []
276 for (var i in pointslist) {
277 jxpoints.push(new jxPoint(20*Number(i), 100*pointslist[i]));
278 }
279 return jxpoints;
280 }
281
282 /******************* Private support funcs****************/
283
284 /**
285 Set the progress/status text
286 */
287 function setStatus(text) {
288 document.getElementById('progress').innerHTML=text;
289 }
290
291 /*
292 @param sessions a list of IDs (Strings).
293 */
294 function update(sessions) {
295 var table = document.getElementById("sessionsTable");
296 table.innerHTML="";
297 for(var session of sessions) {
298 var row = table.insertRow(-1); //-1 = end
299 row.insertCell(0).innerHTML = session;
300 }
301
302 }
303
304
305
306
307 /**
308 Compute utilityes
309 @param linadditive the linear additive utility space
310 @param issueValues the bid containing dict with values for the issues
311 @return utility of issueValues
312 */
313 function utility(profile, issueValues) {
314 var util=0;
315 var weights = profile['issueWeights'];
316
317 for (var issue in issueValues) {
318 util = util + weights[issue] * evaluate(profile['issueUtilities'][issue], issueValues[issue] );
319 }
320 return util;
321 }
322
323 /**
324 Bit hacky, javascript version of evaluator of utility space.
325 Would be much nicer if we could use java here
326 */
327 function evaluate (utilfunc, value) {
328 if (utilfunc == undefined) {
329 return 0;
330 }
331 if (utilfunc['numberutils']!=undefined) {
332 // it's numeric issue. Compute
333 var minval = utilfunc['numberutils']['lowValue'];
334 var minutil = utilfunc['numberutils']['lowUtility'];
335 var maxval = utilfunc['numberutils']['highValue'];
336 var maxutil = utilfunc['numberutils']['highUtility'];
337
338 var alfa = (value-minval) / (maxval - minval) ;
339 alfa = Math.max(Math.min(alfa, 1),0);
340 return alfa * maxutil + (1-alfa) * minutil;
341 }
342 if (utilfunc['discreteutils']!=undefined) {
343 // it's discrete issue. Compute
344 return utilfunc['discreteutils']['valueUtilities'][value];
345 }
346 setStatus("Unknown utility function type "+Object.keys(utilfunc));
347
348 }
349
350
351 ]]>
352
353
354
355
356
357
358
359</script>
360
361
362
363<script type="application/javascript">
364
365
366
367
368
369
370
371 <![CDATA[
372 "use strict";
373 /*
374 This is called when the window DOM is loaded. window.onload runs BEFORE the window is loaded
375 and therefore is too early to remove the noscript message.
376 */
377 document.addEventListener("DOMContentLoaded", function() {
378 // Remove elements with "noscript" class - <noscript> is not allowed in XHTML
379 var noscripts = document.getElementsByClassName("noscript");
380 for (var i = 0; i < noscripts.length; i++) {
381 noscripts[i].parentNode.removeChild(noscripts[i]);
382 }
383 connect();
384
385 }, false);
386 ]]>
387
388
389
390
391
392
393
394
395</script>
396
397
398</html>
Note: See TracBrowser for help on using the repository browser.