diff --git a/README.md b/README.md
index be8d5cf..3f76736 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,6 @@
# AirlineSim Enhancement Suite
-The AirlineSime Enhancement Suite (AES) offers a set of tools to help CEOs build their airlines.
+The AirlineSim Enhancement Suite (AES) offers a set of tools to help CEOs build their airlines.
## Features
@@ -18,7 +18,6 @@ Marcipanas wrote [a guide](https://docs.google.com/document/d/1hzMHb3hTBXSZNtuDK
## Installation
Supported platforms: chromium based browsers (Chrome, Edge, etc)
-
Please follow [racsofp’s guide](https://forums.airlinesim.aero/t/manual-installation-of-the-ase-airlinesim-enhancement-suite-chrome-extension/24671)
## History
@@ -34,3 +33,4 @@ Sources: the [original forum thread](https://forums.airlinesim.aero/t/introducin
- Marcipanas for the original development
- racsofp for their update and installation documentation
- Robert73 for the updated manifest file
+- Zoë Bijl for the continued development
diff --git a/docs/pricingDataObjectExample.js b/docs/pricingDataObjectExample.js
new file mode 100644
index 0000000..85ebc87
--- /dev/null
+++ b/docs/pricingDataObjectExample.js
@@ -0,0 +1,56 @@
+"20240403": {
+ "data": {
+ "C": {
+ "analysisPrice": 0,
+ "analysisPricePoint": 0,
+ "currentPrice": 467,
+ "currentPricePoint": 100,
+ "recommendation": 0,
+ "totalBkd": 0,
+ "totalCap": 0,
+ "useCurrentPrice": 0,
+ "valid": 0
+ },
+ "Cargo": {
+ "analysisPrice": 139,
+ "analysisPricePoint": 100,
+ "currentPrice": 139,
+ "currentPricePoint": 100,
+ "index": 39,
+ "newPrice": 128,
+ "newPriceChange": -8,
+ "newPricePoint": 92,
+ "recType": "bad",
+ "recommendation": "Drop High",
+ "totalBkd": 13,
+ "totalCap": 72,
+ "useCurrentPrice": 1,
+ "valid": 1
+ },
+ "F": {
+ "analysisPrice": 0,
+ "analysisPricePoint": 0,
+ "currentPrice": 859,
+ "currentPricePoint": 100,
+ "recommendation": 0,
+ "totalBkd": 0,
+ "totalCap": 0,
+ "useCurrentPrice": 0,
+ "valid": 0
+ },
+ "Y": {
+ "analysisPrice": 0,
+ "analysisPricePoint": 0,
+ "currentPrice": 203,
+ "currentPricePoint": 100,
+ "recommendation": 0,
+ "totalBkd": 0,
+ "totalCap": 0,
+ "useCurrentPrice": 0,
+ "valid": 0
+ }
+ },
+ "date": 20240403,
+ "pricingUpdated": 1,
+ "updateTime": "14:36 UTC"
+}
\ No newline at end of file
diff --git a/extension/content_aircraftFlights.js b/extension/content_aircraftFlights.js
index edc10fa..8ddf920 100644
--- a/extension/content_aircraftFlights.js
+++ b/extension/content_aircraftFlights.js
@@ -119,7 +119,7 @@ function displayFlightProfit(){
if(value.data){
td.push(formatMoney(value.data.money.CM5.Total));
- td.push($('
').text(formatDate(value.data.date)+' '+value.data.time));
+ td.push($(' ').text(AES.formatDateString(value.data.date)+' '+value.data.time));
} else {
td.push(' ');
td.push(' ');
@@ -137,7 +137,7 @@ function buildTable(){
row.push($(' ').append('Total flights ',''+aircraftFlightData.totalFlights+' '));
row.push($(' ').append('Finished flights ',''+aircraftFlightData.finishedFlights+' '));
row.push($(' ').append('Finished flights with profit/loss extract ',''+aircraftFlightData.profitFlights+' '));
- row.push($(' ').append('Data save time ',''+formatDate(aircraftFlightData.date)+' '+aircraftFlightData.time+' '));
+ row.push($(' ').append('Data save time ',''+AES.formatDateString(aircraftFlightData.date)+' '+aircraftFlightData.time+' '));
let tbody = $(' ').append(row);
return $('').append(tbody);
@@ -146,7 +146,7 @@ function getData(){
//Aircraft ID
let aircraftId = getAircraftId();
let aircraftInfo = getAircraftInfo();
- let date = getDate();
+ let date = AES.getServerDate()
let server = getServerName();
let flights = getFlights();
let flightsStats = getFlightsStats(flights);
@@ -235,39 +235,6 @@ function formatMoney(value){
return container
}
-function formatDate(date){
- return date.substring(0, 4)+'-'+date.substring(4, 6)+'-'+date.substring(6, 8);
-}
-function getDate(){
- let a = $(".as-footer-line-element:has('.fa-clock-o')").text().trim();
- let b = a.split(" ");
- //For date
- let dateTemp = b[0].split("-");
- let date;
- if(dateTemp.length == 1){
- //German
- dateTemp = dateTemp[0].split(".");
- date = dateTemp.map(function(value){
- return value.replace(/[^A-Za-z0-9]/g, '');
- });
- date = date[2] + date[1] + date[0];
- } else {
- //English
- date = dateTemp.map(function(value){
- return value.replace(/[^A-Za-z0-9]/g, '');
- });
- date = date[0] + date[1] + date[2];
- }
- //For time
- let time = b[b.length-2] +' '+b[b.length-1];
- return {date:date,time:time};
-}
-function cleanInteger(a){
- a = a.replace(',','');
- a = a.replace('.','');
- a = a.replace(' AS$','');
- return parseInt(a, 10);
-}
function getServerName(){
let server = window.location.hostname
server = server.split('.');
diff --git a/extension/content_dashboard.js b/extension/content_dashboard.js
index 04f7c5e..cbfb700 100644
--- a/extension/content_dashboard.js
+++ b/extension/content_dashboard.js
@@ -1,2903 +1,2855 @@
-"use strict";
-//MAIN
-//Global vars
-var settings,airline,server,todayDate;
-$(function(){
- todayDate = (getDate('today',0));
- airline = getAirlineCode();
- server = getServerName();
- chrome.storage.local.get(['settings'], function(result) {
- settings = result.settings;
-
- displayDashboard();
- dashboardHandle();
- $("#aes-select-dashboard-main").change(function () {
- dashboardHandle();
- });
- });
-});
-function displayDashboard(){
- let mainDiv = $("#enterprise-dashboard");
- mainDiv.before(
- `
- AirlineSim Enhancement Suite Dashboard
-
-
-
- Show Dashboard
-
-
- General
- Route Management
- Competitor Monitoring
- Aircraft Profitability
- None
-
-
-
-
-
- `
- );
- $("#aes-select-dashboard-main").val(settings.general.defaultDashboard);
-}
-function dashboardHandle(){
- let value = $("#aes-select-dashboard-main").val();
- settings.general.defaultDashboard = value;
- chrome.storage.local.set({settings: settings}, function() {});
- switch(value) {
- case 'general':
- displayGeneral();
- break;
- case 'routeManagement':
- displayRouteManagement();
- break;
- case 'competitorMonitoring':
- displayCompetitorMonitoring();
- break;
- case 'hr':
- displayHr();
- break;
- case 'aircraftProfitability':
- displayAircraftProfitability();
- break;
- default:
- displayDefault();
- }
-}
-//Route Management Dashbord
-function displayRouteManagement(){
- //Check ROute Managemetn seetings
- if(!settings.routeManagement){
- setDefaultRouteManagementSettings();
- }
-
-
- let mainDiv = $("#aes-div-dashboard");
- //Build layout
- mainDiv.empty();
- let title = $(' ').text('Route Management');
- let div = $('
');
- mainDiv.append(title,div);
- //Get schedule
- let scheduleKey = server+airline.code+'schedule';
- chrome.storage.local.get([scheduleKey], function(result) {
- let scheduleData = result[scheduleKey];
- if(scheduleData){
- // Table
- generateRouteManagementTable(scheduleData);
-
- // Option buttons
- let fieldsetEl = document.createElement("fieldset")
- let legendEl = document.createElement("legend")
- let buttonGroupEl = document.createElement("div")
-
- let buttonElements = {
- "selectFirstTen": {
- "label": "select first 10"
- },
- "hideChecked": {
- "label": "hide checked"
- },
- "openInventory": {
- "label": "open inventory (max 10)"
- },
- "reloadTable": {
- "label": "reload table"
- }
- }
-
- for (let key in buttonElements) {
- let buttonObj = buttonElements[key]
- let buttonEl = document.createElement("button")
- let buttonClassNames = buttonObj?.classNames
- let buttonType = buttonObj?.type
- let buttonDefaultClassNames = "btn btn-default"
- buttonEl.innerText = buttonObj.label
-
- if (buttonType) {
- buttonEl.setAttribute("type", buttonType)
- } else {
- buttonEl.setAttribute("type", "button")
- }
-
- if (buttonClassNames) {
- buttonEl.className = buttonClassNames
- } else {
- buttonEl.className = buttonDefaultClassNames
- }
-
- buttonObj.element = buttonEl
-
- buttonGroupEl.append(buttonEl)
- }
-
- legendEl.innerText = "Options"
- buttonGroupEl.classList.add("btn-group")
-
- fieldsetEl.append(legendEl, buttonGroupEl)
-
- let optionsDiv = $('
').append(fieldsetEl);
-
- // Button actions
-
- // Select first ten
- buttonElements["selectFirstTen"].element.addEventListener("click", function(){
- let count = 0
- $('#aes-table-routeManagement tbody tr').each(function(){
- $(this).find("input").prop('checked', true);
- count++;
- if(count > 10){
- return false;
- }
- })
- });
-
- // Remove checked
- buttonElements["hideChecked"].element.addEventListener("click", function(){
- $('#aes-table-routeManagement tbody tr').has('input:checked').remove();
- });
-
- // Open Inventory
- buttonElements["openInventory"].element.addEventListener("click", function(){
- //Get checked collumns
- let pages = $('#aes-table-routeManagement tbody tr').has('input:checked').map(function() {
- let orgdest = $(this).attr('id');
- orgdest = orgdest.split("-");
- orgdest = orgdest[2];
- //let orgdest = $(this).find("td:eq(1)").text() + $(this).find("td:eq(2)").text();
- let url = 'https://'+server+'.airlinesim.aero/app/com/inventory/'+orgdest;
- return url;
- }).toArray();
-
- //Open new tabs
- for (let i = 0; i < pages.length; i++) {
- window.open(pages[i], '_blank');
- if(i==10){
- break;
- }
- }
- });
-
- // Reload table reloadTable
- buttonElements["reloadTable"].element.addEventListener("click", function(){
- generateRouteManagementTable(scheduleData);
- });
- let divRow = $('
').append(optionsDiv,displayRouteManagementFilters(),displayRouteManagementCollumns())
- div.prepend(divRow);
- //Collumns selector Checkbox listener
- $('#aes-table-routeManagement-collumns input').change(function(){
- let show;
- if(this.checked) {
- show = 1;
- } else {
- show = 0;
- }
- let value = $(this).val();
- settings.routeManagement.tableCollumns.forEach(function(col){
- if(col.class == value){
- col.show = show;
- }
- });
- chrome.storage.local.set({settings: settings}, function(){});
- });
-
- } else {
- //no schedule
- div.append("Need schedule info to show this section. Change Dashboard to General -> Schedule -> Extract Schedule.")
- }
- });
-}
-function setDefaultRouteManagementSettings(){
- let collumns = [
- {
- name:'Origin',
- class:'aes-origin',
- number:0,
- show:1,
- value:'origin'
- },
- {
- name:'Destination',
- class:'aes-destination',
- number:0,
- show:1,
- value:'destination'
- },
- {
- name:'Hub',
- class:'aes-hub',
- number:0,
- show:1,
- value:'hub'
- },
- {
- name:'OD',
- class:'aes-od',
- number:0,
- show:1,
- value:'odName'
- },
- {
- name:'Direction',
- class:'aes-direction',
- number:0,
- show:1,
- value:'direction'
- },
- {
- name:'# of flight numbers',
- class:'aes-fltNr',
- number:1,
- show:1,
- value:'fltNr'
- },
- {
- name:'PAX frequency',
- class:'aes-paxFreq',
- number:1,
- show:1,
- value:'paxFreq'
- },
- {
- name:'Cargo frequency',
- class:'aes-cargoFreq',
- number:1,
- show:1,
- value:'cargoFreq'
- },
- {
- name:'Total Frequency',
- class:'aes-totalFreq',
- number:1,
- show:1,
- value:'totalFreq'
- },
- {
- name:'Analysis date',
- class:'aes-analysisDate',
- number:0,
- show:1
- },
- {
- name:'Previous Analysis date',
- class:'aes-analysisPreDate',
- number:0,
- show:1
- },
- {
- name:'Pricing date',
- class:'aes-pricingDate',
- number:0,
- show:1
- },
- {
- name:'PAX load',
- class:'aes-paxLoad',
- number:1,
- show:1
- },
- {
- name:'PAX load Δ',
- class:'aes-paxLoadDelta',
- number:1,
- show:1
- },
- {
- name:'Cargo load',
- class:'aes-cargoLoad',
- number:1,
- show:1
- },
- {
- name:'Cargo load Δ',
- class:'aes-cargoLoadDelta',
- number:1,
- show:1
- },
- {
- name:'Total load',
- class:'aes-load',
- number:1,
- show:1
- },
- {
- name:'Total load Δ',
- class:'aes-loadDelta',
- number:1,
- show:1
- },
- {
- name:'PAX index',
- class:'aes-paxIndex',
- number:1,
- show:1
- },
- {
- name:'PAX index Δ',
- class:'aes-paxIndexDelta',
- number:1,
- show:1
- },
- {
- name:'Cargo index',
- class:'aes-cargoIndex',
- number:1,
- show:1
- },
- {
- name:'Cargo index Δ',
- class:'aes-cargoIndexDelta',
- number:1,
- show:1
- },
- {
- name:'Index',
- class:'aes-index',
- number:1,
- show:1
- },
- {
- name:'Index Δ',
- class:'aes-indexDelta',
- number:1,
- show:1
- },
- {
- name:'Route PAX index',
- class:'aes-routeIndexPax',
- number:1,
- show:1
- },
- {
- name:'Route Cargo index',
- class:'aes-routeIndexCargo',
- number:1,
- show:1
- },
- {
- name:'Route index',
- class:'aes-routeIndex',
- number:1,
- show:1
- }
- ];
- settings.routeManagement = {
- tableCollumns:collumns,
- filter:[]
- };
-}
-function routeManagementApplyFilter(){
- $('#aes-table-routeManagement tbody tr').each(function(){
- let row = this;
- settings.routeManagement.filter.forEach(function(filter){
- let cell = $(row).find("."+filter.collumnCode).text();
- //if(cell){
- //Get collumn info if number or not
- let number;
- for(let i=0;i':
- if(cell < value){
- $(row).remove();
- }
- break;
- case '<':
- if(cell > value){
- $(row).remove();
- }
- }
- });
- });
-}
-function displayRouteManagementFilters(){
- //Table head
- let th = [];
- th.push('Column ');
- th.push('Operation ');
- th.push('Value ');
- th.push(' ');
- let thead= $(' ').append($(' ').append(th));
-
- //Table body
- let tbody = $(' ');
- settings.routeManagement.filter.forEach(function(fil){
- let td = [];
- td.push(' '+fil.collumn+' ');
- td.push(''+fil.operation+' ');
- td.push(''+fil.value+' ');
- td.push(' ');
- tbody.append($(' ').append(td));
- });
-
- //Table foot
- //select collumn
- let option1 = [];
- settings.routeManagement.tableCollumns.forEach(function(col){
- option1.push(''+col.name+' ');
- });
- let select1 = $(' ').append(option1);
-
-
-
- //Select value
- let option = [];
- option.push('= ');
- option.push('!= ');
- option.push('> ');
- option.push('< ');
- let select = $(' ').append(option);
- //Add button
- let btn = $(' ').text('Add Row');
- btn.click(function(){
- let td = [];
- let collumn = $(this).closest("tr").find('#aes-select-routeManagement-filter-collumn option:selected').text();
- let collumnVal = $(this).closest("tr").find('#aes-select-routeManagement-filter-collumn').val();
- let operation = $(this).closest("tr").find('#aes-select-routeManagement-filter-operation option:selected').text();
- let value = $(this).closest("tr").find('#aes-select-routeManagement-filter-value').val()
- td.push(' '+collumn+' ');
- td.push(''+operation+' ');
- td.push(''+value+' ');
- td.push(' ');
-
- tbody.append($(' ').append(td));
- });
-
-
- //Footer rows
- let tf = [];
- tf.push($(' ').html(select1));
- tf.push($(' ').html(select));
- tf.push(' ');
- tf.push($(' ').append(btn));
- let tfoot= $(' ').append($(' ').append(tf));
- let table = $('').append(thead,tbody,tfoot);
- let divTable = $('
').append(table);
-
-
- //
- let saveBtn = $('apply filter ');
- let saveSpan = $(' ');
-
- //Closable legend
- let link = $(' ').text('Filters');
- let legend = $(' ').html(link);
- link.click(function(){
- divForAll.toggle();
- });
-
- let divForAll = $('
').append(divTable,saveBtn,saveSpan);
- let fieldset = $(' ').append(legend,divForAll);
- let div = $('
').append(fieldset);
-
- //Delete row for filter row
- table.on("click", ".aes-a-routeManagement-filter-delete-row", function(){
- $(this).closest("tr").remove();
- });
-
- //Save Button
- saveBtn.click(function(){
-
- saveSpan.removeClass().addClass('warning').text(' saving...');
- let filter = [];
- $('#aes-table-routeManagement-filter tbody tr').each(function(){
- filter.push(
- {
- collumnCode:$(this).find('input').val(),
- collumn:$(this).find('td:eq(0)').text(),
- operation:$(this).find('td:eq(1)').text(),
- value:$(this).find('td:eq(2)').text(),
- }
- );
- });
- settings.routeManagement.filter = filter;
- chrome.storage.local.set({settings: settings}, function(){
- saveSpan.removeClass().addClass('warning').text(' filtering...');
- routeManagementApplyFilter()
- saveSpan.removeClass().addClass('good').text(' done!');
- });
- });
-
-
- return div;
-}
-function displayRouteManagementCollumns(){
- //Table Head
- let th = [];
- th.push('Show ');
- th.push('Column ');
- let thead= $(' ').append($(' ').append(th));
- //Table body
- let tbody= $(' ');
-
- settings.routeManagement.tableCollumns.forEach(function(col){
- let td = [];
- //Checkbox
- if (col.show){
- td.push(' ');
- } else {
- td.push(' ');
- }
- //Name
- td.push(''+col.name+' ');
- tbody.append($(' ').append(td));
- });
-
- let table = $('').append(thead,tbody);
- let divTable = $('
').append(table);
-
- //Closable legend
- let link = $(' ').text('Columns');
- let legend = $(' ').html(link);
- link.click(function(){
- $('#aes-div-routeManagement-collumns').toggle();
- });
-
- let fieldset = $(' ').append(legend,divTable);
- let div = $('
').append(fieldset);
- return div;
-}
-function generateRouteManagementTable(scheduleData){
- //Remove table
- $('#aes-div-routeManagement').remove();
- //Dates
- let dates = [];
- for(let date in scheduleData.date){
- dates.push(date);
- }
- dates.reverse();
- //LatestSchedule
- let schedule = scheduleData.date[dates[0]].schedule;
- //Generate top
- //Table headers
- let collumns = settings.routeManagement.tableCollumns;
-
- //Generate table head
- let thead = $(' ');
- let th = [];
- //Check box
- let checkbox = $(' ');
- checkbox.change(function () {
- if(this.checked) {
- $('#aes-table-routeManagement tbody tr').each(function(){
- $(this).find("input").prop('checked', true);
- });
- } else {
- $('#aes-table-routeManagement tbody tr').each(function(){
- $(this).find("input").prop('checked', false);
- });
- }
- });
- th.push($(' ').html(checkbox));
- collumns.forEach(function(col){
- if(col.show){
- let sort = $(' ').html(col.name);
- sort.click(function(){
- routeManagementSortTable(col.class,col.number);
- });
- th.push($(' ').html(sort));
- }
- });
- //Add open inventory column
- th.push($('Action '));
-
- thead.append($(' ').append(th));
- //Generate table rows
- let tbody = $(' ');
- let uniqueOD = [];
- schedule.forEach(function(od){
- //ODs for analysis
- uniqueOD.push(od.od);
- //Get values flight numbers and total frequency
- let fltNr = 0;
- let paxFreq = 0;
- let cargoFreq = 0;
- for (let flight in od.flightNumber){
- cargoFreq += od.flightNumber[flight].cargoFreq,
- paxFreq += od.flightNumber[flight].paxFreq,
- fltNr++;
- }
- let totalFreq = cargoFreq + paxFreq;
- //hub
- let hub = od.od.slice(0, 3);
- let cellValue = {
- origin:od.origin,
- destination:od.destination,
- odName:od.od,
- direction:od.direction,
- fltNr:fltNr,
- paxFreq:paxFreq,
- cargoFreq:cargoFreq,
- totalFreq:totalFreq,
- hub:hub
- }
- //Table cells
- let cell = [];
- //Checkbox
- cell.push(' ');
- //Schedule
- collumns.forEach(function(col){
- if(col.show){
- if(col.value){
- cell.push($(' ').addClass(col.class).text(cellValue[col.value]));
- } else {
- cell.push($(' ').addClass(col.class));
- }
- }
- });
- let rowId=od.origin+od.destination;
-
- //Add inventory button
- let invBtn = 'Inventory '
- cell.push($(' ').html(invBtn));
-
- let row = $(' ').append(cell);
- tbody.append(row);
- });
- let table = $('').append(thead,tbody);
- let divTable = $('
').append(table);
- $('#aes-div-dashboard-routeManagement').append(divTable)
- //Analysis collumns
- //Get unique ODs
- uniqueOD = [...new Set(uniqueOD)];
- for(let i=0;i b) return -1;
- if (a < b) return 1;
- if (a = b) return 0;
- });
- } else {
- sorted.sort();
- }
- let same = 1;
- for(let i = 0; i < indexes.length; i++){
- if(indexes[i] !== sorted[i]){
- same = 0;
- }
- }
- if(same){
- if(number){
- sorted.sort(function(a, b){
- if (a < b) return -1;
- if (a > b) return 1;
- if (a = b) return 0;
- });
- } else {
- sorted.reverse();
- }
- }
- for(let i=0; i= 0 ; j--){
- if(number){
- let value = parseInt($(tableRows[j]).find("."+collumn).text(),10);
- if(!value){
- value = 0;
- }
- if(value == sorted[i]){
- tableBody.append($(tableRows[j]));
- tableRows.splice(j, 1);
- }
- } else {
- if($(tableRows[j]).find("."+collumn).text() == sorted[i]){
- tableBody.append($(tableRows[j]));
- tableRows.splice(j, 1);
- }
- }
- }
- }
-}
-function updateRouteAnalysisCollumns(data,dates,routeIndex){
-
- if(data){
- let rowId = '#aes-row-'+data.origin+data.destination;
-
- if(dates.analysis){
- //Analysis date
-
- $(rowId+' .aes-analysisDate').text(formatDate(dates.analysis));
-
-
- //Pricing date
- if(dates.pricing){
- $(rowId+' .aes-pricingDate').text(formatDate(dates.pricing));
- }
-
- //Pax Load
- $(rowId+' .aes-paxLoad').html(displayLoad(getRouteAnalysisLoad(data.date[dates.analysis].data,'pax')));
- //Cargo Load
- $(rowId+' .aes-cargoLoad').html(displayLoad(getRouteAnalysisLoad(data.date[dates.analysis].data,'cargo')));
- //All Load
- $(rowId+' .aes-load').html(displayLoad(getRouteAnalysisLoad(data.date[dates.analysis].data,'all')));
-
- //PAX Index
- $(rowId+' .aes-paxIndex').html(displayIndex(getRouteAnalysisIndex(data.date[dates.analysis].data,'pax')));
- //Cargo Index
- $(rowId+' .aes-cargoIndex').html(displayIndex(getRouteAnalysisIndex(data.date[dates.analysis].data,'cargo')));
- //PAX Index
- $(rowId+' .aes-index').html(displayIndex(getRouteAnalysisIndex(data.date[dates.analysis].data,'all')));
-
- if(dates.analysisOneBefore){
- //Previous analysis date
- $(rowId+' .aes-analysisPreDate').text(formatDate(dates.analysisOneBefore));
-
- //Pax Load Delta
- $(rowId+' .aes-paxLoadDelta').html(displayRouteAnalysisLoadDelta(data.date[dates.analysis].data,data.date[dates.analysisOneBefore].data,'pax'));
- //Cargo Load Delta
- $(rowId+' .aes-cargoLoadDelta').html(displayRouteAnalysisLoadDelta(data.date[dates.analysis].data,data.date[dates.analysisOneBefore].data,'cargo'));
- //All Load Delta
- $(rowId+' .aes-loadDelta').html(displayRouteAnalysisLoadDelta(data.date[dates.analysis].data,data.date[dates.analysisOneBefore].data,'all'));
-
- //PAX Index Delta
- $(rowId+' .aes-paxIndexDelta').html(displayRouteAnalysisIndexDelta(data.date[dates.analysis].data,data.date[dates.analysisOneBefore].data,'pax'));
- //Cargo Index Delta
- $(rowId+' .aes-cargoIndexDelta').html(displayRouteAnalysisIndexDelta(data.date[dates.analysis].data,data.date[dates.analysisOneBefore].data,'cargo'));
- //PAX Index Delta
- $(rowId+' .aes-indexDelta').html(displayRouteAnalysisIndexDelta(data.date[dates.analysis].data,data.date[dates.analysisOneBefore].data,'all'));
-
-
- }
-
- //Route Index
- if(routeIndex.pax){
- $(rowId+' .aes-routeIndexPax').html(displayIndex(routeIndex.pax));
- }
- if(routeIndex.cargo){
- $(rowId+' .aes-routeIndexCargo').html(displayIndex(routeIndex.cargo));
- }
- if(routeIndex.all){
- $(rowId+' .aes-routeIndex').html(displayIndex(routeIndex.all));
- }
-
-
-
-
- }
- }
-
-
- return;
- let analysisDate = dates.analysis;
- let pricingDate = dates.pricing;
-
- let paxLoad;
- let paxLoadDelta ;
- let cargoLoad ;
- let cargoLoadDelta ;
- let totalLoad ;
- let totalLoadDelta;
-
-
-
-
-
-
- outDates = getInvPricingAnalaysisPricingDate(dataOut.date);
- if(outDates.analysis){
- $('#aes-row-invPricing-'+origin+dest+'-analysis',tbody).text(formatDate(outDates.analysis));
- outIndex = dataOut.date[outDates.analysis].routeIndex;
- let td = $('#aes-row-invPricing-'+origin+dest+'-OWindex',tbody);
- td.html(displayIndex(outIndex));
- if(outDates.analysisOneBefore){
- outIndexChange = dataOut.date[outDates.analysis].routeIndex - dataOut.date[outDates.analysisOneBefore].routeIndex
- td.append(displayIndexChange(outIndexChange));
- }
- }
- if(outDates.pricing){
- $('#aes-row-invPricing-'+origin+dest+'-pricing',tbody).text(formatDate(outDates.pricing));
- }
-
-}
-function displayRouteAnalysisLoadDelta(dataCurrent,dataPrevious,type){
- let load = getRouteAnalysisLoad(dataCurrent,type);
- let preLoad = getRouteAnalysisLoad(dataPrevious,type);
- if(load && preLoad){
- let diff = load - preLoad;
- let span = $(' ');
- if(diff > 0){
- span.addClass('good').text('+'+diff+"%");
- return span;
- }
- if(diff < 0){
- span.addClass('bad').text(diff+"%");
- return span;
- }
- span.addClass('warning').text(diff+"%");
- return span;
- }
-}
-function displayRouteAnalysisIndexDelta(dataCurrent,dataPrevious,type){
- let index = getRouteAnalysisIndex(dataCurrent,type);
- let preIndex = getRouteAnalysisIndex(dataPrevious,type);
- if(index && preIndex){
- let diff = index - preIndex;
- let span = $(' ');
- if(diff > 0){
- span.addClass('good').text('+'+diff);
- return span;
- }
- if(diff < 0){
- span.addClass('bad').text(diff);
- return span;
- }
- span.addClass('warning').text(diff);
- return span;
- }
-}
-function getRouteAnalysisLoad(data,type){
- let cmp = [];
- switch(type) {
- case 'all':
- cmp = ['Y','C','F','Cargo'];
- break;
- case 'pax':
- cmp = ['Y','C','F'];
- break;
- case 'cargo':
- cmp = ['Cargo'];
- break;
- default:
- // code block
- }
- let cap,bkd;
- cap = bkd = 0;
- cmp.forEach(function(comp){
- if(data[comp].valid){
- cap += data[comp].totalCap;
- bkd += data[comp].totalBkd;
- }
- });
- if(cap){
- return Math.round(bkd/cap*100);
- } else {
- return 0;
- }
-}
-function displayLoad(load){
- if(load){
- let span = $(' ');
- if(load >= 70){
- span.addClass('good').text(load+"%");
- return span;
- }
- if(load < 40){
- span.addClass('bad').text(load+"%");
- return span;
- }
- span.addClass('warning').text(load+"%");
- return span;
- }
-}
-function getRouteAnalysisIndex(data,type){
- let cmp = [];
- let index=0;
- switch(type) {
- case 'all':
- cmp = ['Y','C','F','Cargo'];
- break;
- case 'pax':
- cmp = ['Y','C','F'];
- break;
- case 'cargo':
- cmp = ['Cargo'];
- break;
- default:
- cmp = 0;
- break;
- }
- if(cmp){
- //Multi index
- let count = 0;
- cmp.forEach(function(comp){
- if(data[comp].valid){
- index += data[comp].index;
- count++;
- }
- });
- if(index){
- return Math.round(index/count);
- }
- }
-}
-function getRouteAnalysisImportantDates(dates){
- //Get latest analysis and pricing date
- let latest = {
- analysis:0,
- pricing:0,
- analysisOneBefore:0,
- pricingOneBefore:0
- }
- let analysisDates = [];
- let pricingDates = []
- for(let date in dates) {
- if(dates[date].pricingUpdated){
- pricingDates.push(date);
- }
- analysisDates.push(date);
- }
- analysisDates.reverse();
- pricingDates.reverse();
- if(analysisDates.length){
- latest.analysis = analysisDates[0];
- if(analysisDates[1]){
- latest.analysisOneBefore = analysisDates[1];
- }
- }
- if(pricingDates.length){
- latest.pricing = pricingDates[0];
- if(pricingDates[1]){
- latest.pricingOneBefore = pricingDates[1];
- }
- }
- return latest;
-}
-function displayIndex(index){
- let span = $(' ');
- if(index >= 90){
- return span.addClass('good').text(index);
- }
- if(index <= 50 ){
- return span.addClass('bad').text(index);
- }
- return span.addClass('warning').text(index);
-}
-function displayIndexChange(index){
- if(index > 0){
- return ' (+'+index+' )';
- }
- if(index < 0){
- return ' ('+index+' )';
- }
- return ' ('+index+' )';
-}
-//Display General
-function displayGeneral(){
- let mainDiv = $("#aes-div-dashboard");
- mainDiv.empty();
-
- //Table
- //Head cells
- let th1 = $('Area ');
- let th2 = $('Status ');
- let th3 = $('Action ');
- let headRow = $(' ').append(th1,th2,th3);
- let thead = $(' ').append(headRow);
- //Body cells
- let tbody = $(' ');
- generalAddScheduleRow(tbody);
- generalAddPersonelManagementRow(tbody);
-
-
- let table = $('').append(thead,tbody);
- //Build layout
- let divTable = $('
').append(table);
- let title = $(' ').text('General');
- let div = $('
').append(divTable);
- mainDiv.append(title,div);
-}
-//Display COmpetitor Monitoring
-function displayCompetitorMonitoring(){
- //Div
- let div = $('
');
-
- //Check ROute Managemetn seetings
- //
- if(!settings.competitorMonitoring){
- setDefaultCompetitorMonitoringSettings();
- }
-
- //Display airlines table
- displayCompetitorMonitoringAirlinesTable(div);
-
- let mainDiv = $("#aes-div-dashboard");
- //Build layout
- mainDiv.empty();
- let title = $(' ').text('Competitor Monitoring');
- mainDiv.append(title,div);
-
-}
-function displayCompetitorMonitoringAirlinesTable(div){
- let compAirlines = [];
- let compAirlinesSchedule = [];
- chrome.storage.local.get(null, function(items) {
- //Get data
- for(let key in items){
- if(items[key].type){
- if(items[key].type == 'competitorMonitoring'){
- if(items[key].server == server){
- if(items[key].tracking){
- compAirlines.push(items[key]);
- }
-
- }
- }
- if(items[key].type == 'schedule'){
- if(items[key].server == server){
- let airline = items[key].airline
- compAirlinesSchedule[airline] = items[key];
- }
- }
- }
- }
-
- //Check if any airlines exist
- let rows = [];
- let hrows = [];
- if(compAirlines.length){
- //head
- //second head collumns
- let firstHead = {};
- let th = [];
- settings.competitorMonitoring.tableColumns.forEach(function(col){
- if(col.visible){
- //Sort
- let sort = $(' ').html(col.text);
- sort.click(function(){
- CompetitorMonitoringSortTable(col.field,col.number);
- });
- th.push($(' ').html(sort));
- if(firstHead[col.headGroup]){
- firstHead[col.headGroup]++;
- } else {
- firstHead[col.headGroup] = 1;
- }
- }
- });
- //first head
- let th1 = [];
- for(let titles in firstHead){
- th1.push($(' ').text(titles));
- }
- hrows.push($(' ').append(th1));
- hrows.push($(' ').append(th));
-
- //Data collumns
-
- compAirlines.forEach(function myFunction(value) {
- let data = {};
- //Airline
- data.airlineId = value.id;
- //All Tab0 Collumns
- let dates = [];
- for(let date in value.tab0) {
- dates.push(date);
- }
- dates.sort(function(a, b){return b-a});
- if(dates.length){
- data.airlineCode = value.tab0[dates[0]].code;
- data.airlineName = value.tab0[dates[0]].displayName;
- data.overviewDate = formatDate(dates[0]);
- data.overviewRating = value.tab0[dates[0]].rating;
- data.overviewTotalPax = value.tab0[dates[0]].pax;
- data.overviewTotalCargo = value.tab0[dates[0]].cargo;
- data.overviewStations = value.tab0[dates[0]].stations;
- data.overviewFleet = value.tab0[dates[0]].fleet;
- data.overviewStaff = value.tab0[dates[0]].employees;
- //If previous date exists
- if(dates[1]){
- data.overviewPreDate = formatDate(dates[1]);
- data.overviewRatingDelta = getDelta(getRatingNr(data.overviewRating),getRatingNr(value.tab0[dates[1]].rating));
- data.overviewTotalPaxDelta = getDelta(data.overviewTotalPax,value.tab0[dates[1]].pax);
- data.overviewTotalCargoDelta = getDelta(data.overviewTotalCargo,value.tab0[dates[1]].cargo);
- data.overviewStationsDelta = getDelta(data.overviewStations,value.tab0[dates[1]].stations);
- data.overviewFleetDelta = getDelta(data.overviewFleet,value.tab0[dates[1]].fleet);
- data.overviewStaffDelta = getDelta(data.overviewStaff,value.tab0[dates[1]].employees);
- }
- }
- //All Tab2 Collumns
- dates = [];
- for(let date in value.tab2) {
- dates.push(date);
- }
- dates.sort(function(a, b){return b-a});
- if(dates.length){
- data.fafWeek = formatWeekDate(value.tab2[dates[0]].week);
- data.fafAirportsServed = value.tab2[dates[0]].airportsServed;
- data.fafOperatedFlights = value.tab2[dates[0]].operatedFlights;
- data.fafSeatsOffered = value.tab2[dates[0]].seatsOffered;
- data.fafsko = value.tab2[dates[0]].sko;
- data.fafCargoOffered = value.tab2[dates[0]].cargoOffered;
- data.faffko = value.tab2[dates[0]].fko;
- //If previous date exists
- if(dates[1]){
- data.fafWeekPre = formatWeekDate(value.tab2[dates[1]].week);
- data.fafAirportsServedDelta = getDelta(data.fafAirportsServed,value.tab2[dates[1]].airportsServed);
- data.fafOperatedFlightsDelta = getDelta(data.fafOperatedFlights,value.tab2[dates[1]].operatedFlights);
- data.fafSeatsOfferedDelta = getDelta(data.fafSeatsOffered,value.tab2[dates[1]].seatsOffered);
- data.fafskoDelta = getDelta(data.fafsko,value.tab2[dates[1]].sko);
- data.fafCargoOfferedDelta = getDelta(data.fafCargoOffered,value.tab2[dates[1]].cargoOffered);
- data.faffkoDela = getDelta(data.faffko,value.tab2[dates[1]].fko);
- }
- }
- //Schedule Collumns
- if(compAirlinesSchedule[data.airlineCode]){
- dates = [];
- for(let date in compAirlinesSchedule[data.airlineCode].date) {
- dates.push(date);
- }
- dates.sort(function(a, b){return b-a});
- if(dates.length){
- let hubs = {};
- //For display
- data.scheduleDate = formatDate(dates[0]);
- //For table
- data.scheduleDateUse = dates[0];
- data.scheduleCargoFreq = 0;
- data.schedulePAXFreq = 0;
- data.scheduleFltNr = 0;
- compAirlinesSchedule[data.airlineCode].date[dates[0]].schedule.forEach(function(schedule){
- //Hubs
- let hub = schedule.od.slice(0,3);
- if(hubs[hub]){
- hubs[hub]++;
- } else {
- hubs[hub] = 1;
- }
- for (let flight in schedule.flightNumber){
- //Cargo Freq
- data.scheduleCargoFreq += schedule.flightNumber[flight].cargoFreq;
- //Pax Freq
- data.schedulePAXFreq += schedule.flightNumber[flight].paxFreq;
- //Flight nr
- data.scheduleFltNr++;
- }
- });
- //Total Frequency
- data.scheduleTotalFreq = data.schedulePAXFreq + data.scheduleCargoFreq;
- //Hubs
- let hubArray = [];
- for (let hub in hubs) {
- hubArray.push([hub, hubs[hub]]);
- }
- hubArray.sort(function(a, b) {
- return b[1] - a[1];
- });
- data.scheduleHubs = '';
- hubArray.forEach(function(hubA,index){
- if(index){
- data.scheduleHubs += ', ';
- }
- data.scheduleHubs += hubA[0]+' ('+hubA[1]+')';
- });
-
- //Previous schedule data
- if(dates[1]){
- data.scheduleDatePre = formatDate(dates[1]);
- data.scheduleCargoFreqPre = 0;
- data.schedulePAXFreqPre = 0;
- data.scheduleFltNrPre = 0;
- compAirlinesSchedule[data.airlineCode].date[dates[1]].schedule.forEach(function(schedule){
- //Hubs
- let hub = schedule.od.slice(0,3);
- if(hubs[hub]){
- hubs[hub]++;
- } else {
- hubs[hub] = 1;
- }
- for (let flight in schedule.flightNumber){
- //Cargo Freq
- data.scheduleCargoFreqPre += schedule.flightNumber[flight].cargoFreq;
- //Pax Freq
- data.schedulePAXFreqPre += schedule.flightNumber[flight].paxFreq;
- //Flight nr
- data.scheduleFltNrPre++;
- }
- });
- //Total Frequency
- data.scheduleTotalFreqPre = data.schedulePAXFreq + data.scheduleCargoFreq;
- //Delta Collumns
- data.scheduleFltNrDelta = getDelta(data.scheduleFltNr,data.scheduleFltNrPre);
- data.schedulePAXFreqDelta = getDelta(data.schedulePAXFreq,data.schedulePAXFreqPre);
- data.scheduleCargoFreqDelta = getDelta(data.scheduleCargoFreq,data.scheduleCargoFreqPre);
- data.scheduleTotalFreqDelta = getDelta(data.scheduleTotalFreq,data.scheduleTotalFreqPre);
- }
- }
- }
- //Action collumns
- //Open airline
- data.actionOpenAirline = 'Airline ';
- //Open schedule
- if(compAirlinesSchedule[data.airlineCode]){
- data.actionOpenSchedule = $('Schedule ');
- //Create schedule table
- $('#aes-div-dashboard').on('click', 'button#aes-compMon-btn-schedule-'+data.airlineCode, function() {
- displayCompetitorMonitoringAirlineScheduleTable(div,compAirlinesSchedule[data.airlineCode],data);
- });
- }
- //Remove airline '
- data.actionRemoveAirline = $('Remove ');
- //Remove airline action
- $('#aes-div-dashboard').on('click', 'button#aes-compMon-btn-remove-'+data.airlineCode, function() {
- let key = server+data.airlineId+'competitorMonitoring';
- let remove = $(this);
- chrome.storage.local.get([key], function(compMonitoringData) {
- let compData = compMonitoringData[key];
- compData.tracking = 0;
- chrome.storage.local.set({[compData.key]: compData}, function() {
- $(remove).closest("tr").remove();
- });
- });
- });
-
-
-
- //Populate collumns
- let td = [];
- settings.competitorMonitoring.tableColumns.forEach(function(col){
- if(col.visible){
- td.push($(' ').html(data[col.field]));
-
- }
- });
- rows.push($(' ').append(td));
-
- });
- } else {
- rows.push('No airlines marked for competitor monitoring. Open airline info page to mark airline for tracking. ');
- }
-
- let thead = $(' ').append(hrows);
- let tbody = $(' ').append(rows);
-
- let table = $('').append(thead,tbody);
- let tableWell = $('
').append(table);
-
- //Options
- let divRow = $('
').append(displayCompetitorMonitoringAirlinesTableOptions(),displayCompetitorMonitoringAirlinesTableCollumns());
- div.append(divRow,tableWell);
- });
-}
-function displayCompetitorMonitoringAirlineScheduleTable(mainDiv,scheduleData,data){
- mainDiv.hide();
- //Build schedule rows
- let rows = [];
- let hrow = [];
- if(data.scheduleDateUse){
- let collumns = [
- {
- field:'schedOrigin',
- text:'Origin',
- headGroup:'Schedule',
- visible:1,
- number:0,
- },
- {
- field:'schedDestination',
- text:'Destination',
- headGroup:'Schedule',
- visible:1,
- number:0,
- },
- {
- field:'schedHub',
- text:'Hub',
- headGroup:'Schedule',
- visible:1,
- number:0,
- },
- {
- field:'schedOd',
- text:'OD',
- headGroup:'Schedule',
- visible:1,
- number:0,
- },
- {
- field:'schedDir',
- text:'Direction',
- headGroup:'Schedule',
- visible:1,
- number:0,
- },
- {
- field:'schedFltNr',
- text:'# of flight numbers',
- headGroup:'Schedule',
- visible:1,
- number:1,
- },
- {
- field:'schedPaxFreq',
- text:'PAX frequency',
- headGroup:'Schedule',
- visible:1,
- number:1,
- },
- {
- field:'schedCargoFreq',
- text:'Cargo frequency',
- headGroup:'Schedule',
- visible:1,
- number:1,
- },
- {
- field:'schedTotalFreq',
- text:'Total Frequency',
- headGroup:'Schedule',
- visible:1,
- number:1,
- }
- ];
- //Table Head
- let th = [];
- collumns.forEach(function(col){
- if(col.visible){
- //Sort
- let sort = $(' ').html(col.text);
- sort.click(function(){
- SortTable(col.field,col.number,'aes-table-competitorMonitoring-airline-schedule','aes-comp-sched-');
- });
- th.push($(' ').html(sort));
- }
- });
- hrow.push($(' ').append(th));
- //Table Body
- scheduleData.date[data.scheduleDateUse].schedule.forEach(function(od){
- let td = [];
- let fltNr = 0;
- let paxFreq = 0;
- let cargoFreq = 0;
- for (let flight in od.flightNumber){
- cargoFreq += od.flightNumber[flight].cargoFreq,
- paxFreq += od.flightNumber[flight].paxFreq,
- fltNr++;
- }
- let totalFreq = cargoFreq + paxFreq;
- //hub
- let hub = od.od.slice(0, 3);
- let cellValue = {
- schedOrigin:od.origin,
- schedDestination:od.destination,
- schedOd:od.od,
- schedDir:od.direction,
- schedFltNr:fltNr,
- schedPaxFreq:paxFreq,
- schedCargoFreq:cargoFreq,
- schedTotalFreq:totalFreq,
- schedHub:hub
- }
- collumns.forEach(function(cell){
- if(cell.visible){
- td.push($(' ').html(cellValue[cell.field]));
- }
- });
- rows.push($(' ').append(td));
- });
-
-
-
-
- } else {
- rows.push('No schedule found ');
- }
-
-
-
-
- //Build layout
- let thead = $(' ').append(hrow);
- let tbody = $(' ').append(rows);
- let table = $('').append(thead,tbody);
- let tableWell = $('
').append(table);
- let button = $('Back to overview ');
- let panelDiv = $('
').append(button,tableWell);
- let heading = $(''+data.airlineName+' '+data.airlineCode+' schedule ');
- let div = $('
').append(heading,panelDiv);
- mainDiv.after(div);
- //Button clicks
- button.click(function(){
- div.remove();
- mainDiv.show();
- });
-}
-function displayCompetitorMonitoringAirlinesTableCollumns(){
- //Table Head
- let th = [];
- th.push('Show ');
- th.push('Column ');
- let thead= $(' ').append($(' ').append(th));
- //Table body
- let tbody= $(' ');
-
- settings.competitorMonitoring.tableColumns.forEach(function(col){
- let td = [];
- //Checkbox
- if (col.visible){
- td.push(' ');
- } else {
- td.push(' ');
- }
- //Name
- td.push(''+col.text+' ');
- tbody.append($(' ').append(td));
- });
-
- let table = $('').append(thead,tbody);
- let divTable = $('
').append(table);
- //Collumns selector Checkbox listener
- $('input',table).change(function(){
- let show;
- if(this.checked) {
- show = 1;
- } else {
- show = 0;
- }
- let value = $(this).val();
- settings.competitorMonitoring.tableColumns.forEach(function(col){
- if(col.field == value){
- col.visible = show;
- }
- });
- chrome.storage.local.set({settings: settings}, function(){});
- });
- //Closable legend
- let link = $(' ').text('Columns');
- let legend = $(' ').html(link);
- link.click(function(){
- $('#aes-div-competitorMonitoring-collumns').toggle();
- });
- let fieldset = $(' ').append(legend,divTable);
- let div = $('
').append(fieldset);
- return div;
-}
-function displayCompetitorMonitoringAirlinesTableOptions(){
- let divFieldset = $(' ').html('Options ');
- let btn = $('reload table ');
- divFieldset.append(btn);
- let optionsDiv = $('
').append(divFieldset);
- //Reload table
- btn.click( function(){
- displayCompetitorMonitoring();
- });
-
-
-
- return optionsDiv;
-}
-function CompetitorMonitoringSortTable(collumn,number){
- let tableRows = $('#aes-table-competitorMonitoring tbody tr');
- let tableBody = $('#aes-table-competitorMonitoring tbody');
- tableBody.empty();
- let indexes = [];
- tableRows.each(function(){
- if(number){
- let value = parseInt($(this).find(".aes-"+collumn).text(),10);
- if(value){
- indexes.push(value);
- } else {
- indexes.push(0);
- }
- } else {
- indexes.push($(this).find(".aes-"+collumn).text());
- }
- });
- indexes = [...new Set(indexes)];
- let sorted = [...indexes];
- if(number){
- sorted.sort(function(a, b){
- if (a > b) return -1;
- if (a < b) return 1;
- if (a = b) return 0;
- });
- } else {
- sorted.sort();
- }
- let same = 1;
- for(let i = 0; i < indexes.length; i++){
- if(indexes[i] !== sorted[i]){
- same = 0;
- }
- }
- if(same){
- if(number){
- sorted.sort(function(a, b){
- if (a < b) return -1;
- if (a > b) return 1;
- if (a = b) return 0;
- });
- } else {
- sorted.reverse();
- }
- }
- for(let i=0; i= 0 ; j--){
- if(number){
- let value = parseInt($(tableRows[j]).find(".aes-"+collumn).text(),10);
- if(!value){
- value = 0;
- }
- if(value == sorted[i]){
- tableBody.append($(tableRows[j]));
- tableRows.splice(j, 1);
- }
- } else {
- if($(tableRows[j]).find(".aes-"+collumn).text() == sorted[i]){
- tableBody.append($(tableRows[j]));
- tableRows.splice(j, 1);
- }
- }
- }
- }
-}
-function setDefaultCompetitorMonitoringSettings(){
- let columns = [
- {
- field:'airlineId',
- text:'ID',
- headGroup:'Airline',
- visible:1,
- number:1
- },
- {
- field:'airlineCode',
- text:'Code',
- headGroup:'Airline',
- visible:1,
- number:0
- },
- {
- field:'airlineName',
- text:'Name',
- headGroup:'Airline',
- visible:1,
- number:0
- },
- {
- field:'overviewDate',
- text:'Overview date',
- headGroup:'Overview',
- visible:0,
- number:0
- },
- {
- field:'overviewPreDate',
- text:'Overview previous date',
- headGroup:'Overview',
- visible:0,
- number:0
- },
- {
- field:'overviewRating',
- text:'Rating',
- headGroup:'Overview',
- visible:1,
- number:0
- },
- {
- field:'overviewRatingDelta',
- text:'Rating Δ',
- headGroup:'Overview',
- visible:0,
- number:0
- },
- {
- field:'overviewTotalPax',
- text:'Total pax',
- headGroup:'Overview',
- visible:1,
- number:1
- },
- {
- field:'overviewTotalPaxDelta',
- text:'Total pax Δ',
- headGroup:'Overview',
- visible:1,
- number:1
- },
- {
- field:'overviewTotalCargo',
- text:'Total cargo',
- headGroup:'Overview',
- visible:1,
- number:1
- },
- {
- field:'overviewTotalCargoDelta',
- text:'Total cargo Δ',
- headGroup:'Overview',
- visible:1,
- number:1
- },
- {
- field:'overviewStations',
- text:'Stations',
- headGroup:'Overview',
- visible:1,
- number:1
- },
- {
- field:'overviewStationsDelta',
- text:'Stations Δ',
- headGroup:'Overview',
- visible:1,
- number:1
- },
- {
- field:'overviewFleet',
- text:'Fleet',
- headGroup:'Overview',
- visible:1,
- number:1
- },
- {
- field:'overviewFleetDelta',
- text:'Fleet Δ',
- headGroup:'Overview',
- visible:1,
- number:1
- },
- {
- field:'overviewStaff',
- text:'Staff',
- headGroup:'Overview',
- visible:0,
- number:1
- },
- {
- field:'overviewStaffDelta',
- text:'Staff Δ',
- headGroup:'Overview',
- visible:0,
- number:1
- },
- {
- field:'fafWeek',
- text:'Week',
- headGroup:'Figures',
- visible:0,
- number:0
- },
- {
- field:'fafWeekPre',
- text:'Previous week',
- headGroup:'Figures',
- visible:0,
- number:0
- },
- {
- field:'fafAirportsServed',
- text:'Airports served',
- headGroup:'Figures',
- visible:1,
- number:1
- },
- {
- field:'fafAirportsServedDelta',
- text:'Airports served Δ',
- headGroup:'Figures',
- visible:0,
- number:1
- },
- {
- field:'fafOperatedFlights',
- text:'Operated flights',
- headGroup:'Figures',
- visible:1,
- number:1
- },
- {
- field:'fafOperatedFlightsDelta',
- text:'Operated flights Δ',
- headGroup:'Figures',
- visible:1,
- number:1
- },
- {
- field:'fafSeatsOffered',
- text:'Seats offered',
- headGroup:'Figures',
- visible:1,
- number:1
- },
- {
- field:'fafSeatsOfferedDelta',
- text:'Seats offered Δ',
- headGroup:'Figures',
- visible:1,
- number:1
- },
- {
- field:'fafsko',
- text:'SKO',
- headGroup:'Figures',
- visible:0,
- number:1
- },
- {
- field:'fafskoDelta',
- text:'SKO Δ',
- headGroup:'Figures',
- visible:0,
- number:1
- },
- {
- field:'fafCargoOffered',
- text:'Cargo offered',
- headGroup:'Figures',
- visible:1,
- number:1
- },
- {
- field:'fafCargoOfferedDelta',
- text:'Cargo offered Δ',
- headGroup:'Figures',
- visible:1,
- number:1
- },
- {
- field:'faffko',
- text:'FKO',
- headGroup:'Figures',
- visible:0,
- number:1
- },
- {
- field:'faffkoDela',
- text:'FKO Δ',
- headGroup:'Figures',
- visible:0,
- number:1
- },
- {
- field:'scheduleDate',
- text:'Schedule Date',
- headGroup:'Schedule',
- visible:0,
- number:0
- },
- {
- field:'scheduleDatePre',
- text:'Previous Schedule Date',
- headGroup:'Schedule',
- visible:0,
- number:0
- },
- {
- field:'scheduleHubs',
- text:'Hubs (routes)',
- headGroup:'Schedule',
- visible:1,
- number:0
- },
- {
- field:'scheduleFltNr',
- text:'# of flight numbers',
- headGroup:'Schedule',
- visible:0,
- number:1
- },
- {
- field:'scheduleFltNrDelta',
- text:'# of flight numbers Δ',
- headGroup:'Schedule',
- visible:0,
- number:1
- },
- {
- field:'schedulePAXFreq',
- text:'PAX frequency',
- headGroup:'Schedule',
- visible:0,
- number:1
- },
- {
- field:'schedulePAXFreqDelta',
- text:'PAX frequency Δ',
- headGroup:'Schedule',
- visible:0,
- number:1
- },
- {
- field:'scheduleCargoFreq',
- text:'Cargo frequency',
- headGroup:'Schedule',
- visible:0,
- number:1
- },
- {
- field:'scheduleCargoFreqDelta',
- text:'Cargo frequency Δ',
- headGroup:'Schedule',
- visible:0,
- number:1
- },
- {
- field:'scheduleTotalFreq',
- text:'Total frequency',
- headGroup:'Schedule',
- visible:1,
- number:1
- },
- {
- field:'scheduleTotalFreqDelta',
- text:'Total frequency Δ',
- headGroup:'Schedule',
- visible:1,
- number:1
- },
- {
- field:'actionOpenAirline',
- text:'Open airline page',
- headGroup:'Actions',
- visible:1,
- number:0
- },
- {
- field:'actionOpenSchedule',
- text:'Show airline schedule',
- headGroup:'Actions',
- visible:1,
- number:0
- },
- {
- field:'actionRemoveAirline',
- text:'Remove airline',
- headGroup:'Actions',
- visible:0,
- number:0
- }
- ];
- settings.competitorMonitoring = {
- tableColumns:columns
- };
-}
-function getRatingNr(rating){
- switch(rating) {
- case 'AAA':
- return 10;
- break;
- case 'AA':
- return 9;
- break;
- case 'A':
- return 8;
- break;
- case 'BBB':
- return 7;
- break;
- case 'BB':
- return 6;
- break;
- case 'B':
- return 5;
- break;
- case 'CCC':
- return 4;
- break;
- case 'CC':
- return 3;
- break;
- case 'C':
- return 2;
- break;
- case 'D':
- return 1;
- break;
- default:
- return 0;
- }
-}
-function getDelta(newNr,oldNr){
- return newNr - oldNr;
-};
-//Display Aircraft aircraftProfitability
-function displayAircraftProfitability(){
- if(!settings.aircraftProfitability){
- settings.aircraftProfitability = {};
- }
- if(!settings.aircraftProfitability.hideColumn){
- settings.aircraftProfitability.hideColumn = [];
- }
- //columns
- let columns = [
- {
- category:'Aircraft',
- title:'Aircraft ID',
- data:'aircraftId',
- sortable:1,
- visible:1,
- number:1,
- id:1
- },
- {
- category:'Aircraft',
- title:'Registration',
- data:'registration',
- sortable:1,
- visible:1
- },
- {
- category:'Aircraft',
- title:'Equipment',
- data:'equipment',
- sortable:1,
- visible:1
- },
- {
- category:'Aircraft',
- title:'Fleet',
- data:'fleet',
- sortable:1,
- visible:1
- },
- {
- category:'Aircraft',
- title:'Nickname',
- data:'nickname',
- sortable:1,
- visible:1
- },
- {
- category:'Aircraft',
- title:'Note',
- data:'note',
- sortable:1,
- visible:1
- },
- {
- category:'Aircraft',
- title:'Age',
- data:'age',
- sortable:1,
- visible:1,
- number:1
- },
- {
- category:'Aircraft',
- title:'Maintenance',
- data:'maintenance',
- sortable:1,
- visible:1,
- number:1
- },
- {
- category:'Aircraft',
- title:'Date',
- data:'dateAircraft',
- sortable:1,
- visible:1
- },
- {
- category:'Profit',
- title:'Total flights',
- data:'totalFlights',
- sortable:1,
- visible:1,
- number:1
- },
- {
- category:'Profit',
- title:'Finished flights',
- data:'finishedFlights',
- sortable:1,
- visible:1,
- number:1
- },
- {
- category:'Profit',
- title:'Profit/loss flights',
- data:'profitFlights',
- sortable:1,
- visible:1,
- number:1
- },
- {
- category:'Profit',
- title:'Profit',
- data:'profit',
- sortable:1,
- visible:1,
- number:1,
- format:'money'
- },
- {
- category:'Profit',
- title:'Profit extract date',
- data:'dateProfit',
- sortable:1,
- visible:1
- }
- ];
- if(settings.aircraftProfitability.hideColumn.length){
- columns.forEach(function(column){
- settings.aircraftProfitability.hideColumn.forEach(function(hideColumn){
- if(column.data == hideColumn){
- column.visible = 0;
- }
- });
- });
- }
-
- let key = server + airline.name + 'aircraftFleet';
- //Get storage fleet data
- chrome.storage.local.get(key, function(result) {
- //get aircraft flight data
- let aircraftFleetData = result[key];
- if(aircraftFleetData){
- let keys = [];
- aircraftFleetData.fleet.forEach(function(value){
- keys.push(server + 'aircraftFlights' + value.aircraftId);
- });
- chrome.storage.local.get(keys, function(result) {
- for(let aircraftFlightData in result) {
- for (let i=0; i < aircraftFleetData.fleet.length; i++) {
- if(aircraftFleetData.fleet[i].aircraftId == result[aircraftFlightData].aircraftId){
- aircraftFleetData.fleet[i].profit = {
- date:result[aircraftFlightData].date,
- finishedFlights:result[aircraftFlightData].finishedFlights,
- profit:result[aircraftFlightData].profit,
- profitFlights:result[aircraftFlightData].profitFlights,
- time:result[aircraftFlightData].time,
- totalFlights:result[aircraftFlightData].totalFlights,
- };
- }
- }
- }
- let data = prepareAircraftProfitabilityData(aircraftFleetData);
- let tableDiv;
- if(data.length){
- tableDiv = generateTable(
- {
- column:columns,
- data:data,
- columnPrefix:'aes-aircraftProfit-',
- tableSettings:1,
- options:['openAircraft','removeAircraft','reloadTableAircraftProfit','applyFilter','removeSelected'],
- filter:settings.aircraftProfitability.filter,
- hideColumn:settings.aircraftProfitability.hideColumn,
- tableSettingStorage:'aircraftProfitability'
- }
- );
- } else {
- //Never happens or only when fleet = 0 because of updated script this output is copied bellow
- tableDiv = $('
').text('No aircraft data in memory. Open fleet management to extract aircraft data.')
- }
- //Div
- let div = $('
').append(tableDiv);
- let mainDiv = $("#aes-div-dashboard");
- //Build layout
- mainDiv.empty();
- let title = $(' ').text('Aircraft Profitability');
- mainDiv.append(title,div);
-
- });
- } else {
- //No data
- //Div
- let tableDiv = $('
').text('No aircraft data in memory. Open fleet management to extract aircraft data.')
- let div = $('
').append(tableDiv);
- let mainDiv = $("#aes-div-dashboard");
- //Build layout
- mainDiv.empty();
- let title = $(' ').text('Aircraft Profitability');
- mainDiv.append(title,div);
- }
- });
- function prepareAircraftProfitabilityData(storage){
- let data = [];
- storage.fleet.forEach(function(value){
- let profit = {};
- if(value.profit){
- profit.totalFlights=value.profit.totalFlights;
- profit.finishedFlights=value.profit.finishedFlights;
- profit.profitFlights=value.profit.profitFlights;
- profit.profit=value.profit.profit;
- profit.dateProfit=formatDate(value.profit.date)+' '+value.profit.time;
- }
- data.push({
- aircraftId:value.aircraftId,
- registration:value.registration,
- equipment:value.equipment,
- fleet:value.fleet,
- nickname:value.nickname,
- note:value.note,
- age:value.age,
- maintenance:value.maintanance,
- dateAircraft:formatDate(value.date)+' '+value.time,
- totalFlights:profit.totalFlights,
- finishedFlights:profit.finishedFlights,
- profitFlights:profit.profitFlights,
- profit:profit.profit,
- dateProfit:profit.dateProfit
- });
- });
- return data;
- }
-}
-
-//Auto table generator
-function generateTable(tableOptionsRule){
- let tableHtml = $('');
- let table = {cell:{},row:{},tableHtml:tableHtml};
- //Table Categories
- let tableCategory = {};
- tableOptionsRule.column.forEach(function(value){
- if(value.visible){
- if(!tableCategory[value.category]){
- tableCategory[value.category] = 1;
- } else {
- tableCategory[value.category]++;
- }
- }
- });
- table.cell.category = [];
- //Add checkbox
- if(tableOptionsRule.tableSettings){
- table.cell.category.push(' ')
- }
- for(let category in tableCategory) {
- table.cell.category.push(''+category+' ');
- }
-
- //Table Headers
- table.cell.header = [];
- tableOptionsRule.column.forEach(function(value){
- if(value.visible){
- if(value.sortable){
- //Sort
- let sort = $(' ').text(value.title);
- sort.click(function(){
- masterSortTable(value.data,value.number,table.tableHtml,tableOptionsRule.columnPrefix);
- });
- table.cell.header.push($(' ').html(sort));
- } else {
- table.cell.header.push(''+value.title+' ');
- }
- }
- });
- //Head
- table.row.head = [];
- table.row.head.push($(' ').append(table.cell.category));
- table.row.head.push($(' ').append(table.cell.header));
- //Table Body
- table.row.body = [];
- tableOptionsRule.data.forEach(function(dataValue){
- let cell = [];
- //Add checkbox
- if(tableOptionsRule.tableSettings){
- cell.push(' ');
- }
- let id;
- tableOptionsRule.column.forEach(function(colValue){
- if(colValue.id){
- id = dataValue[colValue.data]
- }
- if(colValue.visible){
- let td = $(' ').addClass(tableOptionsRule.columnPrefix+colValue.data);
- if(colValue.format){
- td.html(masterCellFormat(colValue.format,dataValue[colValue.data]))
- } else {
- td.html(dataValue[colValue.data])
- }
- cell.push(td);
- }
- });
- table.row.body.push($(' ').attr('id', id).append(cell));
- });
- let thead = $(' ').append(table.row.head);
- let tbody = $(' ').append(table.row.body);
- table.tableHtml.append(thead,tbody);
- let tableWell = $('
').append(table.tableHtml);
-
- //Table Settings
- let settingsDiv = '';
- if(tableOptionsRule.tableSettings){
- let divCol = [];
- //Options
- divCol.push($('
').html(masterTableOptions(table.tableHtml,tableOptionsRule.options)));
- divCol.push($('
').html(masterTableFilter(tableOptionsRule.filter,tableOptionsRule.column)));
- divCol.push($('
').html(masterTableColumns()));
- settingsDiv = $('
').append(divCol)
- }
-
- let div = $('
').append(settingsDiv,tableWell);
- return div;
- //Table functions
- function masterSortTable(collumn,number,table,collumnPrefix){
- let tableRows = $('tbody tr',table);
- let tableBody = $('tbody',table);
- tableBody.empty();
- let indexes = [];
- tableRows.each(function(){
- if(number){
- let value = parseInt($(this).find("."+collumnPrefix+collumn).text(),10);
- if(value){
- indexes.push(value);
- } else {
- indexes.push(0);
- }
- } else {
- indexes.push($(this).find("."+collumnPrefix+collumn).text());
- }
- });
- indexes = [...new Set(indexes)];
- let sorted = [...indexes];
- if(number){
- sorted.sort(function(a, b){
- if (a > b) return -1;
- if (a < b) return 1;
- if (a = b) return 0;
- });
- } else {
- sorted.sort();
- }
- let same = 1;
- for(let i = 0; i < indexes.length; i++){
- if(indexes[i] !== sorted[i]){
- same = 0;
- }
- }
- if(same){
- if(number){
- sorted.sort(function(a, b){
- if (a < b) return -1;
- if (a > b) return 1;
- if (a = b) return 0;
- });
- } else {
- sorted.reverse();
- }
- }
- for(let i=0; i= 0 ; j--){
- if(number){
- let value = parseInt($(tableRows[j]).find("."+collumnPrefix+collumn).text(),10);
- if(!value){
- value = 0;
- }
- if(value == sorted[i]){
- tableBody.append($(tableRows[j]));
- tableRows.splice(j, 1);
- }
- } else {
- if($(tableRows[j]).find("."+collumnPrefix+collumn).text() == sorted[i]){
- tableBody.append($(tableRows[j]));
- tableRows.splice(j, 1);
- }
- }
- }
- }
- }
- function masterCellFormat(type,value){
- if(!value){
- return '';
- }
- switch(type) {
- case 'money':
- let span = $(' ');
- let text = '';
- if(value > 0){
- span.addClass('good');
- text = '+'
- }
- if(value < 0){
- span.addClass('bad');
- }
- text = text + value + ' AS$';
- span.text(text);
- return span;
- break;
- default:
- return value;
- }
- }
- function masterTableOptions(table,options){
- let div = $('
');
- options.forEach(function(value,index){
- if(index){
- let span = $(' ');
- div.append(span);
- }
- div.append(masterTableOptionsHandle(value));
- });
- //Closable legend
- let link = $(' ').text('Options');
- let legend = $(' ').html(link);
- link.click(function(){
- div.toggle();
- });
- let fieldset = $(' ').append(legend,div);
- return fieldset;
-
- //Functions
- function masterTableOptionsHandle(value){
- switch(value) {
- case 'openAircraft':
- return masterTableOptionsOpenAircraft();
- break;
- case 'reloadTableAircraftProfit':
- return masterTableOptionsReloadTableAP();
- break;
- case 'removeAircraft':
- return masterTableOptionsRemoveAircraft();
- break;
- case 'applyFilter':
- return masterTableOptionsApplyFilter();
- break;
- case 'removeSelected':
- return masterTableOptionsRemoveSelected();
- break;
- default:
- // code block
- }
- //Option Functions
- function masterTableOptionsOpenAircraft(){
- let btn = $('open aircraft (max 10) ');
- btn.click( function(){
- let urls = $('tbody tr',table).has('input:checked').map(function() {
- let id = $(this).attr('id');
- let url = 'https://'+server+'.airlinesim.aero/app/fleets/aircraft/'+id+'/1';
- return url;
- }).toArray();
- //Open new tabs
- for (let i = 0; i < urls.length; i++) {
- window.open(urls[i], '_blank');
- if(i==10){
- break;
- }
- }
- });
- return btn;
- }
- function masterTableOptionsReloadTableAP(){
- let btn = $('reload table ');
- btn.click( function(){
- displayAircraftProfitability();
- });
- return btn;
- }
- function masterTableOptionsRemoveAircraft(){
- let btn = $('remove aircraft (permanent) ');
- btn.click( function(){
- let id = [];
- let aircraftKey =[];
- $('tbody tr',table).has('input:checked').each(function() {
- let localId = $(this).attr('id');
- id.push(localId);
- aircraftKey.push(server + 'aircraftFlights' + localId);
- $(this).remove();
- });
- if(id.length){
- let fleetKey = server + airline.name + 'aircraftFleet';
- chrome.storage.local.get(fleetKey, function(result) {
- let storedFleetData = result[fleetKey];
- let newFleet = storedFleetData.fleet.filter(function(value) {
- let keep = 1;
- id.forEach(function(idVal){
- if(idVal == value.aircraftId){
- keep = 0;
- }
- });
- return keep;
- });
- storedFleetData.fleet = newFleet;
- chrome.storage.local.set({[fleetKey]: storedFleetData}, function() {
- chrome.storage.local.remove(aircraftKey, function() {});
- });
- });
- }
- });
- return btn;
- }
- function masterTableOptionsApplyFilter(){
- let btn = $('apply filter ');
- btn.click( function(){
- let filter = [];
- table.closest(".as-panel").find('fieldset:eq(1) table tbody tr').each(function(){
- filter.push(
- {
- titlecode:$(this).find('input').val(),
- title:$(this).find('td:eq(0)').text(),
- operation:$(this).find('td:eq(1)').text(),
- value:$(this).find('td:eq(2)').text()
- }
- )
- });
- settings[tableOptionsRule.tableSettingStorage].filter = filter;
- chrome.storage.local.set({settings: settings}, function(){
- $('tbody tr',table).each(function(){
- let row = this;
- filter.forEach(function(filter){
- let cell = $(row).find("."+tableOptionsRule.columnPrefix+filter.titlecode).text();
- //if(cell){
- //Get collumn info if number or not
- let number;
- for(let i=0;i':
- if(cell < value){
- $(row).remove();
- }
- break;
- case '<':
- if(cell > value){
- $(row).remove();
- }
- }
- });
- });
- });
- });
- return btn;
- }
- function masterTableOptionsRemoveSelected(){
- let btn = $('hide selected ');
- btn.click( function(){
- $('tbody tr',table).has('input:checked').remove();
- });
- return btn;
- }
- }
- }
- function masterTableFilter(filter,column){
- //Table head
- let th = [];
- th.push('Column ');
- th.push('Operation ');
- th.push('Value ');
- th.push(' ');
- let thead= $(' ').append($(' ').append(th));
- //Table body
- let row = [];
- if(filter){
- filter.forEach(function(fil){
- row.push($(' ').append(masterTableFilterAddBodyRow(fil.titlecode,fil.title,fil.operation,fil.value)));
- });
- }
-
- let tbody = $(' ').append(row);
- //Table foot
- //select collumn
- let option1 = [];
- column.forEach(function(col){
- option1.push(''+col.title+' ');
- });
- let select1 = $(' ').append(option1);
- //Select value
- let option = [];
- option.push('= ');
- option.push('!= ');
- option.push('> ');
- option.push('< ');
- let select = $(' ').append(option);
- //Value
- let input = $(' ');
- //Add button
- let btn = $(' ').text('Add Row');
- btn.click(function(){
- let column = $('option:selected',select1).text();
- let columnVal = $('option:selected',select1).val();
- let operation = $('option:selected',select).text();
- let value = input.val();
- tbody.append($(' ').append(masterTableFilterAddBodyRow(columnVal,column,operation,value)));
- });
- //Footer rows
- let tf = [];
- tf.push($(' ').html(select1));
- tf.push($(' ').html(select));
- tf.push($(' ').html(input));
- tf.push($(' ').append(btn));
- let tfoot= $(' ').append($(' ').append(tf));
- let tableFilter = $('').append(thead,tbody,tfoot);
- let divTable = $('
').append(tableFilter);
- //Closable legend
- let link = $(' ').text('Filter');
- let legend = $(' ').html(link);
- link.click(function(){
- divTable.toggle();
- });
- let fieldset = $(' ').append(legend,divTable);
- return fieldset;
- //Functions
- function masterTableFilterAddBodyRow(titleCode,title,operation,value){
- let td = [];
- td.push(' '+title+' ');
- td.push(''+operation+' ');
- td.push(''+value+' ');
- let deleteBtn = $(' ').html(' ');
- deleteBtn.click(function(){
- $(this).closest("tr").remove();
- });
- td.push($(' ').append(deleteBtn));
- return td;
- }
- }
- function masterTableColumns(){
- //Table head
- let th = [];
- th.push('Show ');
- th.push('Column ');
- let thead= $(' ').append($(' ').append(th));
- //Table body
- let row = [];
- tableOptionsRule.column.forEach(function(col){
- let td = []
- let input = $(' ');
- input.change(function(){
- if(!tableOptionsRule.hideColumn){
- tableOptionsRule.hideColumn = [];
- }
- let newHideColumns = [];
- let currentColumn = $(this).val();
- newHideColumns = tableOptionsRule.hideColumn.filter(function(value){
- return value != currentColumn;
- });
- if(!this.checked){
- newHideColumns.push(currentColumn);
- }
-
- tableOptionsRule.hideColumn = newHideColumns;
- settings[tableOptionsRule.tableSettingStorage].hideColumn = tableOptionsRule.hideColumn;
- chrome.storage.local.set({settings: settings}, function(){});
- })
- if(col.visible){
- input.prop('checked', true);
- }
- td.push($(' ').append(input));
- td.push($(' ').text(col.title));
- row.push($(' ').append(td));
- });
- let tbody = $(' ').append(row);
- let tableColumns = $('').append(thead,tbody);
- let divTable = $('
').append(tableColumns).hide();
- //Closable legend
- let link = $(' ').text('Columns');
- let legend = $(' ').html(link);
- link.click(function(){
- divTable.toggle();
- });
- let fieldset = $(' ').append(legend,divTable);
- return fieldset;
- }
-}
-//Display general helper functions
-function generalAddScheduleRow(tbody){
- let td1 = $(' ').text("Schedule");
- let td2 = $(' ');
- let td3 = $(' ');
- let row = $(' ').append(td1,td2,td3);
- tbody.append(row);
- //Get schedule
- let scheduleKey = server+airline.code+'schedule';
- chrome.storage.local.get([scheduleKey], function(result) {
- let scheduleData = result[scheduleKey];
- if(scheduleData){
- let lastUpdate = getDate('schedule',scheduleData.date);
- let diff = getDateDiff(todayDate.date,lastUpdate);
- let span = $(' ').text('Last schedule extract '+formatDate(lastUpdate)+' ('+diff+' days ago). Extract new schedule if there are new routes.');
- if(diff >= 0 && diff < 7){
- span.addClass('good');
- } else {
- span.addClass('warning');
- }
- td2.append(span);
- generalUpdateScheduleAction(td3);
-
-
-
- } else {
- //no schedule
- td2.html('No Schedule data found. Extract schedule or some AES parts will not work ');
- generalUpdateScheduleAction(td3);
- }
-
-
-
- });
-}
-function generalUpdateScheduleAction(td3){
- let btn = $('extract schedule data ');
- btn.click(function(){
- settings.schedule.autoExtract = 1;
- //get schedule link
- let link = $('#enterprise-dashboard table:eq(0) tfoot td a:eq(2)');
- chrome.storage.local.set({settings: settings}, function() {
- link[0].click();
- });
- });
- td3.append(btn);
-}
-function generalAddPersonelManagementRow(tbody){
- let td = [];
- td.push($(' ').text("Personnel Management"));
- td.push($(' '));
- td.push($(' '));
- let row = $(' ').append(td);
- tbody.append(row);
- //Get Status
- let key = server+airline.name+'personelManagement';
- chrome.storage.local.get([key], function(result) {
- let personelManagementData = result[key];
- if(personelManagementData){
- let lastUpdate = personelManagementData.date;
- let diff = getDateDiff(todayDate.date,lastUpdate);
- let span = $(' ').text('Last personnel salary update: '+formatDate(lastUpdate)+' ('+diff+' days ago).');
- if(diff >= 0 && diff < 7){
- span.addClass('good');
- } else {
- span.addClass('warning');
- }
- td[1].append(span);
- } else {
- //no schedule
- td[1].html('No personnel salary update date found. ');
- }
- });
-
- //Action
- let btn = $('open personel management ');
- btn.click(function(){
- //get schedule link
- let link = $('#as-navbar-main-collapse > ul > li:eq(4) > ul > li:eq(5) > a');
- link[0].click();
- });
- td[2].append(btn);
-}
-//Display default
-function displayDefault(){
- let mainDiv = $("#aes-div-dashboard");
- mainDiv.empty();
-}
-
-//Table sort and other functions
-function SortTable(collumn,number,tableId,collumnPrefix){
- let tableRows = $('#'+tableId+' tbody tr');
- let tableBody = $('#'+tableId+' tbody');
- tableBody.empty();
- let indexes = [];
- tableRows.each(function(){
- if(number){
- let value = parseInt($(this).find("."+collumnPrefix+collumn).text(),10);
- if(value){
- indexes.push(value);
- } else {
- indexes.push(0);
- }
- } else {
- indexes.push($(this).find("."+collumnPrefix+collumn).text());
- }
- });
- indexes = [...new Set(indexes)];
- let sorted = [...indexes];
- if(number){
- sorted.sort(function(a, b){
- if (a > b) return -1;
- if (a < b) return 1;
- if (a = b) return 0;
- });
- } else {
- sorted.sort();
- }
- let same = 1;
- for(let i = 0; i < indexes.length; i++){
- if(indexes[i] !== sorted[i]){
- same = 0;
- }
- }
- if(same){
- if(number){
- sorted.sort(function(a, b){
- if (a < b) return -1;
- if (a > b) return 1;
- if (a = b) return 0;
- });
- } else {
- sorted.reverse();
- }
- }
- for(let i=0; i= 0 ; j--){
- if(number){
- let value = parseInt($(tableRows[j]).find("."+collumnPrefix+collumn).text(),10);
- if(!value){
- value = 0;
- }
- if(value == sorted[i]){
- tableBody.append($(tableRows[j]));
- tableRows.splice(j, 1);
- }
- } else {
- if($(tableRows[j]).find("."+collumnPrefix+collumn).text() == sorted[i]){
- tableBody.append($(tableRows[j]));
- tableRows.splice(j, 1);
- }
- }
- }
- }
-}
-
-
-
-
-//Helper
-function getDate(type, scheduleData){
- switch(type) {
- case 'schedule':
- //scheduleData must be schedule object with dates as properties
- let dates = [];
- for(let date in scheduleData){
- if (Number.isInteger(parseInt(date))) {
- dates.push(date);
- }
- }
- dates.reverse();
- return dates[0];
- case 'today':
- let a = $(".as-footer-line-element:has('.fa-clock-o')").text().trim();
- let b = a.split(" ");
- //For date
- let dateTemp = b[0].split("-");
- let date;
- if(dateTemp.length == 1){
- //German
- dateTemp = dateTemp[0].split(".");
- date = dateTemp.map(function(value){
- return value.replace(/[^A-Za-z0-9]/g, '');
- });
- date = date[2] + date[1] + date[0];
- } else {
- //English
- date = dateTemp.map(function(value){
- return value.replace(/[^A-Za-z0-9]/g, '');
- });
- date = date[0] + date[1] + date[2];
- }
- //For time
- let time = b[b.length-2] +' '+b[b.length-1];
- return {date:date,time:time};
- default:
- return 0;
- }
-}
-function getDateDiff(date1,date2){
- //Returns day differnece between date1 - date2
- let d1 = new Date(formatDate(date1)+'T12:00:00Z');
- let d2 = new Date(formatDate(date2)+'T12:00:00Z');
- let diff = Math.round((d1 - d2)/(1000 * 60 * 60 * 24));
- return diff;
-}
-function getAirlineCode(){
- //code
- let airline = $("#enterprise-dashboard table tr:eq(1) td").text();
- //name
- let name = $("#as-navbar-main-collapse ul li:eq(0) a:eq(0)").text().trim().replace(/[^A-Za-z0-9]/g, '');
- return {code:airline,name:name};
-}
-function getServerName(){
- let server = window.location.hostname
- server = server.split('.');
- return server[0];
-}
-function formatDate(date){
- return date.substring(0, 4)+'-'+date.substring(4, 6)+'-'+date.substring(6, 8);
-}
-function formatWeekDate(date){
- let a = date.toString();
- return a.substring(0, 2)+'/'+a.substring(2, 6);
-}
+"use strict";
+//MAIN
+//Global vars
+var settings, airline, server, todayDate;
+$(function() {
+ todayDate = AES.getServerDate();
+ airline = AES.getAirlineCode();
+ server = AES.getServerName();
+ chrome.storage.local.get(['settings'], function(result) {
+ settings = result.settings;
+
+ displayDashboard();
+ dashboardHandle();
+ $("#aes-select-dashboard-main").change(function() {
+ dashboardHandle();
+ });
+ });
+});
+
+function displayDashboard() {
+ let mainDiv = $("#enterprise-dashboard");
+ mainDiv.before(
+ `
+ AirlineSim Enhancement Suite Dashboard
+
+
+
+ Show Dashboard
+
+
+ General
+ Route Management
+ Competitor Monitoring
+ Aircraft Profitability
+ None
+
+
+
+
+
+ `
+ );
+ $("#aes-select-dashboard-main").val(settings.general.defaultDashboard);
+}
+
+function dashboardHandle() {
+ let value = $("#aes-select-dashboard-main").val();
+ settings.general.defaultDashboard = value;
+ chrome.storage.local.set({ settings: settings }, function() {});
+ switch (value) {
+ case 'general':
+ displayGeneral();
+ break;
+ case 'routeManagement':
+ displayRouteManagement();
+ break;
+ case 'competitorMonitoring':
+ displayCompetitorMonitoring();
+ break;
+ case 'hr':
+ displayHr();
+ break;
+ case 'aircraftProfitability':
+ displayAircraftProfitability();
+ break;
+ default:
+ displayDefault();
+ }
+}
+//Route Management Dashbord
+function displayRouteManagement() {
+ //Check ROute Managemetn seetings
+ if (!settings.routeManagement) {
+ setDefaultRouteManagementSettings();
+ }
+
+ let mainDiv = $("#aes-div-dashboard");
+ //Build layout
+ mainDiv.empty();
+ let title = $(' ').text('Route Management');
+ let div = $('
');
+ mainDiv.append(title, div);
+ //Get schedule
+ let scheduleKey = server + airline.code + 'schedule';
+ chrome.storage.local.get([scheduleKey], function(result) {
+ let scheduleData = result[scheduleKey];
+ if (scheduleData) {
+ // Table
+ generateRouteManagementTable(scheduleData);
+
+ // Option buttons
+ let fieldsetEl = document.createElement("fieldset")
+ let legendEl = document.createElement("legend")
+ let buttonGroupEl = document.createElement("div")
+
+ let buttonElements = {
+ "selectFirstTen": {
+ "label": "select first 10"
+ },
+ "hideChecked": {
+ "label": "hide checked"
+ },
+ "openInventory": {
+ "label": "open inventory (max 10)"
+ },
+ "reloadTable": {
+ "label": "reload table"
+ }
+ }
+
+ for (let key in buttonElements) {
+ let buttonObj = buttonElements[key]
+ let buttonEl = document.createElement("button")
+ let buttonClassNames = buttonObj?.classNames
+ let buttonType = buttonObj?.type
+ let buttonDefaultClassNames = "btn btn-default"
+ buttonEl.innerText = buttonObj.label
+
+ if (buttonType) {
+ buttonEl.setAttribute("type", buttonType)
+ } else {
+ buttonEl.setAttribute("type", "button")
+ }
+
+ if (buttonClassNames) {
+ buttonEl.className = buttonClassNames
+ } else {
+ buttonEl.className = buttonDefaultClassNames
+ }
+
+ buttonObj.element = buttonEl
+ buttonGroupEl.append(buttonEl)
+ }
+
+ legendEl.innerText = "Options"
+ buttonGroupEl.classList.add("btn-group")
+
+ fieldsetEl.append(legendEl, buttonGroupEl)
+
+ let optionsDiv = $('
').append(fieldsetEl);
+
+ // Button actions
+
+ // Select first ten
+ buttonElements["selectFirstTen"].element.addEventListener("click", function() {
+ let count = 0
+ $('#aes-table-routeManagement tbody tr').each(function() {
+ $(this).find("input").prop('checked', true);
+ count++;
+ if (count > 10) {
+ return false;
+ }
+ })
+ });
+
+ // Remove checked
+ buttonElements["hideChecked"].element.addEventListener("click", function() {
+ $('#aes-table-routeManagement tbody tr').has('input:checked').remove();
+ });
+
+ // Open Inventory
+ buttonElements["openInventory"].element.addEventListener("click", function() {
+ //Get checked collumns
+ let pages = $('#aes-table-routeManagement tbody tr').has('input:checked').map(function() {
+ let orgdest = $(this).attr('id');
+ orgdest = orgdest.split("-");
+ orgdest = orgdest[2];
+ //let orgdest = $(this).find("td:eq(1)").text() + $(this).find("td:eq(2)").text();
+ let url = 'https://' + server + '.airlinesim.aero/app/com/inventory/' + orgdest;
+ return url;
+ }).toArray();
+
+ //Open new tabs
+ for (let i = 0; i < pages.length; i++) {
+ window.open(pages[i], '_blank');
+ if (i == 10) {
+ break;
+ }
+ }
+ });
+
+ // Reload table reloadTable
+ buttonElements["reloadTable"].element.addEventListener("click", function() {
+ generateRouteManagementTable(scheduleData);
+ });
+ let divRow = $('
').append(optionsDiv, displayRouteManagementFilters(), displayRouteManagementCollumns())
+ div.prepend(divRow);
+ //Collumns selector Checkbox listener
+ $('#aes-table-routeManagement-collumns input').change(function() {
+ let show;
+ if (this.checked) {
+ show = 1;
+ } else {
+ show = 0;
+ }
+ let value = $(this).val();
+ settings.routeManagement.tableCollumns.forEach(function(col) {
+ if (col.class == value) {
+ col.show = show;
+ }
+ });
+ chrome.storage.local.set({ settings: settings }, function() {});
+ });
+
+ } else {
+ //no schedule
+ div.append("Need schedule info to show this section. Change Dashboard to General -> Schedule -> Extract Schedule.")
+ }
+ });
+}
+
+function setDefaultRouteManagementSettings() {
+ let collumns = [
+ {
+ name: 'Origin',
+ class: 'aes-origin',
+ number: 0,
+ show: 1,
+ value: 'origin'
+ },
+ {
+ name: 'Destination',
+ class: 'aes-destination',
+ number: 0,
+ show: 1,
+ value: 'destination'
+ },
+ {
+ name: 'Hub',
+ class: 'aes-hub',
+ number: 0,
+ show: 1,
+ value: 'hub'
+ },
+ {
+ name: 'OD',
+ class: 'aes-od',
+ number: 0,
+ show: 1,
+ value: 'odName'
+ },
+ {
+ name: 'Direction',
+ class: 'aes-direction',
+ number: 0,
+ show: 1,
+ value: 'direction'
+ },
+ {
+ name: '# of flight numbers',
+ class: 'aes-fltNr',
+ number: 1,
+ show: 1,
+ value: 'fltNr'
+ },
+ {
+ name: 'PAX frequency',
+ class: 'aes-paxFreq',
+ number: 1,
+ show: 1,
+ value: 'paxFreq'
+ },
+ {
+ name: 'Cargo frequency',
+ class: 'aes-cargoFreq',
+ number: 1,
+ show: 1,
+ value: 'cargoFreq'
+ },
+ {
+ name: 'Total Frequency',
+ class: 'aes-totalFreq',
+ number: 1,
+ show: 1,
+ value: 'totalFreq'
+ },
+ {
+ name: 'Analysis date',
+ class: 'aes-analysisDate',
+ number: 0,
+ show: 1
+ },
+ {
+ name: 'Previous Analysis date',
+ class: 'aes-analysisPreDate',
+ number: 0,
+ show: 1
+ },
+ {
+ name: 'Pricing date',
+ class: 'aes-pricingDate',
+ number: 0,
+ show: 1
+ },
+ {
+ name: 'PAX load',
+ class: 'aes-paxLoad',
+ number: 1,
+ show: 1
+ },
+ {
+ name: 'PAX load Δ',
+ class: 'aes-paxLoadDelta',
+ number: 1,
+ show: 1
+ },
+ {
+ name: 'Cargo load',
+ class: 'aes-cargoLoad',
+ number: 1,
+ show: 1
+ },
+ {
+ name: 'Cargo load Δ',
+ class: 'aes-cargoLoadDelta',
+ number: 1,
+ show: 1
+ },
+ {
+ name: 'Total load',
+ class: 'aes-load',
+ number: 1,
+ show: 1
+ },
+ {
+ name: 'Total load Δ',
+ class: 'aes-loadDelta',
+ number: 1,
+ show: 1
+ },
+ {
+ name: 'PAX index',
+ class: 'aes-paxIndex',
+ number: 1,
+ show: 1
+ },
+ {
+ name: 'PAX index Δ',
+ class: 'aes-paxIndexDelta',
+ number: 1,
+ show: 1
+ },
+ {
+ name: 'Cargo index',
+ class: 'aes-cargoIndex',
+ number: 1,
+ show: 1
+ },
+ {
+ name: 'Cargo index Δ',
+ class: 'aes-cargoIndexDelta',
+ number: 1,
+ show: 1
+ },
+ {
+ name: 'Index',
+ class: 'aes-index',
+ number: 1,
+ show: 1
+ },
+ {
+ name: 'Index Δ',
+ class: 'aes-indexDelta',
+ number: 1,
+ show: 1
+ },
+ {
+ name: 'Route PAX index',
+ class: 'aes-routeIndexPax',
+ number: 1,
+ show: 1
+ },
+ {
+ name: 'Route Cargo index',
+ class: 'aes-routeIndexCargo',
+ number: 1,
+ show: 1
+ },
+ {
+ name: 'Route index',
+ class: 'aes-routeIndex',
+ number: 1,
+ show: 1
+ }
+ ];
+ settings.routeManagement = {
+ tableCollumns: collumns,
+ filter: []
+ };
+}
+
+function routeManagementApplyFilter() {
+ $('#aes-table-routeManagement tbody tr').each(function() {
+ let row = this;
+ settings.routeManagement.filter.forEach(function(filter) {
+ let cell = $(row).find("." + filter.collumnCode).text();
+ //if(cell){
+ //Get collumn info if number or not
+ let number;
+ for (let i = 0; i < settings.routeManagement.tableCollumns.length; i++) {
+ let collumn = settings.routeManagement.tableCollumns[i];
+ if (filter.collumnCode == collumn.class) {
+ number = collumn.number;
+ break;
+ }
+ }
+ let value = filter.value;
+ if (number) {
+ if (cell) {
+ cell = parseInt(cell, 10);
+ }
+ if (value) {
+ value = parseInt(value, 10);
+ }
+ }
+ switch (filter.operation) {
+ case '=':
+ if (cell != value) {
+ $(row).remove();
+ }
+ break;
+ case '!=':
+ if (cell == value) {
+ $(row).remove();
+ }
+ break;
+ case '>':
+ if (cell < value) {
+ $(row).remove();
+ }
+ break;
+ case '<':
+ if (cell > value) {
+ $(row).remove();
+ }
+ }
+ });
+ });
+}
+
+function displayRouteManagementFilters() {
+ //Table head
+ let th = [];
+ th.push('Column ');
+ th.push('Operation ');
+ th.push('Value ');
+ th.push(' ');
+ let thead = $(' ').append($(' ').append(th));
+
+ //Table body
+ let tbody = $(' ');
+ settings.routeManagement.filter.forEach(function(fil) {
+ let td = [];
+ td.push(' ' + fil.collumn + ' ');
+ td.push('' + fil.operation + ' ');
+ td.push('' + fil.value + ' ');
+ td.push(' ');
+ tbody.append($(' ').append(td));
+ });
+
+ //Table foot
+ //select collumn
+ let option1 = [];
+ settings.routeManagement.tableCollumns.forEach(function(col) {
+ option1.push('' + col.name + ' ');
+ });
+ let select1 = $(' ').append(option1);
+
+
+
+ //Select value
+ let option = [];
+ option.push('= ');
+ option.push('!= ');
+ option.push('> ');
+ option.push('< ');
+ let select = $(' ').append(option);
+ //Add button
+ let btn = $(' ').text('Add Row');
+ btn.click(function() {
+ let td = [];
+ let collumn = $(this).closest("tr").find('#aes-select-routeManagement-filter-collumn option:selected').text();
+ let collumnVal = $(this).closest("tr").find('#aes-select-routeManagement-filter-collumn').val();
+ let operation = $(this).closest("tr").find('#aes-select-routeManagement-filter-operation option:selected').text();
+ let value = $(this).closest("tr").find('#aes-select-routeManagement-filter-value').val()
+ td.push(' ' + collumn + ' ');
+ td.push('' + operation + ' ');
+ td.push('' + value + ' ');
+ td.push(' ');
+
+ tbody.append($(' ').append(td));
+ });
+
+ //Footer rows
+ let tf = [];
+ tf.push($(' ').html(select1));
+ tf.push($(' ').html(select));
+ tf.push(' ');
+ tf.push($(' ').append(btn));
+ let tfoot = $(' ').append($(' ').append(tf));
+ let table = $('').append(thead, tbody, tfoot);
+ let divTable = $('
').append(table);
+
+
+ //
+ let saveBtn = $('apply filter ');
+ let saveSpan = $(' ');
+
+ //Closable legend
+ let link = $(' ').text('Filters');
+ let legend = $(' ').html(link);
+ link.click(function() {
+ divForAll.toggle();
+ });
+
+ let divForAll = $('
').append(divTable, saveBtn, saveSpan);
+ let fieldset = $(' ').append(legend, divForAll);
+ let div = $('
').append(fieldset);
+
+ //Delete row for filter row
+ table.on("click", ".aes-a-routeManagement-filter-delete-row", function() {
+ $(this).closest("tr").remove();
+ });
+
+ //Save Button
+ saveBtn.click(function() {
+ saveSpan.removeClass().addClass('warning').text(' saving...');
+ let filter = [];
+ $('#aes-table-routeManagement-filter tbody tr').each(function() {
+ filter.push({
+ collumnCode: $(this).find('input').val(),
+ collumn: $(this).find('td:eq(0)').text(),
+ operation: $(this).find('td:eq(1)').text(),
+ value: $(this).find('td:eq(2)').text(),
+ });
+ });
+ settings.routeManagement.filter = filter;
+ chrome.storage.local.set({ settings: settings }, function() {
+ saveSpan.removeClass().addClass('warning').text(' filtering...');
+ routeManagementApplyFilter()
+ saveSpan.removeClass().addClass('good').text(' done!');
+ });
+ });
+
+ return div;
+}
+
+function displayRouteManagementCollumns() {
+ //Table Head
+ let th = [];
+ th.push('Show ');
+ th.push('Column ');
+ let thead = $(' ').append($(' ').append(th));
+ //Table body
+ let tbody = $(' ');
+
+ settings.routeManagement.tableCollumns.forEach(function(col) {
+ let td = [];
+ //Checkbox
+ if (col.show) {
+ td.push(' ');
+ } else {
+ td.push(' ');
+ }
+ //Name
+ td.push('' + col.name + ' ');
+ tbody.append($(' ').append(td));
+ });
+
+ let table = $('').append(thead, tbody);
+ let divTable = $('
').append(table);
+
+ //Closable legend
+ let link = $(' ').text('Columns');
+ let legend = $(' ').html(link);
+ link.click(function() {
+ $('#aes-div-routeManagement-collumns').toggle();
+ });
+
+ let fieldset = $(' ').append(legend, divTable);
+ let div = $('
').append(fieldset);
+ return div;
+}
+
+function generateRouteManagementTable(scheduleData) {
+ //Remove table
+ $('#aes-div-routeManagement').remove();
+ //Dates
+ let dates = [];
+ for (let date in scheduleData.date) {
+ if (Number.isInteger(parseInt(date))) {
+ dates.push(date);
+ }
+ }
+ dates.reverse();
+ //LatestSchedule
+ let schedule = scheduleData.date[dates[0]].schedule;
+ //Generate top
+ //Table headers
+ let collumns = settings.routeManagement.tableCollumns;
+
+ //Generate table head
+ let thead = $(' ');
+ let th = [];
+ //Check box
+ let checkbox = $(' ');
+ checkbox.change(function() {
+ if (this.checked) {
+ $('#aes-table-routeManagement tbody tr').each(function() {
+ $(this).find("input").prop('checked', true);
+ });
+ } else {
+ $('#aes-table-routeManagement tbody tr').each(function() {
+ $(this).find("input").prop('checked', false);
+ });
+ }
+ });
+ th.push($(' ').html(checkbox));
+ collumns.forEach(function(col) {
+ if (col.show) {
+ let sort = $(' ').html(col.name);
+ sort.click(function() {
+ routeManagementSortTable(col.class, col.number);
+ });
+ th.push($(' ').html(sort));
+ }
+ });
+ //Add open inventory column
+ th.push($('Action '));
+
+ thead.append($(' ').append(th));
+ //Generate table rows
+ let tbody = $(' ');
+ let uniqueOD = [];
+ schedule.forEach(function(od) {
+ //ODs for analysis
+ uniqueOD.push(od.od);
+ //Get values flight numbers and total frequency
+ let fltNr = 0;
+ let paxFreq = 0;
+ let cargoFreq = 0;
+ for (let flight in od.flightNumber) {
+ cargoFreq += od.flightNumber[flight].cargoFreq,
+ paxFreq += od.flightNumber[flight].paxFreq,
+ fltNr++;
+ }
+ let totalFreq = cargoFreq + paxFreq;
+ //hub
+ let hub = od.od.slice(0, 3);
+ let cellValue = {
+ origin: od.origin,
+ destination: od.destination,
+ odName: od.od,
+ direction: od.direction,
+ fltNr: fltNr,
+ paxFreq: paxFreq,
+ cargoFreq: cargoFreq,
+ totalFreq: totalFreq,
+ hub: hub
+ }
+ //Table cells
+ let cell = [];
+ //Checkbox
+ cell.push(' ');
+ //Schedule
+ collumns.forEach(function(col) {
+ if (col.show) {
+ if (col.value) {
+ cell.push($(' ').addClass(col.class).text(cellValue[col.value]));
+ } else {
+ cell.push($(' ').addClass(col.class));
+ }
+ }
+ });
+ let rowId = od.origin + od.destination;
+
+ //Add inventory button
+ let invBtn = 'Inventory '
+ cell.push($(' ').html(invBtn));
+
+ let row = $(' ').append(cell);
+ tbody.append(row);
+ });
+ let table = $('').append(thead, tbody);
+ let divTable = $('
').append(table);
+ $('#aes-div-dashboard-routeManagement').append(divTable)
+ //Analysis collumns
+ //Get unique ODs
+ uniqueOD = [...new Set(uniqueOD)];
+ for (let i = 0; i < uniqueOD.length; i++) {
+ let origin = uniqueOD[i].substring(0, 3);
+ let dest = uniqueOD[i].substring(3, 6);
+ let keyOutbound = server + airline.code + origin + dest + 'routeAnalysis';
+ let keyInbound = server + airline.code + dest + origin + 'routeAnalysis';
+ chrome.storage.local.get([keyOutbound], function(outboundData) {
+ chrome.storage.local.get([keyInbound], function(inboundData) {
+ let outAnalysis = outboundData[keyOutbound];
+ let inAnalysis = inboundData[keyInbound];
+ let outDates, inDates;
+ if (outAnalysis) {
+ outDates = getRouteAnalysisImportantDates(outAnalysis.date);
+ }
+ if (inAnalysis) {
+ inDates = getRouteAnalysisImportantDates(inAnalysis.date);
+ }
+ //Route index
+ let routeIndex = {};
+ let routeIndexPax, routeIndexCargo;
+ if (outAnalysis && inAnalysis) {
+ if (outDates.analysis && inDates.analysis) {
+ let indexType = ['all', 'pax', 'cargo'];
+ indexType.forEach(function(type) {
+ let outIndex = getRouteAnalysisIndex(outAnalysis.date[outDates.analysis].data, type);
+ let inIndex = getRouteAnalysisIndex(inAnalysis.date[inDates.analysis].data, type);
+ if (outIndex && inIndex) {
+ routeIndex[type] = Math.round((outIndex + inIndex) / 2);
+ }
+ });
+ }
+ }
+ //For Outbound
+ updateRouteAnalysisCollumns(outAnalysis, outDates, routeIndex);
+ updateRouteAnalysisCollumns(inAnalysis, inDates, routeIndex);
+ });
+ });
+ }
+}
+
+function routeManagementSortTable(collumn, number) {
+ let tableRows = $('#aes-table-routeManagement tbody tr');
+ let tableBody = $('#aes-table-routeManagement tbody');
+ tableBody.empty();
+ let indexes = [];
+ tableRows.each(function() {
+ if (number) {
+ let value = parseInt($(this).find("." + collumn).text(), 10);
+ if (value) {
+ indexes.push(value);
+ } else {
+ indexes.push(0);
+ }
+ } else {
+ indexes.push($(this).find("." + collumn).text());
+ }
+ });
+ indexes = [...new Set(indexes)];
+ let sorted = [...indexes];
+ if (number) {
+ sorted.sort(function(a, b) {
+ if (a > b) return -1;
+ if (a < b) return 1;
+ if (a = b) return 0;
+ });
+ } else {
+ sorted.sort();
+ }
+ let same = 1;
+ for (let i = 0; i < indexes.length; i++) {
+ if (indexes[i] !== sorted[i]) {
+ same = 0;
+ }
+ }
+ if (same) {
+ if (number) {
+ sorted.sort(function(a, b) {
+ if (a < b) return -1;
+ if (a > b) return 1;
+ if (a = b) return 0;
+ });
+ } else {
+ sorted.reverse();
+ }
+ }
+ for (let i = 0; i < sorted.length; i++) {
+ for (let j = tableRows.length - 1; j >= 0; j--) {
+ if (number) {
+ let value = parseInt($(tableRows[j]).find("." + collumn).text(), 10);
+ if (!value) {
+ value = 0;
+ }
+ if (value == sorted[i]) {
+ tableBody.append($(tableRows[j]));
+ tableRows.splice(j, 1);
+ }
+ } else {
+ if ($(tableRows[j]).find("." + collumn).text() == sorted[i]) {
+ tableBody.append($(tableRows[j]));
+ tableRows.splice(j, 1);
+ }
+ }
+ }
+ }
+}
+
+function updateRouteAnalysisCollumns(data, dates, routeIndex) {
+
+ if (data) {
+ let rowId = '#aes-row-' + data.origin + data.destination;
+
+ if (dates.analysis) {
+ //Analysis date
+ $(rowId + ' .aes-analysisDate').text(AES.formatDateString(dates.analysis));
+
+ //Pricing date
+ if (dates.pricing) {
+ $(rowId + ' .aes-pricingDate').text(AES.formatDateString(dates.pricing));
+ }
+
+ //Pax Load
+ $(rowId + ' .aes-paxLoad').html(displayLoad(getRouteAnalysisLoad(data.date[dates.analysis].data, 'pax')));
+
+ //Cargo Load
+ $(rowId + ' .aes-cargoLoad').html(displayLoad(getRouteAnalysisLoad(data.date[dates.analysis].data, 'cargo')));
+
+ //All Load
+ $(rowId + ' .aes-load').html(displayLoad(getRouteAnalysisLoad(data.date[dates.analysis].data, 'all')));
+
+ //PAX Index
+ $(rowId + ' .aes-paxIndex').html(displayIndex(getRouteAnalysisIndex(data.date[dates.analysis].data, 'pax')));
+
+ //Cargo Index
+ $(rowId + ' .aes-cargoIndex').html(displayIndex(getRouteAnalysisIndex(data.date[dates.analysis].data, 'cargo')));
+
+ //PAX Index
+ $(rowId + ' .aes-index').html(displayIndex(getRouteAnalysisIndex(data.date[dates.analysis].data, 'all')));
+
+ if (dates.analysisOneBefore) {
+ //Previous analysis date
+ $(rowId + ' .aes-analysisPreDate').text(AES.formatDateString(dates.analysisOneBefore));
+
+ //Pax Load Delta
+ $(rowId + ' .aes-paxLoadDelta').html(displayRouteAnalysisLoadDelta(data.date[dates.analysis].data, data.date[dates.analysisOneBefore].data, 'pax'));
+ //Cargo Load Delta
+ $(rowId + ' .aes-cargoLoadDelta').html(displayRouteAnalysisLoadDelta(data.date[dates.analysis].data, data.date[dates.analysisOneBefore].data, 'cargo'));
+ //All Load Delta
+ $(rowId + ' .aes-loadDelta').html(displayRouteAnalysisLoadDelta(data.date[dates.analysis].data, data.date[dates.analysisOneBefore].data, 'all'));
+
+ //PAX Index Delta
+ $(rowId + ' .aes-paxIndexDelta').html(displayRouteAnalysisIndexDelta(data.date[dates.analysis].data, data.date[dates.analysisOneBefore].data, 'pax'));
+ //Cargo Index Delta
+ $(rowId + ' .aes-cargoIndexDelta').html(displayRouteAnalysisIndexDelta(data.date[dates.analysis].data, data.date[dates.analysisOneBefore].data, 'cargo'));
+ //PAX Index Delta
+ $(rowId + ' .aes-indexDelta').html(displayRouteAnalysisIndexDelta(data.date[dates.analysis].data, data.date[dates.analysisOneBefore].data, 'all'));
+ }
+
+ //Route Index
+ if (routeIndex.pax) {
+ $(rowId + ' .aes-routeIndexPax').html(displayIndex(routeIndex.pax));
+ }
+ if (routeIndex.cargo) {
+ $(rowId + ' .aes-routeIndexCargo').html(displayIndex(routeIndex.cargo));
+ }
+ if (routeIndex.all) {
+ $(rowId + ' .aes-routeIndex').html(displayIndex(routeIndex.all));
+ }
+ }
+ }
+
+ return;
+ let analysisDate = dates.analysis;
+ let pricingDate = dates.pricing;
+ let paxLoad;
+ let paxLoadDelta;
+ let cargoLoad;
+ let cargoLoadDelta;
+ let totalLoad;
+ let totalLoadDelta;
+
+ outDates = getInvPricingAnalaysisPricingDate(dataOut.date);
+ if (outDates.analysis) {
+ $('#aes-row-invPricing-' + origin + dest + '-analysis', tbody).text(AES.formatDateString(outDates.analysis));
+ outIndex = dataOut.date[outDates.analysis].routeIndex;
+ let td = $('#aes-row-invPricing-' + origin + dest + '-OWindex', tbody);
+ td.html(displayIndex(outIndex));
+ if (outDates.analysisOneBefore) {
+ outIndexChange = dataOut.date[outDates.analysis].routeIndex - dataOut.date[outDates.analysisOneBefore].routeIndex
+ td.append(displayIndexChange(outIndexChange));
+ }
+ }
+ if (outDates.pricing) {
+ $('#aes-row-invPricing-' + origin + dest + '-pricing', tbody).text(AES.formatDateString(outDates.pricing));
+ }
+}
+
+function displayRouteAnalysisLoadDelta(dataCurrent, dataPrevious, type) {
+ let load = getRouteAnalysisLoad(dataCurrent, type);
+ let preLoad = getRouteAnalysisLoad(dataPrevious, type);
+ if (load && preLoad) {
+ let diff = load - preLoad;
+ let span = $(' ');
+ if (diff > 0) {
+ span.addClass('good').text('+' + diff + "%");
+ return span;
+ }
+ if (diff < 0) {
+ span.addClass('bad').text(diff + "%");
+ return span;
+ }
+ span.addClass('warning').text(diff + "%");
+ return span;
+ }
+}
+
+function displayRouteAnalysisIndexDelta(dataCurrent, dataPrevious, type) {
+ let index = getRouteAnalysisIndex(dataCurrent, type);
+ let preIndex = getRouteAnalysisIndex(dataPrevious, type);
+ if (index && preIndex) {
+ let diff = index - preIndex;
+ let span = $(' ');
+ if (diff > 0) {
+ span.addClass('good').text('+' + diff);
+ return span;
+ }
+ if (diff < 0) {
+ span.addClass('bad').text(diff);
+ return span;
+ }
+ span.addClass('warning').text(diff);
+ return span;
+ }
+}
+
+function getRouteAnalysisLoad(data, type) {
+ let cmp = [];
+ switch (type) {
+ case 'all':
+ cmp = ['Y', 'C', 'F', 'Cargo'];
+ break;
+ case 'pax':
+ cmp = ['Y', 'C', 'F'];
+ break;
+ case 'cargo':
+ cmp = ['Cargo'];
+ break;
+ default:
+ // code block
+ }
+ let cap, bkd;
+ cap = bkd = 0;
+ cmp.forEach(function(comp) {
+ if (data[comp].valid) {
+ cap += data[comp].totalCap;
+ bkd += data[comp].totalBkd;
+ }
+ });
+ if (cap) {
+ return Math.round(bkd / cap * 100);
+ } else {
+ return 0;
+ }
+}
+
+function displayLoad(load) {
+ if (load) {
+ let span = $(' ');
+ if (load >= 70) {
+ span.addClass('good').text(load + "%");
+ return span;
+ }
+ if (load < 40) {
+ span.addClass('bad').text(load + "%");
+ return span;
+ }
+ span.addClass('warning').text(load + "%");
+ return span;
+ }
+}
+
+function getRouteAnalysisIndex(data, type) {
+ let cmp = [];
+ let index = 0;
+ switch (type) {
+ case 'all':
+ cmp = ['Y', 'C', 'F', 'Cargo'];
+ break;
+ case 'pax':
+ cmp = ['Y', 'C', 'F'];
+ break;
+ case 'cargo':
+ cmp = ['Cargo'];
+ break;
+ default:
+ cmp = 0;
+ break;
+ }
+ if (cmp) {
+ //Multi index
+ let count = 0;
+ cmp.forEach(function(comp) {
+ if (data[comp].valid) {
+ index += data[comp].index;
+ count++;
+ }
+ });
+ if (index) {
+ return Math.round(index / count);
+ }
+ }
+}
+
+function getRouteAnalysisImportantDates(dates) {
+ //Get latest analysis and pricing date
+ let latest = {
+ analysis: 0,
+ pricing: 0,
+ analysisOneBefore: 0,
+ pricingOneBefore: 0
+ }
+ let analysisDates = [];
+ let pricingDates = []
+ for (let date in dates) {
+ if (Number.isInteger(parseInt(date))) {
+ if (dates[date].pricingUpdated) {
+ pricingDates.push(date);
+ }
+ analysisDates.push(date);
+ }
+ }
+ analysisDates.reverse();
+ pricingDates.reverse();
+ if (analysisDates.length) {
+ latest.analysis = analysisDates[0];
+ if (analysisDates[1]) {
+ latest.analysisOneBefore = analysisDates[1];
+ }
+ }
+ if (pricingDates.length) {
+ latest.pricing = pricingDates[0];
+ if (pricingDates[1]) {
+ latest.pricingOneBefore = pricingDates[1];
+ }
+ }
+ return latest;
+}
+
+function displayIndex(index) {
+ let span = $(' ');
+ if (index >= 90) {
+ return span.addClass('good').text(index);
+ }
+ if (index <= 50) {
+ return span.addClass('bad').text(index);
+ }
+ return span.addClass('warning').text(index);
+}
+
+function displayIndexChange(index) {
+ if (index > 0) {
+ return ' (+' + index + ' )';
+ }
+ if (index < 0) {
+ return ' (' + index + ' )';
+ }
+ return ' (' + index + ' )';
+}
+//Display General
+function displayGeneral() {
+ let mainDiv = $("#aes-div-dashboard");
+ mainDiv.empty();
+
+ //Table
+ //Head cells
+ let th1 = $('Area ');
+ let th2 = $('Status ');
+ let th3 = $('Action ');
+ let headRow = $(' ').append(th1, th2, th3);
+ let thead = $(' ').append(headRow);
+ //Body cells
+ let tbody = $(' ');
+ generalAddScheduleRow(tbody);
+ generalAddPersonelManagementRow(tbody);
+
+
+ let table = $('').append(thead, tbody);
+ //Build layout
+ let divTable = $('
').append(table);
+ let title = $(' ').text('General');
+ let div = $('
').append(divTable);
+ mainDiv.append(title, div);
+}
+
+//Display COmpetitor Monitoring
+function displayCompetitorMonitoring() {
+ //Div
+ let div = $('
');
+
+ //Check ROute Managemetn seetings
+ //
+ if (!settings.competitorMonitoring) {
+ setDefaultCompetitorMonitoringSettings();
+ }
+
+ //Display airlines table
+ displayCompetitorMonitoringAirlinesTable(div);
+
+ let mainDiv = $("#aes-div-dashboard");
+ //Build layout
+ mainDiv.empty();
+ let title = $(' ').text('Competitor Monitoring');
+ mainDiv.append(title, div);
+
+}
+
+function displayCompetitorMonitoringAirlinesTable(div) {
+ let compAirlines = [];
+ let compAirlinesSchedule = [];
+ chrome.storage.local.get(null, function(items) {
+ //Get data
+ for (let key in items) {
+ if (items[key].type) {
+ if (items[key].type == 'competitorMonitoring') {
+ if (items[key].server == server) {
+ if (items[key].tracking) {
+ compAirlines.push(items[key]);
+ }
+ }
+ }
+ if (items[key].type == 'schedule') {
+ if (items[key].server == server) {
+ let airline = items[key].airline
+ compAirlinesSchedule[airline] = items[key];
+ }
+ }
+ }
+ }
+
+ //Check if any airlines exist
+ let rows = [];
+ let hrows = [];
+ if (compAirlines.length) {
+ //head
+ //second head collumns
+ let firstHead = {};
+ let th = [];
+ settings.competitorMonitoring.tableColumns.forEach(function(col) {
+ if (col.visible) {
+ //Sort
+ let sort = $(' ').html(col.text);
+ sort.click(function() {
+ CompetitorMonitoringSortTable(col.field, col.number);
+ });
+ th.push($(' ').html(sort));
+ if (firstHead[col.headGroup]) {
+ firstHead[col.headGroup]++;
+ } else {
+ firstHead[col.headGroup] = 1;
+ }
+ }
+ });
+ //first head
+ let th1 = [];
+ for (let titles in firstHead) {
+ th1.push($(' ').text(titles));
+ }
+ hrows.push($(' ').append(th1));
+ hrows.push($(' ').append(th));
+
+ //Data collumns
+
+ compAirlines.forEach(function myFunction(value) {
+ let data = {};
+ //Airline
+ data.airlineId = value.id;
+ //All Tab0 Collumns
+ let dates = [];
+ for (let date in value.tab0) {
+ dates.push(date);
+ }
+ dates.sort(function(a, b) { return b - a });
+ if (dates.length) {
+ data.airlineCode = value.tab0[dates[0]].code;
+ data.airlineName = value.tab0[dates[0]].displayName;
+ data.overviewDate = AES.formatDateString(dates[0]);
+ data.overviewRating = value.tab0[dates[0]].rating;
+ data.overviewTotalPax = value.tab0[dates[0]].pax;
+ data.overviewTotalCargo = value.tab0[dates[0]].cargo;
+ data.overviewStations = value.tab0[dates[0]].stations;
+ data.overviewFleet = value.tab0[dates[0]].fleet;
+ data.overviewStaff = value.tab0[dates[0]].employees;
+ //If previous date exists
+ if (dates[1]) {
+ data.overviewPreDate = AES.formatDateString(dates[1]);
+ data.overviewRatingDelta = getDelta(getRatingNr(data.overviewRating), getRatingNr(value.tab0[dates[1]].rating));
+ data.overviewTotalPaxDelta = getDelta(data.overviewTotalPax, value.tab0[dates[1]].pax);
+ data.overviewTotalCargoDelta = getDelta(data.overviewTotalCargo, value.tab0[dates[1]].cargo);
+ data.overviewStationsDelta = getDelta(data.overviewStations, value.tab0[dates[1]].stations);
+ data.overviewFleetDelta = getDelta(data.overviewFleet, value.tab0[dates[1]].fleet);
+ data.overviewStaffDelta = getDelta(data.overviewStaff, value.tab0[dates[1]].employees);
+ }
+ }
+ //All Tab2 Collumns
+ dates = [];
+ for (let date in value.tab2) {
+ dates.push(date);
+ }
+ dates.sort(function(a, b) { return b - a });
+ if (dates.length) {
+ data.fafWeek = AES.formatDateStringWeek(value.tab2[dates[0]].week);
+ data.fafAirportsServed = value.tab2[dates[0]].airportsServed;
+ data.fafOperatedFlights = value.tab2[dates[0]].operatedFlights;
+ data.fafSeatsOffered = value.tab2[dates[0]].seatsOffered;
+ data.fafsko = value.tab2[dates[0]].sko;
+ data.fafCargoOffered = value.tab2[dates[0]].cargoOffered;
+ data.faffko = value.tab2[dates[0]].fko;
+ //If previous date exists
+ if (dates[1]) {
+ data.fafWeekPre = AES.formatDateStringWeek(value.tab2[dates[1]].week);
+ data.fafAirportsServedDelta = getDelta(data.fafAirportsServed, value.tab2[dates[1]].airportsServed);
+ data.fafOperatedFlightsDelta = getDelta(data.fafOperatedFlights, value.tab2[dates[1]].operatedFlights);
+ data.fafSeatsOfferedDelta = getDelta(data.fafSeatsOffered, value.tab2[dates[1]].seatsOffered);
+ data.fafskoDelta = getDelta(data.fafsko, value.tab2[dates[1]].sko);
+ data.fafCargoOfferedDelta = getDelta(data.fafCargoOffered, value.tab2[dates[1]].cargoOffered);
+ data.faffkoDela = getDelta(data.faffko, value.tab2[dates[1]].fko);
+ }
+ }
+ //Schedule Collumns
+ if (compAirlinesSchedule[data.airlineCode]) {
+ dates = [];
+ for (let date in compAirlinesSchedule[data.airlineCode].date) {
+ dates.push(date);
+ }
+ dates.sort(function(a, b) { return b - a });
+ if (dates.length) {
+ let hubs = {};
+ //For display
+ data.scheduleDate = AES.formatDateString(dates[0]);
+ //For table
+ data.scheduleDateUse = dates[0];
+ data.scheduleCargoFreq = 0;
+ data.schedulePAXFreq = 0;
+ data.scheduleFltNr = 0;
+ compAirlinesSchedule[data.airlineCode].date[dates[0]].schedule.forEach(function(schedule) {
+ //Hubs
+ let hub = schedule.od.slice(0, 3);
+ if (hubs[hub]) {
+ hubs[hub]++;
+ } else {
+ hubs[hub] = 1;
+ }
+ for (let flight in schedule.flightNumber) {
+ //Cargo Freq
+ data.scheduleCargoFreq += schedule.flightNumber[flight].cargoFreq;
+ //Pax Freq
+ data.schedulePAXFreq += schedule.flightNumber[flight].paxFreq;
+ //Flight nr
+ data.scheduleFltNr++;
+ }
+ });
+ //Total Frequency
+ data.scheduleTotalFreq = data.schedulePAXFreq + data.scheduleCargoFreq;
+ //Hubs
+ let hubArray = [];
+ for (let hub in hubs) {
+ hubArray.push([hub, hubs[hub]]);
+ }
+ hubArray.sort(function(a, b) {
+ return b[1] - a[1];
+ });
+ data.scheduleHubs = '';
+ hubArray.forEach(function(hubA, index) {
+ if (index) {
+ data.scheduleHubs += ', ';
+ }
+ data.scheduleHubs += hubA[0] + ' (' + hubA[1] + ')';
+ });
+
+ //Previous schedule data
+ if (dates[1]) {
+ data.scheduleDatePre = AES.formatDateString(dates[1]);
+ data.scheduleCargoFreqPre = 0;
+ data.schedulePAXFreqPre = 0;
+ data.scheduleFltNrPre = 0;
+ compAirlinesSchedule[data.airlineCode].date[dates[1]].schedule.forEach(function(schedule) {
+ //Hubs
+ let hub = schedule.od.slice(0, 3);
+ if (hubs[hub]) {
+ hubs[hub]++;
+ } else {
+ hubs[hub] = 1;
+ }
+ for (let flight in schedule.flightNumber) {
+ //Cargo Freq
+ data.scheduleCargoFreqPre += schedule.flightNumber[flight].cargoFreq;
+ //Pax Freq
+ data.schedulePAXFreqPre += schedule.flightNumber[flight].paxFreq;
+ //Flight nr
+ data.scheduleFltNrPre++;
+ }
+ });
+ //Total Frequency
+ data.scheduleTotalFreqPre = data.schedulePAXFreq + data.scheduleCargoFreq;
+ //Delta Collumns
+ data.scheduleFltNrDelta = getDelta(data.scheduleFltNr, data.scheduleFltNrPre);
+ data.schedulePAXFreqDelta = getDelta(data.schedulePAXFreq, data.schedulePAXFreqPre);
+ data.scheduleCargoFreqDelta = getDelta(data.scheduleCargoFreq, data.scheduleCargoFreqPre);
+ data.scheduleTotalFreqDelta = getDelta(data.scheduleTotalFreq, data.scheduleTotalFreqPre);
+ }
+ }
+ }
+ //Action collumns
+ //Open airline
+ data.actionOpenAirline = 'Airline ';
+ //Open schedule
+ if (compAirlinesSchedule[data.airlineCode]) {
+ data.actionOpenSchedule = $('Schedule ');
+ //Create schedule table
+ $('#aes-div-dashboard').on('click', 'button#aes-compMon-btn-schedule-' + data.airlineCode, function() {
+ displayCompetitorMonitoringAirlineScheduleTable(div, compAirlinesSchedule[data.airlineCode], data);
+ });
+ }
+ //Remove airline '
+ data.actionRemoveAirline = $('Remove ');
+ //Remove airline action
+ $('#aes-div-dashboard').on('click', 'button#aes-compMon-btn-remove-' + data.airlineCode, function() {
+ let key = server + data.airlineId + 'competitorMonitoring';
+ let remove = $(this);
+ chrome.storage.local.get([key], function(compMonitoringData) {
+ let compData = compMonitoringData[key];
+ compData.tracking = 0;
+ chrome.storage.local.set({
+ [compData.key]: compData }, function() {
+ $(remove).closest("tr").remove();
+ });
+ });
+ });
+
+ //Populate collumns
+ let td = [];
+ settings.competitorMonitoring.tableColumns.forEach(function(col) {
+ if (col.visible) {
+ td.push($(' ').html(data[col.field]));
+ }
+ });
+ rows.push($(' ').append(td));
+
+ });
+ } else {
+ rows.push('No airlines marked for competitor monitoring. Open airline info page to mark airline for tracking. ');
+ }
+
+ let thead = $(' ').append(hrows);
+ let tbody = $(' ').append(rows);
+
+ let table = $('').append(thead, tbody);
+ let tableWell = $('
').append(table);
+
+ //Options
+ let divRow = $('
').append(displayCompetitorMonitoringAirlinesTableOptions(), displayCompetitorMonitoringAirlinesTableCollumns());
+ div.append(divRow, tableWell);
+ });
+}
+
+function displayCompetitorMonitoringAirlineScheduleTable(mainDiv, scheduleData, data) {
+ mainDiv.hide();
+ //Build schedule rows
+ let rows = [];
+ let hrow = [];
+ if (data.scheduleDateUse) {
+ let collumns = [
+ {
+ field: 'schedOrigin',
+ text: 'Origin',
+ headGroup: 'Schedule',
+ visible: 1,
+ number: 0,
+ },
+ {
+ field: 'schedDestination',
+ text: 'Destination',
+ headGroup: 'Schedule',
+ visible: 1,
+ number: 0,
+ },
+ {
+ field: 'schedHub',
+ text: 'Hub',
+ headGroup: 'Schedule',
+ visible: 1,
+ number: 0,
+ },
+ {
+ field: 'schedOd',
+ text: 'OD',
+ headGroup: 'Schedule',
+ visible: 1,
+ number: 0,
+ },
+ {
+ field: 'schedDir',
+ text: 'Direction',
+ headGroup: 'Schedule',
+ visible: 1,
+ number: 0,
+ },
+ {
+ field: 'schedFltNr',
+ text: '# of flight numbers',
+ headGroup: 'Schedule',
+ visible: 1,
+ number: 1,
+ },
+ {
+ field: 'schedPaxFreq',
+ text: 'PAX frequency',
+ headGroup: 'Schedule',
+ visible: 1,
+ number: 1,
+ },
+ {
+ field: 'schedCargoFreq',
+ text: 'Cargo frequency',
+ headGroup: 'Schedule',
+ visible: 1,
+ number: 1,
+ },
+ {
+ field: 'schedTotalFreq',
+ text: 'Total Frequency',
+ headGroup: 'Schedule',
+ visible: 1,
+ number: 1,
+ }
+ ];
+ //Table Head
+ let th = [];
+ collumns.forEach(function(col) {
+ if (col.visible) {
+ //Sort
+ let sort = $(' ').html(col.text);
+ sort.click(function() {
+ SortTable(col.field, col.number, 'aes-table-competitorMonitoring-airline-schedule', 'aes-comp-sched-');
+ });
+ th.push($(' ').html(sort));
+ }
+ });
+ hrow.push($(' ').append(th));
+ //Table Body
+ scheduleData.date[data.scheduleDateUse].schedule.forEach(function(od) {
+ let td = [];
+ let fltNr = 0;
+ let paxFreq = 0;
+ let cargoFreq = 0;
+ for (let flight in od.flightNumber) {
+ cargoFreq += od.flightNumber[flight].cargoFreq,
+ paxFreq += od.flightNumber[flight].paxFreq,
+ fltNr++;
+ }
+ let totalFreq = cargoFreq + paxFreq;
+ //hub
+ let hub = od.od.slice(0, 3);
+ let cellValue = {
+ schedOrigin: od.origin,
+ schedDestination: od.destination,
+ schedOd: od.od,
+ schedDir: od.direction,
+ schedFltNr: fltNr,
+ schedPaxFreq: paxFreq,
+ schedCargoFreq: cargoFreq,
+ schedTotalFreq: totalFreq,
+ schedHub: hub
+ }
+ collumns.forEach(function(cell) {
+ if (cell.visible) {
+ td.push($(' ').html(cellValue[cell.field]));
+ }
+ });
+ rows.push($(' ').append(td));
+ });
+ } else {
+ rows.push('No schedule found ');
+ }
+
+ //Build layout
+ let thead = $(' ').append(hrow);
+ let tbody = $(' ').append(rows);
+ let table = $('').append(thead, tbody);
+ let tableWell = $('
').append(table);
+ let button = $('Back to overview ');
+ let panelDiv = $('
').append(button, tableWell);
+ let heading = $('' + data.airlineName + ' ' + data.airlineCode + ' schedule ');
+ let div = $('
').append(heading, panelDiv);
+ mainDiv.after(div);
+ //Button clicks
+ button.click(function() {
+ div.remove();
+ mainDiv.show();
+ });
+}
+
+function displayCompetitorMonitoringAirlinesTableCollumns() {
+ //Table Head
+ let th = [];
+ th.push('Show ');
+ th.push('Column ');
+ let thead = $(' ').append($(' ').append(th));
+ //Table body
+ let tbody = $(' ');
+
+ settings.competitorMonitoring.tableColumns.forEach(function(col) {
+ let td = [];
+ //Checkbox
+ if (col.visible) {
+ td.push(' ');
+ } else {
+ td.push(' ');
+ }
+ //Name
+ td.push('' + col.text + ' ');
+ tbody.append($(' ').append(td));
+ });
+
+ let table = $('').append(thead, tbody);
+ let divTable = $('
').append(table);
+ //Collumns selector Checkbox listener
+ $('input', table).change(function() {
+ let show;
+ if (this.checked) {
+ show = 1;
+ } else {
+ show = 0;
+ }
+ let value = $(this).val();
+ settings.competitorMonitoring.tableColumns.forEach(function(col) {
+ if (col.field == value) {
+ col.visible = show;
+ }
+ });
+ chrome.storage.local.set({ settings: settings }, function() {});
+ });
+ //Closable legend
+ let link = $(' ').text('Columns');
+ let legend = $(' ').html(link);
+ link.click(function() {
+ $('#aes-div-competitorMonitoring-collumns').toggle();
+ });
+ let fieldset = $(' ').append(legend, divTable);
+ let div = $('
').append(fieldset);
+ return div;
+}
+
+function displayCompetitorMonitoringAirlinesTableOptions() {
+ let divFieldset = $(' ').html('Options ');
+ let btn = $('reload table ');
+ divFieldset.append(btn);
+ let optionsDiv = $('
').append(divFieldset);
+ //Reload table
+ btn.click(function() {
+ displayCompetitorMonitoring();
+ });
+
+ return optionsDiv;
+}
+
+function CompetitorMonitoringSortTable(collumn, number) {
+ let tableRows = $('#aes-table-competitorMonitoring tbody tr');
+ let tableBody = $('#aes-table-competitorMonitoring tbody');
+ tableBody.empty();
+ let indexes = [];
+ tableRows.each(function() {
+ if (number) {
+ let value = parseInt($(this).find(".aes-" + collumn).text(), 10);
+ if (value) {
+ indexes.push(value);
+ } else {
+ indexes.push(0);
+ }
+ } else {
+ indexes.push($(this).find(".aes-" + collumn).text());
+ }
+ });
+ indexes = [...new Set(indexes)];
+ let sorted = [...indexes];
+ if (number) {
+ sorted.sort(function(a, b) {
+ if (a > b) return -1;
+ if (a < b) return 1;
+ if (a = b) return 0;
+ });
+ } else {
+ sorted.sort();
+ }
+ let same = 1;
+ for (let i = 0; i < indexes.length; i++) {
+ if (indexes[i] !== sorted[i]) {
+ same = 0;
+ }
+ }
+ if (same) {
+ if (number) {
+ sorted.sort(function(a, b) {
+ if (a < b) return -1;
+ if (a > b) return 1;
+ if (a = b) return 0;
+ });
+ } else {
+ sorted.reverse();
+ }
+ }
+ for (let i = 0; i < sorted.length; i++) {
+ for (let j = tableRows.length - 1; j >= 0; j--) {
+ if (number) {
+ let value = parseInt($(tableRows[j]).find(".aes-" + collumn).text(), 10);
+ if (!value) {
+ value = 0;
+ }
+ if (value == sorted[i]) {
+ tableBody.append($(tableRows[j]));
+ tableRows.splice(j, 1);
+ }
+ } else {
+ if ($(tableRows[j]).find(".aes-" + collumn).text() == sorted[i]) {
+ tableBody.append($(tableRows[j]));
+ tableRows.splice(j, 1);
+ }
+ }
+ }
+ }
+}
+
+function setDefaultCompetitorMonitoringSettings() {
+ let columns = [
+ {
+ field: 'airlineId',
+ text: 'ID',
+ headGroup: 'Airline',
+ visible: 1,
+ number: 1
+ },
+ {
+ field: 'airlineCode',
+ text: 'Code',
+ headGroup: 'Airline',
+ visible: 1,
+ number: 0
+ },
+ {
+ field: 'airlineName',
+ text: 'Name',
+ headGroup: 'Airline',
+ visible: 1,
+ number: 0
+ },
+ {
+ field: 'overviewDate',
+ text: 'Overview date',
+ headGroup: 'Overview',
+ visible: 0,
+ number: 0
+ },
+ {
+ field: 'overviewPreDate',
+ text: 'Overview previous date',
+ headGroup: 'Overview',
+ visible: 0,
+ number: 0
+ },
+ {
+ field: 'overviewRating',
+ text: 'Rating',
+ headGroup: 'Overview',
+ visible: 1,
+ number: 0
+ },
+ {
+ field: 'overviewRatingDelta',
+ text: 'Rating Δ',
+ headGroup: 'Overview',
+ visible: 0,
+ number: 0
+ },
+ {
+ field: 'overviewTotalPax',
+ text: 'Total pax',
+ headGroup: 'Overview',
+ visible: 1,
+ number: 1
+ },
+ {
+ field: 'overviewTotalPaxDelta',
+ text: 'Total pax Δ',
+ headGroup: 'Overview',
+ visible: 1,
+ number: 1
+ },
+ {
+ field: 'overviewTotalCargo',
+ text: 'Total cargo',
+ headGroup: 'Overview',
+ visible: 1,
+ number: 1
+ },
+ {
+ field: 'overviewTotalCargoDelta',
+ text: 'Total cargo Δ',
+ headGroup: 'Overview',
+ visible: 1,
+ number: 1
+ },
+ {
+ field: 'overviewStations',
+ text: 'Stations',
+ headGroup: 'Overview',
+ visible: 1,
+ number: 1
+ },
+ {
+ field: 'overviewStationsDelta',
+ text: 'Stations Δ',
+ headGroup: 'Overview',
+ visible: 1,
+ number: 1
+ },
+ {
+ field: 'overviewFleet',
+ text: 'Fleet',
+ headGroup: 'Overview',
+ visible: 1,
+ number: 1
+ },
+ {
+ field: 'overviewFleetDelta',
+ text: 'Fleet Δ',
+ headGroup: 'Overview',
+ visible: 1,
+ number: 1
+ },
+ {
+ field: 'overviewStaff',
+ text: 'Staff',
+ headGroup: 'Overview',
+ visible: 0,
+ number: 1
+ },
+ {
+ field: 'overviewStaffDelta',
+ text: 'Staff Δ',
+ headGroup: 'Overview',
+ visible: 0,
+ number: 1
+ },
+ {
+ field: 'fafWeek',
+ text: 'Week',
+ headGroup: 'Figures',
+ visible: 0,
+ number: 0
+ },
+ {
+ field: 'fafWeekPre',
+ text: 'Previous week',
+ headGroup: 'Figures',
+ visible: 0,
+ number: 0
+ },
+ {
+ field: 'fafAirportsServed',
+ text: 'Airports served',
+ headGroup: 'Figures',
+ visible: 1,
+ number: 1
+ },
+ {
+ field: 'fafAirportsServedDelta',
+ text: 'Airports served Δ',
+ headGroup: 'Figures',
+ visible: 0,
+ number: 1
+ },
+ {
+ field: 'fafOperatedFlights',
+ text: 'Operated flights',
+ headGroup: 'Figures',
+ visible: 1,
+ number: 1
+ },
+ {
+ field: 'fafOperatedFlightsDelta',
+ text: 'Operated flights Δ',
+ headGroup: 'Figures',
+ visible: 1,
+ number: 1
+ },
+ {
+ field: 'fafSeatsOffered',
+ text: 'Seats offered',
+ headGroup: 'Figures',
+ visible: 1,
+ number: 1
+ },
+ {
+ field: 'fafSeatsOfferedDelta',
+ text: 'Seats offered Δ',
+ headGroup: 'Figures',
+ visible: 1,
+ number: 1
+ },
+ {
+ field: 'fafsko',
+ text: 'SKO',
+ headGroup: 'Figures',
+ visible: 0,
+ number: 1
+ },
+ {
+ field: 'fafskoDelta',
+ text: 'SKO Δ',
+ headGroup: 'Figures',
+ visible: 0,
+ number: 1
+ },
+ {
+ field: 'fafCargoOffered',
+ text: 'Cargo offered',
+ headGroup: 'Figures',
+ visible: 1,
+ number: 1
+ },
+ {
+ field: 'fafCargoOfferedDelta',
+ text: 'Cargo offered Δ',
+ headGroup: 'Figures',
+ visible: 1,
+ number: 1
+ },
+ {
+ field: 'faffko',
+ text: 'FKO',
+ headGroup: 'Figures',
+ visible: 0,
+ number: 1
+ },
+ {
+ field: 'faffkoDela',
+ text: 'FKO Δ',
+ headGroup: 'Figures',
+ visible: 0,
+ number: 1
+ },
+ {
+ field: 'scheduleDate',
+ text: 'Schedule Date',
+ headGroup: 'Schedule',
+ visible: 0,
+ number: 0
+ },
+ {
+ field: 'scheduleDatePre',
+ text: 'Previous Schedule Date',
+ headGroup: 'Schedule',
+ visible: 0,
+ number: 0
+ },
+ {
+ field: 'scheduleHubs',
+ text: 'Hubs (routes)',
+ headGroup: 'Schedule',
+ visible: 1,
+ number: 0
+ },
+ {
+ field: 'scheduleFltNr',
+ text: '# of flight numbers',
+ headGroup: 'Schedule',
+ visible: 0,
+ number: 1
+ },
+ {
+ field: 'scheduleFltNrDelta',
+ text: '# of flight numbers Δ',
+ headGroup: 'Schedule',
+ visible: 0,
+ number: 1
+ },
+ {
+ field: 'schedulePAXFreq',
+ text: 'PAX frequency',
+ headGroup: 'Schedule',
+ visible: 0,
+ number: 1
+ },
+ {
+ field: 'schedulePAXFreqDelta',
+ text: 'PAX frequency Δ',
+ headGroup: 'Schedule',
+ visible: 0,
+ number: 1
+ },
+ {
+ field: 'scheduleCargoFreq',
+ text: 'Cargo frequency',
+ headGroup: 'Schedule',
+ visible: 0,
+ number: 1
+ },
+ {
+ field: 'scheduleCargoFreqDelta',
+ text: 'Cargo frequency Δ',
+ headGroup: 'Schedule',
+ visible: 0,
+ number: 1
+ },
+ {
+ field: 'scheduleTotalFreq',
+ text: 'Total frequency',
+ headGroup: 'Schedule',
+ visible: 1,
+ number: 1
+ },
+ {
+ field: 'scheduleTotalFreqDelta',
+ text: 'Total frequency Δ',
+ headGroup: 'Schedule',
+ visible: 1,
+ number: 1
+ },
+ {
+ field: 'actionOpenAirline',
+ text: 'Open airline page',
+ headGroup: 'Actions',
+ visible: 1,
+ number: 0
+ },
+ {
+ field: 'actionOpenSchedule',
+ text: 'Show airline schedule',
+ headGroup: 'Actions',
+ visible: 1,
+ number: 0
+ },
+ {
+ field: 'actionRemoveAirline',
+ text: 'Remove airline',
+ headGroup: 'Actions',
+ visible: 0,
+ number: 0
+ }
+ ];
+ settings.competitorMonitoring = {
+ tableColumns: columns
+ };
+}
+
+function getRatingNr(rating) {
+ switch (rating) {
+ case 'AAA':
+ return 10;
+ break;
+ case 'AA':
+ return 9;
+ break;
+ case 'A':
+ return 8;
+ break;
+ case 'BBB':
+ return 7;
+ break;
+ case 'BB':
+ return 6;
+ break;
+ case 'B':
+ return 5;
+ break;
+ case 'CCC':
+ return 4;
+ break;
+ case 'CC':
+ return 3;
+ break;
+ case 'C':
+ return 2;
+ break;
+ case 'D':
+ return 1;
+ break;
+ default:
+ return 0;
+ }
+}
+
+function getDelta(newNr, oldNr) {
+ return newNr - oldNr;
+};
+//Display Aircraft aircraftProfitability
+function displayAircraftProfitability() {
+ if (!settings.aircraftProfitability) {
+ settings.aircraftProfitability = {};
+ }
+ if (!settings.aircraftProfitability.hideColumn) {
+ settings.aircraftProfitability.hideColumn = [];
+ }
+ //columns
+ let columns = [
+ {
+ category: 'Aircraft',
+ title: 'Aircraft ID',
+ data: 'aircraftId',
+ sortable: 1,
+ visible: 1,
+ number: 1,
+ id: 1
+ },
+ {
+ category: 'Aircraft',
+ title: 'Registration',
+ data: 'registration',
+ sortable: 1,
+ visible: 1
+ },
+ {
+ category: 'Aircraft',
+ title: 'Equipment',
+ data: 'equipment',
+ sortable: 1,
+ visible: 1
+ },
+ {
+ category: 'Aircraft',
+ title: 'Fleet',
+ data: 'fleet',
+ sortable: 1,
+ visible: 1
+ },
+ {
+ category: 'Aircraft',
+ title: 'Nickname',
+ data: 'nickname',
+ sortable: 1,
+ visible: 1
+ },
+ {
+ category: 'Aircraft',
+ title: 'Note',
+ data: 'note',
+ sortable: 1,
+ visible: 1
+ },
+ {
+ category: 'Aircraft',
+ title: 'Age',
+ data: 'age',
+ sortable: 1,
+ visible: 1,
+ number: 1
+ },
+ {
+ category: 'Aircraft',
+ title: 'Maintenance',
+ data: 'maintenance',
+ sortable: 1,
+ visible: 1,
+ number: 1
+ },
+ {
+ category: 'Aircraft',
+ title: 'Date',
+ data: 'dateAircraft',
+ sortable: 1,
+ visible: 1
+ },
+ {
+ category: 'Profit',
+ title: 'Total flights',
+ data: 'totalFlights',
+ sortable: 1,
+ visible: 1,
+ number: 1
+ },
+ {
+ category: 'Profit',
+ title: 'Finished flights',
+ data: 'finishedFlights',
+ sortable: 1,
+ visible: 1,
+ number: 1
+ },
+ {
+ category: 'Profit',
+ title: 'Profit/loss flights',
+ data: 'profitFlights',
+ sortable: 1,
+ visible: 1,
+ number: 1
+ },
+ {
+ category: 'Profit',
+ title: 'Profit',
+ data: 'profit',
+ sortable: 1,
+ visible: 1,
+ number: 1,
+ format: 'money'
+ },
+ {
+ category: 'Profit',
+ title: 'Profit extract date',
+ data: 'dateProfit',
+ sortable: 1,
+ visible: 1
+ }
+ ];
+ if (settings.aircraftProfitability.hideColumn.length) {
+ columns.forEach(function(column) {
+ settings.aircraftProfitability.hideColumn.forEach(function(hideColumn) {
+ if (column.data == hideColumn) {
+ column.visible = 0;
+ }
+ });
+ });
+ }
+
+ let key = server + airline.name + 'aircraftFleet';
+ //Get storage fleet data
+ chrome.storage.local.get(key, function(result) {
+ //get aircraft flight data
+ let aircraftFleetData = result[key];
+ if (aircraftFleetData) {
+ let keys = [];
+ aircraftFleetData.fleet.forEach(function(value) {
+ keys.push(server + 'aircraftFlights' + value.aircraftId);
+ });
+ chrome.storage.local.get(keys, function(result) {
+ for (let aircraftFlightData in result) {
+ for (let i = 0; i < aircraftFleetData.fleet.length; i++) {
+ if (aircraftFleetData.fleet[i].aircraftId == result[aircraftFlightData].aircraftId) {
+ aircraftFleetData.fleet[i].profit = {
+ date: result[aircraftFlightData].date,
+ finishedFlights: result[aircraftFlightData].finishedFlights,
+ profit: result[aircraftFlightData].profit,
+ profitFlights: result[aircraftFlightData].profitFlights,
+ time: result[aircraftFlightData].time,
+ totalFlights: result[aircraftFlightData].totalFlights,
+ };
+ }
+ }
+ }
+ let data = prepareAircraftProfitabilityData(aircraftFleetData);
+ let tableDiv;
+ if (data.length) {
+ tableDiv = generateTable({
+ column: columns,
+ data: data,
+ columnPrefix: 'aes-aircraftProfit-',
+ tableSettings: 1,
+ options: ['openAircraft', 'removeAircraft', 'reloadTableAircraftProfit', 'applyFilter', 'removeSelected'],
+ filter: settings.aircraftProfitability.filter,
+ hideColumn: settings.aircraftProfitability.hideColumn,
+ tableSettingStorage: 'aircraftProfitability'
+ });
+ } else {
+ //Never happens or only when fleet = 0 because of updated script this output is copied bellow
+ tableDiv = $('
').text('No aircraft data in memory. Open fleet management to extract aircraft data.')
+ }
+ //Div
+ let div = $('
').append(tableDiv);
+ let mainDiv = $("#aes-div-dashboard");
+ //Build layout
+ mainDiv.empty();
+ let title = $(' ').text('Aircraft Profitability');
+ mainDiv.append(title, div);
+
+ });
+ } else {
+ //No data
+ //Div
+ let tableDiv = $('
').text('No aircraft data in memory. Open fleet management to extract aircraft data.')
+ let div = $('
').append(tableDiv);
+ let mainDiv = $("#aes-div-dashboard");
+ //Build layout
+ mainDiv.empty();
+ let title = $(' ').text('Aircraft Profitability');
+ mainDiv.append(title, div);
+ }
+ });
+
+ function prepareAircraftProfitabilityData(storage) {
+ let data = [];
+ storage.fleet.forEach(function(value) {
+ let profit = {};
+ if (value.profit) {
+ profit.totalFlights = value.profit.totalFlights;
+ profit.finishedFlights = value.profit.finishedFlights;
+ profit.profitFlights = value.profit.profitFlights;
+ profit.profit = value.profit.profit;
+ profit.dateProfit = AES.formatDateString(value.profit.date) + ' ' + value.profit.time;
+ }
+ data.push({
+ aircraftId: value.aircraftId,
+ registration: value.registration,
+ equipment: value.equipment,
+ fleet: value.fleet,
+ nickname: value.nickname,
+ note: value.note,
+ age: value.age,
+ maintenance: value.maintanance,
+ dateAircraft: AES.formatDateString(value.date) + ' ' + value.time,
+ totalFlights: profit.totalFlights,
+ finishedFlights: profit.finishedFlights,
+ profitFlights: profit.profitFlights,
+ profit: profit.profit,
+ dateProfit: profit.dateProfit
+ });
+ });
+ return data;
+ }
+}
+
+//Auto table generator
+function generateTable(tableOptionsRule) {
+ let tableHtml = $('');
+ let table = { cell: {}, row: {}, tableHtml: tableHtml };
+ //Table Categories
+ let tableCategory = {};
+ tableOptionsRule.column.forEach(function(value) {
+ if (value.visible) {
+ if (!tableCategory[value.category]) {
+ tableCategory[value.category] = 1;
+ } else {
+ tableCategory[value.category]++;
+ }
+ }
+ });
+ table.cell.category = [];
+ //Add checkbox
+ if (tableOptionsRule.tableSettings) {
+ table.cell.category.push(' ')
+ }
+ for (let category in tableCategory) {
+ table.cell.category.push('' + category + ' ');
+ }
+
+ //Table Headers
+ table.cell.header = [];
+ tableOptionsRule.column.forEach(function(value) {
+ if (value.visible) {
+ if (value.sortable) {
+ //Sort
+ let sort = $(' ').text(value.title);
+ sort.click(function() {
+ masterSortTable(value.data, value.number, table.tableHtml, tableOptionsRule.columnPrefix);
+ });
+ table.cell.header.push($(' ').html(sort));
+ } else {
+ table.cell.header.push('' + value.title + ' ');
+ }
+ }
+ });
+ //Head
+ table.row.head = [];
+ table.row.head.push($(' ').append(table.cell.category));
+ table.row.head.push($(' ').append(table.cell.header));
+ //Table Body
+ table.row.body = [];
+ tableOptionsRule.data.forEach(function(dataValue) {
+ let cell = [];
+ //Add checkbox
+ if (tableOptionsRule.tableSettings) {
+ cell.push(' ');
+ }
+ let id;
+ tableOptionsRule.column.forEach(function(colValue) {
+ if (colValue.id) {
+ id = dataValue[colValue.data]
+ }
+ if (colValue.visible) {
+ let td = $(' ').addClass(tableOptionsRule.columnPrefix + colValue.data);
+ if (colValue.format) {
+ td.html(masterCellFormat(colValue.format, dataValue[colValue.data]))
+ } else {
+ td.html(dataValue[colValue.data])
+ }
+ cell.push(td);
+ }
+ });
+ table.row.body.push($(' ').attr('id', id).append(cell));
+ });
+ let thead = $(' ').append(table.row.head);
+ let tbody = $(' ').append(table.row.body);
+ table.tableHtml.append(thead, tbody);
+ let tableWell = $('
').append(table.tableHtml);
+
+ //Table Settings
+ let settingsDiv = '';
+ if (tableOptionsRule.tableSettings) {
+ let divCol = [];
+ //Options
+ divCol.push($('
').html(masterTableOptions(table.tableHtml, tableOptionsRule.options)));
+ divCol.push($('
').html(masterTableFilter(tableOptionsRule.filter, tableOptionsRule.column)));
+ divCol.push($('
').html(masterTableColumns()));
+ settingsDiv = $('
').append(divCol)
+ }
+
+ let div = $('
').append(settingsDiv, tableWell);
+ return div;
+ //Table functions
+ function masterSortTable(collumn, number, table, collumnPrefix) {
+ let tableRows = $('tbody tr', table);
+ let tableBody = $('tbody', table);
+ tableBody.empty();
+ let indexes = [];
+ tableRows.each(function() {
+ if (number) {
+ let value = parseInt($(this).find("." + collumnPrefix + collumn).text(), 10);
+ if (value) {
+ indexes.push(value);
+ } else {
+ indexes.push(0);
+ }
+ } else {
+ indexes.push($(this).find("." + collumnPrefix + collumn).text());
+ }
+ });
+ indexes = [...new Set(indexes)];
+ let sorted = [...indexes];
+ if (number) {
+ sorted.sort(function(a, b) {
+ if (a > b) return -1;
+ if (a < b) return 1;
+ if (a = b) return 0;
+ });
+ } else {
+ sorted.sort();
+ }
+ let same = 1;
+ for (let i = 0; i < indexes.length; i++) {
+ if (indexes[i] !== sorted[i]) {
+ same = 0;
+ }
+ }
+ if (same) {
+ if (number) {
+ sorted.sort(function(a, b) {
+ if (a < b) return -1;
+ if (a > b) return 1;
+ if (a = b) return 0;
+ });
+ } else {
+ sorted.reverse();
+ }
+ }
+ for (let i = 0; i < sorted.length; i++) {
+ for (let j = tableRows.length - 1; j >= 0; j--) {
+ if (number) {
+ let value = parseInt($(tableRows[j]).find("." + collumnPrefix + collumn).text(), 10);
+ if (!value) {
+ value = 0;
+ }
+ if (value == sorted[i]) {
+ tableBody.append($(tableRows[j]));
+ tableRows.splice(j, 1);
+ }
+ } else {
+ if ($(tableRows[j]).find("." + collumnPrefix + collumn).text() == sorted[i]) {
+ tableBody.append($(tableRows[j]));
+ tableRows.splice(j, 1);
+ }
+ }
+ }
+ }
+ }
+
+ function masterCellFormat(type, value) {
+ if (!value) {
+ return '';
+ }
+ switch (type) {
+ case 'money':
+ let span = $(' ');
+ let text = '';
+ if (value > 0) {
+ span.addClass('good');
+ text = '+'
+ }
+ if (value < 0) {
+ span.addClass('bad');
+ }
+ text = text + new Intl.NumberFormat().format(value) + ' AS$';
+ span.text(text);
+ return span;
+ break;
+ default:
+ return value;
+ }
+ }
+
+ function masterTableOptions(table, options) {
+ let div = $('
');
+ options.forEach(function(value, index) {
+ if (index) {
+ let span = $(' ');
+ div.append(span);
+ }
+ div.append(masterTableOptionsHandle(value));
+ });
+ //Closable legend
+ let link = $(' ').text('Options');
+ let legend = $(' ').html(link);
+ link.click(function() {
+ div.toggle();
+ });
+ let fieldset = $(' ').append(legend, div);
+ return fieldset;
+
+ //Functions
+ function masterTableOptionsHandle(value) {
+ switch (value) {
+ case 'openAircraft':
+ return masterTableOptionsOpenAircraft();
+ break;
+ case 'reloadTableAircraftProfit':
+ return masterTableOptionsReloadTableAP();
+ break;
+ case 'removeAircraft':
+ return masterTableOptionsRemoveAircraft();
+ break;
+ case 'applyFilter':
+ return masterTableOptionsApplyFilter();
+ break;
+ case 'removeSelected':
+ return masterTableOptionsRemoveSelected();
+ break;
+ default:
+ // code block
+ }
+ //Option Functions
+ function masterTableOptionsOpenAircraft() {
+ let btn = $('open aircraft (max 10) ');
+ btn.click(function() {
+ let urls = $('tbody tr', table).has('input:checked').map(function() {
+ let id = $(this).attr('id');
+ let url = 'https://' + server + '.airlinesim.aero/app/fleets/aircraft/' + id + '/1';
+ return url;
+ }).toArray();
+ //Open new tabs
+ for (let i = 0; i < urls.length; i++) {
+ window.open(urls[i], '_blank');
+ if (i == 10) {
+ break;
+ }
+ }
+ });
+ return btn;
+ }
+
+ function masterTableOptionsReloadTableAP() {
+ let btn = $('reload table ');
+ btn.click(function() {
+ displayAircraftProfitability();
+ });
+ return btn;
+ }
+
+ function masterTableOptionsRemoveAircraft() {
+ let btn = $('remove aircraft (permanent) ');
+ btn.click(function() {
+ let id = [];
+ let aircraftKey = [];
+ $('tbody tr', table).has('input:checked').each(function() {
+ let localId = $(this).attr('id');
+ id.push(localId);
+ aircraftKey.push(server + 'aircraftFlights' + localId);
+ $(this).remove();
+ });
+ if (id.length) {
+ let fleetKey = server + airline.name + 'aircraftFleet';
+ chrome.storage.local.get(fleetKey, function(result) {
+ let storedFleetData = result[fleetKey];
+ let newFleet = storedFleetData.fleet.filter(function(value) {
+ let keep = 1;
+ id.forEach(function(idVal) {
+ if (idVal == value.aircraftId) {
+ keep = 0;
+ }
+ });
+ return keep;
+ });
+ storedFleetData.fleet = newFleet;
+ chrome.storage.local.set({
+ [fleetKey]: storedFleetData }, function() {
+ chrome.storage.local.remove(aircraftKey, function() {});
+ });
+ });
+ }
+ });
+ return btn;
+ }
+
+ function masterTableOptionsApplyFilter() {
+ let btn = $('apply filter ');
+ btn.click(function() {
+ let filter = [];
+ table.closest(".as-panel").find('fieldset:eq(1) table tbody tr').each(function() {
+ filter.push({
+ titlecode: $(this).find('input').val(),
+ title: $(this).find('td:eq(0)').text(),
+ operation: $(this).find('td:eq(1)').text(),
+ value: $(this).find('td:eq(2)').text()
+ })
+ });
+ settings[tableOptionsRule.tableSettingStorage].filter = filter;
+ chrome.storage.local.set({ settings: settings }, function() {
+ $('tbody tr', table).each(function() {
+ let row = this;
+ filter.forEach(function(filter) {
+ let cell = $(row).find("." + tableOptionsRule.columnPrefix + filter.titlecode).text();
+ //if(cell){
+ //Get collumn info if number or not
+ let number;
+ for (let i = 0; i < tableOptionsRule.column.length; i++) {
+ let column = tableOptionsRule.column[i];
+ if (filter.titlecode == column.data) {
+ number = column.number;
+ break;
+ }
+ }
+ let value = filter.value;
+ if (number) {
+ if (cell) {
+ cell = parseInt(cell, 10);
+ }
+ if (value) {
+ value = parseInt(value, 10);
+ }
+ }
+ switch (filter.operation) {
+ case '=':
+ if (cell != value) {
+ $(row).remove();
+ }
+ break;
+ case '!=':
+ if (cell == value) {
+ $(row).remove();
+ }
+ break;
+ case '>':
+ if (cell < value) {
+ $(row).remove();
+ }
+ break;
+ case '<':
+ if (cell > value) {
+ $(row).remove();
+ }
+ }
+ });
+ });
+ });
+ });
+ return btn;
+ }
+
+ function masterTableOptionsRemoveSelected() {
+ let btn = $('hide selected ');
+ btn.click(function() {
+ $('tbody tr', table).has('input:checked').remove();
+ });
+ return btn;
+ }
+ }
+ }
+
+ function masterTableFilter(filter, column) {
+ //Table head
+ let th = [];
+ th.push('Column ');
+ th.push('Operation ');
+ th.push('Value ');
+ th.push(' ');
+ let thead = $(' ').append($(' ').append(th));
+ //Table body
+ let row = [];
+ if (filter) {
+ filter.forEach(function(fil) {
+ row.push($(' ').append(masterTableFilterAddBodyRow(fil.titlecode, fil.title, fil.operation, fil.value)));
+ });
+ }
+
+ let tbody = $(' ').append(row);
+ //Table foot
+ //select collumn
+ let option1 = [];
+ column.forEach(function(col) {
+ option1.push('' + col.title + ' ');
+ });
+ let select1 = $(' ').append(option1);
+ //Select value
+ let option = [];
+ option.push('= ');
+ option.push('!= ');
+ option.push('> ');
+ option.push('< ');
+ let select = $(' ').append(option);
+ //Value
+ let input = $(' ');
+ //Add button
+ let btn = $(' ').text('Add Row');
+ btn.click(function() {
+ let column = $('option:selected', select1).text();
+ let columnVal = $('option:selected', select1).val();
+ let operation = $('option:selected', select).text();
+ let value = input.val();
+ tbody.append($(' ').append(masterTableFilterAddBodyRow(columnVal, column, operation, value)));
+ });
+ //Footer rows
+ let tf = [];
+ tf.push($(' ').html(select1));
+ tf.push($(' ').html(select));
+ tf.push($(' ').html(input));
+ tf.push($(' ').append(btn));
+ let tfoot = $(' ').append($(' ').append(tf));
+ let tableFilter = $('').append(thead, tbody, tfoot);
+ let divTable = $('
').append(tableFilter);
+ //Closable legend
+ let link = $(' ').text('Filter');
+ let legend = $(' ').html(link);
+ link.click(function() {
+ divTable.toggle();
+ });
+ let fieldset = $(' ').append(legend, divTable);
+ return fieldset;
+ //Functions
+ function masterTableFilterAddBodyRow(titleCode, title, operation, value) {
+ let td = [];
+ td.push(' ' + title + ' ');
+ td.push('' + operation + ' ');
+ td.push('' + value + ' ');
+ let deleteBtn = $(' ').html(' ');
+ deleteBtn.click(function() {
+ $(this).closest("tr").remove();
+ });
+ td.push($(' ').append(deleteBtn));
+ return td;
+ }
+ }
+
+ function masterTableColumns() {
+ //Table head
+ let th = [];
+ th.push('Show ');
+ th.push('Column ');
+ let thead = $(' ').append($(' ').append(th));
+ //Table body
+ let row = [];
+ tableOptionsRule.column.forEach(function(col) {
+ let td = []
+ let input = $(' ');
+ input.change(function() {
+ if (!tableOptionsRule.hideColumn) {
+ tableOptionsRule.hideColumn = [];
+ }
+ let newHideColumns = [];
+ let currentColumn = $(this).val();
+ newHideColumns = tableOptionsRule.hideColumn.filter(function(value) {
+ return value != currentColumn;
+ });
+ if (!this.checked) {
+ newHideColumns.push(currentColumn);
+ }
+
+ tableOptionsRule.hideColumn = newHideColumns;
+ settings[tableOptionsRule.tableSettingStorage].hideColumn = tableOptionsRule.hideColumn;
+ chrome.storage.local.set({ settings: settings }, function() {});
+ })
+ if (col.visible) {
+ input.prop('checked', true);
+ }
+ td.push($(' ').append(input));
+ td.push($(' ').text(col.title));
+ row.push($(' ').append(td));
+ });
+ let tbody = $(' ').append(row);
+ let tableColumns = $('').append(thead, tbody);
+ let divTable = $('
').append(tableColumns).hide();
+ //Closable legend
+ let link = $(' ').text('Columns');
+ let legend = $(' ').html(link);
+ link.click(function() {
+ divTable.toggle();
+ });
+ let fieldset = $(' ').append(legend, divTable);
+ return fieldset;
+ }
+}
+//Display general helper functions
+function generalAddScheduleRow(tbody) {
+ let td1 = $(' ').text("Schedule");
+ let td2 = $(' ');
+ let td3 = $(' ');
+ let row = $(' ').append(td1, td2, td3);
+ tbody.append(row);
+ //Get schedule
+ let scheduleKey = server + airline.code + 'schedule';
+ chrome.storage.local.get([scheduleKey], function(result) {
+ let scheduleData = result[scheduleKey];
+ if (scheduleData) {
+ let lastUpdate = getDate('schedule', scheduleData.date);
+ let diff = AES.getDateDiff([todayDate.date, lastUpdate]);
+ let span = $(' ').text('Last schedule extract ' + AES.formatDateString(lastUpdate) + ' (' + diff + ' days ago). Extract new schedule if there are new routes.');
+ if (diff >= 0 && diff < 7) {
+ span.addClass('good');
+ } else {
+ span.addClass('warning');
+ }
+ td2.append(span);
+ generalUpdateScheduleAction(td3);
+
+
+
+ } else {
+ //no schedule
+ td2.html('No Schedule data found. Extract schedule or some AES parts will not work ');
+ generalUpdateScheduleAction(td3);
+ }
+ });
+}
+
+function generalUpdateScheduleAction(td3) {
+ let btn = $('extract schedule data ');
+ btn.click(function() {
+ settings.schedule.autoExtract = 1;
+ //get schedule link
+ let link = $('#enterprise-dashboard table:eq(0) tfoot td a:eq(2)');
+ chrome.storage.local.set({ settings: settings }, function() {
+ link[0].click();
+ });
+ });
+ td3.append(btn);
+}
+
+function generalAddPersonelManagementRow(tbody) {
+ let td = [];
+ td.push($(' ').text("Personnel Management"));
+ td.push($(' '));
+ td.push($(' '));
+ let row = $(' ').append(td);
+ tbody.append(row);
+ //Get Status
+ let key = server + airline.name + 'personelManagement';
+ chrome.storage.local.get([key], function(result) {
+ let personelManagementData = result[key];
+ if (personelManagementData) {
+ let lastUpdate = personelManagementData.date;
+ let diff = AES.getDateDiff([todayDate.date, lastUpdate]);
+ let span = $(' ').text('Last personnel salary update: ' + AES.formatDateString(lastUpdate) + ' (' + diff + ' days ago).');
+ if (diff >= 0 && diff < 7) {
+ span.addClass('good');
+ } else {
+ span.addClass('warning');
+ }
+ td[1].append(span);
+ } else {
+ //no schedule
+ td[1].html('No personnel salary update date found. ');
+ }
+ });
+
+ //Action
+ let btn = $('open personel management ');
+ btn.click(function() {
+ //get schedule link
+ let link = $('#as-navbar-main-collapse > ul > li:eq(4) > ul > li:eq(5) > a');
+ link[0].click();
+ });
+ td[2].append(btn);
+}
+//Display default
+function displayDefault() {
+ let mainDiv = $("#aes-div-dashboard");
+ mainDiv.empty();
+}
+
+//Table sort and other functions
+function SortTable(collumn, number, tableId, collumnPrefix) {
+ let tableRows = $('#' + tableId + ' tbody tr');
+ let tableBody = $('#' + tableId + ' tbody');
+ tableBody.empty();
+ let indexes = [];
+ tableRows.each(function() {
+ if (number) {
+ let value = parseInt($(this).find("." + collumnPrefix + collumn).text(), 10);
+ if (value) {
+ indexes.push(value);
+ } else {
+ indexes.push(0);
+ }
+ } else {
+ indexes.push($(this).find("." + collumnPrefix + collumn).text());
+ }
+ });
+ indexes = [...new Set(indexes)];
+ let sorted = [...indexes];
+ if (number) {
+ sorted.sort(function(a, b) {
+ if (a > b) return -1;
+ if (a < b) return 1;
+ if (a = b) return 0;
+ });
+ } else {
+ sorted.sort();
+ }
+ let same = 1;
+ for (let i = 0; i < indexes.length; i++) {
+ if (indexes[i] !== sorted[i]) {
+ same = 0;
+ }
+ }
+ if (same) {
+ if (number) {
+ sorted.sort(function(a, b) {
+ if (a < b) return -1;
+ if (a > b) return 1;
+ if (a = b) return 0;
+ });
+ } else {
+ sorted.reverse();
+ }
+ }
+ for (let i = 0; i < sorted.length; i++) {
+ for (let j = tableRows.length - 1; j >= 0; j--) {
+ if (number) {
+ let value = parseInt($(tableRows[j]).find("." + collumnPrefix + collumn).text(), 10);
+ if (!value) {
+ value = 0;
+ }
+ if (value == sorted[i]) {
+ tableBody.append($(tableRows[j]));
+ tableRows.splice(j, 1);
+ }
+ } else {
+ if ($(tableRows[j]).find("." + collumnPrefix + collumn).text() == sorted[i]) {
+ tableBody.append($(tableRows[j]));
+ tableRows.splice(j, 1);
+ }
+ }
+ }
+ }
+}
+
+//Helper
+function getDate(type, scheduleData) {
+ switch (type) {
+ case 'schedule':
+ //scheduleData must be schedule object with dates as properties
+ let dates = [];
+ for (let date in scheduleData) {
+ if (Number.isInteger(parseInt(date))) {
+ dates.push(date);
+ }
+ }
+ dates.reverse();
+ return dates[0];
+ default:
+ return 0;
+ }
+}
diff --git a/extension/content_enterpriceOverview.js b/extension/content_enterpriceOverview.js
index 61fb8a9..fb64b2f 100644
--- a/extension/content_enterpriceOverview.js
+++ b/extension/content_enterpriceOverview.js
@@ -1,398 +1,366 @@
-"use strict";
-//MAIN
-//Global vars
-var server,airlineId,activeTab,compData;
-$(function(){
- server = getServerName();
- airlineId = getAirlineId();
- activeTab = $(".nav-tabs .active").attr('class').split(" ");
- activeTab = activeTab[0];
- let key = server+airlineId+'competitorMonitoring';
- chrome.storage.local.get([key], function(compMonitoringData) {
- compData = compMonitoringData[key];
- if(!compData){
- compData = {
- key:key,
- server:server,
- id:airlineId,
- type:"competitorMonitoring",
- tab0:{},
- tab2:{},
- tracking:0,
- autoExtract:0
- }
- }
- displayMain();
-
-
-
- });
-});
-function displayMain(){
- //Clean
- $('#aes-panel-airline-competitive-monitoring').remove();
- //panel
- let panel = $('
');
-
- //Checkbox
- let checkbox = $(' ');
- let label = $(' ').append(checkbox,' follow this airline in Competitor Monitoring');
- let divCheckbox = $('
').append(label);
-
- //Competitive display comp monitoring
- let divComp = $('
');
- $(checkbox).change(function() {
- if(this.checked) {
- //Update tracker
- compData.tracking =1;
- chrome.storage.local.set({[compData.key]: compData}, function() {});
-
- //Action bar
- let actionBar = $('');
- divComp.append(actionBar);
- //Display
- displayCompetitorMonitoring(divComp);
-
-
- switch(activeTab) {
- case 'tab0':
-
- displayTab0(actionBar);
- break;
- case 'tab1':
- // Nothing
- break;
- case 'tab2':
- displayTab2(actionBar)
- break;
- case 'tab3':
- // Nothing Controled via schedule content script
- break;
- default:
- console.log('Error 0925: Enterprice Overview Active Tab not found '+activeTab)
- die();
- }
- displayAutomation(actionBar);
- } else {
- //Update tracker
- compData.tracking =0;
- chrome.storage.local.set({[compData.key]: compData}, function() {});
- //Display
- divComp.empty();
- }
- });
- //Checkbox default
- if(compData.tracking){
- checkbox.prop('checked', true);
- checkbox.trigger("change");
- }
- //panel
- panel.append(divCheckbox);
-
-
- //Add display
- let mainDiv = $('
').append('AirlineSim Enhancement Suite Airline ',panel,divComp);
- $(".container-fluid:eq(2) h2").after(mainDiv);
-}
-function displayAutomation(actionBar){
- if(!compData.autoExtract){ //
- let span = $(' ');
- let btn = $('save all tab data ');
- btn.click(function(){
- btn.remove();
- span.removeClass().addClass('warning').text('extracting...');
- compData.autoExtract = 1;
- if(activeTab == 'tab0'){
- $('#aes-btn-save-tab0-data').click();
- } else {
- window.open('./'+airlineId+'?tab=0','_self');
- }
- });
- let li = $(' ').append(btn,span);
- actionBar.append(li);
- } else {
- let span = $(' ').addClass('warning').text('Please wait... extracting all tab info...');
- let li = $(' ').append(span);
- actionBar.append(li);
- }
-}
-function displayCompetitorMonitoring(div){
- let th = [];
- th.push('Overview ');
- th.push('Facts and Figures ');
- th.push('Schedule ');
- let headRow = $(' ').append(th);
- let thead = $(' ').append(headRow);
- //body
- let td = [];
- td.push($(' ').html(displayOverviewRow()));
- td.push($(' ').html(displayFactsAndFiguresRow()));
- td.push($(' ').html(displayScheduleRow()));
- let row = $(' ').append(td);
- let tbody = $(' ').append(row);
- let table = $('').append(thead,tbody);
- let divTable = $('
').append(table);
- let divPanel = $('
').append(divTable);
-
- div.append(divPanel);
-
-}
-function displayTab0(actionBar){
- //Get data
- let data = getTab0Data();
- //Save Data
- let span = $(' ');
- let btnSave = $('save competitor overview data ');
-
- btnSave.click(function(){
- btnSave.remove();
- span.removeClass().addClass('warning').text('saving data...');
- let time = getDate();
-
- compData.tab0[time.date] = data;
- compData.tab0[time.date].updateTime = time.time;
- compData.tab0[time.date].date = time.date;
- chrome.storage.local.set({[compData.key]: compData}, function() {
- span.removeClass().addClass("good").text("Overview Tab data Saved!");
- if(compData.autoExtract){
- window.open('./'+airlineId+'?tab=2','_self');
- }
-
- });
- });
- let li = $(' ').append(span,btnSave);
- actionBar.append(li);
-
- //Automation
- if(compData.autoExtract){
- btnSave.click();
- }
-}
-function displayTab2(actionBar){
- let data = getTab2Data();
- //Save Data
- let span = $(' ');
- let btnSave = $('save fact and figures data ');
-
- //Check if this week already saved
- let update =1;
- let dates = [];
- for(let date in compData.tab2) {
- dates.push(date);
- }
- dates.sort(function(a, b){return b-a});
- if(dates.length){
- if(compData.tab2[dates[0]].week == data.week){
- update=0;
- }
- }
-
-
- let li;
- if(update){
- btnSave.click(function(){
- btnSave.remove();
- span.removeClass().addClass('warning').text('saving data...');
- let time = getDate();
-
- compData.tab2[time.date] = data;
- compData.tab2[time.date].updateTime = time.time;
- compData.tab2[time.date].date = time.date;
- chrome.storage.local.set({[compData.key]: compData}, function() {
- span.removeClass().addClass("good").text("Fact and figures Tab data Saved!");
- if(compData.autoExtract){
- window.open('./'+airlineId+'?tab=3','_self');
- }
- });
- });
- li = $(' ').append(span,btnSave);
- } else {
- span.addClass('good').text('The current week facts and figures data is already saved');
- li = $(' ').append(span);
- }
-
-
-
-
- actionBar.append(li);
-
- //Automation
- if(compData.autoExtract){
- if(update){
- btnSave.click();
- } else {
- window.open('./'+airlineId+'?tab=3','_self');
- }
- }
-}
-function displayOverviewRow(){
- let span = $(' ');
- let dates = [];
- for(let propertyName in compData.tab0) {
- dates.push(propertyName);
- }
- dates.sort(function(a, b){return b-a});
- if(dates.length){
- let diff = getDateDiff(getDate().date,dates[0]);
- span.text('Last overview extract '+formatDate(dates[0])+' ('+diff+' days ago)');
- if(diff >= 0 && diff < 7){
- span.addClass('good');
- } else {
- span.addClass('warning');
- }
- } else {
- span.addClass('bad').text('No Overview data')
- }
- return span;
-}
-function displayFactsAndFiguresRow(){
- let span = $(' ');
- let dates = [];
- for(let propertyName in compData.tab2) {
- dates.push(propertyName);
- }
- dates.sort(function(a, b){return b-a});
- if(dates.length){
- let diff = getDateDiff(getDate().date,dates[0]);
- span.text('Last facts and figures extract for week '+formatWeekDate(compData.tab2[dates[0]].week)+' done on '+formatDate(dates[0])+' ('+diff+' days ago)');
- if(diff >= 0 && diff < 7){
- span.addClass('good');
- } else {
- span.addClass('warning');
- }
- } else {
- span.addClass('bad').text('No facts and figures data');
- }
- return span;
-}
-function displayScheduleRow(){
- let span = $(' ');
- let dates = [];
- for(let propertyName in compData.tab0) {
- dates.push(propertyName);
- }
- dates.sort(function(a, b){return b-a});
- if(dates.length){
- let code = compData.tab0[dates[0]].code;
- let scheduleKey = server+code+'schedule';
- chrome.storage.local.get([scheduleKey], function(result) {
- let scheduleData = result[scheduleKey];
- if(scheduleData){
- let scheduleDates = [];
- for(let date in scheduleData.date){
- scheduleDates.push(date);
- }
- scheduleDates.reverse();
- let diff = getDateDiff(getDate().date,scheduleDates[0]);
- span.text('Last schedule extract '+formatDate(dates[0])+' ('+diff+' days ago)');
- if(diff >= 0 && diff < 7){
- span.addClass('good');
- } else {
- span.addClass('warning');
- }
- } else {
- //no schedule
- span.addClass('bad').text('No Schedule data found.');
- }
- });
- } else {
- span.addClass('bad').text('Extract overview to see schedule data');
- }
- return span;
-
-}
-function getTab0Data(){
- let data = {};
- //airline generic ;
- let airline = getAirline();
- data.code = airline.code;
- data.name = airline.name;
- data.displayName = airline.displayName;
- //First table
- let table = $(".layout-col-md-4 > .as-fieldset:eq(0) table tbody");
- data.rating = $('td:eq(1)',$('tr',table).last()).text().trim().replace(/[^A-Za-z0-9]/g, '');
- //console.log(table.find('tr:eq(9) td:eq(1)').text().trim().replace(/[^A-Za-z0-9]/g, ''));
- //console.log($('tr td:eq(1)',table).last().text().trim().replace(/[^A-Za-z0-9]/g, ''));
- //console.log($('td:eq(1)',$('tr',table).last()).text().trim().replace(/[^A-Za-z0-9]/g, ''));
- //Second Table
- table = $(".layout-col-md-4 > .as-fieldset:eq(1) table tbody");
- data.pax = parseInt(table.find('tr:eq(0) td:eq(1)').text().trim().replace(/\D/g, ''),10);
- data.cargo = parseInt(table.find('tr:eq(1) td:eq(1)').text().trim().replace(/\D/g, ''),10);
- data.stations = parseInt(table.find('tr:eq(2) td:eq(1)').text().trim().replace(/\D/g, ''),10);
- data.fleet = parseInt(table.find('tr:eq(3) td:eq(1)').text().trim().replace(/\D/g, ''),10);
- data.employees = parseInt(table.find('tr:eq(4) td:eq(1)').text().trim().replace(/\D/g, ''),10);
- data.tab0data=1;
- return data;
-}
-function getTab2Data(){
- //First table
- let data = {};
- let table = $(".tab-content table");
- data.week = parseInt(table.find('tr:eq(0) th:eq(2)').text().trim().replace(/\D/g, ''),10);
- data.airportsServed = parseInt(table.find('tbody:eq(0) tr:eq(0) td:eq(1)').text().trim().split('(')[0].replace(/\D/g, ''),10);
- data.operatedFlights = parseInt(table.find('tbody:eq(0) tr:eq(1) td:eq(1)').text().trim().split('(')[0].replace(/\D/g, ''),10);
- data.seatsOffered = parseInt(table.find('tbody:eq(1) tr:eq(2) td:eq(1)').text().trim().split('(')[0].replace(/\D/g, ''),10);
- data.sko = parseInt(table.find('tbody:eq(1) tr:eq(5) td:eq(1)').text().trim().split('(')[0].replace(/\D/g, ''),10);
- data.cargoOffered = parseInt(table.find('tbody:eq(2) tr:eq(2) td:eq(1)').text().split('(')[0].trim().replace(/\D/g, ''),10);
- data.fko = parseInt(table.find('tbody:eq(2) tr:eq(5) td:eq(1)').text().trim().split('(')[0].replace(/\D/g, ''),10);
- data.tab2data=2;
- return data;
-}
-function getAirline(){
- let table = $(".container-fluid:eq(2) .layout-row:eq(0) > .layout-col-md-4 > .as-fieldset:eq(0) table tbody");
- let code = table.find('tr:eq(1) td:eq(1)').text().trim().replace(/[^A-Za-z0-9]/g, '');
- let displayName = table.find('tr:eq(0) td:eq(1)').text().trim();
- let name = displayName.replace(/[^A-Za-z0-9]/g, '');
-
- return {code:code,name:name,displayName:displayName};
-}
-function getAirlineId(){
- //ID
- let id = window.location.pathname;
- id = id.split("/");
- id = id[id.length-1];
- return id;
-}
-function getServerName(){
- let server = window.location.hostname
- server = server.split('.');
- return server[0];
-}
-function getDate(){
- let a = $(".as-footer-line-element:has('.fa-clock-o')").text().trim();
- let b = a.split(" ");
- //For date
- let dateTemp = b[0].split("-");
- let date;
- if(dateTemp.length == 1){
- //German
- dateTemp = dateTemp[0].split(".");
- date = dateTemp.map(function(value){
- return value.replace(/[^A-Za-z0-9]/g, '');
- });
- date = date[2] + date[1] + date[0];
- } else {
- //English
- date = dateTemp.map(function(value){
- return value.replace(/[^A-Za-z0-9]/g, '');
- });
- date = date[0] + date[1] + date[2];
- }
- //For time
- let time = b[b.length-2] +' '+b[b.length-1];
- return {date:date,time:time};
-}
-function getDateDiff(date1,date2){
- //Returns day differnece between date1 - date2
- let d1 = new Date(formatDate(date1)+'T12:00:00Z');
- let d2 = new Date(formatDate(date2)+'T12:00:00Z');
- let diff = Math.round((d1 - d2)/(1000 * 60 * 60 * 24));
- return diff;
-}
-function formatDate(date){
- return date.substring(0, 4)+'-'+date.substring(4, 6)+'-'+date.substring(6, 8);
-}
-function formatWeekDate(date){
- let a = date.toString();
- return a.substring(0, 2)+'/'+a.substring(2, 6);
-}
+"use strict";
+//MAIN
+//Global vars
+var server,airlineId,activeTab,compData;
+$(function(){
+ server = getServerName();
+ airlineId = getAirlineId();
+ activeTab = $(".nav-tabs .active").attr('class').split(" ");
+ activeTab = activeTab[0];
+ let key = server+airlineId+'competitorMonitoring';
+ chrome.storage.local.get([key], function(compMonitoringData) {
+ compData = compMonitoringData[key];
+ if(!compData){
+ compData = {
+ key:key,
+ server:server,
+ id:airlineId,
+ type:"competitorMonitoring",
+ tab0:{},
+ tab2:{},
+ tracking:0,
+ autoExtract:0
+ }
+ }
+ displayMain();
+
+
+
+ });
+});
+function displayMain(){
+ //Clean
+ $('#aes-panel-airline-competitive-monitoring').remove();
+ //panel
+ let panel = $('
');
+
+ //Checkbox
+ let checkbox = $(' ');
+ let label = $(' ').append(checkbox,' follow this airline in Competitor Monitoring');
+ let divCheckbox = $('
').append(label);
+
+ //Competitive display comp monitoring
+ let divComp = $('
');
+ $(checkbox).change(function() {
+ if(this.checked) {
+ //Update tracker
+ compData.tracking =1;
+ chrome.storage.local.set({[compData.key]: compData}, function() {});
+
+ //Action bar
+ let actionBar = $('');
+ divComp.append(actionBar);
+ //Display
+ displayCompetitorMonitoring(divComp);
+
+
+ switch(activeTab) {
+ case 'tab0':
+
+ displayTab0(actionBar);
+ break;
+ case 'tab1':
+ // Nothing
+ break;
+ case 'tab2':
+ displayTab2(actionBar)
+ break;
+ case 'tab3':
+ // Nothing Controled via schedule content script
+ break;
+ default:
+ console.log('Error 0925: Enterprice Overview Active Tab not found '+activeTab)
+ die();
+ }
+ displayAutomation(actionBar);
+ } else {
+ //Update tracker
+ compData.tracking =0;
+ chrome.storage.local.set({[compData.key]: compData}, function() {});
+ //Display
+ divComp.empty();
+ }
+ });
+ //Checkbox default
+ if(compData.tracking){
+ checkbox.prop('checked', true);
+ checkbox.trigger("change");
+ }
+ //panel
+ panel.append(divCheckbox);
+
+
+ //Add display
+ let mainDiv = $('
').append('AirlineSim Enhancement Suite Airline ',panel,divComp);
+ $(".container-fluid:eq(2) h2").after(mainDiv);
+}
+function displayAutomation(actionBar){
+ if(!compData.autoExtract){ //
+ let span = $(' ');
+ let btn = $('save all tab data ');
+ btn.click(function(){
+ btn.remove();
+ span.removeClass().addClass('warning').text('extracting...');
+ compData.autoExtract = 1;
+ if(activeTab == 'tab0'){
+ $('#aes-btn-save-tab0-data').click();
+ } else {
+ window.open('./'+airlineId+'?tab=0','_self');
+ }
+ });
+ let li = $(' ').append(btn,span);
+ actionBar.append(li);
+ } else {
+ let span = $(' ').addClass('warning').text('Please wait... extracting all tab info...');
+ let li = $(' ').append(span);
+ actionBar.append(li);
+ }
+}
+function displayCompetitorMonitoring(div){
+ let th = [];
+ th.push('Overview ');
+ th.push('Facts and Figures ');
+ th.push('Schedule ');
+ let headRow = $(' ').append(th);
+ let thead = $(' ').append(headRow);
+ //body
+ let td = [];
+ td.push($(' ').html(displayOverviewRow()));
+ td.push($(' ').html(displayFactsAndFiguresRow()));
+ td.push($(' ').html(displayScheduleRow()));
+ let row = $(' ').append(td);
+ let tbody = $(' ').append(row);
+ let table = $('').append(thead,tbody);
+ let divTable = $('
').append(table);
+ let divPanel = $('
').append(divTable);
+
+ div.append(divPanel);
+
+}
+function displayTab0(actionBar){
+ //Get data
+ let data = getTab0Data();
+ //Save Data
+ let span = $(' ');
+ let btnSave = $('save competitor overview data ');
+
+ btnSave.click(function(){
+ btnSave.remove();
+ span.removeClass().addClass('warning').text('saving data...');
+ let time = AES.getServerDate()
+
+ compData.tab0[time.date] = data;
+ compData.tab0[time.date].updateTime = time.time;
+ compData.tab0[time.date].date = time.date;
+ chrome.storage.local.set({[compData.key]: compData}, function() {
+ span.removeClass().addClass("good").text("Overview Tab data Saved!");
+ if(compData.autoExtract){
+ window.open('./'+airlineId+'?tab=2','_self');
+ }
+
+ });
+ });
+ let li = $(' ').append(span,btnSave);
+ actionBar.append(li);
+
+ //Automation
+ if(compData.autoExtract){
+ btnSave.click();
+ }
+}
+function displayTab2(actionBar){
+ let data = getTab2Data();
+ //Save Data
+ let span = $(' ');
+ let btnSave = $('save fact and figures data ');
+
+ //Check if this week already saved
+ let update =1;
+ let dates = [];
+ for(let date in compData.tab2) {
+ dates.push(date);
+ }
+ dates.sort(function(a, b){return b-a});
+ if(dates.length){
+ if(compData.tab2[dates[0]].week == data.week){
+ update=0;
+ }
+ }
+
+
+ let li;
+ if(update){
+ btnSave.click(function(){
+ btnSave.remove();
+ span.removeClass().addClass('warning').text('saving data...');
+ let time = AES.getServerDate()
+
+ compData.tab2[time.date] = data;
+ compData.tab2[time.date].updateTime = time.time;
+ compData.tab2[time.date].date = time.date;
+ chrome.storage.local.set({[compData.key]: compData}, function() {
+ span.removeClass().addClass("good").text("Fact and figures Tab data Saved!");
+ if(compData.autoExtract){
+ window.open('./'+airlineId+'?tab=3','_self');
+ }
+ });
+ });
+ li = $(' ').append(span,btnSave);
+ } else {
+ span.addClass('good').text('The current week facts and figures data is already saved');
+ li = $(' ').append(span);
+ }
+
+
+
+
+ actionBar.append(li);
+
+ //Automation
+ if(compData.autoExtract){
+ if(update){
+ btnSave.click();
+ } else {
+ window.open('./'+airlineId+'?tab=3','_self');
+ }
+ }
+}
+function displayOverviewRow(){
+ let span = $(' ');
+ let dates = [];
+ for(let propertyName in compData.tab0) {
+ dates.push(propertyName);
+ }
+ dates.sort(function(a, b){return b-a});
+ if(dates.length){
+ let diff = AES.getDateDiff([AES.getServerDate().date, dates[0]]);
+ span.text('Last overview extract '+AES.formatDateString(dates[0])+' ('+diff+' days ago)');
+ if(diff >= 0 && diff < 7){
+ span.addClass('good');
+ } else {
+ span.addClass('warning');
+ }
+ } else {
+ span.addClass('bad').text('No Overview data')
+ }
+ return span;
+}
+function displayFactsAndFiguresRow(){
+ let span = $(' ');
+ let dates = [];
+ for(let propertyName in compData.tab2) {
+ dates.push(propertyName);
+ }
+ dates.sort(function(a, b){return b-a});
+ if(dates.length){
+ let diff = AES.getDateDiff([AES.getServerDate().date, dates[0]]);
+ span.text('Last facts and figures extract for week '+formatWeekDate(compData.tab2[dates[0]].week)+' done on '+AES.formatDateString(dates[0])+' ('+diff+' days ago)');
+ if(diff >= 0 && diff < 7){
+ span.addClass('good');
+ } else {
+ span.addClass('warning');
+ }
+ } else {
+ span.addClass('bad').text('No facts and figures data');
+ }
+ return span;
+}
+function displayScheduleRow(){
+ let span = $(' ');
+ let dates = [];
+ for(let propertyName in compData.tab0) {
+ dates.push(propertyName);
+ }
+ dates.sort(function(a, b){return b-a});
+ if(dates.length){
+ let code = compData.tab0[dates[0]].code;
+ let scheduleKey = server+code+'schedule';
+ chrome.storage.local.get([scheduleKey], function(result) {
+ let scheduleData = result[scheduleKey];
+ if(scheduleData){
+ let scheduleDates = [];
+ for(let date in scheduleData.date){
+ if (Number.isInteger(parseInt(date))) {
+ scheduleDates.push(date);
+ }
+ }
+ scheduleDates.reverse();
+ let diff = AES.getDateDiff([AES.getServerDate().date, scheduleDates[0]]);
+ span.text('Last schedule extract '+AES.formatDateString(dates[0])+' ('+diff+' days ago)');
+ if(diff >= 0 && diff < 7){
+ span.addClass('good');
+ } else {
+ span.addClass('warning');
+ }
+ } else {
+ //no schedule
+ span.addClass('bad').text('No Schedule data found.');
+ }
+ });
+ } else {
+ span.addClass('bad').text('Extract overview to see schedule data');
+ }
+ return span;
+
+}
+function getTab0Data(){
+ let data = {};
+ //airline generic ;
+ let airline = getAirline();
+ data.code = airline.code;
+ data.name = airline.name;
+ data.displayName = airline.displayName;
+ //First table
+ let table = $(".layout-col-md-4 > .as-fieldset:eq(0) table tbody");
+ data.rating = $('td:eq(1)',$('tr',table).last()).text().trim().replace(/[^A-Za-z0-9]/g, '');
+ //console.log(table.find('tr:eq(9) td:eq(1)').text().trim().replace(/[^A-Za-z0-9]/g, ''));
+ //console.log($('tr td:eq(1)',table).last().text().trim().replace(/[^A-Za-z0-9]/g, ''));
+ //console.log($('td:eq(1)',$('tr',table).last()).text().trim().replace(/[^A-Za-z0-9]/g, ''));
+ //Second Table
+ table = $(".layout-col-md-4 > .as-fieldset:eq(1) table tbody");
+ data.pax = parseInt(table.find('tr:eq(0) td:eq(1)').text().trim().replace(/\D/g, ''),10);
+ data.cargo = parseInt(table.find('tr:eq(1) td:eq(1)').text().trim().replace(/\D/g, ''),10);
+ data.stations = parseInt(table.find('tr:eq(2) td:eq(1)').text().trim().replace(/\D/g, ''),10);
+ data.fleet = parseInt(table.find('tr:eq(3) td:eq(1)').text().trim().replace(/\D/g, ''),10);
+ data.employees = parseInt(table.find('tr:eq(4) td:eq(1)').text().trim().replace(/\D/g, ''),10);
+ data.tab0data=1;
+ return data;
+}
+function getTab2Data(){
+ //First table
+ let data = {};
+ let table = $(".tab-content table");
+ data.week = parseInt(table.find('tr:eq(0) th:eq(2)').text().trim().replace(/\D/g, ''),10);
+ data.airportsServed = parseInt(table.find('tbody:eq(0) tr:eq(0) td:eq(1)').text().trim().split('(')[0].replace(/\D/g, ''),10);
+ data.operatedFlights = parseInt(table.find('tbody:eq(0) tr:eq(1) td:eq(1)').text().trim().split('(')[0].replace(/\D/g, ''),10);
+ data.seatsOffered = parseInt(table.find('tbody:eq(1) tr:eq(2) td:eq(1)').text().trim().split('(')[0].replace(/\D/g, ''),10);
+ data.sko = parseInt(table.find('tbody:eq(1) tr:eq(5) td:eq(1)').text().trim().split('(')[0].replace(/\D/g, ''),10);
+ data.cargoOffered = parseInt(table.find('tbody:eq(2) tr:eq(2) td:eq(1)').text().split('(')[0].trim().replace(/\D/g, ''),10);
+ data.fko = parseInt(table.find('tbody:eq(2) tr:eq(5) td:eq(1)').text().trim().split('(')[0].replace(/\D/g, ''),10);
+ data.tab2data=2;
+ return data;
+}
+function getAirline(){
+ let table = $(".container-fluid:eq(2) .layout-row:eq(0) > .layout-col-md-4 > .as-fieldset:eq(0) table tbody");
+ let code = table.find('tr:eq(1) td:eq(1)').text().trim().replace(/[^A-Za-z0-9]/g, '');
+ let displayName = table.find('tr:eq(0) td:eq(1)').text().trim();
+ let name = displayName.replace(/[^A-Za-z0-9]/g, '');
+
+ return {code:code,name:name,displayName:displayName};
+}
+function getAirlineId(){
+ //ID
+ let id = window.location.pathname;
+ id = id.split("/");
+ id = id[id.length-1];
+ return id;
+}
+function getServerName(){
+ let server = window.location.hostname
+ server = server.split('.');
+ return server[0];
+}
+function formatWeekDate(date){
+ let a = date.toString();
+ return a.substring(0, 2)+'/'+a.substring(2, 6);
+}
diff --git a/extension/content_fleetManagement.js b/extension/content_fleetManagement.js
index 6b6e2be..2797ecd 100644
--- a/extension/content_fleetManagement.js
+++ b/extension/content_fleetManagement.js
@@ -1,262 +1,237 @@
-"use strict";
-//MAIN
-//Global vars
-var aircraftData = [];
-var server,aircraftFleetKey,aircraftFleetStorageData,airlineName;
-$(function(){
- if(fltmng_fleetManagementPageOpen()){
- fltmng_getData();
- //Async start
- fltmng_getStorageData();
- }
-});
-function fltmng_fleetManagementPageOpen(){
- let a = $('.as-page-fleet-management');
- if(a.length){
- return true;
- } else {
- return false;
- }
-}
-function fltmng_getData(){
- //Global
- server = fltmng_getServerName();
- let date = fltmng_getDate();
- //Aircraft
- let table = $('.as-page-fleet-management > .row > .col-md-9 > .as-panel:eq(0) table');
- let fleet = $('.as-page-fleet-management > .row > .col-md-9 > h2:eq(0)').text();
- $('tbody tr',table).each(function(){
- let data = {
- registration: $('td:eq(1) > span:eq(0)',this).text(),
- nickname: fltmng_getNickname($('td:eq(1) > div:eq(0)',this).text()),
- equipment:$('td:eq(2) > a:eq(0)',this).text(),
- age:fltmng_getAge($('td:eq(4) > span:eq(0)',this).text()),
- maintanance:fltmng_getMaintanance($('td:eq(4) > div > span:eq(1)',this).text()),
- aircraftId:fltmng_getAircraftId($('td:eq(6) > div > div:eq(1) > a:eq(0)',this).attr('href')),
- note:fltmng_getNickname($('td:eq(7) > span > span',this).text()),
- fleet:fleet,
- date:date.date,
- time:date.time
- }
- aircraftData.push(data);
- });
-}
-function fltmng_getNickname(value){
- if(value == '...'){
- return ''
- } else {
- return value;
- }
-}
-function fltmng_getAge(value){
- value = value.replace(/[a-z]/gi, '');
- value = value.replace(',','.');
- value = parseFloat(value);
- return value;
-}
-function fltmng_getMaintanance(value){
- value = value.replace('%','');
- value = value.replace(',','.');
- value = parseFloat(value);
- return value;
-}
-function fltmng_getAircraftId(value){
- value = value.split('/');
- return parseInt(value[value.length-2],10);
-}
-function fltmng_getStorageData(){
- let keys = [];
- aircraftData.forEach(function(value){
- let key = server + 'aircraftFlights' + value.aircraftId;
- keys.push(key);
- });
- chrome.storage.local.get(keys, function(result) {
- for(let aircraftFlightData in result) {
- for (let i=0; i < aircraftData.length; i++) {
- if(aircraftData[i].aircraftId == result[aircraftFlightData].aircraftId){
- aircraftData[i].profit = {
- date:result[aircraftFlightData].date,
- finishedFlights:result[aircraftFlightData].finishedFlights,
- profit:result[aircraftFlightData].profit,
- profitFlights:result[aircraftFlightData].profitFlights,
- time:result[aircraftFlightData].time,
- totalFlights:result[aircraftFlightData].totalFlights,
- };
- }
- }
- }
- //Async
- fltmng_getAircraftStorageFleetData();
- });
-}
-function fltmng_getAircraftStorageFleetData(){
- airlineName = fltmng_getAirlineName();
- aircraftFleetKey = server + airlineName + 'aircraftFleet';
- chrome.storage.local.get(aircraftFleetKey, function(result) {
- fltmng_updateAircraftFleetStorageData(result[aircraftFleetKey]);
- fltmng_saveData();
- });
-}
-function fltmng_getAirlineName(){
- let name = $('#as-navbar-main-collapse > ul:eq(0) > li:eq(0) > a:eq(0) > span').text();
- name = name.trim().replace(/[^A-Za-z0-9]/g, '');
- return name;
-}
-function fltmng_updateAircraftFleetStorageData(data){
- aircraftFleetStorageData = {
- server:server,
- type:'aircraftFleet',
- airline:airlineName,
- fleet:aircraftData
- }
- if(data){
- let newfleet = [];
- //Push all new aircrafts
- aircraftData.forEach(function(newvalue){
- newfleet.push({
- age:newvalue.age,
- aircraftId:newvalue.aircraftId,
- date:newvalue.date,
- equipment:newvalue.equipment,
- fleet:newvalue.fleet,
- maintanance:newvalue.maintanance,
- nickname:newvalue.nickname,
- note:newvalue.note,
- registration:newvalue.registration,
- time:newvalue.time
- });
- });
-
- //push all old aircrafts that dont have new data
- data.fleet.forEach(function(value){
- let found = 0;
- newfleet.forEach(function(newValue){
- if(value.aircraftId == newValue.aircraftId){
- found = 1;
- }
- });
- if(!found){
- newfleet.push(value);
- }
- });
- //Attach new fleet
- aircraftFleetStorageData.fleet = newfleet;
- }
-}
-function fltmng_saveData(){
- //Remove profit
-
- chrome.storage.local.set({[aircraftFleetKey]: aircraftFleetStorageData}, function() {
- fltmng_display();
- });
-}
-
-function fltmng_display(){
- fltmng_displayAircraftProfit();
-
- let p = [];
- p.push($('
').html(fltmng_displaySavedAircrafts()));
- p.push($('
').html(fltmng_displayNewUpdates()));
-
- let panel = $('
').append(p);
- //Header
- let h = $(' ').text('AES Fleet Management');
- let div = $('
').append(h,panel);
- $('.as-page-fleet-management > h1:eq(0)').after(div);
-}
-function fltmng_displayAircraftProfit(){
- let table = $('.as-page-fleet-management > .row > .col-md-9 > .as-panel:eq(0) table');
- //Head
- let th = ['Profit/Loss ','Extract date '];
- $('thead tr:eq(0)',table).append(th);
- //Body
- $('tbody tr',table).each(function(){
- let id = fltmng_getAircraftId($('td:eq(6) > div > div:eq(1) > a:eq(0)',this).attr('href'));
- let profit,date,time;
- aircraftData.forEach(function(value){
- if(value.aircraftId == id){
- if(value.profit){
- if(value.profit.profitFlights){
- profit = value.profit.profit;
- date = value.profit.date;
- time = value.profit.time;
- }
- }
- }
- });
- let td = [];
- if(date){
- td.push(fltmng_formatMoney(profit));
- td.push($(' ').html(fltmng_formatDate(date)+' '+time));
- } else {
- td.push(' ',' ');
- }
- $(this).append(td);
-
- });
-}
-function fltmng_displaySavedAircrafts(){
- return 'Currently '+aircraftFleetStorageData.fleet.length+' aircrafts stored in memory.';
-}
-function fltmng_displayNewUpdates(){
- let span = $(' ').text('Updated aircraft data for '+aircraftData.length+ ' from '+aircraftData[0].fleet);
- return span;
-}
-function fltmng_getDate(){
- let a = $(".as-footer-line-element:has('.fa-clock-o')").text().trim();
- let b = a.split(" ");
- //For date
- let dateTemp = b[0].split("-");
- let date;
- if(dateTemp.length == 1){
- //German
- dateTemp = dateTemp[0].split(".");
- date = dateTemp.map(function(value){
- return value.replace(/[^A-Za-z0-9]/g, '');
- });
- date = date[2] + date[1] + date[0];
- } else {
- //English
- date = dateTemp.map(function(value){
- return value.replace(/[^A-Za-z0-9]/g, '');
- });
- date = date[0] + date[1] + date[2];
- }
- //For time
- let time = b[b.length-2] +' '+b[b.length-1];
- return {date:date,time:time};
-}
-function fltmng_getServerName(){
- let server = window.location.hostname
- server = server.split('.');
- return server[0];
-}
-function fltmng_formatMoney(value){
- let container = document.createElement("td")
- let formattedValue = Intl.NumberFormat().format(value)
- let indicatorEl = document.createElement("span")
- let valueEl = document.createElement("span")
- let currencyEl = document.createElement("span")
-
- if (value >= 0) {
- valueEl.classList.add("good")
- indicatorEl.innerText = "+"
- }
-
- if (value < 0) {
- valueEl.classList.add("bad")
- indicatorEl.innerText = "-"
- formattedValue = formattedValue.replace("-", "")
- }
-
- valueEl.innerText = formattedValue
- currencyEl.innerText = " AS$"
-
- container.classList.add("aes-text-right", "aes-no-text-wrap")
- container.append(indicatorEl, valueEl, currencyEl)
-
- return container
-}
-function fltmng_formatDate(date){
- return date.substring(0, 4)+'-'+date.substring(4, 6)+'-'+date.substring(6, 8);
-}
+"use strict";
+//MAIN
+//Global vars
+var aircraftData = [];
+var server,aircraftFleetKey,aircraftFleetStorageData,airlineName;
+$(function(){
+ if(fltmng_fleetManagementPageOpen()){
+ fltmng_getData();
+ //Async start
+ fltmng_getStorageData();
+ }
+});
+function fltmng_fleetManagementPageOpen(){
+ let a = $('.as-page-fleet-management');
+ if(a.length){
+ return true;
+ } else {
+ return false;
+ }
+}
+function fltmng_getData(){
+ //Global
+ server = fltmng_getServerName();
+ let date = AES.getServerDate()
+ //Aircraft
+ let table = $('.as-page-fleet-management > .row > .col-md-9 > .as-panel:eq(0) table');
+ let fleet = $('.as-page-fleet-management > .row > .col-md-9 > h2:eq(0)').text();
+ $('tbody tr',table).each(function(){
+ let data = {
+ registration: $('td:eq(1) > span:eq(0)',this).text(),
+ nickname: fltmng_getNickname($('td:eq(1) > div:eq(0)',this).text()),
+ equipment:$('td:eq(2) > a:eq(0)',this).text(),
+ age:fltmng_getAge($('td:eq(4) > span:eq(0)',this).text()),
+ maintanance:fltmng_getMaintanance($('td:eq(4) > div > span:eq(1)',this).text()),
+ aircraftId:fltmng_getAircraftId($('td:eq(6) > div > div:eq(1) > a:eq(0)',this).attr('href')),
+ note:fltmng_getNickname($('td:eq(7) > span > span',this).text()),
+ fleet:fleet,
+ date:date.date,
+ time:date.time
+ }
+ aircraftData.push(data);
+ });
+}
+function fltmng_getNickname(value){
+ if(value == '...'){
+ return ''
+ } else {
+ return value;
+ }
+}
+function fltmng_getAge(value){
+ value = value.replace(/[a-z]/gi, '');
+ value = value.replace(',','.');
+ value = parseFloat(value);
+ return value;
+}
+function fltmng_getMaintanance(value){
+ value = value.replace('%','');
+ value = value.replace(',','.');
+ value = parseFloat(value);
+ return value;
+}
+function fltmng_getAircraftId(value){
+ if (value) {
+ value = value.split('/');
+ return parseInt(value[value.length-2],10);
+ }
+}
+function fltmng_getStorageData(){
+ let keys = [];
+ aircraftData.forEach(function(value){
+ let key = server + 'aircraftFlights' + value.aircraftId;
+ keys.push(key);
+ });
+ chrome.storage.local.get(keys, function(result) {
+ for(let aircraftFlightData in result) {
+ for (let i=0; i < aircraftData.length; i++) {
+ if(aircraftData[i].aircraftId == result[aircraftFlightData].aircraftId){
+ aircraftData[i].profit = {
+ date:result[aircraftFlightData].date,
+ finishedFlights:result[aircraftFlightData].finishedFlights,
+ profit:result[aircraftFlightData].profit,
+ profitFlights:result[aircraftFlightData].profitFlights,
+ time:result[aircraftFlightData].time,
+ totalFlights:result[aircraftFlightData].totalFlights,
+ };
+ }
+ }
+ }
+ //Async
+ fltmng_getAircraftStorageFleetData();
+ });
+}
+function fltmng_getAircraftStorageFleetData(){
+ airlineName = fltmng_getAirlineName();
+ aircraftFleetKey = server + airlineName + 'aircraftFleet';
+ chrome.storage.local.get(aircraftFleetKey, function(result) {
+ fltmng_updateAircraftFleetStorageData(result[aircraftFleetKey]);
+ fltmng_saveData();
+ });
+}
+function fltmng_getAirlineName(){
+ let name = $('#as-navbar-main-collapse > ul:eq(0) > li:eq(0) > a:eq(0) > span').text();
+ name = name.trim().replace(/[^A-Za-z0-9]/g, '');
+ return name;
+}
+function fltmng_updateAircraftFleetStorageData(data){
+ aircraftFleetStorageData = {
+ server:server,
+ type:'aircraftFleet',
+ airline:airlineName,
+ fleet:aircraftData
+ }
+ if(data){
+ let newfleet = [];
+ //Push all new aircrafts
+ aircraftData.forEach(function(newvalue){
+ newfleet.push({
+ age:newvalue.age,
+ aircraftId:newvalue.aircraftId,
+ date:newvalue.date,
+ equipment:newvalue.equipment,
+ fleet:newvalue.fleet,
+ maintanance:newvalue.maintanance,
+ nickname:newvalue.nickname,
+ note:newvalue.note,
+ registration:newvalue.registration,
+ time:newvalue.time
+ });
+ });
+
+ //push all old aircrafts that dont have new data
+ data.fleet.forEach(function(value){
+ let found = 0;
+ newfleet.forEach(function(newValue){
+ if(value.aircraftId == newValue.aircraftId){
+ found = 1;
+ }
+ });
+ if(!found){
+ newfleet.push(value);
+ }
+ });
+ //Attach new fleet
+ aircraftFleetStorageData.fleet = newfleet;
+ }
+}
+function fltmng_saveData(){
+ //Remove profit
+
+ chrome.storage.local.set({[aircraftFleetKey]: aircraftFleetStorageData}, function() {
+ fltmng_display();
+ });
+}
+
+function fltmng_display(){
+ fltmng_displayAircraftProfit();
+
+ let p = [];
+ p.push($('
').html(fltmng_displaySavedAircrafts()));
+ p.push($('
').html(fltmng_displayNewUpdates()));
+
+ let panel = $('
').append(p);
+ //Header
+ let h = $(' ').text('AES Fleet Management');
+ let div = $('
').append(h,panel);
+ $('.as-page-fleet-management > h1:eq(0)').after(div);
+}
+function fltmng_displayAircraftProfit(){
+ let table = $('.as-page-fleet-management > .row > .col-md-9 > .as-panel:eq(0) table');
+ //Head
+ let th = ['Profit/Loss ','Extract date '];
+ $('thead tr:eq(0)',table).append(th);
+ //Body
+ $('tbody tr',table).each(function(){
+ let id = fltmng_getAircraftId($('td:eq(6) > div > div:eq(1) > a:eq(0)',this).attr('href'));
+ let profit,date,time;
+ aircraftData.forEach(function(value){
+ if(value.aircraftId == id){
+ if(value.profit){
+ if(value.profit.profitFlights){
+ profit = value.profit.profit;
+ date = value.profit.date;
+ time = value.profit.time;
+ }
+ }
+ }
+ });
+ let td = [];
+ if(date){
+ td.push(fltmng_formatMoney(profit));
+ td.push($(' ').html(AES.formatDateString(date)+' '+time));
+ } else {
+ td.push(' ',' ');
+ }
+ $(this).append(td);
+
+ });
+}
+function fltmng_displaySavedAircrafts(){
+ return 'Currently '+aircraftFleetStorageData.fleet.length+' aircrafts stored in memory.';
+}
+function fltmng_displayNewUpdates(){
+ let span = $(' ').text('Updated aircraft data for '+aircraftData.length+ ' from '+aircraftData[0].fleet);
+ return span;
+}
+function fltmng_getServerName(){
+ let server = window.location.hostname
+ server = server.split('.');
+ return server[0];
+}
+function fltmng_formatMoney(value){
+ let container = document.createElement("td")
+ let formattedValue = Intl.NumberFormat().format(value)
+ let indicatorEl = document.createElement("span")
+ let valueEl = document.createElement("span")
+ let currencyEl = document.createElement("span")
+
+ if (value >= 0) {
+ valueEl.classList.add("good")
+ indicatorEl.innerText = "+"
+ }
+
+ if (value < 0) {
+ valueEl.classList.add("bad")
+ indicatorEl.innerText = "-"
+ formattedValue = formattedValue.replace("-", "")
+ }
+
+ valueEl.innerText = formattedValue
+ currencyEl.innerText = " AS$"
+
+ container.classList.add("aes-text-right", "aes-no-text-wrap")
+ container.append(indicatorEl, valueEl, currencyEl)
+
+ return container
+}
diff --git a/extension/content_flightInfo.js b/extension/content_flightInfo.js
index 1743989..e8ec437 100644
--- a/extension/content_flightInfo.js
+++ b/extension/content_flightInfo.js
@@ -1,197 +1,164 @@
-"use strict";
-//MAIN
-//Global vars
-var flightInfoData,saveDataSpan;
-$(function(){
- if(privateFlight()){
- if(correctTabOpen()){
- flightInfoData = getData();
- saveData();
- display();
- }
- }
-});
-function saveData(){
- saveDataSpan = $(' ');
- let key = flightInfoData.server+flightInfoData.type+flightInfoData.flightId;
- chrome.storage.local.set({[key]: flightInfoData}, function() {
- saveDataSpan.addClass('good').text('Flight info data saved!');
- chrome.storage.local.get(['settings'], function(result) {
- let settings = result.settings;
- if(settings.flightInfo){
- if(settings.flightInfo.autoClose){
- close();
- }
- }
- });
- });
-}
-function privateFlight(){
- let headers = $('#privInf');
- if(headers.length){
- return true;
- } else {
- return false;
- }
-}
-function correctTabOpen(){
- if($('#flight-page > ul > li:eq(0)').hasClass('active')){
- return true;
- } else {
- return false;
- }
-}
-function getData(){
- //Flight ID
- let flightId = getFlightId();
- let date = getDate();
- let money = getFinancials();
- let server = getServerName();
- return {
- server:server,
- flightId:flightId,
- type:'flightInfo',
- money:money,
- date:date.date,
- time:date.time
- }
-}
-function display(){
- let tableWell = $('
').append(buildTable());
- let p = $('
').html(saveDataSpan);
- let panel = $('
').append(tableWell,p);
- let h = $(' ').text('AES Flight Information');
- let div = $('
').append(h,panel);
- $('body > .container-fluid:eq(0) > h1:eq(0)').after(div);
-}
-function buildTable(){
- //head
- let th = [];
- th.push(' ');
- th.push('Y ');
- th.push('C ');
- th.push('F ');
- th.push('PAX ');
- th.push('Cargo ');
- th.push('Total ');
- let hrow = $(' ').append(th);
- let thead = $(' ').append(hrow);
- //body
- let row = [];
- for(let cm in flightInfoData.money) {
- let td = [];
- td.push(''+cm+' ');
- for(let cmp in flightInfoData.money[cm]) {
- td.push($(' ').html(formatMoney(flightInfoData.money[cm][cmp])));
- }
- row.push($(' ').append(td));
- }
- let tbody = $(' ').append(row);
- //foot
- let tf = [];
- tf.push('Flight Id: ');
- tf.push(''+flightInfoData.flightId+' ');
- tf.push('Date: ');
- tf.push(''+formatDate(flightInfoData.date)+' '+flightInfoData.time+' ');
- tf.push(' ');
- tf.push(' ');
- tf.push(' ');
- let frow = $(' ').append(tf);
- let fblankRow = $(' ').append(' ');
- let tfoot = $(' ').append(fblankRow,frow);
- return $('').append(thead,tbody,tfoot);
-}
-function formatMoney(value){
- let span = $(' ');
- let text = '';
- if(value > 0){
- span.addClass('good');
- text = '+'
- }
- if(value < 0){
- span.addClass('bad');
- }
- text = text + value + ' AS$';
- span.text(text);
- return span;
-}
-function formatDate(date){
- return date.substring(0, 4)+'-'+date.substring(4, 6)+'-'+date.substring(6, 8);
-}
-function getFinancials(){
- let data = {};
- let cm = $('.cm');
- cm.each(function(index){
- let contMargin = 'CM'+(index + 1);
- $('td',this).each(function(i){
- let cmp;
- switch(i) {
- case 0:
- cmp = 'Y'
- break;
- case 1:
- cmp = 'C'
- break;
- case 2:
- cmp = 'F'
- break;
- case 3:
- cmp = 'PAX'
- break;
- case 4:
- cmp = 'Cargo'
- break;
- case 5:
- cmp = 'Total'
- break;
- }
- let value = cleanInteger($(this).text());
- if(!data[contMargin]){
- data[contMargin] = {}
- }
- data[contMargin][cmp] = value;
- });
- });
- return data;
-}
-function getFlightId(){
- let url = window.location.href;
- let a = url.split('id=');
- let b = a[1].split('&');
- return parseInt(b[0],10);
-}
-function getDate(){
- let a = $(".as-footer-line-element:has('.fa-clock-o')").text().trim();
- let b = a.split(" ");
- //For date
- let dateTemp = b[0].split("-");
- let date;
- if(dateTemp.length == 1){
- //German
- dateTemp = dateTemp[0].split(".");
- date = dateTemp.map(function(value){
- return value.replace(/[^A-Za-z0-9]/g, '');
- });
- date = date[2] + date[1] + date[0];
- } else {
- //English
- date = dateTemp.map(function(value){
- return value.replace(/[^A-Za-z0-9]/g, '');
- });
- date = date[0] + date[1] + date[2];
- }
- //For time
- let time = b[b.length-2] +' '+b[b.length-1];
- return {date:date,time:time};
-}
-function cleanInteger(a){
- a = a.replace(',','');
- a = a.replace('.','');
- a = a.replace(' AS$','');
- return parseInt(a, 10);
-}
-function getServerName(){
- let server = window.location.hostname
- server = server.split('.');
- return server[0];
-}
+"use strict";
+//MAIN
+//Global vars
+var flightInfoData,saveDataSpan;
+$(function(){
+ if(privateFlight()){
+ if(correctTabOpen()){
+ flightInfoData = getData();
+ saveData();
+ display();
+ }
+ }
+});
+function saveData(){
+ saveDataSpan = $(' ');
+ let key = flightInfoData.server+flightInfoData.type+flightInfoData.flightId;
+ chrome.storage.local.set({[key]: flightInfoData}, function() {
+ saveDataSpan.addClass('good').text('Flight info data saved!');
+ chrome.storage.local.get(['settings'], function(result) {
+ let settings = result.settings;
+ if(settings.flightInfo){
+ if(settings.flightInfo.autoClose){
+ close();
+ }
+ }
+ });
+ });
+}
+function privateFlight(){
+ let headers = $('#privInf');
+ if(headers.length){
+ return true;
+ } else {
+ return false;
+ }
+}
+function correctTabOpen(){
+ if($('#flight-page > ul > li:eq(0)').hasClass('active')){
+ return true;
+ } else {
+ return false;
+ }
+}
+function getData(){
+ //Flight ID
+ let flightId = getFlightId();
+ let date = AES.getServerDate()
+ let money = getFinancials();
+ let server = getServerName();
+ return {
+ server:server,
+ flightId:flightId,
+ type:'flightInfo',
+ money:money,
+ date:date.date,
+ time:date.time
+ }
+}
+function display(){
+ let tableWell = $('
').append(buildTable());
+ let p = $('
').html(saveDataSpan);
+ let panel = $('
').append(tableWell,p);
+ let h = $(' ').text('AES Flight Information');
+ let div = $('
').append(h,panel);
+ $('body > .container-fluid:eq(0) > h1:eq(0)').after(div);
+}
+function buildTable(){
+ //head
+ let th = [];
+ th.push(' ');
+ th.push('Y ');
+ th.push('C ');
+ th.push('F ');
+ th.push('PAX ');
+ th.push('Cargo ');
+ th.push('Total ');
+ let hrow = $(' ').append(th);
+ let thead = $(' ').append(hrow);
+ //body
+ let row = [];
+ for(let cm in flightInfoData.money) {
+ let td = [];
+ td.push(''+cm+' ');
+ for(let cmp in flightInfoData.money[cm]) {
+ td.push($(' ').html(AES.formatCurrency(flightInfoData.money[cm][cmp])));
+ }
+ row.push($(' ').append(td));
+ }
+ let tbody = $(' ').append(row);
+ //foot
+ let tf = [];
+ tf.push('Flight Id: ');
+ tf.push(''+flightInfoData.flightId+' ');
+ tf.push('Date: ');
+ tf.push(''+AES.formatDateString(flightInfoData.date)+' '+flightInfoData.time+' ');
+ tf.push(' ');
+ tf.push(' ');
+ tf.push(' ');
+ let frow = $(' ').append(tf);
+ let fblankRow = $(' ').append(' ');
+ let tfoot = $(' ').append(fblankRow,frow);
+ return $('').append(thead,tbody,tfoot);
+}
+function formatMoney(value){
+ let span = $(' ');
+ let text = '';
+ if(value > 0){
+ span.addClass('good');
+ text = '+'
+ }
+ if(value < 0){
+ span.addClass('bad');
+ }
+ text = text + value + ' AS$';
+ span.text(text);
+ return span;
+}
+function getFinancials(){
+ let data = {};
+ let cm = $('.cm');
+ cm.each(function(index){
+ let contMargin = 'CM'+(index + 1);
+ $('td',this).each(function(i){
+ let cmp;
+ switch(i) {
+ case 0:
+ cmp = 'Y'
+ break;
+ case 1:
+ cmp = 'C'
+ break;
+ case 2:
+ cmp = 'F'
+ break;
+ case 3:
+ cmp = 'PAX'
+ break;
+ case 4:
+ cmp = 'Cargo'
+ break;
+ case 5:
+ cmp = 'Total'
+ break;
+ }
+ let value = AES.cleanInteger($(this).text());
+ if(!data[contMargin]){
+ data[contMargin] = {}
+ }
+ data[contMargin][cmp] = value;
+ });
+ });
+ return data;
+}
+function getFlightId(){
+ let url = window.location.href;
+ let a = url.split('id=');
+ let b = a[1].split('&');
+ return parseInt(b[0],10);
+}
+function getServerName(){
+ let server = window.location.hostname
+ server = server.split('.');
+ return server[0];
+}
diff --git a/extension/content_fligthSchedule.js b/extension/content_fligthSchedule.js
index c40b7c1..8619f83 100644
--- a/extension/content_fligthSchedule.js
+++ b/extension/content_fligthSchedule.js
@@ -109,7 +109,7 @@ function extractSchedule(){
}
});
//Save to storage
- let dateTime = getDate();
+ let dateTime = AES.getServerDate()
let server = getServerName();
let airline = getAirlineCode();
let newScheduleData = {
@@ -177,30 +177,6 @@ function extractSchedule(){
}
}
//Helper Functions
-function getDate(){
- let a = $(".as-footer-line-element:has('.fa-clock-o')").text().trim();
- let b = a.split(" ");
- //For date
- let dateTemp = b[0].split("-");
- let date;
- if(dateTemp.length == 1){
- //German
- dateTemp = dateTemp[0].split(".");
- date = dateTemp.map(function(value){
- return value.replace(/[^A-Za-z0-9]/g, '');
- });
- date = date[2] + date[1] + date[0];
- } else {
- //English
- date = dateTemp.map(function(value){
- return value.replace(/[^A-Za-z0-9]/g, '');
- });
- date = date[0] + date[1] + date[2];
- }
- //For time
- let time = b[b.length-2] +' '+b[b.length-1];
- return {date:date,time:time};
-}
function getServerName(){
let server = window.location.hostname
server = server.split('.');
diff --git a/extension/content_inventory.js b/extension/content_inventory.js
index 7b9201f..b942f99 100644
--- a/extension/content_inventory.js
+++ b/extension/content_inventory.js
@@ -1,1177 +1,1100 @@
-"use strict";
-//MAIN
-//Global vars
-var settings,pricingData, todayDate, analysis;
-var aesmodule = {valid:1,error:[]};
-$(function(){
- validateAllOptions();
- if(aesmodule.valid){
- //Options correct
- chrome.storage.local.get(['settings'], function(result) {
- settings = result.settings;
- todayDate = parseInt(getCurrentDateTime().date,10);
- //Get flights
- let flights = getFlights();
- let prices = getPriceDetails();
-
- let storageKey = getPricingInventoryKey();
-
- //Check if any snapshots saved
- let defaultPricingData = {
- server:storageKey.server,
- airline:storageKey.airline,
- type:storageKey.type,
- origin:storageKey.origin,
- destination:storageKey.destination,
- key:storageKey.key,
- date:{}
- }
- chrome.storage.local.get({[storageKey.key]:defaultPricingData}, function(result) {
- pricingData = result[storageKey.key];
- //Do Analysis
- analysis = getAnalysis(flights, prices,pricingData.date);
- //Display analysis
- displayAnalysis(analysis,prices);
- //Display history
- displayHistory(analysis);
-
-
- //Automation
- //Check if valid analysis exists
-
- if(analysis.hasValue('valid')){
- //CHeck if updated todayDate
- if(pricingData.date[todayDate]){
- //Today update exists
- //Check if pricing updated today
- if(pricingData.date[todayDate].pricingUpdated){
- //Pricing updated today
- //Do nothing
- } else {
- //Pricing not updated today
- //Check if new price avaialble
- if(analysis.hasValue('newPrice')){
- //Update price
- if(settings.invPricing.autoPriceUpdate){
- $('#aes-btn-invPricing-apply-new-prices').click();
- }
- }
- }
- } else {
- //Today update does not exists
- //Check if new price avaialble
- if(analysis.hasValue('newPrice')){
- //Update price
- if(settings.invPricing.autoPriceUpdate){
- $('#aes-btn-invPricing-apply-new-prices').click();
- } else if(settings.invPricing.autoAnalysisSave){
- $('#aes-btn-invPricing-save-snapshot').click();
- }
- } else {
- //Update data
- if(settings.invPricing.autoAnalysisSave){
- $('#aes-btn-invPricing-save-snapshot').click();
- }
- }
- }
- }
- });
- });
- } else {
- //Options not correct
- displayValidationError();
- }
-
-
-});
-
-
-
-//Get Flights
-function getFlights(){
- let flightRows = $("#inventory-grouped-table tbody tr");
- if (!flightRows.length) {
- flightRows = $("#inventory-table tbody tr");
- }
- let flights = [];
- for(let i = 0; i < flightRows.length; i++ ){
- let flight;
- let row = $(flightRows[i]).find('td');
- //Get variables
- if(row.length == 12){
- //cargo fix for german
- let compCode = $(row[5]).text();
- if( compCode == 'Fracht'){
- compCode = 'Cargo';
- }
- flight = {
- fltNr:$(row[1]).find("a:first").text(),
- date:$(row[2]).text(),
- cmp:compCode,
- cap:cleanInteger($(row[6]).text()),
- bkd:cleanInteger($(row[7]).text()),
- price:cleanInteger($(row[9]).text()),
- status:$(row[10]).text().replace(/\s+/g,'')
- };
-
- }
- if(row.length == 5){
- //cargo fix for german
- let compCode = $(row[0]).text();
- if( compCode == 'Fracht'){
- compCode = 'Cargo';
- }
- flight = {
- fltNr:flight.fltNr,
- date:flight.date,
- cmp:compCode,
- cap:cleanInteger($(row[1]).text()),
- bkd:cleanInteger($(row[2]).text()),
- price:cleanInteger($(row[4]).text()),
- status:flight.status
- };
- }
- flights.push(flight);
- }
- return flights;
-}
-//Get Prices
-function getPriceDetails(){
- let pricingRows = $(".pricing table tbody tr");
- let prices = {};
- for(let i = 0; i < pricingRows.length; i++ ){
- let row = $(pricingRows[i]).find('td');
- let cmp = $(row[0]).text();
- if(cmp == 'Fracht'){
- cmp = 'Cargo';
- }
- prices[cmp] = {
- currentPrice:cleanInteger($(row[1]).text()),
- newPriceInput:$(row[2]).find("input"),
- defaultPrice:cleanInteger($(row[4]).text().replace(/\s+/g,'')),
- currentPricePoint : function() {
- return Math.round((this.currentPrice / this.defaultPrice) * 100);
- }
- };
- }
- return prices;
-}
-//Get Analysis
-function getAnalysis(flights, prices, storedData){
- //Setup object
-
- let data = {
- Y:0,
- C:0,
- F:0,
- Cargo:0
- }
- let analysis = {
- data:data,
- getLoad:function(cmp) {
- if (this.data[cmp].valid){
- return this.data[cmp].totalBkd / this.data[cmp].totalCap;
- } else {
- return 0;
- }
- },
- note:function(cmp) {
- if (this.data[cmp].valid){
- if(this.data[cmp].useCurrentPrice){
- return "Current price analysis";
- } else {
- return "No current price flights, using old price"
- }
- } else {
- return "No data for analysis";
- }
- },
- displayLoad:function(cmp){
- if(this.data[cmp].valid){
- return this.data[cmp].totalBkd + " / " + this.data[cmp].totalCap + " ("+displayPerc(Math.round(this.getLoad(cmp) * 100),'load') +")";
- } else {
- return '-';
- }
- },
- displayRec:function(cmp){
- if(this.data[cmp].recommendation){
- switch (this.data[cmp].recType) {
- case 'good':
- return ''+this.data[cmp].recommendation+' ';
- case 'bad':
- return ''+this.data[cmp].recommendation+' ';
- case 'neutral':
- return ''+this.data[cmp].recommendation+' ';
- default:
- return 'ERROR:2501 Wrong recType set:'+this.data[cmp].recType+' ';
- }
- } else {
- return '-'
- }
- },
- displayPrice:function(cmp,type){
- switch (type) {
- case 'current':
- return formatCurrency(this.data[cmp].currentPrice)+' AS$ ('+displayPerc(this.data[cmp].currentPricePoint,'price')+')';
- case 'new':
- if(this.data[cmp].newPrice){
- return formatCurrency(this.data[cmp].newPrice)+' AS$ ('+displayPerc(this.data[cmp].newPricePoint,'price')+')';
- } else {
- return '-';
- }
- case 'analysis':
- if(this.data[cmp].valid){
- return formatCurrency(this.data[cmp].analysisPrice)+' AS$ ('+displayPerc(this.data[cmp].analysisPricePoint,'price')+')';
- } else {
- return '-';
- }
- default:
- return 'ERROR:2502 Wrong type set:'+type+' ';
- }
- },
- displayIndex:function(cmp){
- if(this.data[cmp].valid){
- let span = $(' ');
- if(this.data[cmp].index >= 90){
- return span.addClass('good').text(this.data[cmp].index);
- }
- if(this.data[cmp].index <= 50 ){
- return span.addClass('bad').text(this.data[cmp].index);
- }
- return span.addClass('warning').text(this.data[cmp].index);
-
- } else {
- return '-';
- }
- },
- displayTotalLoad:function(type){
- let cmp = [];
- switch(type) {
- case 'all':
- cmp = ['Y','C','F','Cargo'];
- break;
- case 'pax':
- cmp = ['Y','C','F'];
- break;
- default:
- // code block
- }
- let load,cap,bkd;
- load = cap = bkd = 0;
- for(let i=0;i');
- if(totalIndex >= 90){
- return span.addClass('good').text(totalIndex);
- }
- if(totalIndex <= 50 ){
- return span.addClass('bad').text(totalIndex);
- }
- return span.addClass('warning').text(totalIndex);
- } else {
- return '-';
- }
- },
- hasValue:function(value){
- for(let cmp in this.data){
- if(this.data[cmp][value]){
- return 1;
- }
- }
- return 0;
- }
-
- };
-
- //Filter flights
- flights = flights.filter(function (flight) {
- return flight.status == 'finished' || flight.status == 'inflight';
- });
-
- //Check historical data
- if(storedData){
- //Shouldbe function inside storage object
- var mostRecentDate;
- let dates = [];
- for(let date in storedData) {
- dates.push(date)
- }
- dates.reverse();
- var mostRecentDate = dates[0];
- var mostRecentData = storedData[mostRecentDate];
- } else {
- var mostRecentData = 0;
- }
-
- //extract each cmp analysis
- for(let cmp in analysis.data) {
- analysis.data[cmp] = {
- totalCap:0,
- totalBkd:0,
- valid:0,
- analysisPrice:0,
- analysisPricePoint:0,
- useCurrentPrice:0,
- currentPrice:prices[cmp].currentPrice,
- currentPricePoint:prices[cmp].currentPricePoint()
- };
- let price = prices[cmp].currentPrice;
- //Only cmp flights
- let cmpFlights = flights.filter(function (flight) {
- return flight.cmp == cmp;
- });
- //if no cmp flights
- if(cmpFlights.length){
- //Check if current price flights avaialble
- let flightsArray = cmpFlights.filter(function (flight) {
- return (flight.price == price);
- });
- if(flightsArray.length){
- analysis.data[cmp].useCurrentPrice = 1;
- analysis.data[cmp].analysisPrice = price;
- analysis.data[cmp].analysisPricePoint = Math.round(price / prices[cmp].defaultPrice* 100);
- analysis.data[cmp].valid = 1;
- } else {
- //Check if historical data available
-
-
- if(mostRecentData){
- flightsArray = cmpFlights.filter(function (flight) {
- return flight.price == mostRecentData.data[cmp].analysisPrice;
- });
- if(flightsArray.length){
- analysis.data[cmp].useCurrentPrice = 0;
- analysis.data[cmp].analysisPrice = mostRecentData.data[cmp].analysisPrice;
- analysis.data[cmp].analysisPricePoint = Math.round(mostRecentData.data[cmp].analysisPrice / prices[cmp].defaultPrice * 100);
- analysis.data[cmp].valid = 1;
- }
- }
- }
- if(analysis.data[cmp].valid){
- flightsArray.forEach(function (flight) {
- analysis.data[cmp].totalCap += flight.cap;
- analysis.data[cmp].totalBkd += flight.bkd;
- });
- }
- }
- }
-
- //END extract each cmp analysis
- analysis = generateRecommendation(analysis,prices);
-
-
- //Make route index
- analysis = generateRouteIndex(analysis);
- return analysis;
-}
-function generateRecommendation(analysis,prices){
- for(let cmp in analysis.data) {
- analysis.data[cmp].recommendation = 0;
- if(analysis.data[cmp].valid){
- if(analysis.data[cmp].useCurrentPrice){
- //Find recommendation
- let load = Math.round(analysis.getLoad(cmp) * 100);
- //Find step
- let step;
- for(let i in settings.invPricing.recommendation[cmp].steps){
- step = settings.invPricing.recommendation[cmp].steps[i];
- if(load >= step.min && load <= step.max){
- break;
- }
- }
- //Find new price point
- let newPricePoint = prices[cmp].currentPricePoint() + step.step;
- //See if new price in bounds for Drop
- if(step.step < 0){
- analysis.data[cmp].recType = 'bad';
- if(newPricePoint < settings.invPricing.recommendation[cmp].minPrice){
- newPricePoint = settings.invPricing.recommendation[cmp].minPrice;
- }
- }
- //See if new price in bounds for Raise
- if(step.step > 0){
- analysis.data[cmp].recType = 'good';
- if(newPricePoint > settings.invPricing.recommendation[cmp].maxPrice){
- newPricePoint = settings.invPricing.recommendation[cmp].maxPrice;
- }
- }
- //see if already at highest/lowest price point
- if(step.step != 0){
- if(newPricePoint == prices[cmp].currentPricePoint()){
- if(newPricePoint == settings.invPricing.recommendation[cmp].minPrice){
- //Already at lowest point
- analysis.data[cmp].recommendation = 'Already at lowest price!';
- }
- if(newPricePoint == settings.invPricing.recommendation[cmp].maxPrice){
- //Already at highest point
- analysis.data[cmp].recommendation = 'Already at highest price!';
- }
- }
- } else {
- analysis.data[cmp].recType = 'neutral';
- }
- //check if not set by exceptions
- if(!analysis.data[cmp].recommendation){
- analysis.data[cmp].recommendation = step.name;
- analysis.data[cmp].newPriceChange = step.step;
- if(step.step){
- analysis.data[cmp].newPricePoint = newPricePoint;
- analysis.data[cmp].newPrice = Math.round(newPricePoint/100 * prices[cmp].defaultPrice);
-
- }
- }
- }
- }
- }
- return analysis;
-}
-function generateRouteIndex(analysis){
- //Each CMP index
- for(let cmp in analysis.data){
- if(analysis.data[cmp].valid){
- let index = (analysis.data[cmp].analysisPricePoint + (analysis.getLoad(cmp) * 100 * 3))/4;
- analysis.data[cmp].index = Math.round(index);
- }
- }
- return analysis;
-}
-//Display analysis
-function displayAnalysis(analysis,prices){
-
- //Build table
- let mainDiv = $(".container-fluid .row .col-md-10 div .as-panel:eq(0)");
- mainDiv.after(
- `
- Analysis (today's snapshot)
-
- `
- );
-
-
-
- //Table head
- let th = [];
- th.push('SC ');
- th.push('Note ');
- th.push('Analysis Price ');
- th.push('Load ');
- th.push('Index ');
- th.push('Current Price ');
- th.push('Recommendation ');
- th.push('New Price ');
- let headRow = $(' ').append(th);
- let thead = $(' ').append(headRow);
-
- //Table body
- let tbody = $(' ');
- for(let cmp in analysis.data) {
- let td = [];
- td.push(''+cmp+' ');
- td.push(''+analysis.note(cmp)+' ');
- td.push(''+analysis.displayPrice(cmp,'analysis')+' ');
- td.push(''+analysis.displayLoad(cmp)+' ');
- td.push($(' ').html(analysis.displayIndex(cmp)));
- td.push(''+analysis.displayPrice(cmp,'current')+' ');
- td.push(''+analysis.displayRec(cmp)+' ');
- td.push(''+analysis.displayPrice(cmp,'new')+' ');
- let row = $(' ').append(td);
- tbody.append(row);
- }
-
- //Table footer
- let footRow = []
- footRow.push(' ');
- //Total PAX
- let tf = [];
- tf.push('Total PAX ');
- tf.push(' ');
- tf.push($(' ').html(analysis.displayTotalLoad('pax')));
- tf.push($(' ').html(analysis.displayTotalIndex('pax')));
- tf.push(' ');
- footRow.push($(' ').append(tf));
- //Total
- tf = [];
- tf.push('Total PAX+Cargo ');
- tf.push(' ');
- tf.push($(' ').html(analysis.displayTotalLoad('all')));
- tf.push($(' ').html(analysis.displayTotalIndex('all')));
- tf.push(' ');
- footRow.push($(' ').append(tf));
- let tfoot = $(' ').append(footRow);
-
-
- $("#aes-table-analysis").append(thead,tbody,tfoot);
-
- //Display pricing and data save buttons
- if(analysis.hasValue('valid')){
- let invPricingAnalysisBar = $('');
- let invPricingAnalysisBarSpan = $(' ');
- invPricingAnalysisBar.append($(' ').html(invPricingAnalysisBarSpan));
- $("#aes-div-analysis").prepend(invPricingAnalysisBar);
- //create buttons
- //Save Data
- let saveInvPricingBtn = $(' ');
- $(saveInvPricingBtn).click(function(){
- $(this).closest("li").remove();
- invPricingAnalysisBarSpan.text('Saving analysis data...');
- //Get updated time
- let updateTime = getCurrentDateTime().time;
- pricingData.date[todayDate] = analysis;
- pricingData.date[todayDate].updateTime = updateTime;
- pricingData.date[todayDate].date = todayDate;
- pricingData.date[todayDate].pricingUpdated = 0;
- chrome.storage.local.set({[pricingData.key]: pricingData}, function() {
- invPricingAnalysisBarSpan.removeClass().addClass("good").text("Data Saved!");
- //Automation
- if(settings.invPricing.autoClose){
- close();
- }
- });
- });
- //Update prices
-
-
-
- let applyNewPriceInvPricingBtn = $('apply new prices (and save data) ');
- $(applyNewPriceInvPricingBtn).click(function(){
- $(this).closest("ul").find("li button").closest("li").remove();
- invPricingAnalysisBarSpan.text('Updating prices...');
- //Get updated time
- let updateTime = getCurrentDateTime().time;
- pricingData.date[todayDate] = analysis;
- pricingData.date[todayDate].updateTime = updateTime;
- pricingData.date[todayDate].date = todayDate;
- pricingData.date[todayDate].pricingUpdated = 1;
- chrome.storage.local.set({[pricingData.key]: pricingData}, function() {
- $('[name="submit-prices"]').click();
- });
-
- });
- //Update new pricing input
- if(analysis.hasValue('newPrice')){
- //Modify new price input
- for(let cmp in analysis.data){
- if(analysis.data[cmp].newPrice){
- prices[cmp].newPriceInput.val(analysis.data[cmp].newPrice);
- }
- }
- }
- //For snapshot button
- if(pricingData.date[todayDate]){
- //Today data does exist
- if(pricingData.date[todayDate].pricingUpdated){
- //Today pricing updated
- invPricingAnalysisBarSpan.text("Today prices have been updated at: "+pricingData.date[todayDate].updateTime);
-
- //Automation
- if(settings.invPricing.autoClose){
- close();
- }
- } else {
- //Today pricing not updated
- invPricingAnalysisBarSpan.text("Today's snapshot data saved at: "+pricingData.date[todayDate].updateTime);
- $(invPricingAnalysisBar).append($(' ').html(saveInvPricingBtn.text("save snapshot data again")));
- if(analysis.hasValue('newPrice')){
- $(invPricingAnalysisBar).append($(' ').html(applyNewPriceInvPricingBtn));
- }
- }
- } else {
- //Today data does not exist
- $(invPricingAnalysisBar).append($(' ').html(saveInvPricingBtn.text("save snapshot data")));
- if(analysis.hasValue('newPrice')){
- $(invPricingAnalysisBar).append($(' ').html(applyNewPriceInvPricingBtn));
- }
- }
- }
-}
-
-//Display History
-function displayHistory(analysis){
- //Prepare data
- let dates = [];
- //Get valid dates can add function here
- for(let date in pricingData.date) {
- dates.push(date)
- }
- dates.sort();
- //If historical data exist then build
- if(dates.length){
- //Build Div
- let mainDiv = $("#aes-div-analysis");
- mainDiv.after('Historical Data
');
-
- //History Options
- let fieldset = $(' ').html('History Options ');
- //Hide Now
- let option1 = $('
').html(' Show "Now" collumn ');
- //Show only Priced
- let option2 = $('
').html(' Show only dates when pricing changed ');
-
- //Number of records
- let option3 = $(' ').html('5 past dates 10 past dates All past dates ')
- let wrapper = $('
').append('Number of past dates ',option3);
-
- fieldset.append(option1,option2,wrapper);
- $("#aes-div-invPricing-historicalData").append(fieldset);
- //Default values
- if(settings.invPricing.historyTable.showNow){
- $("#aes-check-inventory-history-showNow").prop("checked",true);
- }
- if(settings.invPricing.historyTable.showOnlyPricing){
- $("#aes-check-inventory-history-showOnlyPricing").prop("checked",true);
- }
- $("#aes-select-inventory-history-numberPastDates").val(settings.invPricing.historyTable.numberOfDates);
-
- //Change events
- $("#aes-check-inventory-history-showNow").change(function () {
- if(this.checked) {
- settings.invPricing.historyTable.showNow = 1;
- } else {
- settings.invPricing.historyTable.showNow = 0;
- }
- chrome.storage.local.set({settings: settings}, function() {});
- buildHistoryTable();
- });
- $("#aes-check-inventory-history-showOnlyPricing").change(function () {
- buildHistoryTable();
- if(this.checked) {
- settings.invPricing.historyTable.showOnlyPricing = 1;
- } else {
- settings.invPricing.historyTable.showOnlyPricing = 0;
- }
- chrome.storage.local.set({settings: settings}, function() {});
- });
- $("#aes-select-inventory-history-numberPastDates").change(function () {
- settings.invPricing.historyTable.numberOfDates = $('#aes-select-inventory-history-numberPastDates').val();
- chrome.storage.local.set({settings: settings}, function() {});
- buildHistoryTable();
- });
-
- buildHistoryTable();
- }
-}
-function buildHistoryTable(){
- //Clean previous table
- $('#aes-table-inventory-history').remove();
-
- let showNow = 0;
- let showOnlyPricing = 0;
- if($('#aes-check-inventory-history-showNow:checked').length > 0){
- showNow = 1;
- }
- if($('#aes-check-inventory-history-showOnlyPricing:checked').length > 0){
- showOnlyPricing = 1;
- }
-
- let numberOfDates = $('#aes-select-inventory-history-numberPastDates').val();
- switch(numberOfDates) {
- case '5':
- numberOfDates = 5;
- break;
- case '10':
- numberOfDates = 10;
- break;
- case 'all':
- numberOfDates = 0;
- break;
- default:
- numberOfDates = 10;
- }
-
-
-
-
- let dates = [];
- //Get valid dates can add function here
- for(let date in pricingData.date) {
- if(showOnlyPricing){
- if(pricingData.date[date].pricingUpdated){
- dates.push(date);
- }
- } else {
- dates.push(date);
- }
- }
- dates.reverse();
- if(numberOfDates){
- dates = dates.slice(0, numberOfDates);
- }
- dates.sort();
- if(dates.length){
-
- //Headrows
- let th = [' '];
- let th1 = ['SC '];
- for(let i=0;i').text(formatDate(date)));
- th1.push('Price ');
- th1.push('Δ % ');
- th1.push('Load ');
- th1.push('Δ % ');
- //Index
- th1.push('Index ');
- } else {
- th.push($(' ').text(formatDate(date)));
- th1.push('Price ');
- th1.push('Load ');
- //Index
- th1.push('Index ');
- }
- }
- if(showNow){
- //Now
- th.push($(' ').text('Now'));
- th1.push('Price ');
- th1.push('Δ % ');
- th1.push('Load ');
- th1.push('Δ % ');
- //index
- th1.push('Index ');
- }
-
-
- let headRow = $(' ').append(th);
- let headRow2 = $(' ').append(th1);
-
- let thead = $(' ').append(headRow,headRow2);
-
-
-
- //Build table
- let compartments = ['Y','C','F','Cargo'];
-
- //Tbody rows
- let tbody = $(' ');
- compartments.forEach(function(cmp){
- let td = [];
- td.push($(' ').text(cmp));
- //Historical tds
- for(let i=0;i').html(displayHistoryPrice(data)));
- td.push($(' ').html(displayDifference(data,prevData).price));
- td.push($(' ').html(displayHistoryLoad(data)));
- td.push($(' ').html(displayDifference(data,prevData).load));
- //index
- td.push($(' ').html(historyDisplayIndex(data,0)));
- } else {
- //First data point
- td.push($(' ').html(displayHistoryPrice(data)));
- td.push($(' ').html(displayHistoryLoad(data)));
- //index
- td.push($(' ').html(historyDisplayIndex(data,0)));
- }
- }
- if(showNow){
- //Now TDs
- let data = analysis.data[cmp];
- let prevData = pricingData.date[dates[dates.length-1]].data[cmp];
- td.push($(' ').html(displayHistoryPrice(data)));
- td.push($(' ').html(displayDifference(data,prevData).price));
- td.push($(' ').html(displayHistoryLoad(data)));
- td.push($(' ').html(displayDifference(data,prevData).load));
- //Index
- td.push($(' ').html(historyDisplayIndex(data,0)));
- }
-
-
- //Finish row
- let row = $(' ').append(td);
- tbody.append(row);
- });
-
-
- //Table footer Total Rows
- let totalCollumns = th1.length;
- let footRow = [];
- let footerRows = ['pax','all']
- footRow.push(' ');
- //Total PAX
- footerRows.forEach(function(type){
- let tf = [];
- tf.push($(' ').text(historyDisplayTotalText(type)));
- for(let i=0;i');
- tf.push($(' ').html(historyDisplayTotal(data,type)));
- tf.push(' ');
- //index
- tf.push($(' ').html(historyDisplayIndex(data,type)));
- } else {
- tf.push(' ');
- tf.push($(' ').html(historyDisplayTotal(data,type)));
- //index
- tf.push($(' ').html(historyDisplayIndex(data,type)));
- }
- }
- if(showNow){
- //Now
- let data = analysis.data;
- tf.push(' ');
- tf.push($(' ').html(historyDisplayTotal(data,type)));
- tf.push(' ');
- //index
- tf.push($(' ').html(historyDisplayIndex(data,type)));
- }
-
-
- footRow.push($(' ').append(tf));
-
-
- });
-
- let tfoot = $(' ').append(footRow);
-
-
- let table = $('').append(thead,tbody,tfoot);
-
- let tableDiv = $('
').append(table);
-
- $("#aes-div-invPricing-historicalData").append(tableDiv);
-
- }
-
-}
-//Validate
-function validateAllOptions(){
- //Get all options
- //Check if all flight numbers selected
- let valid = $('.col-md-10 > div > .as-panel:eq(1) > ul:eq(0) li:eq(0)').hasClass("active");
- if(!valid){
- aesmodule.valid = 0;
- aesmodule.error.push('Please select All Flight Numbers under Current Inventory');
- return;
- }
- //Check if Apply settings to correctly set
- $('.col-md-10 > div > .as-panel:eq(1) > div > div > div:eq(0) fieldset:eq(2) > div input').each(function(index){
- switch(index) {
- case 0:
- if(!this.checked){
- aesmodule.valid = 0;
- aesmodule.error.push('Please check Airport Pair under Apply settings to in Settings panel');
- }
- break;
- case 1:
- if(!this.checked){
- aesmodule.valid = 0;
- aesmodule.error.push('Please check Flight Numbers under Apply settings to in Settings panel');
- }
- break;
- case 2:
- if(this.checked){
- aesmodule.valid = 0;
- aesmodule.error.push('Please uncheck Return Airport Pair under Apply settings to in Settings panel');
- }
- break;
- case 3:
- if(this.checked){
- aesmodule.valid = 0;
- aesmodule.error.push('Please uncheck Return Flight Numbers under Apply settings to in Settings panel');
- }
- break;
- }
- });
- //Check if Data settings correctly set
- let dataDiv = $('.col-md-10 > div > .as-panel:eq(1) > div > div > div:eq(1) .layout-col-md-3');
- //Service classes
- $('fieldset:eq(0) label',dataDiv).each(function(){
- if(!$('input',this)[0].checked){
- aesmodule.valid = 0;
- aesmodule.error.push('Please check '+$(this).text()+' under Service Classes in Data panel');
- }
- });
- //Flight Status
- $('fieldset:eq(1) label',dataDiv).each(function(index){
- if(index == 1 || index == 2){
- if(!$('input',this)[0].checked){
- aesmodule.valid = 0;
- aesmodule.error.push('Please check '+$(this).text()+' under Flight Status in Data panel');
- }
- }
- });
- //Load
- $('fieldset:eq(2) div',dataDiv).each(function(index){
- if(!index){
- //Minimum
- if(parseInt($('select option:selected',this).text(),10) != 0){
- aesmodule.valid = 0;
- aesmodule.error.push('Please select 0 for '+$('label',this).text()+' under Load in Data panel');
- }
- } else {
- //Max
- if(parseInt($('select option:selected',this).text(),10) != 100){
- aesmodule.valid = 0;
- aesmodule.error.push('Please select 100 for '+$('label',this).text()+' under Load in Data panel');
- }
- }
- });
- //Settings Group by flight
- if($('fieldset:eq(3) input',dataDiv)[0].checked){
- aesmodule.valid = 0;
- aesmodule.error.push('Please uncheck '+$('fieldset:eq(3) label',dataDiv).text()+' under Settings in Data panel');
- }
-
-}
-function displayValidationError(){
- let p = [];
- p.push($('
').text('AES Inventory Pricing Module could not be loaded because of errors:'));
- aesmodule.error.forEach(function(error){
- p.push($('
').html(''+error+' '));
- });
- p.push($('
').html('Refresh the page after making adjustments.'));
- let panel = $('
').append(p);
- let h2 = $(' ').text('AES Inventory Pricing Module');
- let div = $('
').append(h2,panel);
- $('h1:eq(0)').after(h2,panel)
-}
-
-//History Table functions
-function historyDisplayIndex(data,type){
- let cmp = [];
- let index=0;
- switch(type) {
- case 'all':
- cmp = ['Y','C','F','Cargo'];
- break;
- case 'pax':
- cmp = ['Y','C','F'];
- break;
- case 0:
- cmp = 0;
- break;
- }
- if(cmp){
- //Multi index
- let count = 0;
- cmp.forEach(function(comp){
- if(data[comp].valid){
- index += data[comp].index;
- count++;
- }
- });
- index = Math.round(index/count);
- } else {
- //one cmp index
- if(data.valid){
- index = data.index;
- }
- }
- if(index){
- let span = $(' ');
- if(index >= 90){
- return span.addClass('good').text(index);
- }
- if(index <= 50 ){
- return span.addClass('bad').text(index);
- }
- return span.addClass('warning').text(index);
- } else {
- return '-';
- }
-}
-function historyDisplayTotalText(type){
- switch(type) {
- case 'all':
- return "Total PAX+Cargo";
- case 'pax':
- return "Total PAX";
- }
-}
-function historyDisplayTotal(data,type){
- let cmp = [];
- switch(type) {
- case 'all':
- cmp = ['Y','C','F','Cargo'];
- break;
- case 'pax':
- cmp = ['Y','C','F'];
- break;
- default:
- // code block
- }
- let load,cap,bkd;
- load = cap = bkd = 0;
- cmp.forEach(function(comp){
- if(data[comp].valid){
- cap += data[comp].totalCap;
- bkd += data[comp].totalBkd;
- }
- });
- if(cap){
- load = Math.round(bkd/cap*100);
- return bkd+' / '+cap+' ('+displayPerc(load,'load')+')';
- } else {
- return '-';
- }
-}
-function displayHistoryLoad(data){
- if(data.valid){
- let booked = data.totalBkd;
- let capacity = data.totalCap;
- let load = Math.round(booked/capacity * 100);
- return booked+' / '+capacity+' ('+displayPerc(load,'load')+')';
- } else {
- return '-';
- }
-}
-function displayHistoryPrice(data){
- if(data.valid){
- let price =data.analysisPrice;
- let pricePoint = data.analysisPricePoint;
- return formatCurrency(price)+' AS$ ('+displayPerc(pricePoint,'price')+')';
- } else {
- return '-';
- }
-}
-function displayDifference(current,old){
- if(current.valid && old.valid){
- let currentLoad = Math.round(current.totalBkd/current.totalCap * 100);
- let oldLoad = Math.round(old.totalBkd/old.totalCap * 100);
- let load = currentLoad-oldLoad;
- let price = current.analysisPricePoint - old.analysisPricePoint;
- return {load:load,price:price};
- } else {
- return {load:'-',price:'-'};
- }
-}
-
-function displayPerc(perc,type){
- let span = $(' ');
- switch (type) {
- case 'price':
- if(perc >= 100){
- span.addClass('good').text(perc+"%");
- return span.prop('outerHTML');
- }
- if(perc < 75){
- span.addClass('bad').text(perc+"%");
- return span.prop('outerHTML');
- }
- span.addClass('warning').text(perc+"%");
- return span.prop('outerHTML');
- case 'load':
- if(perc >= 70){
- span.addClass('good').text(perc+"%");
- return span.prop('outerHTML');
- }
- if(perc < 40){
- span.addClass('bad').text(perc+"%");
- return span.prop('outerHTML');
- }
- span.addClass('warning').text(perc+"%");
- return span.prop('outerHTML');
- default:
- return 'ERROR:2502 Wrong type set:'+type+' ';
- }
-}
-//Helper functions
-function formatDate(date){
- return date.substring(0, 4)+'-'+date.substring(4, 6)+'-'+date.substring(6, 8);
-}
-function formatCurrency(value) {
- return Intl.NumberFormat().format(value)
-}
-function cleanInteger(a){
- a = a.replace(',','');
- a = a.replace('.','');
- a = a.replace(' AS$','');
- return parseInt(a, 10);
-}
-function getPricingInventoryKey(){
- //Get Origin and Destination
- let x = $("h2:first a");
- let org = $(x[0]).text();
- let dest = $(x[1]).text();
- //get server
- let server = getServerName();
- //get airline code
- let airline = getAirlineCode();
- //create key
- let key = server + airline + org + dest+'routeAnalysis';
- return {key:key,server:server,airline:airline,type:"routeAnalysis",origin:org,destination:dest}
-}
-function getServerName(){
- let server = window.location.hostname
- server = server.split('.');
- return server[0];
-}
-function getAirlineCode(){
- let airline = $("#inventory-grouped-table tbody a:first").text().split(" ");
- if(!airline[0]){
- airline = $("#inventory-table tbody a:first").text().split(" ");
- }
- return airline[0];
-}
-function getCurrentDateTime(){
- let a = $(".as-footer-line-element:has('.fa-clock-o')").text().trim();
- let b = a.split(" ");
- //For date
- let dateTemp = b[0].split("-");
- let date;
- if(dateTemp.length == 1){
- //German
- dateTemp = dateTemp[0].split(".");
- date = dateTemp.map(function(value){
- return value.replace(/[^A-Za-z0-9]/g, '');
- });
- date = date[2] + date[1] + date[0];
- } else {
- //English
- date = dateTemp.map(function(value){
- return value.replace(/[^A-Za-z0-9]/g, '');
- });
- date = date[0] + date[1] + date[2];
- }
- //For time
- let time = b[b.length-2] +' '+b[b.length-1];
- return {date:date,time:time};
-}
+"use strict";
+//MAIN
+//Global vars
+var settings, pricingData, todayDate, analysis;
+var aesmodule = { valid: true, error: [] };
+
+window.addEventListener("load", async (event) => {
+ settings = await getSettings()
+ aesmodule = new Validation()
+
+ if (!aesmodule.valid) {
+ displayValidationError()
+ return
+ }
+ displayInventory()
+})
+
+/**
+ * Get settings from local storage
+ * @returns {object} data.settings
+ */
+async function getSettings() {
+ const data = await chrome.storage.local.get(['settings'])
+ return data.settings
+}
+
+async function displayInventory() {
+ todayDate = parseInt(AES.getServerDate().date, 10);
+ //Get flights
+ let flights = getFlights();
+ let prices = getPriceDetails();
+ let storageKey = getPricingInventoryKey();
+
+ //Check if any snapshots saved
+ let defaultPricingData = {
+ server: storageKey.server,
+ airline: storageKey.airline,
+ type: storageKey.type,
+ origin: storageKey.origin,
+ destination: storageKey.destination,
+ key: storageKey.key,
+ date: {}
+ }
+ const storageData = await chrome.storage.local.get({[storageKey.key]: defaultPricingData})
+ pricingData = storageData[storageKey.key]
+
+ //Do Analysis
+ analysis = getAnalysis(flights, prices, pricingData.date);
+ //Display analysis
+ displayAnalysis(analysis, prices);
+ //Display history
+ displayHistory(analysis);
+
+
+ //Automation
+ //Check if valid analysis exists
+ if (analysis.hasValue('valid')) {
+ //CHeck if updated todayDate
+ if (pricingData.date[todayDate]) {
+ //Today update exists
+ //Check if pricing updated today
+ if (pricingData.date[todayDate].pricingUpdated) {
+ //Pricing updated today
+ //Do nothing
+ } else {
+ //Pricing not updated today
+ //Check if new price avaialble
+ if (analysis.hasValue('newPrice')) {
+ //Update price
+ if (settings.invPricing.autoPriceUpdate) {
+ $('#aes-btn-invPricing-apply-new-prices').click();
+ }
+ }
+ }
+ } else {
+ //Today update does not exists
+ //Check if new price avaialble
+ if (analysis.hasValue('newPrice')) {
+ //Update price
+ if (settings.invPricing.autoPriceUpdate) {
+ $('#aes-btn-invPricing-apply-new-prices').click();
+ } else if (settings.invPricing.autoAnalysisSave) {
+ $('#aes-btn-invPricing-save-snapshot').click();
+ }
+ } else {
+ //Update data
+ if (settings.invPricing.autoAnalysisSave) {
+ $('#aes-btn-invPricing-save-snapshot').click();
+ }
+ }
+ }
+ }
+}
+
+/**
+ * Get Flights
+ * @returns {array} flights - array of flight objects
+ */
+function getFlights() {
+ const flights = []
+ // TODO: also support grouped mode (#inventory-grouped-table)
+ const flightRows = document.querySelectorAll("#inventory-table tbody tr")
+
+ if (!flightRows) {
+ throw new Error("\"Group by flight\" needs to be unchecked")
+ }
+
+ for (const row of flightRows) {
+ const flight = getFlight(row)
+ flights.push(flight)
+ }
+
+ return flights
+}
+
+/**
+ * Get flight information and return as an object
+ * @param {HTMLElement} row - the with flight information
+ * @returns {object} flight - object with the parsed flight information
+ */
+function getFlight(row) {
+ const cells = row.querySelectorAll("td")
+ const flightNumber = cells[1].querySelector("a[href*=numbers").innerText
+ const date = cells[2].innerText
+ const compCode = getCompCode(cells[5].innerText)
+ const capacity = cells[6].innerText
+ const booked = cells[7].innerText
+ const price = cells[9].innerText
+ const status = cells[10].innerText.replace(/\s+/g, "")
+
+ const flight = {
+ fltNr: flightNumber,
+ date: date,
+ cmp: compCode,
+ cap: AES.cleanInteger(capacity),
+ bkd: AES.cleanInteger(booked),
+ price: AES.cleanInteger(price),
+ status: status
+ }
+
+ return flight
+}
+
+/**
+ * Checks if the string is longer than one character and returns a string of "Cargo"
+ * @param {string} text - localised word for "Cargo"
+ * @returns {string} text - either passthrough of the input or "Cargo"
+ */
+function getCompCode(text) {
+ if (!text) {
+ throw new Error("no value provided for getCompCode")
+ }
+
+ if (text.length > 1) {
+ return "Cargo"
+ }
+
+ return text
+}
+
+/**
+ * Get Prices
+ * @returns {object} prices
+ */
+function getPriceDetails() {
+ const pricingRows = document.querySelectorAll(".pricing table tbody tr")
+ const prices = {}
+
+ for (const row of pricingRows) {
+ const cells = row.querySelectorAll("td")
+ const cmp = getCompCode(cells[0].innerText)
+ const price = getPrice(cells)
+
+ prices[cmp] = price
+ }
+
+ return prices
+}
+
+/**
+ * Get price
+ * @param {array} cells
+ * @returns {object} price
+ */
+function getPrice(cells) {
+ const currentPrice = AES.cleanInteger(cells[1].innerText)
+ const defaultPrice = AES.cleanInteger(cells[4].innerText.replace(/\s+/g, ''))
+ const currentPricePoint = getCurrentPricePoint(currentPrice, defaultPrice)
+ const newPriceInput = cells[2].querySelector("input")
+
+ const price = {
+ currentPrice: currentPrice,
+ defaultPrice: defaultPrice,
+ currentPricePoint: currentPricePoint,
+ newPriceInput: newPriceInput
+ }
+
+ return price
+}
+
+/**
+ * @param {string} currentPrice
+ * @param {string} defaultPrice
+ * @returns {integer}
+ */
+function getCurrentPricePoint(currentPrice, defaultPrice) {
+ return Math.round((currentPrice / defaultPrice) * 100)
+}
+
+//Get Analysis
+function getAnalysis(flights, prices, storedData) {
+ //Setup object
+ let mostRecentDate
+ let mostRecentData
+ let data = {
+ Y: 0,
+ C: 0,
+ F: 0,
+ Cargo: 0
+ }
+ let analysis = {
+ data: data,
+ getLoad: function(cmp) {
+ if (this.data[cmp].valid) {
+ return this.data[cmp].totalBkd / this.data[cmp].totalCap;
+ } else {
+ return 0;
+ }
+ },
+ note: function(cmp) {
+ if (this.data[cmp].valid) {
+ if (this.data[cmp].useCurrentPrice) {
+ return "Current price analysis";
+ } else {
+ return "No current price flights, using old price"
+ }
+ } else {
+ return "No data for analysis";
+ }
+ },
+ displayLoad: function(cmp) {
+ if (this.data[cmp].valid) {
+ return this.data[cmp].totalBkd + " / " + this.data[cmp].totalCap + " (" + displayPerc(Math.round(this.getLoad(cmp) * 100), 'load') + ")";
+ } else {
+ return '-';
+ }
+ },
+ displayRec: function(cmp) {
+ if (this.data[cmp].recommendation) {
+ switch (this.data[cmp].recType) {
+ case 'good':
+ return '' + this.data[cmp].recommendation + ' ';
+ case 'bad':
+ return '' + this.data[cmp].recommendation + ' ';
+ case 'neutral':
+ return '' + this.data[cmp].recommendation + ' ';
+ default:
+ return 'ERROR:2501 Wrong recType set:' + this.data[cmp].recType + ' ';
+ }
+ } else {
+ return '-'
+ }
+ },
+ displayPrice: function(cmp, type) {
+ switch (type) {
+ case 'current':
+ return formatCurrency(this.data[cmp].currentPrice) + ' AS$ (' + displayPerc(this.data[cmp].currentPricePoint, 'price') + ')';
+ case 'new':
+ if (this.data[cmp].newPrice) {
+ return formatCurrency(this.data[cmp].newPrice) + ' AS$ (' + displayPerc(this.data[cmp].newPricePoint, 'price') + ')';
+ } else {
+ return '-';
+ }
+ case 'analysis':
+ if (this.data[cmp].valid) {
+ return formatCurrency(this.data[cmp].analysisPrice) + ' AS$ (' + displayPerc(this.data[cmp].analysisPricePoint, 'price') + ')';
+ } else {
+ return '-';
+ }
+ default:
+ return 'ERROR:2502 Wrong type set:' + type + ' ';
+ }
+ },
+ displayIndex: function(cmp) {
+ if (this.data[cmp].valid) {
+ let span = $(' ');
+ if (this.data[cmp].index >= 90) {
+ return span.addClass('good').text(this.data[cmp].index);
+ }
+ if (this.data[cmp].index <= 50) {
+ return span.addClass('bad').text(this.data[cmp].index);
+ }
+ return span.addClass('warning').text(this.data[cmp].index);
+
+ } else {
+ return '-';
+ }
+ },
+ displayTotalLoad: function(type) {
+ let cmp = [];
+ switch (type) {
+ case 'all':
+ cmp = ['Y', 'C', 'F', 'Cargo'];
+ break;
+ case 'pax':
+ cmp = ['Y', 'C', 'F'];
+ break;
+ default:
+ // code block
+ }
+ let load, cap, bkd;
+ load = cap = bkd = 0;
+ for (let i = 0; i < cmp.length; i++) {
+ if (this.data[cmp[i]].valid) {
+ cap += this.data[cmp[i]].totalCap;
+ bkd += this.data[cmp[i]].totalBkd;
+ }
+ }
+
+ if (cap) {
+ load = Math.round(bkd / cap * 100);
+ return bkd + ' / ' + cap + ' (' + displayPerc(load, 'load') + ')';
+ } else {
+ return '-';
+ }
+ },
+ displayTotalIndex: function(type) {
+ let cmp = [];
+ switch (type) {
+ case 'all':
+ cmp = ['Y', 'C', 'F', 'Cargo'];
+ break;
+ case 'pax':
+ cmp = ['Y', 'C', 'F'];
+ break;
+ default:
+ // code block
+ }
+ let count, totalIndex;
+ count = totalIndex = 0;
+ for (let i = 0; i < cmp.length; i++) {
+ if (this.data[cmp[i]].valid) {
+ count++;
+ totalIndex += this.data[cmp[i]].index;
+ }
+ }
+ if (count) {
+ totalIndex = Math.round(totalIndex / count);
+ let span = $(' ');
+ if (totalIndex >= 90) {
+ return span.addClass('good').text(totalIndex);
+ }
+ if (totalIndex <= 50) {
+ return span.addClass('bad').text(totalIndex);
+ }
+ return span.addClass('warning').text(totalIndex);
+ } else {
+ return '-';
+ }
+ },
+ hasValue: function(value) {
+ for (let cmp in this.data) {
+ if (this.data[cmp][value]) {
+ return 1;
+ }
+ }
+ return 0;
+ }
+ };
+
+ //Filter flights
+ flights = flights.filter(function(flight) {
+ return flight.status == 'finished' || flight.status == 'inflight';
+ });
+
+ //Check historical data
+ if (storedData) {
+ //Shouldbe function inside storage object
+ let dates = []
+ for (let date in storedData) {
+ if (Number.isInteger(parseInt(date))) {
+ dates.push(date)
+ }
+ }
+ dates.reverse();
+ mostRecentDate = dates[0]
+ mostRecentData = storedData[mostRecentDate]
+ }
+
+ //extract each cmp analysis
+ for (let cmp in analysis.data) {
+ analysis.data[cmp] = {
+ totalCap: 0,
+ totalBkd: 0,
+ valid: 0,
+ analysisPrice: 0,
+ analysisPricePoint: 0,
+ useCurrentPrice: 0,
+ currentPrice: prices[cmp].currentPrice,
+ currentPricePoint: prices[cmp].currentPricePoint
+ };
+ let price = prices[cmp].currentPrice;
+ //Only cmp flights
+ let cmpFlights = flights.filter(function(flight) {
+ return flight.cmp == cmp;
+ });
+ //if no cmp flights
+ if (cmpFlights.length) {
+ //Check if current price flights avaialble
+ let flightsArray = cmpFlights.filter(function(flight) {
+ return (flight.price == price);
+ });
+ if (flightsArray.length) {
+ analysis.data[cmp].useCurrentPrice = 1;
+ analysis.data[cmp].analysisPrice = price;
+ analysis.data[cmp].analysisPricePoint = Math.round(price / prices[cmp].defaultPrice * 100);
+ analysis.data[cmp].valid = true;
+ } else if (mostRecentData) {
+ // flightsArray = cmpFlights.filter(function(flight) {
+ // return flight.price == mostRecentData.data[cmp].analysisPrice;
+ // });
+ flightsArray = cmpFlights
+ if (flightsArray.length) {
+ analysis.data[cmp].useCurrentPrice = 0;
+ analysis.data[cmp].analysisPrice = mostRecentData.data[cmp].analysisPrice;
+ analysis.data[cmp].analysisPricePoint = Math.round(mostRecentData.data[cmp].analysisPrice / prices[cmp].defaultPrice * 100);
+ analysis.data[cmp].valid = true;
+ }
+ }
+ if (analysis.data[cmp].valid) {
+ flightsArray.forEach(function(flight) {
+ analysis.data[cmp].totalCap += flight.cap;
+ analysis.data[cmp].totalBkd += flight.bkd;
+ });
+ }
+ }
+ }
+
+ //END extract each cmp analysis
+ analysis = generateRecommendation(analysis, prices);
+
+ //Make route index
+ analysis = generateRouteIndex(analysis);
+ return analysis;
+}
+
+function generateRecommendation(analysis, prices) {
+ for (let cmp in analysis.data) {
+ analysis.data[cmp].recommendation = 0;
+ if (analysis.data[cmp].valid) {
+ if (analysis.data[cmp].useCurrentPrice) {
+ //Find recommendation
+ let load = Math.round(analysis.getLoad(cmp) * 100);
+ //Find step
+ let step;
+ for (let i in settings.invPricing.recommendation[cmp].steps) {
+ step = settings.invPricing.recommendation[cmp].steps[i];
+ if (load >= step.min && load <= step.max) {
+ break;
+ }
+ }
+ //Find new price point
+ let newPricePoint = prices[cmp].currentPricePoint + step.step;
+ //See if new price in bounds for Drop
+ if (step.step < 0) {
+ analysis.data[cmp].recType = 'bad';
+ if (newPricePoint < settings.invPricing.recommendation[cmp].minPrice) {
+ newPricePoint = settings.invPricing.recommendation[cmp].minPrice;
+ }
+ }
+ //See if new price in bounds for Raise
+ if (step.step > 0) {
+ analysis.data[cmp].recType = 'good';
+ if (newPricePoint > settings.invPricing.recommendation[cmp].maxPrice) {
+ newPricePoint = settings.invPricing.recommendation[cmp].maxPrice;
+ }
+ }
+ //see if already at highest/lowest price point
+ if (step.step != 0) {
+ if (newPricePoint == prices[cmp].currentPricePoint) {
+ if (newPricePoint == settings.invPricing.recommendation[cmp].minPrice) {
+ //Already at lowest point
+ analysis.data[cmp].recommendation = 'Already at lowest price!';
+ }
+ if (newPricePoint == settings.invPricing.recommendation[cmp].maxPrice) {
+ //Already at highest point
+ analysis.data[cmp].recommendation = 'Already at highest price!';
+ }
+ }
+ } else {
+ analysis.data[cmp].recType = 'neutral';
+ }
+ //check if not set by exceptions
+ if (!analysis.data[cmp].recommendation) {
+ analysis.data[cmp].recommendation = step.name;
+ analysis.data[cmp].newPriceChange = step.step;
+ if (step.step) {
+ analysis.data[cmp].newPricePoint = newPricePoint;
+ analysis.data[cmp].newPrice = Math.round(newPricePoint / 100 * prices[cmp].defaultPrice);
+ }
+ }
+ }
+ }
+ }
+ return analysis;
+}
+
+function generateRouteIndex(analysis) {
+ //Each CMP index
+ for (let cmp in analysis.data) {
+ if (analysis.data[cmp].valid) {
+ let index = (analysis.data[cmp].analysisPricePoint + (analysis.getLoad(cmp) * 100 * 3)) / 4;
+ analysis.data[cmp].index = Math.round(index);
+ }
+ }
+ return analysis;
+}
+
+//Display analysis
+function displayAnalysis(analysis, prices) {
+
+ //Build table
+ let mainDiv = $(".container-fluid .row .col-md-10 div .as-panel:eq(0)");
+ mainDiv.after(
+ `
+ Analysis (today's snapshot)
+
+ `
+ );
+
+ //Table head
+ let th = [];
+ th.push('SC ');
+ th.push('Note ');
+ th.push('Analysis Price ');
+ th.push('Load ');
+ th.push('Index ');
+ th.push('Current Price ');
+ th.push('Recommendation ');
+ th.push('New Price ');
+ let headRow = $(' ').append(th);
+ let thead = $(' ').append(headRow);
+
+ //Table body
+ let tbody = $(' ');
+ for (let cmp in analysis.data) {
+ let td = [];
+ td.push('' + cmp + ' ');
+ td.push('' + analysis.note(cmp) + ' ');
+ td.push('' + analysis.displayPrice(cmp, 'analysis') + ' ');
+ td.push('' + analysis.displayLoad(cmp) + ' ');
+ td.push($(' ').html(analysis.displayIndex(cmp)));
+ td.push('' + analysis.displayPrice(cmp, 'current') + ' ');
+ td.push('' + analysis.displayRec(cmp) + ' ');
+ td.push('' + analysis.displayPrice(cmp, 'new') + ' ');
+ let row = $(' ').append(td);
+ tbody.append(row);
+ }
+
+ //Table footer
+ let footRow = []
+ footRow.push(' ');
+ //Total PAX
+ let tf = [];
+ tf.push('Total PAX ');
+ tf.push(' ');
+ tf.push($(' ').html(analysis.displayTotalLoad('pax')));
+ tf.push($(' ').html(analysis.displayTotalIndex('pax')));
+ tf.push(' ');
+ footRow.push($(' ').append(tf));
+ //Total
+ tf = [];
+ tf.push('Total PAX+Cargo ');
+ tf.push(' ');
+ tf.push($(' ').html(analysis.displayTotalLoad('all')));
+ tf.push($(' ').html(analysis.displayTotalIndex('all')));
+ tf.push(' ');
+ footRow.push($(' ').append(tf));
+ let tfoot = $(' ').append(footRow);
+
+ $("#aes-table-analysis").append(thead, tbody, tfoot);
+
+ //Display pricing and data save buttons
+ if (analysis.hasValue('valid')) {
+ let invPricingAnalysisBar = $('');
+ let invPricingAnalysisBarSpan = $(' ');
+ invPricingAnalysisBar.append($(' ').html(invPricingAnalysisBarSpan));
+ $("#aes-div-analysis").prepend(invPricingAnalysisBar);
+ //create buttons
+ //Save Data
+ let saveInvPricingBtn = $(' ');
+ $(saveInvPricingBtn).click(function() {
+ $(this).closest("li").remove();
+ invPricingAnalysisBarSpan.text('Saving analysis data...');
+ //Get updated time
+ let updateTime = AES.getServerDate().time;
+ pricingData.date[todayDate] = analysis;
+ pricingData.date[todayDate].updateTime = updateTime;
+ pricingData.date[todayDate].date = todayDate;
+ pricingData.date[todayDate].pricingUpdated = 0;
+ chrome.storage.local.set({
+ [pricingData.key]: pricingData }, function() {
+ invPricingAnalysisBarSpan.removeClass().addClass("good").text("Data Saved!");
+ //Automation
+ if (settings.invPricing.autoClose) {
+ close();
+ }
+ });
+ });
+
+ //Update prices
+ let applyNewPriceInvPricingBtn = $('apply new prices (and save data) ');
+ $(applyNewPriceInvPricingBtn).click(function() {
+ $(this).closest("ul").find("li button").closest("li").remove();
+ invPricingAnalysisBarSpan.text('Updating prices...');
+ //Get updated time
+ let updateTime = AES.getServerDate().time;
+ pricingData.date[todayDate] = analysis;
+ pricingData.date[todayDate].updateTime = updateTime;
+ pricingData.date[todayDate].date = todayDate;
+ pricingData.date[todayDate].pricingUpdated = 1;
+ chrome.storage.local.set({
+ [pricingData.key]: pricingData }, function() {
+ $('[name="submit-prices"]').click();
+ });
+ });
+ //Update new pricing input
+ if (analysis.hasValue('newPrice')) {
+ //Modify new price input
+ for (let cmp in analysis.data) {
+ if (analysis.data[cmp].newPrice) {
+ prices[cmp].newPriceInput.value = analysis.data[cmp].newPrice;
+ }
+ }
+ }
+ //For snapshot button
+ if (pricingData.date[todayDate]) {
+ //Today data does exist
+ if (pricingData.date[todayDate].pricingUpdated) {
+ //Today pricing updated
+ invPricingAnalysisBarSpan.text("Today prices have been updated at: " + pricingData.date[todayDate].updateTime);
+
+ //Automation
+ if (settings.invPricing.autoClose) {
+ close();
+ }
+ } else {
+ //Today pricing not updated
+ invPricingAnalysisBarSpan.text("Today's snapshot data saved at: " + pricingData.date[todayDate].updateTime);
+ $(invPricingAnalysisBar).append($(' ').html(saveInvPricingBtn.text("save snapshot data again")));
+ if (analysis.hasValue('newPrice')) {
+ $(invPricingAnalysisBar).append($(' ').html(applyNewPriceInvPricingBtn));
+ }
+ }
+ } else {
+ //Today data does not exist
+ $(invPricingAnalysisBar).append($(' ').html(saveInvPricingBtn.text("save snapshot data")));
+ if (analysis.hasValue('newPrice')) {
+ $(invPricingAnalysisBar).append($(' ').html(applyNewPriceInvPricingBtn));
+ }
+ }
+ }
+}
+
+//Display History
+function displayHistory(analysis) {
+ //Prepare data
+ let dates = [];
+ //Get valid dates can add function here
+ for (let date in pricingData.date) {
+ if (Number.isInteger(parseInt(date))) {
+ dates.push(date)
+ }
+ }
+ dates.sort();
+ //If historical data exist then build
+ if (dates.length) {
+ //Build Div
+ let mainDiv = $("#aes-div-analysis");
+ mainDiv.after('Historical Data
');
+
+ //History Options
+ let fieldset = $(' ').html('History Options ');
+ //Hide Now
+ let option1 = $('
').html(' Show "Now" collumn ');
+ //Show only Priced
+ let option2 = $('
').html(' Show only dates when pricing changed ');
+
+ //Number of records
+ let option3 = $(' ').html('5 past dates 10 past dates All past dates ')
+ let wrapper = $('
').append('Number of past dates ', option3);
+
+ fieldset.append(option1, option2, wrapper);
+ $("#aes-div-invPricing-historicalData").append(fieldset);
+ //Default values
+ if (settings.invPricing.historyTable.showNow) {
+ $("#aes-check-inventory-history-showNow").prop("checked", true);
+ }
+ if (settings.invPricing.historyTable.showOnlyPricing) {
+ $("#aes-check-inventory-history-showOnlyPricing").prop("checked", true);
+ }
+ $("#aes-select-inventory-history-numberPastDates").val(settings.invPricing.historyTable.numberOfDates);
+
+ //Change events
+ $("#aes-check-inventory-history-showNow").change(function() {
+ if (this.checked) {
+ settings.invPricing.historyTable.showNow = 1;
+ } else {
+ settings.invPricing.historyTable.showNow = 0;
+ }
+ chrome.storage.local.set({ settings: settings }, function() {});
+ buildHistoryTable();
+ });
+ $("#aes-check-inventory-history-showOnlyPricing").change(function() {
+ buildHistoryTable();
+ if (this.checked) {
+ settings.invPricing.historyTable.showOnlyPricing = 1;
+ } else {
+ settings.invPricing.historyTable.showOnlyPricing = 0;
+ }
+ chrome.storage.local.set({ settings: settings }, function() {});
+ });
+ $("#aes-select-inventory-history-numberPastDates").change(function() {
+ settings.invPricing.historyTable.numberOfDates = $('#aes-select-inventory-history-numberPastDates').val();
+ chrome.storage.local.set({ settings: settings }, function() {});
+ buildHistoryTable();
+ });
+
+ buildHistoryTable();
+ }
+}
+
+function buildHistoryTable() {
+ //Clean previous table
+ $('#aes-table-inventory-history').remove();
+
+ let showNow = 0;
+ let showOnlyPricing = 0;
+ if ($('#aes-check-inventory-history-showNow:checked').length > 0) {
+ showNow = 1;
+ }
+ if ($('#aes-check-inventory-history-showOnlyPricing:checked').length > 0) {
+ showOnlyPricing = 1;
+ }
+
+ let numberOfDates = $('#aes-select-inventory-history-numberPastDates').val();
+ switch (numberOfDates) {
+ case '5':
+ numberOfDates = 5;
+ break;
+ case '10':
+ numberOfDates = 10;
+ break;
+ case 'all':
+ numberOfDates = 0;
+ break;
+ default:
+ numberOfDates = 10;
+ }
+
+ let dates = [];
+ //Get valid dates can add function here
+ for (let date in pricingData.date) {
+ if (showOnlyPricing) {
+ if (pricingData.date[date].pricingUpdated) {
+ if (Number.isInteger(parseInt(date))) {
+ dates.push(date)
+ }
+ }
+ } else {
+ if (Number.isInteger(parseInt(date))) {
+ dates.push(date)
+ }
+ }
+ }
+ if (numberOfDates) {
+ dates = dates.slice(0, numberOfDates);
+ }
+ dates.sort();
+ dates.reverse();
+ if (dates.length) {
+
+ //Headrows
+ let th = [' '];
+ let th1 = ['SC '];
+ if (showNow) {
+ //Now
+ th.push($(' ').text('Now'));
+ th1.push('Price ');
+ th1.push('Δ % ');
+ th1.push('Load ');
+ th1.push('Δ % ');
+ //index
+ th1.push('Index ');
+ }
+ for (let i = 0; i < dates.length; i++) {
+ let date = dates[i];
+ if (i) {
+ th.push($(' ').text(AES.formatDateString(date)));
+ th1.push('Price ');
+ th1.push('Δ % ');
+ th1.push('Load ');
+ th1.push('Δ % ');
+ //Index
+ th1.push('Index ');
+ } else {
+ th.push($(' ').text(AES.formatDateString(date)));
+ th1.push('Price ');
+ th1.push('Load ');
+ //Index
+ th1.push('Index ');
+ }
+ }
+
+ let headRow = $(' ').append(th);
+ let headRow2 = $(' ').append(th1);
+ let thead = $(' ').append(headRow, headRow2);
+
+ //Build table
+ let compartments = ['Y', 'C', 'F', 'Cargo'];
+
+ //Tbody rows
+ let tbody = $(' ');
+ compartments.forEach(function(cmp) {
+ let td = [];
+ td.push($(' ').text(cmp));
+ if (showNow) {
+ //Now TDs
+ let data = analysis.data[cmp];
+ let prevData = pricingData.date[dates[dates.length - 1]].data[cmp];
+ td.push($(' ').html(displayHistoryPrice(data)));
+ td.push($(' ').html(displayDifference(data, prevData).price));
+ td.push($(' ').html(displayHistoryLoad(data)));
+ td.push($(' ').html(displayDifference(data, prevData).load));
+ //Index
+ td.push($(' ').html(historyDisplayIndex(data, 0)));
+ }
+ //Historical tds
+ for (let i = 0; i < dates.length; i++) {
+ let date = dates[i];
+ let data = pricingData.date[date].data[cmp];
+ if (i) {
+ let prevData = pricingData.date[dates[i - 1]].data[cmp];
+ //Not first data point
+ td.push($(' ').html(displayHistoryPrice(data)));
+ td.push($(' ').html(displayDifference(data, prevData).price));
+ td.push($(' ').html(displayHistoryLoad(data)));
+ td.push($(' ').html(displayDifference(data, prevData).load));
+ //index
+ td.push($(' ').html(historyDisplayIndex(data, 0)));
+ } else {
+ //First data point
+ td.push($(' ').html(displayHistoryPrice(data)));
+ td.push($(' ').html(displayHistoryLoad(data)));
+ //index
+ td.push($(' ').html(historyDisplayIndex(data, 0)));
+ }
+ }
+
+ //Finish row
+ let row = $(' ').append(td);
+ tbody.append(row);
+ });
+
+ //Table footer Total Rows
+ let totalCollumns = th1.length;
+ let footRow = [];
+ let footerRows = ['pax', 'all']
+ footRow.push(' ');
+ //Total PAX
+ footerRows.forEach(function(type) {
+ let tf = [];
+ tf.push($(' ').text(historyDisplayTotalText(type)));
+ if (showNow) {
+ //Now
+ let data = analysis.data;
+ tf.push(' ');
+ tf.push($(' ').html(historyDisplayTotal(data, type)));
+ tf.push(' ');
+ //index
+ tf.push($(' ').html(historyDisplayIndex(data, type)));
+ }
+ for (let i = 0; i < dates.length; i++) {
+ let date = dates[i];
+ let data = pricingData.date[date].data;
+ if (i) {
+ tf.push(' ');
+ tf.push($(' ').html(historyDisplayTotal(data, type)));
+ tf.push(' ');
+ //index
+ tf.push($(' ').html(historyDisplayIndex(data, type)));
+ } else {
+ tf.push(' ');
+ tf.push($(' ').html(historyDisplayTotal(data, type)));
+ //index
+ tf.push($(' ').html(historyDisplayIndex(data, type)));
+ }
+ }
+
+ footRow.push($(' ').append(tf));
+ });
+
+ let tfoot = $(' ').append(footRow);
+ let table = $('').append(thead, tbody, tfoot);
+ let tableDiv = $('
').append(table);
+
+ $("#aes-div-invPricing-historicalData").append(tableDiv);
+ }
+}
+
+function displayValidationError() {
+ let p = [];
+ p.push($('
').text('AES Inventory Pricing Module could not be loaded because of errors:'));
+ aesmodule.errors.forEach(function(error) {
+ p.push($('
').html('' + error + ' '));
+ });
+ p.push($('
').html('Refresh the page after making adjustments.'));
+ let panel = $('
').append(p);
+ let h2 = $(' ').text('AES Inventory Pricing Module');
+ let div = $('
').append(h2, panel);
+ $('h1:eq(0)').after(h2, panel)
+}
+
+//History Table functions
+function historyDisplayIndex(data, type) {
+ let cmp = [];
+ let index = 0;
+ switch (type) {
+ case 'all':
+ cmp = ['Y', 'C', 'F', 'Cargo'];
+ break;
+ case 'pax':
+ cmp = ['Y', 'C', 'F'];
+ break;
+ case 0:
+ cmp = 0;
+ break;
+ }
+ if (cmp) {
+ //Multi index
+ let count = 0;
+ cmp.forEach(function(comp) {
+ if (data[comp].valid) {
+ index += data[comp].index;
+ count++;
+ }
+ });
+ index = Math.round(index / count);
+ } else {
+ //one cmp index
+ if (data.valid) {
+ index = data.index;
+ }
+ }
+ if (index) {
+ let span = $(' ');
+ if (index >= 90) {
+ return span.addClass('good').text(index);
+ }
+ if (index <= 50) {
+ return span.addClass('bad').text(index);
+ }
+ return span.addClass('warning').text(index);
+ } else {
+ return '-';
+ }
+}
+
+function historyDisplayTotalText(type) {
+ switch (type) {
+ case 'all':
+ return "Total PAX+Cargo";
+ case 'pax':
+ return "Total PAX";
+ }
+}
+
+function historyDisplayTotal(data, type) {
+ let cmp = [];
+ switch (type) {
+ case 'all':
+ cmp = ['Y', 'C', 'F', 'Cargo'];
+ break;
+ case 'pax':
+ cmp = ['Y', 'C', 'F'];
+ break;
+ default:
+ // code block
+ }
+ let load, cap, bkd;
+ load = cap = bkd = 0;
+ cmp.forEach(function(comp) {
+ if (data[comp].valid) {
+ cap += data[comp].totalCap;
+ bkd += data[comp].totalBkd;
+ }
+ });
+ if (cap) {
+ load = Math.round(bkd / cap * 100);
+ return bkd + ' / ' + cap + ' (' + displayPerc(load, 'load') + ')';
+ } else {
+ return '-';
+ }
+}
+
+function displayHistoryLoad(data) {
+ if (data.valid) {
+ let booked = data.totalBkd;
+ let capacity = data.totalCap;
+ let load = Math.round(booked / capacity * 100);
+ return booked + ' / ' + capacity + ' (' + displayPerc(load, 'load') + ')';
+ } else {
+ return '-';
+ }
+}
+
+function displayHistoryPrice(data) {
+ if (data.valid) {
+ let price = data.analysisPrice;
+ let pricePoint = data.analysisPricePoint;
+ return formatCurrency(price) + ' AS$ (' + displayPerc(pricePoint, 'price') + ')';
+ } else {
+ return '-';
+ }
+}
+
+function displayDifference(current, old) {
+ if (current.valid && old.valid) {
+ let currentLoad = Math.round(current.totalBkd / current.totalCap * 100);
+ let oldLoad = Math.round(old.totalBkd / old.totalCap * 100);
+ let load = currentLoad - oldLoad;
+ let price = current.analysisPricePoint - old.analysisPricePoint;
+ return { load: load, price: price };
+ } else {
+ return { load: '-', price: '-' };
+ }
+}
+
+function displayPerc(perc, type) {
+ let span = $(' ');
+ switch (type) {
+ case 'price':
+ if (perc >= 100) {
+ span.addClass('good').text(perc + "%");
+ return span.prop('outerHTML');
+ }
+ if (perc < 75) {
+ span.addClass('bad').text(perc + "%");
+ return span.prop('outerHTML');
+ }
+ span.addClass('warning').text(perc + "%");
+ return span.prop('outerHTML');
+ case 'load':
+ if (perc >= 70) {
+ span.addClass('good').text(perc + "%");
+ return span.prop('outerHTML');
+ }
+ if (perc < 40) {
+ span.addClass('bad').text(perc + "%");
+ return span.prop('outerHTML');
+ }
+ span.addClass('warning').text(perc + "%");
+ return span.prop('outerHTML');
+ default:
+ return 'ERROR:2502 Wrong type set:' + type + ' ';
+ }
+}
+//Helper functions
+function formatCurrency(value) {
+ return Intl.NumberFormat().format(value)
+}
+
+function getPricingInventoryKey() {
+ //Get Origin and Destination
+ let x = $("h2:first a");
+ let org = $(x[0]).text();
+ let dest = $(x[1]).text();
+ //get server
+ let server = AES.getServerName();
+ //get airline code
+ let airline = getAirlineCode();
+ //create key
+ let key = server + airline + org + dest + 'routeAnalysis';
+ return { key: key, server: server, airline: airline, type: "routeAnalysis", origin: org, destination: dest }
+}
+
+function getAirlineCode() {
+ let airline = $("#inventory-grouped-table tbody a:first").text().split(" ");
+ if (!airline[0]) {
+ airline = $("#inventory-table tbody a:first").text().split(" ");
+ }
+ return airline[0];
+}
diff --git a/extension/content_personelManagement.js b/extension/content_personelManagement.js
index 391a4f4..8c5b57b 100644
--- a/extension/content_personelManagement.js
+++ b/extension/content_personelManagement.js
@@ -69,7 +69,7 @@ function displayPersonelManagement(){
chrome.storage.local.set({settings: settings}, function(){});
});
input.change(function(){
- settings.personelManagement.value = cleanInteger(input.val());
+ settings.personelManagement.value = AES.cleanInteger(input.val());
chrome.storage.local.set({settings: settings}, function(){});
});
@@ -92,7 +92,7 @@ function displayPersonelManagement(){
let key = server+airline+"personelManagement";
chrome.storage.local.get([key], function(result) {
if(result[key]){
- p.after($('
').text('Last time updated on '+formatDate(result[key].date)+' '+result[key].time));
+ p.after($('
').text('Last time updated on '+AES.formatDateString(result[key].date)+' '+result[key].time));
} else {
p.after($('
').text('No previous personel management data found.'));
}
@@ -111,8 +111,8 @@ function priceUpdate(span){
}
let salaryInput = $(this).find('form input:eq(2)');
- let salary = cleanInteger(salaryInput.val());
- let average = cleanInteger($(this).find('td:eq(9)').text());
+ let salary = AES.cleanInteger(salaryInput.val());
+ let average = AES.cleanInteger($(this).find('td:eq(9)').text());
let salaryBtn = $(this).find('td:eq(8) > form .input-group-btn input');
let newSalary;
switch(type) {
@@ -142,7 +142,7 @@ function priceUpdate(span){
//Save into memory
- let today = getDate();
+ let today = AES.getServerDate()
let key = server + airline + 'personelManagement';
let personelManagementData = {
server:server,
@@ -158,36 +158,6 @@ function priceUpdate(span){
}
});
}
-function cleanInteger(a){
- a = a.replace(',','');
- a = a.replace('.','');
- a = a.replace(' AS$','');
- return parseInt(a, 10);
-}
-function getDate(){
- let a = $(".as-footer-line-element:has('.fa-clock-o')").text().trim();
- let b = a.split(" ");
- //For date
- let dateTemp = b[0].split("-");
- let date;
- if(dateTemp.length == 1){
- //German
- dateTemp = dateTemp[0].split(".");
- date = dateTemp.map(function(value){
- return value.replace(/[^A-Za-z0-9]/g, '');
- });
- date = date[2] + date[1] + date[0];
- } else {
- //English
- date = dateTemp.map(function(value){
- return value.replace(/[^A-Za-z0-9]/g, '');
- });
- date = date[0] + date[1] + date[2];
- }
- //For time
- let time = b[b.length-2] +' '+b[b.length-1];
- return {date:date,time:time};
-}
function getAirline(){
let airline = $("#as-navbar-main-collapse ul li:eq(0) a:eq(0)").text().trim().replace(/[^A-Za-z0-9]/g, '');
return airline;
@@ -196,7 +166,4 @@ function getServerName(){
let server = window.location.hostname
server = server.split('.');
return server[0];
-}
-function formatDate(date){
- return date.substring(0, 4)+'-'+date.substring(4, 6)+'-'+date.substring(6, 8);
-}
+}
diff --git a/extension/css/content.css b/extension/css/content.css
index c227b42..817c134 100644
--- a/extension/css/content.css
+++ b/extension/css/content.css
@@ -1,7 +1,99 @@
+/* Tables */
+.aes-table {
+ width: auto;
+}
+
+.as-table-well:has(.aes-table) {
+ width: fit-content;
+}
+
+/* Helpers */
.aes-text-right {
- text-align: right;
+ text-align: right;
}
.aes-no-text-wrap {
- white-space: nowrap;
+ white-space: nowrap;
+}
+
+/* Specific */
+.aes-aircraftProfit-profit {
+ text-align: right;
+ white-space: nowrap;
+}
+
+/**
+ * About Modal
+ */
+#aes-about-dialog .modal-dialog {
+ width: 40em;
+ max-width: 90vw;
+ margin-right: auto;
+ margin-left: auto;
+}
+
+#aes-about-dialog .modal-body {
+ text-align: center;
+}
+
+#aes-about-dialog h2 {
+ color: inherit;
+}
+
+#aes-about-dialog img {
+ width: 64px;
+ height: 64px;
+ border-radius: 5px;
+}
+
+#aes-about-dialog button[data-dismiss] {
+ position: absolute;
+ top: 10px;
+ right: 10px;
+}
+
+/**
+ * General UI improvements
+ */
+
+/* Align icons and text in menu items */
+.dropdown-menu > li > a:has(.fa) {
+ display: grid;
+ grid-template-columns: 1em auto;
+ gap: .5em;
+ align-items: center;
+}
+
+.dropdown-menu > li > a > .fa {
+ justify-self: center;
+}
+
+/* Hide empty aircraft categories */
+.as-fieldset:has(.types):not(:has(li)) {
+ display: none;
+}
+
+[class^="layout-col-md"]:has(.types):not(:has(li)) {
+ display: none;
+}
+
+/* Dark Mode fixes */
+head:has(link[href^="/dist/assets/theme-dark"]) + body .bad {
+ color: #ffb8b6;
+}
+
+head:has(link[href^="/dist/assets/theme-dark"]) + body .good {
+ color: #7cde7c;
+}
+
+head:has(link[href^="/dist/assets/theme-dark"]) + body .warning {
+ color: #ffbc5d;
+}
+
+head:has(link[href^="/dist/assets/theme-dark"]) + body .visual-flight-plan .vfp div.day div.blocks div.block.flight.locked {
+ color: #a26900;
+}
+
+head:has(link[href^="/dist/assets/theme-dark"]) + body .visual-flight-plan .vfp div.day div.blocks div.block.flight.error {
+ color: #cd0000;
}
\ No newline at end of file
diff --git a/extension/helpers.js b/extension/helpers.js
index 5db47d7..50da230 100644
--- a/extension/helpers.js
+++ b/extension/helpers.js
@@ -1,4 +1,170 @@
/** Shared logic */
class AES {
+ /**
+ * Returns the airline name and code from the dashboard
+ * @returns {object} {name: string, code: string}
+ */
+ static getAirlineCode() {
+ const factsTable = document.querySelector(".facts table")
+ const nameElement = factsTable.querySelector("tr:nth-child(1) td:last-child")
+ const codeElement = factsTable.querySelector("tr:nth-child(2) td:last-child")
+
+ return {
+ name: nameElement.innerText,
+ code: codeElement.innerText
+ }
+ }
+ /**
+ * Returns the server name
+ * @returns {string} server name
+ */
+ static getServerName() {
+ const hostname = window.location.hostname
+ const servername = hostname.split(".")[0]
+
+ return servername
+ }
+
+ /**
+ * Formats a currency value local standards
+ * @param {integer} currency value
+ * @param {string} alignment: "right" | "left"
+ * @returns {HTMLElement} span with formatted value
+ */
+ static formatCurrency(value, alignment) {
+ let container = document.createElement("span")
+ let formattedValue = Intl.NumberFormat().format(value)
+ let indicatorEl = document.createElement("span")
+ let valueEl = document.createElement("span")
+ let currencyEl = document.createElement("span")
+ let containerClasses = "aes-no-text-wrap"
+
+ if (alignment === "right") {
+ containerClasses = "aes-text-right aes-no-text-wrap"
+ }
+
+ if (value >= 0) {
+ valueEl.classList.add("good")
+ indicatorEl.classList.add("good")
+ indicatorEl.innerText = "+"
+ }
+
+ if (value < 0) {
+ valueEl.classList.add("bad")
+ indicatorEl.classList.add("bad")
+ indicatorEl.innerText = "-"
+ formattedValue = formattedValue.replace("-", "")
+ }
+
+ valueEl.innerText = formattedValue
+ currencyEl.innerText = " AS$"
+
+ container.className = containerClasses
+ container.append(indicatorEl, valueEl, currencyEl)
+
+ return container
+ }
+
+ /**
+ * Formats a date string to human readable format
+ * @param {string} "20240524"
+ * @returns {string} "2024-05-24" | "error: invalid format for AES.formatDateString"
+ */
+ static formatDateString(date) {
+ if (!date) {
+ return
+ }
+
+ const correctLength = date.length === 8
+ const isInteger = Number.isInteger(parseInt(date))
+ let result = "error: invalid format for AES.formatDateString"
+
+ if (correctLength && isInteger) {
+ const year = date.substring(0, 4)
+ const month = date.substring(4, 6)
+ const day = date.substring(6, 8)
+ result = `${year}-${month}-${day}`
+ }
+
+ return result
+ }
+ /**
+ * Returns a formatted date (week) string
+ * @param {string} "212024"
+ * @returns {string} "21/2014 | "error: invalid format for AES.formatDateStringWeek"
+ */
+ static formatDateStringWeek(date) {
+ const correctLength = date.toString().length === 6
+ const isInteger = Number.isInteger(parseInt(date))
+ let result = "error: invalid format for AES.formatDateStringWeek"
+
+ if (correctLength && isInteger) {
+ const DateAsString = date.toString()
+ const week = DateAsString.substring(0, 2)
+ const year = DateAsString.substring(2, 6)
+
+ result = `${week}/${year}`
+ }
+
+ return result
+ }
+
+ /**
+ * Gets the server’s current date and time
+ * @returns {object} datetime - { date: "20240607", time: "16:24 UTC" }
+ */
+ static getServerDate() {
+ const source = document.querySelector(".as-navbar-bottom span:has(.fa-clock-o)").innerText.trim()
+ const sourceAsNumbers = this.cleanInteger(source).toString()
+
+ // The source always consists of 12 numbers
+ const expectedLength = 12
+ if (sourceAsNumbers.length != expectedLength) {
+ throw new Error(`Unexpected length for source (${sourceAsNumbers.length}). There might’ve been a UI update. Check AES.getServerDate()`)
+ }
+
+ // Splits the date component from the data,
+ // then splits that into an array for the year, month, and day
+ let dateArray = source.split(" ")[0].split(/\D+/)
+ if (dateArray[0].length === 2) {
+ dateArray.reverse()
+ }
+ let date = dateArray[0]+dateArray[1]+dateArray[2]
+
+ // Strip the date component from the data
+ // leaving only the time
+ let time = source.replace(/.{10}\s/, "")
+
+ const datetime = {
+ date: date,
+ time: time
+ }
+
+ return datetime
+ }
+
+ /**
+ * Returns the difference between dates in days
+ * @param {array} ["20240520", "20240524"]
+ * @returns {integer} 4
+ */
+ static getDateDiff(dates) {
+ let dateA = new Date(`${this.formatDateString(dates[0])}T12:00:00Z`)
+ let dateB = new Date(`${this.formatDateString(dates[1])}T12:00:00Z`)
+ let result = Math.round((dateA - dateB)/(1000 * 60 * 60 * 24))
+
+ return result
+ }
+
+ /**
+ * Cleans a string of punctuation to returns an integer
+ * @param {string} "2,000 AS$" | "2.000 AS$"
+ * @returns {integer} 2000
+ */
+ static cleanInteger(value) {
+ // \D matches any character that's not a digit
+ let result = value.replaceAll(/\D+/g, "")
+ return parseInt(result, 10)
+ }
}
diff --git a/extension/manifest.json b/extension/manifest.json
index ab466f6..4876f95 100644
--- a/extension/manifest.json
+++ b/extension/manifest.json
@@ -2,7 +2,7 @@
"manifest_version": 3,
"name": "AirlineSim Enhancement Suite",
"description": "Great quality of live improvements for AirlineSim",
- "version": "0.6.7",
+ "version": "0.6.8",
"action": {
"default_icon": {
"128": "images/AES-logo-128.png",
@@ -23,47 +23,59 @@
"content_scripts": [
{
"css": ["css/content.css"],
- "js": ["helpers.js"],
- "matches": ["https://*.airlinesim.aero/app/*"]
+ "js": [
+ "js/jquery-3.4.1.min.js",
+ "helpers.js",
+ "modules/aes-menu.js",
+ "modules/about-dialog.js"
+ ],
+ "matches": ["https://*.airlinesim.aero/app/*", "https://*.airlinesim.aero/action/*"]
},
{
- "js": ["js/jquery-3.4.1.min.js", "content_inventory.js"],
+ "js": [
+ "content_inventory.js",
+ "modules/inventory/validation.js"
+ ],
"matches": ["https://*.airlinesim.aero/app/com/inventory/*"]
},
{
- "js": ["js/jquery-3.4.1.min.js", "content_fligthSchedule.js"],
+ "js": ["content_fligthSchedule.js"],
"matches": ["https://*.airlinesim.aero/app/info/enterprises/*tab=3"]
},
{
- "js": ["js/jquery-3.4.1.min.js", "content_settings.js"],
+ "js": ["content_settings.js"],
"matches": ["https://*.airlinesim.aero/app/enterprise/settings*"]
},
{
- "js": ["js/jquery-3.4.1.min.js", "content_dashboard.js"],
+ "js": ["content_dashboard.js"],
"matches": ["https://*.airlinesim.aero/app/enterprise/dashboard*"]
},
{
- "js": ["js/jquery-3.4.1.min.js", "content_personelManagement.js"],
+ "js": ["content_personelManagement.js"],
"matches": ["https://*.airlinesim.aero/action/enterprise/staffOverview*"]
},
{
- "js": ["js/jquery-3.4.1.min.js", "content_enterpriceOverview.js"],
+ "js": ["content_enterpriceOverview.js"],
"matches": ["https://*.airlinesim.aero/app/info/enterprises/*"]
},
{
- "js": ["js/jquery-3.4.1.min.js", "content_flightInfo.js"],
+ "js": ["content_flightInfo.js"],
"matches": ["https://*.airlinesim.aero/action/info/flight*"]
},
{
- "js": ["js/jquery-3.4.1.min.js", "content_aircraftFlights.js"],
+ "js": ["content_aircraftFlights.js"],
"matches": ["https://*.airlinesim.aero/app/fleets/aircraft/*/1*"]
},
{
- "js": ["js/jquery-3.4.1.min.js", "content_fleetManagement.js"],
+ "js": ["content_fleetManagement.js"],
"matches": ["https://*.airlinesim.aero/app/fleets*"]
}
],
"key": "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAlgUt+9pr5xsoJIdZtv2s/miPjNaUMf5NdIRH6wQzgWpGzMCwf46cUSL0FbpnIo6E9d6pITalABU8Dx72/isyas/da0EQNCQkYxhvu2YakUyUMyzKg0jPuxR+VyaEzDMVQKyVD1xZb/jjOkHXvGew/EHPw9BzCdhKRptRqo4gqdgifS0/xQFiqneA35Hhqwo9bh5zfhZpdMsssMHH3uGGm1f4Yeq+j2ZUtvf74v8pWR5+sVI/dFhTSpQaT60sWFYkPVwtpQ5jUwqm9vDyAH0obZxVtBqI5UkmjEJsCXmQW6QdC4+gRwTgrKc137SH+mUVRHfcXogMSa72+szX63pMUQIDAQAB",
"permissions": ["activeTab", "declarativeContent", "storage", "unlimitedStorage"],
- "host_permissions": ["https://*.airlinesim.aero/"]
+ "host_permissions": ["https://*.airlinesim.aero/"],
+ "web_accessible_resources": [{
+ "resources": ["/images/*"],
+ "matches": ["https://*.airlinesim.aero/*"]
+ }]
}
diff --git a/extension/modules/about-dialog.js b/extension/modules/about-dialog.js
new file mode 100644
index 0000000..4924b2b
--- /dev/null
+++ b/extension/modules/about-dialog.js
@@ -0,0 +1,103 @@
+class AboutDialog {
+ #target
+ #container
+ #modalDialog
+ #modalContent
+ #closeButton
+ #body
+
+ constructor() {
+ this.#closeButton = this.#createCloseButton()
+ this.#body = this.#createBody()
+ this.#body.prepend(this.#closeButton)
+ this.#modalContent = this.#createModalContent()
+ this.#modalContent.append(this.#body)
+ this.#modalDialog = this.#createModalDialog()
+ this.#modalDialog.append(this.#modalContent)
+ this.#container = this.#createContainer()
+ this.#container.append(this.#modalDialog)
+ this.#target = this.#setTarget()
+ this.#target.append(this.#container)
+
+ const observer = this.#mutationObserver()
+ observer.observe(this.#container, {attributes: true})
+ }
+
+ #createContainer() {
+ const container = document.createElement("div")
+ container.class = "modal"
+ container.id = "aes-about-dialog"
+ container.setAttribute("role", "dialog")
+ container.setAttribute("aria-modal", "true")
+ container.setAttribute("aria-hidden", "true")
+ container.style = "display: none"
+
+ return container
+ }
+
+ #createModalDialog() {
+ const modalDialog = document.createElement("div")
+ modalDialog.className = "modal-dialog modal-md"
+
+ return modalDialog
+ }
+
+ #createModalContent() {
+ const modalContent = document.createElement("div")
+ modalContent.className = "modal-content"
+
+ return modalContent
+ }
+
+ #createCloseButton() {
+ const icon = document.createElement("span")
+ icon.setAttribute("aria-hidden", "true")
+ icon.innerText = "×"
+ const label = document.createElement("span")
+ label.innerText = "Close"
+ label.className = "sr-only"
+ const button = document.createElement("button")
+ button.setAttribute("type", "button")
+ button.dataset.dismiss = "modal"
+ button.className = "btn btn-default"
+ button.append(icon, label)
+
+ return button
+ }
+
+ #createBody() {
+ const body = document.createElement("div")
+ body.className = "modal-body"
+ const manifest = chrome.runtime.getManifest()
+ const description = manifest.description
+ const version = manifest.version
+
+ body.innerHTML = `
+
+ AirlineSim Enhancement Suite
+ Version ${version}
+ Copyright © 2020-2024 AES Authors. MIT License.
+ `
+
+ return body
+ }
+
+ #setTarget() {
+ const target = document.querySelector("body")
+ return target
+ }
+
+ #mutationObserver() {
+ const observer = new MutationObserver(this.#correctBootstrapBehaviour.bind(this))
+ return observer
+ }
+
+ #correctBootstrapBehaviour() {
+ if (this.#container.classList.contains("in") && !this.#container.classList.contains("modal")) {
+ this.#container.classList.add("modal")
+ this.#container.style = "display: block"
+ }
+ }
+}
+
+new AboutDialog()
diff --git a/extension/modules/aes-menu.js b/extension/modules/aes-menu.js
new file mode 100644
index 0000000..dfa2e61
--- /dev/null
+++ b/extension/modules/aes-menu.js
@@ -0,0 +1,162 @@
+class AESMenu {
+ #target
+ #container
+ #button
+ #menu
+
+ constructor() {
+ this.#target = document.querySelector("#as-navbar-main-collapse .navbar-nav > li:nth-child(5)")
+ this.#container = this.#createContainer()
+ this.#button = this.#createButton()
+ this.#menu = this.#createMenu()
+
+ this.#container.append(this.#button, this.#menu)
+ this.#target.after(this.#container)
+ }
+
+ /**
+ * Creates the menu container
+ * @returns {HTMLElement} container
+ */
+ #createContainer() {
+ const container = document.createElement("li")
+ container.className = "dropdown"
+ return container
+ }
+
+ /**
+ * Creates the menu toggle button
+ * @returns {HTMLElement} button
+ */
+ #createButton() {
+ const caret = document.createElement("span")
+ caret.className = "caret"
+ const button = document.createElement("a")
+ button.setAttribute("role", "button")
+ button.setAttribute("tabindex", "0")
+ button.dataset.toggle = "dropdown"
+ button.className = "dropdown-toggle"
+ button.innerText = "AES"
+ button.style = "cursor: pointer"
+ button.append(caret)
+
+ return button
+ }
+
+ /**
+ * Creates the menu
+ * @returns {HTMLElement} menu
+ */
+ #createMenu() {
+ const menu = document.createElement("ul")
+ menu.className = "dropdown-menu"
+ const menuItems = []
+ const content = [{
+ label: "Community",
+ isHeader: true
+ },{
+ label: "Forum Topic",
+ href: "https://forums.airlinesim.aero/t/introducing-airlinesim-enhancement-suite-beta/",
+ newWindow: true
+ },{
+ isDivider: true
+ },{
+ label: "Support",
+ isHeader: true
+ },{
+ label: "Report a Bug",
+ href: `https://github.com/ZoeBijl/airlinesim-enhancement-suite/issues/new?body=AES:%20v${chrome.runtime.getManifest().version}%0AChrome:%20v${window.navigator.userAgent.match(/Chrom(?:e|ium)\/([0-9]+)/)[1]}%0A%0A`,
+ newWindow: true,
+ icon: { className: "fa-bug" }
+ },{
+ label: "Handbook",
+ href: "https://docs.google.com/document/d/1hzMHb3hTBXSZNtuDKoBuvx1HP9CgB7wVYR59yDYympg/",
+ newWindow: true,
+ icon: { className: "fa-book" }
+ },{
+ label: "GitHub",
+ href: "https://github.com/ZoeBijl/airlinesim-enhancement-suite",
+ newWindow: true,
+ icon: { className: "fa-github" }
+ },{
+ isDivider: true
+ },{
+ label: "About AES",
+ icon: { className: "fa-info" },
+ data: {
+ toggle: "modal",
+ target: "#aes-about-dialog"
+ }
+ }]
+ for (const item of content) {
+ let menuItem = this.#createMenuItem(item)
+ menuItems.push(menuItem)
+ }
+ for (const item of menuItems) {
+ menu.append(item)
+ }
+
+ return menu
+ }
+
+ /**
+ * Creates a menu item
+ * @param {object} content - object containing information required to build the item
+ * @returns {HTMLElement} menuItem
+ */
+ #createMenuItem(content) {
+ const menuItem = document.createElement("li")
+ let menuItemContent, icon
+ if (content.label) {
+ menuItemContent = content.label
+ }
+ if (content.isDivider) {
+ menuItem.className = "divider"
+ return menuItem
+ }
+ if (content.isHeader) {
+ menuItem.className = "dropdown-header"
+ }
+ if (content.icon || content.newWindow) {
+ icon = document.createElement("span")
+ icon.setAttribute("aria-hidden", "true")
+ }
+ if (content.icon) {
+ icon.className = `fa ${content.icon.className}`
+ }
+ if (content.data?.toggle) {
+ const button = document.createElement("a")
+ button.setAttribute("role", "button")
+ button.setAttribute("tabindex", "0")
+ button.style = "cursor: pointer"
+ if (icon) {
+ button.append(icon)
+ }
+ button.append(content.label)
+ for (const attribute in content.data) {
+ button.dataset[attribute] = content.data[attribute]
+ }
+ menuItemContent = button
+ }
+ if (content.href) {
+ const link = document.createElement("a")
+ link.setAttribute("href", content.href)
+ if (content.newWindow && !content.icon) {
+ icon.className = "fa fa-external-link"
+ }
+ if (content.newWindow) {
+ link.setAttribute("target", "_blank")
+ link.setAttribute("rel", "noreferrer noopener")
+ }
+ if (icon) {
+ link.append(icon)
+ }
+ link.append(content.label)
+ menuItemContent = link
+ }
+ menuItem.append(menuItemContent)
+ return menuItem
+ }
+}
+
+new AESMenu()
diff --git a/extension/modules/inventory/validation.js b/extension/modules/inventory/validation.js
new file mode 100644
index 0000000..426b2d1
--- /dev/null
+++ b/extension/modules/inventory/validation.js
@@ -0,0 +1,172 @@
+class Validation {
+ valid = true
+ errors = []
+
+ constructor() {
+ this.checkAllFlightNumbersSelected()
+ this.checkApplyToSettings()
+ this.checkServiceClasses()
+ this.checkFlightStatus()
+ this.checkLoad()
+ this.checkGroupByFlight()
+ }
+
+ /**
+ * Check if “All Flight Numbers” tab is active
+ */
+ checkAllFlightNumbersSelected() {
+ let message = "Please select \"All Flight Numbers\" under Current Inventory"
+ let active = $('.col-md-10 > div > .as-panel:eq(1) > ul:eq(0) li:eq(0)').hasClass("active")
+ if (!active) {
+ this.valid = false
+ this.errors.push(message)
+ }
+ }
+
+ /**
+ * Check “Apply settings to” are set correctly
+ */
+ checkApplyToSettings() {
+ let checkboxes = $('.col-md-10 > div > .as-panel:eq(1) > div > div > div:eq(0) fieldset:eq(2) > div input')
+ let valid
+ let messages = []
+ checkboxes.each(function(index) {
+ switch (index) {
+ case 0:
+ if (!this.checked) {
+ let message = "Please check “Airport Pair” under “Apply settings to” in the “Settings”-panel"
+ valid = false
+ messages.push(message)
+ }
+ break
+ case 1:
+ if (!this.checked) {
+ let message = "Please check “Flight Numbers” under “Apply settings to” in the “Settings”-panel"
+ valid = false
+ messages.push(message)
+ }
+ break
+ case 2:
+ if (this.checked) {
+ let message = "Please uncheck “Return Airport Pair” under “Apply settings to” in the “Settings”-panel"
+ valid = false
+ messages.push(message)
+ }
+ break
+ case 3:
+ if (this.checked) {
+ let message = "Please uncheck “Return Flight Numbers” under “Apply settings to” in the “Settings”-panel"
+ valid = false
+ messages.push(message)
+ }
+ break
+ }
+ })
+
+ if (valid === false) {
+ this.valid = valid
+ this.errors.push(...messages)
+ }
+ }
+
+ /**
+ * Check that all “Service Classes” are selected
+ */
+ checkServiceClasses() {
+ let valid
+ let messages = []
+ let container = $('.col-md-10 > div > .as-panel:eq(1) > div > div > div:eq(1) .layout-col-md-3')
+ let labels = $('fieldset:eq(0) label', container)
+
+ labels.each(function() {
+ if (!$('input', this)[0].checked) {
+ valid = false
+ messages.push(`Please check “${$(this).text()}” under “Service Classes” in the “Data”-panel`)
+ }
+ })
+
+ if (valid === false) {
+ this.valid = valid
+ this.errors.push(...messages)
+ }
+ }
+
+ /**
+ * Check that the correct “Flight Status” is selected
+ */
+ checkFlightStatus() {
+ let valid
+ let messages = []
+ let container = $('.col-md-10 > div > .as-panel:eq(1) > div > div > div:eq(1) .layout-col-md-3')
+ let labels = $('fieldset:eq(1) label', container)
+ labels.each(function(index) {
+ if (index === 1 || index === 2) {
+ if (!$('input', this)[0].checked) {
+ let message = `Please check “${$(this).text()}” under “Flight Status” in the “Data”-panel`
+ valid = false
+ messages.push(message)
+ }
+ }
+ })
+
+ if (valid === false) {
+ this.valid = valid
+ this.errors.push(...messages)
+ }
+ }
+
+ /**
+ * Check “Load” settings
+ */
+ checkLoad() {
+ let valid
+ let messages = []
+ let container = $('.col-md-10 > div > .as-panel:eq(1) > div > div > div:eq(1) .layout-col-md-3')
+
+ $('fieldset:eq(2) div', container).each(function(index) {
+ let valueAsInteger = parseInt($('select option:selected', this).text(), 10)
+
+ // Minimum
+ if (index === 0) {
+ if (valueAsInteger != 0) {
+ let message = `Please select 0 for “${$('label', this).text()}” under “Load” in the “Data”-panel`
+ valid = false
+ messages.push(message)
+ }
+ }
+ // Max
+ if (index === 1) {
+ if (valueAsInteger != 100) {
+ let message = `Please select 100 for “${$('label', this).text()}” under “Load” in the “Data”-panel`
+ valid = false
+ messages.push(message)
+ }
+ }
+ });
+
+ if (valid === false) {
+ this.valid = valid
+ this.errors.push(...messages)
+ }
+ }
+
+ /**
+ * Check “Group by flight” settings
+ */
+ checkGroupByFlight() {
+ let valid
+ let messages = []
+ let container = $('.col-md-10 > div > .as-panel:eq(1) > div > div > div:eq(1) .layout-col-md-3')
+ let checkboxes = $('fieldset:eq(3) input', container)
+ if (checkboxes[0].checked) {
+ let message = `Please uncheck “${$('fieldset:eq(3) label', container).text()}” under “Settings” in the “Data”-panel`
+ valid = false
+ messages.push(message)
+ }
+
+ if (valid === false) {
+ this.valid = valid
+ this.errors.push(...messages)
+ }
+ }
+}