ATC-SIM Helper for Chrome

Ver 1.6b Highlights planes and strips on mouseover and allows multiple commands to be issued in one line. Adds ability to assign routes to planes

  1. // ==UserScript==
  2. // @name ATC-SIM Helper for Chrome
  3. // @namespace atchelper
  4. // @include http://www.atc-sim.com/atc.php
  5. // @include http://atc-sim.com/atc.php
  6. // @include http://www.atc-sim.com/simulator
  7. // @include http://atc-sim.com/simulator
  8. // @version 1.7
  9. // @description Ver 1.6b Highlights planes and strips on mouseover and allows multiple commands to be issued in one line. Adds ability to assign routes to planes
  10. // ==/UserScript==
  11. // Notes
  12.  
  13. // v1.7 fixed URL issue
  14.  
  15. // v1.6a
  16. // fixed bug that did not show "simple" command results in status bar
  17.  
  18. // v1.6
  19. // Edited for use in chrome using tampermonkey
  20. // Added a statusbar since chrome does not have one
  21.  
  22.  
  23. // v1.5
  24. // Fixed bug that did not properly clear out a plane's route if you commanded a different route before the first one was complete.
  25.  
  26. // v1.4
  27. // added ablity to specify a vector as the last waypoint in a route
  28. // fixed bug that kept script from working when using the non www URL
  29.  
  30. // v1.3
  31. // Corrected readback function for all commands. Now reads back results of all commands in a combo command
  32. // added ability to issue multipe waypoint clearance (V command) to planes and they will fly to the points in order
  33. // added up arrow now repeats the previous command with the plane you just clicked
  34. // L and R commands after a heading work now
  35.  
  36. // v1.2
  37. // Fixed bug that stopped readback working on single commands
  38.  
  39. // v1.1
  40. // added ability to issue multiple "C" commands on one line
  41. // Fixed bug that confused speed and heading
  42.  
  43. // v1.0
  44. // Highlights plane on mouseover of progress strip, highlight progress strip on mouseover of plane
  45.  
  46. unsafeWindow.g_fn = new Array();
  47. unsafeWindow.g_fnPl = new Array();
  48. unsafeWindow.g_routes = new Array();
  49. unsafeWindow.g_lastcmd = "";
  50.  
  51. unsafeWindow.fnAddMoStripEvent = function()
  52. {
  53. var objProgressStrips = unsafeWindow.frames["ProgressStrips"].document.getElementById("strips");
  54. var id,cnt;
  55. divs = unsafeWindow.frames["ProgressStrips"].document.getElementsByTagName("div");
  56. txt = divs.length;
  57.  
  58. for(var i = 0; i < divs.length; i++)
  59. {
  60. id = divs[i].id;
  61. if(unsafeWindow.g_fn[id] != true)
  62. {
  63. txt += id + ":true, ";
  64. unsafeWindow.g_fn[id] = true;
  65. divs[i].addEventListener( "mouseover", function() {fnPlaneHighlite(id);}, false);
  66. divs[i].addEventListener( "mouseout", function() {fnPlaneLowlite(id);}, false);
  67. }
  68. else
  69. txt += id + ":false, ";
  70. }
  71. }
  72.  
  73.  
  74. unsafeWindow.fnAddMoPlaneEvent = function()
  75. {
  76. var objProgressStrips = unsafeWindow.document.getElementById("strips");
  77. var id,cnt;
  78. divs = unsafeWindow.document.getElementsByClassName("SanSerif12");
  79. txt = divs.length;
  80.  
  81. for(var i = 0; i < divs.length; i++)
  82. {
  83. id = divs[i].id;
  84. if(unsafeWindow.g_fnPl[id] != true)
  85. {
  86. txt += id + ":true, ";
  87. unsafeWindow.g_fnPl[id] = true;
  88. divs[i].addEventListener( "mouseover", function() {fnStripHighlite(id);}, false);
  89. divs[i].addEventListener( "mouseout", function() {fnStripLowlite(id);}, false);
  90. }
  91. else
  92. txt += id + ":false, ";
  93. }
  94. }
  95.  
  96.  
  97. function fnPlaneHighlite(id)
  98. {
  99. var pln = unsafeWindow.document.getElementById(id);
  100. pln.style.color = "yellow";
  101. pln.style.fontWeight = "bold";
  102. }
  103.  
  104. function fnPlaneLowlite(id)
  105. {
  106. var pln = unsafeWindow.document.getElementById(id);
  107. pln.style.color = "white";
  108. pln.style.fontWeight = "normal";
  109. }
  110.  
  111.  
  112. function fnStripHighlite(id)
  113. {
  114. var pln = unsafeWindow.frames["ProgressStrips"].document.getElementById(id);
  115. pln.style.border = "1px solid red";
  116. }
  117.  
  118. function fnStripLowlite(id)
  119. {
  120. var pln = unsafeWindow.frames["ProgressStrips"].document.getElementById(id);
  121. pln.style.border = "1px solid white";
  122. }
  123.  
  124.  
  125. // ***************************
  126. // intercept the form submit and parse the commands ourself
  127. // ***************************
  128. function fnReProcess(e)
  129. {
  130. var x,cnt,y,v,i,w,z;
  131. var txt = new Array();
  132. var found ;
  133. var test;
  134. var r = new Array();
  135. w="";
  136. var waypoints = false;
  137. if(e.keyCode == 38)
  138. { // up arrow... repeat previous command
  139. unsafeWindow.document.frmClearance.txtClearance.value += unsafeWindow.g_lastcmd.substr(unsafeWindow.g_lastcmd.indexOf(" ")) ;
  140. }
  141. if(e.keyCode == 27)
  142. { // esc
  143. unsafeWindow.document.frmClearance.txtClearance.value = "";
  144. }
  145. if(e.keyCode == 13)
  146. {
  147. v = unsafeWindow.document.frmClearance.txtClearance.value;
  148. unsafeWindow.g_lastcmd = v;
  149. var inArr = v.toUpperCase().split(/\s+/);
  150. // split it up into separate commands.
  151. if(inArr[1] == "C")
  152. { // is it C
  153. cnt = 0;
  154. // we know next var goes with the C, whether it is a speed, dir, or waypoint
  155. for(x=2;x < inArr.length;x++)
  156. {
  157. if(inArr[x] != "")
  158. { // not blank
  159. if((inArr[x] != "S") && (inArr[x] != "X") && (inArr[x] != "EX") && (inArr[x] != "T") && (inArr[x] != "H") && (inArr[x] != "V"))
  160. {
  161. if(waypoints == true)
  162. { // we are reading waypoints into the route
  163. y=0;
  164. found = false;
  165. w = " Routed via: ";
  166. for(z=x;z < inArr.length;z++)
  167. { // store the route
  168. if(!isNaN(inArr[z]) && (inArr[z].length == 3) )
  169. { // its a vector
  170. if((z+1)!=inArr.length)
  171. { // we aren't at the last entry in the route, throw an error
  172. myStatusBar.innerHTML = "Vector must be last entry in route.";
  173. unsafeWindow.document.frmClearance.txtClearance.value = "";
  174. e.preventDefault();
  175. return false;
  176. }
  177. r[y] = inArr[z]; // store the vector
  178. y++;
  179. w += inArr[z];
  180. if((z+1)<inArr.length)
  181. w += "->";
  182. }
  183. else
  184. { // its a waypoint
  185. for (i = 0; i < unsafeWindow.G_arrNavObjects.length; i++)
  186. {
  187. if ((unsafeWindow.G_arrNavObjects[i][0] == inArr[z]) && (unsafeWindow.G_arrNavObjects[i][1] > 0))
  188. { // found the nav id and it's not a runway
  189. r[y] = inArr[z]; // store the NAVID
  190. y++;
  191. found = true;
  192. w += inArr[z];
  193. if((z+1)<inArr.length)
  194. w += "->";
  195. }
  196. }
  197. if(found == false)
  198. { // throw an error
  199. myStatusBar.innerHTML = inArr[z] + " is not a valid NAVID";
  200. unsafeWindow.document.frmClearance.txtClearance.value = "";
  201. e.preventDefault();
  202. return false;
  203. }
  204. }
  205. found = false;
  206. }
  207. x=z; // dont process any more
  208. // if we get here, then all the NAVIDs were valid
  209. // declare the route var
  210. //alert(typeof unsafeWindow.g_routes[inArr[0]]);
  211. if(typeof unsafeWindow.g_routes[inArr[0]] === "undefined")
  212. {
  213. unsafeWindow.g_routes[inArr[0]] = {'rindx':0, 'route':Array()};
  214. }
  215. for(z=0;z < r.length;z++)
  216. { // set the route for this plane. We double buffer in case the navid list has an error, it will not overwrite existing route
  217. unsafeWindow.g_routes[inArr[0]]['route'][z] = r[z];
  218. }
  219. unsafeWindow.g_routes[inArr[0]]['rindx'] = 0;
  220. // set the waypoint to the first one in the list
  221. txt[cnt] = inArr[0] + " C " + unsafeWindow.g_routes[inArr[0]]['route'][0];
  222. cnt++;
  223. }
  224. else
  225. { // not a waypoint
  226. // check to see if we should cancel a route clearance
  227. if(isNaN(inArr[x]) || (inArr[x].length == 3))
  228. { // its a waypoint or vector
  229. if(typeof unsafeWindow.g_routes[inArr[0]] !== "undefined")
  230. {
  231. delete unsafeWindow.g_routes[inArr[0]];
  232. w += " Route Clearance Canceled";
  233. }
  234. }
  235. if(inArr.length > (x+1))
  236. { // if theres something after this command
  237. // see if there is a trailing L or R
  238. if((inArr[x+1] == "L") || (inArr[x+1] == "R"))
  239. {
  240. txt[cnt] = inArr[0] + " " + inArr[1] + " " + inArr[x] + " " + inArr[x+1]; // [PLANEID] C [whatever the next command is] [L|R]
  241. cnt++;
  242. x++;
  243. }
  244. else
  245. {
  246. txt[cnt] = inArr[0] + " " + inArr[1] + " " + inArr[x]; // [PLANEID] C [whatever the next command is]
  247. cnt++;
  248. }
  249. }
  250. else
  251. { // nothing after this command so just put out the command
  252. txt[cnt] = inArr[0] + " " + inArr[1] + " " + inArr[x]; // [PLANEID] C [whatever the next command is]
  253. cnt++;
  254. }
  255. }
  256. }
  257. else
  258. {
  259. if(inArr[x] == "S")
  260. { // speed command
  261. if(inArr.length > (x+1))
  262. { // make sure theres something after the S
  263. txt[cnt] = inArr[0] + " S " + inArr[x+1]; // [PLANEID] S [whatever the next command is]
  264. cnt++;
  265. x++;
  266. }
  267. }
  268. if((inArr[x] == "X") || (inArr[x] == "EX"))
  269. { // Expidite all commands
  270. for(y=0;y<txt.length;y++)
  271. {
  272. txt[y] += " X";
  273. }
  274. }
  275. if(inArr[x] == "T")
  276. { // takeoff command
  277. txt[cnt] = inArr[0] + " T"; // [PLANEID] T
  278. cnt++;
  279. }
  280. if(inArr[x] == "H")
  281. { // hold command
  282. txt[cnt] = inArr[0] + " H"; // [PLANEID] H
  283. cnt++;
  284. }
  285. if(inArr[x] == "V")
  286. { // Next entries in the command are waypoints.
  287. waypoints = true;
  288. }
  289. }
  290. }
  291. }
  292. // send all the commands
  293. var winl,stat;
  294. for(y=0;y<(txt.length);y++)
  295. {
  296. unsafeWindow.document.frmClearance.txtClearance.value = txt[y];
  297. unsafeWindow.fnParseInput();
  298. if(y == 0)
  299. {
  300. //alert(window.status);
  301. winl = window.status + " ";
  302. }
  303. else
  304. {
  305. stat = window.status;
  306. winl += stat.substr(stat.indexOf(" ")) + " ";
  307. }
  308. }
  309. unsafeWindow.document.frmClearance.txtClearance.value = "";
  310. myStatusBar.innerHTML = winl + w;
  311. e.preventDefault();
  312. }
  313. else
  314. { // just a simple command
  315. //alert(window.status);
  316. unsafeWindow.fnParseInput();
  317. //alert(window.status);
  318. myStatusBar.innerHTML = window.status;
  319. e.preventDefault();
  320. }
  321. }
  322. return false;
  323. }
  324.  
  325.  
  326. function fnMyDistance(strFlightID, intObjectID)
  327. {
  328. if(typeof unsafeWindow.G_arrNavObjects[intObjectID] !== "undefined")
  329. {
  330. return Math.sqrt(Math.pow((unsafeWindow.G_objPlanes[strFlightID][2] + unsafeWindow.intXoffset - unsafeWindow.G_arrNavObjects[intObjectID][2]),2) + Math.pow((unsafeWindow.G_objPlanes[strFlightID][3] + unsafeWindow.intYoffset - unsafeWindow.G_arrNavObjects[intObjectID][3]),2));
  331. }
  332. else
  333. {
  334. return "x";
  335. }
  336. }
  337.  
  338. unsafeWindow.fnWPCheck = function()
  339. {
  340. var cnt,ID,txt,d;
  341. var cnt ="";
  342. d = new String();
  343. for(ID in unsafeWindow.G_objPlanes)
  344. {
  345. if(typeof unsafeWindow.g_routes[ID] !== "undefined")
  346. { // this plane has a route
  347. if((unsafeWindow.G_objPlanes[ID][7] == 0) && unsafeWindow.G_objPlanes[ID][11] === null)
  348. { // we've reached a waypoint.
  349. if(unsafeWindow.g_routes[ID]['route'].length > unsafeWindow.g_routes[ID]['rindx']+1)
  350. { // theres another waypoint in the route
  351. unsafeWindow.g_routes[ID]['rindx']++;
  352. txt = unsafeWindow.document.frmClearance.txtClearance.value;
  353. unsafeWindow.document.frmClearance.txtClearance.value = ID + " C " + unsafeWindow.g_routes[ID]['route'][unsafeWindow.g_routes[ID]['rindx']];
  354. unsafeWindow.fnParseInput();
  355. unsafeWindow.document.frmClearance.txtClearance.value = txt;
  356. }
  357. }
  358. }
  359. }
  360. if(cnt)
  361. myStatusBar.innerHTML = cnt
  362. }
  363.  
  364.  
  365. unsafeWindow.fnCleanup = function()
  366. { // cleans up vars created in GM when planes are no longer on screen
  367. var ID,cnt;
  368. // planes
  369. for(ID in unsafeWindow.g_fnPl)
  370. {
  371. if(!unsafeWindow.document.getElementById(ID))
  372. {
  373. delete unsafeWindow.g_fnPl[ID]
  374. }
  375. }
  376. // progress strips
  377. for(ID in unsafeWindow.g_fn)
  378. {
  379. if(!unsafeWindow.frames["ProgressStrips"].document.getElementById(ID))
  380. {
  381. delete unsafeWindow.g_fn[ID]
  382. }
  383. }
  384. // routes
  385. for(ID in unsafeWindow.g_routes)
  386. {
  387. if(!unsafeWindow.document.getElementById(ID))
  388. {
  389. delete unsafeWindow.g_routes[ID]
  390. }
  391. }
  392. }
  393. var canvasbody, myStatusBar;
  394. canvasbody = document.getElementById('canvas');
  395. if (canvasbody) {
  396. // create our own "status bar"
  397. myStatusBar = document.createElement('div');
  398. myStatusBar.innerHTML = "Welcome to ATC-SIM";
  399. myStatusBar.setAttribute("id", "myStatus");
  400. myStatusBar.style.position="fixed";
  401. myStatusBar.style.bottom="0";
  402. myStatusBar.style.left="0";
  403. myStatusBar.style.padding= "1px 4px 1px 3px";
  404. myStatusBar.style.fontSize="12px";
  405.  
  406. myStatusBar.style.backgroundColor = "#cccccc";
  407. canvasbody.insertBefore(myStatusBar, canvasbody.firstChild);
  408. }
  409.  
  410.  
  411. setInterval ( "fnAddMoStripEvent()", 2000 );
  412. setInterval ( "fnAddMoPlaneEvent()", 2000 );
  413. setInterval ( "fnWPCheck()", 2000 );
  414.  
  415. setInterval ( "fnCleanup()", 5000 );
  416.  
  417. unsafeWindow.document.frmClearance.txtClearance.addEventListener( "keydown", fnReProcess, false);