// ==UserScript==
// @name ATC-SIM Helper for Chrome
// @namespace atchelper
// @include http://www.atc-sim.com/atc.php
// @include http://atc-sim.com/atc.php
// @include http://www.atc-sim.com/simulator
// @version 1.6c
// @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
// ==/UserScript==
// Notes
// v1.6a
// fixed bug that did not show "simple" command results in status bar
// v1.6
// Edited for use in chrome using tampermonkey
// Added a statusbar since chrome does not have one
// v1.5
// Fixed bug that did not properly clear out a plane's route if you commanded a different route before the first one was complete.
// v1.4
// added ablity to specify a vector as the last waypoint in a route
// fixed bug that kept script from working when using the non www URL
// v1.3
// Corrected readback function for all commands. Now reads back results of all commands in a combo command
// added ability to issue multipe waypoint clearance (V command) to planes and they will fly to the points in order
// added up arrow now repeats the previous command with the plane you just clicked
// L and R commands after a heading work now
// v1.2
// Fixed bug that stopped readback working on single commands
// v1.1
// added ability to issue multiple "C" commands on one line
// Fixed bug that confused speed and heading
// v1.0
// Highlights plane on mouseover of progress strip, highlight progress strip on mouseover of plane
unsafeWindow.g_fn = new Array();
unsafeWindow.g_fnPl = new Array();
unsafeWindow.g_routes = new Array();
unsafeWindow.g_lastcmd = "";
unsafeWindow.fnAddMoStripEvent = function()
{
var objProgressStrips = unsafeWindow.frames["ProgressStrips"].document.getElementById("strips");
var id,cnt;
divs = unsafeWindow.frames["ProgressStrips"].document.getElementsByTagName("div");
txt = divs.length;
for(var i = 0; i < divs.length; i++)
{
id = divs[i].id;
if(unsafeWindow.g_fn[id] != true)
{
txt += id + ":true, ";
unsafeWindow.g_fn[id] = true;
divs[i].addEventListener( "mouseover", function() {fnPlaneHighlite(id);}, false);
divs[i].addEventListener( "mouseout", function() {fnPlaneLowlite(id);}, false);
}
else
txt += id + ":false, ";
}
}
unsafeWindow.fnAddMoPlaneEvent = function()
{
var objProgressStrips = unsafeWindow.document.getElementById("strips");
var id,cnt;
divs = unsafeWindow.document.getElementsByClassName("SanSerif12");
txt = divs.length;
for(var i = 0; i < divs.length; i++)
{
id = divs[i].id;
if(unsafeWindow.g_fnPl[id] != true)
{
txt += id + ":true, ";
unsafeWindow.g_fnPl[id] = true;
divs[i].addEventListener( "mouseover", function() {fnStripHighlite(id);}, false);
divs[i].addEventListener( "mouseout", function() {fnStripLowlite(id);}, false);
}
else
txt += id + ":false, ";
}
}
function fnPlaneHighlite(id)
{
var pln = unsafeWindow.document.getElementById(id);
pln.style.color = "yellow";
pln.style.fontWeight = "bold";
}
function fnPlaneLowlite(id)
{
var pln = unsafeWindow.document.getElementById(id);
pln.style.color = "white";
pln.style.fontWeight = "normal";
}
function fnStripHighlite(id)
{
var pln = unsafeWindow.frames["ProgressStrips"].document.getElementById(id);
pln.style.border = "1px solid red";
}
function fnStripLowlite(id)
{
var pln = unsafeWindow.frames["ProgressStrips"].document.getElementById(id);
pln.style.border = "1px solid white";
}
// ***************************
// intercept the form submit and parse the commands ourself
// ***************************
function fnReProcess(e)
{
var x,cnt,y,v,i,w,z;
var txt = new Array();
var found ;
var test;
var r = new Array();
w="";
var waypoints = false;
if(e.keyCode == 38)
{ // up arrow... repeat previous command
unsafeWindow.document.frmClearance.txtClearance.value += unsafeWindow.g_lastcmd.substr(unsafeWindow.g_lastcmd.indexOf(" ")) ;
}
if(e.keyCode == 27)
{ // esc
unsafeWindow.document.frmClearance.txtClearance.value = "";
}
if(e.keyCode == 13)
{
v = unsafeWindow.document.frmClearance.txtClearance.value;
unsafeWindow.g_lastcmd = v;
var inArr = v.toUpperCase().split(/\s+/);
// split it up into separate commands.
if(inArr[1] == "C")
{ // is it C
cnt = 0;
// we know next var goes with the C, whether it is a speed, dir, or waypoint
for(x=2;x < inArr.length;x++)
{
if(inArr[x] != "")
{ // not blank
if((inArr[x] != "S") && (inArr[x] != "X") && (inArr[x] != "EX") && (inArr[x] != "T") && (inArr[x] != "H") && (inArr[x] != "V"))
{
if(waypoints == true)
{ // we are reading waypoints into the route
y=0;
found = false;
w = " Routed via: ";
for(z=x;z < inArr.length;z++)
{ // store the route
if(!isNaN(inArr[z]) && (inArr[z].length == 3) )
{ // its a vector
if((z+1)!=inArr.length)
{ // we aren't at the last entry in the route, throw an error
myStatusBar.innerHTML = "Vector must be last entry in route.";
unsafeWindow.document.frmClearance.txtClearance.value = "";
e.preventDefault();
return false;
}
r[y] = inArr[z]; // store the vector
y++;
w += inArr[z];
if((z+1)<inArr.length)
w += "->";
}
else
{ // its a waypoint
for (i = 0; i < unsafeWindow.G_arrNavObjects.length; i++)
{
if ((unsafeWindow.G_arrNavObjects[i][0] == inArr[z]) && (unsafeWindow.G_arrNavObjects[i][1] > 0))
{ // found the nav id and it's not a runway
r[y] = inArr[z]; // store the NAVID
y++;
found = true;
w += inArr[z];
if((z+1)<inArr.length)
w += "->";
}
}
if(found == false)
{ // throw an error
myStatusBar.innerHTML = inArr[z] + " is not a valid NAVID";
unsafeWindow.document.frmClearance.txtClearance.value = "";
e.preventDefault();
return false;
}
}
found = false;
}
x=z; // dont process any more
// if we get here, then all the NAVIDs were valid
// declare the route var
//alert(typeof unsafeWindow.g_routes[inArr[0]]);
if(typeof unsafeWindow.g_routes[inArr[0]] === "undefined")
{
unsafeWindow.g_routes[inArr[0]] = {'rindx':0, 'route':Array()};
}
for(z=0;z < r.length;z++)
{ // set the route for this plane. We double buffer in case the navid list has an error, it will not overwrite existing route
unsafeWindow.g_routes[inArr[0]]['route'][z] = r[z];
}
unsafeWindow.g_routes[inArr[0]]['rindx'] = 0;
// set the waypoint to the first one in the list
txt[cnt] = inArr[0] + " C " + unsafeWindow.g_routes[inArr[0]]['route'][0];
cnt++;
}
else
{ // not a waypoint
// check to see if we should cancel a route clearance
if(isNaN(inArr[x]) || (inArr[x].length == 3))
{ // its a waypoint or vector
if(typeof unsafeWindow.g_routes[inArr[0]] !== "undefined")
{
delete unsafeWindow.g_routes[inArr[0]];
w += " Route Clearance Canceled";
}
}
if(inArr.length > (x+1))
{ // if theres something after this command
// see if there is a trailing L or R
if((inArr[x+1] == "L") || (inArr[x+1] == "R"))
{
txt[cnt] = inArr[0] + " " + inArr[1] + " " + inArr[x] + " " + inArr[x+1]; // [PLANEID] C [whatever the next command is] [L|R]
cnt++;
x++;
}
else
{
txt[cnt] = inArr[0] + " " + inArr[1] + " " + inArr[x]; // [PLANEID] C [whatever the next command is]
cnt++;
}
}
else
{ // nothing after this command so just put out the command
txt[cnt] = inArr[0] + " " + inArr[1] + " " + inArr[x]; // [PLANEID] C [whatever the next command is]
cnt++;
}
}
}
else
{
if(inArr[x] == "S")
{ // speed command
if(inArr.length > (x+1))
{ // make sure theres something after the S
txt[cnt] = inArr[0] + " S " + inArr[x+1]; // [PLANEID] S [whatever the next command is]
cnt++;
x++;
}
}
if((inArr[x] == "X") || (inArr[x] == "EX"))
{ // Expidite all commands
for(y=0;y<txt.length;y++)
{
txt[y] += " X";
}
}
if(inArr[x] == "T")
{ // takeoff command
txt[cnt] = inArr[0] + " T"; // [PLANEID] T
cnt++;
}
if(inArr[x] == "H")
{ // hold command
txt[cnt] = inArr[0] + " H"; // [PLANEID] H
cnt++;
}
if(inArr[x] == "V")
{ // Next entries in the command are waypoints.
waypoints = true;
}
}
}
}
// send all the commands
var winl,stat;
for(y=0;y<(txt.length);y++)
{
unsafeWindow.document.frmClearance.txtClearance.value = txt[y];
unsafeWindow.fnParseInput();
if(y == 0)
{
//alert(window.status);
winl = window.status + " ";
}
else
{
stat = window.status;
winl += stat.substr(stat.indexOf(" ")) + " ";
}
}
unsafeWindow.document.frmClearance.txtClearance.value = "";
myStatusBar.innerHTML = winl + w;
e.preventDefault();
}
else
{ // just a simple command
//alert(window.status);
unsafeWindow.fnParseInput();
//alert(window.status);
myStatusBar.innerHTML = window.status;
e.preventDefault();
}
}
return false;
}
function fnMyDistance(strFlightID, intObjectID)
{
if(typeof unsafeWindow.G_arrNavObjects[intObjectID] !== "undefined")
{
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));
}
else
{
return "x";
}
}
unsafeWindow.fnWPCheck = function()
{
var cnt,ID,txt,d;
var cnt ="";
d = new String();
for(ID in unsafeWindow.G_objPlanes)
{
if(typeof unsafeWindow.g_routes[ID] !== "undefined")
{ // this plane has a route
if((unsafeWindow.G_objPlanes[ID][7] == 0) && unsafeWindow.G_objPlanes[ID][11] === null)
{ // we've reached a waypoint.
if(unsafeWindow.g_routes[ID]['route'].length > unsafeWindow.g_routes[ID]['rindx']+1)
{ // theres another waypoint in the route
unsafeWindow.g_routes[ID]['rindx']++;
txt = unsafeWindow.document.frmClearance.txtClearance.value;
unsafeWindow.document.frmClearance.txtClearance.value = ID + " C " + unsafeWindow.g_routes[ID]['route'][unsafeWindow.g_routes[ID]['rindx']];
unsafeWindow.fnParseInput();
unsafeWindow.document.frmClearance.txtClearance.value = txt;
}
}
}
}
if(cnt)
myStatusBar.innerHTML = cnt
}
unsafeWindow.fnCleanup = function()
{ // cleans up vars created in GM when planes are no longer on screen
var ID,cnt;
// planes
for(ID in unsafeWindow.g_fnPl)
{
if(!unsafeWindow.document.getElementById(ID))
{
delete unsafeWindow.g_fnPl[ID]
}
}
// progress strips
for(ID in unsafeWindow.g_fn)
{
if(!unsafeWindow.frames["ProgressStrips"].document.getElementById(ID))
{
delete unsafeWindow.g_fn[ID]
}
}
// routes
for(ID in unsafeWindow.g_routes)
{
if(!unsafeWindow.document.getElementById(ID))
{
delete unsafeWindow.g_routes[ID]
}
}
}
var canvasbody, myStatusBar;
canvasbody = document.getElementById('canvas');
if (canvasbody) {
// create our own "status bar"
myStatusBar = document.createElement('div');
myStatusBar.innerHTML = "Welcome to ATC-SIM";
myStatusBar.setAttribute("id", "myStatus");
myStatusBar.style.position="fixed";
myStatusBar.style.bottom="0";
myStatusBar.style.left="0";
myStatusBar.style.padding= "1px 4px 1px 3px";
myStatusBar.style.fontSize="12px";
myStatusBar.style.backgroundColor = "#cccccc";
canvasbody.insertBefore(myStatusBar, canvasbody.firstChild);
}
setInterval ( "fnAddMoStripEvent()", 2000 );
setInterval ( "fnAddMoPlaneEvent()", 2000 );
setInterval ( "fnWPCheck()", 2000 );
setInterval ( "fnCleanup()", 5000 );
unsafeWindow.document.frmClearance.txtClearance.addEventListener( "keydown", fnReProcess, false);