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

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

Small fixes

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