EL_PATRON / KondafExp

// ==UserScript==
// @name           KondafExp
// @Author	   EL_PATRON
// @version        1.9.2
// @include        *game/index.php?page=*ingame&component=*fleetdispatch*
// @include        *game/index.php?page=*
// @exclude        *game/index.php?*messages*
// @exclude        *game/index.php?page=ingame&component=galaxy*
// @license         MIT
// @grant        GM_addStyle
// @run-at       document-start
// ==/UserScript==

let redirect = localStorage.getItem('ogl-redirect');
if(redirect && redirect.indexOf('https') > -1)
{
    localStorage.setItem('ogl-redirect', false);
    window.location.href = redirect;
}

// goodbye tooltips
(function goodbyeTipped()
{
    if(typeof Tipped !== 'undefined')
    {
        Tipped =
        {
            create:function() { return false; },
            read:function() { return false; },
            hide:function() { return false; },
            remove:function() { return false; },
            show:function() { return false; },
            hideAll:function() { return false; },
            visible:function() { return false; },
            refresh:function() { return false; },
        };
    }
    else requestAnimationFrame(() => goodbyeTipped());
})();

class OGLight
{
    constructor()
    {
        this.rawURL = new URL(window.location.href);
        this.page = this.rawURL.searchParams.get('component') || this.rawURL.searchParams.get('page');
        this.mode = this.rawURL.searchParams.get('oglMode') || 0; // 0=default; 1=transpo; 2=lock; 3=autoHarvest; 4=raid;
        this.ecoSpeed = document.querySelector('head meta[name="ogame-universe-speed"]').getAttribute('content');
        this.planetList = document.querySelectorAll('.smallplanet');
        this.language = window.location.host.indexOf('-fr.ogame.gameforge.com') > -1 ? 0 : 1; // 0=fr; 1=en;
        this.isMobile = ('ontouchstart' in document.documentElement);
        this.highlighted = false;
        this.tooltipList = {};

        // current planet
        this.current = {};
        this.current.planet = (document.querySelector('.smallplanet .active') || document.querySelector('.smallplanet .planetlink')).parentNode;
        this.current.coords = this.current.planet.querySelector('.planet-koords').textContent.slice(1, -1);
        this.current.hasMoon = this.current.planet.querySelector('.moonlink') ? true : false;
        this.current.isMoon = this.current.hasMoon && this.current.planet.querySelector('.moonlink.active') ? true : false;

        // get data & init default values
        this.json = JSON.parse(localStorage.getItem('ogl-data')) || {};
        this.json.tech114 = this.json.tech114 || 0;
        this.json.ptFret = this.json.ptFret || 5000;
        this.json.gtFret = this.json.gtFret || 25000;
        this.json.pfFret = this.json.pfFret || 10000;
        this.json.autoHarvest = this.json.autoHarvest || ['0:0:0', 3];
        this.json.myMines = this.json.myMines || {};
        this.json.myActivities = this.json.myActivities || {};
        this.json.sideStalk = this.json.sideStalk || false;
        this.json.markers = this.json.markers || {};
        this.json.locked = this.json.locked || {};
        this.json.targetTabs = this.json.targetTabs || {g:1, s:0};
        this.json.spyProbes = this.json.spyProbes || 5;

        // user options
        this.json.options = this.json.options || {};
        this.json.options.fret = this.json.options.fret || 202;
        this.json.options.harvestMission = this.json.options.harvestMission || 3;
        this.json.options.spyFilter = this.json.options.spyFilter || '$';
        this.json.options.rvalLimit = this.json.options.rvalLimit || 400000 * this.ecoSpeed;
        this.json.options.headerDisabled = this.json.options.headerDisabled || {};
        this.json.options.spyTableEnable = this.json.options.spyTableEnable === false ? false : true;
        this.json.options.compactViewEnable = this.json.options.compactViewEnable === false ? false : true;
        this.json.options.autoDeleteEnable = this.json.options.autoDeleteEnable === true ? true : false;
        this.json.options.kept = this.json.options.kept || [0,0,0];
        this.json.options.hiddenTargets = this.json.options.hiddenTargets || {};

        this.start();
    }

    start()
    {
        if(this.page == 'fleetdispatch')
        {
            fleetDispatcher.apiTechData.forEach(tech =>
            {
                if(tech[0] == 114) this.json.tech114 = tech[1];
                if(tech[0] == 111) this.json.tech111 = tech[1];
            });

            this.json.ptFret = fleetDispatcher.fleetHelper.shipsData[202].baseCargoCapacity;
            this.json.gtFret = fleetDispatcher.fleetHelper.shipsData[203].baseCargoCapacity;
            this.json.pfFret = fleetDispatcher.fleetHelper.shipsData[219].baseCargoCapacity;

            this.json.playerClass = fleetDispatcher.apiCommonData[1][1];

            this.saveData();

            this.current.resources =
            {
                metal:  fleetDispatcher.metalOnPlanet,
                crystal:  fleetDispatcher.crystalOnPlanet,
                deut:  fleetDispatcher.deuteriumOnPlanet,
            }
        }

        this.sideOptions();
        this.neededCargo();
        this.preselectShips();
        this.keepResources();
        this.harvest();
        this.autoHarvest();
        this.expedition();
        this.quickPlanetList();
        this.timers();
        this.marker();
        this.targetList();
        this.sideStalk();
        this.checkDebris();
        this.spyTable();
        this.lock();
        this.sideLock();
        this.flyingResources();

        // util.
        this.missingEnergy();
        this.minesLevel();
        this.highlightTarget();
        this.toggleImage();
        this.checkInputs();
        this.keyboardActions();
        this.betterTooltip();
        this.utilities();
        this.loopUtilities();
        this.checkResources();
    }

    sideOptions()
    {
        let harvestOptions = this.createDOM('div', {'class':'ogl-harvestOptions'});
        let container = document.querySelector('#myPlanets') || document.querySelector('#myWorlds');
        container.prepend(harvestOptions);

        let syncOption = harvestOptions.appendChild(this.createDOM('div', {'class':'ogl-option ogl-syncOption tooltipLeft', 'title':this.getTranslatedText(0)}, '{}'));
        syncOption.addEventListener('click', () => this.importExport());

        harvestOptions.appendChild(this.createDOM('a', {'class':'ogl-option ogl-targetIcon tooltipLeft', 'title':this.getTranslatedText(1)}));

        // switch between PT/GT
//        let cargo = harvestOptions.appendChild(this.createDOM('div', {'class':'ogl-option ogl-defaultCargo tooltipLeft', 'title':this.getTranslatedText(2)}, this.getTranslatedText(16)));
//        if(this.json.options.fret == 202)
//        {
//            cargo.innerHTML = this.getTranslatedText(15);
//            cargo.classList.add('ogl-smallCargo');
//        }
//        cargo.addEventListener('click', () =>
//        {
//            this.json.options.fret = this.json.options.fret == 202 ? 203 : 202;
//            this.saveData();
//            document.location.reload();
//        });
//
//         switch between statio/transpo
//        let mission = harvestOptions.appendChild(this.createDOM('div', {'class':'ogl-option ogl-harvestMission tooltipLeft', 'title':this.getTranslatedText(3)}));
//        if(this.json.options.harvestMission == 3) mission.classList.add('ogl-transpoIcon');
//        mission.addEventListener('click', () =>
//        {
//          let oldMission = this.json.options.harvestMission;
//            this.json.options.harvestMission = this.json.options.harvestMission == 3 ? 4 : 3;
//
//            this.saveData();
//            window.location.href = window.location.href.replace(`&mission=${oldMission}`, `&mission=${this.json.options.harvestMission}`);
//        });
//
      // harvest from planets
        let autoHarvestPlanet = harvestOptions.appendChild(this.createDOM('div', {'class':'ogl-option ogl-autoHarvest ogl-autoHarvestPlanet tooltipLeft', 'title':this.getTranslatedText(4)}));
        if(this.mode == 3) autoHarvestPlanet.classList.add('ogl-active');

        autoHarvestPlanet.addEventListener('click', () =>
        {
            this.openPlanetList((planet) =>
            {
                this.json.autoHarvest = [planet.galaxy + ':' + planet.system + ':' + planet.position, planet.type];
                this.saveData();
                let link = `?page=ingame&component=fleetdispatch&galaxy=${planet.galaxy}&system=${planet.system
                }&position=${planet.position}&type=${planet.type}&mission=${this.json.options.harvestMission}&oglMode=3`;
               window.location.href = 'https://' + window.location.host + window.location.pathname + link;
            });
        });
    }

    neededCargo()
    {
        if(this.page == 'fleetdispatch')
        {
            shipsOnPlanet.forEach(ship =>
            {
                if(ship.id == 202 || ship.id == 203)
                {
                    let min =
                    {
                        metal : Math.max(0, fleetDispatcher.metalOnPlanet - this.json.options.kept[0]),
                        crystal : Math.max(0, fleetDispatcher.crystalOnPlanet - this.json.options.kept[1]),
                        deut : Math.max(0, fleetDispatcher.deuteriumOnPlanet - this.json.options.kept[2])
                    }

                    let total = min.metal + min.crystal + min.deut;

                    let amount = this.calcNeededShips({'fret':ship.id, 'resources':total});
                    let span = this.createDOM('span', {class:'ogl-needed'}, amount.toLocaleString('de-DE'));
                    document.querySelector(`.technology[data-technology="${ship.id}"]`).appendChild(span);

                    // add needed buttons
                    span.addEventListener('click', event =>
                    {
                        event.stopPropagation();
                        document.querySelector('#resetall').click();
                        this.selectShips(ship.id, amount);
                    });
                }
            });
        }
    }

    fillFret(params)
    {
        params = params || {};

        if(params.resources)
        {
            let min =
            {
                metal: Math.min(params.resources.metal, this.current.resources.metal),
                crystal: Math.min(params.resources.crystal, this.current.resources.crystal),
                deut: Math.min(params.resources.deut, this.current.resources.deut - fleetDispatcher.getConsumption()),
            }

            let capacity = fleetDispatcher.getCargoCapacity();

            fleetDispatcher.cargoDeuterium = Math.min(min.deut, capacity);
            fleetDispatcher.cargoCrystal = Math.min(min.crystal, capacity - fleetDispatcher.cargoDeuterium);
            fleetDispatcher.cargoMetal = Math.min(min.metal, capacity - fleetDispatcher.cargoDeuterium - fleetDispatcher.cargoCrystal);
        }
    }

    harvest()
    {
        if(this.page == 'fleetdispatch')
        {
            if(this.mode == 1)
            {
                let total = fleetDispatcher.metalOnPlanet + fleetDispatcher.crystalOnPlanet + fleetDispatcher.deuteriumOnPlanet;
                this.selectShips(this.json.options.fret, this.calcNeededShips({'resources':total}));
                document.querySelector('#allresources').click();
            }
        }

        // buttons action on click
        let btnAction = (event, coords, type) =>
        {
            event.preventDefault();
            event.stopPropagation();

            let link = `?page=ingame&component=fleetdispatch&galaxy=${coords[0]}&system=${coords[1]
            }&position=${coords[2]}&type=${type}&mission=${this.json.options.harvestMission
            }&oglMode=1`;

            window.location.href = 'https://' + window.location.host + window.location.pathname + link;
        }

        // planet & moon harvest icons
        this.planetList.forEach(planet =>
        {
            let coords = planet.querySelector('.planet-koords').textContent.slice(1, -1).split(':');

            if(this.current.coords != coords.join(':') || this.current.isMoon)
            {
                let btn = planet.querySelector('.planetlink').appendChild(this.createDOM('div', {'class':'ogl-harvest ogl-planet'}));
                btn.addEventListener('click',  event => btnAction(event, coords, 1));
            }

            let moon = planet.querySelector('.moonlink');

            if(moon)
            {
                moon.classList.remove('tooltipLeft');
                moon.classList.add('tooltipRight');

                if(this.current.coords == coords.join(':') && this.current.isMoon) return;

                let btn = planet.querySelector('.moonlink').appendChild(this.createDOM('button', {'class':'ogl-harvest ogl-moon'}));
                btn.addEventListener('click', event => btnAction(event, coords, 3));
            }
        });
    }

    openPlanetList(callcback)
    {
        let container = this.createDOM('div', {'class':'ogl-dialogContainer ogl-quickLinks'}, '<h1>'+this.getTranslatedText(10)+'</h1>');

        let buildButton = (planet, id, galaxy, system, position, type) =>
        {
            let data = {'id':id, 'galaxy':galaxy, 'system':system, 'position':position, 'type':type};

            let div = container.appendChild(this.createDOM('div'));

            if(type == 1) div.classList.add('ogl-quickPlanet');
            else div.classList.add('ogl-quickMoon');

            div.addEventListener('click', () =>  callcback(data));

            if((planet == this.current.planet && !this.current.isMoon && type == 1)
            || (planet == this.current.planet && this.current.isMoon && type == 3))
            {
                div.classList.add('ogl-quickEmpty');
            }

            return div;
        }

        this.planetList.forEach(planet =>
        {
            let coords = planet.querySelector('.planet-koords').textContent.slice(1, -1).split(':');

            // planet
            let btn = buildButton(planet, new URL(planet.querySelector('.planetlink').href).searchParams.get('cp'),
                coords[0], coords[1], coords[2], 1);

            btn.innerHTML = `[${coords.join(':')}] ${planet.querySelector('.planet-name').textContent}`;

            // moon
            if(planet.querySelector('.moonlink'))
            {
                let btn = buildButton(planet, new URL(planet.querySelector('.moonlink').href).searchParams.get('cp'),
                    coords[0], coords[1], coords[2], 3);

                btn.innerHTML = '<figure class="planetIcon moon"></figure>';
            }
            else container.appendChild(this.createDOM('div', {'class':'ogl-quickEmpty'}));
        });

        this.popup(false, container);
    }

    autoHarvest()
    {
        this.planetList.forEach((p, index) =>
        {
            p.setAttribute('data-redirect', index);

            if(this.mode == 3)
            {
                if(p.querySelector('.planet-koords').textContent.slice(1, -1) == this.json.autoHarvest[0])
                {
                    let target = this.json.autoHarvest[1] == 3 ? p.querySelector('.moonlink') : p.querySelector('.planetlink');
                    target.classList.add('ogl-target');
                }
            }
        });

        let currentIndex = parseInt(this.current.planet.getAttribute('data-redirect'));
        let nextIndex = currentIndex + 1 >= this.planetList.length ? 0 : currentIndex + 1;

        this.next = {};
        this.next.planet = document.querySelector(`.smallplanet[data-redirect="${nextIndex}"]`);
        this.next.coords = this.next.planet.querySelector('.planet-koords').textContent.slice(1, -1);
        this.next.id = this.next.planet.getAttribute('id').replace('planet-', '');
        this.next.hasMoon = this.next.planet.querySelector('.moonlink') ? true : false;

        if(this.page == 'fleetdispatch')
        {
            if(this.mode == 3)
            {
                let coords = this.json.autoHarvest[0].split(':');
                let type = this.json.autoHarvest[1];
                let id = this.next.id;

                if(this.current.isMoon && this.next.hasMoon)
                {
                    let url = new URL(this.next.planet.querySelector('.moonlink').href);
                    id = url.searchParams.get('cp');
                }

                let link = `?page=ingame&component=fleetdispatch&galaxy=${coords[0]}&system=${coords[1]
                }&position=${coords[2]}&type=${type}&mission=${this.json.options.harvestMission}&cp=${id}&oglMode=${this.mode}`;
                link = 'https://' + window.location.host + window.location.pathname + link;

                let skip = document.querySelector('#fleet1 #planet').appendChild(this.createDOM('button', {'class':'btn_blue ogl-skip'}, this.getTranslatedText(9)));
                skip.addEventListener('click', () => window.location.href = link);

                let needed = document.querySelector(`.technology[data-technology="${this.json.options.fret}"] .ogl-needed`);
                if(needed) needed.click();

                document.querySelector('#allresources').click();

                document.querySelector('#sendFleet').addEventListener('click', () =>
                {
                    localStorage.setItem('ogl-redirect', link);
                });

                document.addEventListener('keydown', event =>
                {
                    if(event.keyCode === 13 && fleetDispatcher.currentPage == 'fleet3')
                    {
                        localStorage.setItem('ogl-redirect', link);
                    }
                });
            }
        }
    }

    expedition()
    {
        if(this.page == 'fleetdispatch')
        {
            let parser = new DOMParser();
            let http = new XMLHttpRequest();
            http.open('GET', 'https://' + window.location.host + '/api/serverData.xml');
            http.send();
            http.onreadystatechange = () =>
            {
                if(http.readyState === XMLHttpRequest.DONE && http.status === 200)
                {
                    let xml = parser.parseFromString(http.responseText, 'text/xml');
                    let topScore = parseInt(xml.querySelector('topScore').innerHTML);

                    // https://board.origin.ogame.gameforge.com/index.php/Thread/872-Guide-12-Expedition-guide/

                    let maxTotal = 0;
                    let minPT, minGT = 0;

                    if(topScore < 10000)
                    {
                        maxTotal = 40000;
                        minPT = 273;
                        minGT = 91;
                    }
                    else if(topScore < 100000)
                    {
                        maxTotal = 500000;
                        minPT = 423;
                        minGT = 141;
                    }
                    else if(topScore < 1000000)
                    {
                        maxTotal = 1200000;
                        minPT = 423;
                        minGT = 191;
                    }
                    else if(topScore < 5000000)
                    {
                        maxTotal = 1800000;
                        minPT = 423;
                        minGT = 91;
                    }
                    else if(topScore < 25000000)
                    {
                        maxTotal = 2400000;
                        minPT = 573;
                        minGT = 191;
                    }
                    else if(topScore < 50000000)
                    {
                        maxTotal = 3000000;
                        minPT = 723;
                        minGT = 241;
                    }
                    else if(topScore < 75000000)
                    {
                        maxTotal = 3600000;
                        minPT = 873;
                        minGT = 291;
                    }
                    else if(topScore < 100000000)
                    {
                        maxTotal = 4200000;
                        minPT = 1023;
                        minGT = 341;
                    }
                    else
                    {
                        maxTotal = 5000000;
                        minPT = 1223;
                        minGT = 417;
                    }

                    maxTotal = this.json.playerClass == 3 ? maxTotal * 3 * this.ecoSpeed : maxTotal * 2;

                    let maxPT = Math.max(minPT, this.calcNeededShips({'fret':202, 'resources':maxTotal}));
                    let maxGT = Math.max(minGT, this.calcNeededShips({'fret':203, 'resources':maxTotal}));

                    if(!document.querySelector('#allornone .allornonewrap')) return;

                    let ptExpe = document.querySelector('#allornone .secondcol').appendChild(this.createDOM('button', {class:'ogl-prefab ogl-ptexpe'}));
                    let gtExpe = document.querySelector('#allornone .secondcol').appendChild(this.createDOM('button', {class:'ogl-prefab ogl-gtexpe'}));

                    let coords = this.current.coords.split(':');

                    [ptExpe, gtExpe].forEach(btn =>
                    {
                        btn.addEventListener('click', () =>
                        {
                            document.querySelector('#resetall').click();

                            let type = btn == ptExpe ? 202 : 203;
                            let count = btn == ptExpe ? maxPT : maxGT;

                            let prio = [218, 213, 211, 215, 207];
                            let bigship = 0;

                            prio.forEach(shipID =>
                            {
                                if(bigship == 0 && document.querySelector(`.technology[data-technology="${shipID}"] .amount`).getAttribute('data-value') > 0)
                                {
                                    bigship = shipID;
                                }
                            });

                            shipsOnPlanet.forEach(ship =>
                            {
                                if(ship.id == type) this.selectShips(ship.id, count);
                                else if(ship.id == bigship) this.selectShips(ship.id, 1);
                                else if(ship.id == 210) this.selectShips(ship.id, 1);
                                else if(ship.id == 219) this.selectShips(ship.id, 1);
                            });

                            fleetDispatcher.targetPlanet.galaxy = coords[0];
                            fleetDispatcher.targetPlanet.system = coords[1];
                            fleetDispatcher.targetPlanet.position = 16;
                            fleetDispatcher.targetPlanet.type = 1;
                            fleetDispatcher.targetPlanet.name = '-';
                            fleetDispatcher.mission = 15;
                            fleetDispatcher.refresh();
                        });
                    });
                }
            }
        }
    }

