show.js
  1  
  2  var g_sim_logs = '';
  3  var g_my_login = 0;
  4  var g_rand_prev;
  5  var g_rand_repl = [];
  6  var g_eval_lvls;
  7  
  8  
  9  function my_console_log(str)
 10  {
 11  //    console.log(str);
 12  }
 13  
 14  
 15  function hash_login(login)
 16  {
 17      var seed = 0;
 18      for (var i = 0; i < login.length; i ++)
 19      {
 20  	if (i%2 == 0)
 21  	    seed += 973 * (login.charCodeAt(i)+i);
 22  	else
 23  	    seed += 5 * login.charCodeAt(i) * i;
 24      }
 25  //    console.log("hash login : '"+login+"' -> "+seed);
 26      return (seed);
 27  }
 28  
 29  
 30  function err(thetype, field)
 31  {
 32      my_console_log("Fatal error in "+thetype+", on field "+field);
 33      throw '';
 34  }
 35  
 36  
 37  function my_random(a, b)
 38  {
 39      if (g_my_login == '')
 40  	return (Math.round(parseInt(a) + (parseInt(b)-parseInt(a))*Math.random()));
 41      var prev = g_rand_prev;
 42      prev ^= prev << 13;
 43      prev ^= prev >> 17;
 44      prev ^= prev << 5;
 45      g_rand_prev = prev;
 46      prev = (prev & 0x7FFFFFFF) % (parseInt(b)-parseInt(a)+1);
 47      return (Math.round(parseInt(a) + prev));
 48  }
 49  
 50  function random_repl(str)
 51  {
 52      var regex = /\[(\d+)-(\d+)\]([a-z])/g;
 53      var res;
 54      var str2 = str;
 55      while (res = regex.exec(str))
 56      {
 57  	my_console_log(res);
 58  	g_rand_repl[res[3]] = my_random(res[1], res[2]);
 59  	str2 = str2.replace(res[0], ""+g_rand_repl[res[3]]);
 60  	my_console_log(str2);
 61      }
 62      regex = /\[([a-z])\]/g;
 63      while (res = regex.exec(str))
 64      {
 65  	my_console_log(res);
 66  	if (g_rand_repl[res[1]] != null)
 67  	{
 68  	    str2 = str2.replace(res[0], ""+g_rand_repl[res[1]]);
 69  	    my_console_log(str2);
 70  	}
 71  	else
 72  	    return (null);
 73      }
 74  
 75      if (str2 == "default") return (str2);
 76      // check if any non digital, non dot, non slash char, except previous line
 77      regex = /[^\d\.\/]/g;
 78      if (regex.exec(str2))
 79  	return (null);
 80      
 81      return (str2);
 82  }
 83  
 84  function show_host(root, h)
 85  {
 86      if (!h['id']) err("hosts", "id");
 87      if (!h['type']) err("hosts id "+h['id'], "type");
 88      if (!h['name']) err("hosts id "+h['id'], "name");
 89      if (!h['geometry']) err("hosts id "+h['id'], "geometry");
 90      if (!h['img']) err("hosts id "+h['id'], "img");
 91  
 92      var tab = h['geometry'].split(/[^0-9]+/);
 93      if (tab.length != 4) err("hosts id "+h['id'], "geometry parsing");
 94      h['w'] = parseInt(tab[0]);
 95      h['h'] = parseInt(tab[1]);
 96      h['x'] = parseInt(tab[2]);
 97      h['y'] = parseInt(tab[3]);
 98      
 99      var newelem = document.createElement('div');
100      newelem.className = 'host_div';
101      newelem.style.position = "absolute";
102      newelem.style.width = h['w']+'px';
103      newelem.style.height = h['h']+'px';
104      newelem.style.top = h['y'] + 'px';
105      newelem.style.left = h['x'] + 'px';
106      newelem.style.backgroundImage = 'url(img/'+h['img']+')';
107      root.appendChild(newelem);
108  
109      // label + routes
110      var tab = h['labelpos'].split(',');
111      if (tab.length != 2) err("host id "+h['id'], "labelpos parsing");
112      h['lx'] = parseInt(tab[0]);
113      h['ly'] = parseInt(tab[1]);
114  
115      var newelem = document.createElement('div');
116      newelem.className = 'host_info_div';
117      newelem.style.position = "absolute";
118      newelem.style.top = (h['y']+h['ly'])+'px';
119      newelem.style.left = (h['x']+h['lx'])+'px';
120      var label = '<table><tr><td>'+h['type']+' '+h['id']+': <i>'+h['name']+'</id></td></tr>';
121      var str = '';
122      routes.forEach(r => {if (h['id'] == r['hid']) { str += '<tr><td>'+get_route_info(r)+'</td></tr>\n'; r['h'] = h;}});
123      if (str != '') label += '<tr><td>Routes :</td></tr>\n'+str;
124      label += '</table>';
125      newelem.innerHTML = label;
126      root.appendChild(newelem);
127      
128  }
129  
130  
131  
132  function get_route_info(r)
133  {
134      if (!r['rid']) err("route", "rid");
135      if (!r['hid']) err("route id "+r['rid'], "hid");
136      if (!r['route']) err("route id "+r['rid'], "route");
137      if (!r['route_edit']) err("route id "+r['rid'], "route_edit");
138      if (!r['gate']) err("route id "+r['rid'], "gate");
139      if (!r['gate_edit']) err("route id "+r['rid'], "gate_edit");
140  
141      if ((r['route'] = random_repl(r['route'])) == null) err("route id "+r['rid'], "route ip random syntax");
142      if ((r['gate'] = random_repl(r['gate'])) == null) err("route id "+r['rid'], "gate random syntax");
143      
144      if (r['route_edit'] == 'true') route_active = ''; else route_active = 'disabled';
145      if (r['gate_edit'] == 'true') gate_active = ''; else gate_active = 'disabled';
146      var routestr = '<input size=15 type=text id=route_'+r['rid']+' value="'+r['route']+'" '+route_active+'> =&gt; <input size=15 type=text id=gate_'+r['rid']+' value="'+r['gate']+'" '+gate_active+'>';
147  //    my_console_log("add label route : ##"+routestr);
148      return (routestr);
149  }
150  
151  
152  
153  function show_ifs(root, itf)
154  {
155      if (!itf['if']) err("ifs", "if");
156      if (!itf['hid']) err("ifs "+itf['if'], "hid");
157      if (!itf['ip']) err("ifs "+itf['if'], "ip");
158      if (!itf['mask']) err("ifs "+itf['if'], "mask");
159      if (!itf['ip_edit']) err("ifs "+itf['if'], "ip_edit");
160      if (!itf['mask_edit']) err("ifs "+itf['if'], "mask_edit");
161      if (!itf['type']) err("ifs "+itf['if'], "type");
162      if (!itf['pos']) err("ifs "+itf['if'], "pos");
163  
164      if ((itf['ip'] = random_repl(itf['ip'])) == null) err("ifs "+itf['if'], "ip random syntax");
165      if ((itf['mask'] = random_repl(itf['mask'])) == null) err("ifs "+itf['if'], "mask random syntax");
166      
167      hosts.forEach(h => {if (itf['hid'] == h['id']) itf['h'] = h});
168  
169      var tab = itf['pos'].split(',');
170      if (tab.length != 2) err("ifs id "+itf['if'], "pos parsing");
171      itf['dx'] = parseInt(tab[0]);
172      itf['dy'] = parseInt(tab[1]);
173  
174      if (itf['type'] == 'std')
175      {
176  	var newelem = document.createElement('div');
177  	newelem.className = 'itf_div';
178  	newelem.style.position = "absolute";
179  	newelem.style.top = (itf['h']['y']+itf['dy'])+'px';
180  	newelem.style.left = (itf['h']['x']+itf['dx'])+'px';
181  	if (itf['ip_edit'] == 'true') ip_active = ''; else ip_active = 'disabled';
182  	if (itf['mask_edit'] == 'true') mask_active = ''; else mask_active = 'disabled';
183  	newelem.innerHTML = 'Interface '+itf['if']+'<br />IP : <input size=15 type=text id=ip_'+itf['if']+' value="'+itf['ip']+'" '+ip_active+'><br />Mask : <input size=15 type=text id=mask_'+itf['if']+' value="'+itf['mask']+'" '+mask_active+'>';
184  	root.appendChild(newelem);
185      }
186  }
187  
188  
189  
190  
191  
192  function draw_links(root, l)
193  {
194      if (!l['if1'] || !l['if2']) err("links", "id");
195  
196      ifs.forEach(i => {if (i['if'] == l['if1']) l['e1'] = i});
197      ifs.forEach(i => {if (i['if'] == l['if2']) l['e2'] = i});
198  
199      hosts.forEach(h => {if (h['id'] == l['e1']['hid']) l['h1'] = h});
200      hosts.forEach(h => {if (h['id'] == l['e2']['hid']) l['h2'] = h});
201      
202      var aLine = document.createElementNS('http://www.w3.org/2000/svg', 'line');
203      aLine.setAttribute('id', 'link_'+l['if1']+'_'+l['if2']);
204      aLine.id = 'link_'+l['if1']+'_'+l['if2'];
205      aLine.setAttribute('x1', ""+(parseInt(l['h1']['x'])+parseInt(l['h1']['w'])/2));
206      aLine.setAttribute('y1', ""+(parseInt(l['h1']['y'])+parseInt(l['h1']['h'])/2));
207      aLine.setAttribute('x2', ""+(parseInt(l['h2']['x'])+parseInt(l['h2']['w'])/2));
208      aLine.setAttribute('y2', ""+(parseInt(l['h2']['y'])+parseInt(l['h2']['h'])/2));
209      aLine.setAttribute('stroke', "black");
210      aLine.setAttribute('stroke-width', 3);
211      (document.getElementById('sl')).appendChild(aLine);
212  }
213  
214  
215  function prep_goals(g)
216  {
217      if (!g['id']) err("goals", "id");
218      if (!g['type']) err("goals "+g['id'], "type");
219      if (g['type'] == 'reach')
220      {
221  	if (!g['id1']) err("goals "+g['id'], "id1");
222  	if (!g['id2']) err("goals "+g['id'], "id2");
223  	hosts.forEach(h => {if (h['id'] == g['id1']) g['h1'] = h});
224  	hosts.forEach(h => {if (h['id'] == g['id2']) g['h2'] = h});
225      }
226      if (g['type'] == 'reach_if')
227      {
228  	if (!g['if_id1']) err("goals "+g['id'], "if_id1");
229  	if (!g['if_id2']) err("goals "+g['id'], "if_id2");
230  	ifs.forEach(itf => {if (itf['if'] == g['if_id1']) { g['h1'] = itf['h']; g['if1'] = itf;}});
231  	ifs.forEach(itf => {if (itf['if'] == g['if_id2']) { g['h2'] = itf['h']; g['if2'] = itf;}});
232      }
233  }
234  
235  
236  function next_eval()
237  {
238      if (g_eval_lvls.length >= 3)
239  	return ('end.html');
240      var lvl;
241      do {
242  	lvl = Math.round(6 + 4*Math.random());
243      } while (g_eval_lvls.includes(lvl))
244      g_eval_lvls.push(lvl);
245      localStorage.setItem("g_my_eval", JSON.stringify(g_eval_lvls));
246      return ('level'+lvl+'.html');
247  }
248  
249  
250  function my_download(filename, text)
251  {
252      var element = document.createElement('a');
253      element.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(text));
254      element.setAttribute('download', filename);
255  
256      element.style.display = 'none';
257      document.body.appendChild(element);
258  
259      element.click();
260  
261      document.body.removeChild(element);
262  }
263  
264  function dl_config()
265  {
266      var infos = { 'routes':{}, 'ifs':{} };
267      routes.forEach(elem => { infos['routes'][elem['rid']] = {};
268  			     if (elem['route_edit'] == 'true') infos['routes'][elem['rid']]['route'] = document.getElementById('route_'+elem['rid']).value;
269  			     if (elem['gate_edit'] == 'true') infos['routes'][elem['rid']]['gate'] = document.getElementById('gate_'+elem['rid']).value;
270  			   });
271      ifs.forEach(elem => { infos['ifs'][elem['if']] = {};
272  			  if (elem['ip_edit'] == 'true') infos['ifs'][elem['if']]['ip'] = document.getElementById('ip_'+elem['if']).value;
273  			  if (elem['mask_edit'] == 'true') infos['ifs'][elem['if']]['mask'] = document.getElementById('mask_'+elem['if']).value;
274  			});
275      my_download('level'+level+'.json', JSON.stringify(infos));
276  }
277  
278  
279  function show_goals(g)
280  {
281      g_sim_logs += '******* Goal ID '+g['id']+' ********\n';
282      var div = document.getElementById("goals_id");
283      div.innerHTML += 'Goal '+g['id']+' : ';
284      if (g['type'] == 'reach')
285      {
286  	var obj = sim_goal(g);
287  	div.innerHTML += '<i>'+g['h1']['name']+'</i> need to communicate with <i>'+g['h2']['name']+'</i> - Status : '+obj.text;
288      }
289      if (g['type'] == 'reach_if')
290      {
291  	var obj = sim_goal(g);
292  	div.innerHTML += 'Interface <i>'+g['if1']['if']+'</i> need to communicate with interface <i>'+g['if2']['if']+'</i> - Status : '+obj.text;
293      }
294      div.innerHTML += '<br />\n';
295      return (obj.status);
296  }
297  
298  
299  function all_goals()
300  {
301      if (g_my_login != '')
302  	g_sim_logs = '** generated for login "'+g_my_login+'" **\n';
303      else
304  	g_sim_logs = '** evaluation mode round '+g_eval_lvls.length+'**\n';
305      document.getElementById("goals_id").innerHTML = '<h2>Level '+level+' : </h2>\n';
306      var nb = 0;
307      goals.forEach(elem => nb += show_goals(elem));
308      document.getElementById("goals_id").innerHTML += '<input type=button value="Check again" onclick="all_goals();"> <input type=button value="Get my config" onclick="dl_config();">';
309      if (nb == goals.length)
310      {
311  	if (g_my_login != '')
312  	{
313  	    if (level < 10)
314  		document.getElementById("goals_id").innerHTML += " <input type=button value='Next level' onclick='window.location=\"level"+(level+1)+".html\";'>";
315  	    else
316  		document.getElementById("goals_id").innerHTML += " <input type=button value='Complete !' onclick='window.location=\"end.html\";'>";
317  	}
318  	else
319  	{   // defense case
320  	    document.getElementById("goals_id").innerHTML += " <input type=button value='Next' onclick='window.location=next_eval();'>";
321  	}		
322      }
323      document.getElementById("logs_id").innerHTML = g_sim_logs.replace(/\n/g, '<br />');
324  }
325  
326  
327  function load_board()
328  {
329      if (!(g_my_login = localStorage.getItem("g_my_login")))
330  	g_my_login = ''; // will means evaluation & full random
331      g_rand_prev = level + hash_login(g_my_login); // initialize replayable pseudo random generator
332      if (g_my_login == '')
333  	g_eval_lvls = JSON.parse(localStorage.getItem("g_my_eval"));
334      
335      var root = document.getElementById("root_id");
336  
337      hosts.forEach(elem => show_host(root, elem));
338  
339      ifs.forEach(elem => show_ifs(root, elem));
340      
341      links.forEach(elem => draw_links(root, elem));
342  
343      goals.forEach(elem => prep_goals(elem));
344      all_goals();
345      // only for very first time : don't show any log
346      document.getElementById("logs_id").innerHTML = 'Logs will be displayed here';
347  }