The_Stubbs / InfoCompte

// ==UserScript==
// @name         InfoCompte
// @namespace    https://openuserjs.org/users/The_Stubbs
// @version      9.3.3
// @description  InfoCompte script for OGame
// @author       Vulca, benneb & now The Stubbs
// @license      MIT
// @match        https://*.ogame.gameforge.com/game/*
// @updateURL    https://openuserjs.org/meta/The_Stubbs/InfoCompte.meta.js
// @downloadURL  https://openuserjs.org/install/The_Stubbs/InfoCompte.user.js
// @grant        GM_addStyle
// @grant        GM_getValue
// @grant        GM_setValue
// @run-at       document-idle
// @mood         https://www.youtube.com/watch?v=lklHS1G9E-M&t
// ==/UserScript==

// Modules
	const Classes = (function(){
		class Body {
			static get_costs_defences_from( technologies, rates ){
				let result = 0;
				if( technologies ){
					for( const id of Technologies.ids.units.defences ){
						const technology = technologies[ id ];
						if( technology ){
							result += Unit.get_costs_from( id, technology, rates );
						}
					}
				}
				return result;
			}
			static get_costs_ships_statics_from( technologies, rates ){
				let result = 0;
				if( technologies ){
					for( const id of Technologies.ids.units.ships.statics ){
						const technology = technologies[ id ];
						if( technology ){
							result += Unit.get_costs_from( id, technology, rates );
						}
					}
				}
				return result;
			}
		}
		class Positions {
			static get_costs_mines_from( positions, rates ){
				let result = 0;
				for( const coordinates in positions ){
					const position = positions[ coordinates ];
					const technologies = position.planet.technologies;
					result += Planet.get_costs_mines_from( technologies, rates );
				}
				return result;
			}
			static get_productions_upgraded_from( data, rates ){
				const positions = data.game.player.positions;
				const researches = data.game.player.researches;
				const initial_planet_count = Object.values( positions ).length;
				const upgraded_planet_count = Math.ceil( researches[124].upgraded * .5 ) + 1;
				let result = 0;
				for( const coordinates in positions ){
					const position = positions[ coordinates ];
					result += Planet.get_productions_upgraded_from( data, position, rates );
				}
				return result / initial_planet_count * upgraded_planet_count;
			}
		}
		class Position {
			static bonuses = {
				metal: [1.35, 1.23, 1.17, 1],
				crystal: [1.4, 1.3, 1.2, 1]
			}
			static get_metal_production_bonus( value ){
				const i = Math.min( 3, Math.abs( value - 8 ) );
				return Position.bonuses.metal[ i ];
			}
			static get_crystal_production_bonus( value ){
				const i = Math.min( 3, value - 1 );
				return Position.bonuses.crystal[ i ];
			}
		}
		class Researches {
			static get_costs_from( technologies, rates ){
				let result = 0;
				if( technologies ){
					for( const id of Technologies.ids.researches ){
						const technology = technologies[ id ];
						if( technology ){
							result += Upgradable.get_costs_from( id, technology, rates );
						}
					}
				}
				return result;
			}
			static get_costs_upgrade_from( technologies, rates ){
				let result = 0;
				if( technologies ){
					for( const id of Technologies.ids.researches ){
						const technology = technologies[ id ];
						if( technology ){
							result += Upgradable.get_costs_upgrade_from( id, technology, rates );
						}
					}
				}
				return result;
			}
		}
		class Technologies {
			static costs = {
				1: {
					metal: 60,
					crystal: 15,
					deuterium: 0,
					coefficient: 1.5
				},
				2: {
					metal: 48,
					crystal: 24,
					deuterium: 0,
					coefficient: 1.6
				},
				3: {
					metal: 225,
					crystal: 75,
					deuterium: 0,
					coefficient: 1.5
				},
				4: {
					metal: 75,
					crystal: 30,
					deuterium: 0,
					coefficient: 1.5
				},
				12: {
					metal: 900,
					crystal: 360,
					deuterium: 180,
					coefficient: 1.8
				},
				14: {
					metal: 400,
					crystal: 120,
					deuterium: 200,
					coefficient: 2
				},
				15: {
					metal: 1_000_000,
					crystal: 500_000,
					deuterium: 100_000,
					coefficient: 2
				},
				21: {
					metal: 400,
					crystal: 200,
					deuterium: 100,
					coefficient: 2
				},
				22: {
					metal: 1_000,
					crystal: 0,
					deuterium: 0,
					coefficient: 2
				},
				23: {
					metal: 1_000,
					crystal: 500,
					deuterium: 0,
					coefficient: 2
				},
				24: {
					metal: 1_000,
					crystal: 1_000,
					deuterium: 0,
					coefficient: 2
				},
				31: {
					metal: 200,
					crystal: 400,
					deuterium: 200,
					coefficient: 2
				},
				33: {
					metal: 0,
					crystal: 50_000,
					deuterium: 100_000,
					coefficient: 2
				},
				34: {
					metal: 20_000,
					crystal: 40_000,
					deuterium: 0,
					coefficient: 2
				},
				36: {
					metal: 200,
					crystal: 0,
					deuterium: 50,
					coefficient: 5
				},
				41: {
					metal: 20_000,
					crystal: 40_000,
					deuterium: 20_000,
					coefficient: 2
				},
				42: {
					metal: 20_000,
					crystal: 40_000,
					deuterium: 20_000,
					coefficient: 2
				},
				43: {
					metal: 2_000_000,
					crystal: 4_000_000,
					deuterium: 2_000_000,
					coefficient: 2
				},
				44: {
					metal: 20_000,
					crystal: 20_000,
					deuterium: 1_000,
					coefficient: 2
				},
				106: {
					metal: 200,
					crystal: 1_000,
					deuterium: 200,
					coefficient: 2
				},
				108: {
					metal: 0,
					crystal: 400,
					deuterium: 600,
					coefficient: 2
				},
				109: {
					metal: 800,
					crystal: 200,
					deuterium: 0,
					coefficient: 2
				},
				110: {
					metal: 200,
					crystal: 600,
					deuterium: 0,
					coefficient: 2
				},
				111: {
					metal: 1_000,
					crystal: 0,
					deuterium: 0,
					coefficient: 2
				},
				113: {
					metal: 0,
					crystal: 800,
					deuterium: 400,
					coefficient: 2
				},
				114: {
					metal: 0,
					crystal: 4_000,
					deuterium: 2_000,
					coefficient: 2
				},
				115: {
					metal: 400,
					crystal: 0,
					deuterium: 600,
					coefficient: 2
				},
				117: {
					metal: 2_000,
					crystal: 4_000,
					deuterium: 600,
					coefficient: 2
				},
				118: {
					metal: 10_000,
					crystal: 20_000,
					deuterium: 6_000,
					coefficient: 2
				},
				120: {
					metal: 200,
					crystal: 100,
					deuterium: 0,
					coefficient: 2
				},
				121: {
					metal: 1_000,
					crystal: 300,
					deuterium: 100,
					coefficient: 2
				},
				122: {
					metal: 2_000,
					crystal: 4_000,
					deuterium: 1_000,
					coefficient: 2
				},
				123: {
					metal: 240_000,
					crystal: 400_000,
					deuterium: 160_000,
					coefficient: 2
				},
				124: {
					metal: 4_000,
					crystal: 8_000,
					deuterium: 4_000,
					coefficient: 1.75
				},
				199: {
					metal: 0,
					crystal: 0,
					deuterium: 0,
					coefficient: 3
				},
				202: {
					metal: 2_000,
					crystal: 2_000,
					deuterium: 0
				},
				203: {
					metal: 6_000,
					crystal: 6_000,
					deuterium: 0
				},
				204: {
					metal: 3_000,
					crystal: 1_000,
					deuterium: 0
				},
				205: {
					metal: 6_000,
					crystal: 4_000,
					deuterium: 0
				},
				206: {
					metal: 20_000,
					crystal: 7_000,
					deuterium: 2_000
				},
				207: {
					metal: 45_000,
					crystal: 15_000,
					deuterium: 0
				},
				208: {
					metal: 10_000,
					crystal: 20_000,
					deuterium: 10_000
				},
				209: {
					metal: 10_000,
					crystal: 6_000,
					deuterium: 2_000
				},
				210: {
					metal: 0,
					crystal: 1_000,
					deuterium: 0
				},
				211: {
					metal: 50_000,
					crystal: 25_000,
					deuterium: 15_000
				},
				212: {
					metal: 0,
					crystal: 2_000,
					deuterium: 500
				},
				213: {
					metal: 60_000,
					crystal: 50_000,
					deuterium: 15_000
				},
				214: {
					metal: 5_000_000,
					crystal: 4_000_000,
					deuterium: 1_000_000
				},
				215: {
					metal: 30_000,
					crystal: 40_000,
					deuterium: 15_000
				},
				217: {
					metal: 2_000,
					crystal: 2_000,
					deuterium: 1_000
				},
				218: {
					metal: 85_000,
					crystal: 55_000,
					deuterium: 20_000
				},
				219: {
					metal: 8_000,
					crystal: 15_000,
					deuterium: 8_000
				},
				401: {
					metal: 2_000,
					crystal: 0,
					deuterium: 0
				},
				402: {
					metal: 1_500,
					crystal: 500,
					deuterium: 0
				},
				403: {
					metal: 6_000,
					crystal: 2_000,
					deuterium: 0
				},
				404: {
					metal: 20_000,
					crystal: 15_000,
					deuterium: 2_000
				},
				405: {
					metal: 5_000,
					crystal: 3_000,
					deuterium: 0
				},
				406: {
					metal: 50_000,
					crystal: 50_000,
					deuterium: 30_000
				},
				407: {
					metal: 10_000,
					crystal: 10_000,
					deuterium: 0
				},
				408: {
					metal: 50_000,
					crystal: 50_000,
					deuterium: 0
				},
				502: {
					metal: 8_000,
					crystal: 0,
					deuterium: 2_000
				},
				503: {
					metal: 12_500,
					crystal: 2_500,
					deuterium: 10_000
				},
				11_101: {
					metal: 7,
					crystal: 2,
					deuterium: 0,
					coefficient: 1.2
				},
				11_102: {
					metal: 5,
					crystal: 2,
					deuterium: 0,
					coefficient: 1.23
				},
				11_103: {
					metal: 20_000,
					crystal: 25_000,
					deuterium: 10_000,
					coefficient: 1.3
				},
				11_104: {
					metal: 5_000,
					crystal: 3_200,
					deuterium: 1_500,
					coefficient: 1.7
				},
				11_105: {
					metal: 50_000,
					crystal: 40_000,
					deuterium: 50_000,
					coefficient: 1.7
				},
				11_106: {
					metal: 9_000,
					crystal: 6_000,
					deuterium: 3_000,
					coefficient: 1.5
				},
				11_107: {
					metal: 25_000,
					crystal: 13_000,
					deuterium: 7_000,
					coefficient: 1.09
				},
				11_108: {
					metal: 50_000,
					crystal: 25_000,
					deuterium: 15_000,
					coefficient: 1.5
				},
				11_109: {
					metal: 75_000,
					crystal: 20_000,
					deuterium: 25_000,
					coefficient: 1.09
				},
				11_110: {
					metal: 150_000,
					crystal: 30_000,
					deuterium: 15_000,
					coefficient: 1.12
				},
				11_111: {
					metal: 80_000,
					crystal: 35_000,
					deuterium: 60_000,
					coefficient: 1.5
				},
				11_112: {
					metal: 250_000,
					crystal: 125_000,
					deuterium: 125_000,
					coefficient: 1.2
				},
				11_201: {
					metal: 5_000,
					crystal: 2_500,
					deuterium: 500,
					coefficient: 1.3
				},
				11_202: {
					metal: 7_000,
					crystal: 10_000,
					deuterium: 5_000,
					coefficient: 1.5
				},
				11_203: {
					metal: 15_000,
					crystal: 10_000,
					deuterium: 5_000,
					coefficient: 1.3
				},
				11_204: {
					metal: 20_000,
					crystal: 15_000,
					deuterium: 7_500,
					coefficient: 1.3
				},
				11_205: {
					metal: 25_000,
					crystal: 20_000,
					deuterium: 10_000,
					coefficient: 1.2
				},
				11_206: {
					metal: 35_000,
					crystal: 25_000,
					deuterium: 15_000,
					coefficient: 1.5
				},
				11_207: {
					metal: 70_000,
					crystal: 40_000,
					deuterium: 20_000,
					coefficient: 1.3
				},
				11_208: {
					metal: 80_000,
					crystal: 50_000,
					deuterium: 20_000,
					coefficient: 1.5
				},
				11_209: {
					metal: 320_000,
					crystal: 240_000,
					deuterium: 100_000,
					coefficient: 1.5
				},
				11_210: {
					metal: 320_000,
					crystal: 240_000,
					deuterium: 100_000,
					coefficient: 1.5
				},
				11_211: {
					metal: 120_000,
					crystal: 30_000,
					deuterium: 25_000,
					coefficient: 1.5
				},
				11_212: {
					metal: 100_000,
					crystal: 40_000,
					deuterium: 30_000,
					coefficient: 1.3
				},
				11_213: {
					metal: 200_000,
					crystal: 100_000,
					deuterium: 100_000,
					coefficient: 1.3
				},
				11_214: {
					metal: 160_000,
					crystal: 120_000,
					deuterium: 50_000,
					coefficient: 1.5
				},
				11_215: {
					metal: 160_000,
					crystal: 120_000,
					deuterium: 50_000,
					coefficient: 1.5
				},
				11_216: {
					metal: 320_000,
					crystal: 240_000,
					deuterium: 100_000,
					coefficient: 1.5
				},
				11_217: {
					metal: 300_000,
					crystal: 180_000,
					deuterium: 120_000,
					coefficient: 1.5
				},
				11_218: {
					metal: 500_000,
					crystal: 300_000,
					deuterium: 200_000,
					coefficient: 1.3
				},
				12_101: {
					metal: 9,
					crystal: 3,
					deuterium: 0,
					coefficient: 1.2
				},
				12_102: {
					metal: 7,
					crystal: 2,
					deuterium: 0,
					coefficient: 1.2
				},
				12_103: {
					metal: 40_000,
					crystal: 10_000,
					deuterium: 15_000,
					coefficient: 1.3
				},
				12_104: {
					metal: 5_000,
					crystal: 3_800,
					deuterium: 1_000,
					coefficient: 1.7
				},
				12_105: {
					metal: 50_000,
					crystal: 40_000,
					deuterium: 50_000,
					coefficient: 1.65
				},
				12_106: {
					metal: 10_000,
					crystal: 8_000,
					deuterium: 1_000,
					coefficient: 1.4
				},
				12_107: {
					metal: 20_000,
					crystal: 15_000,
					deuterium: 10_000,
					coefficient: 1.2
				},
				12_108: {
					metal: 50_000,
					crystal: 35_000,
					deuterium: 15_000,
					coefficient: 1.5
				},
				12_109: {
					metal: 85_000,
					crystal: 44_000,
					deuterium: 25_000,
					coefficient: 1.4
				},
				12_110: {
					metal: 120_000,
					crystal: 50_000,
					deuterium: 20_000,
					coefficient: 1.4
				},
				12_111: {
					metal: 250_000,
					crystal: 150_000,
					deuterium: 100_000,
					coefficient: 1.8
				},
				12_112: {
					metal: 250_000,
					crystal: 125_000,
					deuterium: 125_000,
					coefficient: 1.5
				},
				12_201: {
					metal: 10_000,
					crystal: 6_000,
					deuterium: 1_000,
					coefficient: 1.5
				},
				12_202: {
					metal: 7_500,
					crystal: 12_500,
					deuterium: 5_000,
					coefficient: 1.5
				},
				12_203: {
					metal: 15_000,
					crystal: 10_000,
					deuterium: 5_000,
					coefficient: 1.5
				},
				12_204: {
					metal: 20_000,
					crystal: 15_000,
					deuterium: 7_500,
					coefficient: 1.3
				},
				12_205: {
					metal: 25_000,
					crystal: 20_000,
					deuterium: 10_000,
					coefficient: 1.5
				},
				12_206: {
					metal: 50_000,
					crystal: 50_000,
					deuterium: 20_000,
					coefficient: 1.5
				},
				12_207: {
					metal: 70_000,
					crystal: 40_000,
					deuterium: 20_000,
					coefficient: 1.5
				},
				12_208: {
					metal: 160_000,
					crystal: 120_000,
					deuterium: 50_000,
					coefficient: 1.5
				},
				12_209: {
					metal: 75_000,
					crystal: 55_000,
					deuterium: 25_000,
					coefficient: 1.5
				},
				12_210: {
					metal: 85_000,
					crystal: 40_000,
					deuterium: 35_000,
					coefficient: 1.5
				},
				12_211: {
					metal: 120_000,
					crystal: 30_000,
					deuterium: 25_000,
					coefficient: 1.5
				},
				12_212: {
					metal: 100_000,
					crystal: 40_000,
					deuterium: 30_000,
					coefficient: 1.5
				},
				12_213: {
					metal: 200_000,
					crystal: 100_000,
					deuterium: 100_000,
					coefficient: 1.2
				},
				12_214: {
					metal: 220_000,
					crystal: 110_000,
					deuterium: 110_000,
					coefficient: 1.3
				},
				12_215: {
					metal: 240_000,
					crystal: 120_000,
					deuterium: 120_000,
					coefficient: 1.3
				},
				12_216: {
					metal: 250_000,
					crystal: 250_000,
					deuterium: 250_000,
					coefficient: 1.4
				},
				12_217: {
					metal: 500_000,
					crystal: 300_000,
					deuterium: 200_000,
					coefficient: 1.5
				},
				12_218: {
					metal: 300_000,
					crystal: 180_000,
					deuterium: 120_000,
					coefficient: 1.7
				},
				13_101: {
					metal: 6,
					crystal: 2,
					deuterium: 0,
					coefficient: 1.21
				},
				13_102: {
					metal: 5,
					crystal: 2,
					deuterium: 0,
					coefficient: 1.18
				},
				13_103: {
					metal: 30_000,
					crystal: 20_000,
					deuterium: 10_000,
					coefficient: 1.3
				},
				13_104: {
					metal: 5_000,
					crystal: 3_800,
					deuterium: 1_000,
					coefficient: 1.8
				},
				13_105: {
					metal: 50_000,
					crystal: 40_000,
					deuterium: 50_000,
					coefficient: 1.8
				},
				13_106: {
					metal: 7_500,
					crystal: 7_000,
					deuterium: 1_000,
					coefficient: 1.3
				},
				13_107: {
					metal: 35_000,
					crystal: 15_000,
					deuterium: 10_000,
					coefficient: 1.5
				},
				13_108: {
					metal: 50_000,
					crystal: 20_000,
					deuterium: 30_000,
					coefficient: 1.07
				},
				13_109: {
					metal: 100_000,
					crystal: 10_000,
					deuterium: 3_000,
					coefficient: 1.14
				},
				13_110: {
					metal: 100_000,
					crystal: 40_000,
					deuterium: 20_000,
					coefficient: 1.5
				},
				13_111: {
					metal: 55_000,
					crystal: 50_000,
					deuterium: 30_000,
					coefficient: 1.5
				},
				13_112: {
					metal: 250_000,
					crystal: 125_000,
					deuterium: 125_000,
					coefficient: 1.4
				},
				13_201: {
					metal: 10_000,
					crystal: 6_000,
					deuterium: 1_000,
					coefficient: 1.5
				},
				13_202: {
					metal: 7_500,
					crystal: 12_500,
					deuterium: 5_000,
					coefficient: 1.3
				},
				13_203: {
					metal: 15_000,
					crystal: 10_000,
					deuterium: 5_000,
					coefficient: 1.5
				},
				13_204: {
					metal: 20_000,
					crystal: 15_000,
					deuterium: 7_500,
					coefficient: 1.3
				},
				13_205: {
					metal: 160_000,
					crystal: 120_000,
					deuterium: 50_000,
					coefficient: 1.5
				},
				13_206: {
					metal: 50_000,
					crystal: 50_000,
					deuterium: 20_000,
					coefficient: 1.5
				},
				13_207: {
					metal: 70_000,
					crystal: 40_000,
					deuterium: 20_000,
					coefficient: 1.3
				},
				13_208: {
					metal: 160_000,
					crystal: 120_000,
					deuterium: 50_000,
					coefficient: 1.5
				},
				13_209: {
					metal: 160_000,
					crystal: 120_000,
					deuterium: 50_000,
					coefficient: 1.5
				},
				13_210: {
					metal: 85_000,
					crystal: 40_000,
					deuterium: 35_000,
					coefficient: 1.2
				},
				13_211: {
					metal: 120_000,
					crystal: 30_000,
					deuterium: 25_000,
					coefficient: 1.3
				},
				13_212: {
					metal: 160_000,
					crystal: 120_000,
					deuterium: 50_000,
					coefficient: 1.5
				},
				13_213: {
					metal: 200_000,
					crystal: 100_000,
					deuterium: 100_000,
					coefficient: 1.5
				},
				13_214: {
					metal: 160_000,
					crystal: 120_000,
					deuterium: 50_000,
					coefficient: 1.5
				},
				13_215: {
					metal: 320_000,
					crystal: 240_000,
					deuterium: 100_000,
					coefficient: 1.5
				},
				13_216: {
					metal: 320_000,
					crystal: 240_000,
					deuterium: 100_000,
					coefficient: 1.5
				},
				13_217: {
					metal: 500_000,
					crystal: 300_000,
					deuterium: 200_000,
					coefficient: 1.5
				},
				13_218: {
					metal: 300_000,
					crystal: 180_000,
					deuterium: 120_000,
					coefficient: 1.7
				},
				14_101: {
					metal: 4,
					crystal: 3,
					deuterium: 0,
					coefficient: 1.21
				},
				14_102: {
					metal: 6,
					crystal: 3,
					deuterium: 0,
					coefficient: 1.21
				},
				14_103: {
					metal: 20_000,
					crystal: 20_000,
					deuterium: 30_000,
					coefficient: 1.3
				},
				14_104: {
					metal: 7_500,
					crystal: 5_000,
					deuterium: 800,
					coefficient: 1.8
				},
				14_105: {
					metal: 60_000,
					crystal: 30_000,
					deuterium: 50_000,
					coefficient: 1.8
				},
				14_106: {
					metal: 8_500,
					crystal: 5_000,
					deuterium: 3_000,
					coefficient: 1.25
				},
				14_107: {
					metal: 15_000,
					crystal: 15_000,
					deuterium: 20_000,
					coefficient: 1.2
				},
				14_108: {
					metal: 75_000,
					crystal: 25_000,
					deuterium: 30_000,
					coefficient: 1.05
				},
				14_109: {
					metal: 87_500,
					crystal: 25_000,
					deuterium: 30_000,
					coefficient: 1.2
				},
				14_110: {
					metal: 150_000,
					crystal: 30_000,
					deuterium: 30_000,
					coefficient: 1.5
				},
				14_111: {
					metal: 75_000,
					crystal: 50_000,
					deuterium: 55_000,
					coefficient: 1.2
				},
				14_112: {
					metal: 500_000,
					crystal: 250_000,
					deuterium: 250_000,
					coefficient: 1.4
				},
				14_201: {
					metal: 10_000,
					crystal: 6_000,
					deuterium: 1_000,
					coefficient: 1.5
				},
				14_202: {
					metal: 7_500,
					crystal: 12_500,
					deuterium: 5_000,
					coefficient: 1.5
				},
				14_203: {
					metal: 15_000,
					crystal: 10_000,
					deuterium: 5_000,
					coefficient: 1.5
				},
				14_204: {
					metal: 20_000,
					crystal: 15_000,
					deuterium: 7_500,
					coefficient: 1.5
				},
				14_205: {
					metal: 25_000,
					crystal: 20_000,
					deuterium: 10_000,
					coefficient: 1.5
				},
				14_206: {
					metal: 50_000,
					crystal: 50_000,
					deuterium: 20_000,
					coefficient: 1.3
				},
				14_207: {
					metal: 70_000,
					crystal: 40_000,
					deuterium: 20_000,
					coefficient: 1.5
				},
				14_208: {
					metal: 80_000,
					crystal: 50_000,
					deuterium: 20_000,
					coefficient: 1.2
				},
				14_209: {
					metal: 320_000,
					crystal: 240_000,
					deuterium: 100_000,
					coefficient: 1.5
				},
				14_210: {
					metal: 85_000,
					crystal: 40_000,
					deuterium: 35_000,
					coefficient: 1.2
				},
				14_211: {
					metal: 120_000,
					crystal: 30_000,
					deuterium: 25_000,
					coefficient: 1.5
				},
				14_212: {
					metal: 100_000,
					crystal: 40_000,
					deuterium: 30_000,
					coefficient: 1.5
				},
				14_213: {
					metal: 200_000,
					crystal: 100_000,
					deuterium: 100_000,
					coefficient: 1.5
				},
				14_214: {
					metal: 160_000,
					crystal: 120_000,
					deuterium: 50_000,
					coefficient: 1.5
				},
				14_215: {
					metal: 240_000,
					crystal: 120_000,
					deuterium: 120_000,
					coefficient: 1.5
				},
				14_216: {
					metal: 320_000,
					crystal: 240_000,
					deuterium: 100_000,
					coefficient: 1.5
				},
				14_217: {
					metal: 500_000,
					crystal: 300_000,
					deuterium: 200_000,
					coefficient: 1.5
				},
				14_218: {
					metal: 300_000,
					crystal: 180_000,
					deuterium: 120_000,
					coefficient: 1.7
				}
			}
			static ids = {
				miniatures: {
					'https://gf2.geo.gfsrv.net/cdnd9/60555c3c87b9eb3b5ddf76780b5712.jpg': 202,
					'https://gf3.geo.gfsrv.net/cdn23/9e24203ce8e9723008272d51786780.jpg': 202,
					'https://gf1.geo.gfsrv.net/cdn34/fdbcc505474e3e108d10a3ed4a19f4.jpg': 203,
					'https://gf1.geo.gfsrv.net/cdn0c/f38c9fcab7e958698a7f8013b3cc3e.jpg': 203,
					'https://gf2.geo.gfsrv.net/cdnd2/9ed5c1b6aea28fa51f84cdb8cb1e7e.jpg': 204,
					'https://gf1.geo.gfsrv.net/cdncb/9091972f8d216eb9ab0b01b31065ff.jpg': 204,
					'https://gf1.geo.gfsrv.net/cdnf1/8266a2cbae5ad630c5fedbdf270f3e.jpg': 205,
					'https://gf1.geo.gfsrv.net/cdn66/a5931e3e4a1609da1bfe4ea7984758.jpg': 205,
					'https://gf2.geo.gfsrv.net/cdn45/b7ee4f9d556a0f39dae8d2133e05b7.jpg': 206,
					'https://gf2.geo.gfsrv.net/cdn11/26d5b34d33384155d541f8e3a56bd0.jpg': 206,
					'https://gf1.geo.gfsrv.net/cdn32/3f4a081f4d15662bed33473db53d5b.jpg': 207,
					'https://gf3.geo.gfsrv.net/cdn54/04ae451ca1bbf437b04dcb1689e7ac.jpg': 207,
					'https://gf1.geo.gfsrv.net/cdn6f/41a21e4253d2231f8937ddef1ba43e.jpg': 208,
					'https://gf2.geo.gfsrv.net/cdn4b/875d71d6af78f83966b16fc806f398.jpg': 208,
					'https://gf1.geo.gfsrv.net/cdn07/6246eb3d7fa67414f6b818fa79dd9b.jpg': 209,
					'https://gf3.geo.gfsrv.net/cdn20/6bf35a0f61e69a466a0a4691a8e089.jpg': 209,
					'https://gf3.geo.gfsrv.net/cdnb5/347821e80cafc52aec04f27c3a2a4d.jpg': 210,
					'https://gf2.geo.gfsrv.net/cdn19/4b46516da39af486f25103faacaeae.jpg': 210,
					'https://gf1.geo.gfsrv.net/cdnca/4d55a520aed09d0c43e7b962f33e27.jpg': 211,
					'https://gf1.geo.gfsrv.net/cdn35/da0705b3be831864ffa2b5a91d630d.jpg': 211,
					'https://gf2.geo.gfsrv.net/cdnda/665c65072887153d44a6684ec276e9.jpg': 212,
					'https://gf2.geo.gfsrv.net/cdnd3/5f3ca7e91fc0a9b1ee014c3c01ea41.jpg': 212,
					'https://gf3.geo.gfsrv.net/cdn2a/c2b9fedc9c93ef22f2739c49fbac52.jpg': 213,
					'https://gf3.geo.gfsrv.net/cdn82/6ba84c9dfcfff57452dcaf77d8f722.jpg': 213,
					'https://gf3.geo.gfsrv.net/cdn84/155e9e24fc1d34ed4660de8d428f45.jpg': 214,
					'https://gf1.geo.gfsrv.net/cdnfb/6be8cd7c88e3c5510e8a9d8ca64daa.jpg': 214,
					'https://gf3.geo.gfsrv.net/cdn5a/24f511ec14a71e2d83fd750aa0dee2.jpg': 215,
					'https://gf3.geo.gfsrv.net/cdn50/07f6bd1320f406d474639b7f1f499c.jpg': 215,
					'https://gf3.geo.gfsrv.net/cdn26/28e8d79a5b489dc795cc47f3adf165.jpg': 217,
					'https://gf1.geo.gfsrv.net/cdnf3/a31e24320e2814bc93a4ebef8f55b4.jpg': 217,
					'https://gf1.geo.gfsrv.net/cdn39/12d016c8bb0d71e053b901560c17cc.jpg': 218,
					'https://gf3.geo.gfsrv.net/cdn87/1febaddff40e056ce9bf0c1ac930f8.jpg': 218,
					'https://gf3.geo.gfsrv.net/cdne2/b8d8d18f2baf674acedb7504c7cc83.jpg': 219,
					'https://gf2.geo.gfsrv.net/cdn72/56a8934f9a63b45d1294eea63767e5.jpg': 219,
					'https://gf1.geo.gfsrv.net/cdn93/4c4fbd313bc449e16f5212f23d6311.jpg': 401,
					'https://gf2.geo.gfsrv.net/cdnaf/b5d139528cdf1233e61bd58184e1c5.jpg': 401,
					'https://gf2.geo.gfsrv.net/cdn19/68e11c389f7f62134def76575b27e5.jpg': 402,
					'https://gf2.geo.gfsrv.net/cdn7d/34b3f95bf2d4e3355fed09a3e1877e.jpg': 402,
					'https://gf2.geo.gfsrv.net/cdnae/3adede7d38b3ecfc7457375a4cd2a5.jpg': 403,
					'https://gf2.geo.gfsrv.net/cdnd4/9d88c2d9b8e5872bef32a7f8659695.jpg': 403,
					'https://gf2.geo.gfsrv.net/cdndb/2e7227f88e3601612093ee2e9101e0.jpg': 404,
					'https://gf3.geo.gfsrv.net/cdn2c/0fc6c29d06858b5b9ca0b0a4d1532e.jpg': 404,
					'https://gf1.geo.gfsrv.net/cdn01/2add2bd4bf0cbcf07f779bf85d43cc.jpg': 405,
					'https://gf2.geo.gfsrv.net/cdn11/4dd51eeb4ab03af617828169bffd5b.jpg': 405,
					'https://gf1.geo.gfsrv.net/cdn0c/ceed170b2583498228e9ab6b087af1.jpg': 406,
					'https://gf1.geo.gfsrv.net/cdn07/ea3e0adf01fb3cf64e1938a7c55dfb.jpg': 406,
					'https://gf1.geo.gfsrv.net/cdn93/58390eb6945e04861c99eb311366cc.jpg': 407,
					'https://gf2.geo.gfsrv.net/cdna9/4d20894a828929ff5a61f62c757149.jpg': 407,
					'https://gf1.geo.gfsrv.net/cdn95/1c77121b235b5a9e9591c7c78883d3.jpg': 408,
					'https://gf2.geo.gfsrv.net/cdnda/533c32ff26f4db6857e3e41c09d443.jpg': 408,
					'https://gf2.geo.gfsrv.net/cdnd1/fb4e438cabd12ef1b0500a0f41abc1.jpg': 502,
					'https://gf2.geo.gfsrv.net/cdn7a/40a392214240328e42014108815526.jpg': 502,
					'https://gf2.geo.gfsrv.net/cdn47/36221e9493458b9fcc776bf350983e.jpg': 503,
					'https://gf2.geo.gfsrv.net/cdn19/2cf0473c0bb2e5cf3135358ccc4edf.jpg': 503
				},
				moon: {
					buildings: [4, 12, 14, 21, 22, 23, 24, 41, 42, 43]
				},
				planet: {
					buildings: [4, 12, 14, 15, 21, 22, 23, 24, 31, 33, 34, 36, 44],
					lifeforms: {
						all: [
							11101, 11102, 11103, 11104, 11105, 11106, 11107, 11108, 11109, 11110, 11111, 11112,
							11201, 11202, 11203, 11204, 11205, 11206, 11207, 11208, 11209, 11210, 11211, 11212, 11213, 11214, 11215, 11216, 11217, 11218,
							12101, 12102, 12103, 12104, 12105, 12106, 12107, 12108, 12109, 12110, 12111, 12112,
							12201, 12202, 12203, 12204, 12205, 12206, 12207, 12208, 12209, 12210, 12211, 12212, 12213, 12214, 12215, 12216, 12217, 12218,
							13101, 13102, 13103, 13104, 13105, 13106, 13107, 13108, 13109, 13110, 13111, 13112,
							13201, 13202, 13203, 13204, 13205, 13206, 13207, 13208, 13209, 13210, 13211, 13212, 13213, 13214, 13215, 13216, 13217, 13218,
							14101, 14102, 14103, 14104, 14105, 14106, 14107, 14108, 14109, 14110, 14111, 14112,
							14201, 14202, 14203, 14204, 14205, 14206, 14207, 14208, 14209, 14210, 14211, 14212, 14213, 14214, 14215, 14216, 14217, 14218
						],
						buildings: [
							11101, 11102, 11103, 11104, 11105, 11106, 11107, 11108, 11109, 11110, 11111, 11112,
							12101, 12102, 12103, 12104, 12105, 12106, 12107, 12108, 12109, 12110, 12111, 12112,
							13101, 13102, 13103, 13104, 13105, 13106, 13107, 13108, 13109, 13110, 13111, 13112,
							14101, 14102, 14103, 14104, 14105, 14106, 14107, 14108, 14109, 14110, 14111, 14112
						],
						researches: [
							11201, 11202, 11203, 11204, 11205, 11206, 11207, 11208, 11209, 11210, 11211, 11212, 11213, 11214, 11215, 11216, 11217, 11218,
							12201, 12202, 12203, 12204, 12205, 12206, 12207, 12208, 12209, 12210, 12211, 12212, 12213, 12214, 12215, 12216, 12217, 12218,
							13201, 13202, 13203, 13204, 13205, 13206, 13207, 13208, 13209, 13210, 13211, 13212, 13213, 13214, 13215, 13216, 13217, 13218,
							14201, 14202, 14203, 14204, 14205, 14206, 14207, 14208, 14209, 14210, 14211, 14212, 14213, 14214, 14215, 14216, 14217, 14218
						]
					},
					mines: [1, 2, 3]
				},
				researches: [106, 108, 109, 110, 111, 113, 114, 115, 117, 118, 120, 121, 122, 123, 124, 199],
				units: {
					all: [202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 217, 218, 219, 401, 402, 403, 404, 405, 406, 407, 408, 502, 503],
					defences: [401, 402, 403, 404, 405, 406, 407, 408, 502, 503],
					ships: {
						all: [202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 217, 218, 219],
						statics: [212, 217]
					}
				}
			}
		}
		class Temperatures {
			static get_deuterium_production_bonus( value ){
				return 1.44 - .004 * value;
			}
		}
		class Unit {
			static get_costs_from( id, technology, rates ){
				let result = 0;
				if( technology?.value ){
					const cost = Technologies.costs[ id ];
					result += cost.metal * technology.value / rates.metal;
					result += cost.crystal * technology.value / rates.crystal;
					result += cost.deuterium * technology.value / rates.deuterium;
				}
				return result;
			}
			static get_costs_upgrade_from( id, technology, rates ){
				let result = 0;
				if( technology?.upgrade ){
					const cost = Technologies.costs[ id ];
					result += cost.metal * technology.upgrade / rates.metal;
					result += cost.crystal * technology.upgrade / rates.crystal;
					result += cost.deuterium * technology.upgrade / rates.deuterium;
				}
				return result;
			}
		}
		class Upgradable {
			static get_costs_from( id, technology, rates ){
				let result = 0;
				if( technology?.value ){
					const cost = Technologies.costs[ id ];
					for( let i = 1; i <= technology.value; i++ ){
						result += this.get_costs_level_from( i, cost, rates );
					}
				}
				return result;
			}
			static get_costs_upgrade_from( id, technology, rates ){
				let result = 0;
				if( technology?.upgrade ){
					const cost = Technologies.costs[ id ];
					for( let i = technology.value + 1; i <= technology.upgraded; i++ ){
						result += this.get_costs_level_from( i, cost, rates );
					}
				}
				return result;
			}
			static get_costs_level_from( value, cost, rates ){
				let result = 0;
				result += Math.floor( cost.metal * cost.coefficient ** ( value - 1 ) ) / rates.metal;
				result += Math.floor( cost.crystal * cost.coefficient ** ( value - 1 ) ) / rates.crystal;
				result += Math.floor( cost.deuterium * cost.coefficient ** ( value - 1 ) ) / rates.deuterium;
				return result;
			}
		}
		class Moon extends Body {
			static get_costs_buildings_from( technologies, rates ){
				let result = 0;
				if( technologies ){
					for( const id of Technologies.ids.moon.buildings ){
						const technology = technologies[ id ];
						if( technology ){
							result += Upgradable.get_costs_from( id, technology, rates );
						}
					}
				}
				return result;
			}
			static get_costs_upgrades_from( technologies, rates ){
				let result = 0;
				if( technologies ){
					for( const id of Technologies.ids.moon.buildings ){
						const technology = technologies[ id ];
						if( technology?.upgrade ){
							result += Upgradable.get_costs_upgrade_from( id, technology, rates );
						}
					}
					for( const id of Technologies.ids.units.all ){
						const technology = technologies[ id ];
						if( technology?.upgrade ){
							result += Unit.get_costs_upgrade_from( id, technology, rates );
						}
					}
				}
				return result;
			}
		}
		class Planet extends Body {
			static get_costs_buildings_from( technologies, rates ){
				let result = 0;
				if( technologies ){
					for( const id of Technologies.ids.planet.buildings ){
						const technology = technologies[ id ];
						if( technology ){
							result += Upgradable.get_costs_from( id, technology, rates );
						}
					}
				}
				return result;
			}
			static get_costs_lifeforms_buildings_from( technologies, rates ){
				let result = 0;
				if( technologies ){
					for( const id of Technologies.ids.planet.lifeforms.buildings ){
						const technology = technologies[ id ];
						if( technology ){
							result += Lifeform.get_costs_from( id, technology, rates );
						}
					}
				}
				return result;
			}
			static get_costs_lifeforms_researches_from( technologies, rates ){
				let result = 0;
				if( technologies ){
					for( const id of Technologies.ids.planet.lifeforms.researches ){
						const technology = technologies[ id ];
						if( technology ){
							result += Lifeform.get_costs_from( id, technology, rates );
						}
					}
				}
				return result;
			}
			static get_costs_mines_from( technologies, rates ){
				const metal = Planet.get_costs_mines_metal_from( technologies, rates );
				const crystal = Planet.get_costs_mines_crystal_from( technologies, rates );
				const deuterium = Planet.get_costs_mines_deuterium_from( technologies, rates );
				return metal + crystal + deuterium;
			}
			static get_costs_mines_metal_from( technologies, rates ){
				const id = 1;
				const technology = technologies?.[ id ];
				return technology ? Upgradable.get_costs_from( id, technology, rates ) : 0;
			}
			static get_costs_mines_crystal_from( technologies, rates ){
				const id = 2;
				const technology = technologies?.[ id ];
				return technology ? Upgradable.get_costs_from( id, technology, rates ) : 0;
			}
			static get_costs_mines_deuterium_from( technologies, rates ){
				const id = 3;
				const technology = technologies?.[ id ];
				return technology ? Upgradable.get_costs_from( id, technology, rates ) : 0;
			}
			static get_costs_upgrades_from( technologies, rates ){
				let result = 0;
				if( technologies ){
					for( const id of Technologies.ids.planet.buildings ){
						const technology = technologies[ id ];
						if( technology?.upgrade ){
							result += Upgradable.get_costs_upgrade_from( id, technology, rates );
						}
					}
					for( const id of Technologies.ids.planet.mines ){
						const technology = technologies[ id ];
						if( technology?.upgrade ){
							result += Upgradable.get_costs_upgrade_from( id, technology, rates );
						}
					}
					for( const id of Technologies.ids.planet.lifeforms.all ){
						const technology = technologies[ id ];
						if( technology?.upgrade ){
							result += Lifeform.get_costs_upgrade_from( id, technology, rates );
						}
					}
					for( const id of Technologies.ids.units.all ){
						const technology = technologies[ id ];
						if( technology?.upgrade ){
							result += Unit.get_costs_upgrade_from( id, technology, rates );
						}
					}
				}
				return result;
			}
			static get_productions_upgraded_from( data, position, rates ){
				const mines = Planet.get_productions_upgraded_mines_from( data, position, rates );
				const crawlers = Planet.get_productions_upgraded_crawlers_from( data, position, mines );
				const plasma = Planet.get_productions_upgraded_plasma_from( data, mines );
				const classes = Planet.get_productions_classes_from( data, mines );
				const officers = Planet.get_productions_officers_from( data, mines );
				return mines.total + crawlers + plasma + classes + officers;
			}
			static get_productions_upgraded_mines_from( data, position, rates ){
				const metal = Planet.get_productions_upgraded_mines_metal_from( data, position, rates );
				const crystal = Planet.get_productions_upgraded_mines_crystal_from( data, position, rates );
				const deuterium = Planet.get_productions_upgraded_mines_deuterium_from( data, position, rates );
				const total = metal + crystal + deuterium;
				return {
					metal,
					crystal,
					deuterium,
					total
				};
			}
			static get_productions_upgraded_mines_metal_from( data, position, rates ){
				const speed = data.game.universe.speed;
				const level = position.planet.technologies[1].upgraded;
				const bonus = Position.get_metal_production_bonus( position.location );
				return Math.round( 30 * level * 1.1 ** level * bonus * speed ) / rates.metal;
			}
			static get_productions_upgraded_mines_crystal_from( data, position, rates ){
				const speed = data.game.universe.speed;
				const level = position.planet.technologies[2].upgraded;
				const bonus = Position.get_crystal_production_bonus( position.location );
				return Math.round( 20 * level * 1.1 ** level * bonus * speed ) / rates.crystal;
			}
			static get_productions_upgraded_mines_deuterium_from( data, position, rates ){
				const speed = data.game.universe.speed;
				const level = position.planet.technologies[3].upgraded;
				const temperature = position.planet.temperatures.max;
				const bonus = Temperatures.get_deuterium_production_bonus( temperature );
				return Math.round( 10 * level * 1.1 ** level * bonus * speed ) / rates.deuterium;
			}
			static get_productions_upgraded_crawlers_from( data, position, productions ){
				const bonus = data.game.player.class === 'miner' ? 1.5 : 1;
				const factor = bonus;
				const count = position.planet.technologies[217].upgraded;
				return productions.total * Math.min( .5, .02 * bonus * factor * count );
			}
			static get_productions_upgraded_plasma_from( data, productions ){
				const level = data.game.player.researches[122].upgraded;
				const metal = productions.metal * .01 * level;
				const crystal = productions.crystal * .0066 * level;
				const deuterium = productions.deuterium * .0033 * level;
				return metal + crystal + deuterium;
			}
			static get_productions_classes_from( data, productions ){
				const player = data.game.player;
				const miner_bonus = player.class === 'miner' ? .25 : 0;
				const trader_bonus = player?.alliance?.class === 'trader' ? .05 : 0;
				return productions.total * ( miner_bonus + trader_bonus );
			}
			static get_productions_officers_from( data, productions ){
				const officers = data.game.player.officers;
				let bonus = officers.geologist ? .1 : 0;
				bonus += officers.all ? .02 : 0;
				return productions.total * bonus;
			}
		}
		class Lifeform extends Upgradable {
			static get_costs_level_from( value, cost, rates ){
				let result = 0;
				result += Math.floor( cost.metal * cost.coefficient ** ( value - 1 ) * value ) / rates.metal;
				result += Math.floor( cost.crystal * cost.coefficient ** ( value - 1 ) * value ) / rates.crystal;
				result += Math.floor( cost.deuterium * cost.coefficient ** ( value - 1 ) * value ) / rates.deuterium;
				return result;
			}
		}
		return {
			moon: Moon,
			planet: Planet,
			positions: Positions,
			researches: Researches,
			technologies: Technologies,
			upgradable: Upgradable
		};
	})();
	const Colors = (function(){
		return {
			defaults: {
				main: '#6f9fc8',
				mines: '#eb782d',
				planets_buildings: '#9c3d00',
				moons_buildings: '#83919c',
				lifeforms_buildings: '#6c56a3',
				lifeforms_researches: '#95559f',
				researches: '#0077b6',
				defences: '#16bd05',
				ships: '#e30613',
				crawlers: '#eb782d',
				metal: '#a9a9a9',
				crystal: '#8dceec',
				deuterium: '#6cc6a3'
			},
			user: {
				mines: '#eb782d',
				planets_buildings: '#9c3d00',
				moons_buildings: '#83919c',
				lifeforms_buildings: '#6c56a3',
				lifeforms_researches: '#95559f',
				researches: '#0077b6',
				defences: '#16bd05',
				ships: '#e30613',
				metal: '#a9a9a9',
				crystal: '#8dceec',
				deuterium: '#6cc6a3'
			}
		};
	})();
	const Components = (function(){
		const Chart = (function(){
			function get_html_from( data ){
				const slices = get_html_slices_from( data );
				return `<svg viewBox="0 0 100 100" transform="rotate(-90)">${ slices }</svg>`;
			}
			function get_html_slices_from( data ){
				let	rotation = 0;
				let result = '';
				for( const key in data ){
					const { percent, color } = data[ key ];
					result += get_html_slice_from( percent, color, rotation );
					rotation += percent;
				}
				return result;
			}
			function get_html_slice_from( percent, color, rotation ){
				const offset = 2 * Math.PI * 25;
				return `<circle cx=50 cy=50 r=25
								fill=transparent
								stroke=${ color }
								stroke-width=50
								stroke-dasharray="${ percent * offset } ${ offset }"
								transform="rotate( ${ rotation * 360 } 50 50 )"/>`;
			}
			return {
				get_html_from
			}
		})();
		const Energy = (function(){
			function init_from( data ){
				const positions = data.game.player.positions;
				for( const coordinates in positions ){
					const planet = positions[ coordinates ].planet;
					if( planet.id && planet.resources?.energy < 0 ){
						const element = document.querySelector( `#planet-${ planet.id } .planet-name` );
						element.classList.add( 'ic_energy-warning' );
					}
				}
			}
			return {
				init_from
			};
		})();
		const Highscores = (function(){
			function init_from( data ){
				set_gaps_from( data );
				get_highscores();
			}
			function set_gaps_from( data ){
				const points = data.game.universe.highscores[ currentCategory ][ currentType ].player.points;
				for( const element of document.querySelectorAll( '#ranks tbody tr:not( .myrank ) .score' ) ){
					const value = Types.get_number_from( element.firstChild.textContent );
					const difference = value - points;
					let content = difference > 0 ? '+' : '';
					content += Types.get_string_number_full_from( difference );
					element.title = content;
					element.classList.add( 'tooltipRight' );
				}
			}
			async function get_highscores(){
				const selector = '#stat_list_content';
				await Scraper.element_has_changed( selector );
				await Scraper.element_has_changed( selector );
				const storage = Storage.get();
				const scraper = await Scraper.get();
				const data = Data.get_from( storage, scraper );
				Storage.set_from( data );
				Highscores.init_from( data );
			}
			return {
				init_from
			};
		})();
		const Menu = (function(){
			function init(){
				set_html();
			}
			function set_html(){
				const result = `<li id="ic_menu-button">
									<span class="menu_icon">
										<div class="tooltipRight">
										<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 -960 960 960">
											<path fill="currentColor" d="m388-80-20-126q-19-7-40-19t-37-25l-118 54-93-164 108-79q-2-9-2.5-20.5T185-480q0-9 .5-20.5T188-521L80-600l93-164 118 54q16-13 37-25t40-18l20-127h184l20 126q19 7 40.5 18.5T669-710l118-54 93 164-108 77q2 10 2.5 21.5t.5 21.5q0 10-.5 21t-2.5 21l108 78-93 164-118-54q-16 13-36.5 25.5T592-206L572-80H388Zm92-270q54 0 92-38t38-92q0-54-38-92t-92-38q-54 0-92 38t-38 92q0 54 38 92t92 38Z"/>
										</svg>
										</div>
									</span>
									<a class="menubutton" href="${ Translation.support_link }" target="_blank">
										<span class="textlabel">InfoCompte ${ GM_info.script.version }</span>
									</a>
								</li>`;
				document.querySelector( '#menuTable' ).innerHTML += result;
			}
			return {
				init
			};
		})();
		const Overview = (function(){
			const Panels = (function(){
				const Account = (function(){
					function get_html_from( data ){
						const { points, percents, positions, chart } = get_data_from( data );
						return `<div id="ic_account-points-panel" class="ic_panel" data-state="expanded">
									<h3 class="ic_panel_title"><span></span>${ Translation.points_repartition }</h3>
									<div class="ic_panel_main">
										<table>
											<tr>
												<th>${ Translation.mines }</th>
												<td>${ points.planets.mines.all } — <span class="ic_percent">${ percents.planets.mines.all }</span></td>
											</tr>
											<tr>
												<th>${ Translation.planets_buildings }</th>
												<td>${ points.planets.buildings } — <span class="ic_percent">${ percents.planets.buildings }</span></td>
											</tr>
											<tr>
												<th>${ Translation.moons_buildings }</th>
												<td>${ points.moons.buildings } — <span class="ic_percent">${ percents.moons.buildings }</span></td>
											</tr>
											<tr>
												<th>${ Translation.lifeforms_buildings }</th>
												<td>${ points.planets.lifeforms.buildings } — <span class="ic_percent">${ percents.planets.lifeforms.buildings }</span></td>
											</tr>
											<tr>
												<th>${ Translation.lifeforms_researches }</th>
												<td>${ points.planets.lifeforms.researches } — <span class="ic_percent">${ percents.planets.lifeforms.researches }</span></td>
											</tr>
											<tr>
												<th>${ Translation.researches }</th>
												<td>${ points.researches } — <span class="ic_percent">${ percents.researches }</span></td>
											</tr>
											<tr>
												<th>${ Translation.ships }</th>
												<td>${ points.units.ships.all } — <span class="ic_percent">${ percents.units.ships.all }</span></td>
											</tr>
											<tr>
												<th>${ Translation.defences }</th>
												<td>${ points.units.defences } — <span class="ic_percent">${ percents.units.defences }</span></td>
											</tr>
											<tr>
												<th>${ Translation.indestructibles }</th>
												<td>
													<div>${ points.indestructibles } — <span class="ic_percent">${ percents.indestructibles }</span></div>
													<div>- ${ positions.if_destroyed } ${ Translation.if_destroyed }</div>
												</td>
											</tr>
											<tr>
												<th>${ Translation.upgrades }</th>
												<td>
													<div>${ points.upgrades } — <span class="ic_percent">${ percents.upgrades }</span></div>
													<div>+ ${ positions.when_finished } ${ Translation.when_finished }</div>
												</td>
											</tr>
										</table>
										${ Chart.get_html_from( chart ) }
									</div>
								</div>`;
					}
					function get_data_from( data ){
						const { points, percents } = data.game.player;
						return {
							points: get_data_points_from( points ),
							percents: get_data_percents_from( percents ),
							positions: get_data_positions_from( data ),
							chart: get_data_chart_from( data )
						};
					}
					function get_data_points_from( data ){
						const result = {};
						for( const key in data ){
							const value = data[ key ];
							if( Types.are_objects( value ) ){
								result[ key ] = get_data_points_from( value );
							}else{
								result[ key ] = Types.get_string_number_truncated_from( value );
							}
						}
						return result;
					}
					function get_data_percents_from( data ){
						const result = {};
						for( const key in data ){
							const value = data[ key ];
							if( Types.are_objects( value ) ){
								result[ key ] = get_data_percents_from( value );
							}else{
								result[ key ] = Types.get_percent_from( value );
							}
						}
						return result;
					}
					function get_data_positions_from( data ){
						const positions = data.game.universe.highscores?.[1][0].player.positions;
						const result = {
							if_destroyed: 0,
							when_finished: 0
						};
						if( positions ){
							result.if_destroyed = positions.if_destroyed - positions.current;
							result.when_finished = positions.current - positions.when_finished;
						}
						return result;
					}
					function get_data_chart_from( data ){
						const percents = data.game.player.percents;
						const colors = data.script.colors.user;
						return {
							mines: {
								percent: percents.planets.mines.all,
								color: colors.mines
							},
							planets_buildings: {
								percent: percents.planets.buildings,
								color: colors.planets_buildings
							},
							moons_buildings: {
								percent: percents.moons.buildings,
								color: colors.moons_buildings
							},
							lifeforms_buildings: {
								percent: percents.planets.lifeforms.buildings,
								color: colors.lifeforms_buildings
							},
							lifeforms_researches: {
								percent: percents.planets.lifeforms.researches,
								color: colors.lifeforms_researches
							},
							researches: {
								percent: percents.researches,
								color: colors.researches
							},
							ships: {
								percent: percents.units.ships.all,
								color: colors.ships
							},
							defences: {
								percent: percents.units.defences,
								color: colors.defences
							}
						};
					}
					return {
						get_html_from
					};
				})();
				const Positions = (function(){
					function get_html_from( data ){
						const rows = get_html_rows_from( get_data_from( data ) );
						return `<div id="ic_positions-points-panel" class="ic_panel" data-state="collapsed">
								<h3 class="ic_panel_title"><span></span>${ Translation.planets_points_repartition }</h3>
								<div class="ic_panel_main">
									<table>
										${ rows }
									</table>
								</div>
							</div>`;
					}
					function get_html_rows_from( positions ){
						let result = '';
						for( const coordinates in positions ){
							const position = positions[ coordinates ];
							result += `<tr>
										<th>${ coordinates }</th>
										<td>${ get_html_cells_names_from( position ) }</td>
										<td>${ get_html_cells_mines_from( position ) }</td>
										<td>${ get_html_cells_buildings_from( position ) }</td>
										<td>${ get_html_cells_lifeforms_buildings_from( position ) }</td>
										<td>${ get_html_cells_lifeforms_researches_from( position ) }</td>
										<td>${ get_html_cells_defences_from( position ) }</td>
										<td>${ get_html_cells_all_from( position ) }</td>
									</tr>`;
						}
						return result;
					}
					function get_html_cells_names_from( position ){
						const { moon, planet } = position;
						let result = `<div>${ planet.name }</div>`;
						result += moon ? `<div>${ moon.name }</div>` : '';
						return result;
					}
					function get_html_cells_mines_from( position ){
						const result = get_html_span_from( position.planet.points.mines.all );
						return `<div>${ result }</div>`;
					}
					function get_html_cells_buildings_from( position ){
						const { moon, planet } = position;
						let result = `<div>${ get_html_span_from( planet.points.buildings ) }</div>`;
						result += moon ? `<div>${ get_html_span_from( moon.points.buildings ) }</div>` : '';
						return result;
					}
					function get_html_cells_lifeforms_buildings_from( position ){
						const result = get_html_span_from( position.planet.points.lifeforms.buildings );
						return `<div>${ result }</div>`;
					}
					function get_html_cells_lifeforms_researches_from( position ){
						const result = get_html_span_from( position.planet.points.lifeforms.researches );
						return `<div>${ result }</div>`;
					}
					function get_html_cells_defences_from( position ){
						const { moon, planet } = position;
						let result = `<div>${ get_html_span_from( planet.points.units.defences ) }</div>`;
						result += moon ? `<div>${ get_html_span_from( moon.points.units.defences ) }</div>` : '';
						return result;
					}
					function get_html_cells_all_from( position ){
						const { moon, planet } = position;
						let result = `<div>
										${ get_html_span_from( planet.points.statics ) }
										 —
										<span class="ic_percent">${ planet.percent }</span>
									</div>`;
						if( moon ){
							result +=`<div>
										${ get_html_span_from( moon.points.statics ) }
										 —
										<span class="ic_percent">${ moon.percent }</span>
									</div>`;
						}
						return result;
					}
					function get_html_span_from( points ){
						return `<span class="tooltipRight" title="${ points.full }">${ points.compact }</span>`;
					}
					function get_data_from( data ){
						const player = data.game.player;
						const positions = player.positions;
						const points = player.points.positions;
						const percents = player.percents.positions;
						const result = {};
						for( const coordinates in positions ){
							const { moon, planet } = positions[ coordinates ];
							const position = result[ coordinates ] = {
								planet: {
									name: planet.name || Translation.planet,
									points: get_data_points_from( points[ coordinates ].planet ),
									percent: Types.get_percent_from( percents[ coordinates ].planet.statics )
								}
							};
							if( moon ){
								position.moon = {
									name: moon.name || Translation.moon,
									points: get_data_points_from( points[ coordinates ].moon ),
									percent: Types.get_percent_from( percents[ coordinates ].moon.statics )
								};
							}
						}
						return result;
					}
					function get_data_points_from( data ){
						const result = {};
						for( const key in data ){
							const value = data[ key ];
							if( Types.are_objects( value ) ){
								result[ key ] = get_data_points_from( value );
							}else{
								result[ key ] = {
									full: Types.get_string_number_truncated_from( value ),
									compact: Types.get_string_number_compact_from( value )
								}
							}
						}
						return result;
					}
					return {
						get_html_from
					};
				})();
				const Productions = (function(){
					function get_html_from( data ){
						const { mines, lifeforms, bonuses, total, rates } = get_data_from( data );
						return `<div id="ic_productions-panel" class="ic_panel" data-state="collapsed">
									<h3 class="ic_panel_title"><span></span>${ Translation.daily_productions }</h3>
									<div class="ic_panel_main">
										<table>
											<tr>
												<th></th>
												<th></th>
												<th></th>
												<th></th>
												<th><abbr title="${ Translation.deuterium_equivalent } ( ${ rates.metal }/${ rates.crystal }/${ rates.deuterium } )">${ Translation.total }</abbr></th>
											</tr>
											<tr>
												<th>${ Translation.mines }</th>
												<td>${ mines.metal }</td>
												<td>${ mines.crystal }</td>
												<td>${ mines.deuterium }</td>
												<td>${ mines.all }</td>
											</tr>
											<tr>
												<th>${ Translation.lifeforms }</th>
												<td>${ lifeforms.metal }</td>
												<td>${ lifeforms.crystal }</td>
												<td>${ lifeforms.deuterium }</td>
												<td>${ lifeforms.all }</td>
											</tr>
											<tr>
												<th>${ Translation.objects } & ${ Translation.officers }</th>
												<td>${ bonuses.metal }</td>
												<td>${ bonuses.crystal }</td>
												<td>${ bonuses.deuterium }</td>
												<td>${ bonuses.all }</td>
											</tr>
											<tr>
												<th>${ Translation.total }</th>
												<td>${ total.metal }</td>
												<td>${ total.crystal }</td>
												<td>${ total.deuterium }</td>
												<td>${ total.all }</td>
											</tr>
										</table>
									</div>
								</div>`;
					}
					function get_data_from( data ){
						const productions = data.game.player.productions;
						const rates = data.script.rates;
						const result = {};
						for( const key in productions ){
							const value = productions[ key ];
							result[ key ] = {
								all: Types.get_string_number_truncated_from( value.metal * 24 / rates.metal + value.crystal * 24 / rates.crystal + value.deuterium * 24 / rates.deuterium ),
								metal: Types.get_string_number_truncated_from( value.metal * 24 ),
								crystal: Types.get_string_number_truncated_from( value.crystal * 24 ),
								deuterium: Types.get_string_number_truncated_from( value.deuterium * 24 )
							}
						}
						result.rates = {
							metal: Types.get_string_number_full_from( parseFloat( rates.metal ) ),
							crystal: Types.get_string_number_full_from( parseFloat( rates.crystal ) ),
							deuterium: Types.get_string_number_full_from( parseFloat( rates.deuterium ) )
						};
						return result;
					}
					return {
						get_html_from
					};
				})();
				const Amortizations = (function(){
					const Tables = (function(){
						const Mines = (function(){
							function get_next_rentabilities(){
								const data = Storage.get()
								const positions = data.game.player.positions;
								const results = {};
								for( const coordinates in positions ){
									const position = positions[ coordinates ];
									const technologies = position.planet.technologies;
									const result = results[ position.planet.name ] = {};
									for( let i = 1; i < 4; i++ ){
										result[ i ] = {
											level: technologies[ i ].upgraded + 1,
											rentability: Types.get_duration_from( get_next_rentability_from( data, position, i ) )
										};
									}
								}
								return results;
							}
							function get_next_rentability_from( data, position, id ){
								const technology = position.planet.technologies[ id ];
								const rates = data.script.rates;
								// save inital values before manual upgrade
								const initial_production = Classes.planet.get_productions_upgraded_from( data, position, rates );
								const initial_value = technology.value;
								const initial_upgrade = technology.upgrade;
								const initial_upgraded = technology.upgraded;
								// set manual upgrade
								technology.value = technology.upgraded;
								technology.upgrade = 1;
								technology.upgraded = technology.value + 1;
								// compute needed values
								const upgrade_cost = Classes.upgradable.get_costs_upgrade_from( id, technology, rates );
								const upgraded_production = Classes.planet.get_productions_upgraded_from( data, position, rates );
								// restore initial values
								technology.value = initial_value;
								technology.upgrade = initial_upgrade;
								technology.upgraded = initial_upgraded;
								// return result
								const production_gains = upgraded_production - initial_production;
								return upgrade_cost / production_gains;
							}
							function get_html_from( data ){
								let result = '';
								if( data ){
									result = `<table id="ic_amortizations-tables_mines">
												<caption>${ Translation.mines }</caption>
												<tbody>${ get_html_rows_from( data ) }</tbody>
											</table>`;
								}
								return result;
							}
							function get_html_rows_from( data ){
								let result = '';
								for( const key in data ){
									const { 1: metal, 2: crystal, 3: deuterium } = data[ key ];
									result += `<tr>
												<th>${ key }</th>
												<td>
													<div>${ Translation.metal } ${ metal.level }</div>
													<div>${ metal.rentability }</div>
												</td>
												<td>
													<div>${ Translation.crystal } ${ crystal.level }</div>
													<div>${ crystal.rentability }</div>
												</td>
												<td>
													<div>${ Translation.deuterium } ${ deuterium.level }</div>
													<div>${ deuterium.rentability }</div>
												</td>
											</tr>`;
								}
								return result;
							}
							return {
								get_next_rentabilities,
								get_next_rentability_from,
								get_html_from
							};
						})();
						const Researches = (function(){
							const Astrophysics = (function(){
								function get_next_rentabilities(){
									const data = Storage.get();
									const technology = data.game.player.researches[124];
									const result = {};
									for( let i = 0; i < 3; i++ ){
										const rentability = get_next_rentability_from( data );
										technology.value = Math.ceil( technology.value * .5 ) * 2 + 1;
										technology.upgraded = technology.value;
										const level = `${ technology.upgraded - 1 }/${ technology.upgraded }`;
										result[ level ] = Types.get_duration_from( rentability );
									}
									return result;
								}
								function get_next_rentability_from( data ){
									const positions = data.game.player.positions;
									const technology = data.game.player.researches[124];
									const rates = data.script.rates;
									// save inital values before manual upgrade
									const initial_production = Classes.positions.get_productions_upgraded_from( data, rates );
									const initial_planet_count = Object.values( positions ).length;
									const initial_value = technology.value;
									const initial_upgrade = technology.upgrade;
									const initial_upgraded = technology.upgraded;
									// set manual upgrade
									technology.upgraded = Math.round( technology.value * .5 ) * 2 + 1;
									technology.value = Math.max( 0, technology.upgraded - 2 );
									technology.upgrade = technology.upgraded - technology.value;
									// compute needed values
									const upgrade_cost = Classes.upgradable.get_costs_upgrade_from( 124, technology, rates );
									const mines_cost = Classes.positions.get_costs_mines_from( positions, rates ) / initial_planet_count;
									const upgraded_production = Classes.positions.get_productions_upgraded_from( data, rates );
									// restore initial values
									technology.value = initial_value;
									technology.upgrade = initial_upgrade;
									technology.upgraded = initial_upgraded;
									// return result
									return ( upgrade_cost + mines_cost  ) / ( upgraded_production - initial_production );
								}
								function get_html_from( data ){
									let result = `<th>${ Translation[124] }</th>`;
									for( const key in data ){
										const value =  data[ key ];
										result += `<td><div>${ key }</div><div>${ value }</div></td>`;
									}
									return result;
								}
								return {
									get_next_rentabilities,
									get_next_rentability_from,
									get_html_from
								};
							})();
							const Plasma = (function(){
								function get_next_rentabilities(){
									const data = Storage.get();
									const technology = data.game.player.researches[122];
									const result = {};
									for( let i = 0; i < 3; i++ ){
										const rentability = get_next_rentability_from( data );
										const level = technology.upgraded += 1;
										result[ level ] = Types.get_duration_from( rentability );
									}
									return result;
								}
								function get_next_rentability_from( data ){
									const positions = data.game.player.positions;
									const technology = data.game.player.researches[122];
									const rates = data.script.rates;
									// save inital values before manual upgrade
									const initial_production = Classes.positions.get_productions_upgraded_from( data, rates );
									const initial_value = technology.value;
									const initial_upgrade = technology.upgrade;
									const initial_upgraded = technology.upgraded;
									// set manual upgrade
									technology.value = technology.upgraded;
									technology.upgrade = 1;
									technology.upgraded = technology.value + 1;
									// compute needed values
									const upgrade_cost = Classes.upgradable.get_costs_upgrade_from( 122, technology, rates );
									const upgraded_production = Classes.positions.get_productions_upgraded_from( data, rates );
									// restore initial values
									technology.value = initial_value;
									technology.upgrade = initial_upgrade;
									technology.upgraded = initial_upgraded;
									// return result
									return upgrade_cost / ( upgraded_production - initial_production );
								}
								function get_html_from( data ){
									let result = `<th>${ Translation[122] }</th>`;
									for( const key in data ){
										const value =  data[ key ];
										result += `<td><div>${ key }</div><div>${ value }</div></td>`;
									}
									return result;
								}
								return {
									get_next_rentabilities,
									get_next_rentability_from,
									get_html_from
								};
							})();
							function get_next_rentabilities(){
								return {
									122: Plasma.get_next_rentabilities(),
									124: Astrophysics.get_next_rentabilities()
								};
							}
							function get_html_from( data ){
								let result = '';
								if( data ){
									result = `<table id="ic_amortizations-tables_researches">
												<caption>${ Translation.researches }</caption>
												<tbody>${ Plasma.get_html_from( data[122] ) }</tbody>
												<tbody>${ Astrophysics.get_html_from( data[124] ) }</tbody>
											</table>`;
								}
								return result;
							}
							return {
								astrophysics: Astrophysics,
								plasma: Plasma,
								get_next_rentabilities,
								get_html_from
							};
						})();
						const Queue = (function(){
							function get_next_rentabilities(){
								const data = Storage.get()
								const positions = data.game.player.positions;
								const researches = data.game.player.researches;
								const results = [];
								for( let i = 0; i < 50; i++ ){
									const rentabilities = get_next_rentabilities_from( data );
									const result = get_next_rentability_from( rentabilities );
									if( result.technology === 122 ){
										const technology = researches[122];
										technology.value = technology.upgraded;
										technology.upgraded = technology.value + 1;
										technology.upgrade = 1;
										result.title = `${ Translation[122] } ${ technology.upgraded }`;
									}else if( result.technology === 124 ){
										const technology = researches[124];
										technology.value = Math.ceil( technology.value * .5 ) * 2 + 1;
										technology.upgraded = technology.value;
										result.title = `${ Translation[124] } ${ technology.upgraded - 1 }/${ technology.upgraded }`;
									}else{
										const position = positions[ result.coordinates ];
										const technology = position.planet.technologies[ result.technology ];
										technology.value = technology.upgraded;
										technology.upgraded = technology.value + 1;
										technology.upgrade = 1;
										result.planet = positions[ result.coordinates ].planet.name;
										result.title = `${ Translation[ result.technology ] } ${ technology.upgraded }`;
									}
									results.push( result );
								}
								return results;
							}
							function get_next_rentabilities_from( data ){
								const positions = data.game.player.positions;
								const result = [];
								result[0] = {
									technology: 122,
									rentability: Researches.plasma.get_next_rentability_from( data )
								};
								result[1] = {
									technology: 124,
									rentability: Researches.astrophysics.get_next_rentability_from( data )
								};
								for( const coordinates in positions ){
									const position = positions[ coordinates ];
									for( let i = 1; i < 4; i++ ){
										result.push( {
											technology: i,
											rentability: Mines.get_next_rentability_from( data, position, i ),
											coordinates
										} );
									}
								}
								return result;
							}
							function get_next_rentability_from( data ){
								const result = {};
								result.rentability = Infinity;
								for( const element of data ){
									if( result.rentability > element.rentability ){
										result.rentability = element.rentability;
										result.technology = element.technology;
										result.coordinates = element.coordinates;
									}
								}
								return result;
							}
							function get_html_from( data ){
								let result = '';
								let i = 1;
								if( data ){
									for( const element of data ){
										result += `<tr>
														<th>${ i++ }.</th>
														<td>${ element.planet || '' }</td>
														<td class="ic_technology-${ element.technology }">
															<div>${ element.title }</div>
															<div>${ Types.get_duration_from( element.rentability ) }</div>
														</td>
													</tr>`;
									}
									result = `<table id="ic_amortizations-tables_queue">
												<caption>${ Translation.queue }</caption>
												<tbody>${ result }</tbody>
											</table>`;
								}
								return result;
							}
							return {
								get_next_rentabilities,
								get_html_from
							};
						})();
						function get_data(){
							return {
								mines: Mines.get_next_rentabilities(),
								researches: Researches.get_next_rentabilities(),
								queue: Queue.get_next_rentabilities()
							};
						}
						function get_html_from( data ){
							let result = Mines.get_html_from( data?.mines );
							result += Researches.get_html_from( data?.researches );
							result += Queue.get_html_from( data?.queue );
							return result;
						}
						function set_html_from( data ){
							const element = document.querySelector( '#ic_amortizations-tables' );
							let result = Mines.get_html_from( data.mines );
							result += Researches.get_html_from( data.researches );
							result += Queue.get_html_from( data.queue );
							element.innerHTML = result;
						}
						return {
							get_data,
							get_html_from,
							set_html_from
						};
					})();
					function get_html_from( data ){
						const tables = Tables.get_html_from( data.script.amortizations );
						return `<div id="ic_amortizations-panel" class="ic_panel" data-state="collapsed">
									<h3 class="ic_panel_title"><span></span>${ Translation.amortizations }</h3>
									<div class="ic_panel_main">
										<div id="ic_amortizations-tables">${ tables }</div>
										<button class="btn_blue">${ Translation.recalculate }</button>
									</div>
								</div>`;
					}
					function set_events(){
						const element = document.querySelector( '#ic_amortizations-panel button' );
						element.addEventListener( 'click', function( event ){
							event.preventDefault();
							try{
								const data = Storage.get();
								const result = Tables.get_data();
								data.script.amortizations = result
								Tables.set_html_from( result );
								Storage.set_from( data );
							}catch( error ){
								alert( Translation.data_alert );
							}
						} );
					}
					return {
						get_html_from,
						set_events
					};
				})();
				const Exports = (function(){
					const Texts = (function(){
						const Empire = (function(){
							function get_from( data ){
								return get_sections_title_from( `${ Translation.empire_of } ${ data.game.player.name } ${ Translation.on } ${ data.game.universe.name }.${ data.game.universe.language }` )
									 + get_sections_classes_from( data )
									 + get_sections_lifeforms_levels_from( data )
									 + get_sections_points_from( data )
									 + get_sections_production_from( data )
									 + get_sections_temperatures_from( data )
									 + get_sections_planets_fields_from( data )
									 + get_sections_planets_buildings_from( data )
									 + get_sections_moons_buildings_from( data )
									 + get_sections_lifeforms_buildings_from( data )
									 + get_sections_lifeforms_researches_from( data )
									 + get_sections_researches_from( data )
									 + get_sections_ships_from( data )
									 + get_sections_planets_defences_from( data )
									 + get_sections_moons_defences_from( data );
							}
							function get_sections_points_from( data ){
								const points = data.game.player.points;
								const percents = data.game.player.percents;
								const mines_points = Types.get_string_number_truncated_from( points.planets.mines.all );
								const mines_percent = Types.get_percent_from( percents.planets.mines.all );
								const planets_buildings_points = Types.get_string_number_truncated_from( points.planets.buildings );
								const planets_buildings_percent = Types.get_percent_from( percents.planets.buildings );
								const moons_buildings_points = Types.get_string_number_truncated_from( points.moons.buildings );
								const moons_buildings_percent = Types.get_percent_from( percents.moons.buildings );
								const lifeforms_buildings_points = Types.get_string_number_truncated_from( points.planets.lifeforms.buildings );
								const lifeforms_buildings_percent = Types.get_percent_from( percents.planets.lifeforms.buildings );
								const lifeforms_researches_points = Types.get_string_number_truncated_from( points.planets.lifeforms.researches );
								const lifeforms_researches_percent = Types.get_percent_from( percents.planets.lifeforms.researches );
								const researches_points = Types.get_string_number_truncated_from( points.researches );
								const researches_percent = Types.get_percent_from( percents.researches );
								const ships_points = Types.get_string_number_truncated_from( points.units.ships.all );
								const ships_percent = Types.get_percent_from( percents.units.ships.all );
								const defences_points = Types.get_string_number_truncated_from( points.units.defences );
								const defences_percent = Types.get_percent_from( percents.units.defences );
								const total_points = Types.get_string_number_truncated_from( points.total );
								const indestructibles_percent = Types.get_percent_from( percents.indestructibles );
								const indestructibles_suffix = `${ indestructibles_percent } ${ Translation.indestructibles.toLowerCase() }`;
								return get_sections_block( Translation.points_repartition, [
									[ Translation.mines, mines_points, null, mines_percent ],
									[ Translation.planets_buildings, planets_buildings_points, null, planets_buildings_percent ],
									[ Translation.moons_buildings, moons_buildings_points, null, moons_buildings_percent ],
									[ Translation.lifeforms_buildings, lifeforms_buildings_points, null, lifeforms_buildings_percent ],
									[ Translation.lifeforms_researches, lifeforms_researches_points, null, lifeforms_researches_percent ],
									[ Translation.researches, researches_points, null, researches_percent ],
									[ Translation.ships, ships_points, null, ships_percent ],
									[ Translation.defences, defences_points, null, defences_percent ],
									[ Translation.total, total_points, null, indestructibles_suffix ]
								] );
							}
							function get_sections_production_from( data ){
								const total = data.game.player.productions.total;
								const metal = Types.get_string_number_truncated_from( total.metal * 24 );
								const crystal = Types.get_string_number_truncated_from( total.crystal * 24 );
								const deuterium = Types.get_string_number_truncated_from( total.deuterium * 24 );
								return get_sections_block( Translation.daily_productions, [
									[ Translation.metal, metal ],
									[ Translation.crystal, crystal ],
									[  Translation.deuterium, deuterium ]
								] );
							}
							function get_sections_temperatures_from( data ){
								const positions = data.game.player.positions;
								const values = [];
								for( const coordinates in positions ){
									const temperature = positions[ coordinates ].planet.temperatures.max;
									values.push( temperature );
								}
								const rows = {
									'': {
										values
									}
								};
								return get_sections_inline( Translation.temperatures_maximum, rows, 0, get_average_from );
							}
							function get_sections_researches_from( data ){
								const researches = data.game.player.researches;
								const rows = [];
								for( const key in researches ){
									const research = researches[ key ];
									const row = [ Translation[ key ] ];
									if( research.upgrade ){
										row.push( research.upgraded, 'gold' );
									}else{
										row.push( research.value );
									}
									rows.push( row );
								}
								return get_sections_block( Translation.researches, rows );
							}
							function get_sections_ships_from( data ){
								const positions = data.game.player.positions;
								const values = {};
								const upgraded = {};
								const rows = [];
								for( const coordinates in positions ){
									const { planet, moon } = positions[ coordinates ];
									const ids = Classes.technologies.ids.units.ships.all;
									for( const key of ids ){
										const technology = planet.technologies[ key ];
										if( technology ){
											values[ key ] ||= 0;
											values[ key ] += technology.upgraded;
											upgraded[ key ] += technology.upgrade ? true : false;
										}
									}
									if( moon ){
										for( const key of ids ){
											const technology = moon.technologies[ key ];
											if( technology ){
												values[ key ] ||= 0;
												values[ key ] += technology.upgraded;
												upgraded[ key ] += technology.upgrade ? true : false;
											}
										}
									}
								}
								for( const key in values ){
									let value = values[ key ];
									if( value ){
										const row = [];
										row[0] = Translation[ key ];
										row[1] = Types.get_string_number_full_from( value );
										if( upgraded[ key ] ){
											row[2] = 'gold';
										}
										rows.push( row );
									}
								}
								return get_sections_block( Translation.ships, rows );
							}
							function get_sections_planets_fields_from( data ){
								const positions = data.game.player.positions;
								const maximum = [];
								const used = [];
								for( const coordinates in positions ){
									const fields = positions[ coordinates ].planet.fields;
									maximum.push( fields.maximum );
									used.push( fields.used );
								}
								const rows = {
									[ Translation.maximum ]: {
										values: maximum
									},
									[ Translation.used ]: {
										values: used
									}
								};
								return get_sections_inline( Translation.planet_fields, rows, 3, get_average_from );
							}
							function get_sections_planets_buildings_from( data ){
								const ids = Classes.technologies.ids.planet;
								const rows = get_sections_inline_technologies_from( data, 'planet', [ ...ids.mines, ...ids.buildings ] );
								return get_sections_inline( Translation.planets_buildings, rows, 2, get_sum_from );
							}
							function get_sections_planets_defences_from( data ){
								const rows = get_sections_inline_technologies_from( data, 'planet', Classes.technologies.ids.units.defences );
								return get_sections_inline( Translation.planets_defences, rows, 8, get_sum_from );
							}
							function get_sections_moons_buildings_from( data ){
								const rows = get_sections_inline_technologies_from( data, 'moon', Classes.technologies.ids.moon.buildings );
								return get_sections_inline( Translation.moons_buildings, rows, 2, get_sum_from );
							}
							function get_sections_lifeforms_buildings_from( data ){
								const rows = get_sections_inline_technologies_from( data, 'planet', Classes.technologies.ids.planet.lifeforms.buildings );
								return get_sections_inline( Translation.lifeforms_buildings, rows, 2, get_sum_from );
							}
							function get_sections_lifeforms_researches_from( data ){
								const rows = get_sections_inline_technologies_from( data, 'planet', Classes.technologies.ids.planet.lifeforms.researches );
								return get_sections_inline( Translation.lifeforms_researches, rows, 2, get_sum_from );
							}
							function get_sections_moons_defences_from( data ){
								const rows = get_sections_inline_technologies_from( data, 'moon', Classes.technologies.ids.units.defences );
								return get_sections_inline( Translation.planets_defences, rows, 8, get_sum_from );
							}
							function get_sections_block( subtitle, rows ){
								let result = '';
								for( const [ key, value, color, suffix ] of rows ){
									let content = `${ key } : `;
									content += get_colored_from( value, color || Colors.defaults.main );
									if( suffix ){
										content += ` · ${ suffix }`;
									}
									result += `${ content }\n`;
								}
								if( result ){
									result = get_sections_subtitle_from( subtitle )
											 + result
											 + '\n';
								}
								return result;
							}
							function get_sections_inline( subtitle, rows, digits, fn ){
								let result = '';
								for( const key in rows ){
									const { values, upgrades } = rows[ key ];
									let total = fn( values );
									if( total ){
										let content = [];
										let has_upgrade = false;
										for( let i = 0; i < values.length; i++ ){
											const value = values[ i ];
											const upgrade = upgrades?.[ i ];
											const padding = get_padding_from( value, digits );
											const colored = upgrade ? get_colored_from( value, 'gold' ) : value;
											if( upgrade ){
												has_upgrade = true;
											}
											content[ i ] = padding + colored;
										}
										total = Types.get_string_number_full_from( total );
										total = get_colored_from( total, has_upgrade ? 'gold' : Colors.defaults.main );
										content = content.join( ', ' );
										content = `${ content }  · ${ total } ${ key }\n`;
										result += content;
									}
								}
								if( result ){
									result = get_sections_subtitle_from( subtitle )
											 + result
											 + '\n';
								}
								return result;
							}
							function get_sections_inline_technologies_from( data, type, ids ){
								const positions = data.game.player.positions;
								const result = {};
								for( const coordinates in positions ){
									const body = positions[ coordinates ][ type ];
									if( body ){
										for( const id of ids ){
											const technology = body.technologies[ id ];
											if( technology ){
												const key = Translation[ id ]
												result[ key ] ||= {
													values: [],
													upgrades: []
												};
												if( technology.upgrade ){
													result[ key ].values.push( technology.upgraded );
													result[ key ].upgrades.push( true );
												}else{
													result[ key ].values.push( technology.value );
													result[ key ].upgrades.push( false );
												}
											}
										}
									}
								}
								return result;
							}
							return {
								get_from
							};
						})();
						const Production = (function(){
							function get_from( data ){
								return get_sections_title_from( `${ Translation.production_of } ${ data.game.player.name } ${ Translation.on } ${ data.game.universe.name }.${ data.game.universe.language }` )
									 + get_sections_classes_from( data )
									 + get_sections_points_from( data )
									 + get_sections_planets_from( data )
									 + get_sections_researches_from( data )
									 + get_sections_production_from( data )
							}
							function get_sections_planets_from( data ){
								const subtitle = get_sections_subtitle_from( Translation.planets );
								const positions = data.game.player.positions;
								let content = '';
								let i = 1;
								for( const coordinates in positions ){
									const { location, planet } = positions[ coordinates ];
									const { technologies, temperatures } = planet;
									content += get_planet_place_from( i++ );
									content += get_planet_location_from( location );
									content += get_planet_technology_from( technologies[1], Colors.defaults.metal, 2 );
									content += get_planet_technology_from( technologies[2], Colors.defaults.crystal, 2 );
									content += get_planet_technology_from( technologies[3], Colors.defaults.deuterium, 2 );
									content += get_planet_technology_from( technologies[217], Colors.defaults.crawlers, 0 );
									content += get_planet_temperature_from( temperatures.max );
								}
								return `${ subtitle + content }\n`;
							}
							function get_sections_points_from( data ){
								const subtitle = get_sections_subtitle_from( Translation.points_repartition );
								const mines = data.game.player.points.planets.mines;
								const metal = get_colored_from( Types.get_string_number_truncated_from( mines.metal ), Colors.defaults.metal );
								const crystal = get_colored_from( Types.get_string_number_truncated_from( mines.crystal ), Colors.defaults.crystal );
								const deuterium = get_colored_from( Types.get_string_number_truncated_from( mines.deuterium ), Colors.defaults.deuterium );
								const total = Types.get_string_number_truncated_from( mines.all );
								return subtitle
									   + `${ Translation[1] } : ${ metal }\n`
									   + `${ Translation[2] } : ${ crystal }\n`
									   + `${ Translation[3] } : ${ deuterium }\n`
									   + `${ Translation.total } : ${ total }\n\n`;
							}
							function get_sections_production_from( data ){
								const subtitle = get_sections_subtitle_from( Translation.daily_productions );
								const productions = data.game.player.productions;
								const mines = productions.mines;
								const bonuses = productions.bonuses;
								const lifeforms = productions.lifeforms;
								const total = productions.total;
								const mines_metal = get_colored_from( Types.get_string_number_truncated_from( mines.metal * 24 ), Colors.defaults.metal );
								const mines_crystal = get_colored_from( Types.get_string_number_truncated_from( mines.crystal * 24 ), Colors.defaults.crystal );
								const mines_deuterium = get_colored_from( Types.get_string_number_truncated_from( mines.deuterium * 24 ), Colors.defaults.deuterium );
								const lifeforms_metal = get_colored_from( Types.get_string_number_truncated_from( lifeforms.metal * 24 ), Colors.defaults.metal );
								const lifeforms_crystal = get_colored_from( Types.get_string_number_truncated_from( lifeforms.crystal * 24 ), Colors.defaults.crystal );
								const lifeforms_deuterium = get_colored_from( Types.get_string_number_truncated_from( lifeforms.deuterium * 24 ), Colors.defaults.deuterium );
								const bonuses_metal = get_colored_from( Types.get_string_number_truncated_from( bonuses.metal * 24 ), Colors.defaults.metal );
								const bonuses_crystal = get_colored_from( Types.get_string_number_truncated_from( bonuses.crystal * 24 ), Colors.defaults.crystal );
								const bonuses_deuterium = get_colored_from( Types.get_string_number_truncated_from( bonuses.deuterium * 24 ), Colors.defaults.deuterium );
								const total_metal = get_colored_from( Types.get_string_number_truncated_from( total.metal * 24 ), Colors.defaults.metal );
								const total_crystal = get_colored_from( Types.get_string_number_truncated_from( total.crystal * 24 ), Colors.defaults.crystal );
								const total_deuterium = get_colored_from( Types.get_string_number_truncated_from( total.deuterium * 24 ), Colors.defaults.deuterium );
								return subtitle
									   + `${ Translation.mines } : ${ mines_metal }, ${ mines_crystal }, ${ mines_deuterium }\n`
									   + `${ Translation.lifeforms } : ${ lifeforms_metal }, ${ lifeforms_crystal }, ${ lifeforms_deuterium }\n`
									   + `${ Translation.objects } & ${ Translation.officers } : ${ bonuses_metal }, ${ bonuses_crystal }, ${ bonuses_deuterium }\n`
									   + `${ Translation.total } : ${ total_metal }, ${ total_crystal }, ${ total_deuterium }\n\n`;
							}
							function get_sections_researches_from( data ){
								const researches = data.game.player.researches;
								const research = researches[ 122 ];
								const subtitle = get_sections_subtitle_from( Translation.researches );
								let content = '';
								if( research ){
									let value;
									let color;
									if( research.upgrade ){
										value = research.upgraded;
										color = 'gold';
									}else{
										value = research.value;
										color = Colors.defaults.main;
									}
									value = get_colored_from( value, color );
									content += `${ Translation[ 122 ] } : ${ value }\n`
								}
								return content ? `${ subtitle + content }\n` : '';
							}
							function get_planet_place_from( value ){
								return `${ value.toString().padStart( 2, '0' ) }. `;
							}
							function get_planet_location_from( value ){
								return `P${ value.toString().padStart( 2, '0' ) }, `;
							}
							function get_planet_technology_from( technology, color, padding ){
								let value;
								if( technology.upgrade ){
									value = technology.upgraded;
									color = 'gold';
								}else{
									value = technology.value;
								}
								return get_padding_from( value, padding ) + get_colored_from( Types.get_string_number_full_from( value ), color ) + ', ';
							}
							function get_planet_temperature_from( value ){
								return get_colored_from( value + ' °C', '#f5bbb4' ) + '\n';
							}
							return {
								get_from
							};
						})();
						function get_sections_title_from( value ){
							const date = new Date();
							const locale_date =  date.toLocaleDateString( 'fr-FR' );
							const locale_time = date.toLocaleTimeString( 'de-DE', { timeStyle: 'short' } );
							const url = `[url=https://board.fr.ogame.gameforge.com/index.php?thread/746302-infocompte/]InfoCompte ${ GM_info.script.version }[/url]`
							const title = get_sized_from( get_colored_from( value, Colors.defaults.main ), 24 );
							const stamp = `${ Translation.generated_on } ${ locale_date } ${ Translation.at } ${ locale_time } ${ Translation.with } ${ url }`;
							return `${ title }\n${ stamp }\n\n`;
						}
						function get_sections_subtitle_from( value ){
							return get_sized_from( get_colored_from( value, Colors.defaults.main ), 18 ) + '\n';
						}
						function get_sections_classes_from( data ){
							const class_player = data.game.player.class;
							const class_alliance = data.game.player?.alliance?.class;
							let result = '';
							if( class_player ){
								const value = Translation[ `classes_player_${ class_player }` ];
								result += get_colored_from( value, Colors.defaults.main );
							}
							if( class_alliance ){
								const value = Translation[ `classes_alliance_${ class_alliance }` ];
								const colored = get_colored_from( value, Colors.defaults.main );
								result += result ? ` & ${ colored }` : colored;
							}
							if( result ){
								result = get_sized_from( result, 14 )
										 + '\n\n';
							}
							return result;
						}
						function get_sections_lifeforms_levels_from( data ){
							const subtitle = get_sections_subtitle_from( Translation.lifeforms_levels );
							const lifeforms = data.game.player.lifeforms;
							let result = '';
							for( const key in lifeforms ){
								const lifeform = lifeforms[ key ];
								const level = get_colored_from( lifeform.level, Colors.defaults.main );
								const current_xp = Types.get_string_number_full_from( lifeform.xp.current );
								const maximum_xp = Types.get_string_number_full_from( lifeform.xp.maximum );
								result += `${ Translation[ key ] } : ${ level } · ${ current_xp }/${ maximum_xp } xp\n`;
							}
							if( result ){
								result = `${ subtitle + result }\n`;
							}
							return result;
						}
						function get_padding_from( value, length ){
							const count = Math.max( 0, length - value.toString().length );
							return '_'.repeat( count );
						}
						function get_colored_from( value, color ){
							return `[color=${ color }]${ value }[/color]`;
						}
						function get_sized_from( value, size ){
							return `[size=${ size }]${ value }[/size]`;
						}
						function get_sum_from( array ){
							return array.reduce( ( previous, current ) => previous + current, 0 );
						}
						function get_average_from( array ){
							return Math.round( get_sum_from( array ) / array.length ) + ' Ø';
						}
						return {
							empire: Empire,
							production: Production
						};
					})();
					function get_html(){
						return	`<div id="ic_exports-panel" class="ic_panel" data-state="collapsed">
									<h3 class="ic_panel_title"><span></span>Exports</h3>
									<div class="ic_panel_main">
										<form>
											<button id="ic_empire-export-button" class="ic_button btn_blue">${ Translation.empire }</button>
											<button id="ic_production-export-button" class="ic_button btn_blue">${ Translation.production }</button>
											<label><input type="radio" name="export" disabled>${ Translation.image }</label>
											<label><input type="radio" name="export" checked>${ Translation.text }</label>
											<label><input type="checkbox" checked>BBCode</label>
										</form>
										<div id="ic_exports-notification">${ Translation.export_notification }</div>
									</div>
								</div>`;
					}
					function set_events_from( data ){
						document.querySelector( '#ic_exports-panel form' ).addEventListener( 'submit', event => event.preventDefault() );
						document.querySelector( '#ic_empire-export-button' ).addEventListener( 'click', event => set_empire_text_to_clipboard_from( data ) );
						document.querySelector( '#ic_production-export-button' ).addEventListener( 'click', event => set_productions_text_to_clipboard_from( data ) );
					}
					function set_empire_text_to_clipboard_from( data ){
						try{
							set_text_export_to_clipboard_from( Texts.empire.get_from( data ) );
						}catch( error ){
							console.error(error)
							alert( Translation.data_alert );
						}
					}
					function set_productions_text_to_clipboard_from( data ){
						try{
							set_text_export_to_clipboard_from( Texts.production.get_from( data ) );
						}catch( error ){
							alert( Translation.data_alert );
						}
					}
					function set_text_export_to_clipboard_from( content ){
						const element = document.querySelector( '#ic_exports-panel form [type="checkbox"]' );
						const result = element.checked ? content : content.replace( /\[\/?[^\]]*\]/g, '' );
						navigator.clipboard.writeText( result );
						set_notification();
					}
					async function set_notification(){
						const form = document.querySelector( '#ic_exports-panel form' );
						const notification = document.querySelector( '#ic_exports-notification' );
						await form.animate( { opacity: 0 }, 250 ).finished;
						form.style.display = 'none';
						notification.style.display = 'flex';
						await notification.animate( { opacity: [0, 1] }, 250 ).finished;
						await notification.animate( { opacity: [1, 0] }, { delay: 1_500, duration: 500 } ).finished;
						notification.style.display = 'none';
						form.style.display = 'flex';
						form.animate( { opacity: [0, 1] }, 500 );
					}
					return {
						get_html,
						set_events_from
					};
				})();
				function get_html_from( data ){
					return `${ Account.get_html_from( data ) }
							${ Positions.get_html_from( data ) }
							${ Productions.get_html_from( data ) }
							${ Amortizations.get_html_from( data ) }
							${ Exports.get_html() }`;
				}
				function set_html_from( data ){
					const collapsibles = data.script.collapsibles;
					for( const element of document.querySelectorAll( '.ic_panel' ) ){
						if( collapsibles[ element.id ] === 'collapsed' ) collapse( element );
						else if( collapsibles[ element.id ] === 'expanded' ) expand( element );
						else if( element.dataset.state === 'collapsed' ) collapse( element );
						else if( element.dataset.state === 'expanded' ) expand( element );
					}
				}
				function set_events_from( data ){
					Amortizations.set_events();
					Exports.set_events_from( data );
					for( const element of document.querySelectorAll( '.ic_panel' ) ){
						const title = element.firstElementChild;
						title.addEventListener( 'click', event => toggle( element ) );
					}
				}
				function toggle( element ){
					const data = Storage.get();
					const collapsibles = data.script.collapsibles;
					if( element.dataset.state === 'collapsed' ){
						collapsibles[ element.id ] = 'expanded';
						expand( element );
					}else if( element.dataset.state === 'expanded' ){
						collapsibles[ element.id ] = 'collapsed';
						collapse( element );
					}
					Storage.set_from( data );
				}
				function collapse( element ){
					const main = element.querySelector( '.ic_panel_main' );
					element.dataset.state = 'collapsed';
					main.style.display = 'none';
				}
				function expand( element ){
					const main = element.querySelector( '.ic_panel_main' );
					element.dataset.state = 'expanded';
					main.style.display = null;
				}
				return {
					get_html_from,
					set_html_from,
					set_events_from
				};
			})();
			function init_from( data ){
				set_html_from( data );
				set_events_from( data );
			}
			function set_html_from( data ){
				const result = `<div class="ic_box">
									<h3 class="ic_box_title">${ Translation.account_overview }</h3>
									${ Panels.get_html_from( data ) }
								</div>`;
				document.querySelector( '#inhalt' ).innerHTML += result;
				Panels.set_html_from( data );
			 }
			function set_events_from( data ){
				Panels.set_events_from( data );
			}
			return {
				init_from
			};
		})();
		const Settings = (function(){
			function init_from( data ){
				set_html_from( data );
				set_events();
			}
			function set_html_from( data ){
				const colors = data.script.colors.user;
				const rates = data.script.rates;
				const result = `<h1>${ Translation.settings }<span class="ui-icon ui-icon-closethick"></span></h1>
								<form>
									<fieldset>
										<legend>${ Translation.rates }</legend>
										<label>${ Translation.metal }<input type="number" value="${ rates.metal }" data-key="metal"></label>
										<label>${ Translation.crystal }<input type="number" value="${ rates.crystal }" data-key="crystal"></label>
										<label>${ Translation.deuterium }<input type="number" value="${ rates.deuterium }" data-key="deuterium" disabled></label>
									</fieldset>
									<fieldset>
										<legend>${ Translation.colors }</legend>
										${ get_html_colors_from( data ) }
									</fieldset>
								</form>
                                <button class="btn_blue" type="button">Clear script data</button>
								<a href="https://ko-fi.com/A0A4DEZRA" target="_blank">Buy me a coffee <span>\u2764</span></a>`;
				// toolbarcomponent element not allowed for compatibility reason with AntiGame & OGame Tracker
                const element = document.createElement('dialog');
                element.id = 'ic_dialog';
				element.innerHTML += result;
                document.body.appendChild(element);
			}
			function get_html_colors_from( data ){
				const colors = data.script.colors.user;
				let result = '';
				for( const key in colors ){
					const title = Translation[ key ];
					const value = colors[ key ];
					result += `<label>${ title }<input type="color" value="${ value }" data-key="${ key }"></label>`;
				}
				return result;
			}
			function set_events(){
				set_events_dialog();
				set_events_change();
				set_events_reset();
			}
			function set_events_dialog(){
				const dialog = document.querySelector( '#ic_dialog' );
				const open = document.querySelector( '#ic_menu-button .menu_icon div');
				const close = document.querySelector( '#ic_dialog .ui-icon');
				open.addEventListener( 'mousedown', event => dialog.showModal() );
				close.addEventListener( 'mousedown', event => dialog.close() );
			}
			function set_events_change(){
				const dialog = document.querySelector( '#ic_dialog' );
				dialog.addEventListener( 'change', function(){
					const data = Storage.get();
					for( const input of dialog.querySelectorAll( '[type=color]' ) ){
						const key = input.dataset.key;
						const value = input.value;
						data.script.colors.user[ key ] = value;
					}
					for( const input of dialog.querySelectorAll( '[type=number]' ) ){
						const key = input.dataset.key;
						const value = input.value;
						data.script.rates[ key ] = value;
					}
					Storage.set_from( data );
				} );
			}
			function set_events_reset(){
				const button = document.querySelector( '#ic_dialog button' );
				button.addEventListener( 'click', function( event ){
					Storage.clear();
					window.location.reload();
				} );
			}
			return {
				init_from
			};
		})();
		const Styles = (function(){
			function init_from( data ){
				const result = get_from( data );
				GM_addStyle( result );
			}
			function get_from( data ){
				const colors = data.script.colors.user;
				return `.ic_box {
							background: #0d1014;
							border: 2px solid black;
							box-sizing: border-box;
							color: lightgrey;
							line-height: 1;
							margin: 0 auto 51px;
							padding: 8px;
							position: relative;
							width: 654px;
						}
						.ic_box::before,
						.ic_box::after {
							content: '';
							position: absolute;
							width: 668px;
						}
						.ic_box::before {
							background: url(//gf3.geo.gfsrv.net/cdn53/f333e15eb738b8ec692340f507e1ae.png) bottom left no-repeat,
										url(//gf2.geo.gfsrv.net/cdnd5/66551209db14e23b3001901b996cc6.png) bottom right no-repeat;
							height: 28px;
							left: -9px;
							top: -3px;
						}
						.ic_box::after {
							background: url(//gf3.geo.gfsrv.net/cdnea/0330abcdca0d125d35a0ebace4b584.png) bottom left no-repeat,
										url(//gf1.geo.gfsrv.net/cdn9b/8003a40825bc96919c5fec01b018b8.png) bottom right no-repeat;
							height: 50px;
							bottom: -4px;
							left: -9px;
							z-index: -1;
						}
						.ic_box_title {
							background: url(//gf1.geo.gfsrv.net/cdnfb/a4e7913209228ebaf2297429aeb87b.png);
							color: #6f9fc8;
							font: bold 12px/27px Verdana,Arial,Helvetica,sans-serif;
							margin: -9px -8px 4px;
							text-align: center;
							position: relative;
						}
						.ic_box_title::before,
						.ic_box_title::after {
							content: '';
							display: block;
							position: absolute;
							top: 0;
							width: 26px;
							height: 27px;
						}
						.ic_box_title::before {
							background: url(//gf2.geo.gfsrv.net/cdn4a/127bd495b9325216af08a588ecc540.png);
							left: 0;
						}
						.ic_box_title::after {
							background: url(//gf2.geo.gfsrv.net/cdn1d/80db96934a5b82ce002f839cd85a44.png);
							right: 0;
						}
						.ic_panel {
							padding: 1px 0;
						}
						.ic_panel_title {
							background-image: url(//gf3.geo.gfsrv.net/cdne1/d03835718066a5a592a6426736e019.png);
							color: #576472;
							cursor: pointer;
							font-weight: bold;
							line-height: 28px;
							overflow: hidden;
							padding-left: 35px;
							position: relative;
						}
						.ic_panel_title::after {
							background-image: url(//gf3.geo.gfsrv.net/cdne1/d03835718066a5a592a6426736e019.png);
							background-position: -21px -169px;
							content: '';
							display: block;
							position: absolute;
							right: -2px;
							top: 1px;
							width: 10px;
							height: 26px;
						}
						.ic_panel_title:hover::after {
							background-position: -21px -196px;
						}
						.ic_panel_title:hover {
							background-position: 0 -28px;
							color: #6f9fc8;
						}
						.ic_panel_title > span {
							background-image: url(//gf3.geo.gfsrv.net/cdne1/d03835718066a5a592a6426736e019.png);
							left: -4px;
							position: absolute;
							width: 31px;
							height: 27px;
						}
						.ic_panel[ data-state="expanded" ] .ic_panel_title > span {
							background-position: 0 -113px;
						}
						.ic_panel[ data-state="expanded" ] .ic_panel_title:hover > span {
							background-position: 0 -141px;
						}
						.ic_panel[ data-state="collapsed" ] .ic_panel_title > span {
							background-position: 0 -57px;
						}
						.ic_panel[ data-state="collapsed" ] .ic_panel_title:hover > span {
							background-position: 0 -85px;
						}
						.ic_panel_main {
							background: #12171c;
							border: 1px solid black;
							display: flex;
							margin: 0 1px;
						}
						.ic_panel table {
							font-size: 11px;
						}
						.ic_panel tbody th {
							text-align: left;
						}
						.ic_panel caption {
							border-bottom: 1px dotted rgb( 128, 128, 128, .2 );
							color: #6f9fc8;
							font: bold 12px/27px Verdana,Arial,Helvetica,sans-serif;
							line-height: 1;
							padding: 16px 8px;
							text-align: left;
						}
						.ic_panel tr:nth-child( even ) {
							background: #141e26;
						}
						.ic_panel tr > * {
							padding: 6px;
							white-space: nowrap;
						}
						.ic_panel tr > :first-child {
							padding-left: 8px;
						}
						.ic_panel tr > :last-child {
							padding-right: 8px;
						}
						.ic_panel td {
							text-align: right;
						}
						.ic_panel :is( th, td ) > div:not( :last-child ) {
							margin-bottom: 6px;
						}
						#ic_account-points-panel tr:nth-child( 8 ) > * {
							padding-bottom: 8px;
						}
						#ic_account-points-panel tr:nth-child( 9 ) > * {
							border-top: 1px dotted rgb( 128, 128, 128, .2 );
							padding-top: 8px;
						}
						#ic_account-points-panel th::before {
							color: transparent;
							content: '\u2b24';
							margin-right: 8px;
						}
						#ic_account-points-panel tr:nth-child( 1 ) th::before {
							color: ${ colors.mines };
						}
						#ic_account-points-panel tr:nth-child( 2 ) th::before {
							color: ${ colors.planets_buildings };
						}
						#ic_account-points-panel tr:nth-child( 3 ) th::before {
							color: ${ colors.moons_buildings };
						}
						#ic_account-points-panel tr:nth-child( 4 ) th::before {
							color: ${ colors.lifeforms_buildings };
						}
						#ic_account-points-panel tr:nth-child( 5 ) th::before {
							color: ${ colors.lifeforms_researches };
						}
						#ic_account-points-panel tr:nth-child( 6 ) th::before {
							color: ${ colors.researches };
						}
						#ic_account-points-panel tr:nth-child( 7 ) th::before {
							color: ${ colors.ships };
						}
						#ic_account-points-panel tr:nth-child( 8 ) th::before {
							color: ${ colors.defences };
						}
						#ic_account-points-panel svg {
							margin: auto;
							width: 33.3%;
						}
						#ic_positions-points-panel table {
							width: 100%;
						}
						#ic_positions-points-panel tr > :nth-child( -n+2 ) {
							width: 0;
						}
						#ic_positions-points-panel td {
							text-align: center;
							vertical-align: baseline;
						}
						#ic_positions-points-panel td:nth-child( 2 ) {
							text-align: left;
						}
						#ic_positions-points-panel td:nth-child( 3 ) {
							color: ${ colors.mines };
						}
						#ic_positions-points-panel td:nth-child( 4 ) {
							color: ${ colors.planets_buildings };
						}
						#ic_positions-points-panel td:nth-child( 4 ) div:nth-child( 2 ){
							color: ${ colors.moons_buildings };
						}
						#ic_positions-points-panel td:nth-child( 5 ) {
							color: ${ colors.lifeforms_buildings };
						}
						#ic_positions-points-panel td:nth-child( 6 ) {
							color: ${ colors.lifeforms_researches };
						}
						#ic_positions-points-panel td:nth-child( 7 ) {
							color: ${ colors.defences };
						}
						#ic_positions-points-panel td:last-child {
							text-align: right;
							width: 0;
						}
						#ic_productions-panel table {
							table-layout: fixed;
							width: 100%;
						}
						#ic_productions-panel tr:first-child th {
							text-align: right;
						}
						#ic_productions-panel td:nth-child( 2 ) {
							color: ${ colors.metal };
						}
						#ic_productions-panel td:nth-child( 3 ) {
							color: ${ colors.crystal };
						}
						#ic_productions-panel td:nth-child( 4 ) {
							color: ${ colors.deuterium };
						}
						#ic_amortizations-panel .ic_panel_main {
							align-items: end;
							flex-direction: column;
							gap: 8px;
						}
						#ic_amortizations-panel .ic_panel_main .btn_blue {
							margin: 8px 6px;
						}
						#ic_amortizations-panel table {
							width: 100%;
						}
						#ic_amortizations-panel th {
							width: 0;
						}
						#ic_amortizations-tables_mines {
							table-layout: fixed;
						}
						#ic_amortizations-tables_mines td:nth-child( 2 ) {
							color: ${ colors.metal };
						}
						#ic_amortizations-tables_mines td:nth-child( 3 ) {
							color: ${ colors.crystal };
						}
						#ic_amortizations-tables_mines td:nth-child( 4 ) {
							color: ${ colors.deuterium };
						}
						#ic_amortizations-tables_researches {
							table-layout: fixed;
						}
						#ic_amortizations-tables_queue tbody {
							display: block;
							column-count: 2;
						}
						#ic_amortizations-tables_queue tr {
							display: block;
						}
						#ic_amortizations-tables_queue tr:nth-child( n+26 ):nth-child( even ){
							background: #12171c;
						}
						#ic_amortizations-tables_queue tr:nth-child( n+26 ):nth-child( odd ){
							background: #141e26;
						}
						#ic_amortizations-tables_queue th {
							text-align: right;
						}
						#ic_amortizations-tables_queue td {
							width: 50%;
						}
						#ic_amortizations-tables_queue td:first-of-type {
							text-align: left;
						}
						#ic_amortizations-tables_queue .ic_technology-1 {
							color: ${ colors.metal }
						}
						#ic_amortizations-tables_queue .ic_technology-2 {
							color: ${ colors.crystal }
						}
						#ic_amortizations-tables_queue .ic_technology-3 {
							color: ${ colors.deuterium }
						}
						#ic_amortizations-tables_queue :is( .ic_technology-122, .ic_technology-124 ) {
							color: ${ colors.researches }
						}
						#ic_exports-panel .ic_panel_main {
							align-items: center;
							display: flex;
							padding: 8px;
						}
						#ic_exports-panel form {
							display: flex;
						}
						#ic_exports-panel form label {
							align-items: center;
							display: inline-flex;
						}
						#ic_exports-panel form label:not( :last-of-type ) {
							margin-right: 8px;
						}
						#ic_exports-panel form input {
							margin: 0 4px 0 0;
						}
						#ic_exports-panel form > label:nth-child( 3 ) {
							opacity: .33;
						}
						#ic_exports-panel form :is( label:nth-child( 3 ), label:nth-child( 3 ) input ):hover {
							cursor: default;
						}
						#ic_exports-panel form :is( label, input ):hover {
							cursor: pointer;
						}
						#ic_exports-panel form button {
							margin-right: 8px;
						}
						#ic_exports-panel form button:last-of-type {
							margin-right: 16px;
						}
						#ic_exports-notification {
							display: none;
							padding: 7.5px 0;
						}
						#ic_exports-notification::before {
							content: '\u2713';
							margin-right: 4px;
						}
						#ic_menu-button .textlabel {
							font-size: 10px;
						}
						#ic_menu-button .menu_icon div {
							align-items: center;
							background: linear-gradient( to bottom, #1b2024 50%, #000 50% );
							border-radius: 4px;
							color: #353a3c;
							display: flex;
							justify-content: center;
							width: 27px;
							height: 27px;
						}
						#ic_menu-button .menu_icon div:hover {
							color: #d39343;
							cursor: pointer;
						}
						#ic_dialog {
							background: url(//gf1.geo.gfsrv.net/cdnc8/a70be772b78f27691516fa29654cef.jpg) -100px -100px;
							border: 1px solid #1f2833;
							color: lightgrey;
							padding: 16px;
						}
						#ic_dialog::backdrop {
							background: rgb( 0, 0, 0, .5 );
						}
						#ic_dialog h1 {
							background: linear-gradient( to top, #3d4b5b 0%, #2b343f 49%, #1f262d 50%, #1f2934 100% );
							color: #6f9fc8;
							display: flex;
							font-weight: bold;
							justify-content: space-between;
							margin: -16px -16px 16px;
							padding: 8px 16px;
						}
						#ic_dialog .ui-icon:hover {
							cursor: pointer;
						}
						#ic_dialog form {
							display: flex;
							flex-direction: column;
							gap: 16px;
							margin-bottom: 16px;
						}
						#ic_dialog legend {
							color: #6f9fc8;
							font-weight: bold;
							margin-bottom: 8px;
						}
						#ic_dialog label {
							align-items: center;
							display: flex;
							gap: 8px;
							justify-content: space-between;
						}
						#ic_dialog label:hover {
							cursor: pointer;
						}
						#ic_dialog label:not( :last-child ) {
							margin-bottom: 4px;
						}
						#ic_dialog [type=color] {
							-webkit-appearance: none;
							background: none;
							border: none;
							width: 37px;
						}
						#ic_dialog [type=color]::-webkit-color-swatch-wrapper {
							padding: 0;
						}
						#ic_dialog [type=color]::-webkit-color-swatch {
							border: none;
							border-radius: 3px;
						}
						#ic_dialog [type=color]:hover {
							cursor: pointer;
						}
						#ic_dialog [type=number] {
							-moz-appearance: textfield;
							background: #b3c3cb;
							border: 1px solid #668599;
							border-radius: 3px;
							padding: 2px 4px;
							text-align: center;
							width: 26px;
						}
						#ic_dialog [type=number]::-webkit-outer-spin-button,
						#ic_dialog [type=number]::-webkit-inner-spin-button {
							-webkit-appearance: none;
							margin: 0;
						}
						#ic_dialog [type=number]:disabled {
							background: none;
							border: 1px solid white;
							color: white;
							opacity: .5;
							width: 26px;
						}
						#ic_dialog button {
							display:block;
							width: 100%;
						}
						#ic_dialog a {
							display: block;
							margin-top: 8px;
							text-align: center;
						}
						#ic_dialog a span {
							color: #ff3131;
						}
						.ic_energy-warning::after {
							animation: pulse 1s ease-in-out infinite alternate;
							color: yellow;
							content: '\ud83d\uddf2';
							margin-left: 4px;
						}
						.ic_percent {
							display: inline-block;
							width: 48px;
						}
						.btn_blue {
							min-width: unset;
						}
						@keyframes pulse {
							to {
								opacity: 0;
							}
						}`;
			}
			return {
				init_from
			};
		})();
		function init_from( data ){
			if( currentPage !== 'empire' ){
				if( currentPage === 'highscore' ){
					Highscores.init_from( data );
				}else if( currentPage === 'overview' ){
					Overview.init_from( data );
				}
				Energy.init_from( data );
				Menu.init();
				Settings.init_from( data );
				Styles.init_from( data );
			}
		}
		return {
			init_from
		};
	})();
	const Data = (function(){
		function get_from( stored, scraped ){
			const result = get_merged_from( stored, scraped );
			remove_obselete_positions_from( result, scraped );
			sort_positions_from( result, scraped );
			set_script_data_to( result );
			set_computed_to( result );
			return result;
		}
		function get_merged_from( ...objects ){
			const result = {};
			for( const object of objects ){
				for( const key in object ){
					if( Types.are_objects( result[ key ], object[ key ] ) ){
						const value = get_merged_from( result[ key ], object[ key ] );
						result[ key ] = value;
					}else if( object[ key ] !== undefined ){
						const value = object[ key ];
						result[ key ] = value;
					}
				}
			}
			return result;
		}
		function set_computed_to( data ){
			set_computed_points_to( data );
			set_computed_percents_to( data );
			set_computed_productions_to( data );
			set_computed_highscores_to( data );
		}
		function set_computed_points_to( data ){
			const { points, positions, researches } = data.game.player;
			const result = {
				indestructibles: 0,
				moons: {
					buildings: 0
				},
				planets: {
					buildings: 0,
					lifeforms: {
						buildings: 0,
						researches: 0,
					},
					mines: {
						all: 0,
						metal: 0,
						crystal: 0,
						deuterium: 0
					}
				},
				positions: {},
				researches: 0,
				total: 0,
				units: {
					defences: 0,
					ships: {
						all: 0
					}
				},
				upgrades: 0
			};
			if( points ){
				const rates = {
					metal: 1,
					crystal: 1,
					deuterium: 1
				};
				for( const coordinates in positions ){
					const position = result.positions[ coordinates ] = {};
					const { moon, planet } = positions[ coordinates ];
					position.planet = get_computed_points_planet_from( planet, rates );
					if( moon ){
						position.moon = get_computed_points_moon_from( moon, rates );
					}
				}
				for( const coordinates in result.positions ){
					const { moon, planet } = result.positions[ coordinates ];
					result.planets.buildings += planet.buildings;
					result.planets.lifeforms.buildings += planet.lifeforms.buildings;
					result.planets.lifeforms.researches += planet.lifeforms.researches;
					result.planets.mines.all += planet.mines.all;
					result.planets.mines.metal += planet.mines.metal;
					result.planets.mines.crystal += planet.mines.crystal;
					result.planets.mines.deuterium += planet.mines.deuterium;
					result.units.defences += planet.units.defences;
					result.upgrades += planet.upgrades;
					if( moon ){
						result.moons.buildings += moon.buildings;
						result.units.defences += moon.units.defences;
						result.upgrades += moon.upgrades;
					}
				}
				result.researches = Classes.researches.get_costs_from( researches, rates ) * .001;
				result.upgrades += Classes.researches.get_costs_upgrade_from( researches, rates ) * .001;
				result.total = points.total;
				result.units.ships.all = result.total - Math.trunc( result.moons.buildings + result.planets.buildings + result.planets.lifeforms.buildings + result.planets.lifeforms.researches + result.planets.mines.all + result.researches + result.units.defences );
				result.indestructibles = result.total - result.moons.buildings - result.units.defences - result.units.ships.all;
			}
			data.game.player.points = result;
		}
		function get_computed_points_moon_from( moon, rates ){
			const technologies = moon.technologies;
			const result = {
				buildings: Classes.moon.get_costs_buildings_from( technologies, rates ) * .001,
				units: {
					defences: Classes.moon.get_costs_defences_from( technologies, rates ) * .001,
					ships: {
						statics: Classes.moon.get_costs_ships_statics_from( technologies, rates ) * .001
					}
				},
				upgrades: Classes.moon.get_costs_upgrades_from( technologies, rates ) * .001,
				statics: 0
			};
			result.statics = result.buildings + result.units.defences + result.units.ships.statics;
			return result;
		}
		function get_computed_points_planet_from( planet, rates ){
			const technologies = planet.technologies;
			const result = {
				buildings: Classes.planet.get_costs_buildings_from( technologies, rates ) * .001,
				lifeforms: {
					buildings: Classes.planet.get_costs_lifeforms_buildings_from( technologies, rates ) * .001,
					researches: Classes.planet.get_costs_lifeforms_researches_from( technologies, rates ) * .001
				},
				mines: {
					all: 0,
					metal: Classes.planet.get_costs_mines_metal_from( technologies, rates ) * .001,
					crystal: Classes.planet.get_costs_mines_crystal_from( technologies, rates ) * .001,
					deuterium: Classes.planet.get_costs_mines_deuterium_from( technologies, rates ) * .001
				},
				units: {
					defences: Classes.planet.get_costs_defences_from( technologies, rates ) * .001,
					ships: {
						statics: Classes.planet.get_costs_ships_statics_from( technologies, rates ) * .001
					}
				},
				upgrades: Classes.planet.get_costs_upgrades_from( technologies, rates ) * .001,
				statics: 0
			};
			result.mines.all = result.mines.metal + result.mines.crystal + result.mines.deuterium;
			result.statics = result.buildings + result.lifeforms.buildings + result.lifeforms.researches + result.mines.all + result.units.defences + result.units.ships.statics;
			return result;
		}
		function set_computed_percents_to( data ){
			const points = data.game.player.points;
			const total = points.total;
			data.game.player.percents = get_computed_percents_from( points, total );
		}
		function get_computed_percents_from( points, total ){
			const result = {};
			for( const key in points ){
				const value = points[ key ];
				if( Types.are_objects( value ) ){
					result[ key ] = get_computed_percents_from( value, total );
				}else{
					result[ key ] = value / total || 0;
				}
			}
			return result;
		}
		function set_computed_productions_to( data ){
			const positions = data.game.player.positions;
			data.game.player.productions = {
				bonuses: get_computed_productions_bonuses_from( positions ),
				lifeforms: get_computed_productions_lifeforms_from( positions ),
				mines: get_computed_productions_mines_from( positions ),
				total: get_computed_productions_total_from( positions )
			};
		}
		function get_computed_productions_bonuses_from( positions ){
			const result = {
				metal: 0,
				crystal: 0,
				deuterium: 0
			};
			for( const coordinates in positions ){
				const productions = positions[ coordinates ].planet.productions;
				if( productions ){
					const objects = productions.objects;
					const geologist = productions.geologist;
					const officers = productions.officers;
					result.metal += objects.metal + geologist.metal + officers.metal;
					result.crystal += objects.crystal + geologist.crystal + officers.crystal;
					result.deuterium += objects.deuterium + geologist.deuterium + officers.deuterium;
				}
			}
			return result;
		}
		function get_computed_productions_lifeforms_from( positions ){
			const result = {
				metal: 0,
				crystal: 0,
				deuterium: 0
			};
			for( const coordinates in positions ){
				const productions = positions[ coordinates ].planet.productions;
				if( productions?.lifeforms ){
					result.metal += productions.lifeforms.metal;
					result.crystal += productions.lifeforms.crystal;
					result.deuterium += productions.lifeforms.deuterium;
				}
			}
			return result;
		}
		function get_computed_productions_mines_from( positions ){
			const result = {
				metal: 0,
				crystal: 0,
				deuterium: 0
			};
			for( const coordinates in positions ){
				const productions = positions[ coordinates ].planet.productions;
				if( productions ){
					result.metal += productions.mines.metal;
					result.crystal += productions.mines.crystal;
					result.deuterium += productions.mines.deuterium;
				}
			}
			return result;
		}
		function get_computed_productions_total_from( positions ){
			const result = {
				metal: 0,
				crystal: 0,
				deuterium: 0
			};
			for( const coordinates in positions ){
				const productions = positions[ coordinates ].planet.productions;
				if( productions ){
					result.metal += productions.total.metal;
					result.crystal += productions.total.crystal;
					result.deuterium += productions.total.deuterium;
				}
			}
			return result;
		}
		function set_computed_highscores_to( data ){
			if( currentPage === 'highscore' ){
				const { player, players } = data.game.universe.highscores[1][0];
				const points = data.game.player.points;
				const positions = player.positions;
				const upgraded = player.points + points.upgrades;
				// set default values
				positions.if_destroyed = positions.current;
				positions.when_finished = positions.current;
				// get highscores player position when destroyed
				for( const key in players ){
					const value = players[ key ];
					if( value < points.indestructibles ){
						positions.if_destroyed = parseInt( key ) - 1;
						break;
					}
				}
				// get highscores player position when upgraded
				for( const key in players ){
					const value = players[ key ];
					if( value <= upgraded ){
						positions.when_finished = parseInt( key );
						break;
					}
				}
			}
		}
		function set_script_data_to( data ){
			data.script ||= {
				amortizations: {},
				collapsibles: {},
				colors: {
					defaults: Colors.defaults,
					user: Colors.user
				},
				rates: {
					metal: 2,
					crystal: 1.5,
					deuterium: 1
				}
			};
		}
		function remove_obselete_positions_from( result, scraped ){
			const result_positions = result.game.player.positions;
			const scraped_positions = scraped.game.player.positions;
			if( currentPage === 'empire' ){
				for( const coordinates in result_positions ){
					const position = scraped_positions[ coordinates ];
					if( !position ){
						if( planetType === 0 ) delete result_positions[ coordinates ];
						else delete result_positions[ coordinates ].moon;
					}
				}
			}else{
				for( const coordinates in result_positions ){
					const position = scraped_positions[ coordinates ];
					if( !position ) delete result_positions[ coordinates ];
					else if( !position.moon ) delete result_positions[ coordinates ].moon;
				}
			}
		}
		function sort_positions_from( result, scraped ){
            if( currentPage !== 'empire' ) {
                const result_positions = result.game.player.positions;
			    const scraped_positions = scraped.game.player.positions;
                const sorted_positions = {};
                for( const coordinates in scraped_positions ){
                    sorted_positions[ coordinates ] = result_positions[ coordinates ];
                }
                result.game.player.positions = sorted_positions;
            }
		}
		return {
			get_from
		};
	})();
	const Scraper = (function(){
		async function get(){
			console.group( 'InfoCompte' );
			for( let i = 0; i < 5; i++ ){
				try{
					const result = get_data();
					console.log( 'Data has been scraped with success:', result );
					return result;
				}catch( error ){
					console.log( 'A problem occurred while scraping data (see below). The script will attempt to scrape the data again...' );
					console.error( error );
					await new Promise( resolve => setTimeout( resolve, 1_000 ) );
				}
			}
			console.groupEnd();
		}
		function get_data(){
			return {
				game: {
					interface: get_interface(),
					player: get_player(),
					universe: get_universe()
				}
			};
		}
		function get_interface(){
			return {
				coordinates: document.head.querySelector( 'meta[name=ogame-planet-coordinates]' ).content,
				type: document.head.querySelector( 'meta[name=ogame-planet-type]' ).content
			};
		}
		function get_player(){
			return {
				id: parseInt( document.head.querySelector( 'meta[name=ogame-player-id]' ).content ),
				name: document.head.querySelector( 'meta[name=ogame-player-name]' ).content,
				class: get_player_class(),
				officers: get_player_officers(),
				points: get_player_points(),
				positions: get_player_positions(),
				lifeforms: get_player_lifeforms(),
				researches: get_player_researches(),
				alliance: get_player_alliance()
			};
		}
		function get_player_class(){
			if( currentPage !== 'empire' ){
				let result = null;
				for( const key of [ 'miner', 'warrior', 'explorer' ] ){
					if( document.querySelector( `#characterclass .${ key }` ) ){
						result = key;
						break;
					}
				}
				return result;
			}
		}
		function get_player_officers(){
			if( currentPage !== 'empire' ){
				const result = {};
				result.all = true;
				for( const key of [ 'commander', 'admiral', 'engineer', 'geologist', 'technocrat' ] ){
					const element = document.querySelector( `#officers a.on.${ key }` );
					if( element ){
						result[ key ] = true;
					}else{
						result[ key ] = result.all = false;
					}
				}
				return result;
			}
		}
		function get_player_points(){
			if( currentPage === 'overview' ){
				const result = {};
				let values = document.querySelector( '#overviewcomponent > script:nth-child(2)' ).textContent;
				values = values.split( '\n' )[20];
				values = values.replaceAll( LocalizationStrings.thousandSeperator, '' ).match( /\d+/g );
				result.total = parseInt( values[2] );
				return result;
			}
		}
		function get_player_positions(){
			if( currentPage === 'empire' ){
				return get_player_positions_from_empire();
			}else{
				return get_player_positions_from_list();
			}
		}
		function get_player_positions_from_list(){
			const elements = document.querySelectorAll( '#planetList .smallplanet' );
			const count =  parseInt( document.querySelector( '#countColonies > p > span' ).textContent.match( /\d+/g )[0] );
			const result = {};
			if( elements.length !== count ){
				throw new Error( 'All positions are not displayed yet in planetList html element' );
			}
			for( const element of elements ){
				const coordinates = element.querySelector( '.planet-koords' ).textContent.slice( 1, -1 );
				const position = result[ coordinates ] = {};
				position.location = parseInt( coordinates.split( ':' )[2] );
				position.planet = {};
				if( element.querySelector( '.moonlink' ) ){
					position.moon = {};
				}
			}
			const coordinates = document.head.querySelector( 'meta[name=ogame-planet-coordinates]' ).content;
			const type = document.head.querySelector( 'meta[name=ogame-planet-type]' ).content;
			const body = result[ coordinates ][ type ] = get_player_body();
			return result;
		}
		function get_player_positions_from_empire(){
			const type = planetType ? 'moon' : 'planet';
			const result = {};
			for( const element of document.querySelectorAll( '.planet:not( .summary )' ) ){
				const coordinates = element.querySelector( '.planetData .coords' ).textContent.slice( 1, -1 );
				const position = result[ coordinates ] = {};
				position.location = parseInt( coordinates.split( ':' )[2] );
				position[ type ] = get_player_body_from( element );
			}
			return result;
		}
		function get_player_body(){
			return {
				id: document.head.querySelector( 'meta[name=ogame-planet-id]' ).content,
				name: document.head.querySelector( 'meta[name=ogame-planet-name]' ).content,
				fields: get_player_fields(),
				temperatures: get_player_temperatures(),
				technologies: get_player_technologies_from_body(),
				lifeform: get_player_lifeform(),
				productions: get_player_productions(),
				resources: get_player_resources()
			};
		}
		function get_player_body_from( element ){
			const technologies = element.querySelectorAll( '.values:not( .items, .resources, .storage, .research ) > div' );
			return {
				name: element.querySelector( '.planetname' ).textContent,
				fields: get_player_fields_from( element ),
				temperatures: get_player_temperatures_from( element ),
				technologies: get_player_technologies_from( technologies ),
				resources: get_player_resources_from( element )
			};
		}
		function get_player_fields(){
			if( currentPage === 'overview' ){
				const content = document.querySelector( '#overviewcomponent > script:nth-child(2)' ).textContent;
				const values = content.replaceAll( LocalizationStrings.thousandSeperator, '' ).split( '\n' )[14].match( /\d+/g );
				return {
					used: parseInt( values[2] ),
					maximum: parseInt( values[3] )
				};
			}
		}
		function get_player_fields_from( element ){
			const values = element.querySelector( '.fields' ).textContent.match( /\d+/g );
			return {
				used: parseInt( values[0] ),
				maximum: parseInt( values[1] )
			};
		}
		function get_player_temperatures(){
			if( currentPage === 'overview' ){
				let values = document.querySelector( '#overviewcomponent > script:nth-child(2)' ).textContent;
				values = values.split( '\n' )[16];
				values = values.replaceAll( /\\u\S{0,5}/g, '' ).match( /-?\d+/g );
				return {
					min: parseInt( values[1] ),
					max: parseInt( values[2] )
				};
			}
		}
		function get_player_temperatures_from( element ){
			const values = element.querySelector( '.planetDataBottom' ).textContent.match( /-?\d+/g );
			return {
				min: parseInt( values[0] ),
				max: parseInt( values[1] )
			};
		}
		function get_player_lifeform(){
			let result = null;
			for( const key of [ 'lifeform1', 'lifeform2', 'lifeform3', 'lifeform4' ] ){
				if( document.querySelector( `#lifeform .${ key }` ) ){
					result = key;
					break;
				}
			}
			return result;
		}
		function get_player_productions(){
			const element = document.querySelector( '.listOfResourceSettingsPerPlanet' );
			if( element ){
				return {
					basic: {
						metal: get_player_productions_value_from( element.querySelector( '.alt :nth-child(2)' ) ),
						crystal: get_player_productions_value_from( element.querySelector( '.alt :nth-child(3)' ) )
					},
					mines: {
						metal: get_player_productions_value_from( element.querySelector( '.\\31  :nth-child(3)' ) ),
						crystal: get_player_productions_value_from( element.querySelector( '.\\32  :nth-child(4)' ) ),
						deuterium: get_player_productions_value_from( element.querySelector( '.\\33  :nth-child(5)' ) )
					},
					fusion: {
						deuterium: get_player_productions_value_from( element.querySelector( '.\\31 2  :nth-child(5)' ) ),
						factor: get_player_productions_factor_from( element.querySelector( '.\\31 2' ) )
					},
					lifeforms: get_player_productions_lifeform_from( element ),
					crawlers: {
						metal: get_player_productions_value_from( element.querySelector( '.\\32 17 :nth-child(3)' ) ),
						crystal: get_player_productions_value_from( element.querySelector( '.\\32 17 :nth-child(4)' ) ),
						deuterium: get_player_productions_value_from( element.querySelector( '.\\32 17 :nth-child(5)' ) ),
						factor: get_player_productions_factor_from( element.querySelector( '.\\32 17' ) )
					},
					plasma: {
						metal: get_player_productions_value_from( element.querySelector( '.\\31 22 :nth-child(3)' ) ),
						crystal: get_player_productions_value_from( element.querySelector( '.\\31 22 :nth-child(4)' ) ),
						deuterium: get_player_productions_value_from( element.querySelector( '.\\31 22 :nth-child(5)' ) )
					},
					objects: {
						metal: get_player_productions_value_from( element.querySelector( '.\\31 000 :nth-child(3)' ) ),
						crystal: get_player_productions_value_from( element.querySelector( '.\\31 000 :nth-child(4)' ) ),
						deuterium: get_player_productions_value_from( element.querySelector( '.\\31 000 :nth-child(5)' ) )
					},
					geologist: {
						metal: get_player_productions_value_from( element.querySelector( '.\\31 001 :nth-child(3)' ) ),
						crystal: get_player_productions_value_from( element.querySelector( '.\\31 001 :nth-child(4)' ) ),
						deuterium: get_player_productions_value_from( element.querySelector( '.\\31 001 :nth-child(5)' ) )
					},
					officers: {
						metal: get_player_productions_value_from( element.querySelector( '.\\31 003 :nth-child(3)' ) ),
						crystal: get_player_productions_value_from( element.querySelector( '.\\31 003 :nth-child(4)' ) ),
						deuterium: get_player_productions_value_from( element.querySelector( '.\\31 003 :nth-child(5)' ) )
					},
					classes: {
						player: {
							metal: get_player_productions_value_from( element.querySelector( '.\\31 004 :nth-child(3)' ) ),
							crystal: get_player_productions_value_from( element.querySelector( '.\\31 004 :nth-child(4)' ) ),
							deuterium: get_player_productions_value_from( element.querySelector( '.\\31 004 :nth-child(5)' ) )
						},
						alliance: {
							metal: get_player_productions_value_from( element.querySelector( '.\\31 005 :nth-child(3)' ) ),
							crystal: get_player_productions_value_from( element.querySelector( '.\\31 005 :nth-child(4)' ) ),
							deuterium: get_player_productions_value_from( element.querySelector( '.\\31 005 :nth-child(5)' ) )
						}
					},
					total: {
						metal: get_player_productions_value_from( element.querySelector( '.summary :nth-child(2)' ) ),
						crystal: get_player_productions_value_from( element.querySelector( '.summary :nth-child(3)' ) ),
						deuterium: get_player_productions_value_from( element.querySelector( '.summary :nth-child(4)' ) )
					}
				};
			}
		}
		function get_player_productions_lifeform_from( element ){
			const result = {
				metal: 0,
				crystal: 0,
				deuterium: 0
			};
			if( document.querySelector( '#lifeform .lifeform-item-icon' ) ){
				const elements = element.querySelectorAll( '.\\31 2 ~ tr' );
				for( const element of elements ){
					const is_satellite = element.classList.contains( '212' );
					if( is_satellite ) break;
					result.metal += get_player_productions_value_from( element.querySelector( ':nth-child(3)' ) );
					result.crystal += get_player_productions_value_from( element.querySelector( ':nth-child(4)' ) );
					result.deuterium += get_player_productions_value_from( element.querySelector( ':nth-child(5)' ) );
				}
			}
			return result;
		}
		function get_player_productions_value_from( element ){
			let value = element.querySelector( 'span' ).title;
			value = value.replaceAll( LocalizationStrings.thousandSeperator, '' );
			value = value.replace( LocalizationStrings.decimalPoint, '.' );
			return parseFloat( value );
		}
		function get_player_productions_factor_from( element ){
			// dropdown game options management
			let value = element.querySelector( 'a' )?.dataset.value;
			value ||= element.querySelector( 'option:checked' ).value;
			return parseInt( value ) * .01;
		}
		function get_player_resources(){
			const result = {};
			const resources = resourcesBar.resources;
			for( const key in resources ){
				result[ key ] = resources[ key ].amount;
			}
			return result
		}
		function get_player_resources_from( element ){
			const result = {};
			result.energy = parseInt( element.querySelector( '.planetDataTop .coords.textRight' ).textContent );
			for( const { classList, textContent } of element.querySelectorAll( '.resources > div' ) ){
				const key = classList[0];
				const value = parseInt( textContent.replaceAll( LocalizationStrings.thousandSeperator, '' ) );
				result[ key ] = value;
			}
			return result;
		}
		function get_player_lifeforms(){
			if( currentPage === 'lfsettings' ){
				const result = {};
				for( const element of document.querySelectorAll( '.lifeform-item' ) ){
					const id = element.querySelector( '.lifeform-item-icon' ).classList[1];
					const values = element.querySelector( '.lifeform-item-wrapper p:nth-last-of-type(2)' ).textContent.match( /\d+/g );
					result[ id ] = {
						level: parseInt( values[0] ),
						xp: {
							current: parseInt( values[1] ),
							maximum: parseInt( values[2] )
						}
					};
				}
				return result;
			}
		}
		function get_player_researches(){
			if( currentPage === 'empire' ){
				const elements = document.querySelector( '.planet:not( .summary )' ).querySelectorAll( '.research > div' );
				return get_player_technologies_from( elements );
			}else if( currentPage === 'research' ){
				return get_player_technologies();
			}
		}
		function get_player_technologies_from( elements ){
			const result = {};
			for( const element of elements ){
				const id = parseInt( element.classList[0] );
				const value = Types.get_number_from( element.firstChild.textContent );
				let upgrade = 0;
				if( id > 200 && id < 600 ){
					for( const { textContent } of element.querySelectorAll( '.active, .loop' ) ){
						upgrade += parseInt( textContent );
					}
				}else{
					const content = element.querySelector( '.active' )?.textContent;
					upgrade = Math.max( 0, parseInt( content || 0 ) - value );
				}
				result[ id ] = {
					value,
					upgrade,
					upgraded: value + upgrade
				}
			}
			return result;
		}
		function get_player_technologies_from_body(){
			const has_technologies = document.querySelector( '#technologies' );
			const is_research = currentPage === 'research';
			if( has_technologies && !is_research ){
				return get_player_technologies();
			}
		}
		function get_player_technologies(){
			const result = {};
			for( const element of document.querySelectorAll( '#technologies ul > li.hasDetails' ) ){
				const id = parseInt( element.dataset.technology );
				const value = parseInt( element.querySelector( '.level, .amount' ).dataset.value );
				let upgrade = 0;
				if( id > 200 && id < 600 ){
					for( const element of document.querySelectorAll( '#productionboxshipyardcomponent :is( .first, .queue td )' ) ){
						const { src } = element.querySelector( 'img' );
						if( Classes.technologies.ids.miniatures[ src ] === id ){
							upgrade += parseInt( element.textContent );
						}
					}
				}else{
					const level = element.querySelector( '.targetlevel' )?.dataset.value || 0;
					upgrade = Math.max( 0, parseInt( level ) - value );
				}
				result[ id ] = {
					value,
					upgrade,
					upgraded: value + upgrade
				}
			}
			return result;
		}
		function get_player_alliance(){
			if( currentPage === 'alliance' ){
				const classes = document.querySelector( '.alliance_class' ).classList;
				const result = {};
				for( const key of [ 'trader', 'warrior', 'explorer' ] ){
					if( classes.contains( key ) ){
						result.class = key;
						break;
					}
				}
				return result;
			}
		}
		function get_universe(){
			return {
				language: document.head.querySelector( 'meta[name=ogame-language]' ).content,
				name: document.head.querySelector( 'meta[name=ogame-universe-name]' ).content,
				speed: parseInt( document.head.querySelector( 'meta[name=ogame-universe-speed]' ).content ),
				highscores: get_universe_highscores()
			};
		}
		function get_universe_highscores(){
			if( currentPage === 'highscore' ){
				const result = {};
				const category = result[ currentCategory ] = {};
				const type = category[ currentType ] = {};
				const players = type.players = {};
				const player = type.player = {};
				const positions = player.positions = {};
				if( document.querySelector( '.myrank' ) ){
					positions.current = parseInt( document.querySelector( '.myrank .position' ).textContent );
					player.points = get_universe_highscores_points_from( document.querySelector( '.myrank .score' ) );
				}
				for( const element of document.querySelectorAll( '#ranks tbody tr' ) ){
					const position = parseInt( element.querySelector( '.position' ).textContent );
					players[ position ] = get_universe_highscores_points_from( element.querySelector( '.score' ) );
				}
				return result;
			}
		}
		function get_universe_highscores_points_from( element ){
			// firstChild used for OGLight compatibility
			const value = element.firstChild.textContent;
			return Types.get_number_from( value );
		}
		function element_has_changed( selector ){
			return new Promise( function( resolve ){
				const element = document.querySelector( selector );
				const options = { childList: true, subtree: true }
				const observer = new MutationObserver( function(){
					observer.disconnect();
					resolve();
				} );
				observer.observe( element, options );
			} );
		}
		return {
			get,
			element_has_changed
		};
	})();
	const Storage = (function(){
		const id = document.head.querySelector( 'meta[name=ogame-player-id]' ).content;
		const version = 5;
		const key = `${ id }_v${ version }`;
		function get(){
			return GM_getValue( key, {} );
		}
		function set_from( data ){
			GM_setValue( key, data );
		}
		function clear(){
			GM_setValue( key, {} );
		}
		return {
			get,
			set_from,
			clear
		};
	})();
	const Translation = (function(){
		const translations = {
			en: {
				1: 'Metal mine',
				2: 'Crystal mine',
				3: 'Deuterium synthesizer',
				4: 'Solar plant',
				12: 'Fusion plant',
				14: 'Robotics factory',
				15: 'Nanite factory',
				21: 'Shipyard',
				22: 'Metal storage',
				23: 'Crystal storage',
				24: 'Deuterium storage',
				31: 'Research laboratory',
				33: 'Terraformer',
				34: 'Alliance depot',
				36: 'Repair dock',
				41: 'Moonbase',
				42: 'Sensor phalanx',
				43: 'Jump gate',
				44: 'Missile silo',
				106: 'Espionage',
				108: 'Computer',
				109: 'Weapons',
				110: 'Shielding',
				111: 'Armour',
				113: 'Energy',
				114: 'Hyperspace',
				115: 'Combustion drive',
				117: 'Impulse drive',
				118: 'Hyperspace drive',
				120: 'Laser',
				121: 'Ion',
				122: 'Plasma',
				123: 'Intergalacticresearch network',
				124: 'Astrophysics',
				199: 'Graviton',
				202: 'Small cargo',
				203: 'Large cargo',
				204: 'Light fighter',
				205: 'Heavy fighter',
				206: 'Cruiser',
				207: 'Battleship',
				208: 'Colony ship',
				209: 'Recycler',
				210: 'Espionage probe',
				211: 'Bomber',
				212: 'Solar satellite',
				213: 'Destroyer',
				214: 'Deathstar',
				215: 'Battlecruiser',
				217: 'Crawler',
				218: 'Reaper',
				219: 'Pathfinder',
				401: 'Rocket launchers',
				402: 'Light lasers',
				403: 'Heavy laser',
				404: 'Gauss cannon',
				405: 'Ion cannon',
				406: 'Plasma turret',
				407: 'Small shield dome',
				408: 'Large shield dome',
				502: 'Anti-ballistic missiles',
				503: 'Interplanetary missile',
				11_101: 'Residential Sector',
				11_102: 'Biosphere Farm',
				11_103: 'Research Centre',
				11_104: 'Academy of Sciences',
				11_105: 'Neuro-Calibration Centre',
				11_106: 'High Energy Smelting',
				11_107: 'Food Silo',
				11_108: 'Fusion-Powered Production',
				11_109: 'Skyscraper',
				11_110: 'Biotech Lab',
				11_111: 'Metropolis',
				11_112: 'Planetary Shield',
				11_201: 'Intergalactic Envoys',
				11_202: 'High-Performance Extractors',
				11_203: 'Fusion Drives',
				11_204: 'Stealth Field Generator',
				11_205: 'Orbital Den',
				11_206: 'Research AI',
				11_207: 'High-Performance Terraformer',
				11_208: 'Enhanced Production Technologies',
				11_209: 'Light Fighter Mk II',
				11_210: 'Cruiser Mk II',
				11_211: 'Improved Lab Technology',
				11_212: 'Plasma Terraformer',
				11_213: 'Low-Temperature Drives',
				11_214: 'Bomber Mk II',
				11_215: 'Destructeur Mk II',
				11_216: 'Battlecruiser Mk II',
				11_217: 'Robot Assistants',
				11_218: 'Supercomputer',
				12_101: 'Meditation Enclave',
				12_102: 'Crystal Farm',
				12_103: 'Rune Technologium',
				12_104: 'Rune Forge',
				12_105: 'Oriktorium',
				12_106: 'Magma Forge',
				12_107: 'Disruption Chamber',
				12_108: 'Megalith',
				12_109: 'Crystal Refinery',
				12_110: 'Deuterium Synthesiser',
				12_111: 'Mineral Research Centre',
				12_112: 'Advanced Recycling Plant',
				12_201: 'Magma Refinement',
				12_202: 'Acoustic Scanning',
				12_203: 'High Energy Pump Systems',
				12_204: 'Cargo Hold Expansion',
				12_205: 'Magma-Powered Production',
				12_206: 'Geothermal Power Plants',
				12_207: 'Depth Sounding',
				12_208: 'Ion Crystal Enhancement (Heavy Fighter)',
				12_209: 'Improved Stellarator',
				12_210: 'Hardened Diamond Drill Heads',
				12_211: 'Seismic Mining Technology',
				12_212: 'Magma-Powered Pump Systems',
				12_213: 'Ion Crystal Modules',
				12_214: 'Optimised Silo Construction Method',
				12_215: 'Diamond Energy Transmitter',
				12_216: 'Obsidian Shield Reinforcement',
				12_217: 'Rune Shields',
				12_218: 'Rock’tal Collector Enhancement',
				13_101: 'Assembly Line',
				13_102: 'Fusion Cell Factory',
				13_103: 'Robotics Research Centre',
				13_104: 'Update Network',
				13_105: 'Quantum Computer Centre',
				13_106: 'Automatised Assembly Centre',
				13_107: 'High-Performance Transformer',
				13_108: 'Microchip Assembly Line',
				13_109: 'Production Assembly Hall',
				13_110: 'High-Performance Synthesiser',
				13_111: 'Chip Mass Production',
				13_112: 'Nano Repair Bots',
				13_201: 'Catalyser Technology',
				13_202: 'Plasma Drive',
				13_203: 'Efficiency Module',
				13_204: 'Depot AI',
				13_205: 'General Overhaul (Light Fighter)',
				13_206: 'Automated Transport Lines',
				13_207: 'Improved Drone AI',
				13_208: 'Experimental Recycling Technology',
				13_209: 'General Overhaul (Cruiser)',
				13_210: 'Slingshot Autopilot',
				13_211: 'High-Temperature Superconductors',
				13_212: 'General Overhaul (Battleship)',
				13_213: 'Artificial Swarm Intelligence',
				13_214: 'General Overhaul (Battlecruiser)',
				13_215: 'General Overhaul (Bomber)',
				13_216: 'General Overhaul (Destroyer)',
				13_217: 'Experimental Weapons Technology',
				13_218: 'Mechan General Enhancement',
				14_101: 'Sanctuary',
				14_102: 'Antimatter Condenser',
				14_103: 'Vortex Chamber',
				14_104: 'Halls of Realisation',
				14_105: 'Forum of Transcendence',
				14_106: 'Antimatter Convector',
				14_107: 'Cloning Laboratory',
				14_108: 'Chrysalis Accelerator',
				14_109: 'Bio Modifier',
				14_110: 'Psionic Modulator',
				14_111: 'Ship Manufacturing Hall',
				14_112: 'Supra Refractor',
				14_201: 'Heat Recovery',
				14_202: 'Sulphide Process',
				14_203: 'Psionic Network',
				14_204: 'Telekinetic Tractor Beam',
				14_205: 'Enhanced Sensor Technology',
				14_206: 'Neuromodal Compressor',
				14_207: 'Neuro-Interface',
				14_208: 'Interplanetary Analysis Network',
				14_209: 'Overclocking (Heavy Fighter)',
				14_210: 'Telekinetic Drive',
				14_211: 'Sixth Sense',
				14_212: 'Psychoharmoniser',
				14_213: 'Efficient Swarm Intelligence',
				14_214: 'Overclocking (Large Cargo)',
				14_215: 'Gravitation Sensors',
				14_216: 'Overclocking (Battleship)',
				14_217: 'Psionic Shield Matrix',
				14_218: 'Kaelesh Discoverer Enhancement',
				account_overview: "Account overview",
				alliance: 'Alliance',
				amortizations: 'Amortizations',
				at: 'at',
				buildings: 'Buildings',
				classes_alliance_researcher: 'Researcher',
				classes_alliance_trader: 'Trader',
				classes_alliance_warrior: 'Warrior',
				classes_player_explorer: 'Discoverer',
				classes_player_miner: 'Collector',
				classes_player_warrior: 'General',
				clear_confirm: 'You are going to delete the InfoCompte data.',
				colors: 'Colors',
				crystal: 'Crystal',
				daily_productions: 'Daily productions',
				data_alert: 'Data are missing. Visit the Empire view.',
				days: 'jours',
				defences: 'Defences',
				deuterium: 'Deuterium',
				deuterium_equivalent: 'Deuterium equivalent',
				empire: 'Empire',
				empire_of: "Empire of",
				export_notification: 'Export placed in clipboard',
				generated_on: 'Generated on',
				highscore: 'Highscore',
				hours: 'hours',
				if_destroyed: 'place(s) if destroyed',
				image: 'Image',
				indestructibles: 'Indestructibles',
				levels: 'Levels',
				lifeform1: 'Human',
				lifeform2: 'Rock’tal',
				lifeform3: 'Mecha',
				lifeform4: 'Kaelesh',
				lifeforms: 'Lifeforms',
				lifeforms_buildings: 'Lifeform buildings',
				lifeforms_levels: 'Lifeform levels',
				lifeforms_researches: 'Lifeform researches',
				maximum: 'maximum',
				metal: 'Metal',
				mines: 'Mines',
				mines_only: 'Mines only',
				months: 'months',
				moon: 'Moon',
				moons_buildings: 'Moons buildings',
				moons_defences: 'Moons defences',
				objects: 'Objects',
				officers: 'Officers',
				on: 'on',
				others: 'Others',
				planet: 'Planet',
				planet_fields: 'Planet fields',
				planets: 'Planets',
				planets_buildings: 'Planetary buildings',
				planets_defences: 'Planetary defences',
				planets_points_repartition: 'Planets points repartition',
				points: 'Points',
				points_repartition: 'Points repartition',
				production: 'Production',
				production_of: "Production of",
				productions: 'Productions',
				queue: 'Upgrades queue',
				rates: 'Trade rates',
				recalculate: 'Recalculate',
				researches: 'Researches',
				resources: 'Resources',
				script_data: 'Script data',
				settings: 'Settings',
				ships: 'Ships',
				shipyards: 'Shipyards',
				support_link: "https://forum.origin.ogame.gameforge.com/forum/thread/151-infocompte/",
				temperatures_maximum: 'Maxmimum temperatures',
				text: 'Text',
				total: 'Total',
				upgrades: 'In construction',
				used: 'used',
				weeks: 'weeks',
				when_finished: 'place(s) when finished',
				with: 'with',
				years: 'years'
			},
			fr: {
				1: "Mine de métal",
				2: "Mine de cristal",
				3: "Synthétiseur de deutérium",
				4: "Centrale électrique solaire",
				12: "Centrale électrique de fusion",
				14: "Usine de robots",
				15: "Usine de nanites",
				21: "Chantier spatial",
				22: "Hangar de métal",
				23: "Hangar de cristal",
				24: "Réservoir de deutérium",
				31: "Laboratoire de recherche",
				33: "Terraformeur",
				34: "Dépôt de ravitaillement",
				36: "Dock spatial",
				41: "Base lunaire",
				42: "Phalange de capteur",
				43: "Porte de saut spatial",
				44: "Silo de missiles",
				106: "Espionnage",
				108: "Ordinateur",
				109: "Armes",
				110: "Bouclier",
				111: "Protection",
				113: "Énergie",
				114: "Hyperespace",
				115: "Réacteur à combustion",
				117: "Réacteur à impulsion",
				118: "Propulsion hyperespace",
				120: "Laser",
				121: "Ions",
				122: "Plasma",
				123: "Réseau de recherche",
				124: "Astrophysique",
				199: "Graviton",
				202: "Petit transporteur",
				203: "Grand transporteur",
				204: "Chasseur léger",
				205: "Chasseur lourd",
				206: "Croiseur",
				207: "Vaisseau de bataille",
				208: "Vaisseau de colonisation",
				209: "Recycleur",
				210: "Sonde d'espionnage",
				211: "Bombardier",
				212: "Satellite solaire",
				213: "Destructeur",
				214: "Étoile de la mort",
				215: "Traqueur",
				217: "Foreuse",
				218: "Faucheur",
				219: "Éclaireur",
				401: "Lanceur de missiles",
				402: "Artillerie laser légère",
				403: "Artillerie laser lourde",
				404: "Canon de Gauss",
				405: "Artillerie à ions",
				406: "Lanceur de plasma",
				407: "Petit bouclier",
				408: "Grand bouclier",
				502: "Missile d'interception",
				503: "Missile interplanétaire",
				11_101: "Secteur résidentiel",
				11_102: "Ferme biosphérique",
				11_103: "Centre de recherche",
				11_104: "Académie des sciences",
				11_105: "Centre de neurocalibrage",
				11_106: "Fusion à haute énergie",
				11_107: "Réserve alimentaire",
				11_108: "Extraction par fusion",
				11_109: "Tour d’habitation",
				11_110: "Laboratoire de biotechnologie",
				11_111: "Metropolis",
				11_112: "Bouclier planétaire",
				11_201: "Intergalactic Envoys",
				11_202: "Extracteurs à haute performance",
				11_203: "Moteur à fusion",
				11_204: "Générateur de champ de camouflage",
				11_205: "Planque orbitale",
				11_206: "IA de recherche",
				11_207: "Terraformeur à haute performance",
				11_208: "Technologies d'extraction améliorés",
				11_209: "Chasseur léger Mk II",
				11_210: "Croiseur Mk II",
				11_211: "Technologie de laboratoire améliorée",
				11_212: "Terraformeur à plasma",
				11_213: "Propulseurs à faible température",
				11_214: "Bombardier Mk II",
				11_215: "Destroyer Mk II",
				11_216: "Traqueur Mk II",
				11_217: "Assistants robotiques",
				11_218: "Superordinateur",
				12_101: "Enclave stoïque",
				12_102: "Culture du cristal",
				12_103: "Centre technologique runique",
				12_104: "Forge runique",
				12_105: "Orictorium",
				12_106: "Fusion magmatique",
				12_107: "Chambre de disruption",
				12_108: "Monument rocheux",
				12_109: "Raffinerie de cristal",
				12_110: "Syntoniseur de deutérium",
				12_111: "Centre de recherche sur les minéraux",
				12_112: "Usine de traitement à haut rendement",
				12_201: "Batteries volcaniques",
				12_202: "Sondage acoustique",
				12_203: "Système de pompage à haute énergie",
				12_204: "Extension d'espace fret",
				12_205: "Extraction",
				12_206: "Centrales géothermiques",
				12_207: "Sondage en profondeur",
				12_208: "Renforcement à cristaux ioniques",
				12_209: "Stellarator amélioré",
				12_210: "Tête de forage en dimant",
				12_211: "Technologie d'extraction sismique",
				12_212: "Pompes au magma",
				12_213: "Module à cristaux ioniques",
				12_214: "Construction optimisée de silos",
				12_215: "Émetteur d'énergie à diamants",
				12_216: "Intensification du bouclier à l'obsidienne",
				12_217: "Boucliers runiques",
				12_218: "Renfort du collecteur Rocta",
				13_101: "Chaîne de production",
				13_102: "Usine de fusion de cellules",
				13_103: "Centre de recherche en robotique",
				13_104: "Réseau d’actualisation",
				13_105: "Centre d’informatique quantique",
				13_106: "Centre d’assemblage automatisé",
				13_107: "Transformateur hyperpuissant",
				13_108: "Chaîne de production de micropuces",
				13_109: "Atelier de montage",
				13_110: "Synthétiseur à haut rendement",
				13_111: "Production de masse de puces",
				13_112: "Nanorobots réparateurs",
				13_201: "Technique de catalyse",
				13_202: "Moteur à plasma",
				13_203: "Module d'optimisation",
				13_204: "IA du dépôt",
				13_205: "Révision général (chasseur léger)",
				13_206: "Chaîne de production automatisée",
				13_207: "IA de drone améliorée",
				13_208: "Technique de recyclage expérimental",
				13_209: "Révision général (croiseur)",
				13_210: "Pilote automatique Slingshot",
				13_211: "Supraconducteur à haute température",
				13_212: "Révision général (vaisseau de bataille)",
				13_213: "Intelligence artificielle collective",
				13_214: "Révision général (traqueur)",
				13_215: "Révision général (bombardier)",
				13_216: "Révision général (destructeur)",
				13_217: "Technique d'armement expérimental",
				13_218: "Renforcement du général des Mechas",
				14_101: "Refugium",
				14_102: "Condensateur d’antimatière",
				14_103: "Salle à vortex",
				14_104: "Maison du savoir",
				14_105: "Forum de la transcendance",
				14_106: "Convecteur d’antimatière",
				14_107: "Laboratoire de clonage",
				14_108: "Accélérateur par chrysalide",
				14_109: "Biomodificateur",
				14_110: "Modulateur psionique",
				14_111: "Hangar de construction de vaisseau",
				14_112: "Supraréfracteur",
				14_201: "Récupération de chaleur",
				14_202: "Traitement au sulfure",
				14_203: "Réseau psionique",
				14_204: "Faisceau de traction télékinésique	",
				14_205: "Technologie de détection améliorée",
				14_206: "Compresseur neuromodal",
				14_207: "Neuro-interface",
				14_208: "Réseau d'analyse superglobal",
				14_209: "Surcadençage (chasseur lourd)",
				14_210: "Système de propulsion télékinétique",
				14_211: "Sixième sens",
				14_212: "Harmonisateur psychique",
				14_213: "Efficient Swarm Intelligence",
				14_214: "Surcadençage (grand transporteur)",
				14_215: "Capteurs gravitationnels",
				14_216: "Surcadençage (vaisseau de bataille)",
				14_217: "Matrice de protection psionique",
				14_218: "Renforcement d'explorateur Kaelesh",
				account_overview: "Résumé du compte",
				alliance: "Alliance",
				amortizations: "Amortissements",
				at: "à",
				buildings: "Bâtiments",
				classes_alliance_researcher: "Chercheur",
				classes_alliance_trader: "Marchand",
				classes_alliance_warrior: "Guerrier",
				classes_player_explorer: "Explorateur",
				classes_player_miner: "Collecteur",
				classes_player_warrior: "Général",
				clear_confirm: "Vous êtes sur le point de supprimer les données d'InfoCompte.",
				colors: "Couleurs",
				crystal: "Cristal",
				daily_productions: "Productions journalières",
				data_alert: "Il manque des données. Visitez la vue Empire.",
				days: "jours",
				defences: "Défenses",
				deuterium: "Deutérium",
				deuterium_equivalent: "Équivalent deutérium",
				empire: "Empire",
				empire_of: "Empire du joueur",
				export_notification: "Export placé dans le presse-papier",
				generated_on: "Généré le",
				highscore: "Classement",
				hours: "heures",
				if_destroyed: "place(s) si détruit",
				image: "Image",
				indestructibles: "Indestructibles",
				levels: "Niveaux",
				lifeform1: "Humains",
				lifeform2: "Roctas",
				lifeform3: "Mecas",
				lifeform4: "Kaeleshs",
				lifeforms: "Formes de vie",
				lifeforms_buildings: "Bâtiments FDV",
				lifeforms_levels: "Niveaux des FDV",
				lifeforms_researches: "Recherches FDV",
				maximum: "maximum",
				metal: "Métal",
				mines: "Mines",
				mines_only: "Mines seules",
				months: "mois",
				moon: "Lune",
				moons_buildings: "Bâtiments lunaires",
				moons_defences: "Défenses lunaires",
				objects: "Objets",
				officers: "Officiers",
				on: "sur",
				others: "Autres",
				planet: "Planète",
				planet_fields: "Cases planétaires",
				planets: "Planètes",
				planets_buildings: "Bâtiments planétaires",
				planets_defences: "Défenses planétaires",
				planets_points_repartition: "Répartition des points par planète",
				points: "Points",
				points_repartition: "Répartition des points",
				production: "Production",
				production_of: "Production du joueur",
				productions: "Productions",
				queue: "File de constructions",
				rates: "Taux de change",
				recalculate: "Recalculer",
				researches: "Recherches",
				resources: "Ressources",
				script_data: "Données du script",
				settings: "Options",
				ships: "Vaisseaux",
				shipyards: "Chantiers spatiaux",
				support_link: "https://board.fr.ogame.gameforge.com/index.php?thread/746302-infocompte/",
				temperatures_maximum: "Températures maximales",
				text: "Texte",
				total: "Total",
				upgrades: "En construction",
				used: "utilisées",
				weeks: "semaines",
				when_finished: "place(s) quand terminé",
				with: "avec",
				years: "années"
			}
		};
		const translation = translations[ document.documentElement.lang ] || translations.en;
		return translation;
	})();
	const Types = (function(){
		const locale = LocalizationStrings.decimalPoint === '.' ? 'en-US' : 'de-DE';
		const options = {
			compact: {
				notation: 'compact' ,
				compactDisplay: 'short',
				maximumFractionDigits: 2
			},
			decimal: {
				style: 'decimal',
				maximumFractionDigits: 2
			},
			percent: {
				style: 'percent',
				minimumFractionDigits: 2
			}
		};
		function get_number_from( value ){
			value = value.replaceAll( LocalizationStrings.thousandSeperator, '' );
			return parseInt( value );
		}
		function get_string_number_compact_from( value ){
			value = Math.floor( value ).toLocaleString( 'en', options.compact );
			return value.replaceAll( '.', LocalizationStrings.decimalPoint );
		}
		function get_string_number_full_from( value ){
			return value.toLocaleString( locale, options.decimal );
		}
		function get_string_number_truncated_from( value ){
			return Math.trunc( value ).toLocaleString( locale, options.decimal );
		}
		function get_duration_from( value ){
			let unit;
			if( value === Infinity ){
				return '&infin;';
			}else if( value > 8_760 ){
				unit = Translation.years;
				value /= 8_760
			}else if( value > 732 ){
				unit = Translation.months;
				value /= 732;
			}else if( value > 168 ){
				unit = Translation.weeks;
				value /= 168;
			}else if( value > 24 ){
				unit = Translation.days;
				value /= 24;
			}else{
				unit = Translation.hours;
			}
			value = value.toLocaleString( locale, options.decimal );
			return `${ value } ${ unit }`;
		}
		function get_percent_from( value ){
			return value.toLocaleString( locale, options.percent );
		}
		function are_objects( ...values ){
			let result = true;
			for( const value of values ){
				const is_object = value != null && value.constructor.name === 'Object';
				if( !is_object ){
					result = false;
					break;
				}
			}
			return result;
		}
		return {
			get_number_from,
			get_string_number_compact_from,
			get_string_number_full_from,
			get_string_number_truncated_from,
			get_duration_from,
			get_percent_from,
			are_objects
		};
	})();
// Initialization
	const storage = Storage.get();
	const scraper = await Scraper.get();
	const data = Data.get_from( storage, scraper );
	Components.init_from( data );
	Storage.set_from( data );