    quickPlanetList()
    {
        if(this.page == 'fleetdispatch' && fleetDispatcher)
        {
            if(!document.querySelector("#shortcuts .dropdown")) return;

            let btn = document.querySelector('#shortcuts span').appendChild(this.createDOM('btn', {'class':'ogl-quickBtn'}, '-'));
            let container = this.createDOM('div', {'class':'ogl-dialogContainer ogl-quickLinks'});

            container.addEventListener('click', event =>
            {
                if(!event.target.href)
                {
                    event.stopPropagation();
                    event.preventDefault();
                }
            });

            btn.addEventListener('click', () =>
            {
                this.openPlanetList((planet) =>
                {
                    fleetDispatcher.targetPlanet = planet;
                    fleetDispatcher.refresh();
                    document.querySelector('.ogl-dialogOverlay').classList.remove('ogl-active');
                    document.querySelector('#continueToFleet3').focus();
                });
            });
        }
    }

    timers()
    {
        let now = Date.now();

        if(!this.json.myActivities[this.current.coords]) this.json.myActivities[this.current.coords] = [0, 0];

        let planetActivity = this.json.myActivities[this.current.coords][0];
        let moonActivity = this.json.myActivities[this.current.coords][1];

        if(this.current.isMoon) moonActivity = now;
        else planetActivity = now;

        this.json.myActivities[this.current.coords] = [planetActivity, moonActivity];
        this.saveData();

        this.planetList.forEach(planet =>
        {
            let coords = planet.querySelector('.planet-koords').textContent.slice(1, -1);
            let timers = this.json.myActivities[coords] || [0,0];

            let pTimer = planet.querySelector('.planetlink').appendChild(this.createDOM('div', {'class':'ogl-timer ogl-short ogl-medium',
                'data-timer':Math.min(Math.round((now - timers[0]) / 60000), 60)}));

            this.updateTimer(pTimer);
            setInterval(() => this.updateTimer(pTimer, true), 60000);

            if(planet.querySelector('.moonlink'))
            {
                let mTimer = planet.querySelector('.moonlink').appendChild(this.createDOM('div', {'class':'ogl-timer ogl-short ogl-medium',
                    'data-timer':Math.min(Math.round((now - timers[1]) / 60000), 60)}));

                this.updateTimer(mTimer);
                setInterval(() => this.updateTimer(mTimer, true), 60000);
            }
        });
    }

    updateTimer(element, increment)
    {
        let time = parseInt(element.getAttribute('data-timer'));
        if(time <= 61)
        {
            if(increment)
            {
                time++;
                element.setAttribute('data-timer', time);
            }

            element.title = time;

            if(time >= 30) { element.classList.remove('ogl-medium'); }
            if(time >= 15) { element.classList.remove('ogl-short'); };
        }
    }

    minesLevel()
    {
        if(this.page == 'supplies' && !this.current.isMoon)
        {
            let targetMetal = document.querySelector('.technology.metalMine .targetlevel');
            let targetCrystal = document.querySelector('.technology.crystalMine .targetlevel');
            let targetDeut = document.querySelector('.technology.deuteriumSynthesizer .targetlevel');

            let metal = targetMetal ? '('+targetMetal.getAttribute('data-value')+')' : document.querySelector('.technology.metalMine .level').getAttribute('data-value');
            let crystal = targetCrystal ? '('+targetCrystal.getAttribute('data-value')+')' : document.querySelector('.technology.crystalMine .level').getAttribute('data-value');
            let deut = targetDeut ? '('+targetDeut.getAttribute('data-value')+')' : document.querySelector('.technology.deuteriumSynthesizer .level').getAttribute('data-value');

            this.json.myMines[this.current.coords] = {'metal':metal, 'crystal':crystal, 'deut':deut};
            this.saveData();
        }

        this.planetList.forEach(planet =>
        {
            let coords = planet.querySelector('.planet-koords').textContent.slice(1, -1);

            if(!this.json.myMines[coords]) return;

            let metal = this.json.myMines[coords].metal;
            let crystal = this.json.myMines[coords].crystal;
            let deut = this.json.myMines[coords].deut;

            let div = this.createDOM('div', {'class':'ogl-mines'});
            div.textContent = `${metal}-${crystal}-${deut}`;
            planet.querySelector('.planetlink').appendChild(div);
        });
    }

    marker()
    {
        if(this.page == 'galaxy')
        {
            this.FPSLoop('marker');

            let galaxytable = document.querySelector('#galaxytable');

            if(!galaxytable || galaxytable.classList.contains('ogl-markerReady')) return;
            galaxytable.classList.add('ogl-markerReady');

            // move planets
            /*document.querySelectorAll('td.microplanet').forEach(planet =>
            {
                planet.parentNode.insertBefore(planet, planet.parentNode.querySelector('td.moon'));
            });*/

            let coords = document.querySelector('#galaxy_input').value;
            coords += ':' + document.querySelector('#system_input').value;

            document.querySelectorAll('#galaxytable tbody .allytag').forEach((element, index) =>
            {
                let id = coords + ':' + (parseInt(index) + 1);
                let colors = this.createDOM('div', {'class':'ogl-colors', 'data-coords':id});
                element.appendChild(colors);

                this.addMarkerUI(id, colors);
            });

            document.querySelectorAll('#galaxytable tbody tr').forEach((element, index) =>
            {
                let id = coords + ':' + (parseInt(index) + 1);

                if(this.json.markers[id])
                {
                    element.classList.add('ogl-marked');
                    element.setAttribute('data-marked', this.json.markers[id]);
                }
            });
        }
        else if(this.page == 'messages')
        {
            document.querySelectorAll('.ogl-colors').forEach(element =>
            {
                this.addMarkerUI(element.getAttribute('data-coords'), element);
            });

            document.querySelectorAll('.ogl-spyTable tr').forEach((element, index) =>
            {
                if(index > 0)
                {
                    let coords = element.querySelector('.ogl-colors').getAttribute('data-coords');

                    if(this.json.markers[coords])
                    {
                        element.classList.add('ogl-marked');
                        element.setAttribute('data-marked', this.json.markers[coords]);
                    }
                }
            });
        }
    }

    targetList()
    {
        let targetIcon = document.querySelector('.ogl-harvestOptions .ogl-targetIcon');

        if(!targetIcon.classList.contains('ogl-targetsReady'))
        {
            targetIcon.classList.add('ogl-targetsReady');
            targetIcon.addEventListener('click', () => this.popup(header, content));
        }

        // popup header
        let header = this.createDOM('div');
        header.innerHTML = '<h1>'+this.getTranslatedText(13)+'</h1>';

        ['red', 'yellow', 'green', 'blue', 'violet', 'gray'].forEach(color =>
        {
            let toggle = this.createDOM('div', {'class':'tooltip ogl-toggle', 'title':this.getTranslatedText(5)});
            toggle.setAttribute('data-toggle', color);
            header.appendChild(toggle);

            if(!this.json.options.hiddenTargets[color]) toggle.classList.add('ogl-active');

            toggle.addEventListener('click', () =>
            {
                this.json.options.hiddenTargets[color] = this.json.options.hiddenTargets[color] ? false : true;
                this.saveData();

                if(this.json.options.hiddenTargets[color]) toggle.classList.remove('ogl-active');
                else toggle.classList.add('ogl-active');

                content.querySelectorAll(`.ogl-targetItem[data-marked="${color}"]`).forEach(planet =>
                {
                    if(this.json.options.hiddenTargets[color]) planet.classList.add('ogl-colorHidden');
                    else planet.classList.remove('ogl-colorHidden');
                });

                checkEmpty();
            });
        });

        header.appendChild(this.createDOM('hr'));

        // popup content
        let content = this.createDOM('div', {'class':'ogl-dialogContainer ogl-stalkContainer'});
        let galaxyTabList = header.appendChild(this.createDOM('div', {'class':'ogl-tabList ogl-galaxyTabList'}));
        let systemTabList = header.appendChild(this.createDOM('div', {'class':'ogl-tabList ogl-systemTabList'}));
        let planetList = content.appendChild(this.createDOM('div', {'class':'ogl-stalkPlanets'}))

        let checkEmpty = () =>
        {
            for(let g=1; g<=10; g++)
            {
                let childrenList = content.querySelectorAll(`.ogl-targetItem[data-galaxy="${g}"]:not(.ogl-colorHidden)`);

                if(childrenList.length > 0)
                {
                    header.querySelector(`.ogl-tab[data-galaxy="${g}"]`).classList.remove('ogl-isEmpty');
                }
                else
                {
                    header.querySelector(`.ogl-tab[data-galaxy="${g}"]`).classList.add('ogl-isEmpty');
                }
            }

            for(let s=0; s<step * 10; s+=step)
            {
                let childrenList = content.querySelectorAll(`.ogl-targetItem[data-galaxy="${this.json.targetTabs.g}"][data-system="${s}"]:not(.ogl-colorHidden)`);

                if(childrenList.length > 0)
                {
                    header.querySelector(`.ogl-tab[data-system="${s}"]`).classList.remove('ogl-isEmpty');
                }
                else
                {
                    header.querySelector(`.ogl-tab[data-system="${s}"]`).classList.add('ogl-isEmpty');
                }
            }
        }

        // cleanup saved coords
        for(let coords in this.json.markers)
        {
            if(this.json.markers[coords] == '')
            {
                delete this.json.markers[coords];
            }
        };

        // sort coords
        let keys = Object.keys(this.json.markers).sort((a, b) =>
        {
            let coordsA = a.split(':').map(x => x.padStart(3, '0')).join('');
            let coordsB = b.split(':').map(x => x.padStart(3, '0')).join('');

            return coordsA - coordsB;
        });

        let step = 50;

        // system buttons
        for(let i=0; i<step * 10; i+=step)
        {
            let sTab = systemTabList.appendChild(this.createDOM('div', {'class':'ogl-tab', 'data-system':i}, i));
            if(this.json.targetTabs.s == i) sTab.classList.add('ogl-active');

            sTab.addEventListener('click', event =>
            {
                header.querySelectorAll('.ogl-tab[data-system]').forEach(e => e.classList.remove('ogl-active'));
                event.target.classList.add('ogl-active');

                content.querySelectorAll(`.ogl-targetItem[data-system]`).forEach(planet =>
                {
                    planet.classList.add('ogl-systemHidden');

                    if(planet.getAttribute('data-system') == i)
                    {
                        planet.classList.remove('ogl-systemHidden');
                    }

                    this.json.targetTabs.s = i;
                    this.saveData();
                });
            });
        }

        // galaxy buttons
        for(let i=1; i<=10; i++)
        {
            let gTab = galaxyTabList.appendChild(this.createDOM('div', {'class':'ogl-tab', 'data-galaxy':i}, 'G'+i));
            if(this.json.targetTabs.g == i) gTab.classList.add('ogl-active');

            if(this.json.targetTabs.g == 0)
            {
                gTab.click();
            }

            gTab.addEventListener('click', event =>
            {
                header.querySelectorAll('.ogl-tab[data-galaxy]').forEach(e => e.classList.remove('ogl-active'));
                event.target.classList.add('ogl-active');

                content.querySelectorAll(`.ogl-targetItem[data-galaxy]`).forEach(planet =>
                {
                    planet.classList.add('ogl-galaxyHidden');

                    if(planet.getAttribute('data-galaxy') == i)
                    {
                        planet.classList.remove('ogl-galaxyHidden');
                    }
                });

                this.json.targetTabs.g = i;
                this.saveData();

                checkEmpty();
            });
        }

        // build ui
        keys.forEach(coords =>
        {
            if(this.json.markers[coords])
            {
                let splitted = coords.split(':');
                let a = this.createDOM('a', {'class':'ogl-marked ogl-targetItem'}, `${coords}`);

                if(this.json.markers[coords])
                {
                    a.setAttribute('data-marked', this.json.markers[coords]);
                    a.setAttribute('data-coords', coords);
                    a.setAttribute('data-galaxy', splitted[0]);
                    a.setAttribute('data-system', Math.floor(splitted[1] / step) * step);
                }

                let atk = a.appendChild(this.createDOM('div', {'class':'ogl-atk tooltip', 'title':this.getTranslatedText(22)}));

                atk.addEventListener('click', () =>
                {
                    event.preventDefault();
                    event.stopPropagation();

                    let needed = this.calcNeededShips({'resources':this.json.options.rvalLimit});
                    let link = `?page=ingame&component=fleetdispatch&galaxy=${splitted[0]}&system=${splitted[1]
                        }&position=${splitted[2]}&type=1&mission=1&am${this.json.options.fret}=${needed}`;
                    link = 'https://' + window.location.host + window.location.pathname + link;

                    if(event.ctrlKey) window.open(link, '_blank');
                    else
                    {
                        if(this.page == 'fleetdispatch')
                        {
                            this.selectShips(this.json.options.fret, needed);
                            fleetDispatcher.targetPlanet = {'galaxy':splitted[0], 'system':splitted[1], 'position':splitted[2], 'type':1, 'name':'-'};
                            fleetDispatcher.mission = 1;
                            fleetDispatcher.refresh();

                            document.querySelector('.ogl-dialogOverlay').classList.remove('ogl-active');

                            if(fleetDispatcher.currentPage == 'fleet1') document.querySelector('#continueToFleet2').focus();
                            else if(fleetDispatcher.currentPage == 'fleet2') document.querySelector('#continueToFleet3').focus();
                            else document.querySelector('#sendFleet').focus();
                        }
                        else window.location.href = link;
                    }
                });


                a.addEventListener('click', () =>
                {
                    let link = `?page=ingame&component=galaxy&galaxy=${splitted[0]}&system=${splitted[1]
                    }&position=${splitted[2]}`;
                    link = 'https://' + window.location.host + window.location.pathname + link;

                    if(event.ctrlKey) window.open(link, '_blank');
                    else
                    {
                        if(this.page == 'galaxy')
                        {
                            document.querySelector('#galaxy_input').value = splitted[0];
                            document.querySelector('#system_input').value = splitted[1];
                            submitForm();
                            this.highlighted = coords.join(':');
                        }
                        else window.location.href = link;
                    }
                });

                if(this.json.options.hiddenTargets[this.json.markers[coords]])
                {
                    a.classList.add('ogl-colorHidden');
                }

                if(this.json.targetTabs.g != splitted[0])
                {
                    a.classList.add('ogl-galaxyHidden');
                }

                if(this.json.targetTabs.s != Math.floor(splitted[1] / step) * step)
                {
                    a.classList.add('ogl-systemHidden');
                }

                planetList.appendChild(a);
            }
        });
        checkEmpty();
    }

    addMarkerUI(coords, parent)
    {
        let div = this.createDOM('div', {'class':'ogl-colorChoice'});

        ['red', 'yellow', 'green', 'blue', 'violet', 'gray'].forEach(color =>
        {
            let circle = div.appendChild(this.createDOM('div', {'data-marker':color}));
            div.appendChild(circle);

            if(this.json.markers[coords] && this.json.markers[coords] == color)
            {
                circle.classList.add('ogl-active');
            }

            circle.addEventListener('click', () =>
            {
                div.querySelectorAll('div[data-marker]').forEach(e => e.classList.remove('ogl-active'));

                if(this.json.markers[coords] && this.json.markers[coords] == color)
                {
                    delete this.json.markers[coords];
                    parent.closest('tr').removeAttribute('data-marked');
                }
                else
                {
                    this.json.markers[coords] = color;
                    circle.classList.add('ogl-active');
                    parent.closest('tr').setAttribute('data-marked', color);
                }

                document.querySelector('.ogl-tooltip').classList.remove('ogl-active');

                this.saveData();
                this.targetList();
                this.sideStalk();
            });
        });

        let eventAction = this.isMobile ? 'touchstart' : 'mouseenter';

        parent.addEventListener(eventAction, () =>
        {
            this.tooltip(parent, div);
        });
    }

