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-06-14 提交的版本,檢視 最新版本

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