source: src/main/webapp/newsession.xhtml@ 5

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

Fix consistency check LinearAdditiveUtilitySpace

File size: 11.8 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>Session</h1>
10
11 On this page you can configure the settings for running a new session
12 and start the session.
13
14 <br /> Protocol:
15 <select>
16 <option value="SAOP">SAOP</option>
17 </select>
18
19 <br /> Deadline:
20 <input type="number" id="deadlinevalue" name="deadline" min="1"
21 max="10000" value="10" />
22 <select id="deadlinetype">
23 <option value="TIME">seconds</option>
24 <option value="ROUNDS">rounds</option>
25 </select>
26
27 <br /> Domain/Profile Server:
28 <input type="url" name="url" id="profilesserverurl"
29 value="localhost:8080/profilesserver-1.0.0"
30 pattern=".*:[0-9]+/profilesserver" size="30"
31 onchange="connectDomain()"> </input>
32 <br /> Domain:
[2]33 <select id="domainselection" onchange="selectDomain()">
[1]34 <!-- <option>Waiting for profiles server</option> -->
35 </select>
36
37 <br />
38 <br />
39
40 <div id="box" class="box">
41 <br /> <b>Participants</b> <br /> Parties Server: <input type="url"
[4]42 name="url" id="partiesserverurl"
43 value="localhost:8080/partiesserver-1.0.0"
[1]44 pattern=".*:[0-9]+/partiesserver" size="30"
[4]45 onchange="connectParties()"> </input> <br /> <br /> <b>Edit
46 next party</b> <br /> Party: <select id="partyselection">
[1]47 </select> <br /> Profile: <select id="profileselection">
48 </select> <br />
49
50 <button onclick="addParty()">Add</button>
51
52
53 <br /> <br /> <b>Selected Profiles, Parties for the session</b>
54 <table>
55 <thead>
56 <th align="left" width='40%'>Party</th>
57 <th align="left" width='40%'>Profile</th>
58 </thead>
59 <tbody id="partiesList">
60 <tr id="partiesList">
61 </tr>
62
63 </tbody>
64 </table>
65
66 </div>
67
68 <form>
69 <input id="startbutton" type="button" value="Start Session"
70 onclick="start()" />
71 </form>
72
73 <div id="started" style="visibility: hidden">
[4]74 Your session started. Waiting for the results. <br />
75 </div>
76 <div id="results" style="visibility: hidden">
[5]77 Session completed. <a href="" id="logref">view the log
[1]78 file</a> <br /> <a href="" id="plotref">render a utilities plot</a>.
79 </div>
80
81</body>
82
83<script type="application/javascript">
84
85
[2]86
[4]87
[1]88 // FIXME quick and dirty code. No clean MVC
89
90
91 <![CDATA[
[2]92 //"use strict";
[1]93
94 var domainwebsocket = null;
95 var partieswebsocket=null;
96 // currently known domains (and profiles) as coming from domainwebsocket.
97 // keys are domain names, values are list of profile names
98 var knowndomains={};
99
100 /**
101 List of created participants for the session. Each participant is a dictionary.
102 Each dict element contains keys
103 "party" and "profile", both containing a String containing
104 a valid IRI to the party resp. the profile to use.
105 The party should contain a IRI that gives a new instance of the required party.
106 The profile should contain an IRI that gives the profile contents.
107 */
108 var partyprofiles=[];
109
[2]110 /** from http://fitzgeraldnick.com/2010/08/10/settimeout-patterns.html */
111
112 function async (fn) {
113 setTimeout(fn, 1000);
114 }
115
116 function sometimeWhen (test, then) {
117 async(function () {
118 if ( test() ) {
119 then();
120 } else {
121 async(arguments.callee);
122 }
123 });
124 }
125
126
127
[1]128 /**
129 Refresh known domains using given profilesserver URL.
130 Called when user enters URL for domain server.
131 */
132 function connectDomain() {
133 if (domainwebsocket!=null) {
134 domainwebsocket.close();
135 domainwebsocket=null;
136 }
137 var url=document.getElementById("profilesserverurl").value;
138 var target = "ws://"+url+"/websocket/liststream";
139 if ('WebSocket' in window) {
140 domainwebsocket = new WebSocket(target);
141 } else if ('MozWebSocket' in window) {
142 domainwebsocket = new MozWebSocket(target);
143 } else {
144 alert('WebSocket is not supported by this browser. Please use a newer browser');
145 return;
146 }
147 domainwebsocket.onopen = function () {
148 // whatever.
149 };
150 domainwebsocket.onmessage = function (event) {
151 updateDomainComboBox(JSON.parse(event.data));
152 };
153 domainwebsocket.onclose = function (event) {
154 alert('Info: Server closed connection. Code: ' + event.code +
155 (event.reason == "" ? "" : ", Reason: " + event.reason));
156 domainwebsocket=null;
157 updateDomainComboBox({});
158 };
159 }
160
161 /**
162 Sets a new knowndomains value and Updates the contents of the domain selector combobox.
163 @param the known domains, a map of the form {"jobs":["jobs1","jobs2"]}
164 where the keys are the names of the available domains nd the values a list of the available profiles in that domain.
165
166 */
167 function updateDomainComboBox(newdomains) {
168 knowndomains=newdomains
169 var combobox = document.getElementById("domainselection");
170 combobox.options.length=0;
171 for (var domain in knowndomains) {
172 var option = document.createElement('option');
173 option.text = option.value = domain;
174 combobox.add(option, 0);
175 }
176 selectDomain();
177 }
178 /**
179 Refresh known parties using given partiesserver URL.
180 Called when user enters URL for parties server.
181 */
182 function connectParties() {
183 if (partieswebsocket!=null) {
184 partieswebsocket.close();
185 partieswebsocket=null;
186 }
187 var url=document.getElementById("partiesserverurl").value;
188 var target = "ws://"+url+"/available";
189 if ('WebSocket' in window) {
190 partieswebsocket = new WebSocket(target);
191 } else if ('MozWebSocket' in window) {
192 partieswebsocket = new MozWebSocket(target);
193 } else {
194 alert('WebSocket is not supported by this browser. Please use a newer browser');
195 return;
196 }
197 partieswebsocket.onopen = function () {
198 // whatever.
199 };
200 partieswebsocket.onmessage = function (event) {
201 updateParties(JSON.parse(event.data));
202 };
203 partieswebsocket.onclose = function (event) {
204 alert('Info: Server closed connection. Code: ' + event.code +
205 (event.reason == "" ? "" : ", Reason: " + event.reason));
206 partieswebsocket=null;
207 updateParties({});
208 };
209 }
210
211
212 /**
213 refresh table: copy all parties elements in there.
214 Typically parties is something like
215 [{"uri":"http:130.161.180.1:8080/partiesserver/run/randomparty-1.0.0",
216 "capabilities":{"protocols":["SAOP"]},
217 "description":"places random bids until it can accept an offer with utility >0.6",
218 "id":"randomparty-1.0.0",
219 "partyClass":"geniusweb.exampleparties.randomparty.RandomParty"},
220 ...]
221 */
222 function updateParties(parties) {
223 var combobox = document.getElementById("partyselection");
224 combobox.options.length=0;
225 for (var party in parties) {
226 var option = document.createElement('option');
227 option.text = option.value = parties[party].uri;
228 combobox.add(option, 0);
229 }
230 }
231
232
233
234
235 /**
236 Called when the selected domain changes. Assumes knowndomains has been set.
237 Updates the available profiles in the profile combobox.
238 @param selection the name of the selected domain.
239 */
240 function selectDomain() {
241 // determined current selection
242 var domaincombobox = document.getElementById("domainselection");
243 if (domaincombobox.options.length==0) return; // fixme clean profiles options?
244 var domain = domaincombobox.options[domaincombobox.selectedIndex].value;
245
246 var profilecombo = document.getElementById("profileselection");
247 profilecombo.options.length=0;
248 for (var profile in knowndomains[domain]) {
249 var option = document.createElement('option');
250 option.text = option.value = knowndomains[domain][profile];
251 profilecombo.add(option, 0);
252 }
253 }
254
255 /**
256 Called when user clicks "Add"
257 */
258 function addParty() {
259 var partycombo = document.getElementById("partyselection");
260 var profilecombo = document.getElementById("profileselection");
261
262 if (partycombo.options.length==0) {
263 alert("Please set partier server and select a party");
264 return;
265 }
266 if (profilecombo.options.length==0) {
267 alert("Please set domain/profile server and select a domain and a profile");
268 return;
269 }
270 var newpartyprof = {};
271 newpartyprof["party"]=partycombo.options[partycombo.selectedIndex].value;
272 newpartyprof["profile"]=profilecombo.options[profilecombo.selectedIndex].value;
273
274 partyprofiles.push(newpartyprof)
275 updatePartyProfileTable(); // what, MVC?
276 }
277
278 /** updates the party and profiles table, to match the #partyprofiles list. */
279 function updatePartyProfileTable() {
280 var table = document.getElementById("partiesList");
281 table.innerHTML = ""; // clear table
282 for ( var pp in partyprofiles) {
283 var row = table.insertRow(-1);
284 var cell1 = row.insertCell(-1);
285 var cell2 = row.insertCell(-1);
286 cell1.innerHTML = partyprofiles[pp]["party"];
287 cell2.innerHTML = partyprofiles[pp]["profile"];
288 }
289
290 }
291
[2]292 var x=1;
[1]293 /**
294 start the session as currently set on this page.
295 We need to send a SessionSettings object to the server, which typically looks like this
296 but is protocol dependent (currently we do SAOP)
297
298 {"SAOPSettings":
299 {"participants":[
300 {"party":"http://party1","profile":"ws://profile1"},
301 {"party":"http://party2","profile":"ws://profile2"}],
302 "deadline":{"deadlinetime":{"durationms":100}}}}
303
304 participants are already in the global partyprofiles dictionary
305 */
306 function start() {
307 if (Object.keys(partyprofiles).length <2) {
308 alert("At least 2 parties are needed to run a session.");
309 return;
310 }
311
312 // see https://www.w3schools.com/xml/dom_httprequest.asp
[5]313 document.getElementById("startbutton").disabled=true;
314 document.getElementById("started").setAttribute("style","");
315
316 var xmlHttp = new XMLHttpRequest();
[1]317 xmlHttp.onreadystatechange = function() {
318 if (this.readyState == 4) {
319 if (this.status == 200) {
[4]320 var logurl="log/"+this.responseText+".json";
321 document.getElementById("logref").href=logurl;
[1]322 document.getElementById("plotref").href="plotlog.xhtml?id="+this.responseText;
323
[4]324 sometimeWhen(function() { return urlExists(logurl) },
325 function() { document.getElementById("results").setAttribute("style",""); });
[2]326
[1]327 }
328 else
329 alert("request failed:"+this.statusText);
330 }
331 }
332 xmlHttp.open("POST", "run", true);
333 xmlHttp.send(makeRequest());
334
335 }
336
[4]337
338 /**
339 @return true iff the URL exists.
340 */
341 function urlExists(urlToFile) {
342 // Warning. Synchronous XMLHttpRequest on the main thread is
343 // deprecated because of its detrimental effects to the end user’s
344 // experience. For more help http://xhr.spec.whatwg.org/
345 var xhr = new XMLHttpRequest();
346 xhr.open('HEAD', urlToFile, false);
347 xhr.send();
348
349 return (xhr.status == "200")
350 }
[1]351
352 /**
353 @return a json request package for the run server
354 */
355 function makeRequest() {
356 var deadline={};
357 var value = document.getElementById("deadlinevalue").value;
358 var dtypecombo = document.getElementById("deadlinetype");
359 if (dtypecombo.options[dtypecombo.selectedIndex].value=="TIME") {
360 deadline["deadlinetime"] = { "durationms": 1000*value};
361 } else {
362 // ROUNDS
363 deadline["deadlinerounds"] = {"rounds": value, "durationms":10000};
364 }
365
366
367 return JSON.stringify({"SAOPSettings": { "participants": partyprofiles, "deadline":deadline }});
368
369 }
370
371
372 /**
373 Initialize the page after html is loaded.
374 */
375 function init() {
[2]376 document.getElementById("partiesserverurl").value =window.location.hostname+":8080/partiesserver-1.0.0"
377 document.getElementById("profilesserverurl").value =window.location.hostname+":8080/profilesserver-1.0.0"
[1]378 connectDomain();
379 connectParties();
380
381 }
382 ]]>
383
384
[4]385
[1]386</script>
387
388</html>
Note: See TracBrowser for help on using the repository browser.