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

目前為 2016-03-19 提交的版本,檢視 最新版本

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