    stalk(sender)
    {
        if(this.page == 'galaxy')
        {
            sender.classList.add('ogl-stalkReady');

            let eventAction = this.isMobile ? 'touchstart' : 'mouseenter';

            let galaxyPlayer = {};
            galaxyPlayer.id = sender.getAttribute('rel');

            let content = document.querySelector('#' + galaxyPlayer.id);

            galaxyPlayer.name = content.querySelector('h1 span').textContent;
            galaxyPlayer.rank = content.querySelector('.rank a') ? content.querySelector('.rank a').textContent : '0';
            galaxyPlayer.links = {};
            galaxyPlayer.planets = [];
            galaxyPlayer.ready = false;

            content.querySelectorAll('a').forEach(link =>
            {
                if(link.href.indexOf('page=highscore') > -1) galaxyPlayer.links.highscore = link.href;
                else if(link.href.indexOf('page=chat') > -1) galaxyPlayer.links.chat = link.href;
                else if(link.classList.contains('js_openChat')) galaxyPlayer.links.chat = link.href;
                else if(link.href.indexOf('component=buddies') > -1) galaxyPlayer.links.buddy = link.href;
                else if(link.href.indexOf('page=ignorelist') > -1) galaxyPlayer.links.ignore = link.href;
            });

            galaxyPlayer.content = this.createDOM('div');
            galaxyPlayer.content.innerHTML =
            `
                <h1>${galaxyPlayer.name} <a href="${galaxyPlayer.links.highscore || ''}" class="ogl-ranking">#${galaxyPlayer.rank || 'b'}</a></h1>
                <hr>
                <a href="${galaxyPlayer.links.chat || ''}" class="icon icon_chat sendMail js_openChat" data-playerid="${galaxyPlayer.id}"></a>
                <a href="${galaxyPlayer.links.buddy || ''}" class="icon icon_user overlay buddyrequest"></a>
                <a href="${galaxyPlayer.links.ignore || ''}" class="icon icon_against"></a>
            `;

            sender.appendChild(this.createDOM('a', {'href':galaxyPlayer.links.highscore || '', 'class':'ogl-ranking'}, ('#' + galaxyPlayer.rank) || 'b'));

            let count = galaxyPlayer.content.appendChild(this.createDOM('span', {'class':'ogl-right'}));
            galaxyPlayer.content.appendChild(this.createDOM('hr'));
            let list = galaxyPlayer.content.appendChild(this.createDOM('div', {'class':'ogl-stalkPlanets'}));
            let date = galaxyPlayer.content.appendChild(this.createDOM('div', {'class':'ogl-fullGrid ogl-right ogl-date'}));
            let sideStalk = galaxyPlayer.content.appendChild(this.createDOM('a', {'class':'ogl-pin'}));
            sideStalk.addEventListener('click', () => this.sideStalk(galaxyPlayer));

            sender.addEventListener(eventAction, () =>
            {
                this.tooltip(sender, galaxyPlayer.content, false, {}, 200);

                if(galaxyPlayer.ready)
                {
                    list.innerHTML = '';
                    this.updateStalk(galaxyPlayer).forEach(e => list.appendChild(e));
                }
                else
                {
                    let http = this.callAPI('https://' + window.location.host + '/api/playerData.xml?id=' + galaxyPlayer.id.replace('player', ''));

                    http.onreadystatechange = () =>
                    {
                        if(http.readyState === XMLHttpRequest.DONE && http.status === 200)
                        {
                            let parser = new DOMParser();
                            let xml = parser.parseFromString(http.responseText, 'text/xml');
                            galaxyPlayer.planets = [];

                            Array.from(xml.querySelectorAll('planet')).forEach((planet, index) =>
                            {
                                let jsonPlanet = {};
                                jsonPlanet.name = planet.getAttribute('name');
                                jsonPlanet.coords = planet.getAttribute('coords');
                                jsonPlanet.hasMoon = planet.querySelector('moon') ? true : false;
                                jsonPlanet.isMain = index == 0 ? true : false;

                                galaxyPlayer.planets.push(jsonPlanet);
                            });

                            galaxyPlayer.planets.sort((a, b) =>
                            {
                                let coordsA = a.coords.split(':').map(x => x.padStart(3, '0')).join('');
                                let coordsB = b.coords.split(':').map(x => x.padStart(3, '0')).join('');

                                return coordsA - coordsB;
                            });

                            list.innerHTML = '';
                            this.updateStalk(galaxyPlayer).forEach(e => list.appendChild(e));

                            let timestamp = parseInt(xml.querySelector('playerData').getAttribute('timestamp'));
                            galaxyPlayer.date = date.innerHTML = new Date(timestamp * 1000).toLocaleDateString("fr-FR");

                            count.innerHTML = galaxyPlayer.planets.length + ' planet(s)';

                            galaxyPlayer.ready = true;
                        }
                    }
                }
            });
        }
    }

    updateStalk(galaxyPlayer)
    {
        let domArr = [];

        galaxyPlayer.planets.forEach(planet =>
        {
            let coords = planet.coords.split(':');

            let a = this.createDOM('a');
            a.appendChild(this.createDOM('span', {}, planet.coords));
            a.setAttribute('data-coords', planet.coords);

            if(planet.isMain)
            {
                a.classList.add('ogl-main');
                a.appendChild(this.createDOM('i', {}, 'PM'));
            }

            let mIcon = a.appendChild(this.createDOM('div', {'class':'ogl-moon'}));

            a.addEventListener('click', () =>
            {
                let link = `?page=ingame&component=galaxy&galaxy=${coords[0]}&system=${coords[1]
                }&position=${coords[2]}`;
                link = 'https://' + window.location.host + window.location.pathname + link;

                if(event.ctrlKey) window.open(link, '_blank');
                else
                {
                    if(this.page == 'galaxy')
                    {
                        document.querySelector('#galaxy_input').value = coords[0];
                        document.querySelector('#system_input').value = coords[1];
                        submitForm();
                        this.highlighted = coords.join(':');
                    }
                    else window.location.href = link;
                }
            });

            if(planet.hasMoon)
            {
                mIcon.classList.add('ogl-active');
            }

            let color = this.json.markers[planet.coords];

            if(color)
            {
                a.classList.add('ogl-marked');
                a.setAttribute('data-marked', color);
            }
            else
            {
                a.classList.remove('ogl-marked');
                a.removeAttribute('data-marked');
            }

            domArr.push(a);
        });

        return domArr;
    }

    sideStalk(galaxyPlayer)
    {
        if(galaxyPlayer)
        {
            this.json.sideStalk = JSON.stringify(galaxyPlayer);
            this.saveData();
        }

        if(this.json.sideStalk)
        {
            let sideStalk = document.querySelector('.ogl-sideStalk');
            let sidePlayer = galaxyPlayer || JSON.parse(this.json.sideStalk);

            if(!sideStalk)
            {
                sideStalk = document.querySelector('#rechts').appendChild(this.createDOM('div', {'class':'ogl-sideStalk'}));
            }

            sideStalk.innerHTML = `
                ${sidePlayer.name} #${sidePlayer.rank}
                <hr>
            `;

            let btn = sideStalk.appendChild(this.createDOM('a', {'class':'close-tooltip'}));
            btn.addEventListener('click', () =>
            {
                this.json.sideStalk = false;
                this.saveData();
                sideStalk.remove();
            });

            document.querySelector('.ogl-sideStalk > div') && document.querySelector('.ogl-sideStalk > div').remove();
            let container = sideStalk.appendChild(this.createDOM('div', {'class':'ogl-stalkPlanets'}));

            this.updateStalk(sidePlayer).forEach(dom => container.appendChild(dom));

            container.appendChild(this.createDOM('div', {'class':'ogl-right ogl-date'}, sidePlayer.date));
        }
    }

    checkDebris()
    {
        if(this.page == 'galaxy')
        {
            this.FPSLoop('checkDebris');

            document.querySelectorAll('.debris').forEach(element =>
            {
                let debris = element.querySelector('.ListLinks');
                if(debris && !debris.classList.contains('ogl-debrisReady'))
                {
                    debris.classList.add('ogl-debrisReady');
                    let total = 0;

                    debris.querySelectorAll('.debris-content').forEach(resources =>
                    {
                        let value = this.removeNumSeparator(resources.innerText.replace(/(\D*)/, ''));
                        total += parseInt(value);

                        element.querySelector('.debrisField').innerHTML += this.formatToUnits(value) + '<br>';
                    });

                    if(total > this.json.options.rvalLimit)
                    {
                        element.classList.add('ogl-active');
                    }
                }
            });

            let expeBox = document.querySelector('.expeditionDebrisSlotBox');
            if(expeBox && !expeBox.classList.contains('ogl-done'))
            {
                let content = expeBox.querySelectorAll('.ListLinks li');
                expeBox.classList.add('ogl-done');

                let scouts = content[2];
                let action = content[3];
                let res =
                [
                    content[0].textContent.replace(/(\D*)/, ''),
                    content[1].textContent.replace(/(\D*)/, '')
                ];

                expeBox.innerHTML = `
                    <img src="https://gf1.geo.gfsrv.net/cdnc5/fa3e396b8af2ae31e28ef3b44eca91.gif">
                    <div>
                        <div class="ogl-metal">${res[0]}</div>
                        <div class="ogl-crystal">${res[1]}</div>
                    </div>
                    <div>
                        <div>${scouts.textContent}</div>
                        <div>${action.outerHTML}</div>
                    </div>
                `;
            }
        }
    }

    spyTable()
    {
        if(this.page == 'fleetdispatch' && this.mode == 4)
        {
            let link = 'https://' + window.location.host + window.location.pathname + '?page=messages';

            document.querySelector('#sendFleet').addEventListener('click', () =>
            {
                localStorage.setItem('ogl-redirect', link);
            });

            let sent = false;

            document.addEventListener('keydown', event =>
            {
                if(!sent && event.keyCode === 13 && fleetDispatcher.currentPage == 'fleet3')
                {
                    localStorage.setItem('ogl-redirect', link);
                    sent = true;
                }
            });
        }

        if(this.page != 'messages') return;

        this.FPSLoop('spyTable');

        let tab = document.querySelector('#subtabs-nfFleet20');

        if(!tab || !tab.classList.contains('ui-tabs-active')
        || !document.querySelector('.pagination')
        || document.querySelector('.ogl-spyTable')) return;

        tab.classList.add('ogl-spyTableReady');

        let reportList = [];

        document.querySelectorAll('.msg').forEach(msg =>
        {
            if(!msg.querySelector('.msg_title')
            || !msg.querySelector('.msg_content .resspan')
            || msg.classList.contains('ogl-reportReady')) return;

            msg.classList.add('ogl-reportReady');

            let data = msg.querySelectorAll('.compacting');

            let rawDate = msg.querySelector('.msg_date').textContent.split(/\.| /g);
            let cleanDate = new Date(`${rawDate[2]}-${rawDate[1]}-${rawDate[0]} ${rawDate[3]}`);
            let deltaDate = Date.now() - cleanDate;
            let mins = deltaDate / 60000;
            let hours = mins / 60;

            if(!parseInt(data[0].querySelectorAll('span.fright')[0].textContent.match(/\d+/))) return;

            let report = {};
            report.attacked = msg.querySelector('.icon_attack img');
            report.type = msg.querySelector('figure.moon') ? 3 : 1;
            report.name = data[0].querySelectorAll('span[class^="status"]')[0].textContent.replace(/&nbsp;/g,'').trim();
            report.status = data[0].querySelectorAll('span[class^="status"]')[1].textContent.replace(/&nbsp;/g,'').trim();
            report.spy = msg.querySelector('a[onclick*="sendShipsWithPopup"]').getAttribute('onclick');
            report.activity = parseInt(data[0].querySelectorAll('span.fright')[0].textContent.match(/\d+/)[0]);
            report.coords = (/\[.*\]/g).exec(msg.querySelector('.msg_title').innerHTML)[0].slice(1, -1);
            report.coordsLink = msg.querySelector('.msg_title a').href;
            report.detail = msg.querySelector('.msg_actions a.fright').href;
            report.delete = msg.querySelector('.msg_head .fright a .icon_refuse');
            report.fleet = data[4].querySelectorAll('span').length > 0 ? this.cleanValue(data[4].querySelectorAll('span')[0].textContent.replace(/(\D*)/, '').split(' ')[0]) : "No Data";
            report.defense = data[4].querySelectorAll('span').length > 1 ? this.cleanValue(data[4].querySelectorAll('span')[1].textContent.replace(/(\D*)/, '').split(' ')[0]) : "No Data";
            report.deltaDate = deltaDate;
            report.cleanDate = cleanDate;
            report.date = hours < 1 ? Math.floor(mins)+' min' : Math.floor(hours)+'h';
            report.loot = data[3].querySelector('.ctn').textContent.replace(/(\D*)/, '').replace(/%/, '');
            report.metal = this.cleanValue(data[2].querySelectorAll('.resspan')[0].textContent.replace(/(\D*)/, ''));
            report.crystal = this.cleanValue(data[2].querySelectorAll('.resspan')[1].textContent.replace(/(\D*)/, ''));
            report.deut = this.cleanValue(data[2].querySelectorAll('.resspan')[2].textContent.replace(/(\D*)/, ''));
            report.total = report.metal + report.crystal + report.deut;
            report.renta = Math.round(report.total * report.loot / 100);
            report.pt = this.calcNeededShips({'moreFret':true, 'fret':202, 'resources':Math.ceil(report.total * report.loot / 100)});
            report.gt = this.calcNeededShips({'moreFret':true, 'fret':203, 'resources':Math.ceil(report.total * report.loot / 100)});
            report.pf = this.calcNeededShips({'moreFret':true, 'fret':219, 'resources':Math.ceil(report.total * report.loot / 100)});

            let resRatio = [report.total/report.metal, report.total/report.crystal, report.total/report.deut];
            report.resRatio = resRatio.map(x => Math.round(1/x*100));

            report.tmpCoords = report.coords.split(':');
            report.tmpCoords = report.tmpCoords.map(x => x.padStart(3, '0'));
            report.tmpCoords = report.tmpCoords.join('');

            reportList.push(report);
        });

        this.sortTable(reportList);
    }

