source: src/main/webapp/newtournament.xhtml@ 10

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

Added ANAC2019 Example parties: Agentgg and WinkyAgent

File size: 13.1 KB
RevLine 
[1]1<?xml version="1.0" encoding="UTF-8"?>
2<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
3<head>
4<title>Profiles and Domains list</title>
5<link rel="stylesheet" type="text/css" href="style.css" />
6
7</head>
8<body onload="init()">
9 <h1>Tournament</h1>
10
11 On this page you can configure the settings for running a new
12 tournament and start the tournament.
13 <br />
14 <br />
15
16 <select>
17 <option value="APP">All Permutations Tournament Protocol
18 (APP)</option>
19 </select>
20 <br />
21 <br />
[6]22 <input type="number" id="partiespersession" name="tentacles" min="2"
23 max="10" value="2" /> Number of parties in each session
[1]24 <br />
25
[6]26 <input type="checkbox" id="reuseparties" /> Pick parties with return
27 when creating sessions
[1]28 <br />
29
30 <br />
31 <div id="box" class="box">
[8]32 Session Protocol settings <br /> Session Protocol:
33 <select id="protocolselection">
[1]34 <option value="SAOP">SAOP</option>
[8]35 <option value="SHAOP">SHAOP</option>
36 </select>
37
38 <br /> Deadline: <input type="number" id="deadlinevalue"
[6]39 name="deadline" min="1" max="10000" value="10" /> <select
40 id="deadlinetype">
[8]41 <option value="ROUNDS">rounds</option>
[1]42 <option value="TIME">seconds</option>
43 </select>
44 </div>
45 <br />
46
47 <div id="box" class="box">
[6]48 <br /> Domain/Profile Server: <input type="url" name="url"
[10]49 id="profilesserverurl" value="localhost:8080/profilesserver-1.3.0"
[1]50 pattern=".*:[0-9]+/profilesserver" size="30"
[6]51 onchange="connectDomain()"> </input> <br /> Domain: <select
52 id="domainselection" onchange="selectDomain()">
[1]53 <!-- <option>Waiting for profiles server</option> -->
[6]54 </select> <br /> <br />
[1]55 <button onclick="addProfile()">Add</button>
56 Profile: <select id="profileselection">
57 <!-- <option>Waiting for partiesserver</option> -->
[8]58 </select>
59 Filter: <input type="text" id="filter" value="" maxlength="40" />
60
61 <br /> <br />
[1]62
63 <table id="profiles">
64 <thead>
65 <th align="left">Selected Profiles</th>
66 </thead>
67 <tbody id="profilesList">
68 <tr>
69 </tr>
70
71 </tbody>
72 </table>
73 <br />
74 </div>
75 <br />
76 <div id="box" class="box">
[6]77 <br /> Parties Server: <input type="url" name="url"
[10]78 id="partiesserverurl" value="localhost:8080/partiesserver-1.3.0"
[1]79 pattern=".*:[0-9]+/partiesserver" size="30"
[6]80 onchange="connectParties()"> </input> <br /> <br />
[1]81 Party: <select id="partyselection">
82 <!-- <option>Waiting for partiesserver</option> -->
[6]83 </select> <br /> Parameters: { <input type="text" id="parameters"
84 onchange="updateParameters()" value="" maxlength="100" /> } <br />
85 <button onclick="addParty()">Add</button>
86
87 <br /> <br />
[1]88 <table>
89 <thead>
[6]90 <th align="left">Party</th>
91 <th align="left">Parameters</th>
[1]92 </thead>
93 <tbody id="partiesList">
94 <tr id="partiesList">
95 </tr>
96
97 </tbody>
98 </table>
99
100 </div>
101 <br />
102 <form>
[6]103 <input id="startbutton" type="button" value="Start Tournament"
104 onclick="start()" />
[1]105 </form>
[6]106 <div id="started" style="visibility: hidden">
107 Your tournament started. Click <a href="" id="logref">here</a> to view
[9]108 the log file. <br />
109 <a href="" id="plotref">show results table.</a>.
[1]110 </div>
111
112</body>
113
114<script type="application/javascript">
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
[6]133
[1]134 // FIXME quick and dirty code. No clean MVC
135
136
137 <![CDATA[
138 "use strict";
139
140 var domainwebsocket = null;
141 var partieswebsocket=null;
142 // currently known domains (and profiles) as coming from domainwebsocket.
143 // keys are domain names, values are list of profile names
144 var knowndomains={};
145
146 var parties=[];
147 var profiles=[]
[6]148 // current setting of parameters
149 var parameters = {};
[1]150
151
152 /**
153 Refresh known domains using given profilesserver URL.
154 Called when user enters URL for domain server.
155 */
156 function connectDomain() {
157 if (domainwebsocket!=null) {
158 domainwebsocket.close();
159 domainwebsocket=null;
160 }
161 var url=document.getElementById("profilesserverurl").value;
162 var target = "ws://"+url+"/websocket/liststream";
163 if ('WebSocket' in window) {
164 domainwebsocket = new WebSocket(target);
165 } else if ('MozWebSocket' in window) {
166 domainwebsocket = new MozWebSocket(target);
167 } else {
168 alert('WebSocket is not supported by this browser. Please use a newer browser');
169 return;
170 }
171 domainwebsocket.onopen = function () {
172 // whatever.
173 };
174 domainwebsocket.onmessage = function (event) {
175 updateDomainComboBox(JSON.parse(event.data));
176 };
177 domainwebsocket.onclose = function (event) {
178 alert('Info: Server closed connection. Code: ' + event.code +
179 (event.reason == "" ? "" : ", Reason: " + event.reason));
180 domainwebsocket=null;
181 updateDomainComboBox({});
182 };
183 }
184
185 /**
186 Sets a new knowndomains value and Updates the contents of the domain selector combobox.
187 @param the known domains, a map of the form {"jobs":["jobs1","jobs2"]}
188 where the keys are the names of the available domains nd the values a list of the available profiles in that domain.
189
190 */
191 function updateDomainComboBox(newdomains) {
192 knowndomains=newdomains
193 var combobox = document.getElementById("domainselection");
194 combobox.options.length=0;
195 for (var domain in knowndomains) {
196 var option = document.createElement('option');
197 option.text = option.value = domain;
198 combobox.add(option, 0);
199 }
200 selectDomain();
201 }
202 /**
203 Refresh known parties using given partiesserver URL.
204 Called when user enters URL for parties server.
205 */
206 function connectParties() {
207 if (partieswebsocket!=null) {
208 partieswebsocket.close();
209 partieswebsocket=null;
210 }
211 var url=document.getElementById("partiesserverurl").value;
212 var target = "ws://"+url+"/available";
213 if ('WebSocket' in window) {
214 partieswebsocket = new WebSocket(target);
215 } else if ('MozWebSocket' in window) {
216 partieswebsocket = new MozWebSocket(target);
217 } else {
218 alert('WebSocket is not supported by this browser. Please use a newer browser');
219 return;
220 }
221 partieswebsocket.onopen = function () {
222 // whatever.
223 };
224 partieswebsocket.onmessage = function (event) {
225 updateParties(JSON.parse(event.data));
226 };
227 partieswebsocket.onclose = function (event) {
228 alert('Info: Server closed connection. Code: ' + event.code +
229 (event.reason == "" ? "" : ", Reason: " + event.reason));
230 partieswebsocket=null;
231 updateParties({});
232 };
233 }
234
235
236 function updateParties(parties) {
237 var combobox = document.getElementById("partyselection");
238 combobox.options.length=0;
239 for (var party in parties) {
240 var option = document.createElement('option');
241 option.text = option.value = parties[party].uri;
242 combobox.add(option, 0);
243 }
244 }
245
246
247
[6]248 /**
249 updates parameters field to match the given text.
250 */
251 function updateParameters() {
252 var text="{"+document.getElementById("parameters").value+"}";
253 try {
254 parameters=JSON.parse(text);
255 } catch(e) {
256 alert("Parameters can not be parsed. "+e);
257 return;
258 }
259 }
[1]260
261 /**
262 Called when the selected domain changes. Assumes knowndomains has been set.
263 Updates the available profiles in the profile combobox.
264 @param selection the name of the selected domain.
265 */
266 function selectDomain() {
267 // determined current selection
268 var domaincombobox = document.getElementById("domainselection");
269 if (domaincombobox.options.length==0) return; // fixme clean profiles options?
270 var domain = domaincombobox.options[domaincombobox.selectedIndex].value;
271
272 var profilecombo = document.getElementById("profileselection");
273 profilecombo.options.length=0;
274 for (var profile in knowndomains[domain]) {
275 var option = document.createElement('option');
276 option.text = option.value = knowndomains[domain][profile];
277 profilecombo.add(option, 0);
278 }
279 }
280
281 /**
282 Called when user clicks "Add"
283 */
284 function addParty() {
285 var partycombo = document.getElementById("partyselection");
286
287 if (partycombo.options.length==0) {
288 alert("Please set partier server and select a party");
289 return;
290 }
[6]291 parties.push({"partyref":partycombo.options[partycombo.selectedIndex].value, "parameters":parameters})
[1]292 updatePartyTable();
293 }
294
295 /** updates the party table, to match the #partyprofiles list. */
296 function updatePartyTable() {
297 var table = document.getElementById("partiesList");
298 table.innerHTML = ""; // clear table
299 for ( var party in parties) {
300 var row = table.insertRow(-1);
301 var cell1 = row.insertCell(-1);
[6]302 var cell2 = row.insertCell(-1);
303 cell1.innerHTML = parties[party]["partyref"];
304 cell2.innerHTML = JSON.stringify(parties[party]["parameters"]);
[1]305 }
306
307 }
308
309 /**
310 Called when user clicks "Add" to add a profile
311 */
312 function addProfile() {
313 var profilecombo = document.getElementById("profileselection");
[8]314
[1]315 if (profilecombo.options.length==0) {
316 alert("Please set domain/profile server and select a domain and a profile");
317 return;
318 }
[8]319 var filteroptions = document.getElementById("filter").value;
320 if (filteroptions!="") {
321 filteroptions="?"+filteroptions;
322 }
323
324 profiles.push(profilecombo.options[profilecombo.selectedIndex].value + filteroptions)
[1]325 updateProfileTable(); // what, MVC?
326 }
327
328 /** updates the party table, to match the #partyprofiles list. */
329 function updateProfileTable() {
330 var table = document.getElementById("profilesList");
331 table.innerHTML = ""; // clear table
332 for ( var profile in profiles) {
333 var row = table.insertRow(-1);
334 var cell1 = row.insertCell(-1);
335 cell1.innerHTML = profiles[profile];
336 }
337
338 }
339
340 /**
341 start the tournament as currently set on this page.
[8]342 We need to send a TournamentSettings object to the server, which typically looks like this with SAOP
343 <code>
[1]344 {"AllPermutationsSettings":{"parties":["party1","party2"],
345 "profiles":["profile1","profile2","profile3"],
346 "reuseParties":false,
347 "partiesPerSession":2,
348 "sessionsettings":{"SAOPSettings":{"participants":[],"deadline":{"deadlinetime":{"durationms":10}}}}}}
[8]349 </code>
350 participants are already in the global partyprofiles dictionary
[1]351
[8]352 With SHAOP, it looks like this
353 <code>
354 {
355 "AllPermutationsSettings": {
356 "parties": [ { "partyref": "classpath:geniusweb.exampleparties.simpleshaop.ShaopParty", "parameters": { } },
357 { "partyref": "classpath:geniusweb.exampleparties.randomparty.RandomParty", "parameters": { }}
358 ],
359 "reuseParties": false,
360 "profiles": [ "prof1?partial=10", "prof2?partial=15"],
361 "partiesPerSession": 2,
362 "sessionsettings": { "SHAOPSettings": {
363 "participants": [ ],
364 "deadline": { "deadlinerounds": { "rounds": 10, "durationms": 10000 } } } } } }
365 </code>
[1]366 */
367 function start() {
368 var npersession = document.getElementById("partiespersession").value;
369
370 if (parties.length < npersession || npersession <2) {
371 alert("At least "+npersession+" parties are needed.");
372 return;
373 }
374
375 if (profiles.length < npersession) {
376 alert("At least "+npersession+" profiles are needed.");
377 return;
378 }
379
380 // see https://www.w3schools.com/xml/dom_httprequest.asp
381 var xmlHttp = new XMLHttpRequest();
382 xmlHttp.onreadystatechange = function() {
383 if (this.readyState == 4) {
384 if (this.status == 200) {
385 document.getElementById("startbutton").disabled=true;
386 document.getElementById("started").setAttribute("style","");
387 document.getElementById("logref").href="log/"+this.responseText+".json";
[9]388 document.getElementById("plotref").href="utilstable.xhtml?"+this.responseText;
[1]389 } else
390 alert("request failed:"+this.statusText);
391 }
392 }
393 xmlHttp.open("POST", "run", true);
394 xmlHttp.send(makeRequest());
395 }
396
397 /**
398 @return a json request package containing a AllPermutationsSettings
399 */
400 function makeRequest() {
401 var deadline={};
402 var value = document.getElementById("deadlinevalue").value;
403 var dtypecombo = document.getElementById("deadlinetype");
404 if (dtypecombo.options[dtypecombo.selectedIndex].value=="TIME") {
405 deadline["deadlinetime"] = { "durationms": 1000*value};
406 } else {
407 // ROUNDS
408 deadline["deadlinerounds"] = {"rounds": value, "durationms": 10000};
409 }
[8]410 var reuseParties = document.getElementById("reuseparties").checked;
[1]411
[8]412 var protocolcombobox = document.getElementById("protocolselection");
413 var protocol = protocolcombobox.options[protocolcombobox.selectedIndex].value;
414 var header=protocol+"Settings";
415
416 // create S(H)AOPSettings. [header] is a weird ECMA script workaround for javascript issue.
417 var sessionSettings = { [header]:{"participants":[],"deadline":deadline}};
[1]418 return JSON.stringify({"AllPermutationsSettings":{"parties":parties,"profiles":profiles,"reuseParties":reuseParties,"partiesPerSession":2,"sessionsettings":sessionSettings}});
419 }
420
421 /**
422 Initialize the page after html is loaded.
423 */
424 function init() {
[10]425 document.getElementById("partiesserverurl").value =window.location.hostname+":8080/partiesserver-1.3.0";
426 document.getElementById("profilesserverurl").value =window.location.hostname+":8080/profilesserver-1.3.0";
[2]427
428
[1]429 connectDomain();
430 connectParties();
431 }
432
433
434 ]]>
435
436
437
438
[6]439
[1]440</script>
441
442</html>
Note: See TracBrowser for help on using the repository browser.