// ==UserScript== // @name FMC Extension for GEFS-Online // @description This extension (by Ethan Shields) adds an FMC which controls other features included such as VNAV, LNAV, route, progress information, etc. // @namespace GEFS-Plugins // @match http://*.gefs-online.com/gefs.php* // @match http://localhost:3000/gefs.php* // @match http://127.0.0.1:3000/gefs.php* // @run-at document-end // @version 0.5.0 // @grant none // ==/UserScript== /* Copyright (c) 2016 Ethan Shields, 2015 Harry Xue This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, please visit http://www.gnu.org/licenses/gpl-3.0.html. */ !function(t){var a=setInterval(function(){gefs.aircraft&&gefs.aircraft.animationValue&&gefs.aircraft.animationValue.altitude&&(clearInterval(a),t())},4)}(function(){function t(){var t=gefs.aircraft.llaLocation[0]||0,a=gefs.aircraft.llaLocation[1]||0,e=W[1]||0,n=W[2]||0,i=["--","--","--","--","--"],d=m(fmc.waypoints.nextWaypoint);d=10>d?Math.round(10*d)/10:Math.round(d);for(var p,s=0,o=!0;s0&&(i[2]=g(p-I,!1),i[3]=v(i[2][0],i[2][1]))),r(p,d,i)}function a(){var t=m(fmc.waypoints.nextWaypoint);t<=b(60)&&l(fmc.waypoints.nextWaypoint+1),clearInterval(V),V=te?(f=n>e?fmc.math.getClimbrate(a,e):d[1],h=t):(f=d[1],h=M)}else f=d[1],h=M;else"descent"==D&&(r?n>e&&(f=fmc.math.getClimbrate(a,e),h=t):(f=d[1],l>12e3+R&&(h=100*Math.round((12e3+R)/100))));"cruise"!==D||!F&&I||(r?(I=m(i.length)-e,I+=x(t-M)):I=x(R-M),I=Math.round(I),$("#todInput").val(""+I).change()),u&&$("#Qantas94Heavy-ap-spd > input").val(""+u).change(),f&&$("#Qantas94Heavy-ap-vs > input").val(""+f).change(),h&&$("#Qantas94Heavy-ap-alt > input").val(""+h).change(),s()}function n(t){if(!gefs.pause&&!flight.recorder.playing&&!flight.recorder.paused){var a=Math.round(gefs.aircraft.animationValue.ktas),e=Math.round(gefs.aircraft.animationValue.heading360),i=Math.round(gefs.aircraft.animationValue.altitude),d=gefs.debug.fps,p=Math.round(1e4*gefs.aircraft.llaLocation[0])/1e4,s=Math.round(1e4*gefs.aircraft.llaLocation[1])/1e4,r=new Date,o=r.getUTCHours(),l=r.getUTCMinutes(),c=u(h(o,l));t=t||"none",$("").addClass("data").append($(""+c+"").css("padding","0px 10px 0px 10px"),$(""+a+"").css("padding","0px 10px 0px 10px"),$(""+e+"").css("padding","0px 10px 0px 10px"),$(""+i+"").css("padding","0px 10px 0px 10px"),$(""+p+"").css("padding","0px 10px 0px 10px"),$(""+s+"").css("padding","0px 10px 0px 10px"),$(""+d+"").css("padding","0px 10px 0px 10px"),$(""+t+"").css("padding","0px 10px 0px 10px")).appendTo("#logData")}clearInterval(S),S=gefs.aircraft.animationValue.altitude>18e3?setInterval(n,12e4):setInterval(n,3e4)}function i(){gefs.aircraft.animationValue.gearPosition!==gefs.aircraft.animationValue.gearTarget&&n(1===gefs.aircraft.animationValue.gearTarget?"Gear Up":"Gear Down"),clearInterval(N),N=gefs.aircraft.animationValue.altitude<1e4?setInterval(i,12e3):setInterval(i,6e4)}function d(){gefs.aircraft.animationValue.flapsPosition!==gefs.aircraft.animationValue.flapsTarget&&n("Flaps set to "+gefs.aircraft.animationValue.flapsTarget)}function p(){var t=gefs.aircraft.animationValue.kcas,a=gefs.aircraft.animationValue.altitude;t>255&&1e4>a&&n("Overspeed"),clearInterval(q),q=1e4>a?setInterval(p,15e3):setInterval(p,3e4)}function s(){var t=100*Math.round(gefs.aircraft.animationValue.altitude/100);if("climb"===D&&t===Number(M))$("#phaseBtn").click();else if("cruise"===D){var a=m(fmc.waypoints.route.length+1);t!==Number(M)?$("#phaseBtn").click():I>=a&&$("#phaseBtn").click()}}function r(t,a,e){for(var n=0;nt?Math.round(10*t)/10:Math.round(t),$("#flightete").text("ETE: "+e[0]),$("#flighteta").text("ETA: "+e[1]),$("#todete").text("ETE: "+e[2]),$("#todeta").text("ETA: "+e[3]),$("#flightdist").text(t+" nm"),$("#externaldist").text(t+" nm"),$("#toddist").text(t-I+" nm"),$("#nextDist").text(a+" nm"),$("#nextETE").text(e[4])}function o(){var t,a,e=(gefs.aircraft.name,gefs.groundElevation*metersToFeet,gefs.aircraft.animationValue.altitude),n="M."===$("#Qantas94Heavy-ap-spd span:last-child").text().trim(),i=function(){$("#Qantas94Heavy-ap-spd span:last-child").click()};if("climb"==D){3e4>e?n&&i():e>=3e4&&(n||i());for(var d,p=fmc.vnav.profile.climb,s=0;sp[s][0]&&e<=p[s][1]&&(d=s);t=p[d][2],a=p[d][3]}else if("descent"==D){e>3e4?n||i():n&&i();for(var d,p=fmc.vnav.profile.descent,s=0;sp[s][0]&&e<=p[s][1]&&(d=s);t=p[d][2],a=p[d][3]}return[t,a]}function l(t){if(fmc.waypoints.nextWaypoint!=t)if(t<=fmc.waypoints.route.length){fmc.waypoints.nextWaypoint=t;var a=fmc.waypoints.route[fmc.waypoints.nextWaypoint-1];a[4]?$("#Qantas94Heavy-ap-icao > input").val(a[0]).change():($("#Qantas94Heavy-ap-gc-lat > input").val(a[1]).change(),$("#Qantas94Heavy-ap-gc-lon > input").val(a[2]).change()),$(".activate").removeClass("btn-warning"),$("#waypoints tr:nth-child("+(t+1)+") .btn").addClass("btn-warning")}else $("#Qantas94Heavy-ap-icao > input").val(W[0]).change(),$(".activate").removeClass("btn-warning");else $(".activate").removeClass("btn-warning"),fmc.waypoints.nextWaypoint=void 0,$("#Qantas94Heavy-ap-icao > input").val("").change()}function c(){for(var t=fmc.waypoints.nextWaypoint;t<=fmc.waypoints.route.length;t++)if(fmc.waypoints.route[t-1][3])return t;return-1}function u(t){return t[1]=f(t[1]),t[0]+":"+t[1]}function f(t){return 10>t&&(t="0"+t),t}function h(t,a){return a>=60&&(a-=60,t++),t>=24&&(t-=24),[t,a]}function g(t,a){var e=t/gefs.aircraft.animationValue.ktas,n=parseInt(e),i=Math.round(60*(e-n));return a&&(i+=Math.round(gefs.aircraft.animationValue.altitude/4e3)),h(n,i)}function v(t,a){var e=new Date,n=e.getHours(),i=e.getMinutes();return n+=t,i+=Number(a),h(n,i)}function m(t){var a,e=gefs.aircraft.llaLocation||[0,0,0],n=fmc.waypoints.nextWaypoint||0,i=fmc.waypoints.route;if(0!==i.length&&fmc.waypoints.nextWaypoint){a=fmc.math.getDistance(e[0],e[1],i[n-1][1],i[n-1][2]);for(var d=n;t>d&&di.length&&(a+=fmc.math.getDistance(i[i.length-1][1],i[i.length-1][2],W[1],W[2]))}else a=fmc.math.getDistance(e[0],e[1],W[1],W[2]);return a}function x(t){var a;return a=0>t?t/-1e3*3.4:t/1e3*2.5}function b(t){var a=gefs.aircraft.animationValue.kcas,e=.107917*Math.pow(Math.E,.0128693*a),n=fmc.math.toRadians(t);return e*Math.tan(n/2)+.2}function y(){k?(k=!1,$("#vnavButton").removeClass("btn btn-warning").addClass("btn"),clearInterval(A)):M?(k=!0,$("#vnavButton").removeClass("btn").addClass("btn btn-warning"),A=setInterval(e,5e3)):alert("Please enter a cruising altitude.")}function C(){$("#tSpd").hasClass("btn-warning")?($("#tSpd").removeClass("btn-warning").addClass("btn-default").text("OFF"),spdControl=!1):($("#tSpd").removeClass("btn-default").addClass("btn-warning").text("ON"),spdControl=!0)}function w(){$("#logData tr").remove(".data")}var I,M,k=!1,W=[],D="climb",F=!1,R=0,T={climb:[[1500,4e3,210,3e3],[4e3,1e4,250,2500],[1e4,18e3,295,2200],[18e3,27e3,295,1800],[27e3,3e4,295,1500],[3e4,1e99,.78,1500]],descent:[[3e4,1e99,.78,-2300],[18e3,3e4,295,-2100],[12e3,18e3,280,-1800],[1e4,12e3,250,-1500]]};window.feetToNM=1/6076,window.nmToFeet=6076,window.fmc={},fmc.math={toRadians:function(t){return t*Math.PI/180},toDegrees:function(t){return 180*t/Math.PI},getGroundSpeed:function(){var t=gefs.aircraft.animationValue.ktas,a=60*gefs.aircraft.animationValue.climbrate*feetToNM;return Math.sqrt(t*t-a*a)},getDistance:function(t,a,e,n){var i=fmc.math,d=i.toRadians(e-t),p=i.toRadians(n-a);t=i.toRadians(t),e=i.toRadians(e);var s=Math.sin(d/2)*Math.sin(d/2)+Math.cos(t)*Math.cos(e)*Math.sin(p/2)*Math.sin(p/2),r=2*Math.atan2(Math.sqrt(s),Math.sqrt(1-s));return i.earthRadiusNM*r},getBearing:function(t,a,e,n){var i=fmc.math;t=i.toRadians(t),e=i.toRadians(e),a=i.toRadians(a),n=i.toRadians(n);var d=Math.sin(n-a)*Math.cos(e),p=Math.cos(t)*Math.sin(e)-Math.sin(t)*Math.cos(e)*Math.cos(n-a),s=i.toDegrees(Math.atan2(d,p));return s},getClimbrate:function(t,a){var e=fmc.math.getGroundSpeed(),n=100*Math.round(e*(t/(a*nmToFeet))*nmToFeet/60/100);return n},earthRadiusNM:3440.06},fmc.waypoints={input:"",route:[],nextWaypoint:"",makeFixesArray:function(){var t=[],a=$("#departureInput").val();a&&t.push(a),$(".waypoint td:first-child div > input").each(function(){t.push($(this).val())});var e=$("#arrivalInput").val();return e&&t.push(e),t},toFixesString:function(){return fmc.waypoints.makeFixesArray().join(" ")},toRouteString:function(){return JSON.stringify([$("#departureInput").val(),$("#arrivalInput").val(),$("#flightNumInput").val(),fmc.waypoints.route])},getCoords:function(t){return autopilot_pp.require("icaoairports")[t]?autopilot_pp.require("icaoairports")[t]:autopilot_pp.require("waypoints")[t]?autopilot_pp.require("waypoints")[t]:!1},formatCoords:function(t){if(t.indexOf(" ")>-1){var a,e=t.split(" "),n=Number(e[0]),i=Number(e[1])/60;return a=0>n?n-i:n+i}return Number(t)},toRoute:function(t){if(0!==t.indexOf('["')){var a,e=(t.indexOf("fpl="),!0),n=$("#wptDeparture")[0].checked,i=$("#wptArrival")[0].checked,d=$("#waypoints tbody tr").length-1,p=[];p=t.trim().toUpperCase().split(" ");for(var s=0;s5||p[s].length<1||!/^\w+$/.test(p[s]))&&(e=!1);if(e){for(var s=0;d>s;s++)fmc.waypoints.removeWaypoint(1);if(fmc.waypoints.route=[],n){var r=p[0];$("#departureInput").val(r).change(),a=1}else a=0,$("#departureInput").val("").change();for(var s=0;s+a").addClass("waypoint").append($("").append($("
").addClass("input-prepend input-append").append($("").addClass("input-medium").addClass("wpt").css("width","75px").attr("type","text").attr("placeholder","Fix/Apt.").change(function(){var a=$(this).val(),e=t.getCoords(a),n=$(this).parents().eq(2).index()-1;e?($(this).parents().eq(2).children(".position").children("div").children(".lat").val(e[0]),$(this).parents().eq(2).children(".position").children("div").children(".lon").val(e[1]),t.route[n]=[a,e[0],e[1],void 0,!0]):(t.route[n][0]=a,t.route[n][4]=!1)}))),$("").addClass("position").append($("
").addClass("input-prepend input-append").append($("").addClass("input-medium lat").css("width","80px").attr({type:"text",tabindex:"-1"}).change(function(){var a=$(this).parents().eq(2).index()-1;t.route[a][1]=t.formatCoords($(this).val()),t.route[a][4]=!1}),$("").addClass("input-medium lon").css("width","80px").attr({type:"text",tabindex:"-1"}).change(function(){var a=$(this).parents().eq(2).index()-1;t.route[a][2]=t.formatCoords($(this).val()),t.route[a][4]=!1}))),$("").addClass("altitude").append($("
").addClass("input-prepend input-append").append($("").addClass("input-medium alt").css("width","40px").attr({type:"text",tabindex:"-1",placeholder:"Ft."}).change(function(){var a=$(this).parents().eq(2).index()-1;t.route[a][3]=Number($(this).val())}))),$("").append($("
").addClass("input-prepend input-append").append($("