    sortTable(arr)
    {
        arr.sort((a, b) =>
        {
            if(this.json.options.spyFilter == "$")
            {
                return b.renta - a.renta;
            }
            else if(this.json.options.spyFilter == "DATE")
            {
                return a.deltaDate - b.deltaDate;
            }
            else if(this.json.options.spyFilter == "COORDS")
            {
                return a.tmpCoords - b.tmpCoords;
            }
            else if(this.json.options.spyFilter == "FLEET")
            {
                return b.fleet - a.fleet;
            }
            else if(this.json.options.spyFilter == "DEF")
            {
                return b.defense - a.defense;
            }
        });

        let pagination = document.querySelector('.pagination');

        let tableOptions = this.createDOM('div', {'class':'ogl-tableOptions'});
        pagination.parentNode.insertBefore(tableOptions, pagination);

        // eye icon, toggle report table
        let enableTable = tableOptions.appendChild(this.createDOM('button', {'class':'icon icon_eye ogl-enableTable tooltip', 'title':this.getTranslatedText(8)}));
        if(this.json.options.spyTableEnable) enableTable.classList.add('ogl-active');
        enableTable.addEventListener('click', () =>
        {
            this.json.options.spyTableEnable = this.json.options.spyTableEnable ? false : true;
            this.saveData();
            document.location.reload();
        });

        let compactView = tableOptions.appendChild(this.createDOM('button', {'class':'icon icon_maximize ogl-icon tooltip', 'title':this.getTranslatedText(11)}));
        if(this.json.options.compactViewEnable) compactView.classList.add('ogl-active');
        compactView.addEventListener('click', () =>
        {
            this.json.options.compactViewEnable = this.json.options.compactViewEnable ? false : true;
            this.saveData();
            document.location.reload();
        });

        // trash icon, toggle auto delete
        let autoDelete = tableOptions.appendChild(this.createDOM('button', {'class':'icon icon_trash ogl-autoDelete tooltip', 'title':this.getTranslatedText(7)}));
        if(this.json.options.autoDeleteEnable) autoDelete.classList.add('ogl-active');
        autoDelete.addEventListener('click', () =>
        {
            this.json.options.autoDeleteEnable = this.json.options.autoDeleteEnable ? false : true;
            this.saveData();
            document.location.reload();
        });

        // separator
        tableOptions.appendChild(this.createDOM('div', {'style':'height:1px;width:20px;'}));

        // spy table
        let table = this.createDOM('table', {'class':'ogl-spyTable'});
        pagination.parentNode.insertBefore(table, pagination);

        if(!this.json.options.spyTableEnable) table.classList.add('ogl-hidden');

        // header
        let header = this.createDOM('tr');
        table.appendChild(header);

        header.appendChild(this.createDOM('th', {}, '#'));
        header.appendChild(this.createDOM('th', {'data-filter':'DATE'}, 'Date (*)'));
        header.appendChild(this.createDOM('th', {'data-filter':'COORDS'}, 'Coords'));
        header.appendChild(this.createDOM('th', {}, 'Name (+)'));
        header.appendChild(this.createDOM('th', {'data-filter':'$'}, 'Renta'));
        header.appendChild(this.createDOM('th', {'data-filter':'FLEET'}, 'Fleet'));
        header.appendChild(this.createDOM('th', {'data-filter':'DEF'}, 'Def'));
        if(this.json.options.compactViewEnable || this.json.options.fret == 202) header.appendChild(this.createDOM('th', {'class':'ogl-sc'}));
        if(this.json.options.compactViewEnable || this.json.options.fret == 203) header.appendChild(this.createDOM('th', {'class':'ogl-lc'}));
        if(this.json.options.compactViewEnable || this.json.options.fret == 219) header.appendChild(this.createDOM('th', {'class':'ogl-pf'}));
        header.appendChild(this.createDOM('th', {'class':'ogl-headerColors'}, '-'));
        header.appendChild(this.createDOM('th', {}, 'Actions'));

        document.querySelectorAll('.ogl-spyTable th').forEach(th =>
        {
            let filter = th.getAttribute('data-filter');

            if(this.json.options.spyFilter == filter) th.classList.add('ogl-active');

            th.addEventListener('click', () =>
            {
                if(filter)
                {
                    this.json.options.spyFilter = filter;
                    this.saveData();
                    document.location.reload();
                }
            });
        });

        // body
        arr.forEach((report, index) =>
        {
            let line = this.createDOM('tr');
            table.appendChild(line);

            line.appendChild(this.createDOM('td', {}, index + 1));

            let dateDetail = `
                ${report.cleanDate.toLocaleDateString()}<br>
                ${report.cleanDate.toLocaleTimeString()}<br>
                Activity : ${report.activity}
            `;

            let dateText = `${report.cleanDate.toLocaleTimeString()}<br>`;

            let date = line.appendChild(this.createDOM('td', {'class':'tooltipLeft ogl-date', 'title':dateDetail}, dateText));
            if(report.activity <= 15) date.classList.add('ogl-danger');
            else if(report.activity < 60) date.classList.add('ogl-care');
            else date.classList.add('ogl-good');

            let moonContent = report.type == 3 ? `<figure class="planetIcon moon"></figure>` : '';

            let coords = line.appendChild(this.createDOM('td'));
            coords.appendChild(this.createDOM('a', {'href':report.coordsLink}, report.coords + moonContent));

            let name = line.appendChild(this.createDOM('td', {'class':'ogl-name'}));
            name.appendChild(this.createDOM('a', {'class':'msg_action_link overlay', 'href':report.detail}, report.name + ' ' + report.status));

            let totalDetail = `
                <div class="ogl-metal">M: ${this.formatToUnits(report.metal)}</div>
                <div class="ogl-crystal">C: ${this.formatToUnits(report.crystal)}</div>
                <div class="ogl-deut">D: ${this.formatToUnits(report.deut)}</div>
                <div class="splitLine"></div>
                TOTAL: ${this.formatToUnits(report.total)}
            `;

            let total = line.appendChild(this.createDOM('td', {'class':'tooltipLeft ogl-lootable', 'title':totalDetail}, this.formatToUnits(report.renta)));

            if(this.json.options.rvalLimit <= Math.round(report.total * report.loot / 100)) total.classList.add('ogl-good');

            if(report.attacked) line.classList.add('ogl-attacked');

            total.style.background = `linear-gradient(to right, #9c4949 ${report.resRatio[0]}%, #498d9c ${report.resRatio[0]}%
                , #498d9c ${report.resRatio[0] + report.resRatio[1]}%, #abdeb4 ${report.resRatio[2]}%)`;

            let fleet = line.appendChild(this.createDOM('td', {}, this.formatToUnits(report.fleet)));
            if(report.fleet > 0 || report.fleet == 'No Data') fleet.classList.add('ogl-danger');

            let defense = line.appendChild(this.createDOM('td', {}, this.formatToUnits(report.defense)));
            if(report.defense > 0 || report.defense == 'No Data') defense.classList.add('ogl-danger');

            let splittedCoords = report.coords.split(':');

            if(this.json.options.compactViewEnable || this.json.options.fret == 202)
            {
                // sc
                let ptlink = `?page=ingame&component=fleetdispatch&galaxy=${splittedCoords[0]}&system=${splittedCoords[1]
                }&position=${splittedCoords[2]}&type=${report.type}&mission=1&am202=${report.pt}&oglMode=4`;

                let pt = line.appendChild(this.createDOM('td'));
                pt.appendChild(this.createDOM('a', {'href':'https://' + window.location.host + window.location.pathname + ptlink}, report.pt));
            }

            if(this.json.options.compactViewEnable || this.json.options.fret == 203)
            {
                // lc
                let gtlink = `?page=ingame&component=fleetdispatch&galaxy=${splittedCoords[0]}&system=${splittedCoords[1]
                }&position=${splittedCoords[2]}&type=${report.type}&mission=1&am203=${report.gt}&oglMode=4`;

                let gt = line.appendChild(this.createDOM('td'));
                gt.appendChild(this.createDOM('a', {'href':'https://' + window.location.host + window.location.pathname + gtlink}, report.gt));
            }

            if(this.json.options.compactViewEnable || this.json.options.fret == 219)
            {
                // pf
                let pflink = `?page=ingame&component=fleetdispatch&galaxy=${splittedCoords[0]}&system=${splittedCoords[1]
                }&position=${splittedCoords[2]}&type=${report.type}&mission=1&am219=${report.pf}&oglMode=4`;

                let pf = line.appendChild(this.createDOM('td'));
                pf.appendChild(this.createDOM('a', {'href':'https://' + window.location.host + window.location.pathname + pflink}, report.pf));
            }

            let colors = line.appendChild(this.createDOM('td'));
            colors.appendChild(this.createDOM('div', {class:'ogl-colors', 'data-coords':report.coords}));

            let opt = line.appendChild(this.createDOM('td', {'class':'ogl-spyOptions'}));

            let moreBtn = opt.appendChild(this.createDOM('button', {'class':'icon icon_fastforward'}));
            moreBtn.addEventListener('click', () =>
            {
                if(line.nextSibling && line.nextSibling.classList.contains('ogl-sub')) return;

                for(let i=6; i>1; i--)
                {
                    let newLine = this.createDOM('tr', {'class':'ogl-sub'});
                    line.after(newLine);

                    newLine.appendChild(this.createDOM('td', {}, '-'));
                    newLine.appendChild(this.createDOM('td', {}, '-'));
                    newLine.appendChild(this.createDOM('td', {}, '-'));
                    newLine.appendChild(this.createDOM('td', {}, '-'));

                    let newTotal = Math.ceil(report.total * report.loot / 100);

                    for(let j=1; j<i; j++)
                    {
                        newTotal -= (newTotal * report.loot / 100);
                    }

                    newLine.appendChild(this.createDOM('td', {}, this.formatToUnits(Math.ceil(newTotal))));
                    newLine.appendChild(this.createDOM('td', {}, '-'));
                    newLine.appendChild(this.createDOM('td', {}, '-'));

                    if(this.json.options.compactViewEnable || this.json.options.fret == 202)
                    {
                        let newPTFret = this.calcNeededShips({'moreFret':true, 'resources':newTotal, 'fret':202});
                        let newPTLink = `?page=ingame&component=fleetdispatch&galaxy=${splittedCoords[0]}&system=${splittedCoords[1]
                        }&position=${splittedCoords[2]}&type=${report.type}&mission=1&am202=${newPTFret}&oglMode=4`;

                        let newPT = newLine.appendChild(this.createDOM('td'));
                        newPT.appendChild(this.createDOM('a', {'href':'https://' + window.location.host + window.location.pathname + newPTLink}, newPTFret));
                    }

                    if(this.json.options.compactViewEnable || this.json.options.fret == 203)
                    {
                        let newGTFret = this.calcNeededShips({'moreFret':true, 'resources':newTotal, 'fret':203});
                        let newGTLink = `?page=ingame&component=fleetdispatch&galaxy=${splittedCoords[0]}&system=${splittedCoords[1]
                        }&position=${splittedCoords[2]}&type=${report.type}&mission=1&am203=${newGTFret}&oglMode=4`;

                        let newGT = newLine.appendChild(this.createDOM('td'));
                        newGT.appendChild(this.createDOM('a', {'href':'https://' + window.location.host + window.location.pathname + newGTLink}, newGTFret));
                    }

                    if(this.json.options.compactViewEnable || this.json.options.fret == 219)
                    {
                        let newPFFret = this.calcNeededShips({'moreFret':true, 'resources':newTotal, 'fret':219});
                        let newPFLink = `?page=ingame&component=fleetdispatch&galaxy=${splittedCoords[0]}&system=${splittedCoords[1]
                        }&position=${splittedCoords[2]}&type=${report.type}&mission=1&am219=${newPFFret}&oglMode=4`;

                        let newPF = newLine.appendChild(this.createDOM('td'));
                        newPF.appendChild(this.createDOM('a', {'href':'https://' + window.location.host + window.location.pathname + newPFLink}, newPFFret));
                    }

                    newLine.appendChild(this.createDOM('td', {}, '-'));
                    newLine.appendChild(this.createDOM('td', {}, '-'));
                }
            });

            opt.appendChild(this.createDOM('button', {'class':'icon icon_eye', 'onclick':report.spy}));

            let deleteBtn = opt.appendChild(this.createDOM('button', {'class':'icon icon_close'}));
            deleteBtn.addEventListener('click', () =>
            {
                document.querySelectorAll('.ogl-sub').forEach(sub => sub.remove());
                report.delete.click();
                line.remove();
            });

            if(this.json.options.autoDeleteEnable && ((report.fleet == 0 && Math.round(report.total * report.loot / 100) < this.json.options.rvalLimit)))
            {
                deleteBtn.click();
            }
        });

        this.marker();
    }

    lock()
    {
        if(this.page == 'supplies' || this.page == 'research' || this.page == 'facilities')
        {
            this.FPSLoop('lock');

            let data;
            let detail = document.querySelector('#technologydetails');

            let tech = {};
            tech.onMoon = this.current.isMoon;

            if(this.json.locked[this.current.coords])
            {
                data = JSON.parse(this.json.locked[this.current.coords]);

                if(data.onMoon == tech.onMoon)
                {
                    let techDom = document.querySelector(`#technologies .technology[data-technology="${data.id}"]`);

                    if(techDom)
                    {
                        let finished = parseInt(techDom.querySelector('.level').getAttribute('data-value')) >= data.level;
                        let started = techDom.querySelector('.targetlevel') ? parseInt(techDom.querySelector('.targetlevel').getAttribute('data-value')) >= data.level : false;

                        if(started || finished)
                        {
                            this.json.locked[this.current.coords] = '';
                            this.saveData();
                        }
                    }
                }
            }

            if(!detail || detail.classList.contains('ogl-detailReady')) return;
            detail.classList.add('ogl-detailReady');

            let m = detail.querySelector('.costs .metal');
            let c = detail.querySelector('.costs .crystal');
            let d = detail.querySelector('.costs .deuterium');

            tech.id = detail.getAttribute('data-technology-id');
            tech.metal = m ? parseInt(m.getAttribute('data-value')) + 1 : 0;
            tech.crystal = c ? parseInt(c.getAttribute('data-value')) + 1 : 0;
            tech.deut = d ? parseInt(d.getAttribute('data-value')) + 1 : 0;
            tech.name = detail.querySelector('h3').textContent;

            let btn = detail.querySelector('.sprite_large').appendChild(this.createDOM('button', {'class':'ogl-lock'}));

            if(data)
            {
                btn.innerHTML = `<span>${data.name}</span> (${data.level})`;
                btn.classList.add('ogl-active');

                /*if(data.isShip)
                {
                    detail.querySelector('.upgrade').addEventListener('click', () =>
                    {

                    });
                }*/
            }

            btn.addEventListener('click', () =>
            {
                if(data && data.id == tech.id)
                {
                    this.json.locked[this.current.coords] = '';
                }
                else
                {
                    if(this.page != 'shipyard')
                    {
                        tech.level = parseInt(detail.querySelector('.level').getAttribute('data-value'));
                        tech.metal = Math.max(0, tech.metal - parseInt(this.removeNumSeparator(document.querySelector('#resources_metal').textContent)));
                        tech.crystal = Math.max(0, tech.crystal - parseInt(this.removeNumSeparator(document.querySelector('#resources_crystal').textContent)));
                        tech.deut = Math.max(0, tech.deut - parseInt(this.removeNumSeparator(document.querySelector('#resources_deuterium').textContent)));
                    }
                    else
                    {
                        let amount = prompt('Quantité');
                        if(!amount || isNaN(amount)) return;

                        tech.level = amount;
                        tech.metal = tech.metal * amount;
                        tech.crystal = tech.crystal * amount;
                        tech.deut = tech.deut * amount;
                        tech.isShip = true;
                    }

                    this.json.locked[this.current.coords] = JSON.stringify(tech);
                }

                detail.classList.remove('ogl-detailReady');
                btn.remove();

                this.saveData();
                this.sideLock();
            });
        }
    }

    sideLock()
    {
        document.querySelectorAll('.ogl-sideLock').forEach(e => e.remove());

        this.planetList.forEach(planet =>
        {
            let coords = planet.querySelector('.planet-koords').textContent.slice(1, -1);
            let splittedCoords = coords.split(':');

            if(this.json.locked[coords])
            {
                let data = JSON.parse(this.json.locked[coords]);
                let btn = planet.appendChild(this.createDOM('button', {'class':'ogl-sideLock tooltip tooltipRight'}));
                btn.title = `
                    ${data.name} (${data.level})
                    <div class="splitLine"></div>
                    M: ${this.formatToUnits(Math.max(0, data.metal - 1))}<br>
                    C: ${this.formatToUnits(Math.max(0, data.crystal - 1))}<br>
                    D: ${this.formatToUnits(Math.max(0, data.deut - 1))}
                `;

                btn.addEventListener('click', () =>
                {
                    let type = planet.querySelector('.moonlink') && !planet.querySelector('.moonlink.active') ? 3 : 1;

                    let link = `?page=ingame&component=fleetdispatch&galaxy=${splittedCoords[0]}&system=${splittedCoords[1]
                    }&position=${splittedCoords[2]}&type=${type}&mission=${this.json.options.harvestMission}&oglMode=2`;

                    window.location.href = 'https://' + window.location.host + window.location.pathname + link;
                });

                let destCoords =
                [
                    this.rawURL.searchParams.get(`galaxy`) || 0,
                    this.rawURL.searchParams.get(`system`) || 0,
                    this.rawURL.searchParams.get(`position`) || 0,
                ].join(':');

                if(this.mode == 2 && coords == destCoords)
                {
                    btn.classList.add('ogl-sideLockFilled');
                }
            }
        });

        if(this.page == 'fleetdispatch' && this.mode == 2)
        {
            if(fleetDispatcher)
            {
                let coords = fleetDispatcher.targetPlanet.galaxy + ':' + fleetDispatcher.targetPlanet.system + ':' + fleetDispatcher.targetPlanet.position;

                if(this.json.locked[coords])
                {
                    let data = JSON.parse(this.json.locked[coords]);

                    let metal = Math.min(data.metal, fleetDispatcher.metalOnPlanet);
                    let crystal = Math.min(data.crystal, fleetDispatcher.crystalOnPlanet);
                    let deut = Math.min(data.deut, fleetDispatcher.deuteriumOnPlanet);

                    let total = metal + crystal + deut;
                    this.selectShips(this.json.options.fret, this.calcNeededShips({'resources':total}));

                    this.fillFret({'resources':{'metal':metal, 'crystal':crystal, 'deut':deut}});

                    let sent = false;

                    let sendAction = () =>
                    {
                        data.metal = Math.max(0, data.metal - fleetDispatcher.cargoMetal);
                        data.crystal = Math.max(0, data.crystal - fleetDispatcher.cargoCrystal);
                        data.deut = Math.max(0, data.deut - fleetDispatcher.cargoDeuterium);

                        this.json.locked[coords] = JSON.stringify(data);
                        this.saveData();
                        sent = true;
                    };

                    document.addEventListener('keydown', event =>
                    {
                        if(!sent && event.keyCode === 13 && fleetDispatcher.currentPage == 'fleet3')
                        {
                            sendAction();
                        }
                    });

                    document.querySelector('#sendFleet').addEventListener('click', () =>
                    {
                        if(!sent)
                        {
                            sendAction();
                        }
                    });
                }
            }
        }
    }

    missingEnergy()
    {
        if(this.page == 'supplies' && !this.current.isMoon)
        {
            this.FPSLoop('missingEnergy');

            let detail = document.querySelector('#technologydetails');

            if(!detail || detail.classList.contains('ogl-energyReady') || !detail.querySelector('.level')
            || parseInt(detail.getAttribute('data-technology-id')) > 3) return;
            detail.classList.add('ogl-energyReady');

            let node = detail.querySelector('.additional_energy_consumption span.value');
            let neededEnergy = parseInt(node.getAttribute('data-value'));
            let currentEnergy = parseInt(this.removeNumSeparator(document.querySelector('#resources_energy').textContent));

            let totalEnergy = currentEnergy - neededEnergy;
            let span = node.appendChild(this.createDOM('span', {}, ` (${totalEnergy.toLocaleString('de-DE')})`));

            totalEnergy > 0 ? span.classList.add('bonus') : span.classList.add('overmark');
        }
    }

    flyingResources()
    {
        if(this.page == 'movement')
        {
            let container = this.createDOM('div', {'class':'ogl-dialogContainer ogl-flyingGrid'});
            let div = container.appendChild(this.createDOM('div'));
            let btn = document.querySelector('#planet').appendChild(this.createDOM('div', {'class':'btn_blue'}, this.getTranslatedText(18)));
            btn.addEventListener('click', () => this.popup(false, container));

            let resources = {};
            let total = {'metal':0, 'crystal':0, 'deut':0};

            document.querySelectorAll('.fleetDetails').forEach(line =>
            {
                let mission = line.getAttribute('data-mission-type');
                let back = line.getAttribute('data-return-flight');
                let route = line.querySelector('.route');
                let tr = route.querySelectorAll('tr');
                let destination;

                if(back != 1 && (mission == 3 || mission == 4 || mission == 7))
                {
                    destination = line.querySelector('.destinationCoords').textContent.slice(1, -1);
                    //destination = line.querySelector('.destinationData').innerHTML;
                }
                else
                {
                    destination = line.querySelector('.originCoords').textContent.slice(1, -1);
                    //destination = line.querySelector('.originData').innerHTML;
                }

                let metal = parseInt(this.removeNumSeparator(tr[tr.length-3].querySelector('.value').textContent.trim()));
                let crystal = parseInt(this.removeNumSeparator(tr[tr.length-2].querySelector('.value').textContent.trim()));
                let deut = parseInt(this.removeNumSeparator(tr[tr.length-1].querySelector('.value').textContent.trim()));

                resources[destination] = resources[destination] || {'metal':0, 'crystal':0, 'deut':0};
                resources[destination].metal += metal;
                resources[destination].crystal += crystal;
                resources[destination].deut += deut;

                total.metal += metal;
                total.crystal += crystal;
                total.deut += deut;
            });

            Object.keys(resources).sort((a, b) =>
            {
                let coordsA = a.split(':').map(x => x.padStart(3, '0')).join('');
                let coordsB = b.split(':').map(x => x.padStart(3, '0')).join('');

                return coordsA - coordsB;
            }).forEach(target =>
            {
                div.innerHTML += `
                    <div>
                        <div class="ogl-destination">${target}</div>
                        <hr>
                        <div class="ogl-metal"><span>m:</span>${this.formatToUnits(resources[target].metal)}</div>
                        <div class="ogl-crystal"><span>c:</span>${this.formatToUnits(resources[target].crystal)}</div>
                        <div class="ogl-deut"><span>d:</span>${this.formatToUnits(resources[target].deut)}</div>
                    </div>
                `;
            });

            div.innerHTML += `
                <div class="ogl-fullGrid">
                    <div class="ogl-destination">TOTAL</div>
                    <hr>
                    <div class="ogl-metal"><span>m:</span>${total.metal.toLocaleString('de-DE')}</div>
                    <div class="ogl-crystal"><span>c:</span>${total.crystal.toLocaleString('de-DE')}</div>
                    <div class="ogl-deut"><span>d:</span>${total.deut.toLocaleString('de-DE')}</div>
                </div>
            `;
        }
    }

    highlightTarget()
    {
        if(this.page == 'galaxy')
        {
            this.FPSLoop('highlightTarget');

            if(document.querySelector('#galaxyLoading').style.display != 'none') return;

            let coords;

            if(this.highlighted)
            {
                coords = this.highlighted.split(':');
            }
            else
            {
                coords =
                [
                    this.rawURL.searchParams.get(`galaxy`) || 0,
                    this.rawURL.searchParams.get(`system`) || 0,
                    this.rawURL.searchParams.get(`position`) || 0,
                ];
                coords.join(':');
            }

            if(document.querySelector('#galaxy_input').value == coords[0]
            && document.querySelector('#system_input').value == coords[1])
            {
                let target = document.querySelectorAll('#galaxytable tbody tr')[parseInt(coords[2])-1];
                if(target) target.classList.add('ogl-highlighted');
            }

            document.querySelectorAll('a[data-coords]').forEach(a =>
            {
                let hCoords = a.getAttribute('data-coords').split(':');

                if(document.querySelector('#galaxy_input').value == hCoords[0]
                && document.querySelector('#system_input').value == hCoords[1])
                {
                    a.classList.add('ogl-active');
                }
                else
                {
                    a.classList.remove('ogl-active');
                }
            });
        }
    }

