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

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

Initial Release

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