// ==UserScript==
// @name Webgame vylepšení
// @version 2024-06-27
// @description Sbírka vylepšení pro hru Webgame
// @author yS
// @match *://*.webgame.cz/wg/*
// @grant GM_setValue
// @grant GM_getValue
// @grant GM_deleteValue
// @grant GM_listValues
// @grant GM_info
// @icon https://www.google.com/s2/favicons?sz=64&domain=webgame.cz
// @namespace https://greasyfork.org/users/1005892
// ==/UserScript==
// TODO:
// nastaveni zobrazeni pomeru ztrat prestize utocnika / obrance
// nastaveni prevodu techu na $
// otestovat obyc listu
// archiv - ztraty nase / nepritele
// archiv - ztraty v $
(function () {
"use strict";
// options
const VALKY_OBRACENE = "valky_flipped";
const ZOBRAZENE_ZOLDY = "zobrazene_zoldy";
const MODIFY_ARCHIVE = "modify_archive";
const MODIFY_ADVANCEMENTS = "modify_advancements";
// menu options
const ROZVOJ_MENU_LINK = "rozvoj";
const GENERALS_MENU_LINK = "generalove";
const PRODEJ_MENU_LINK = "prodej";
const POKROKY_MENU_LINK = "pokroky";
// budovy settings
const COUNTRY_ALI_DATA = "country_ali_data";
const COUNTRY_ALI_DATA_TIME_OFFSET_MILLIS = 24 * 60 * 60 * 1000;
// rozvedka
const REPEAT_ROZVEDKA = "rozvedka_repeat";
const MAX_OBTIZNOST_OPERACE = "rozvedka_difficulty";
// prices
const ENERGY_PRICE = "energy";
const FOOD_PRICE = "food";
const TECHNOLOGY_PRICES = "tech_prices";
// country stats
const COUNTRY_STATS = "country_stats";
// pokroky
const ADV_SHOW_BASE_PRICE = "advancements_show_base_price";
const ADV_SHOW_BASE_PRICE_IN_TOOLTIP = "advancements_show_base_price_tooltip";
const ADV_SHOW_MIN_PRICE = "advancements_show_min_price";
const ADV_SHOW_MIN_PRICE_IN_TOOLTIP = "advancements_show_min_price_tooltip";
const ADV_SHOW_CURRENT_PRICE = "advancements_show_current_price";
// aliance
const ALI_ALLOW_CHANGES = "aliance_modify";
const ALI_SHOW_CARDS = "aliance_show_cards";
const ALI_SHOW_REGIME = "aliance_show_regime";
const ALI_SHOW_ROCKETS = "aliance_show_rockets";
const ALI_SHOW_WARS = "aliance_show_wars";
const ALI_WARS_WITH_ANCHORS = "aliance_show_wars_with_anchors";
const ALI_SHOW_FILTER = "aliance_show_filter";
const ALI_SAVED_INFO = "aliance_saved_info";
// strike
const STRIKE_SHOW_EXP = "strike_show_exp";
const STRIKE_WARNING_DISABLES_BUTTON = "strike_warning_disables_button";
const USED_SETTINGS = [
ROZVOJ_MENU_LINK,
GENERALS_MENU_LINK,
PRODEJ_MENU_LINK,
POKROKY_MENU_LINK,
REPEAT_ROZVEDKA,
MAX_OBTIZNOST_OPERACE,
VALKY_OBRACENE,
ZOBRAZENE_ZOLDY,
ENERGY_PRICE,
FOOD_PRICE,
COUNTRY_ALI_DATA,
COUNTRY_STATS,
TECHNOLOGY_PRICES,
MODIFY_ARCHIVE,
MODIFY_ADVANCEMENTS,
ADV_SHOW_BASE_PRICE,
ADV_SHOW_BASE_PRICE_IN_TOOLTIP,
ADV_SHOW_MIN_PRICE,
ADV_SHOW_MIN_PRICE_IN_TOOLTIP,
ADV_SHOW_CURRENT_PRICE,
ALI_ALLOW_CHANGES,
ALI_SHOW_CARDS,
ALI_SHOW_REGIME,
ALI_SHOW_ROCKETS,
ALI_SHOW_WARS,
ALI_WARS_WITH_ANCHORS,
ALI_SHOW_FILTER,
ALI_SAVED_INFO,
STRIKE_SHOW_EXP,
STRIKE_WARNING_DISABLES_BUTTON,
];
function execute() {
deleteUnusedSettings();
createMenuItemSettings();
addMenuLinks();
modifyLista();
if (location.href.indexOf("s=detailyaliance") != -1) {
modifyDetailyAli();
} else if (location.href.indexOf("s=ppravidla") != -1) {
modifyPravidlaValky();
} else if (location.href.indexOf("index.php?p=konflikty&s=awarstat&getali=") != -1) {
modifyValky();
} else if (location.href.indexOf("p=dotace&s=ehelp") != -1) {
modifyHospoPage();
} else if (location.href.endsWith("p=detaily") || location.href.indexOf("detaily&sid=") != -1 || location.href.indexOf("p=detaily&s=detaily&adetaily=true") != -1) {
processCountryDetail();
} else if (location.href.indexOf("s=detailyprestiz") != -1) {
processPrestigeDetails();
} else if (location.href.endsWith("p=rozvedka&s=tajsluzba") == true || location.href.indexOf("p=rozvedka") !== -1) {
modifyRozvedka();
} else if (location.href.endsWith("p=zebricek&s=stats")) {
modifyStatisticsPage();
} else if (location.href.indexOf("archiv") != -1) {
modifyArchive();
} else if (location.href.indexOf("p=technologie&s=pokroky") != -1) {
modify_advancements.process();
} else if (location.href.indexOf("p=valka") != -1) {
modify_valka.process();
} else if (location.href.indexOf("p=zebricek&s=aliazebr") != -1) {
ali_zebricek.process();
}
}
let log;
setLogger(console.log);
function setLogger(logger) {
// eslint-disable-next-line no-undef
log = logger.bind(console, `[${GM_info.script.name}]`);
}
function setSetting(setting_name, value) {
// eslint-disable-next-line no-undef
GM_setValue(setting_name, value);
}
function getSetting(setting_name, default_value) {
// eslint-disable-next-line no-undef
return GM_getValue(setting_name, default_value);
}
async function deleteUnusedSettings() {
// eslint-disable-next-line no-undef
const keys = await GM_listValues();
keys.forEach((key) => {
if (!USED_SETTINGS.includes(key)) {
// eslint-disable-next-line no-undef
GM_deleteValue(key);
}
});
}
function createMenuItemSettings() {
const menu = document.getElementById("left_menu");
const list = menu.children[0];
let li = createElement("li");
list.appendChild(li);
let ul = createElement("ul");
li.appendChild(ul);
li = createElement("li");
ul.appendChild(li);
const settings_button = createElement("a", { textContent: "Modifikace ⚙️" });
settings_button.addEventListener("click", function () {
let element = document.getElementById("settings_window");
element.classList.toggle("hidden");
});
li.appendChild(settings_button);
createSettingsWindow();
}
function createElement(tag = "div", props = null, attributes = null) {
let element = document.createElement(tag);
for (const key in props) {
if (!Object.hasOwnProperty.call(props, key)) {
continue;
}
const value = props[key];
element[key] = value;
}
for (const key in attributes) {
if (!Object.hasOwnProperty.call(attributes, key)) {
continue;
}
const value = attributes[key];
if (typeof value === "object") {
Object.assign(element[key], value);
} else {
element.setAttribute(key, value);
}
}
return element;
}
function createButton(text, func = null, params = null, props = {}, attributes = null) {
if (props === null) props = {};
props.textContent = text;
props.type = "button";
const class_name = props.className ? props.className + " " : "";
props.className = class_name + "submit btn";
let button = createElement("button", props, attributes);
button.addEventListener("click", (e) => {
if (func !== null) {
func(params, e);
}
});
return button;
}
function createSettingsWindow() {
addSettingsCss();
const content = document.getElementById("content");
let div = createElement("div", { id: "settings_window", className: "settings_window hidden" });
content.appendChild(div);
let button = createButton(
"x",
() => {
div.classList.toggle("hidden");
},
null,
{ className: "btn-close" }
);
div.appendChild(button);
let settings = {
menu_link_header: { label: "Zobrazit v menu odkazy na:", header: true },
rozvoj_menu_link: { setting_name: ROZVOJ_MENU_LINK, label: "Rozvoj", default_value: true },
generalove_menu_link: { setting_name: GENERALS_MENU_LINK, label: "Generály", default_value: true },
prodej_menu_link: { setting_name: PRODEJ_MENU_LINK, label: "Prodej", default_value: true },
pokroky_menu_link: { setting_name: POKROKY_MENU_LINK, label: "Pokroky", default_value: true },
archive_header: { label: "Archiv:", header: true, space_before: true },
archive_changes: { setting_name: MODIFY_ARCHIVE, label: "Povolit změny", default_value: true },
pokroky_header: { label: "Pokroky:", header: true, space_before: true },
pokroky_changes: { setting_name: MODIFY_ADVANCEMENTS, label: "Povolit změny", default_value: true },
min_price: { setting_name: ADV_SHOW_MIN_PRICE, label: "Povolit zobrazení minimální ceny", default_value: true },
min_price_tooltip: { setting_name: ADV_SHOW_MIN_PRICE_IN_TOOLTIP, label: "Zobrazit minimální cenu v tooltipu", default_value: false },
base_price: { setting_name: ADV_SHOW_BASE_PRICE, label: "Povolit zobrazení základní ceny", default_value: true },
base_price_tooltip: { setting_name: ADV_SHOW_BASE_PRICE_IN_TOOLTIP, label: "Zobrazit základní cenu v tooltipu", default_value: true },
current_price: { setting_name: ADV_SHOW_CURRENT_PRICE, label: "Zobrazit aktuální cenu", default_value: true },
strike_header: { label: "Útok:", header: true, space_before: true },
strike_exp: { setting_name: STRIKE_SHOW_EXP, label: "Zobrazit zkušenosti za kolo", default_value: true },
strike_button: { setting_name: STRIKE_WARNING_DISABLES_BUTTON, label: "Potvrzení útoku při porušení pravidel", default_value: true },
ali_header: { label: "Žebříček aliancí:", header: true, space_before: true },
ali_changes: { setting_name: ALI_ALLOW_CHANGES, label: "Povolit změny", default_value: true },
ali_show_cards: { setting_name: ALI_SHOW_CARDS, label: "Zobrazit sloupec kartiček", default_value: true },
ali_show_regime: { setting_name: ALI_SHOW_REGIME, label: "Zobrazit sloupec zřízení", default_value: true },
ali_show_rockets: { setting_name: ALI_SHOW_ROCKETS, label: "Zobrazit sloupec rakety", default_value: true },
ali_show_wars: { setting_name: ALI_SHOW_WARS, label: "Zobrazit sloupec válek", default_value: true },
ali_show_wars_with_anchors: { setting_name: ALI_WARS_WITH_ANCHORS, label: "Sloupec válek obsahuje i kotvy", default_value: true },
ali_show_filter: { setting_name: ALI_SHOW_FILTER, label: "Zobrazit filtr", default_value: true },
others_header: { label: "Jiné:", header: true, space_before: true },
zobrazene_zoldy: { setting_name: ZOBRAZENE_ZOLDY, label: "Zobrazit výdaje armády v detailu země", default_value: true },
valky_obracene: { setting_name: VALKY_OBRACENE, label: "Války - poměr prestiží na začátku: vyhlašující ali / cílová", default_value: true },
};
for (const key in settings) {
const setting = settings[key];
if (setting.header) {
const h3 = createElement("h3", { textContent: setting.label, className: setting.space_before ? "m-top" : "" });
div.appendChild(h3);
} else {
const config = createConfig(setting.setting_name, setting.label, false, setting.default_value);
div.appendChild(config);
}
}
button = createButton(
"Refresh stránky",
() => {
refreshPage();
},
null,
{ className: "btn-refresh" }
);
div.appendChild(button);
}
function addArchiveCss() {
const styles = `
.row {
display: grid;
gap: 1rem;
grid-template-columns: 5fr 4fr 4fr;
}
.row span:first-child {
font-weight: bold;
}
.row span:not(:first-child) {
text-align: right;
}
`;
addCss(styles);
}
function addSettingsCss() {
const styles = `
.icon {
display: inline-block;
width: 16px;
height: 16px;
border: 1px solid black;
border-radius: 10px;
background: #aff;
color: black;
font-weight: bold;
text-align: center;
}
.btn {
width: fit-content;
border-radius: 2px;
padding: 0.2rem 0.4rem;
background-color: #444;
color: white;
cursor: pointer;
font-weight: bold;
text-shadow: 0 0 5px black;
-webkit-transition: background-color 400ms linear;
-ms-transition: background-color 400ms linear;
transition: background-color 400ms linear;
}
.btn:hover {
background-color: #777;
}
.btn.btn-close {
position: absolute;
top: 5px;
right: 5px;
}
.btn.btn-refresh {
margin-left: auto;
margin-right: auto;
}
.settings_window {
display: flex;
flex-direction: column;
gap: 2px;
z-index: 1000;
position: fixed;
padding: 10px;
top: 130px;
left: 150px;
background: #666;
border: 1px solid #aaa;
border-radius: 5px
}
.settings_window h3 {
margin: 0 0 6px 0;
font-weight: bold;
text-shadow: 0 0 5px black;
}
.settings_window .m-top {
margin-top: 10px;
}
.settings_window input[type=checkbox] {
margin-right: 10px;
cursor: pointer;
box-shadow: 3px 3px #555;
}
.hidden {
display: none;
}`;
addCss(styles);
}
function addTooltipCss(tooltip_width = 100, to_left = false) {
const margin_left = to_left ? tooltip_width * 0.75 : tooltip_width / 2;
const left = to_left ? 75 : 50;
const styles = `
.tooltip { position: relative; }
.tooltip .tooltiptext {
visibility: hidden;
width: ${tooltip_width}px;
top: 100%;
left: ${left}%;
margin-left: -${margin_left}px;
background-color: #363636;
color: #fff;
text-align: left;
padding: 5px 5px;
margin-top: 10px;
border-radius: 6px;
border: 1px solid white;
position: absolute;
z-index: 1;
}
.tooltip .tooltiptext.center { text-align: center; }
.tooltip:hover .tooltiptext { visibility: visible; }
.tooltip .tooltiptext::after {
content: ' ';
position: absolute;
bottom: 100%;
left: ${left}%;
margin-left: -5px;
border-width: 5px;
border-style: solid;
border-color: transparent transparent white transparent;
}
.tooltiptext .header { font-weight: bold; border-bottom: 1px solid white; }
.tooltiptext .divider { height: 1px; width: 100%; border-bottom: 1px solid white; } `;
addCss(styles);
}
function wrapInTooltip(element) {
element.classList.add("tooltiptext");
element.parentElement.classList.add("tooltip");
}
function createConfig(setting_name, label_text, force_reload = false, default_value = true) {
let label = createElement("label");
let input = createElement("input", { type: "checkbox", checked: getSetting(setting_name, default_value) });
label.appendChild(input);
label.appendChild(document.createTextNode(label_text));
input.addEventListener("change", function () {
setSetting(setting_name, input.checked);
if (force_reload) {
refreshPage();
}
});
return label;
}
function addMenuLinks() {
let vlada_menu_index = 4;
let play_menu_index = 5;
addButtonIfToggled(ROZVOJ_MENU_LINK, "Rozvoj", "index.php?p=vlada&s=rozvoj", vlada_menu_index, 1);
addButtonIfToggled(GENERALS_MENU_LINK, "Generálové", "index.php?p=valka&s=general", play_menu_index, 6);
addButtonIfToggled(PRODEJ_MENU_LINK, "Prodej", "index.php?p=svetovy_trh&s=trhposlat", play_menu_index, 4);
addButtonIfToggled(POKROKY_MENU_LINK, "Pokroky", "index.php?p=technologie&s=pokroky", play_menu_index, 3);
}
function addButtonIfToggled(value_key, button_text, link, menu_index, submenu_index) {
if (!getSetting(value_key, true)) {
return;
}
let menu = document.getElementById("left_menu");
menu = menu.children[0];
addButton(button_text, link, menu, menu_index, submenu_index);
}
function addButton(button_text, link, menu, menu_index, submenu_index) {
let relevant_menu = menu.children[menu_index].children[0];
let element = createElement("a", { href: link, textContent: button_text });
let li = createElement("li");
li.append(element);
relevant_menu.insertBefore(li, relevant_menu.children[submenu_index]);
}
// DETAILY ALI
function modifyDetailyAli() {
let table = document.getElementsByClassName("vis_tbl");
if (table == null) {
return;
}
table = table[0];
let exp_object = calculateExp(table);
let container_element = document.getElementsByClassName("container");
let content_element = container_element[0].children[0];
let div = createElement("div", {
style: "width: 250px; background: #222222; border: 2px solid; border-bottom-color: #000; border-right-color: #000; border-left-color: #555; border-top-color: #555; padding: 3px; margin-left: calc(50% - 125px); text-align: center;",
});
let p = createElement("p", { textContent: "Aktualní ali hodnost: " + exp_object.current_ali_level });
div.append(p);
p = createElement("p", { textContent: "Celkový počet zkušeností ali: " + exp_object.total_exp + "k" });
div.append(p);
p = createElement("p", { textContent: "Chybějící počet zkušeností ali: " + exp_object.missing_exp + "k" });
div.append(p);
content_element.insertBefore(div, content_element.children[1]);
}
function calculateExp(table) {
const EXPERIENCE_PER_LEVEL = [10000, 20000, 40000, 80000, 150000, 250000, 400000, 600000, 850000, 1150000, 1500000, 1950000, 2450000];
let rows = table.getElementsByTagName("tr");
let exp_total_row = rows[17];
let exp_total_columns = exp_total_row.getElementsByTagName("td");
let total_exp = 0;
let row_count = exp_total_columns.length;
let member_count = row_count - 1;
for (let i = 1; i < row_count; i++) {
total_exp = total_exp + parseInt(exp_total_columns[i].innerHTML) * 1000;
}
for (let i = 0; i < EXPERIENCE_PER_LEVEL.length; i++) {
if (EXPERIENCE_PER_LEVEL[i] * member_count < total_exp) {
continue;
}
let missing_exp = EXPERIENCE_PER_LEVEL[i] * member_count - total_exp;
let exp_object = {
missing_exp: missing_exp / 1000,
total_exp: total_exp / 1000,
current_ali_level: i + 1,
};
return exp_object;
}
}
// DETAILY ALI KONEC
// HOSPO, MAX PRESTIZ PRESTIZ
function modifyHospoPage() {
const table = document.forms[0].children[0];
if (table == null) return false;
const row = table.insertRow(table.rows.length - 1);
row.insertCell().textContent = "Prestiž";
let total_prestige = 0;
let prestige_per_unit = [0, 0, 0, 0.002, 0.02, 0.02, 1, 5, 3.5, 3.5, 2.7];
for (let i = 3; i < table.rows.length - 2; i++) {
const cell = table.rows[i].cells[1];
total_prestige += parseFloat(Number(cell.textContent) * prestige_per_unit[i]);
const input = table.rows[i].cells[2].children[0];
input.dataset.prestige = prestige_per_unit[i];
input.addEventListener("keyup", processHospaPrestige);
}
row.insertCell().textContent = parseInt(total_prestige * 10) / 10;
const cell = row.insertCell();
cell.textContent = 0;
cell.id = "sent_prestige";
}
function processHospaPrestige() {
const result_cell = document.getElementById("sent_prestige");
let total_prestige = 0;
const table = document.forms[0].children[0];
for (let i = 3; i < table.rows.length - 2; i++) {
const max_value = Number(table.rows[i].cells[1].textContent);
const cell = table.rows[i].cells[2];
const input = cell.children[0];
let value = input.value;
if (value <= 0) {
continue;
}
value = value > max_value ? max_value : value;
const prestige_per_unit = parseFloat(input.dataset.prestige);
total_prestige += value * prestige_per_unit;
}
result_cell.textContent = total_prestige.toFixed(1);
}
// HOSPO KONEC
// PRAVIDLA VALEK
function modifyPravidlaValky() {
const table = document.forms[0].elements[1].closest("table");
if (table == null) {
return;
}
let button;
let elements = getElementsInTheWarForm(1);
button = createButton("Reset", resetWar, elements);
table.parentElement.insertBefore(button, table.nextSibling);
button = createButton("Přepnout", toggleUtoky, elements);
table.parentElement.insertBefore(button, table.nextSibling);
button = createButton("Farmy (10)", warFarmyUtoky, elements);
table.parentElement.insertBefore(button, table.nextSibling);
button = createButton("Farmy", setWarAgainstFarms, elements);
table.parentElement.insertBefore(button, table.nextSibling);
button = createButton("Klasika", setWarClassic, elements);
table.parentElement.insertBefore(button, table.nextSibling);
}
function toggleUtoky(elements) {
for (let i = 0; i < elements.length; i++) {
elements[i].value = 1 - elements[i].value;
elements[i].checked = !elements[i].checked;
}
}
function setUtoky(elements, values) {
for (let i = 0; i < elements.length; i++) {
elements[i].value = values[i] == true ? 1 : 0;
elements[i].checked = values[i];
}
}
function setTextInputy(elements, values) {
for (let i = 0; i < elements.length; i++) {
elements[i].value = values[i];
}
}
function warFarmyUtoky(elements) {
setWarAgainstFarms(elements);
let text_input_elements = getElementsInTheWarForm(1, "text");
setTextInputy(text_input_elements, [0, 0, 10]);
}
function setWarAgainstFarms(elements) {
let values = [
false,
false,
true, // normaly jen lupy
true,
true,
true,
false,
true,
true, // taktika mimo bombeni
true,
false,
false,
false,
true,
false,
true,
true,
false,
false,
false, // sabotaz jen epky, bourani, demoralizace, sabotaz
true,
true,
true,
true,
true, // kradez rozvedkou = ok
true,
false,
false,
false, // jen konve
];
setUtoky(elements, values);
}
function setWarClassic(elements) {
let values = [
true,
false,
true, // normaly jen lupy
true,
true,
true,
false,
true,
true, // taktika mimo bombeni
true,
false,
false,
false,
true,
false,
true,
true,
false,
false,
false, // sabotaz jen epky, bourani, demoralizace, sabotaz
true,
true,
true,
true,
true, // kradez rozvedkou = ok
true,
false,
false,
false, // jen konve
];
setUtoky(elements, values);
}
function resetWar(elements) {
for (let i = 0; i < elements.length; i++) {
elements[i].value = 1;
elements[i].checked = true;
}
}
function getElementsInTheWarForm(nth, type = "checkbox") {
return document.querySelectorAll("form>div:nth-of-type(" + nth + ") input[type=" + type + "]");
}
// PRAVIDLA VALEK KONEC
// ROZVEDKA
function repeatAction(difficulties) {
const repeat_action = getSetting(REPEAT_ROZVEDKA, 0);
if (repeat_action == 0) {
// log("opky se uz nemaji opakovat => konec");
return;
}
// ziskat obtiznost z opky
let content = document.getElementById("icontent");
if (content == null) return;
let message_start = content.innerHTML.indexOf("<br><br><br>");
if (message_start == -1) return;
let message = content.innerHTML.slice(message_start + 12);
message = message.slice(0, message.indexOf("<"));
if (message.indexOf("infiltrovali") != -1) {
// log("infiltrace úspěšná => konec.");
setSetting(REPEAT_ROZVEDKA, 0);
return;
}
let difficulty_text = content.querySelector("b");
if (difficulty_text == null) {
// log("tucny text nenalezen => konec");
setSetting(REPEAT_ROZVEDKA, 0);
return;
}
difficulty_text = difficulty_text.innerText;
let obtiznost = difficulties.indexOf(difficulty_text);
if (obtiznost == -1) {
// log("Obtížnost [" + difficulty_text + "] nebyla nalezena => konec");
setSetting(REPEAT_ROZVEDKA, 0);
return;
}
const max_operation_difficulty = getSetting(MAX_OBTIZNOST_OPERACE, 0);
if (obtiznost > max_operation_difficulty) {
// log("Obtížnost je moc vysoka => konec");
setSetting(REPEAT_ROZVEDKA, 0);
return;
}
setSetting(REPEAT_ROZVEDKA, repeat_action - 1);
// log("reload page");
location.reload();
}
let technology_prices = (function () {
let prices = null;
function fetchTechnologyPrices() {
return new Promise((resolve) => {
let req = new XMLHttpRequest();
let url = "index.php?p=svetovy_trh&s=techkoupit";
req.open("GET", url);
req.onload = function () {
if (req.readyState == 4 && req.status == 200) {
let parser = new DOMParser();
let doc = parser.parseFromString(req.response, "text/html");
let warning_elements = doc.getElementsByClassName("warn");
if (warning_elements.length > 0 || !doc.forms[0]) {
// reject("Není přístup na světový trh");
return;
}
let technologie_prices = [];
let price_cells = doc.forms[0].children[0].querySelectorAll(".mactprice");
price_cells.forEach((price_cell) => {
const value = Number(price_cell.innerHTML.split("<")[0].replace(/\s/g, ""));
technologie_prices.push(value);
});
resolve(technologie_prices);
} else {
// reject("Soubor nenalezen");
}
};
req.send();
});
}
return {
async get() {
if (prices) return prices;
let technology_prices_data = getSetting(TECHNOLOGY_PRICES, null);
let time_in_millis = getCurrentTimeInMillis();
const hour_in_millis = 60 * 60 * 1000;
if (!technology_prices_data || technology_prices_data.updated_at == undefined || technology_prices_data.updated_at + hour_in_millis < time_in_millis) {
let technology_prices = await fetchTechnologyPrices();
technology_prices_data.prices = technology_prices;
setSetting(TECHNOLOGY_PRICES, {
updated_at: time_in_millis,
prices: technology_prices,
});
}
prices = technology_prices_data.prices;
return prices;
},
};
})();
async function modifyRozvedka() {
if (document.forms.tajsluzba === undefined) return;
let header_elements = document.getElementsByTagName("h1");
if (header_elements.length == 0 || header_elements[0].innerText != "Rozvědka") {
return false;
}
const difficulties = ["snadná jak facka", "jednoduchá", "středně náročná", "velice náročná", "extrémně náročná", "téměř neproveditelná"];
repeatAction(difficulties);
let submit_elements = document.getElementsByClassName("submit");
let list_elements = document.getElementsByClassName("tbl_sim");
if (submit_elements.length == 0 || list_elements.length == 0) {
return true;
}
let max_operation_element = document.querySelector("#icontent > p > strong");
let max_operation_count = parseInt(max_operation_element.innerText);
if (isNaN(max_operation_count) == true) {
max_operation_count = 15;
}
let submit_element = submit_elements[0];
let list_element = list_elements[0];
let inputs = [];
let li_index = 2;
// kolikrat opakovat opku
let li = createElement("li", { textContent: "Opakovat operaci: " });
let input = createNumberInput("repeat_operation", 5, 1, max_operation_count);
li.append(input);
inputs[0] = input;
list_element.insertBefore(li, list_element.children[li_index++]);
//
// do jake obtiznosti
li = createElement("li", { textContent: "Maximální obtížnost operace: " });
input = createElement("select");
li.append(input);
for (var i = 0; i < difficulties.length; i++) {
input.append(createElement("option", { value: i, textContent: difficulties[i] }));
}
input.options[2].selected = true;
inputs[1] = input;
list_element.insertBefore(li, list_element.children[li_index++]);
//
// brute force button
let button = createButton("Opakuj operaci");
button.params = inputs;
button.addEventListener("click", (e) => {
setSetting(REPEAT_ROZVEDKA, e.currentTarget.params[0].value - 1);
setSetting(MAX_OBTIZNOST_OPERACE, e.currentTarget.params[1].selectedIndex);
let submit_elements = document.getElementsByClassName("submit");
let list_elements = document.getElementsByClassName("tbl_sim");
if (submit_elements.length == 0 || list_elements.length == 0) {
return true;
}
let submit_element = submit_elements[0];
submit_element.click();
});
submit_element.parentElement.append(button);
const stat_elements = wrapCountrySpyStatsAroundElement(list_element);
list_element.style.height = "fit-content";
list_element.style.marginBottom = "0";
list_element.style.marginTop = "auto";
stat_elements[0].style.marginTop = "14px";
}
function wrapCountrySpyStatsAroundElement(element, country_id = getCountryId()) {
const country_stats = getCountryStats(country_id);
if (country_stats === undefined) return;
const country_stats_table = createCountryStatsSpySuccessTable(country_stats);
const operations_stats_table = createCountryStatsSpyOperationsTable(country_stats);
const combined_spy_stats_difficulty = getAllSpyStats();
const combined_country_stats_table = createCombinedSpySuccessTable(combined_spy_stats_difficulty);
let tables = [country_stats_table, combined_country_stats_table, operations_stats_table];
for (let index = 0; index < tables.length; index++) {
const table = tables[index];
table.style.margin = "unset";
table.style.height = "fit-content";
}
let container = createElement("div", { style: "position: relative" });
element.parentElement.insertBefore(container, element);
let wrapper = createElement("div", { style: "display: flex; gap: 0.5rem; justify-content: center; margin: 5px auto;" });
container.appendChild(wrapper);
wrapper.appendChild(operations_stats_table);
element.style.margin = "unset";
wrapper.appendChild(element);
const country_stats_table_wrapper = createElement();
wrapper.appendChild(country_stats_table_wrapper);
country_stats_table_wrapper.appendChild(createElement("h2", { textContent: "Statistiky země 🔄", style: "padding-bottom: 0.25rem" }));
country_stats_table_wrapper.appendChild(country_stats_table);
const combined_country_stats_table_wrapper = createElement();
wrapper.appendChild(combined_country_stats_table_wrapper);
// h2.style.textAlign = "center";
combined_country_stats_table_wrapper.appendChild(createElement("h2", { textContent: "Kombinované statistiky všech zemí 🔄", style: "padding-bottom: 0.25rem;" }));
combined_country_stats_table_wrapper.appendChild(combined_country_stats_table);
combined_country_stats_table_wrapper.style.display = "none";
country_stats_table_wrapper.addEventListener("click", () => {
country_stats_table_wrapper.style.display = "none";
combined_country_stats_table_wrapper.style.display = "block";
});
combined_country_stats_table_wrapper.addEventListener("click", () => {
combined_country_stats_table_wrapper.style.display = "none";
country_stats_table_wrapper.style.display = "block";
});
return [operations_stats_table, country_stats_table_wrapper, combined_country_stats_table_wrapper];
}
function getCountryId() {
let country_id = document.querySelector("#uLista a").href.split("id=")[1];
if (country_id == undefined) {
//obyc lista, mozna nefunguje?
const lista = document.getElementById("#uLista");
country_id = lista.children[0].textContent.split("#")[1];
}
return country_id;
}
function createNumberInput(id, default_value = 5, min = 1, max = 15, class_text = "short") {
if (default_value > max) {
default_value = max;
}
let input = createElement("input", { className: class_text, type: "number", value: default_value, min, max, id });
return input;
}
// ROZVEDKA KONEC
// valky
function modifyValky() {
const flipped = getSetting(VALKY_OBRACENE, 0);
const textContent = flipped == 1 ? "Přehodit počítání prestiže na: cílová / vyhlašující ali" : "Přehodit počítání prestiže na: vyhlašující ali / cílová";
let func = () => {
setSetting(VALKY_OBRACENE, 1 - getSetting(VALKY_OBRACENE, 0));
location.reload();
};
let button = createButton(textContent, func);
let div = createElement("div", { style: "margin: 0 auto; width: fit-content;" });
div.append(button);
let header = document.getElementsByTagName("h1")[0];
header.parentElement.insertBefore(div, header.nextElementSibling);
let tables = document.querySelectorAll(".container .vis_tbl");
// ziskat nazev ali ve valce
let offset = isGameOver() ? 1 : 0;
for (let i = 1 + offset; i < tables.length; i++) {
const table = tables[i];
for (let column_index = 4; column_index < 6; column_index++) {
const vyhlasujici_ali_prestiz = parseInt(table.rows[column_index].children[1].innerText);
const cilova_ali_prestiz = parseInt(table.rows[column_index].children[2].innerText);
let procentualni_sila_ali = flipped == 0 ? cilova_ali_prestiz / vyhlasujici_ali_prestiz : vyhlasujici_ali_prestiz / cilova_ali_prestiz;
procentualni_sila_ali = Math.round(procentualni_sila_ali * 10000) / 100;
let color = "palegreen";
if ((procentualni_sila_ali > 120 && flipped == 0) || (procentualni_sila_ali < 80 && flipped == 1)) {
color = "chartreuse";
} else if ((procentualni_sila_ali < 80 && flipped == 0) || (procentualni_sila_ali > 120 && flipped == 1)) {
color = "coral";
}
table.rows[column_index].children[0].append(createElement("span", { textContent: "(" + procentualni_sila_ali + "%)", style: "margin-left: 5px; color: " + color }));
}
}
}
// valky konec
// lista
function saveResourcePrices() {
if ((location.href.indexOf("svetovy_trh") != -1 && location.href.indexOf("tech") === -1) || location.href.indexOf("domtrh") != -1) {
getPricesFromMarket();
} else if (location.href.indexOf("index.php?p=archiv") === -1) {
let info_messages = document.getElementsByClassName("infomsg");
if (info_messages.length === 0) {
return;
}
let count = info_messages.length - 1,
food_set = false,
energy_set = false,
max_tries = 3;
while (--count >= 0 && max_tries-- > 0) {
let info_message = info_messages[count];
if (info_message.textContent.indexOf("nakoupili") === -1) {
continue;
}
const price = Number(info_message.textContent.split("po ")[1].split("$")[0]);
let variable;
if (info_message.textContent.indexOf("jídla") != -1) {
if (food_set) continue;
variable = FOOD_PRICE;
food_set = true;
} else if (info_message.textContent.indexOf("energie") != -1) {
if (energy_set) continue;
variable = ENERGY_PRICE;
energy_set = true;
}
if (variable !== undefined) {
setSetting(variable, price);
}
if (food_set && energy_set) {
return;
}
}
}
}
function getPricesFromMarket() {
const column_names = ["cena/kus", "tržní cena"];
let tables = document.getElementsByClassName("vis_tbl");
if (tables.length === 0) {
return;
}
let column_price = 0,
table;
main_loop: for (let i = 0; i < tables.length; i++) {
table = tables[i];
for (let j = 0; j < table.rows[0].cells.length; j++) {
const cell = table.rows[0].cells[j];
if (column_names.includes(cell.textContent.toLowerCase())) {
column_price = j;
break main_loop;
}
}
}
if (column_price === 0) {
return;
}
let cell = table.rows[1].cells[column_price];
let price = cell.innerText.split("\n")[0].replace("$", "");
if (price === "") {
price = cell.children[0].value;
}
setSetting(FOOD_PRICE, Number(price));
cell = table.rows[2].cells[column_price];
price = cell.innerText.split("\n")[0].replace("$", "");
if (price === "") {
price = cell.children[0].value;
}
setSetting(ENERGY_PRICE, Number(price));
}
function modifyLista() {
if (isGameOver()) {
return;
}
saveResourcePrices();
let lista = document.getElementById("uLista");
if (lista == null) {
// lista neni z nejakeho duvodu vubec na strance => skip
return;
}
if (lista.rows[0].cells[0].children[0].tagName == "IMG") {
processGoldLista();
addListaObserver();
return;
}
let tables = document.getElementsByTagName("table");
const dividers = ["$", "t", "MWh"];
// chceme vsechny tabulky, protoze na strance se muze 2x vyskytovat #uLista - stara + nova po odehrani kol
for (let i = 0; i < tables.length; i++) {
const table = tables[i];
if (table.id != "uLista") {
// neni uLista => skip
continue;
}
const row = table.rows[0];
for (let j = 1; j < 4; j++) {
const cell = row.cells[j];
processListaCell(cell, dividers[j - 1]);
}
}
}
function addListaObserver() {
let lista_elements = document.querySelectorAll("#uLista");
const lista_element = lista_elements[lista_elements.length - 1];
addObserver(lista_element, processGoldLista);
}
function addObserver(
element,
callback,
options = {
childList: true,
subtree: false,
}
) {
let observer = new MutationObserver(function (mutations) {
mutations.forEach(function (mutation) {
if (mutation.type == "childList" && mutation.addedNodes.length > 0) {
callback();
}
});
});
observer.observe(element, options);
}
function processGoldLista() {
let lista_elements = document.querySelectorAll("table#uLista");
for (let index = 0; index < lista_elements.length; index++) {
const lista = lista_elements[index];
updateGoldLista(lista);
}
}
function updateGoldLista(lista) {
let tables = lista.querySelectorAll("table");
let table = tables[0];
if (!table) {
return;
}
const turns_element = lista.querySelector("strong");
let playable_turns = 140;
if (turns_element) {
playable_turns = Number(turns_element.textContent.split("+")[0]);
}
const energy_price = getSetting(ENERGY_PRICE, 15);
const food_price = getSetting(FOOD_PRICE, 15);
const prices = [1, food_price, energy_price];
const resource_names = ["money", "food", "energy"];
const resources = new Map();
resource_names.forEach((resource_name, index) => {
let resource = {
value: Number(table.rows[index].cells[1].textContent.replace(/\s/g, "")),
per_turn: Number(table.rows[index].cells[2].textContent.replace(/\s/g, "")),
};
let stockpiled = 140;
if (resource.per_turn < 0) {
stockpiled = Math.floor(resource.value / -resource.per_turn);
}
if (stockpiled > 140 || stockpiled < 0) {
stockpiled = 140;
}
resource.stockpiles_for = stockpiled;
resource.spotreba = -resource.per_turn * prices[index];
resources.set(resource_name, resource);
});
let cell;
let resources_for_turns = getMoneyFor(resources.get("money"), resources.get("food"), resources.get("energy"));
cell = table.rows[0].cells[3];
if (cell === undefined) {
cell = table.rows[0].insertCell();
cell.style.textAlign = "right";
cell.style.paddingLeft = "20px";
} else {
for (let index = cell.children.length - 1; index >= 0; index--) {
const element = cell.children[index];
element.remove();
}
}
let props = { textContent: resources_for_turns[0], className: "plus" };
if (Number(resources_for_turns[0].split(" kol")[0]) < playable_turns) {
props.className = "minus";
}
let money_for_turns = createElement("span", props);
cell.appendChild(money_for_turns);
let separator = createElement("span", { textContent: " | " });
cell.appendChild(separator);
props = { textContent: resources_for_turns[1], className: "minus", style: "padding-right: 0;" };
if (Number(resources_for_turns[1].replaceAll(String.fromCharCode(160), "").slice(0, -1)) > 0) {
props.className = "plus";
}
let money_change_per_turn = createElement("span", props);
cell.appendChild(money_change_per_turn);
resource_names.forEach((resource_name, index) => {
if (index === 0) return;
const resource = resources.get(resource_name);
if (resource.per_turn < 0) {
const stockpiles_for = Math.round(resource.stockpiles_for * 10) / 10;
const stockpiles_text = stockpiles_for == 0 ? "" : stockpiles_for + " kol | ";
cell = table.rows[index].cells[3];
if (cell === undefined) {
cell = table.rows[index].insertCell();
cell.style.textAlign = "right";
cell.style.paddingLeft = "20px";
cell.classList.add("minus");
}
cell.textContent = `${stockpiles_text} ${formatNumber(-resource.spotreba)}$`;
}
});
}
function getMoneyFor(money, food, energy) {
let current_money = money.value,
current_spotreba = money.spotreba,
total_spotreba = current_spotreba + (energy.spotreba < 0 ? 0 : energy.spotreba) + (food.spotreba < 0 ? 0 : food.spotreba),
money_for = 0,
money_for_offset = 0;
if (total_spotreba < 0) {
return ["140+ kol", formatNumber(-total_spotreba) + "$"];
}
if (food.stockpiles_for !== energy.stockpiles_for && food.stockpiles_for !== 0) {
let is_more_of_food = food.stockpiles_for > energy.stockpiles_for;
let more_res = is_more_of_food ? food : energy;
let less_res = is_more_of_food ? energy : food;
if (less_res.stockpiles_for !== 0) {
money_for = current_money / current_spotreba;
if (money_for >= 0 && money_for < less_res.stockpiles_for) {
return [Math.floor(money_for) + " kol", formatNumber(-total_spotreba) + "$"];
}
money_for_offset = Math.min(money_for, less_res.stockpiles_for);
current_money -= current_spotreba * less_res.stockpiles_for;
}
current_spotreba += less_res.spotreba;
money_for = money_for_offset + current_money / current_spotreba;
if (money_for >= 0 && money_for < more_res.stockpiles_for) {
return [Math.floor(money_for) + " kol", formatNumber(-total_spotreba) + "$"];
}
money_for_offset = Math.min(money_for, more_res.stockpiles_for);
current_money -= current_spotreba * (more_res.stockpiles_for - less_res.stockpiles_for);
}
current_spotreba = money.spotreba + food.spotreba + energy.spotreba;
current_spotreba = money.spotreba + Math.max(food.spotreba, 0) + Math.max(energy.spotreba, 0);
money_for = money_for_offset + current_money / current_spotreba;
if (money_for > 140 || money_for < 0) {
money_for = "140+";
} else {
money_for = Math.floor(money_for);
}
return [money_for + " kol", formatNumber(-total_spotreba) + "$"];
}
function formatNumber(number) {
return number.toString().replace(/\B(?=(\d{3})+(?!\d))/g, String.fromCharCode(160));
}
function processListaCell(cell, divider) {
if (cell == null) return;
let text = cell.innerText;
if (text == "") return;
text = text.replaceAll(" ", "");
const values = text.split(divider);
const production = values[1].split(":")[1];
if (production >= 0) {
return;
}
const at_storage = values[0].split(":")[1];
const turns_left = Math.floor((parseInt(at_storage) / parseInt(production)) * -1);
addListaCellInformation(cell, turns_left);
}
function addListaCellInformation(cell, turns_left) {
let color_class = "plus";
if (turns_left < 20) {
color_class = "minus";
}
const paragraph = createElement("p", { textContent: "Vydrží: ", className: color_class });
const bold = createElement("b", { textContent: turns_left, className: color_class });
bold.innerText = turns_left;
if (color_class != null) {
bold.classList.add(color_class);
}
paragraph.append(bold);
paragraph.append(document.createTextNode("kol"));
cell.append(paragraph);
}
//
// detaily zeme
class ArmyUnit {
count;
name;
base_wage;
base_food_consumption;
base_energy_consumption;
prestige;
total_prestige;
wages_total;
expenses_total;
expenses_per_unit;
expenses_per_prestige_point;
constructor(name, count, prestige) {
this.name = name;
this.count = count;
this.prestige = prestige;
this.total_prestige = prestige * count;
}
setCount(count) {
this.count = count;
this.total_prestige = this.prestige * count;
}
}
function createArmyUnit(name, count, base_wage, prestige, base_food_consumption = 0.005, base_energy_consumption = 0) {
const unit = new ArmyUnit(name, count, prestige);
unit.base_wage = base_wage;
unit.base_food_consumption = base_food_consumption;
unit.base_energy_consumption = base_energy_consumption;
return unit;
}
function createCountryStatsSpySuccessTable(country_stats) {
const operation_difficulties = ["snadná jak facka", "jednoduchá", "středně náročná", "velice náročná", "extrémně náročná", "téměř neproveditelná"];
return createCountryStatsSpyTable(country_stats.spy_stats.success_stats, operation_difficulties);
}
function createCombinedSpySuccessTable(complete_stats) {
const operation_difficulties = ["snadná jak facka", "jednoduchá", "středně náročná", "velice náročná", "extrémně náročná", "téměř neproveditelná"];
return createCountryStatsSpyTable(complete_stats, operation_difficulties);
}
function createCountryStatsSpyOperationsTable(country_stats) {
const operation_names = archive_spy.OPERATION_SEARCH_TERMS.map((value) => value.operation);
return createCountryStatsSpyTable(country_stats.spy_stats.operation_stats, operation_names, "Název operace", false);
}
function getAllSpyStats() {
let all_country_stats = getSetting(COUNTRY_STATS, {});
let total_stats = {};
for (let country_id in all_country_stats) {
let country_stats = all_country_stats[country_id];
if (country_stats.spy_stats == null) continue;
const success_stats = country_stats.spy_stats.success_stats;
for (let key in success_stats) {
if (total_stats[key] == null) {
total_stats[key] = {
count: 0,
success: 0,
};
}
total_stats[key].count += success_stats[key].count;
total_stats[key].success += success_stats[key].success;
}
}
return total_stats;
}
function createCountryStatsSpyTable(stats, keys, information_name = "Obtížnost", add_total_row = true) {
let table = createElement("table", { className: "vis_tbl" });
const header_text = [information_name, "Operací", "Úspěšných", "%"];
const header = table.insertRow();
header_text.forEach((text) => {
const header_cell = createElement("th", { textContent: text });
header.appendChild(header_cell);
});
let total_count = 0;
let total_succeeded = 0;
let colors = [
// red to green
"#900", // 0
"#B20", // 1
"#F50", // 2
"#FA0", // 3
"#FD0", // 4
"#DF0", // 5
"#AF0", // 6
"#5F0", // 7
"#2B0", // 8
"#090", // 9
"#090", // 10
];
keys.forEach((key) => {
const current_stat = stats[key];
if (current_stat === undefined) return;
const success_chance = (current_stat.count > 0 ? Math.round((current_stat.success / current_stat.count) * 1000) / 10 : 0) + "%";
total_count += current_stat.count;
total_succeeded += current_stat.success;
const row = table.insertRow();
let cell = row.insertCell();
cell.classList.add("l");
cell.innerText = key.charAt(0).toUpperCase() + key.slice(1);
cell = row.insertCell();
cell.innerText = current_stat.count;
cell = row.insertCell();
cell.innerText = current_stat.success;
let color_id = 0;
if (current_stat.count !== 0) {
color_id = Math.floor((current_stat.success / current_stat.count) * 10);
}
cell = row.insertCell();
cell.style.color = colors[color_id];
cell.innerText = success_chance;
});
if (add_total_row) {
const row = table.insertRow();
let cell = row.insertCell();
cell.classList.add("l");
cell.innerText = "Celkem";
cell = row.insertCell();
cell.innerText = total_count;
cell = row.insertCell();
cell.innerText = total_succeeded;
let color_id = 0;
if (total_count !== 0) {
color_id = Math.floor((total_succeeded / total_count) * 10);
}
cell = row.insertCell();
cell.style.color = colors[color_id];
cell.innerText = (total_count !== 0 ? Math.round((total_succeeded / total_count) * 10000) / 100 : 0) + "%";
}
return table;
}
async function createWagesTable(eco_detail_table, war_detail_table, prestige, total_wage_reduction, resources_reduction, vlada) {
let is_robokrat = vlada == "Robokracie";
let values = getValuesFromTheCell(eco_detail_table.rows[1].cells[1]);
let people = parseInt(values[2]);
const base_consumption = 0.005 * ((1 * (100 - resources_reduction)) / 100);
let consumption_food = base_consumption,
consumption_energy = 0;
if (is_robokrat) {
consumption_food = 0;
consumption_energy = base_consumption;
}
values = getValuesFromTheCell(war_detail_table.rows[1].cells[5]);
let units = [];
units.push(createArmyUnit("Vojáci", parseInt(values[0]), 0.06, 1, consumption_food, consumption_energy));
units.push(createArmyUnit("Tanky", parseInt(values[1]), 0.42, 5, consumption_food, consumption_energy));
units.push(createArmyUnit("Stíhačky", parseInt(values[2]), 0.32, 3.5, consumption_food, consumption_energy));
units.push(createArmyUnit("Bunkry", parseInt(values[3]), 0.35, 3.5, consumption_food, consumption_energy));
units.push(createArmyUnit("Mechové", parseInt(values[4]), 0.2, 2.7, 0, base_consumption));
units.push(createArmyUnit("Agenti", parseInt(values[5]), 5.0, 15, consumption_food, consumption_energy));
addUnitsBeingSold(units);
let food_price = 10;
let energy_price = 10;
let prices = await fetchMarketPrices();
food_price = prices[0];
energy_price = prices[1];
let wages_total = calculateTotalWages(units, prestige, -total_wage_reduction);
let expenses_total = calculateTotalExpenses(units, food_price, energy_price);
let expenses_container = createExpensesTable(units, expenses_total, wages_total, food_price, energy_price, total_wage_reduction, resources_reduction);
war_detail_table.parentElement.insertBefore(expenses_container, war_detail_table.nextElementSibling);
let result = {
prestige: prestige,
units: units,
people: people,
is_robokrat: is_robokrat,
wages_total: wages_total,
expenses_total: expenses_total,
food_price: food_price,
energy_price: energy_price,
};
return result;
}
function addUnitsBeingSold(units) {
let package_elements = document.querySelectorAll(".gtrans, .gsale");
for (let index = 0; index < package_elements.length; index++) {
let cell = package_elements[index];
let row = cell.parentElement;
const name_to_find = row.cells[2].textContent.slice(0, -1);
const unit = units.find(({ name }) => name === name_to_find);
if (unit !== undefined) {
unit.count += Number(row.cells[3].textContent.replace(/\s/g, ""));
}
}
}
function addSpyRobberyColumn(eco_detail_table, war_detail_table, prestige) {
let values = getValuesFromTheCell(eco_detail_table.rows[1].cells[3]);
let money = parseInt(values[0].slice(0, -1));
let food = parseInt(values[1].slice(0, -1));
let energy = parseInt(values[2].slice(0, -1));
values = getValuesFromTheCell(war_detail_table.rows[1].cells[3]);
let spy_tech_points = parseInt(values[10]);
let safe_technology_points = spy_tech_points * 2;
let technology_to_steal = 0;
values.forEach((value) => {
let technology_points = parseInt(value);
if (technology_points > safe_technology_points) {
technology_to_steal += (technology_points - safe_technology_points) * 0.05 + safe_technology_points * 0.002;
} else {
technology_to_steal += technology_points * 0.002;
}
});
let safe_money = Math.min(spy_tech_points * 1000, money);
let unsafe_money = money - safe_money;
let money_to_steal = Math.round(Math.min(unsafe_money * 0.25 + safe_money * 0.01, prestige));
let safe_food = Math.min(spy_tech_points * 50, food);
let unsafe_food = food - safe_food;
let food_to_steal = Math.round(Math.min(unsafe_food * 0.25 + safe_food * 0.01, prestige / 5));
let safe_energy = Math.min(spy_tech_points * 50, energy);
let unsafe_energy = energy - safe_energy;
let energy_to_steal = Math.round(Math.min(unsafe_energy * 0.25 + safe_energy * 0.01, prestige / 5));
let th = createElement("th", { textContent: "Další informace", colSpan: 2 });
war_detail_table.rows[0].appendChild(th);
// krádez rozvedkou:
let td = war_detail_table.rows[1].insertCell();
td.classList.add("rname", "l");
let div = createElement("div");
td.appendChild(div);
let strong = createElement("strong", { textContent: "Krádež rozvědkou" });
div.appendChild(strong);
div = createElement("div", { textContent: "Peníze" });
td.appendChild(div);
div = createElement("div", { textContent: "Jídlo" });
td.appendChild(div);
div = createElement("div", { textContent: "Energie" });
td.appendChild(div);
div = createElement("div", { textContent: "Technologie" });
td.appendChild(div);
td.appendChild(createElement("br"));
div = createElement("div", { textContent: "Mechy %" });
td.appendChild(div);
td = war_detail_table.rows[1].insertCell();
td.classList.add("rdata", "r");
td.appendChild(createElement("br"));
div = createElement("div", { textContent: formatNumber(money_to_steal) });
td.appendChild(div);
div = createElement("div", { textContent: formatNumber(food_to_steal) });
td.appendChild(div);
div = createElement("div", { textContent: formatNumber(energy_to_steal) });
td.appendChild(div);
div = createElement("div", { textContent: formatNumber(Math.floor(technology_to_steal)) });
td.appendChild(div);
td.appendChild(createElement("br"));
const mechy_percentage_in_army_text = getMechyPercentageInArmy(war_detail_table);
div = createElement("div", { textContent: mechy_percentage_in_army_text });
td.appendChild(div);
}
function getMechyPercentageInArmy(war_detail_table) {
const values = getValuesFromTheCell(war_detail_table.rows[1].cells[5]);
let units = [];
units.push(new ArmyUnit("Mechové", parseInt(values[4]), 2.7));
units.push(new ArmyUnit("Vojáci", parseInt(values[0]), 1));
units.push(new ArmyUnit("Tanky", parseInt(values[1]), 5));
units.push(new ArmyUnit("Stíhačky", parseInt(values[2]), 3.5));
units.push(new ArmyUnit("Bunkry", parseInt(values[3]), 3.5));
let prestige_sum = units.reduce((acc, obj) => acc + obj.total_prestige, 0);
if (prestige_sum === 0) {
return "0%";
}
return ((units[0].total_prestige / prestige_sum) * 100).toFixed(1) + "%";
}
function addCountryDetailButtons(show_wages) {
let infotext = document.getElementsByClassName("infotext");
if (infotext.length === 0) {
return;
}
infotext = infotext[0];
const padding = "0.5rem";
const div = createElement("div", { style: "margin-top: 0.6rem;" });
infotext.append(div);
let text = show_wages ? "Vypnout zobrazení výdajů" : "Zapnout zobrazení výdajů";
let func = () => {
setSetting(ZOBRAZENE_ZOLDY, !show_wages);
refreshPage();
};
const show_wages_button = createButton(text, func, null, { style: `padding: ${padding}` });
div.appendChild(show_wages_button);
const current_country = location.href.endsWith("p=detaily");
const refresh_stats_button = createButton("Aktualizovat statistiky země", null, null, { style: `padding: ${padding}` });
refresh_stats_button.addEventListener("click", async function () {
await archive_spy.processSpyArchive(countryDetailGetCountryId(), current_country, false, true, refresh_stats_button);
});
div.appendChild(refresh_stats_button);
const fetch_all_stats_button = createButton("Získat kompletní statistiky země", null, null, { style: `padding: ${padding}` });
fetch_all_stats_button.classList.add("submit");
fetch_all_stats_button.style.padding = padding;
fetch_all_stats_button.innerText = "Získat kompletní statistiky země";
fetch_all_stats_button.addEventListener("click", async function () {
await archive_spy.processSpyArchive(countryDetailGetCountryId(), current_country, true, true, fetch_all_stats_button);
});
div.appendChild(fetch_all_stats_button);
const fetch_all_stats_for_ali_button = createButton("Získat statistiky všech zemí v alianci", null, null, { style: `padding: ${padding}` });
fetch_all_stats_for_ali_button.addEventListener("click", async function () {
await processSpyArchiveForAlliance(fetch_all_stats_for_ali_button);
});
div.appendChild(fetch_all_stats_for_ali_button);
const reset_button = createButton("Vynulovat statistiky všech zemí", null, null, { style: `padding: ${padding}` });
reset_button.addEventListener("click", async function () {
resetStats();
});
div.appendChild(reset_button);
}
async function processCountryDetail() {
const show_wages = getSetting(ZOBRAZENE_ZOLDY, true);
const country_id = countryDetailGetCountryId();
const country_stats = getCountryStats(country_id);
addCountryDetailButtons(show_wages);
let eco_detail_table = document.getElementById("tdetail");
let war_detail_table = document.getElementById("detaily");
if (!war_detail_table || !eco_detail_table) {
return;
}
let values = getValuesFromTheCell(eco_detail_table.rows[1].cells[1]);
let prestige = parseInt(values[0]);
addSpyRobberyColumn(eco_detail_table, war_detail_table, prestige);
if (country_stats !== undefined) {
wrapCountrySpyStatsAroundElement(eco_detail_table, country_id);
}
if (!show_wages) {
return;
}
let vlada = null,
hodnost = null,
ekonom = 0,
ali_bonus = 0,
ali_tag = null;
// ziskat hodnost
let hodnost_elements = document.getElementsByClassName("hodnost");
if (hodnost_elements.length === 0) {
return;
}
hodnost = Number(hodnost_elements[0].textContent.split("(")[1].split(")")[0]);
let table = hodnost_elements[0].closest("table");
// ziskat zrizeni
vlada = table.rows[0].cells[3].textContent;
// ziskat ali tag
let country_full_name = table.rows[0].cells[1].textContent;
if (country_full_name.includes("[")) {
ali_tag = country_full_name.split("[")[1].split("]")[0];
}
let generals_table = document.getElementById("dgen");
if (generals_table) {
for (let index = 1; index < generals_table.rows.length; index++) {
const row = generals_table.rows[index];
let cell = row.cells[1];
if (cell.textContent.includes("Ekonom")) {
ekonom = Number(row.cells[2].textContent);
break;
}
}
}
if (ali_tag !== null && ali_tag !== "Bezalianční") {
let saved_ali_data = getSetting(COUNTRY_ALI_DATA, null);
let time_in_millis = getCurrentTimeInMillis();
if (saved_ali_data == null || saved_ali_data.ali_tag != ali_tag || saved_ali_data.updated_at + COUNTRY_ALI_DATA_TIME_OFFSET_MILLIS < time_in_millis) {
// pouze provadet request, jestli informace ze settingu jsou ulozene informace z jine aliance a nebo jsou data moc stara
ali_bonus = await fetchAliFundaBonus(ali_tag);
setSetting(COUNTRY_ALI_DATA, {
ali_tag: ali_tag,
ali_bonus: ali_bonus,
updated_at: time_in_millis,
});
} else {
ali_bonus = saved_ali_data.ali_bonus;
}
}
let resources_reduction = 0;
let total_wage_reduction = ali_bonus;
let econom_effective_level = ekonom;
if (ekonom > 5) {
econom_effective_level = 4 + ((ekonom - 4) * (ekonom - 3)) / 2;
}
total_wage_reduction += econom_effective_level * 5;
if (hodnost >= 11) resources_reduction += 15;
if (hodnost >= 12) total_wage_reduction += 25;
if (vlada === "Fundamentalismus") total_wage_reduction += 25;
// ziskat prestiz - done
// ziskat pocty jednotek - done
// ziskat vladu (funda? robo?) - done
// ziskat budovy - skip
// ziskat techy (asi jen celkem?) - skip
// ziskat hodnost (>=11 = snizeni vydaju; >=12 = snizeni zoldu)
// ziskat snizeni vydaju (ze stranky vlada, popr dopocitat pres vladu - fund, gena ekonoma a h12 + funda ali bonus)
// vypocitat spotrebu armady
// vypocitat spotrebu jidla pro obyvatele (1000 lidi = 0.25 jidla mimo robo)
// vypocitat spotrebu energie
// pocitani spotreby energie pro budovy:
// mesta, obchodni zony, laborky, tovarny = x0.2
// vesnice, farmy, zabavni strediska, vojenske zakladny, kasarny, stavebni firmy = x0.1
// pocitani spotreby energie pres techy = x0.005
// pocitani spotreby energie pres mechy = x0.005
// robokrati mnohonasobne vyssi spotreba energie budovami (???)
// plazmy??
createWagesTable(eco_detail_table, war_detail_table, prestige, total_wage_reduction, resources_reduction, vlada);
}
async function fetchAliFundaBonus(ali_tag) {
return new Promise((resolve) => {
const url = "index.php?p=najit&s=najittag&tag=" + ali_tag;
let req = new XMLHttpRequest();
req.open("GET", url);
req.onload = function () {
if (req.readyState == 4 && req.status == 200) {
let parser = new DOMParser();
let doc = parser.parseFromString(req.response, "text/html");
let funda_bonus = 0;
let table = doc.getElementById("alliance-members");
let member_count = table.rows.length - 3;
const fund_text = "Fund";
for (let index = 1; index < member_count + 1; index++) {
const row = table.rows[index];
let cell = row.cells[6];
if (cell.textContent === fund_text) {
funda_bonus = Math.floor(member_count / 2) * 3;
break;
}
}
resolve(funda_bonus);
} else {
resolve(0);
}
};
req.send();
});
}
function getValuesFromTheCell(cell) {
return cell.innerHTML.replaceAll("\n\t", "").replaceAll(" ", "").split("<br>");
}
function calculateTotalWages(units, prestige, wage_increase = 0) {
const wage_modification = Math.max((1 + wage_increase / 100) * (1 + prestige / 5000000), 0.1);
let wages_total = 0;
for (const unit of units) {
unit.expenses_per_unit = unit.base_wage * wage_modification;
unit.wages_total = Math.round(unit.count * unit.expenses_per_unit * 100) / 100;
wages_total += unit.wages_total;
}
return Math.round(wages_total * 100) / 100;
}
function calculateTotalExpenses(units, food_price, energy_price) {
let expenses_total = 0;
for (const unit of units) {
unit.expenses_per_unit += unit.base_food_consumption * food_price + unit.base_energy_consumption * energy_price;
unit.expenses_per_prestige_point = unit.expenses_per_unit / unit.prestige;
unit.expenses_total = Math.round(unit.expenses_per_unit * unit.count * 100) / 100;
expenses_total += unit.expenses_total;
}
return Math.round(expenses_total * 100) / 100;
}
function fetchMarketPrices() {
return new Promise((resolve) => {
let req = new XMLHttpRequest();
let url = "index.php?p=domtrh";
req.open("GET", url);
req.onload = function () {
if (req.readyState == 4 && req.status == 200) {
let parser = new DOMParser();
let doc = parser.parseFromString(req.response, "text/html");
let prices = [];
let price_cells = doc.querySelectorAll("#icontent form .vis_tbl .mactprice");
for (let i = 0; i < 2; i++) {
const price_cell = price_cells[i];
prices.push(Number(price_cell.innerText.replaceAll(" ", "").replace("$", "")));
}
resolve(prices);
} else {
log("File not found");
}
};
req.send();
});
}
function createExpensesTable(units, expenses_total, wages_total, food_price, energy_price, total_wage_reduction, resources_reduction) {
const div = createElement();
div.append(createElement("h2", { textContent: "Výdaje za armádu" }));
const table = createElement("table", { id: "spotreba_jednotek", className: "vis_tbl", style: "table-layout: fixed; min-width: 600px; max-width: 1200px; width: 70%;" });
div.append(table);
const th_values = [
"Jednotka",
"Počet",
"Celkem",
`Žold (${(total_wage_reduction <= 0 ? "+" : "") + -total_wage_reduction}%)`,
`Suroviny (${(resources_reduction <= 0 ? "+" : "") + -resources_reduction}%)`,
"Na 1 jednotku",
"Na bod prestiže",
"Procento výdajů",
];
let row = table.insertRow();
th_values.forEach((th_value) => {
row.appendChild(createElement("th", { textContent: th_value }));
});
let total_food_cost = 0,
total_energy_cost = 0;
units.forEach((unit) => {
const food_consumed = unit.base_food_consumption * unit.count;
const food_cost = food_consumed * food_price;
total_food_cost += food_cost;
const energy_consumed = unit.base_energy_consumption * unit.count;
const energy_cost = energy_consumed * energy_price;
total_energy_cost += energy_cost;
const base_wage_per_unit = unit.wages_total / unit.count;
const base_resources_consumption = unit.base_food_consumption * food_price + unit.base_energy_consumption * energy_price;
const wage_percentage = (base_wage_per_unit / (base_wage_per_unit + base_resources_consumption)) * 100;
const others_percentage = (base_resources_consumption / (base_wage_per_unit + base_resources_consumption)) * 100;
const row = table.insertRow();
let cell = row.insertCell();
cell.textContent = unit.name;
cell.classList.add("rname", "l");
addCellWithNumericalValue(row, unit.count, 0, "");
cell = addCellWithNumericalValue(row, unit.expenses_total);
cell.title = `Žold: ${Math.round(wage_percentage * 10) / 10}% \nSuroviny: ${Math.round(others_percentage * 10) / 10}%`;
cell = addCellWithNumericalValue(row, unit.wages_total);
cell.title = `Žold: ${Math.round(wage_percentage * 10) / 10}% \nSuroviny: ${Math.round(others_percentage * 10) / 10}%`;
if (food_cost > energy_cost) {
cell = addCellWithNumericalValue(row, food_cost);
cell.title = `Celková spotřeba jídla jednotkou: ${Math.round(food_consumed * 10) / 10}\nCena jídla: ${food_price}`;
} else {
cell = addCellWithNumericalValue(row, energy_cost);
if (energy_cost > 0) {
cell.title = `Celková spotřeba energie jednotkou: ${Math.round(energy_consumed * 10) / 10}\nCena energie: ${energy_price}`;
}
}
cell = addCellWithNumericalValue(row, unit.expenses_per_unit, 3);
cell.title = `Žold: ${Math.round(base_wage_per_unit * 1000) / 1000}$ \nSuroviny: ${Math.round(base_resources_consumption * 1000) / 1000}$`;
cell = addCellWithNumericalValue(row, unit.expenses_per_prestige_point, 3);
cell.title = `Žold: ${Math.round((base_wage_per_unit / unit.prestige) * 1000) / 1000}$ \nSuroviny: ${Math.round((base_resources_consumption / unit.prestige) * 1000) / 1000}$`;
let percent = expenses_total > 0 ? unit.expenses_total / expenses_total : 0;
cell = addCellWithNumericalValue(row, percent * 100, 1, "%");
cell.title = `Žold: ${Math.round(wage_percentage * 10) / 10}% \nSuroviny: ${Math.round(others_percentage * 10) / 10}%`;
});
row = table.insertRow();
let cell = row.insertCell();
cell.textContent = "Celkem";
cell.classList.add("rname", "l");
cell.colSpan = 2;
addCellWithNumericalValue(row, expenses_total);
addCellWithNumericalValue(row, wages_total);
cell = addCellWithNumericalValue(row, total_food_cost + total_energy_cost);
cell.title = `Celkem jídlo: \t${formatNumber(total_food_cost.toFixed(1))}$\nCelkem energie: \t${formatNumber(total_energy_cost.toFixed(1))}$`;
row.insertCell().colSpan = 3;
return div;
}
function processPrestigeDetails() {
let tables = document.getElementsByClassName("vis_tbl");
let table = null;
for (let i = 0; i < tables.length; i++) {
if (tables[i].rows.length > 10) {
table = tables[i];
break;
}
}
if (table === null) return;
let percent = 0,
prestige = 0;
for (let index = 3; index < table.rows.length; index++) {
const row = table.rows[index];
if (row.cells[0].tagName === "TH") {
insertPrestigeDetailsRow(table, index, prestige, percent);
prestige = 0;
percent = 0;
index++;
continue;
}
const percent_cell = row.cells[1];
const prestige_cell = row.cells[4];
percent += Number(percent_cell.textContent.split("%")[0]);
prestige += Number(prestige_cell.textContent.replace(/\s/g, ""));
}
insertPrestigeDetailsRow(table, table.rows.length, prestige, percent);
}
function insertPrestigeDetailsRow(table, index, prestige, percent) {
const row = table.insertRow(index);
let cell = row.insertCell();
cell.classList.add("rname", "l");
cell.textContent = "Celkem";
cell = row.insertCell();
cell.classList.add("perf");
cell.textContent = percent.toFixed(1) + "%";
cell = row.insertCell();
cell.classList.add("rdata");
cell.colSpan = 2;
cell = row.insertCell();
cell.classList.add("rdata");
cell.textContent = formatNumber(prestige);
}
function modifyStatisticsPage() {
let table = document.getElementById("statszrizeni");
if (!table) {
return;
}
let rows = Array.from(table.rows);
let row = rows.shift();
row.insertBefore(createElement("th", { innerHTML: "%<br>zemí" }), row.children[2]);
let countries_count = rows.reduce((acc, row) => acc + Number(row.cells[1].textContent), 0);
rows.forEach((row) => {
const count = Number(row.cells[1].textContent);
const cell = row.insertCell(2);
const percent = (100 * count) / countries_count;
cell.textContent = formatNumber(percent.toFixed(1)) + "%";
});
let sum_row = table.insertRow();
let cell = sum_row.insertCell();
cell.classList.add("l");
cell.textContent = "Celkem";
cell = sum_row.insertCell();
cell.textContent = countries_count;
cell = sum_row.insertCell();
cell.textContent = "100.0%";
const stats = getStatsData();
if (!stats) {
return;
}
cell = sum_row.insertCell();
cell.textContent = stats.average_land;
cell = sum_row.insertCell();
cell.textContent = stats.average_prestige;
cell = sum_row.insertCell();
cell.textContent = stats.max_prestige;
cell = sum_row.insertCell();
cell.textContent = stats.average_turns_played;
}
function getStatsData() {
const table = document.getElementById("statvalues");
if (!table) {
return null;
}
let stats_data = {};
let rows = Array.from(table.rows);
const labels = ["average_prestige", "average_land", "max_prestige", "average_turns_played"];
const row_index = [1, 2, 1, 6];
const column_index = [1, 1, 3, 1];
for (let index = 0; index < row_index.length; index++) {
const row = rows[row_index[index]];
const value = Number(row.children[column_index[index]].textContent);
stats_data[labels[index]] = value;
}
return stats_data;
}
function addCellWithNumericalValue(row, value, fraction_digits = 1, after_value = "$") {
const cell = row.insertCell();
cell.textContent = formatNumber(value.toFixed(fraction_digits)) + after_value;
cell.classList.add("rdata", "r");
return cell;
}
function modifyArchive() {
const modify_archive = getSetting(MODIFY_ARCHIVE, true);
if (!modify_archive) {
return;
}
let tables = document.getElementsByClassName("vis_tbl");
let table = null;
for (let i = 0; i < tables.length; i++) {
if (tables[i].rows.length > 2 && tables[i].rows[0].cells.length == 2) {
table = tables[i];
break;
}
}
if (table === null) {
return;
}
const TOOLTIP_ROW_VALUES = ["name", "count", "prestige"];
addArchiveCss();
addTooltipCss(240, true);
let header_row = table.rows[0];
header_row.style.position = "sticky";
header_row.style.top = "0";
header_row.style.zIndex = "1";
header_row.appendChild(createElement("th", { textContent: "Prestiž na expy" }));
const colors = ["red", "lime", "mediumorchid"];
for (let index = 1; index < table.rows.length; index++) {
const row = table.rows[index];
let message = row.cells[1].textContent;
message = message.replace("Nová - Útoky", "").replace("Nová - Spojenci", "").replace("Nová - Rozvědka", "").trim();
let result = null;
if (message.indexOf("Nepřátelským mechům") !== -1) {
result = processExpTazeni(message);
} else if (message.indexOf("na nás podnikla partyzánský útok") !== -1) {
result = processExpPartyzan(message);
} else if (message.indexOf("Naši vojáci odvrátili partyzánský útok") !== -1) {
result = processExpPartyzanSuccessful(message);
} else if (message.startsWith("Pěchotě země ")) {
result = processExpVniknutiDoBunkru(message);
} else if (message.startsWith("Naši vojáci odvrátili vniknutí do bunkrů")) {
result = processExpVniknutiDoBunkruSuccessful(message);
} else if (message.startsWith("Naší pěchotě se")) {
result = processExpVniknutiDoBunkruUtok(message);
} else if (message.startsWith("Tankové brigádě ")) {
result = processExpTyl(message);
} else if (message.startsWith("Bleskový úder tankové brigády ")) {
result = processExpTyl(message, true);
} else if (message.startsWith("Letectvo nepřátelské země")) {
result = processExpNaletSuccessful(message);
} else if (message.indexOf("na naše strategická vojenská zařízení") !== -1) {
result = processExpNalet(message);
} else if (message.startsWith("Stali jsme se obětí loupežného útoku") || message.startsWith("Stali jsme se obětí částečného loupežného útoku")) {
result = processExpLoupezak(message);
} else if (message.indexOf("prolomila naši obranu a zabrala ") !== -1) {
result = processExpDobyvak(message);
} else if (message.startsWith("Naší tankové brigádě se")) {
result = processExpTylUtok(message);
} else if (message.startsWith("Bleskový úder naší tankové brigády")) {
result = processExpTylUtok(message, false);
} else if (message.indexOf("Naši elitní piloti podnikli taktický nálet") !== -1 || message.indexOf("Naši elitní piloti podnikli částečný taktický nálet") !== -1) {
result = processExpNaletUtok(message);
} else if (message.startsWith("Našim mechům se podařilo během nočního tažení")) {
result = processExpTazeniUtok(message);
} else if (message.indexOf("Při loupeživém útoku na ") !== -1) {
result = processExpNormalUtok(message);
} else if (message.indexOf("Obsadili jsme") !== -1) {
result = processExpNormalUtok(message);
} else if (message.startsWith("Partyzánský útok")) {
result = processExpPartyzanUtok(message);
} else if (message.startsWith("Naši vojáci neuspěli díky silnému odporu")) {
result = processExpPartyzanUtok(message, false);
} else if (message.startsWith("Barbarská armáda")) {
result = processExpVyhlaz(message);
} else if (message.indexOf("Při vyhlazovacím útoku") !== -1) {
result = processExpDobyvakSuccessful(message);
} else if (message.startsWith("Sebevědomá země")) {
result = processExpDobyvakSuccessful(message);
} else if (message.indexOf("bombardovaly naše budovy") !== -1) {
result = processExpBombeni(message);
} else if (message.startsWith("Naše mocné protiletecké síly")) {
result = processExpBombeniSuccessful(message);
} else if (message.indexOf("úspěšně bombardovaly civilní cíle") !== -1) {
result = processExpBombeniUtok(message);
} else if (message.startsWith("Našim jednotkám se nepodařilo obejít přesilu nepřátelských mechů")) {
result = processExpTazeniUtok(message);
} else if (message.startsWith("Země") && message.indexOf("nebyla poražena. Naše ztráty byly ")) {
result = processExpNormalUtok(message);
} else if (message.startsWith("Byli jsme povoláni zemí")) {
result = processExpSpojka(message);
} else if (message.startsWith("Rozvědka")) {
// process opku
if (message.indexOf("Naši agenti ukradli celkem") !== -1) {
processTechnologyToMoney(message, row);
}
}
const cell = row.insertCell();
if (result === null) continue;
cell.style.textAlign = "center";
cell.style.userSelect = "none";
if (result.exp_ratio !== null) {
cell.textContent = result.exp_ratio;
cell.style.color = colors[result.type];
const tooltip = createElement();
cell.appendChild(tooltip);
wrapInTooltip(tooltip);
const header = addRowToTooltip(tooltip, { name: "Jednotka", count: "Počet", prestige: "Prestiž" });
header.classList.add("header");
for (let index = 0; index < result.units_lost.length; index++) {
const unit = result.units_lost[index];
addRowToTooltip(tooltip, unit);
}
tooltip.appendChild(createElement("p", { className: "divider" }));
const additional_info = [
{
name: "Celkem:",
count: "",
prestige: result.total_prestige,
},
{
name: "Zkušeností:",
count: "",
prestige: result.experience,
},
];
for (let index = 0; index < additional_info.length; index++) {
const info = additional_info[index];
addRowToTooltip(tooltip, info);
}
}
}
function addRowToTooltip(tooltip, information) {
const p = createElement("p", { className: "row" });
tooltip.appendChild(p);
for (let i = 0; i < TOOLTIP_ROW_VALUES.length; i++) {
const unit_value = TOOLTIP_ROW_VALUES[i];
const span = createElement("span", { textContent: information[unit_value] });
p.appendChild(span);
}
return p;
}
}
async function processTechnologyToMoney(message, row) {
message = message.split("Rozpis: ")[1];
let numbers = message.match(/(\d)+/g);
let words = message.replace(/[0-9]/g, "").split(".")[0].split(", ");
let tech_prices = await technology_prices.get();
let total_money = 0,
title = "";
for (let i = 0; i < words.length; i++) {
let count = Number(numbers[i]);
if (count === 0) {
continue;
}
let word = words[i];
let price = tech_prices[i];
total_money += price * count;
title += `${word}: ${formatNumber(count)}x ${formatNumber(price)}$ = ${formatNumber(Math.floor(price * count))}$\n`;
}
let p = createElement("p", { textContent: "Hodnota celkem: ", title });
row.cells[1].appendChild(p);
p.appendChild(createElement("span", { textContent: formatNumber(Math.floor(total_money)) + "$", style: "font-weight: bold; color: lime;" }));
}
function processExpTazeni(message) {
if (message.indexOf("nepodařilo obejít přesilu našich mechů") !== -1) {
message = message.split("nepodařilo obejít přesilu našich mechů")[1];
let numbers = message.match(/(\d)+/g);
let units = [UNITS.get("mechy", Number(numbers[1]))];
let experience = Number(numbers.pop());
return processExp(units, experience);
}
message = message.split("se podařilo během nočního tažení naší zemí zlikvidovat")[1];
let numbers = message.match(/(\d)+/g);
let units = [
UNITS.get("vojaci", Number(numbers.shift())),
UNITS.get("tanky", Number(numbers.shift())),
UNITS.get("stihacky", Number(numbers.shift())),
UNITS.get("budovy", Number(numbers.shift())),
UNITS.get("mechy", Number(numbers[1])),
];
let experience = Number(numbers.pop());
return processExp(units, experience);
}
function processExpTazeniUtok(message) {
message = message.split("Zničeno bylo")[1];
let numbers = message.match(/(\d)+/g);
let units = [UNITS.get("mechy", Number(numbers.shift()))];
let experience = Number(numbers.pop());
return processExp(units, experience, 1);
}
function processExpPartyzan(message) {
message = message.split("%, zabito bylo ")[1];
let numbers = message.match(/(\d)+/g);
let units = [UNITS.get("agenti", Number(numbers.shift())), UNITS.get("energie", Number(numbers.shift())), UNITS.get("vojaci", Number(numbers[1]))];
let experience = Number(numbers.pop());
return processExp(units, experience);
}
function processExpPartyzanSuccessful(message) {
message = message.split("Zahynulo při tom ")[1];
let numbers = message.match(/(\d)+/g);
let units = [UNITS.get("vojaci", Number(numbers.shift()))];
let experience = Number(numbers.pop());
return processExp(units, experience);
}
function processExpPartyzanUtok(message, success = true) {
let separator = "Při bojích zahynulo";
if (!success) separator = "Zahynulo při tom";
message = message.split(separator)[1];
let numbers = message.match(/(\d)+/g);
let units = [UNITS.get("vojaci", Number(numbers.shift()))];
let experience = Number(numbers.pop());
return processExp(units, experience, 1);
}
function processExpVniknutiDoBunkru(message) {
message = message.split("se podařilo vniknout do ")[1];
let numbers = message.match(/(\d)+/g);
let units = [UNITS.get("bunkry", Number(numbers.shift()))];
let experience = Number(numbers.pop());
return processExp(units, experience);
}
function processExpVniknutiDoBunkruSuccessful(message) {
message = message.split("Zahynulo při tom ")[1];
let numbers = message.match(/(\d)+/g);
let units = [UNITS.get("vojaci", Number(numbers.shift()))];
let experience = Number(numbers.pop());
return processExp(units, experience);
}
function processExpVniknutiDoBunkruUtok(message) {
message = message.split("Při tom zahynulo")[1];
let numbers = message.match(/(\d)+/g);
let units = [UNITS.get("vojaci", Number(numbers.shift()))];
let experience = Number(numbers.pop());
return processExp(units, experience, 1);
}
function processExpTyl(message, success = false) {
let separator = "My jsme při tom přišli o";
if (success) separator = "Ztratili jsme při tom";
message = message.split(separator)[1];
let numbers = message.match(/(\d)+/g);
let units = [UNITS.get("tanky", Number(numbers.shift()))];
let experience = Number(numbers.pop());
return processExp(units, experience);
}
function processExpTylUtok(message, success = true) {
let separator = "My jsme při tom přišli o ";
if (!success) {
separator = "Ztratili jsme při tom ";
}
message = message.split(separator)[1];
let numbers = message.match(/(\d)+/g);
let units = [UNITS.get("tanky", Number(numbers.shift()))];
let experience = Number(numbers.pop());
return processExp(units, experience, 1);
}
function processExpNalet(message) {
message = message.split("Nálety nám zničily ")[1];
let numbers = message.match(/(\d)+/g);
let units = [UNITS.get("budovy_na_ruiny", Number(numbers.shift())), UNITS.get("stihacky", Number(numbers.shift())), UNITS.get("bunkry", Number(numbers.shift()))];
let experience = Number(numbers.pop());
return processExp(units, experience);
}
function processExpNaletSuccessful(message) {
message = message.split("Při obraně jsme ztratili ")[1];
let numbers = message.match(/(\d)+/g);
let units = [UNITS.get("stihacky", Number(numbers.shift())), UNITS.get("bunkry", Number(numbers.shift()))];
let experience = Number(numbers.pop());
return processExp(units, experience);
}
function processExpBombeni(message) {
message = message.split("Pod troskami")[1];
let numbers = message.match(/(\d)+/g);
let units = [
UNITS.get("budovy", Number(numbers.shift())),
UNITS.get("ruiny", Number(numbers.shift())),
UNITS.get("stihacky", Number(numbers.shift())),
UNITS.get("bunkry", Number(numbers.shift())),
];
let experience = Number(numbers.pop());
return processExp(units, experience);
}
function processExpBombeniSuccessful(message) {
message = message.split(". Bylo zničeno ")[1];
let numbers = message.match(/(\d)+/g);
numbers.shift(); // nepratelske stihacky
let units = [UNITS.get("stihacky", Number(numbers.shift())), UNITS.get("bunkry", Number(numbers.shift()))];
let experience = Number(numbers.pop());
return processExp(units, experience);
}
function processExpBombeniUtok(message) {
message = message.split("Bylo zničeno")[1];
let numbers = message.match(/(\d)+/g);
let units = [UNITS.get("stihacky", Number(numbers.shift()))];
let experience = Number(numbers.pop());
return processExp(units, experience, 1);
}
function processExpNaletUtok(message) {
message = message.split("vojenských základen nepřítele")[1];
let numbers = message.match(/(\d)+/g);
let units = [UNITS.get("stihacky", Number(numbers.shift()))];
let experience = Number(numbers.pop());
return processExp(units, experience, 1);
}
function processExpLoupezak(message) {
message = message.split("Bylo nám násilně zabráno ")[1];
return processNormal(message);
}
function processExpNormalUtok(message) {
message = message.split("Naše ztráty byly ")[1];
return processNormalUtok(message);
}
function processExpSpojka(message) {
message = message.split("V bojích bylo ztraceno ")[1];
return processNormalUtok(message, true);
}
function processExpDobyvak(message) {
message = message.split("prolomila naši obranu a zabrala ")[1];
return processNormal(message);
}
function processExpDobyvakSuccessful(message) {
message = message.split("Naše ztráty byly")[1];
let numbers = message.match(/(\d)+/g);
const experience = Number(numbers.pop());
let units = [
UNITS.get("vojaci", Number(numbers.shift())),
UNITS.get("tanky", Number(numbers.shift())),
UNITS.get("bunkry", Number(numbers.shift())),
UNITS.get("mechy", Number(numbers.shift())),
];
return processExp(units, experience);
}
function processExpVyhlaz(message) {
message = message.split(" zničila ")[1];
let numbers = message.match(/(\d)+/g);
const experience = Number(numbers.pop());
let units = [
UNITS.get("budovy", Number(numbers[0])),
UNITS.get("ruiny", Number(numbers[1])),
UNITS.get("penize", Number(numbers[3])),
UNITS.get("jidlo", Number(numbers[4])),
UNITS.get("energie", Number(numbers[5])),
UNITS.get("technologie", Number(numbers[6])),
UNITS.get("vojaci", Number(numbers[7])),
UNITS.get("tanky", Number(numbers[8])),
UNITS.get("bunkry", Number(numbers[9])),
UNITS.get("mechy", Number(numbers[10])),
];
return processExp(units, experience);
}
function processNormal(message) {
let numbers = message.match(/(\d)+/g);
const experience = Number(numbers.pop());
let units = [
UNITS.get("uzemi", Number(numbers[0])),
UNITS.get("budovy", Number(numbers[2]) * 2),
UNITS.get("penize", Number(numbers[3])),
UNITS.get("jidlo", Number(numbers[4])),
UNITS.get("energie", Number(numbers[5])),
UNITS.get("technologie", Number(numbers[6])),
UNITS.get("vojaci", Number(numbers[7])),
UNITS.get("tanky", Number(numbers[8])),
UNITS.get("bunkry", Number(numbers[9])),
UNITS.get("mechy", Number(numbers[10])),
];
return processExp(units, experience);
}
function processNormalUtok(message, is_spojka = false) {
let numbers = message.match(/(\d)+/g);
const experience = Number(numbers.pop());
let units = [
UNITS.get("vojaci", Number(numbers.shift())),
UNITS.get("tanky", Number(numbers.shift())),
UNITS.get("bunkry", Number(numbers.shift())),
UNITS.get("mechy", Number(numbers.shift())),
];
let type = is_spojka ? 2 : 1;
return processExp(units, experience, type);
}
/**
*
* @param {array} units
* @param {int} experience
* @param {int} type 0 = defense, 1 = attack, 2 = ally
* @returns {object}
*/
function processExp(units, experience, type = 0) {
let total_prestige = 0,
units_lost = [];
for (let index = 0; index < units.length; index++) {
const unit = units[index];
const prestige = unit.count * unit.prestige;
total_prestige += prestige;
units_lost.push({ name: unit.name + ":", count: formatNumber(unit.count), prestige: formatNumber(prestige.toFixed(1)) });
}
let percentage = total_prestige == 0 ? 999 : (experience / total_prestige) * 100;
experience = formatNumber(experience.toFixed(1));
total_prestige = formatNumber(total_prestige.toFixed(1));
return { exp_ratio: formatNumber(percentage.toFixed(2)) + "%", units_lost, total_prestige, type, experience };
}
let archive_spy = (function () {
const URL = "index.php?p=archiv&typ=3&limit=";
const ALLY_URL = "index.php?p=archiv&typ=3&tag=1&id=$country_id$&limit=";
const MESSAGES_PER_PAGE = 30;
const OPERATION_SEARCH_TERMS = [
// infiltrace
{
term: /infiltrova(li|t) vládu/,
operation: "Infiltrovat vládu",
},
{
term: /infiltrova(li|t) rozvědku/,
operation: "Infiltrovat rozvědku",
},
{
term: /infiltrova(li|t) generální štáb/,
operation: "Infiltrovat generální štáb",
},
{
term: /infiltrova(li|t) vědecká centra/,
operation: "Infiltrovat vědecká centra",
},
// sabotazni
{
term: /naboura(li|t) ovládání mechů/,
operation: "Nabourat ovládání mechů",
},
{
term: /zavirova(li|t) počítače/,
operation: "Počítačový virus",
},
{
term: /sabotova(li|t) letiště/,
operation: "Sabotovat letiště",
},
{
term: /rozšíři(li|t) epidemii/,
operation: "Rozšířit epidemii",
},
{
term: /demoralizova(li|t) obyvatele/,
operation: "Demoralizovat obyvatele",
},
{
term: /zniči.*raket/,
operation: "Zničit rakety",
},
// loupezive
{
term: /vykr(a|á)(dli|st) sklady/,
operation: "Vykrást sklady",
},
{
term: /vykr(a|á)(dli|st) centrální banku/,
operation: "Vykrást centrální banku",
},
{
term: /napích(li|nout) ropovod/,
operation: "Napíchnout ropovod",
},
{
term: /ukr(a|á)(st|dli) (celkem )?(\d)*( )?technologi(í|e)/,
operation: "Ukrást technologie",
},
{
term: /prod(a|á)(vá|t) drogy/,
operation: "Prodat drogy",
},
// TODO zbytek sabotaznich:
{
term: " ",
operation: "Jiné",
},
];
let country_id;
let current_page;
let last_message_time = null;
let fetch_until_time = null;
let messages;
let spy_success_stats;
let spy_operation_stats;
let button = null;
function initValues(_country_id) {
initSuccessStats();
initMessagesStats();
country_id = _country_id;
current_page = 0;
last_message_time = null;
fetch_until_time = null;
current_page = 0;
spy_operation_stats = {};
}
function initSuccessStats() {
let value = {
count: 0,
success: 0,
};
spy_success_stats = {
"snadná jak facka": value,
jednoduchá: value,
"středně náročná": value,
"velice náročná": value,
"extrémně náročná": value,
"téměř neproveditelná": value,
};
}
function initMessagesStats() {
messages = {
success: [],
failed: [],
};
}
function save() {
let stats = getSetting(COUNTRY_STATS, {});
stats[country_id] = {
spy_stats: {
success_stats: spy_success_stats,
operation_stats: spy_operation_stats,
last_message: last_message_time,
// spy_messages: archive_spy.messages,
},
};
setSetting(COUNTRY_STATS, stats);
}
async function processSpyArchive(is_ally, force_all = false) {
const country_stats = getCountryStats(country_id);
if (country_stats !== undefined && !force_all) {
let spy_stats = country_stats.spy_stats;
spy_success_stats = spy_stats.success_stats;
spy_operation_stats = spy_stats.operation_stats;
let time = spy_stats.last_message;
fetch_until_time = time ? archiveGetTimeInMillis(time) : null;
}
let message_count = 0;
let url = URL;
if (is_ally) {
url = ALLY_URL.replace("$country_id$", country_id);
}
do {
message_count = await fetchPage(url + current_page++ * MESSAGES_PER_PAGE, processArchivePage);
if (button !== null) {
button.textContent = `Probíhá... ${current_page}`;
}
} while (message_count === MESSAGES_PER_PAGE);
}
function processArchivePage(doc) {
let tables = doc.getElementsByClassName("vis_tbl");
let table = null;
for (let i = 0; i < tables.length; i++) {
if (tables[i].rows.length > 2 && tables[i].rows[0].cells.length >= 2) {
table = tables[i];
break;
}
}
if (table === null) {
return;
}
let rows = table.rows;
if (last_message_time === null) {
last_message_time = rows[1].cells[0].textContent;
}
for (let i = 1; i < rows.length; i++) {
let time = rows[i].cells[0].textContent;
let time_in_millis = archiveGetTimeInMillis(time);
if (fetch_until_time && fetch_until_time === time_in_millis) {
return;
}
let original_message = rows[i].cells[1].textContent;
if (original_message.indexOf("Operace byla ") == -1) {
continue;
}
let difficulty = original_message.split("Operace byla ")[1].split(".")[0];
let difficulty_results = spy_success_stats[difficulty];
let count = 0;
let success = 0;
if (difficulty_results !== undefined) {
count = difficulty_results.count;
success = difficulty_results.success;
}
// pushing message to correct messages
const failed_operation = original_message.indexOf("nepodařilo") !== -1;
if (failed_operation) {
messages["failed"].push(original_message);
} else {
success++;
messages["success"].push(original_message);
}
for (let index = 0; index < OPERATION_SEARCH_TERMS.length; index++) {
const search_term = OPERATION_SEARCH_TERMS[index];
if (original_message.match(search_term.term) !== null) {
let current = spy_operation_stats[search_term.operation];
if (current === undefined) {
current = {
count: 0,
success: 0,
};
spy_operation_stats[search_term.operation] = current;
}
current.count++;
if (!failed_operation) {
current.success++;
}
break;
}
}
spy_success_stats[difficulty] = {
count: ++count,
success: success,
};
}
return table.rows.length - 1;
}
return {
OPERATION_SEARCH_TERMS,
messages() {
return messages;
},
spy_success_stats() {
return spy_success_stats;
},
last_message_time() {
return last_message_time;
},
async processSpyArchive(country_id, is_ally = false, force_all = false, reload_page = false, _button = null) {
initValues(country_id);
button = _button;
if (button !== null) {
button.textContent = "Probíhá...";
}
await processSpyArchive(is_ally, force_all);
save();
if (reload_page) {
refreshPage();
}
},
// spy_operation_stats: spy_operation_stats
};
})();
const modify_advancements = (function () {
const MAX_REDUCTIONS = {
T: {
reduction: 80,
countries: 80,
},
K: {
reduction: 60,
countries: 300,
},
};
const ADVANCEMENT_EXCEPTIONS = {
"Fúzní elektrárny": {
base_price: 400000,
minimum_price: 160000,
not_affected_by_difficulty: true,
},
"Nejvyšší budova světa": {
base_price: 4000000,
minimum_price: 4000000,
per_country_price: 50000,
},
"Vojenská akademie": {
base_price: 1000,
minimum_price: 1000,
per_country_price: 2,
cap_price: 4000,
},
};
function process() {
const table = getAdvancementTable();
if (table === null) {
return;
}
const show_base_price = getSetting(ADV_SHOW_BASE_PRICE, true);
const show_min_price = getSetting(ADV_SHOW_MIN_PRICE, true);
const show_current_price = getSetting(ADV_SHOW_CURRENT_PRICE, true);
const difficulty = getCurrentTechnologicalDifficulty();
if (show_base_price) {
addTooltipCss(300);
}
for (let index = 1; index < table.rows.length; index++) {
const row = table.rows[index];
const type = getAdvancementType(row);
const advancement_name = getAdvancementName(row);
const current_price_element = getCurrentPriceElement(row);
const current_price = getCurrentPrice(current_price_element);
const times_researched = getTimesResearched(row);
formatValueOnElement(current_price_element);
const price_reduction = getPriceReduction(row, type);
let elements = [];
if (show_base_price) {
elements.push(addBasePrice(current_price_element, current_price, price_reduction, difficulty, advancement_name));
}
if (type == "S") {
continue;
}
if (show_min_price) {
elements.push(addMinPrice(current_price_element, current_price, price_reduction, difficulty, type, advancement_name, times_researched));
}
if (show_current_price) {
addPriceReduction(current_price_element, price_reduction);
}
mergeTooltips(elements);
}
}
function mergeTooltips(elements) {
if (elements.length < 2) {
return;
}
for (let index = 0; index < elements.length; index++) {
const element = elements[index];
if (!element.classList.contains("tooltiptext")) return;
}
let content = "";
for (let index = 1; index < elements.length; index++) {
const element = elements[index];
content += "<p>" + element.innerHTML + "</p>";
element.remove();
}
const tooltip = elements[0];
tooltip.innerHTML += content;
}
function getPriceReduction(row, type) {
if (type == "S" || type == "K-") {
return 100;
}
const country_count = Number(row.cells[3].textContent);
return getPrice(type, country_count);
}
function getPrice(type, countries) {
if (type == "S" || type == "K-") {
return 100;
}
const reduction = MAX_REDUCTIONS[type].reduction;
const countries_max = MAX_REDUCTIONS[type].countries;
const base = 100 - reduction;
const discounted = reduction * (1 - Math.min(countries / countries_max, 1));
return base + discounted;
}
function getMinPrice(type) {
if (type == "S" || type == "K-") {
return 100;
}
return getPrice(type, MAX_REDUCTIONS[type].countries);
}
function getAdvancementType(row) {
let value = row.cells[0].textContent.match(/\([TSK-]*\)/g)[0];
return value.slice(1).slice(0, -1);
}
function getAdvancementName(row) {
const cell = row.cells[0];
const child_nodes = cell.childNodes;
return child_nodes[child_nodes.length - 1].textContent.split(" (")[0].trim();
}
function addPriceReduction(element, price_reduction) {
const wrapper = createElement("i", { textContent: "Aktuální cena pokroku je: " + Math.round(price_reduction * 10) / 10 + "%" });
const parent = element.parentElement.parentElement;
const sibling = element.parentElement.nextSibling;
if (sibling) {
parent.insertBefore(wrapper, sibling);
} else {
parent.appendChild(wrapper);
}
return wrapper;
}
function addMinPrice(current_price_element, current_price, price_reduction, difficulty, type, advancement_name, times_researched) {
let min_price = 0;
if (ADVANCEMENT_EXCEPTIONS[advancement_name] !== undefined) {
let exception = ADVANCEMENT_EXCEPTIONS[advancement_name];
min_price = exception.minimum_price;
if (exception.per_country_price) {
let extra_price = exception.per_country_price * times_researched;
if (exception.cap_price && exception.cap_price <= min_price + extra_price) {
min_price = exception.cap_price;
} else {
min_price += extra_price;
}
}
if (!exception.not_affected_by_difficulty) {
min_price = min_price * difficulty;
}
} else {
min_price = (current_price / price_reduction) * getMinPrice(type);
}
const element = addPriceValue(current_price_element, min_price, "Minimální cena");
if (getSetting(ADV_SHOW_MIN_PRICE_IN_TOOLTIP, false)) {
element.classList.add("center");
wrapInTooltip(element);
}
return element;
}
function addBasePrice(current_price_element, current_price, current_reduction, difficulty, advancement_name) {
let base_price = 0;
if (ADVANCEMENT_EXCEPTIONS[advancement_name] !== undefined) {
base_price = ADVANCEMENT_EXCEPTIONS[advancement_name].base_price;
} else {
base_price = getBasePrice(current_price, current_reduction, difficulty);
}
const element = addPriceValue(current_price_element, base_price, "Základní cena");
if (getSetting(ADV_SHOW_BASE_PRICE_IN_TOOLTIP, true)) {
element.classList.add("center");
wrapInTooltip(element);
}
return element;
}
function getCurrentPrice(current_price_element) {
return Number(current_price_element.textContent);
}
function getCurrentPriceElement(row) {
return row.getElementsByTagName("em")[0];
}
function getTimesResearched(row) {
return Number(row.cells[3].textContent);
}
function formatValueOnElement(current_price_element) {
const current_price = Number(current_price_element.textContent);
current_price_element.textContent = formatNumber(current_price);
}
function addPriceValue(element, value, label = "") {
const wrapper = createElement("p", { className: "imprp" });
const i = createElement("i");
wrapper.appendChild(i);
const em = createElement("em", { textContent: formatNumber(value.toFixed(0)) });
i.appendChild(em);
i.innerHTML = label + ": " + i.innerHTML + " " + element.nextSibling.textContent;
const parent = element.parentElement.parentElement;
const sibling = element.parentElement.nextSibling;
if (sibling) {
parent.insertBefore(wrapper, sibling);
} else {
parent.appendChild(wrapper);
}
return wrapper;
}
function getBasePrice(current_price, current_reduction, difficulty) {
return ((current_price / current_reduction) * 100) / difficulty;
}
function getAdvancementTable() {
let tables = document.getElementsByClassName("vis_tbl");
let table = null;
for (let i = 0; i < tables.length; i++) {
if (tables[i].rows[0].cells[0].textContent == "Pokrok") {
table = tables[i];
break;
}
}
return table;
}
function getCurrentTechnologicalDifficulty() {
let elements = document.querySelectorAll(".infotext strong");
let difficulty = null;
for (let i = 0; i < elements.length; i++) {
if (elements[i].textContent.indexOf("Náročnost pokroků je") !== -1) {
const parts = elements[i].textContent.split(" ");
difficulty = Number(parts[parts.length - 1]);
break;
}
}
return difficulty;
}
return {
process() {
if (getSetting(MODIFY_ADVANCEMENTS, true)) {
process();
}
},
};
})();
const modify_valka = (function () {
const pripravenost_za_kolo = 3;
const vyssi_dopriprava_nad_pripravenosti = 10;
const WARNING_MESSAGE = "!!! Útokem se dopouštíte porušení pravidel VEDENÍ ALIANCE !!!";
const STYLES = "input[type=submit][disabled] { background: red; border-color: black; }";
let last_production_table = null;
let warning_message_element = null;
function process() {
if (getSetting(STRIKE_SHOW_EXP, true)) {
showExp();
}
if (getSetting(STRIKE_WARNING_DISABLES_BUTTON, true)) {
if (hasWarningMessage()) {
addStrikeCss();
disableButton();
addForceAttackButton();
}
}
}
function addStrikeCss() {
addCss(STYLES);
}
function disableButton() {
const button = getStrikeSubmitButton();
button.disabled = true;
}
function addForceAttackButton() {
const warning_message = getWarningMessage();
if (warning_message === null) {
return;
}
const parent = warning_message.parentElement;
parent.style.textAlign = "center";
const button = createButton("Rozumím a chci pokračovat", () => {
getStrikeSubmitButton().disabled = false;
});
parent.appendChild(button);
}
function getStrikeSubmitButton() {
return document.forms[0].querySelector("input[type=submit]");
}
function getWarningMessage() {
if (warning_message_element !== null) return warning_message_element;
let warning_messages = document.getElementsByClassName("warn");
if (warning_messages.length == 0) return null;
for (let index = 0; index < warning_messages.length; index++) {
const element = warning_messages[index];
if (element.textContent == WARNING_MESSAGE) {
warning_message_element = element;
break;
}
}
return warning_message_element;
}
function hasWarningMessage() {
return getWarningMessage() !== null;
}
function showExp() {
const strong_elements = document.getElementsByTagName("strong");
let experience_element = null;
for (let i = 0; i < strong_elements.length; i++) {
if (strong_elements[i].nextSibling && strong_elements[i].nextSibling.textContent == " zkušeností.") {
experience_element = strong_elements[i];
break;
}
}
if (experience_element === null) {
return;
}
const experience = Number(experience_element.textContent);
const turns_played = getPlayedTurns();
const pripravenost = getCombatReadiness();
const turns_to_full = getTurnsToBeCombatReady(pripravenost, true);
const turns_to_less_than_3 = getTurnsToBeCombatReady(pripravenost, false);
const experience_to_full = getExperiencePerTurn(experience, turns_played + turns_to_full);
let break_element = createElement("br");
experience_element.parentElement.insertBefore(break_element, experience_element.nextSibling.nextSibling);
let element = addResults("Zkušeností / kolo: ", experience_to_full, break_element);
if (turns_to_full != turns_to_less_than_3) {
const experience_to_less_than_3 = getExperiencePerTurn(experience, turns_played + turns_to_less_than_3);
addResults("Zkušeností za kolo (<3%): ", experience_to_less_than_3, element);
}
}
function getPlayedTurns() {
let tables = document.getElementsByClassName("vis_tbl");
let turns = 0;
for (let index = 0; index < tables.length; index++) {
const table = tables[index];
if (table.rows[0].cells[0].textContent == "Peníze") {
last_production_table = table;
turns++;
}
}
return turns;
}
function getCombatReadiness() {
if (!last_production_table) {
log("Není uložená poslední tabulka.");
return 100;
}
return 100 - Number(last_production_table.rows[2].cells[5].textContent.slice(0, -1));
}
function getTurnsToBeCombatReady(pripravenost, doFull = true) {
let turns = 0;
if (pripravenost > 10) {
const per_turn = pripravenost_za_kolo + 1;
turns = Math.ceil((pripravenost - vyssi_dopriprava_nad_pripravenosti) / per_turn);
pripravenost -= turns * per_turn;
}
if (doFull) {
turns += Math.ceil(pripravenost / pripravenost_za_kolo);
} else {
turns += Math.floor(pripravenost / pripravenost_za_kolo);
}
return turns;
}
function getExperiencePerTurn(experience, turns) {
return (experience / turns).toFixed(0);
}
function addResults(label, experience, insertBeforeElement) {
let p = createElement("p", { textContent: label, style: "margin-left: 1ch;" });
p.appendChild(createElement("strong", { textContent: experience }));
let parent = insertBeforeElement.parentElement;
parent.insertBefore(p, insertBeforeElement.nextSibling);
return p;
}
return {
process() {
process();
},
};
})();
function fetchPage(url, callback) {
return new Promise((resolve) => {
let req = new XMLHttpRequest();
req.open("GET", url);
req.onload = function () {
if (req.readyState == 4 && req.status == 200) {
let parser = new DOMParser();
let doc = parser.parseFromString(req.response, "text/html");
resolve(callback(doc));
}
};
req.send();
});
}
async function processSpyArchiveForAlliance(button) {
button.textContent = "Probíhá...";
let country_ids = await fetchCountryIds();
button.textContent = `Probíhá... 0 / ${country_ids.length}`;
for (let index = 0; index < country_ids.length; index++) {
const country_id = country_ids[index];
await archive_spy.processSpyArchive(country_id, true, false, false);
updateProgressBackground(button, index, country_ids.length);
}
refreshPage();
}
function updateProgressBackground(button, completed, total) {
button.textContent = "Probíhá ... " + (completed + 1) + " / " + total;
const progress = Math.floor(((completed + 1) / total) * 100);
let background = "chocolate";
if (progress < 100) {
background = `linear-gradient(to right, chocolate ${progress}%, #363636 ${progress}%)`;
}
button.style.background = background;
}
function fetchCountryIds() {
const URL = "index.php?p=detaily&s=detaily&adetaily=true";
return fetchPage(URL, getCountryIdsCallback);
}
function getCountryIdsCallback(doc) {
let country_ids = [];
let table = doc.forms[0].children[0];
for (let i = 1; i < table.rows.length; i++) {
const row = table.rows[i];
const img = row.querySelector("img");
if (img === null) {
continue;
}
const country_id = Number(img.parentElement.href.split("to_id=")[1]);
country_ids.push(country_id);
}
return country_ids;
}
function getCountryStats(country_id) {
const all_country_stats = getSetting(COUNTRY_STATS, {});
return all_country_stats[country_id];
}
function archiveGetTimeInMillis(time) {
let date = archiveProcessTime(time);
return date.getTime();
}
function archiveProcessTime(time) {
let parts = time.split(" ");
let date_parts = parts[0].split(".");
let date = new Date(date_parts[2], date_parts[1] - 1, date_parts[0]);
let hour_parts = parts[1].split(":");
date.setHours(hour_parts[0], hour_parts[1], hour_parts[2]);
return date;
}
function countryDetailGetCountryId() {
let mail_to = document.querySelector(".vis_tbl td:nth-child(2) a");
return Number(mail_to.href.split("id=")[1]);
}
const ali_detail = (function () {
const separator = ",";
const allowed_cards = ["G", "F", "S", "Q", "P", "Z", "R"];
const rocket_cards = ["L", "B", "N"];
const cards_to_replace = {
"?": "Q",
};
const REGIMES = {
Feud: "e",
Demo: "d",
Rep: "r",
Tech: "t",
Fund: "f",
Anar: "a",
Kom: "k",
Dikt: "i",
Utop: "u",
Robo: "b",
};
let cards, regimes, rockets;
// to clear values
function initializeMaps() {
cards = new Map();
regimes = new Map();
rockets = new Map();
}
function transformMapToString(map) {
let result = Array.from(map, ([key, value]) => ({ key, value }));
result = result.sort((a, b) => b.value - a.value);
return result.reduce((value, current_value) => value + current_value.key + current_value.value + separator, "").slice(0, -1);
}
function processTable(table) {
if (table === null) throw new Error("Není tabulka v detailu aliance");
for (let i = 1; i < table.rows.length - 2; i++) {
processRow(table.rows[i]);
}
}
function processRow(row) {
addRegimeFromRow(row);
processCards(row);
}
function cardName(card) {
return card in cards_to_replace ? cards_to_replace[card] : card;
}
function getWarsData(doc) {
const table = doc.getElementById("find-treaties-wars");
if (!table) return "";
const ali_tag = getAliTag(doc);
const wars = new Map();
for (let i = 1; i < table.rows.length; i++) {
const row = table.rows[i];
const cells = row.cells;
if (cells[0].colSpan > 1) continue; // is war description = skip
const declarant = cells[0].children[0].textContent.trim();
const declaree = cells[0].children[1].textContent.trim();
const ali = ali_tag == declarant ? declaree : declarant;
const age = getDeclarationAge(cells[2].textContent);
if (!wars.has(ali)) {
wars.set(ali, { age });
} else {
const war = wars.get(ali);
war.kotva = true;
war.age = Math.max(war.age, age);
}
}
const war_data = function () {
return { count: 0, kotev: 0 };
};
let wars_simplified = [war_data(), war_data(), war_data(), war_data()];
for (let [, war] of wars) {
const age = Math.min(war.age, 3);
wars_simplified[age].count++;
if (war.kotva) {
wars_simplified[age].kotev++;
}
}
let result = "";
for (let i = 0; i < wars_simplified.length; i++) {
if (wars_simplified[i].count === 0) continue;
result += wars_simplified[i].count + "x" + i + "x" + wars_simplified[i].kotev + ",";
}
result = result.slice(0, -1);
return result;
}
function getDeclarationAge(text) {
const numbers = text.match(/\d+/g);
const day = numbers[0];
const month = numbers[1];
const hours = numbers[2];
const minutes = numbers[3];
const date = new Date();
date.setDate(day);
date.setMonth(month - 1);
date.setHours(hours);
date.setMinutes(minutes);
const current_time = new Date();
if (current_time - date < 0) date.setFullYear(date.getFullYear() - 1);
return Math.floor((current_time - date) / 1000 / 60 / 60 / 24);
}
function getAliTag(doc) {
const table = doc.getElementById("find-alliance-summary");
return table.rows[0].cells[1].textContent.match(/(?<=\[).*(?=\])/g)[0];
}
function processCards(row) {
const cell = row.cells[9];
if (!cell.children) return;
let allowed_types = allowed_cards.concat(rocket_cards);
for (let index = 0; index < cell.children.length; index++) {
const element = cell.children[index];
let card_type = cardName(element.alt.slice(1, -1));
if (allowed_types.indexOf(card_type) == -1) {
continue;
}
let map = cards;
if (rocket_cards.indexOf(card_type) != -1) map = rockets;
let count = map.get(card_type);
if (count === undefined) {
count = 0;
}
map.set(card_type, count + 1);
}
}
function addRegimeFromRow(row) {
const cell = row.cells[6];
const regime = cell.textContent;
let regime_value = REGIMES[regime];
if (regime_value === undefined) {
throw new Error("Neznámá vláda - " + regime);
}
let count = regimes.get(regime_value);
if (count === undefined) {
count = 0;
}
regimes.set(regime_value, count + 1);
}
function getMembersTable(doc) {
return doc.getElementById("alliance-members");
}
function getInformation(doc) {
initializeMaps();
const table = getMembersTable(doc);
processTable(table);
const wars = getWarsData(doc);
const cards_result = transformMapToString(cards);
const regimes_result = transformMapToString(regimes);
const rockets_result = transformMapToString(rockets);
return { cards: cards_result, regimes: regimes_result, rockets: rockets_result, wars };
}
return {
getInformation(doc = document) {
return getInformation(doc);
},
};
})();
const ali_zebricek = (function () {
const FULL_SEPARATOR = "*||*";
const SEPARATOR = "*|*";
const URL = "index.php?p=najit&s=najittag&tag=";
const ICONS = {
F: "img/f.gif",
S: "img/x.gif",
P: "img/p.gif",
G: "img/gv.gif",
R: "img/r.gif",
Q: "img/q.gif",
Z: "img/z.gif",
L: "img/l.gif",
B: "img/b.gif",
N: "img/n.gif",
};
const REGIMES = {
e: "Feud",
d: "Demo",
r: "Rep",
t: "Tech",
f: "Fund",
a: "Anar",
k: "Kom",
i: "Dikt",
u: "Utop",
b: "Robo",
};
const STYLES = `
.vis_tbl tr:first-child {
position: sticky;
top: 0;
z-index: 1;
}
.grid {
display: grid;
gap: 1rem;
}
.filter_container h2 {
border-bottom: 1px solid white;
margin-bottom: 0.5rem;
font-size: 1.5rem;
text-transform: inherit;
letter-spacing: 1.5px;
}
.filter_container input {
padding: 1px 0 1px 4px;
margin: 0 0.5rem;
}
.row {
width: fit-content;
margin: auto;
padding: 0.1rem;
}
.header {
width: 160px;
display: flex;
justify-content: space-around;
font-weight: bold;
}
.row img {
vertical-align: sub;
}
tr.fits_not td {
background: rgb(160, 20, 20);
}
.icon.war_count {
border-radius: unset;
margin-right: 0.25rem;
}
`;
const show_wars_with_anchors = getSetting(ALI_WARS_WITH_ANCHORS, true);
const filter_buttons = [];
const table_data = [];
async function process() {
const table = getTable();
if (table === null) {
return;
}
const saved_information = getAllSavedInformations();
addControls(table, saved_information);
saveDataRows(table, saved_information);
if (getSetting(ALI_SHOW_CARDS, true)) {
addCards(table, saved_information);
}
if (getSetting(ALI_SHOW_REGIME, true)) {
addRegimes(table, saved_information);
}
if (getSetting(ALI_SHOW_ROCKETS, true)) {
addRockets(table, saved_information);
}
if (getSetting(ALI_SHOW_WARS, true)) {
addWars(table, saved_information);
}
if (getSetting(ALI_SHOW_FILTER, true)) {
addFilter();
}
}
function addCards(table, saved_information) {
addColumn(table, saved_information, { header_text: "Kartičky", type: "cards", callback: cardContentCallback });
}
function addRockets(table, saved_information) {
addColumn(table, saved_information, { header_text: "Rakety", type: "rockets", callback: cardContentCallback });
}
function addRegimes(table, saved_information) {
addTooltipCss();
addColumn(table, saved_information, { header_text: "Vlády", type: "regimes", callback: regimeContentCallback });
}
function addWars(table, saved_information) {
addColumn(table, saved_information, { header_text: "Války", type: "wars", callback: warsContentCallback });
}
function saveDataRows(table, saved_information) {
if (saved_information.length == 0) return;
for (let index = 1; index < table.rows.length; index++) {
const row = table.rows[index];
const ali_tag = getAliTag(row);
const ali_information = saved_information.filter((ali_information) => ali_information.tag === ali_tag)[0];
if (ali_information === undefined) {
continue;
}
const cards_data = (ali_information.cards + "," + ali_information.rockets).split(",");
const data = [];
cards_data.forEach((card_data) => {
if (card_data.length == 0) return;
const card_type = card_data.slice(0, -1);
const card_count = card_data.slice(-1);
data[card_type] = Number(card_count);
});
table_data.push({
data,
row,
});
}
}
function addFilter() {
let form = getSearchForm();
if (form === null) {
return;
}
addZebricekCss();
const container = createElement("div", { className: "grid", style: "grid-template-columns: 1fr 1fr 1fr;" });
form.parentElement.insertBefore(container, form);
container.appendChild(createElement());
container.appendChild(form);
const filter_container = createElement("div", { className: "filter_container" });
container.appendChild(filter_container);
filter_container.appendChild(createElement("h2", { textContent: "Filtr kartiček" }));
const header = createElement("div", { className: "row header" });
filter_container.appendChild(header);
header.appendChild(createElement("span", { textContent: "Min" }));
header.appendChild(createElement("span", { textContent: "Max" }));
const keys = Object.keys(ICONS);
keys.forEach((key) => {
filter_container.appendChild(createFilterRow(key));
});
}
function createFilterRow(key) {
const wrapper = createElement("div", { className: "row" });
const input_min = createNumberInput(key + "_min", 0, 0, 10);
input_min.addEventListener("change", () => filterRows());
wrapper.appendChild(input_min);
const icon = createElement("img", { src: ICONS[key], alt: key });
wrapper.appendChild(icon);
const input_max = createNumberInput(key + "_max", 10, 0, 10);
input_max.addEventListener("change", () => filterRows());
wrapper.appendChild(input_max);
filter_buttons.push({
min: input_min,
max: input_max,
});
return wrapper;
}
function getSearchForm() {
if (document.forms.length == 0) return null;
return document.forms[0];
}
function filterRows() {
const filter = {};
filter_buttons.forEach((buttons) => {
const type = buttons.min.id.slice(0, 1);
const min = Number(buttons.min.value);
const max = Number(buttons.max.value);
if (min > 0 || max < buttons.max.max) {
filter[type] = { min, max };
}
});
for (let index = 0; index < table_data.length; index++) {
const data = table_data[index];
const row = data.row;
const cards_data = data.data;
if (fitsCriteria(cards_data, filter)) {
row.classList.remove("fits_not");
} else {
row.classList.add("fits_not");
}
}
}
function fitsCriteria(cards_data, filter) {
const keys = Object.keys(filter);
for (let index = 0; index < keys.length; index++) {
const key = keys[index];
const min = filter[key].min;
const max = filter[key].max;
const count = cards_data[key] === undefined ? 0 : cards_data[key];
if (count < min || count > max) {
return false;
}
}
return true;
}
function addColumn(table, saved_information, { header_text, type, callback }) {
const th = createElement("th", { textContent: header_text });
table.rows[0].appendChild(th);
for (let index = 1; index < table.rows.length; index++) {
const row = table.rows[index];
const ali_tag = getAliTag(row);
const ali_information = saved_information.filter((ali_information) => ali_information.tag === ali_tag)[0];
const cell = row.insertCell();
if (ali_information === undefined) {
cell.textContent = "chybí";
row.classList.add("not_fetched");
continue;
}
if (ali_information[type] === "") {
continue;
}
let data = ali_information[type].split(",");
callback(cell, data);
}
}
function cardContentCallback(cell, data) {
for (let index = 0; index < data.length; index++) {
const value = data[index];
const count = Number(value.slice(1));
cell.appendChild(createElement("span", { textContent: count + "x " }));
const icon_type = value.slice(0, 1);
const icon = createElement("img", { src: ICONS[icon_type], style: "margin-right: 5px; " });
cell.appendChild(icon);
}
}
function regimeContentCallback(cell, data) {
const icon = createElement("span", { textContent: "?", className: "tooltip icon" });
cell.appendChild(icon);
cell.classList.add("c");
const wrapper = createElement("div", { className: "tooltiptext" });
icon.appendChild(wrapper);
for (let index = 0; index < data.length; index++) {
const value = data[index];
const count = Number(value.slice(1));
const regime = REGIMES[value.slice(0, 1)];
wrapper.appendChild(createElement("p", { textContent: count + "x " + regime }));
}
}
function warsContentCallback(cell, data) {
const background_colors = ["rgb(0, 255, 0)", "rgb(255, 255, 0)", "rgb(255, 128, 0)", "rgb(0, 0, 0)"];
let war_count = 0;
const age_values = ["<24", "24-48", "48-72", ">72"];
for (let index = 0; index < data.length; index++) {
const parts = data[index].split("x");
const count = Number(parts[0]);
war_count += count;
const days = Number(parts[1]);
const kotev = Number(parts[2]);
const age = age_values[days];
const background_color = background_colors[days];
const color = days == 3 ? "color: white;" : "";
const props = {
className: "icon",
style: `background:${background_color}; ${color}`,
};
let anchor_element = null;
if (show_wars_with_anchors) {
if (count > kotev) {
props.textContent = count - kotev;
props.title = count - kotev + "x " + age;
}
if (kotev > 0) {
anchor_element = createElement("span", {
textContent: kotev,
className: "icon",
title: "Zakotveno: " + kotev + "x " + age,
style: `background: linear-gradient(135deg, ${background_color} 50%, #99F 50%); ${color})`,
});
}
} else {
props.textContent = count;
props.title = count + "x " + age + ", z toho zakotveno: " + kotev;
}
if (props.textContent !== undefined) {
cell.appendChild(createElement("span", props));
}
if (anchor_element) {
cell.appendChild(anchor_element);
}
}
cell.prepend(createElement("span", { textContent: war_count, className: "icon war_count", title: `Celkem: ${war_count} ${war_count == 1 ? "válka" : "války"}` }));
}
async function resetAllInformations() {
setSetting(ALI_SAVED_INFO, "");
refreshPage();
}
function getAliTagsFromRows(rows) {
let ali_tags = [];
for (let index = 0; index < rows.length; index++) {
const row = rows[index];
const ali_tag = getAliTag(row);
ali_tags.push(ali_tag);
}
return ali_tags;
}
async function fetchInformationForAliances(ali_tags, button) {
let data = [];
const length = ali_tags.length;
for (let index = 0; index < length; index++) {
const result = await fetchInformationForAnAliance(ali_tags[index]);
data.push(result);
updateProgressBackground(button, index, length);
}
return data;
}
function removeDuplicates(saved_information, ali_tags) {
for (let index = 0; index < ali_tags.length; index++) {
const tag = ali_tags[index];
const found_index = saved_information.findIndex((card) => card.tag === tag, tag);
if (found_index !== -1) {
saved_information.splice(found_index, 1);
}
}
return saved_information;
}
function saveInformation(saved_information, new_ali_information, ali_tags = null, remove_duplicates = false) {
if (remove_duplicates) {
saved_information = removeDuplicates(saved_information, ali_tags);
}
let result = "";
if (saved_information.length > 0) {
result = saved_information.reduce(
(acc, information) =>
acc + information.tag + SEPARATOR + information.cards + SEPARATOR + information.regimes + SEPARATOR + information.rockets + SEPARATOR + information.wars + FULL_SEPARATOR,
""
);
}
result += new_ali_information.join(FULL_SEPARATOR);
result.slice(0, -FULL_SEPARATOR.length);
setSetting(ALI_SAVED_INFO, result);
refreshPage();
}
async function fetchMissingInformations({ table, saved_information }, e) {
const rows = table.querySelectorAll(".not_fetched");
const ali_tags = getAliTagsFromRows(rows);
let ali_Information = await fetchInformationForAliances(ali_tags, e.target);
saveInformation(saved_information, ali_Information);
}
async function refreshAllInformations({ table, saved_information }, e) {
let rows = Array.from(table.rows);
rows.shift();
const ali_tags = getAliTagsFromRows(rows);
let ali_Information = await fetchInformationForAliances(ali_tags, e.target);
saveInformation(saved_information, ali_Information, ali_tags, true);
}
function getAllSavedInformations() {
let saved_information = getSetting(ALI_SAVED_INFO, "");
if (saved_information.length === 0) {
return [];
}
saved_information = saved_information.split(FULL_SEPARATOR);
const ali_informations = [];
for (let index = 0; index < saved_information.length; index++) {
const cards = saved_information[index];
const parts = cards.split(SEPARATOR);
const formatted_cards = {
tag: parts[0],
cards: parts[1],
regimes: parts[2],
rockets: parts[3],
wars: parts[4],
};
ali_informations.push(formatted_cards);
}
return ali_informations;
}
function addControls(table, saved_information) {
const h1 = document.getElementsByTagName("h1")[0];
const container = createElement("div", { style: "text-align: end" });
h1.parentElement.insertBefore(container, h1.nextSibling);
container.appendChild(createButton("Získat informace pro chybějící aliance", fetchMissingInformations, { table, saved_information }));
container.appendChild(createButton("Získat informace o aliancích pro tuto stránku", refreshAllInformations, { table, saved_information }));
container.appendChild(createButton("Smazat všechna data o aliancích", () => resetAllInformations()));
}
function getTable() {
const tables = document.getElementsByClassName("vis_tbl");
if (tables.length == 0) {
return null;
}
for (let index = 0; index < tables.length; index++) {
if (tables[index].rows[0].cells[1].textContent === "Aliance") {
return tables[index];
}
}
return null;
}
function getAliTag(row) {
return row.cells[1].textContent.match(/(?<=\[).+(?=\])/)[0];
}
async function fetchInformationForAnAliance(ali_tag) {
const results = await fetchPage(URL + ali_tag, ali_detail.getInformation);
return ali_tag + SEPARATOR + results.cards + SEPARATOR + results.regimes + SEPARATOR + results.rockets + SEPARATOR + results.wars;
}
function addZebricekCss() {
addCss(STYLES);
}
return {
process() {
if (!getSetting(ALI_ALLOW_CHANGES, true)) return;
return process();
},
};
})();
//
function resetStats() {
setSetting(COUNTRY_STATS, {});
refreshPage();
}
function refreshPage() {
window.location.replace(location.href);
}
function getCurrentTimeInMillis() {
return new Date().getTime();
}
function isGameOver() {
let table = document.querySelector(".container .vis_tbl");
if (!table) {
return false;
}
return table.rows[0].children[0].innerText == "Věk skončil";
}
function addCss(css) {
let style = document.createElement("style");
if (style.styleSheet) {
style.styleSheet.cssText = css;
} else {
style.appendChild(document.createTextNode(css));
}
document.getElementsByTagName("head")[0].appendChild(style);
}
const UNITS = {
vojaci: new ArmyUnit("Vojáci", 0, 1),
tanky: new ArmyUnit("Tanky", 0, 5),
stihacky: new ArmyUnit("Stíhačky", 0, 3.5),
bunkry: new ArmyUnit("Bunkry", 0, 3.5),
mechy: new ArmyUnit("Mechy", 0, 2.7),
agenti: new ArmyUnit("Agenti", 0, 15),
penize: new ArmyUnit("Peníze", 0, 0.002),
jidlo: new ArmyUnit("Jídlo", 0, 0.02),
energie: new ArmyUnit("Energie", 0, 0.02),
uzemi: new ArmyUnit("Uzemi", 0, 15),
budovy: new ArmyUnit("Budovy", 0, 5),
budovy_na_ruiny: new ArmyUnit("Budovy Na Ruiny", 0, 3),
ruiny: new ArmyUnit("Ruiny", 0, 2),
technologie: new ArmyUnit("Technologie", 0, 1),
get(unit_name, count = 0) {
const unit = this[unit_name];
unit.setCount(count);
return unit;
},
};
execute();
//
})();