    toggleImage()
    {
        let btn = this.createDOM('a', {'class':'toggleHeader'});
        let wrapper = document.querySelector('#supplies header, #facilities header, #research header, #defense header, #shipyard header');
        if(wrapper) wrapper.appendChild(btn);

        btn.addEventListener('click', () =>
        {
            this.json.options.headerDisabled[this.page] = this.json.options.headerDisabled[this.page] ? false : true;
            this.saveData();

            if(this.json.options.headerDisabled[this.page])
            {
                document.querySelector('.maincontent header').classList.add('ogl-shortHeader');
            }
            else
            {
                document.querySelector('.maincontent header').classList.remove('ogl-shortHeader');
            }
        });

        if(this.json.options.headerDisabled[this.page])
        {
            document.querySelector('.maincontent header').classList.add('ogl-shortHeader');
        }
    }

    keepResources()
    {
        if(this.page == 'fleetdispatch')
        {
            fleetDispatcher.metalOnPlanet = Math.max(0, this.current.resources.metal - this.json.options.kept[0]);
            fleetDispatcher.crystalOnPlanet = Math.max(0, this.current.resources.crystal - this.json.options.kept[1]);
            fleetDispatcher.deuteriumOnPlanet = Math.max(0, this.current.resources.deut - this.json.options.kept[2]);
            fleetDispatcher.refresh();

            document.querySelectorAll('#resources .res').forEach((element, index) =>
            {
                let div = element.appendChild(this.createDOM('div', {'class':'ogl-keepRes tooltip', 'title':this.getTranslatedText(12)}, '-'));
                let container = this.createDOM('div', {'class':'ogl-dialogContainer'});
                container.appendChild(this.createDOM('h1', {}, this.getTranslatedText(25)));
                container.appendChild(this.createDOM('hr'));
                let input = container.appendChild(this.createDOM('input', {'type':'text', 'class':'ogl-formatInput'}));
                container.appendChild(this.createDOM('hr'));
                let button = container.appendChild(this.createDOM('button', {'class':'btn_blue'}, 'OK'));

                if(this.json.options.kept[index]) div.classList.add('ogl-active');

                container.addEventListener('click', event =>
                {
                    event.preventDefault();
                    event.stopPropagation();
                });

                div.addEventListener('click', () =>
                {
                    input.value = this.json.options.kept[index];
                    this.popup(false, container);
                });

                button.addEventListener('click', () =>
                {
                    this.json.options.kept[index] = parseInt(this.removeNumSeparator(input.value));
                    this.saveData();
                    document.location.reload();
                });
            });
        }
    }

    checkResources(params)
    {
        if(this.page != 'fleetdispatch') return;

        params = params || {};
        this.FPSLoop('checkResources', params);

        if(fleetDispatcher.currentPage == 'fleet1')
        {
            if(fleetDispatcher.cargoMetal > 0 || fleetDispatcher.cargoCrystal > 0 || fleetDispatcher.cargoDeuterium > 0)
            {
                params.loop = true;
                params.resources = {'metal':fleetDispatcher.cargoMetal, 'crystal':fleetDispatcher.cargoCrystal, 'deut':fleetDispatcher.cargoDeuterium};
            }
        }
        else if(fleetDispatcher.currentPage == 'fleet2')
        {
            if(params.loop)
            {
                params.loop = false;
                this.fillFret({'resources':params.resources});
            }
        }
        else if(fleetDispatcher.currentPage == 'fleet3')
        {
            let max = this.current.resources.deut - this.json.options.kept[2] - fleetDispatcher.getConsumption();
            if(fleetDispatcher.cargoDeuterium > max)
            {
                fleetDispatcher.cargoDeuterium = Math.max(0, max);
                fleetDispatcher.refresh();
            }
        }
    }

    checkInputs()
    {
        this.FPSLoop('checkInputs');

        if(this.page == 'fleetdispatch')
        {
            document.querySelectorAll('.technology input').forEach(i => i.classList.add('ogl-formatInput'));
        }

        document.querySelectorAll('input.ogl-formatInput').forEach(input =>
        {
            if(input.value) input.value = parseInt(this.removeNumSeparator(input.value, true)).toLocaleString('de-DE');
        });
    }

    selectShips(shipID, amount)
    {
        if(this.page == 'fleetdispatch')
        {
            fleetDispatcher.shipsOnPlanet.forEach(ship =>
            {
                if(ship.id == shipID)
                {
                    if(amount > ship.number) amount = ship.number;

                    fleetDispatcher.selectShip(shipID, amount);
                    fleetDispatcher.refresh();
                    document.querySelector('#continueToFleet2').focus();
                }
            });
        }

        return amount;
    }

    preselectShips()
    {
        if(this.page == 'fleetdispatch')
        {
            fleetDispatcher.shipsOnPlanet.forEach(ship =>
            {
                let param = this.rawURL.searchParams.get(`am${ship.id}`);
                if(param)
                {
                    this.selectShips(ship.id, param);
                }
            });
        }
    }

    calcNeededShips(options)
    {
        options = options || {};

        // get resources
        let resources = [this.removeNumSeparator(document.querySelector('#resources_metal').textContent),
            this.removeNumSeparator(document.querySelector('#resources_crystal').textContent),
            this.removeNumSeparator(document.querySelector('#resources_deuterium').textContent)];

        resources = resources.reduce((a, b) => parseInt(a) + parseInt(b));

        if(options.resources || options.resources == 0) resources = options.resources;

        let type = options.fret || this.json.options.fret;
        let fret;

        if(type == 202)
        {
            fret = this.json.ptFret;
        }
        else if(type == 203)
        {
            fret = this.json.gtFret;
        }
        else if(type == 219)
        {
            fret = this.json.pfFret;
        }

        let total = resources / fret;
        if(options.moreFret) total *= 107 / 100;

        return Math.ceil(total);
    }

    calcAvailableFret(shipAmount)
    {
        let fret = this.json.options.fret == 203 ? this.json.gtFret : this.json.ptFret;
        return shipAmount * fret;
    }

    saveData()
    {
        localStorage.setItem('ogl-data', JSON.stringify(this.json));
    }

    createDOM(element, options, content)
    {
        let e = document.createElement(element);

        for(var key in options)
        {
            e.setAttribute(key, options[key]);
        }

        if(content || content == 0) e.innerHTML = content;

        return e;
    }

    formatToUnits(value)
	{
        let precision;

        if(value == 0) precision = 0;
        else if(value < 1000000) precision = 1;
        else if(value < 1000000000) precision = 2;
        else precision = 3;

        if(isNaN(value)) return value;

		const abbrev = ['', 'k', 'M', 'Md', 't'];
		const unrangifiedOrder = Math.floor(Math.log10(Math.abs(value)) / 3);
		const order = Math.max(0, Math.min(unrangifiedOrder, abbrev.length-1));
		const suffix = abbrev[order];

		return (value / Math.pow(10, order * 3)).toFixed(precision) + suffix;
    }

    cleanValue(value)
    {
        if(this.language == 0)
        {
            if(value.indexOf('Md') > -1)
            {
                if(value.indexOf(',') == -1)
                {
                    value = value.replace('Md', '.000Md');
                }

                value = value.replace(/\Md/g, '').replace(/\,/g, '.');

                value = value.split('.');
                value[1] = value[1].padEnd(9, '0');
                value = value.join();
                value = value.replace(/\,/g, '');
            }
            else if(value.indexOf('M') > -1)
            {
                if(value.indexOf(',') == -1)
                {
                    value = value.replace('M', '.000M');
                }

                value = value.replace(/\M/g, '').replace(/\,/g, '.');

                value = value.split('.');
                value[1] = value[1].padEnd(6, '0');
                value = value.join();
                value = value.replace(/\,/g, '');
            }
            else
            {
                value = value.replace(/\./g, '');
            }
        }
        else
        {
            if(value.indexOf('Md') > -1)
            {
                if(value.indexOf('.') == -1)
                {
                    value = value.replace('Md', '.000Md');
                }

                value = value.replace(/\Md/g, '').replace(/\,/g, '.');

                value = value.split('.');
                value[1] = value[1].padEnd(9, '0');
                value = value.join();
                value = value.replace(/\,/g, '');
            }
            else if(value.indexOf('Mn') > -1)
            {
                if(value.indexOf('.') == -1)
                {
                    value = value.replace('Mn', '.000Mn');
                }

                value = value.replace(/\Mn/g, '').replace(/\,/g, '.');

                value = value.split('.');
                value[1] = value[1].padEnd(6, '0');
                value = value.join();
                value = value.replace(/\,/g, '');
            }
            else
            {
                value = value.replace(/\./g, '');
            }
        }


		return parseInt(value);
    }

    addStyle(option, style)
    {
        if(option != 'disabled')
        {
            GM_addStyle(style);
        }
    }

    callAPI(url)
    {
        let http = new XMLHttpRequest();
        http.open('GET', url);
        http.send();
        return http;
    }

    removeNumSeparator(str, forced)
    {
        if(this.language == 0 || forced)
        {
            return str.replace(/\./g, '');
        }
        else
        {
            return str.replace(/\,/g, '');
        }
    }

    keyboardActions()
    {
        if(this.page == 'fleetdispatch')
        {
            document.addEventListener('keydown', event =>
            {
                if((!document.querySelector('.ui-dialog') || document.querySelector('.ui-dialog').style.display == 'none')
                && !document.querySelector('.chat_box_textarea:focus'))
                {
                    if(event.keyCode === 13 && fleetDispatcher.currentPage == 'fleet1')
                    {
                        if(fleetDispatcher.shipsToSend.length == 0)
                        {
                            document.querySelector(`.technology[data-technology="${this.json.options.fret}"] .ogl-needed`)
                            && document.querySelector(`.technology[data-technology="${this.json.options.fret}"] .ogl-needed`).click();
                        }
                    }

                    if(event.keyCode === 65 && fleetDispatcher.currentPage == 'fleet1')
                    {
                        document.querySelector('#sendall').click();
                    }

                    if(event.keyCode === 65 && fleetDispatcher.currentPage == 'fleet3')
                    {
                        //this.fillFret({'once':true});
                        document.querySelector('#allresources').click();
                    }
                }
            });
        }
    }

    FPSLoop(callbackAsString, params)
    {
        setTimeout(() =>
        {
            requestAnimationFrame(() => this[callbackAsString](params));
        }, 1000 / 20);
    }

    tooltip(sender, content, autoHide, side, timer)
    {
        side = side || {};
        timer = timer || 300;

        let tooltip = document.querySelector('.ogl-tooltip');
        document.querySelector('.ogl-tooltip > div') && document.querySelector('.ogl-tooltip > div').remove();

        let close = document.querySelector('.close-tooltip');

        if(!tooltip)
        {
            tooltip = document.body.appendChild(this.createDOM('div', {'class':'ogl-tooltip'}));

            close = tooltip.appendChild(this.createDOM('a', {'class':'close-tooltip'}));

            close.addEventListener('click', () => tooltip.classList.remove('ogl-active'));

            document.body.addEventListener('click', event =>
            {
                if(!event.target.getAttribute('rel')
                && !event.target.closest('.tooltipRel')
                && !event.target.classList.contains('ogl-colors')
                && !tooltip.contains(event.target))
                {
                    tooltip.classList.remove('ogl-active');
                }
            });
        }

        if(sender != this.oldSender) tooltip.classList.remove('ogl-active');
        tooltip.classList.remove('ogl-autoHide');
        tooltip.classList.remove('ogl-tooltipLeft');
        tooltip.classList.remove('ogl-tooltipRight');
        tooltip.classList.remove('ogl-tooltipBottom');

        this.oldSender = sender;

        let rect = sender.getBoundingClientRect();
        let win = sender.ownerDocument.defaultView;
        let position =
        {
            x:rect.left + win.pageXOffset,
            y:rect.top + win.pageYOffset
        };

        if(side.left)
        {
            tooltip.classList.add('ogl-tooltipLeft');
            position.y -= 20;
            position.y += rect.height / 2;
        }
        else if(side.right)
        {
            tooltip.classList.add('ogl-tooltipRight');
            position.x += rect.width;
            position.y -= 20;
            position.y += rect.height / 2;
        }
        else if(side.bottom)
        {
            tooltip.classList.add('ogl-tooltipBottom');
            position.x += rect.width / 2;
            position.y += rect.height;
        }
        else
        {
            position.x += rect.width / 2;
        }

        if(sender.classList.contains('tooltipOffsetX'))
        {
            position.x += 33;
        }

        if(autoHide)
        {
            tooltip.classList.add('ogl-autoHide');
        }

        tooltip.appendChild(content);

        tooltip.style.top = position.y + 'px';
        tooltip.style.left = position.x + 'px';

        this.tooltipTimer = setTimeout(() => tooltip.classList.add('ogl-active'), timer);

        if(!sender.classList.contains('ogl-tooltipInit'))
        {
            sender.classList.add('ogl-tooltipInit');
            sender.addEventListener('mouseleave', event =>
            {
                if(autoHide)
                {
                    tooltip.classList.remove('ogl-active');
                }
                clearTimeout(this.tooltipTimer);
            });
        }

        return tooltip;
    }

    popup(header, content)
    {
        let overlay = document.querySelector('.ogl-dialogOverlay');

        if(!overlay)
        {
            overlay = document.body.appendChild(this.createDOM('div', {'class':'ogl-dialogOverlay'}));
            overlay.addEventListener('click', event => overlay.classList.remove('ogl-active'));
        }

        let dialog = overlay.querySelector('.ogl-dialog');

        if(!dialog)
        {
            dialog = overlay.appendChild(this.createDOM('div', {'class':'ogl-dialog'}));
            let close = dialog.appendChild(this.createDOM('div', {'class':'close-tooltip'}));
            close.addEventListener('click', () => overlay.classList.remove('ogl-active'));

            dialog.addEventListener('click', event =>
            {
                event.preventDefault();
                event.stopPropagation();
            });
        }

        let top = dialog.querySelector('header') || dialog.appendChild(this.createDOM('header'));
        let body = dialog.querySelector('.ogl-dialogContent') || dialog.appendChild(this.createDOM('div', {'class':'ogl-dialogContent'}));

        top.innerHTML = '';
        body.innerHTML = '';

        if(header)
        {
            top.appendChild(header);
        }

        if(content)
        {
            body.appendChild(content);
        }

        overlay.classList.add('ogl-active');
    }

    betterTooltip()
    {
        this.FPSLoop('betterTooltip');

        let eventAction = this.isMobile ? 'touchstart' : 'mouseenter';

        if(this.page == 'galaxy')
        {
            // tooltipRel galaxy
            document.querySelectorAll('.tooltipRel').forEach(sender =>
            {
                if(sender.getAttribute('rel').indexOf('player') == 0)
                {
                    if(!sender.classList.contains('ogl-stalkReady'))
                    {
                        this.stalk(sender);
                    }
                }
            });

            if(document.querySelector('#galaxytable:not(.ogl-ready)'))
            {
                document.querySelector('#galaxytable').classList.add('ogl-ready');
                document.querySelector('.ogl-tooltip') && document.querySelector('.ogl-tooltip').classList.remove('ogl-active');
                this.tooltipList = {};
            }
        }

        document.querySelectorAll('.tooltip, .tooltipLeft, .tooltipRight, .tooltipBottom, .tooltipClose, .tooltipHTML, .tooltipRel, .tooltipCustom').forEach(sender =>
        {
            if(!sender.classList.contains('ogl-tooltipReady')
            && !sender.classList.contains('ogl-stalkReady')
            && !sender.classList.contains('activity'))
            {
                sender.classList.add('ogl-tooltipReady');

                sender.addEventListener(eventAction, () =>
                {
                    let content;
                    let appendMode = false;

                    if(sender.classList.contains('tooltipRel'))
                    {
                        let id = '#' + sender.getAttribute('rel');
                        this.tooltipList[id] = this.tooltipList[id] || document.querySelector(id);
                        content = this.tooltipList[id];
                        appendMode = true;
                    }
                    else
                    {
                        content = sender.getAttribute('data-title');
                    }

                    if(!content)
                    {
                        content = sender.getAttribute('title');
                        if(!content) return;
                        sender.setAttribute('data-title', content);
                    }

                    sender.removeAttribute('title');

                    if(sender.classList.contains('tooltipHTML'))
                    {
                        content = content.replace('|', '<hr>');
                    }

                    if(sender.classList.contains('planetlink'))
                    {
                        sender.classList.remove('tooltipLeft');
                        sender.classList.add('tooltipRight');
                        sender.classList.add('tooltipOffsetX');
                    }

                    if(sender.getAttribute('id')
                    && sender.getAttribute('id').indexOf('route_') == 0)
                    {
                        sender.classList.add('tooltipRight');
                    }

                    let div = this.createDOM('div');
                    appendMode ? div.appendChild(content) : div.innerHTML = content;

                    let side = {};
                    side.left = sender.classList.contains('tooltipLeft');
                    side.right = sender.classList.contains('tooltipRight');
                    side.bottom = sender.classList.contains('tooltipBottom');

                    let autoHide = true;
                    if(sender.classList.contains('tooltipClose')
                    || sender.classList.contains('tooltipCustom'))
                    {
                        autoHide = false;
                    }

                    this.tooltip(sender, div, autoHide, side);
                });
            }
        });
    }

    utilities()
    {
        // fix top tooltips
        document.querySelectorAll('#resources .tooltipHTML, #commandercomponent .tooltipHTML').forEach(e =>
        {
            e.classList.add('tooltipBottom');
        });

        if(this.page == 'fleetdispatch')
        {
            // speed slider
            document.querySelector('.steps').addEventListener('click', () =>
            {
                document.querySelector('#continueToFleet3').focus();
            });

            document.querySelector('#speedPercentage').classList.add('ogl-hidden');

            let slider = this.createDOM('div', {'class':'ogl-fleetSpeed'});
            document.querySelector('#fleetBriefingPart1').appendChild(slider);

            slider.innerHTML = `
                <div data-step="1">10</div>
                <div data-step="2">20</div>
                <div data-step="3">30</div>
                <div data-step="4">40</div>
                <div data-step="5">50</div>
                <div data-step="6">60</div>
                <div data-step="7">70</div>
                <div data-step="8">80</div>
                <div data-step="9">90</div>
                <div class="ogl-active" data-step="10">100</div>
            `;

            slider.addEventListener('click', event =>
            {
                slider.querySelectorAll('div').forEach(e => e.classList.remove('ogl-active'));
                event.target.classList.add('ogl-active');
                fleetDispatcher.speedPercent = event.target.getAttribute('data-step');
                fleetDispatcher.refresh();
                document.querySelector('#continueToFleet3').focus();
            });

            slider.addEventListener('mouseover', event =>
            {
                fleetDispatcher.speedPercent = event.target.getAttribute('data-step');
                fleetDispatcher.refresh();
            });

            slider.addEventListener('mouseout', event =>
            {
                fleetDispatcher.speedPercent = slider.querySelector('.ogl-active').getAttribute('data-step');
                fleetDispatcher.refresh();
            });

            // ship infos
            let data = fleetDispatcher.fleetHelper.shipsData;
            for(let id in data)
            {
                let infos = `
                    <div class="ogl-fleetInfo">
                        ${data[id].name}
                        <hr>
                        <div><span>Carg.</span>${data[id].cargoCapacity.toLocaleString('de-DE')}</div>
                        <div><span>${this.getTranslatedText(19)}</span>${data[id].speed.toLocaleString('de-DE')}</div>
                        <div><span>Consum</span>${data[id].fuelConsumption.toLocaleString('de-DE')}</div>
                    </div>
                `;

                let ship = document.querySelector(`.technology[data-technology="${id}"]`);

                if(ship)
                {
                    ship.setAttribute('data-title', infos);
                    ship.removeAttribute('title');
                }
            }

            // preselect associated moon/planet
            document.addEventListener('keydown', event =>
            {
                if(fleetDispatcher.currentPage == 'fleet2'
                && fleetDispatcher.currentPlanet.galaxy == fleetDispatcher.targetPlanet.galaxy
                && fleetDispatcher.currentPlanet.system == fleetDispatcher.targetPlanet.system
                && fleetDispatcher.currentPlanet.position == fleetDispatcher.targetPlanet.position
                && fleetDispatcher.currentPlanet.type == fleetDispatcher.targetPlanet.type
                && event.keyCode === 13)
                {
                    fleetDispatcher.targetPlanet.type = fleetDispatcher.targetPlanet.type == 1 ? 3 : 1;
                    if(!fleetDispatcher.mission) fleetDispatcher.mission = this.json.options.harvestMission;
                    fleetDispatcher.refresh();
                }
            });
        }
    }

    loopUtilities()
    {
        this.FPSLoop('loopUtilities');

        if(this.page == 'fleetdispatch')
        {
            if(!fleetDispatcher.mission && fleetDispatcher.currentPage == 'fleet3')
            {
                // select expedition mission
                if(!fleetDispatcher.mission && fleetDispatcher.targetPlanet.position == 16)
                {
                    fleetDispatcher.mission = 15;
                }

                // select unique mission available
                if(!fleetDispatcher.mission && document.querySelectorAll('#missions .on').length == 1)
                {
                    document.querySelectorAll('#missions .on')[0].querySelector('a').click();
                }

                fleetDispatcher.refresh();
            }

            // add fret on fleet1
            if(fleetDispatcher.currentPage == 'fleet1' && document.querySelector('#civilships'))
            {
                let div = document.querySelector('#civilships .ogl-fret') || document.querySelector('#civilships').appendChild(this.createDOM('div', {'class':'ogl-fret'}));
                div.textContent = fleetDispatcher.getCargoCapacity().toLocaleString('de-DE');
            }
        }

        if(this.page == 'galaxy')
        {
            if(document.querySelector('a[onclick*="sendShips"'))
            {
                let ships = document.querySelector('a[onclick*="sendShips"').getAttribute('onclick').match(/\d+/g).map(Number);
                if(ships[0] == 6) this.json.spyProbes = ships[5];
            }
        }
    }

    getTranslatedText(id)
    {
        let text =
        {
            0 :
            [
                "Gestion des données",
                "Administrar Info",
            ],
            1 :
            [
                "Ouvrir la liste de cibles",
                "Abrir Lista de objetivos",
            ],
            2 :
            [
                "Alterne entre PT et GT comme type de vaisseaux à utilser pour les envois de ressources",
                "Cambiar entre cargas pequeñas o cargas grandes para el transporte de recursos",
            ],
            3 :
            [
                "Alterne entre transport et stationnement comme type de mission à utiliser pour les rapatriements",
                "Switch between transport and deployment as default mission to use for transporting resources",
            ],
            4 :
            [
                "Rapatrie les ressources vers la planète/lune ciblée",
                "Enviar recursos al Planeta/Luna",
            ],
            5 :
            [
                "Afficher/masquer les cibles",
                "Mostrar objetivos ignorados",
            ],
            6 :
            [
                "Rentabilité minimale d'une cible pour être considéré comme intéressante",
                "Rentabilidad minima que debe alcanzar el objetivo para q valga la pena sangron",
            ],
            7 :
            [
                "Active/désactive la suppression automatique des rapports inintéréssants",
                "Toggle automatic removal of low rentability reports",
            ],
            8 :
            [
                "Active/désactive le tableau d'espionnage",
                "Toggle spy table",
            ],
            9 :
            [
                "Ignorer cette planète",
                "Saltar planeta",
            ],
            10 :
            [
                "Envoyer vers...",
                "enviar a...",
            ],
            11 :
            [
                "Active/désactive la vue compacte",
                "vista compacta",
            ],
            12 :
            [
                "Quantité de ressources à laisser ici",
                "Cantidad de recursos que deben quedarse en el planeta",
            ],
            13 :
            [
                "Liste des cibles",
                "Lista de objetivos",
            ],
            14 :
            [
                "Aucun résultat trouvé",
                "No se encontraron datos",
            ],
            15 :
            [
                "PT",
                "NPC",
            ],
            16 :
            [
                "GT",
                "NGC",
            ],
            17 :
            [
                "Epingler ces données",
                "Mantener info.",
            ],
            18 :
            [
                "Ressources en vol",
                "Recursos en Vuelo",
            ],
            19 :
            [
                "Vit.",
                "Vel.",
            ],
            20 :
            [
                "Espionner la planète",
                "Espiar Planeta",
            ],
            21 :
            [
                "Espionner la lune",
                "Espiar Luna",
            ],
            22 :
            [
                "Attaquer la planète",
                "Atacar Planeta",
            ],
            23 :
            [
                "Technologie hyperespace",
                "Tecnologia de Hiperespacio",
            ],
            24 :
            [
                "Seuil rentabilité (RVal)",
                "MArgen de Rentabilidad)",
            ],
            25 :
            [
                "Quantité de ressources à garder",
                "Cantidad de recursos a mantener",
            ],
        }

        return '<span class="ogl-translated">'+text[id][this.language]+'</span>';
    }

    importExport()
    {
        let container = this.createDOM('div', {'class':'ogl-dialogContainer ogl-importExport'}, '<h1>'+this.getTranslatedText(0)+'</h1>');
        let text = container.appendChild(this.createDOM('textarea', {}, JSON.stringify(this.json)));
        text.addEventListener('click', () => text.select());

        container.appendChild(this.createDOM('hr'));
        container.appendChild(this.createDOM('span', {}, this.getTranslatedText(23)));
        container.appendChild(this.createDOM('span', {'class':'ogl-right'}, this.json.tech114));
        container.appendChild(this.createDOM('hr'));
        container.appendChild(this.createDOM('span', {}, this.getTranslatedText(24)));

        // limit option
        let rvalInput = container.appendChild(this.createDOM('input', {'type':'text',
            'class':'ogl-rvalInput ogl-formatInput tooltip', 'value':this.json.options.rvalLimit, 'title':this.getTranslatedText(6)}));
        container.appendChild(this.createDOM('hr'));

        let importBtn = container.appendChild(this.createDOM('button', {'class':'btn_blue'}, 'Save'));
        importBtn.addEventListener('click', () =>
        {
            this.json = JSON.parse(text.value);
            this.json.options.rvalLimit = parseInt(this.removeNumSeparator(rvalInput.value));
            this.saveData();
            document.location.reload();
        });

        let resetBtn = container.appendChild(this.createDOM('button', {'class':'btn_blue ogl-btn_red'}, 'Reset'));
        resetBtn.addEventListener('click', () =>
        {
            let reset = confirm("Voulez vous vraiment supprimer les données d'OGLight ?");
            if(reset)
            {
                this.json = {};
                this.saveData();
                document.location.reload();
            }
        });

        container.appendChild(this.createDOM('div', {'class':'clearfloat'}));

        this.popup(false, container);
    }
}

window.addEventListener ("DOMContentLoaded", () =>
{
    let oglight = new OGLight();
});

GM_addStyle(`
#rechts
{
    margin-top:-57px;
}

#countColonies
{
    background:linear-gradient(to right, #1c2b38 45%, #090e13) !important;
    box-shadow:inset 0 1px rgba(255,255,255,.07);
    font-size:10px;
    height:22px !important;
    line-height:22px !important;
    margin:0 0 5px 0 !important;
    outline:1px solid #000;
}

.smallplanet
{
    height:auto !important;
    margin-bottom:5px !important;
    position:relative !important;
    height:31px !important;
    width:100% !important;
}

.planetlink, .moonlink
{
    background:linear-gradient(to right, #1c2b38 45%, #090e13);
    background-position:0 !important;
    box-shadow:inset 0 1px rgba(255,255,255,.07), inset 0 16px rgba(255,255,255,.03);
    outline:1px solid #000;
    height:100% !important;
    margin:0 !important;
    overflow:hidden;
    padding:0 !important;
    position:absolute;
    top:0 !important;
}

.planetlink
{
    left:0 !important;
    width:114px;
}

.moonlink
{
    left:auto !important;
    right:0 !important;
    width:30px;
}

.planetlink:hover, .moonlink:hover
{
    outline-color:#fff;
}

.planetlink.active, .moonlink.active
{
    background:linear-gradient(to right, #862f88, #090e13);
}

.planetlink.ogl-target, .moonlink.ogl-target
{
    outline-color:#ffc937;
}

.planetlink .ogl-timer, .moonlink .ogl-timer
{
    background:#ab2a2a;
    border:1px solid #121a23;
    border-radius:50%;
    bottom:0;
    content:'';
    height:5px;
    right:1px;
    position:absolute;
    top:1px;
    width:5px;
}

.planetlink .ogl-medium, .moonlink .ogl-medium
{
    background:#ce9021;
}

.planetlink .ogl-short, .moonlink .ogl-short
{
    background:#36bb6c;
}

.planetlink .planetPic, .moonlink img
{
    display:none;
}

.planetlink .planet-name
{
    color:#fff !important;
    font-size:10px !important;
    font-weight:normal !important;
    position:absolute;
    top:3px !important;
}

.planetlink .planet-koords
{
    color:#99c6f5 !important;
    font-size:10px !important;
    font-weight:normal !important;
    opacity:.7;
    position:absolute !important;
    top:15px !important;
    transform:translateX(0);
    transition:transform .2s, opacity .2s;
}

.planetlink:hover .planet-koords
{
    opacity:0;
    transform:translateX(-10px);
}

.planetlink.active .planet-koords
{
    color:#ffbfc9 !important;
}


.planetlink .planet-name,
.planetlink .planet-koords,
.planetlink .ogl-mines
{
    font-size:10px !important;
    left:5px !important;
}

.ogl-planet, .ogl-moon
{
    background:#3c536d;
    border-radius:12px;
    cursor:pointer;
    height:12px;
    right:2px;
    padding:0;
    position:absolute;
    bottom:2px;
    width:12px;
    z-index:1;
}

.ogl-planet:hover
{
    background:#f87bfb !important;
}

.ogl-planet:after
{
    border:2px solid transparent;
    border-bottom:2px solid #1d2b3a;
    border-radius:50%;
    content:'';
    display:block;
    height:16px;
    left:-8px;
    position:absolute;
    top:-10px;
    transform:rotate(-20deg);
    width:19px;
}

.ogl-planet:hover:after
{
    border-bottom:2px solid #a62fa9 !important;
}

.ogl-moon
{
    background:none;
    box-shadow:inset -6px -3px #3c536d;
}

.moonlink .ogl-moon:hover
{
    box-shadow:inset -6px -3px #f87bfb !important;
}

.planetlink .ogl-mines
{
    color:#ffbfc9 !important;
    opacity:0;
    position:absolute;
    top:15px !important;
    transform:translateX(-10px);
    transition:transform .2s, opacity .2s;
}

.planetlink:hover .ogl-mines
{
    opacity:.7;
    transform:translateX(0);
}

.smallplanet .constructionIcon
{
    bottom:2px !important;
    left:auto !important;
    right:52px !important;
    top:auto !important;
    z-index:10;
}

 .smallplanet .constructionIcon.moon
{
    left:auto !important;
    right:15px !important;
}

.smallplanet .alert
{
    left:auto !important;
    right:52px !important;
    top:2px !important;
    z-index:10;
}

.smallplanet .alert.moon
{
    left:auto !important;
    right:15px !important;
}

#galaxytable
{
    background:#0e1115;
}

#galaxytable tbody
{
    border-spacing:1px;
}

#galaxytable tbody tr
{
    background:linear-gradient(to left, #090e13, #1c2b38, #090e13);
}

#galaxytable tbody tr td
{
    background:none !important;
    border-radius:0;
    box-shadow:inset 0 1px rgba(255,255,255,.07), inset 0 15px rgba(255,255,255,.03);
    outline:1px solid #000;
    text-shadow:1px 1px #000;
    filter:brightness(100%) !important;
}

#galaxytable tbody tr td.planetname
{
    width:160px !important;
}

#galaxytable tbody tr td.action
{
    width:83px !important;
}

#galaxytable tbody tr td.moon a
{
    width:38px !important;
}

#galaxytable tbody tr td .moon_a
{
    background-size:30px !important;
    width:100% !important;
}

#galaxytable .playername
{
    padding:0 7px;
    position:relative;
    text-align:left;
}

#galaxytable .playername > a
{
    display:inline-block;
}

#galaxytable .playername .status_abbr_longinactive
{
    color:#888 !important;
}

#galaxytable .playername .status_abbr_inactive
{
    color:#c3c3c3 !important;
}

#galaxytable .playername span
{
    display:inline-block;
    overflow:hidden;
    text-overflow:ellipsis;
    vertical-align:top;
    max-width:60px;
    white-space:nowrap;
}

#galaxytable .allytag
{
    position:relative;
}

#galaxytable tr[data-marked].debris.ogl-active td
{
    background:#c14529 !important;
    opacity:1 !important;
}

#galaxytable .debrisField
{
    background:none !important;
    color:#fff;
    font-size:10px;
    line-height:14px;
    padding:0;
    width:100% !important;
}

#galaxytable tr[class*="filtered_filter"],
#galaxytable tr[data-marked="gray"]
{
    background:none;
    opacity:1 !important;
}

tr[class*="filtered_filter"] td,
tr[data-marked="gray"] td,
.ogl-stalkPlanets [data-marked="gray"]
{
    opacity:.2 !important;
}

#galaxytable .debris.ogl-active
{
    background:#c14529 !important;
    opacity:1 !important;
}

#galaxytable tr[data-marked]:not([data-marked="gray"])
{
    box-shadow:inset 0 50px 0 rgba(0,0,0,.5);
}

#galaxytable tr[data-marked]:not([data-marked="gray"]) td
{
    opacity:1 !important;
}

#galaxytable .ogl-highlighted
{
    filter:contrast(.9) brightness(1.4) saturate(1.2);
}

.ogl-colors
{
    background:linear-gradient(-45deg, #fff, #ab2727, #f3de4c, #28c78d, #1f8ad6, #8e35d2, #fff);
    background:#212121;
    border:2px dotted #414f5d;
    border-radius:50%;
    box-shadow:inset 0 5px 5px rgba(0,0,0,.7);
    cursor:pointer;
    height:16px;
    position:absolute;
    top:5px;
    width:16px;
}

.ogl-colors:hover
{
    box-shadow:inset 0 50px rgba(255,255,255,.1), inset 0 5px 5px rgba(0,0,0,.7);
}

div[data-marker], [data-marked] .ogl-colors
{
    background:currentColor;
    border:2px solid currentColor;
    border-radius:50%;
    box-shadow:inset 0 50px rgba(0,0,0,.9);
    cursor:pointer;
    height:16px;
    width:16px;
}

.ogl-spyTable .ogl-colors
{
    height:20px;
    left:1px;
    padding:0;
    top:1px;
    width:20px;
}

.ogl-colorChoice
{
    background:rgba(0,0,0,.5);
    border-radius:6px;
    display:grid;
    grid-gap:10px;
    grid-template-columns:repeat(2, 1fr);
    padding:10px;
}

div[data-marker].ogl-active,
[data-marked] .ogl-colors,
div[data-marker]:hover
{
    box-shadow:inset 0 50px rgba(0,0,0,.3), inset 0 5px 5px rgba(0,0,0,.3);
}

[data-marker="red"], [data-marked="red"] .ogl-colors, [data-toggle="red"] { color:#ab2727; }
[data-marker="yellow"], [data-marked="yellow"] .ogl-colors, [data-toggle="yellow"] { color:#f3de4c; }
[data-marker="green"], [data-marked="green"] .ogl-colors, [data-toggle="green"] { color:#28c78d; }
[data-marker="blue"], [data-marked="blue"] .ogl-colors, [data-toggle="blue"] { color:#1f8ad6; }
[data-marker="violet"], [data-marked="violet"] .ogl-colors, [data-toggle="violet"] { color:#8e35d2; }
[data-marker="gray"], [data-marked="gray"] .ogl-colors, [data-toggle="gray"] { color:#8a8a8a; }

.ogl-stalkPlanets [data-marked="red"] { background:#ab2727 !important; }
.ogl-stalkPlanets [data-marked="yellow"] { background:#f3de4c !important; }
.ogl-stalkPlanets [data-marked="green"] { background:#28c78d !important; }
.ogl-stalkPlanets [data-marked="blue"] { background:#1f8ad6 !important; }
.ogl-stalkPlanets [data-marked="violet"] { background:#8e35d2 !important; }

.ogl-spyTable tr { background:#33333e; }
.ogl-spyTable tr[data-marked="red"] { background:#6b3e3f !important; }
.ogl-spyTable tr[data-marked="yellow"] { background:#696734 !important; }
.ogl-spyTable tr[data-marked="green"] { background:#21544b !important; }
.ogl-spyTable tr[data-marked="blue"] { background:#225477 !important; }
.ogl-spyTable tr[data-marked="violet"] { background:#5d3d77 !important; }

#galaxytable tr[data-marked="red"] { background:linear-gradient(to left, #090e13, #b13434, #090e13) !important; }
#galaxytable tr[data-marked="yellow"] { background:linear-gradient(to left, #090e13, #907923, #090e13) !important; }
#galaxytable tr[data-marked="green"] { background:linear-gradient(to left, #090e13, #2c846f, #090e13) !important; }
#galaxytable tr[data-marked="blue"] { background:linear-gradient(to left, #090e13, #2677b1, #090e13) !important; }
#galaxytable tr[data-marked="violet"] { background:linear-gradient(to left, #090e13, #5d2b94, #090e13) !important; }

.ogl-targetIcon
{
    background:#6b2020 !important;
    cursor:pointer;
    height:100%;
    position:relative;
    width:100%;
}

.ogl-targetIcon:before
{
    background:#c14d4d;
    border-radius:50%;
    border:6px double #fff;
    box-sizing:border-box;
    content:'';
    height:15px;
    left:50%;
    position:absolute;
    top:50%;
    transform:translate(-50%, -50%);
    width:15px;
}

.ogl-targetIcon:hover:before
{
    background:#cd33ff;
    border-color:#e39fff;
}

.ogl-needed
{
    background:#141e26;
    border-radius:5px 0;
    font-size:11px;
    left:2px;
    padding:3px 4px;
    position:absolute;
    top:2px;
}

.ogl-spyTable
{
    border-spacing:0 1px;
    font-size:11px;
    text-align:center;
    width:100%;
}

.ogl-spyTable figure
{
    margin-left:3px;
    vertical-align:sub;
}

.ogl-spyTable tr:not(:first-child):hover
{
    outline:1px solid #ffc937;
}

.ogl-spyTable tr:nth-child(odd)
{
    box-shadow:inset 0 -40px rgba(0,0,0,.4);
}

.ogl-spyTable tr:nth-child(even)
{
    box-shadow:inset 0 -40px rgba(0,0,0,.5);
}

.ogl-spyTable td, .ogl-spyTable th
{
    color:#8193a2;
    height:26px;
    margin:auto;
    padding:0 3px;
    position:relative;
}

.ogl-spyTable th
{
    background:#0a0d0e;
    color:#d4d4d4;
    font-size:10px;
}

.ogl-spyTable .ogl-headerColors
{
    width:20px;
}

.ogl-spyTable th[data-filter]
{
    cursor:pointer;
}

.ogl-spyTable th[data-filter]:hover,
.ogl-spyTable th[data-filter].ogl-active
{
    background:#862f88;
    color:#fff;
}

.ogl-spyTable th[data-filter]:after
{
    content:'<>';
    display:inline-block;
    font-family:consolas;
    font-size:9px;
    margin-left:3px;
    transform:rotate(90deg);
}

.ogl-spyTable .ogl-metal
{
    background:#52504f;
}

.ogl-spyTable .ogl-crystal
{
    background:#406b8a;
}

.ogl-spyTable .ogl-deut
{
    background:#376f58;
}

.ogl-spyTable a
{
    color:inherit;
    text-decoration:none;
}

.ogl-spyTable a:hover
{
    color:orange;
}

.ogl-spyTable tr > *:nth-child(odd)
{
    box-shadow:inset 0 -40px rgba(0,0,0,.2);
}

.ogl-spyTable .ogl-spyOptions *
{
    margin:0 1px;
}

.ogl-spyTable .ogl-attacked td:not(.ogl-colors)
{
    color:#f49cf5;
}

.ogl-spyTable .ogl-good
{
    color:#73d2af !important;
}

.ogl-spyTable .ogl-care
{
    color:#d2b62c !important;
}

.ogl-spyTable .ogl-danger
{
    color:#fb6a6a !important;
}

.ogl-spyTable .ogl-name
{
    padding-left:5px;
    text-align:left;
}

.ogl-spyTable .ogl-sub
{
    background:linear-gradient(to left, #090e13, #0c1319, #090e13);
}

.ogl-spyTable .ogl-lootable:not(:hover)
{
    background:none !important;
}

.ogl-spyTable .ogl-lootable:hover
{
    color:#fff !important;
}

.ogl-spyTable .ogl-sc,
.ogl-spyTable .ogl-lc,
.ogl-spyTable .ogl-pf
{
    image-rendering:pixelated;
    min-width:26px;
}

.ogl-spyTable .ogl-sc:before,
.ogl-spyTable .ogl-lc:before,
.ogl-spyTable .ogl-pf:before
{
    background:url('https://gf3.geo.gfsrv.net/cdn53/7a9861be0c38bf7de05a57c56d73cf.jpg') no-repeat !important;
    background-size:550px 825px !important;
    display:block;
    content:'';
    height:26px;
    left:50%;
    position:absolute;
    top:0;
    transform:translateX(-50%);
    width:26px;
}

.ogl-spyTable .ogl-sc:before
{
    background-position:42.1% 51.72% !important;
}

.ogl-spyTable .ogl-lc:before
{
    background-position:47.36% 51.72% !important;
}

.ogl-spyTable .ogl-pf:before
{
    background-position:78.94% 51.72% !important;
}

.ogl-tableOptions
{
    border-bottom:2px solid #1d1d1d;
    height:20px;
    text-align:right;
    width:100%;
}

.ogl-tableOptions:before
{
    content:'OGL options:';
    margin-right:5px;
    vertical-align:top;
}

.ogl-tableOptions > *
{
    float:right !important;
}

.ogl-tableOptions button
{
    cursor:pointer;
    margin-left:5px;
}

.ogl-smallBtn
{
    height:16px !important;
    line-height:10px !important;
    min-width:0 !important;
    padding:0 4px !important;
}

.ogl-none
{
    background:#000;
    color:gold;
    font-size:16px;
    line-height:30px;
    text-align:center;
    width:30px;
}

.ogl-harvestOptions
{
    background:#171e25;
    box-shadow:inset 0 1px rgba(255,255,255,.07);
    display:grid;
    grid-template-columns:repeat(5, 1fr);
    justify-items:center;
    margin-top:5px;
    outline:1px solid #000;
    padding:3px;
    text-align:center;
    width:141px;
}

.ogl-option
{
    background-color:#4f2361;
    border:1px solid #000;
    border-radius:4px;
    color:#fff !important;
    cursor:pointer;
    display:inline-block;
    font-size:11px;
    height:22px;
    image-rendering:crisp-edges;
    image-rendering:-moz-crisp-edges;
    image-rendering:-webkit-optimize-contrast;
    line-height:22px;
    overflow:hidden;
    position:relative;
    text-decoration:none;
    width:22px;
}

.ogl-option:after
{
    background:linear-gradient(to top, #000 50%, #fff 50%);
    bottom:0;
    content:'';
    display:block;
    height:100%;
    opacity:.1;
    position:absolute;
    width:100%;
}

.ogl-option:hover:after
{
    background:linear-gradient(to top, #8500a5 50%, #fa40ff 50%);
    opacity:.5;
}

.ogl-harvestMission
{
    background:url("https://gf2.geo.gfsrv.net/cdn14/f45a18b5e55d2d38e7bdc3151b1fee.jpg") no-repeat;
    background-position:30% 0 !important;
    background-size:calc(22px * 11) !important;
}

.ogl-harvestMission.ogl-transpoIcon
{
    background-position:50% 0 !important;
}

.ogl-harvestMission.ogl-active
{
    background-position-y:0 !important;
}

.ogl-defaultCargo
{
    background:url("https://gf2.geo.gfsrv.net/cdn7e/41c09757d8212f48fc574515c8bc87.jpg") no-repeat;
    background-position:69.3% 0 !important;
    background-size:calc(22px * 14) !important;
}

.ogl-defaultCargo.ogl-smallCargo
{
    background-position:61.3% 0 !important;
}

.ogl-harvestType
{
    background:#262879;
}

.ogl-autoHarvest
{
    background:url("https://gf2.geo.gfsrv.net/cdn14/f45a18b5e55d2d38e7bdc3151b1fee.jpg") no-repeat;
    background-position:10% 0 !important;
    background-size:calc(22px * 11) !important;
}

.ogl-autoHarvest.ogl-active
{
    border:1px solid #ffc937;
}

.ogl-harvest
{
    transform:scale(1.15);
    transform-origin:bottom right;
}

.ogl-skip
{
    position:absolute;
    left:2px;
    top:2px;
    z-index:10;
}

.ogl-skipList
{
    background-color:#13181d;
    box-shadow:inset 0 1px rgba(255,255,255,.05);
    color:#96a0a2 !important;
    line-height:24px;
    outline:1px solid #000;
    padding:0 5px;
    position:relative;
}

.ogl-skipList:nth-child(odd)
{
    background-color:#0d1014;
}

.ogl-skipList:hover
{
    background:rgba(255, 215, 0, 0.1) !important;
    color:#e6648e !important;
    outline:1px solid gold;
    z-index:10;
}

.ogl-skipList figure
{
    margin-left:5px;
}

.ogl-ranking
{
    position:absolute;
    right:5px;
}

.ogl-stalkContainer h1
{
    display:inline-block;
    margin-right:5px;
    vertical-align:sub;
}

.ogl-toggle.ogl-active
{
    box-shadow:inset 0 50px rgba(0,0,0,.3);
}

.ogl-toggle.ogl-active:before
{
    color:#fff;
    content:"✓";
    display:inline-block;
    left:0;
    line-height:16px;
    text-align:center;
    top:0;
    width:100%;
}

.ogl-toggle:hover
{
    opacity:.7;
}

.ogl-toggle
{
    background:currentColor;
    border:2px solid currentColor;
    border-radius:3px;
    box-shadow:inset 0 50px rgba(0,0,0,.9);
    display:inline-block;
    height:14px;
    margin-right:5px;
    vertical-align:middle;
    width:14px;
}

.ogl-stalk h1 a, .ogl-ranking
{
    color:#e6648e !important;
    font-size:10px;
}

.ogl-stalk h1 a:hover, .ogl-ranking:hover
{
    color:orange !important;
    text-decoration:underline !important;
}

.ogl-stalk h1 s
{
    color:#fff;
}

.ogl-stalkPlanets
{
    display:grid;
    grid-gap:5px;
    grid-template-columns:repeat(4, 1fr);
}

.ogl-tooltip .ogl-stalkPlanets
{
    grid-template-columns:repeat(3, 1fr);
}

.ogl-sideStalk .ogl-stalkPlanets
{
    max-height:none;
}

.ogl-stalkPlanets > a
{
    background:#1e2123;
    border:2px solid #2f2f2f;
    border-radius:3px;
    box-sizing:border-box;
    color:#fff !important;
    cursor:pointer;
    display:block;
    font-size:11px;
    height:27px;
    line-height:23px;
    padding:0 22px 0 8px;
    position:relative;
    text-decoration:none !important;
    text-align:left !important;
}

.ogl-stalkPlanets > a.ogl-main i
{
    color:gold;
    font-size:10px;
    font-style:normal;
    margin-left:4px;
}

.ogl-stalkPlanets [data-marked]:not([data-marked="gray"])
{
    border:2px solid rgba(0, 0, 0, 0.44);
    box-shadow:inset 0 50px 0 rgba(0,0,0,.6);
}

.ogl-stalkPlanets > a.ogl-active
{
    border:2px dotted rgba(255,255,255,.7) !important;
}

.ogl-stalkPlanets > a:hover
{
    border:2px solid #FF5722 !important;
}

.ogl-stalkPlanets.ogl-stalkList a
{
    opacity:1 !important;
    text-align:center;
}

.ogl-stalkPlanets .ogl-moon
{
    bottom:5px;
    box-shadow:inset -6px -3px rgba(0,0,0,.5);
    right:6px;
    transform:scale(1);
}

.ogl-stalkPlanets .ogl-moon.ogl-active
{
    box-shadow:inset -6px -3px gold;
}

.ogl-stalkPlanets .ogl-moon:hover:not(.ogl-active)
{
    box-shadow:inset -6px -3px rgba(0,0,0,.5) !important;
}

.ogl-stalkPlanets .splitLine
{
    grid-column: 1/-1;
}

.ogl-textRight
{
    text-align:right;
}

.ogl-lock
{
    background:rgba(0,0,0,.7) !important;
    box-sizing:border-box;
    color:#fff;
    height:30px;
    line-height:30px !important;
    text-align:left;
    width:100%;
}

.ogl-lock:before
{
    background:url("//gf1.geo.gfsrv.net/cdn6f/91ad13c8f9a7e9390085d12adde508.png");
    background-position:0 -272px;
    background-repeat:no-repeat;
    content:'';
    display:inline-block;
    margin:0 10px 0 5px;
    height:16px;
    vertical-align:sub;
    width:16px;
}

.ogl-lock.ogl-active:before
{
    filter:sepia(100%) hue-rotate(-50deg) saturate(10);
}

.ogl-lock > span
{
    display:inline-block;
    overflow:hidden;
    text-overflow:ellipsis;
    max-width:130px;
    vertical-align:top;
    white-space:nowrap;
}

.ogl-sideLock
{
    background:url("//gf1.geo.gfsrv.net/cdn6f/91ad13c8f9a7e9390085d12adde508.png");
    background-position:0 -272px;
    background-repeat:no-repeat;
    filter:sepia(100%) hue-rotate(-50deg) saturate(10);
    height:16px;
    left:100%;
    position:absolute;
    width:16px;
    z-index:1;
}

.ogl-sideLockFilled
{
    filter:sepia(100%) hue-rotate(80deg) saturate(3);
}

#allornone .secondcol
{
    background:#0d1014;
    border-radius:5px;
    display:grid !important;
    grid-template-columns:repeat(4, 1fr);
    padding:5px !important;
    width:150px !important;
}

#allornone .secondcol .clearfloat
{
    display:none !important;
}

#allornone .secondcol *
{
    float:none !important;
}

.ogl-prefab
{
    background:url(https://gf2.geo.gfsrv.net/cdn7e/41c09757d8212f48fc574515c8bc87.jpg);
    background-position:calc(-8px * 30) 0 !important;
    background-size:calc(30px * 14) !important;
    border:1px solid #000;
    cursor:pointer;
    display:inline-block;
    height:30px;
    position:relative;
    width:30px;
    z-index:10;
}

.ogl-prefab:before
{
    background:url(https://gf2.geo.gfsrv.net/cdn14/f45a18b5e55d2d38e7bdc3151b1fee.jpg) no-repeat;
    background-size:calc(36px * 11) !important;
    background-position:-3px -5px;
    border:1px solid #000;
    content:'';
    display:block;
    height:28px;
    right:-5px;
    position:absolute;
    top:-5px;
    transform:scale(.5);
    transform-origin:top right;
    width:28px;
}

.ogl-prefab:hover
{
    border:1px solid orange;
}

.ogl-gtexpe
{
    background-position:calc(-9px * 30) 0 !important;
}

.ogl-importExport .ogl-rvalInput
{
    cursor:auto !important;
    float:right;
    height:14px;
    line-height:16px;
    padding:0 4px;
    text-align:center;
    width:60px !important;
}

.ogl-importExport .ogl-right
{
    margin-top:0;
}

.ogl-importExport .btn_blue
{
    float:right;
    margin-left:5px;
}

.ogl-quickLinks
{
    box-sizing:border-box;
    display:grid;
    grid-gap:1px;
    grid-template-columns:auto 40px;
    user-select:none;
}

.ogl-quickLinks > div
{
    background-color:#13181d;
    box-shadow:inset 0 1px rgba(255,255,255,.05);
    color:#96a0a2 !important;
    line-height:24px;
    outline:1px solid #000;
    position:relative;
}

.ogl-quickLinks > .ogl-quickPlanet:nth-of-type(4n+3),
.ogl-quickLinks > .ogl-quickPlanet:nth-of-type(4n+3) + div
{
    background-color:#0d1014;
}

.ogl-quickPlanet
{
    cursor:pointer;
    font-size:11px;
    padding:0 8px;
}

.ogl-quickMoon
{
    cursor:pointer;
    text-align:center !important;
}

.ogl-quickEmpty
{
    background-color:#3c1212 !important;
}

.ogl-quickPlanet:not(.ogl-quickEmpty):hover, .ogl-quickMoon:not(.ogl-quickEmpty):hover
{
    background:rgba(255, 94, 0, 0.18) !important;
    color:#ffa330 !important;
    outline:1px solid #ad5b16;
    z-index:10;
}

#shortcuts .dropdown.planets
{
    display:none !important;
}

.ogl-quickBtn
{
    background:#1e2c39;
    border:1px solid #000;
    border-radius:4px;
    box-shadow:inset 0 1px 3px rgba(255,255,255,.1), 0 0 10px 3px #192026;
    box-sizing:border-box;
    display:block;
    height:24px;
    line-height:22px;
    margin-top:4px;
    padding:0 4px;
    position:relative;
    width:144px;
}

.ogl-quickBtn:before
{
    background:url("https://gf3.geo.gfsrv.net/cdne1/d03835718066a5a592a6426736e019.png");
    background-position:100% -488px;
    content:'';
    display:block;
    height:24px;
    position:absolute;
    right:-1px;
    top:-1px;
    width:24px;
}

.ogl-quickBtn:hover
{
    background:#243746;
}

.ogl-quickBtn:hover:before
{
    background-position:100% -512px;
}

.maincontent .ogl-shortHeader
{
    height:auto !important;
    min-height:40px !important;
}

.maincontent .ogl-shortHeader #slot01
{
    right:40px !important;
}

.maincontent .ogl-shortHeader + #technologydetails_wrapper
{
    display:none !important;
    margin-top:-48px !important;
    position:relative !important;
}

.maincontent .ogl-shortHeader + #technologydetails_wrapper.slide-up
{
    display:block !important;
}

.toggleHeader
{
    background:url("//gf1.geo.gfsrv.net/cdn0b/d55059f8c9bab5ebf9e8a3563f26d1.gif") no-repeat 0 -22px !important;
    cursor:pointer;
    height:22px;
    position:absolute;
    right:13px;
    top:8px;
    width:23px;
}

.ogl-shortHeader .toggleHeader, .shortHeader .toggleHeader
{
    background:url("//gf1.geo.gfsrv.net/cdn0b/d55059f8c9bab5ebf9e8a3563f26d1.gif") no-repeat 0 0 !important;
}

.ogl-hidden
{
    display:none !important;
}

.eventFleet[data-mission-type="1"],
.fleetDetails[data-mission-type="1"]
{
    background:#3e2724 !important;
}

.eventFleet[data-mission-type="3"],
.fleetDetails[data-mission-type="3"]
{
    background:#2c351d !important;
}

.eventFleet[data-mission-type="4"],
.fleetDetails[data-mission-type="4"]
{
    background:#15312c !important;
}

.eventFleet[data-mission-type="6"],
.fleetDetails[data-mission-type="6"]
{
    background:#35340f !important;
}

.eventFleet[data-mission-type="7"],
.fleetDetails[data-mission-type="7"]
{
    background:#173f61 !important;
}

.eventFleet[data-mission-type="8"],
.fleetDetails[data-mission-type="8"]
{
    background:#0d2f15 !important;
}

.eventFleet[data-mission-type="9"],
.fleetDetails[data-mission-type="9"]
{
    background:#381313 !important;
}

.eventFleet[data-mission-type="15"],
.fleetDetails[data-mission-type="15"]
{
    background:#192542 !important;
}

#eventContent tr:nth-child(odd)
{
    box-shadow:inset 0 150px 0 rgba(0,0,0,.2);
}

.eventFleet[data-return-flight="true"],
.fleetDetails[data-return-flight="1"]
{
    box-shadow:inset 0 150px 0 rgba(0,0,0,.45);
}

#eventContent tr[data-return-flight="true"]:nth-child(odd)
{
    box-shadow:inset 0 150px 0 rgba(0,0,0,.55);
}

#eventContent tr[data-return-flight="true"] td
{
    color:rgba(255,255,255,.5);
}

.eventFleet .countDown, .eventFleet .arrivalTime
{
    text-align:left;
    text-indent:5px;
}

.ogl-translated
{
    font-size:11px;
}

.ogl-defaultCargo .ogl-translated
{
    background:rgba(0,0,0,.7);
    display:block;
    font-size:10px;
}

.ogl-keepRes
{
    background:linear-gradient(to top, #de8225, #da5a15);
    border:none;
    border-radius:2px;
    box-shadow:inset 0 5px #e88748, inset 0 1px #df8b39, inset 0 -1px #dd9828;
    color:#fff;
    float:right;
    height:11px;
    line-height:11px;
    margin-top:1px;
    padding:0;
    text-align:center;
    width:14px;
}

.ogl-keepRes.ogl-active
{
    background:linear-gradient(to top, #a02b8d, #c44ecc);
    box-shadow:inset 0 5px #d748e8, inset 0 1px #ce5fca, inset 0 -1px #de47da;
}

.res #selectMinMetal,
.res #selectMinCrystal,
.res #selectMinDeuterium,
.res #selectMaxMetal,
.res #selectMaxCrystal,
.res #selectMaxDeuterium
{
    cursor:pointer;
}

.ogl-sideStalk
{
    background:#171d23;
    margin-top:15px;
    outline:1px solid #000;
    padding:10px;
    position:relative;
    width:127px;
}

.ogl-sideStalk .close-tooltip
{
    position:absolute;
    right:0;
    top:0;
}

.ogl-sideStalk hr
{
    background:rgba(255,255,255,.2);
    border:none;
    height:1px;
}

.ogl-sideStalk h1 a
{
    color:#e6648e !important;
    font-size:10px;
}

.ogl-sideStalk .ogl-stalkPlanets
{
    grid-template-columns:repeat(1, 1fr);
}

.ogl-sideStalk .ogl-stalkPlanets a
{
    width:auto;
}

.ogl-stalk .icon_eye
{
    cursor:pointer;
    filter:sepia(100%) hue-rotate(-50deg) saturate(5);
    position:absolute;
    top:2px;
    right:20px;
}

.ogl-right
{
    float:right;
    margin-top:5px;
    text-align:right;
}

.ogl-fullGrid
{
    grid-column:1/-1;
}

.ogl-dialog h1
{
    grid-column:1/-1;
    margin-bottom:10px;
}

.ogl-flyingGrid > div
{
    display:grid;
    grid-gap:10px;
    grid-template-columns:repeat(4,1fr);
    overflow-y:auto;
}

.ogl-flyingGrid > div > div
{
    background:#0f1317;
    padding:10px;
}

.ogl-flyingGrid .ogl-metal span,
.ogl-flyingGrid .ogl-crystal span,
.ogl-flyingGrid .ogl-deut span
{
    display:inline-block;
    margin-right:10px;
    width:20px;
}

.ogl-flyingGrid .ogl-destination
{
    text-align:center;
}

.ogl-hiddenTooltip
{
    display:none !important;
    visibility:hidden !important;
    z-index:-1 !important;
}

.ogl-fleetSpeed
{
    background:linear-gradient(to left, #248469, #b9801a, #a72525);
    display:grid;
    grid-template-columns:repeat(10, 1fr);
    margin-top:8px;
}

.ogl-fleetSpeed > div
{
    border-bottom:1px solid #000;
    border-top:1px solid #000;
    box-shadow:inset 0 1px rgba(255,255,255,.07),
        inset 0 11px rgba(255,255,255,.15),
        inset 1px 0 rgba(255,255,255,.2);
    color:#fff;
    cursor:pointer;
    font-size:11px;
    padding:4px 3px;
    text-align:center;
    text-shadow:1px 1px rgba(0,0,0,.4);
}

.ogl-fleetSpeed > div:hover
{
    background:rgba(255,255,255,.2);
}

.ogl-fleetSpeed > div.ogl-active
{
    background:#751f63;
    box-shadow:inset 0 1px rgba(255,255,255,.07),
        inset 0 11px rgba(255,255,255,.07),
        inset 1px 0 rgba(255,255,255,.2),
        inset -1px 0 rgba(0,0,0,.3),
        0 0 5px 5px rgba(0,0,0,.25);
    outline:2px solid #fff;
    z-index:3;
}

.ogl-tooltip
{
    background:#171d23;
    border:2px solid #364352;
    border-radius:7px;
    box-shadow:0 0 10px #000;
    display:none;
    font-size:11px;
    padding:10px;
    position:absolute;
    transform:translateX(-50%) translateY(-100%);
    max-width:370px;
    width:fit-content;
    z-index:100000;
}

.ogl-tooltip div[style*="display:none;"]
{
    display:block !important;
}

.ogl-tooltip a
{
    color:cornflowerblue;
    text-decoration:none;
}

.ogl-tooltip a:hover
{
    color:orange;
}

.ogl-tooltip.ogl-active
{
    display:block;
}

.ogl-tooltip hr, .ogl-dialog hr
{
    background:#364352;
    border:none;
    height:1px;
}

.ogl-tooltip .ogl-date,
.ogl-sideStalk .ogl-date
{
    color:#61768e;
    font-size:10px;
}

.ogl-tooltip .ogl-pin
{
    position:absolute;
    right:26px;
    top:7px;
}

.ogl-tooltip .ogl-pin:hover
{
    box-shadow:inset 0 1px rgba(255,255,255,.1), inset 0 50px rgba(255,255,255,.2);
}

.ogl-tooltip .ogl-ranking
{
    position:relative !important;
    right:auto !important;
}

.ogl-tooltip .icon_chat,
.ogl-tooltip .icon_user,
.ogl-tooltip .icon_against
{
    margin-right:0px;
}

.ogl-tooltip .galaxyTooltip
{
    display:block !important;
}

.ogl-tooltip.ogl-autoHide .close-tooltip
{
    display:none;
}

.ogl-tooltip.ogl-tooltipLeft
{
    transform:translateX(-100%);
}

.ogl-tooltip.ogl-tooltipRight
{
    transform:none;
}

.ogl-tooltip.ogl-tooltipBottom
{
    transform:translateX(-50%);
}

.ogl-tooltip:after
{
    background:#171d23;
    border-bottom:2px solid #364352;
    border-right:2px solid #364352;
    bottom:-6px;
    content:'';
    display:block;
    height:15px;
    left:50%;
    pointer-events:none;
    position:absolute;
    transform:translateX(-50%) rotate(45deg);
    width:15px;
    z-index:-1;
}

.ogl-tooltip.ogl-tooltipLeft:after
{
    border:none;
    border-top:2px solid #364352;
    border-right:2px solid #364352;
    bottom:auto;
    left:auto;
    top:8px;
    transform:rotate(45deg);
    right:-6px;
}

.ogl-tooltip.ogl-tooltipRight:after
{
    border:none;
    border-bottom:2px solid #364352;
    border-left:2px solid #364352;
    bottom:auto;
    left:-6px;
    transform:rotate(45deg);
    top:8px;
}

.ogl-tooltip.ogl-tooltipBottom:after
{
    border:none;
    border-top:2px solid #364352;
    border-left:2px solid #364352;
    bottom:auto;
    left:50%;
    top:-8px;
    transform:translateX(-50%) rotate(45deg);
}

.ogl-listSeparator
{
    background:rgba(255,255,255,.1);
    font-size:14px;
    margin-top:5px;
    padding:5px 0;
    text-align:center;
}

.ogl-listSeparator:after
{
    content:'>';
    display:inline-block;
    float:right;
    font-family:consolas;
    margin-right:10px;
    transform:rotate(90deg);
}

.ogl-dialogOverlay
{
    align-items:center;
    background:rgba(0,0,0,.7);
    bottom:0;
    display:none;
    justify-content:center;
    left:0;
    position:fixed;
    right:0;
    top:0;
    z-index:1000;
}

.ogl-dialogOverlay.ogl-active
{
    display:flex;
}

.ogl-dialog
{
    background:#1a222b;
    display:inline-flex;
    overflow:hidden;
    padding:20px;
    position:fixed;
    max-width:700px;
}

.ogl-dialog .close-tooltip
{
    position:absolute;
    right:5px;
    top:5px;
}

.ogl-dialogContent
{
    max-height:70vh;
    overflow-y:auto;
    padding:10px;
}

.ogl-dialogContent .ogl-stalkPlanets
{
    align-content:start;
    background:#0d1117;
    padding:10px;
    min-height:300px;
    min-width:467px;
}

.ogl-dialogContent .ogl-stalkPlanets .ogl-targetItem
{
    width:112px;
}

.ogl-tabList
{
    display:inline-block;
    vertical-align:top;
    width:50%;
}

.ogl-tabList .ogl-tab
{
    background:#334258;
    border-radius:2px;
    color:#fff;
    cursor:pointer;
    margin-right:2px;
    margin-bottom:2px;
    padding:5px 0;
    text-align:center;
}

.ogl-tabList .ogl-tab:hover
{
    background:#a95b19;
}

.ogl-tabList .ogl-tab.ogl-active
{
    background:#a95b19;
    opacity:1 !important;
}

.ogl-tab.ogl-isEmpty
{
    opacity:.2;
}

.ogl-colorHidden,
.ogl-galaxyHidden,
.ogl-systemHidden
{
    display:none !important;
}

.ogl-atk
{
    background:#c14d4d;
    border:6px double #fff;
    border-radius:50%;
    box-sizing:border-box;
    height:14px;
    position:absolute;
    bottom:4px;
    right:3px;
    width:14px;
}

.ogl-atk:hover
{
    background:#cd33ff;
    border-color:#e39fff;
}

.ogl-fleetInfo div:nth-of-type(1)
{
    color:#edff54;
}

.ogl-fleetInfo div:nth-of-type(2)
{
    color:#66f8ff;
}

.ogl-fleetInfo div:nth-of-type(3)
{
    color:#ff7c7c;
}

.ogl-fleetInfo span
{
    display:inline-block;
    width:50px;
}

#civilships .ogl-fret
{
    bottom:5px;
    color:#edff54;
    font-size:10px;
    position:absolute;
    right:20px;
}

/* FLEET INFO TOOTIP
------------------------------- */
table.fleetinfo tr td,
table.fleetinfo tr th
{
    padding:2px 5px;
}

table.fleetinfo tr:nth-child(even)
{
    box-shadow:inset 0 50px rgba(0,0,0,.2);
}

table.fleetinfo tr:nth-child(odd)
{
    box-shadow:inset 0 50px rgba(0,0,0,.4);
}

table.fleetinfo tr:nth-last-child(-n+3) .value
{
    position:absolute;
    right:10px;
}

table.fleetinfo tr:nth-last-child(3),
.ogl-metal
{
    color:#dc6e6e;
}

table.fleetinfo tr:nth-last-child(2),
.ogl-crystal
{
    color:#73e5ff;
}

table.fleetinfo tr:nth-last-child(1),
.ogl-deut
{
    color:#a6e0b0;
}

/* BTN_BLUE
------------------------------- */
.btn_blue
{
    background:#485f93 !important;
    border:1px solid #5b77b5 !important;
    border-radius:2px !important;
}

.ogl-btn_red
{
    background:#b13131 !important;
    border:1px solid #de3e3e !important;
}

.btn_blue:hover
{
    background:#c75817 !important;
    border:1px solid #e06c29 !important;
}

/* ICONS
------------------------------- */
.close-tooltip, .icon_chat,
.icon_close, .icon_fastforward, .icon_user,
.icon_missile, .icon_eye, .icon_against,
.icon_maximize, .icon_trash,
.ogl-pin
{
    background:currentColor;
    color:#485f93 !important;
    cursor:pointer;
    border-radius:2px;
    box-shadow:inset 0 1px rgba(255,255,255,.1);
    height:16px;
    overflow:hidden;
    position:relative;
    width:16px;
}

/*.ogl-tableOptions .icon
{
    background:#696969;
}*/

.close-tooltip.ogl-active, .icon_chat.ogl-active,
.icon_close.ogl-active, .icon_fastforward.ogl-active, .icon_user.ogl-active,
.icon_missile.ogl-active, .icon_eye.ogl-active, .icon_against.ogl-active,
.icon_maximize.ogl-active, .icon_trash.ogl-active,
.ogl-pin.ogl-active, .ogl-tableOptions .icon.ogl-active
{
    color:#813383 !important;
}

.close-tooltip:hover, .icon_chat:hover,
.icon_close:hover, .icon_fastforward:hover, .icon_user:hover,
.icon_missile:hover, .icon_eye:hover, .icon_against:hover,
.icon_maximize:hover, .icon_trash:hover,
.ogl-pin:hover, .ogl-tableOptions .icon:hover
{
    color:#c75817 !important;
}

.icon.hueRotate
{
    background:#41846b !important;
    filter:none !important;
}

.icon_eye:before
{
   background:#fff;
   border-radius:0 12px;
   content:'';
   display:block;
   height:14px;
   left:50%;
   position:absolute;
   top:50%;
   transform:translate(-50%, -50%) scale(.6, .85) rotate(-45deg);
   width:14px;
}

.icon_eye:after
{
   background:inherit;
   border-radius:10px;
   content:'';
   display:block;
   height:4px;
   left:50%;
   position:absolute;
   top:50%;
   transform:translate(-68%, -35%);
   width:4px;
}

.icon_chat:before
{
    background:#fff;
    border-radius:1px;
    content:'';
    display:block;
    height:7px;
    left:50%;
    position:absolute;
    top:50%;
    transform:translate(-50%, -60%);
    width:10px;
}

.icon_chat:after
{
    background:#fff;
   content:'';
   display:block;
   height:4px;
   left:50%;
   position:absolute;
   top:50%;
   transform:rotate(45deg) translate(-10%, 20%);
   width:4px;
}

.icon_close:before,
.close-tooltip:before
{
    background:#fff;
    content:'';
    display:block;
    height:9px;
    left:50%;
    position:absolute;
    top:50%;
    transform:translate(-50%, -50%) rotate(45deg);
    width:2px;
}

.icon_close:after,
.close-tooltip:after
{
    background:#fff;
    content:'';
    display:block;
    height:9px;
    left:50%;
    position:absolute;
    top:50%;
    transform:translate(-50%, -50%) rotate(-45deg);
    width:2px;
}

.icon_fastforward:before
{
    border-bottom:2px solid #fff;
    border-right:2px solid #fff;
    box-sizing:border-box;
    content:'';
    display:block;
    height:6px;
    left:50%;
    position:absolute;
    top:50%;
    transform:translate(-20%, -50%) rotate(-45deg);
    width:6px;
}

.icon_fastforward:after
{
    border-bottom:2px solid #fff;
    border-right:2px solid #fff;
    box-sizing:border-box;
    content:'';
    display:block;
    height:6px;
    left:50%;
    position:absolute;
    top:50%;
    transform:translate(-110%, -50%) rotate(-45deg);
    width:6px;
}

.icon_user:before
{
    background:#fff;
    border-radius:50px 50px 0 0;
    content:'';
    display:block;
    height:6px;
    left:50%;
    position:absolute;
    top:60%;
    transform:translate(-50%, -50%);
    width:12px;
}

.icon_user:after
{
    background:#fff;
    border:2px solid currentColor;
    border-radius:10px;
    content:'';
    display:block;
    height:6px;
    left:50%;
    position:absolute;
    top:30%;
    transform:translate(-50%, -50%);
    width:6px;
}

.icon_missile:before
{
    border:2px solid #fff;
    border-radius:50%;
    box-sizing:border-box;
    content:'';
    display:block;
    height:11px;
    left:50%;
    position:absolute;
    top:50%;
    transform:translate(-50%, -50%);
    width:11px;
}

.icon_missile:after
{
    background:#fff;
    border-radius:50%;
    content:'';
    display:block;
    height:3px;
    left:50%;
    position:absolute;
    top:50%;
    transform:translate(-50%, -50%);
    width:3px;
}

.icon_against:before
{
    border:2px solid #fff;
    border-radius:50%;
    box-sizing:border-box;
    content:'';
    display:block;
    height:11px;
    left:50%;
    position:absolute;
    top:50%;
    transform:translate(-50%, -50%);
    width:11px;
}

.icon_against:after
{
    background:#fff;
    content:'';
    display:block;
    height:9px;
    left:50%;
    position:absolute;
    top:50%;
    transform:translate(-50%, -50%) rotate(-45deg);
    width:2px;
}

.ogl-pin:before
{
    border-left:3px solid transparent;
    border-right:3px solid transparent;
    border-top:3px solid #fff;
    content:'';
    display:block;
    height:0;
    left:50%;
    position:absolute;
    top:72%;
    transform:translate(-50%, -50%);
    width:0;
}

.ogl-pin:after
{
    border:2px solid #fff;
    border-radius:50%;
    content:'';
    display:block;
    height:4px;
    left:50%;
    position:absolute;
    top:45%;
    transform:translate(-50%, -50%);
    width:4px;
}

.icon_maximize:before
{
    border:1px solid #fff;
    box-sizing:border-box;
    content:'';
    display:block;
    height:6px;
    left:60%;
    position:absolute;
    top:45%;
    transform:translate(-50%, -50%);
    width:6px;
}

.icon_maximize:after
{
    background:inherit;
    border:1px solid #fff;
    box-sizing:border-box;
    content:'';
    display:block;
    height:6px;
    left:40%;
    position:absolute;
    top:55%;
    transform:translate(-50%, -50%);
    width:6px;
}

.icon_trash:before
{
    background:repeating-linear-gradient(to right, transparent, #fff 2px);
    border:1px solid #fff;
    border-radius:0 0 2px 2px;
    border-top:none;
    box-sizing:border-box;
    content:'';
    display:block;
    height:8px;
    left:50%;
    position:absolute;
    top:55%;
    transform:translate(-50%, -50%);
    width:8px;
}

.icon_trash:after
{
    background:#fff;
    box-sizing:border-box;
    content:'';
    display:block;
    height:2px;
    left:50%;
    position:absolute;
    top:25%;
    transform:translate(-50%, -50%);
    width:10px;
}

/* EXPEDITION DEBRIS
------------------------------- */
.expeditionDebrisSlotBox
{
    align-items:center;
    display:grid;
    grid-template-columns:20% auto auto auto;
}

.expeditionDebrisSlotBox li
{
    list-style:none;
}

.expeditionDebrisSlotBox > img
{
    float:right;
    justify-self:center;
}

.expeditionDebrisSlotBox > div
{
    line-height:1.6;
    text-align:left;
}

.expeditionDebrisSlotBox a:hover
{
    color:orange;
}
`);