// ==UserScript==
// @name hwmTavernFilter
// @author Tamozhnya1
// @namespace Tamozhnya1
// @version 2.7
// @description Фильтр заявок в таверне
// @include *heroeswm.ru/tavern.php*
// @include *lordswm.com/tavern.php*
// @grant GM_getValue
// @grant GM_setValue
// @grant GM_addStyle
// @license MIT
// ==/UserScript==
const playerIdMatch = document.cookie.match(/pl_id=(\d+)/);
if(!playerIdMatch) {
return;
}
const PlayerId = playerIdMatch[1];
const areas = {
"Empire Capital": { tower: 50, resources: 150 },
"Eagle Nest": { tower: 50, resources: 150 },
"Harbour City": { tower: 50, resources: 150 },
"East River": { tower: 75, resources: 200 },
"Portal Ruins": { tower: 75, resources: 200 },
"Mithril Coast": { tower: 75, resources: 200 },
"The Wilderness": { tower: 75, resources: 200 },
"Tiger Lake": { tower: 150, resources: 400 },
"Dragons' Caves": { tower: 150, resources: 400 },
"Great Wall": { tower: 150, resources: 400 },
"Sublime Arbor": { tower: 150, resources: 400 },
"Rogues' Wood": { tower: 100, resources: 300 },
"Shining Spring": { tower: 100, resources: 300 },
"Titans' Valley": { tower: 100, resources: 300 },
"Wolf Dale": { tower: 100, resources: 300 },
"Sunny City": { tower: 100, resources: 300 },
"Fishing Village": { tower: 100, resources: 300 },
"Peaceful Camp": { tower: 125, resources: 350 },
"Magma Mines": { tower: 125, resources: 350 },
"Kingdom Castle": { tower: 125, resources: 350 },
"Lizard Lowland": { tower: 200, resources: 500 },
"Bear Mountain": { tower: 200, resources: 500 },
"Ungovernable Steppe": { tower: 200, resources: 500 },
"Green Wood": { tower: 100, resources: 300 },
"Fairy Trees": { tower: 100, resources: 300 },
"Crystal Garden": { tower: 100, resources: 300 }
};
const isEn = document.documentElement.lang == "en";
const locations = {
"Empire Capital": "Столица Империи",
"East River": "Восточная Река",
"Tiger Lake": "Тигриное Озеро",
"Rogues' Wood": "Лес Разбойников",
"Wolf Dale": "Долина Волков",
"Peaceful Camp": "Мирный Лагерь",
"Lizard Lowland": "Равнина Ящеров",
"Green Wood": "Зеленый Лес",
"Eagle Nest": "Орлиное Гнездо",
"Portal Ruins": "Руины Портала",
"Dragons' Caves": "Пещеры Драконов",
"Shining Spring": "Сияющий Родник",
"Sunny City": "Солнечный Город",
"Magma Mines": "Магма Шахты",
"Bear Mountain": "Медвежья Гора",
"Fairy Trees": "Магический Лес",
"Harbour City": "Портовый Город",
"Mithril Coast": "Мифриловый Берег",
"Great Wall": "Великая Стена",
"Titans' Valley": "Равнина Титанов",
"Fishing Village": "Рыбачье село",
"Kingdom Castle": "Замок Королевства",
"Ungovernable Steppe": "Непокорная Степь",
"Crystal Garden": "Кристальный Сад",
"East Island": "Восточный Остров",
"The Wilderness": "Дикие земли",
"Sublime Arbor": "Великое Древо"
};
main();
function main() {
const tavernRef = document.querySelector("a[href='/tavern.php']");
if(tavernRef) {
tavernRef.parentNode.appendChild(document.createTextNode(" / "));
const showOptionsRef = addElement("a", { href: "javascript:void(0)", innerHTML: isEn ? "Filter settings" : "Настрока фильтра" }, tavernRef.parentNode);
showOptionsRef.addEventListener("click", showOptions);
}
applyFilter();
}
function showOptions() {
if(showPupupPanel(GM_info.script.name)) {
return;
}
const fieldsMap = [];
fieldsMap.push([addElement("b", { innerText: "Выберите районы" })]);
let i = 0;
let fieldsRow = [];
for(const area in areas) {
i++;
const areaName = isEn ? area : locations[area];
const areaLabel = addElement("label", { for: `areaCheckbox${i}`, innerHTML: `${areaName} (${areas[area].tower}/${areas[area].resources})` });
const areaCheckbox = addElement("input", { id: `areaCheckbox${i}`, type: "checkbox" });
areaCheckbox.checked = getPlayerBool(`show${area}`, true);
areaCheckbox.addEventListener("click", function() { setPlayerValue(`show${area}`, this.checked); });
fieldsRow.push(areaLabel);
fieldsRow.push(areaCheckbox);
if(i % 4 == 0) {
fieldsMap.push(fieldsRow);
fieldsRow = [];
}
}
fieldsMap.push(fieldsRow);
fieldsMap.push([]);
// Уровень противника
const levelFromCaption = addElement("b", { innerText: isEn ? "Partner level from" : "Уровень противника от" });
const minLevelSelect = addElement("select");
minLevelSelect.addEventListener("change", function() { setPlayerValue("minLevel", this.value); });
const levelToCaption = addElement("b", { innerText: isEn ? "to" : "до" });
const maxLevelSelect = addElement("select");
maxLevelSelect.addEventListener("change", function() { setPlayerValue("maxLevel", this.value); });
const opponentLevels = {};
opponentLevels[-1] = isEn ? "Any" : "Любой";
for(let i = 0; i <= 20; i++) {
opponentLevels[i] = i.toString();
}
for(const opponentLevel in opponentLevels) {
let option = addElement("option", { value: opponentLevel, innerHTML: opponentLevels[opponentLevel] }, minLevelSelect);
if(opponentLevel == getPlayerValue("minLevel", "-1")) {
option.setAttribute("selected", "selected");
}
option = addElement("option", { value: opponentLevel, innerHTML: opponentLevels[opponentLevel] }, maxLevelSelect);
if(opponentLevel == getPlayerValue("maxLevel", "-1")) {
option.setAttribute("selected", "selected");
}
}
fieldsMap.push([levelFromCaption, minLevelSelect, levelToCaption, maxLevelSelect]);
// Тип игры
const gameTypeCaption = addElement("b", { innerText: isEn ? "Game type" : "Тип игры" });
const gameTypeSelect = addElement("select");
gameTypeSelect.addEventListener("change", function() { setPlayerValue("gameType", this.value); });
const gameTypes = {"-1": isEn ? "Any" : "Любой", "1": isEn ? "One desk" : "Одна колода", "8": isEn ? "Infinite desk" : "Бесконечная колода"};
for(const gameType in gameTypes) {
const option = addElement("option", { value: gameType, innerHTML: gameTypes[gameType] }, gameTypeSelect);
if(gameType == getPlayerValue("gameType", "-1")) {
option.setAttribute("selected", "selected");
}
}
fieldsMap.push([gameTypeCaption, gameTypeSelect]);
// Время на ход
const moveTimeFromCaption = addElement("b", { innerText: isEn ? "Turn time from" : "Время на ход от"});
const minTimeSelect = addElement("select");
minTimeSelect.addEventListener("change", function() { setPlayerValue("minTime", this.value); });
const moveTimeToCaption = addElement("b", { innerText: isEn ? "to" : "до" });
const maxTimeSelect = addElement("select");
maxTimeSelect.addEventListener("change", function() { setPlayerValue("maxTime", this.value); });
const moveTimes = {"-1": isEn ? "Any" : "Любая", "15": isEn ? "15 sec" :"15 сек.", "30": isEn ? "30 sec" : "30 сек.", "40": isEn ? "40 sec" : "40 сек."};
for(const moveTime in moveTimes) {
let option = addElement("option", { value: moveTime, innerHTML: moveTimes[moveTime] }, minTimeSelect);
if(moveTime == getPlayerValue("minTime", "-1")) {
option.setAttribute("selected", "selected");
}
option = addElement("option", { value: moveTime, innerHTML: moveTimes[moveTime] }, maxTimeSelect);
if(moveTime == getPlayerValue("maxTime", "-1")) {
option.setAttribute("selected", "selected");
}
}
fieldsMap.push([moveTimeFromCaption, minTimeSelect, moveTimeToCaption, maxTimeSelect]);
// Величина ставки
const betValueFromCaption = addElement("b", { innerText: isEn ? "Bet value from" : "Величина ставки от" });
const minBetSelect = addElement("select");
minBetSelect.addEventListener("change", function() { setPlayerValue("minBet", this.value); });
const betValueToCaption = addElement("b", { innerText: isEn ? "to" : "до" });
const maxBetSelect = addElement("select");
maxBetSelect.addEventListener("change", function() { setPlayerValue("maxBet", this.value); });
const betValues = { "-1": isEn ? "Any" : "Любая", "0": "0", "40": "40", "100": "100", "300": "300", "600": "600", "1000": "1000",
"2000": "2000", "3000": "3000", "4000": "4000", "5000": "5000", "6000": "6000", "7000": "7000",
"10000": "10000", "11000": "11000", "12000": "12000", "20000": "20000", "25000": "25000", "30000": "30000",
"35000": "35000", "40000": "40000", "50000": "50000" };
for(const betValue in betValues) {
let option = addElement("option", { value: betValue, innerHTML: betValues[betValue] }, minBetSelect);
if(betValue == getPlayerValue("minBet", "-1")) {
option.setAttribute("selected", "selected");
}
option = addElement("option", { value: betValue, innerHTML: betValues[betValue] }, maxBetSelect);
if(betValue == getPlayerValue("maxBet", "-1")) {
option.setAttribute("selected", "selected");
}
}
fieldsMap.push([betValueFromCaption, minBetSelect, betValueToCaption, maxBetSelect]);
createPupupPanel(GM_info.script.name, getScriptReferenceHtml() + " " + getSendErrorMailReferenceHtml(), fieldsMap, onScriptOptionToggle);
}
function onScriptOptionToggle(isShown) {
if(isShown) {
setTimeout("clearTimeout(Timer)", 0); // Вкл/выкл таймер обновления страницы (взаимодействие со скриптом на странице)
} else {
setTimeout("Refresh()", 0);
applyFilter();
}
}
function applyFilter() {
const options = { minBet: parseInt(getPlayerValue("minBet", "-1")), maxBet: parseInt(getPlayerValue("maxBet", "-1")), gameType: parseInt(getPlayerValue("gameType", -1)), minLevel: parseInt(getPlayerValue("minLevel", -1)), maxLevel: parseInt(getPlayerValue("maxLevel", -1)), minTime: parseInt(getPlayerValue("minTime", -1)), maxTime: parseInt(getPlayerValue("maxTime", -1)) };
//console.log(options);
let currentTavern;
const bets = Array.from(document.querySelectorAll("table[class='wb'] > tbody > tr")).filter(x => x.querySelector("img[src*='gold.png']")).map(x => {
if(x.cells.length == 6) {
if(!x.cells[0].hasAttribute("location")) {
x.cells[0].setAttribute("location", x.cells[0].innerHTML);
}
currentTavern = x.cells[0].getAttribute("location");
const locationName = isEn ? currentTavern : locations[currentTavern];
x.cells[0].innerHTML = `${locationName}<br><span title="${isEn ? "Tower height" : "Высота башни"}">${areas[currentTavern].tower}</span> / <span title="${isEn ? "Resources" : "Ресурсов"}">${areas[currentTavern].resources}</span>`;
}
const bet = {
tavern: currentTavern,
level: parseInt(x.querySelector("a[href^='pl_info.php']").parentNode.querySelector("i").innerText.replace("(", "").replace(")", "")),
gameType: x.querySelector("img[src*='1koloda']") ? 1 : 8,
time: parseInt((new RegExp(`(\\d+) ${isEn ? "sec" : "сек"}.`)).exec(x.innerHTML)[1]),
betValue: parseInt(x.querySelector("img[src*='gold.png']").parentNode.nextElementSibling.innerText.replace(",", "")),
mayEnter: x.querySelector("a[href^='join_to_card_game.php']") ? true : false
};
bet.enabled = bet.mayEnter
&& (options.gameType == -1 || options.gameType == bet.gameType)
&& (options.minLevel == -1 || options.minLevel <= bet.level)
&& (options.maxLevel == -1 || options.maxLevel >= bet.level)
&& (options.minTime == -1 || options.minTime <= bet.time)
&& (options.maxTime == -1 || options.maxTime >= bet.time)
&& (options.minBet == -1 || options.minBet <= bet.betValue)
&& (options.maxBet == -1 || options.maxBet >= bet.betValue);
x.style.display = getPlayerBool(`show${bet.tavern}`, true) ? "" : "none";
x.style.backgroundColor = bet.enabled ? "green" : "gray";
if(bet.mayEnter) {
x.querySelector("a[href^='join_to_card_game.php']").style.pointerEvents = bet.enabled ? "" : "none";
}
//console.log(bet);
return bet;
});
}
// API
function createPupupPanel(panelName, panelTitle, fieldsMap, panelToggleHandler) {
const backgroundPopupPanel = addElement("div", { id: panelName, style: "position: fixed; left: 0; top: 0; width: 100%; height: 100%; overflow: auto; background-color: rgb(0,0,0); background-color: rgba(0,0,0,0.4); z-index: 200;" }, document.body);
backgroundPopupPanel.addEventListener("click", function(e) { if(e.target == this) { hidePupupPanel(panelName, panelToggleHandler); }});
const contentDiv = addElement("div", { style: `top: 50%; transform: translateY(-50%); padding: 5px; display: flex; flex-wrap: wrap; position: relative; margin: auto; padding: 0; width: fit-content; background-image: linear-gradient(to right, #eea2a2 0%, #bbc1bf 19%, #57c6e1 42%, #b49fda 79%, #7ac5d8 100%); border: 1mm ridge rgb(211, 220, 50);` }, backgroundPopupPanel);
if(panelTitle) {
addElement("b", { innerHTML: panelTitle, style: "text-align: center; margin: auto; width: 90%; display: block;" }, contentDiv);
}
const divClose = addElement("span", { id: panelName + "close", title: isEn ? "Close" : "Закрыть", innerHTML: "×", style: "cursor: pointer; font-size: 20px; font-weight: bold;" }, contentDiv);
divClose.addEventListener("click", function() { hidePupupPanel(panelName, panelToggleHandler); });
addElement("div", { style: "flex-basis: 100%; height: 0;"}, contentDiv);
if(fieldsMap) {
let contentTable = addElement("table", { style: "flex-basis: 100%; width: min-content;"}, contentDiv);
for(const rowData of fieldsMap) {
if(rowData.length == 0) { // Спомощью передачи пустой стороки-массива, указываем, что надо начать новую таблицу после брейка
addElement("div", { style: "flex-basis: 100%; height: 0;"}, contentDiv);
contentTable = addElement("table", undefined, contentDiv);
continue;
}
const row = addElement("tr", undefined, contentTable);
for(const cellData of rowData) {
const cell = addElement("td", undefined, row);
if(cellData) {
if(typeof(cellData) == "string") {
cell.innerText = cellData;
} else {
cell.appendChild(cellData);
}
}
}
}
}
if(panelToggleHandler) {
panelToggleHandler(true);
}
return contentDiv;
}
function showPupupPanel(panelName, panelToggleHandler) {
const backgroundPopupPanel = document.getElementById(panelName);
if(backgroundPopupPanel) {
backgroundPopupPanel.style.display = '';
if(panelToggleHandler) {
panelToggleHandler(true);
}
return true;
}
return false;
}
function hidePupupPanel(panelName, panelToggleHandler) {
const backgroundPopupPanel = document.getElementById(panelName);
backgroundPopupPanel.style.display = 'none';
if(panelToggleHandler) {
panelToggleHandler(false);
}
}
function getValue(key, defaultValue) { return GM_getValue(key, defaultValue); };
function setValue(key, value) { GM_setValue(key, value); };
function deleteValue(key) { return GM_deleteValue(key); };
function getPlayerValue(key, defaultValue) { return GM_getValue(`${key}${PlayerId}`, defaultValue); };
function setPlayerValue(key, value) { GM_setValue(`${key}${PlayerId}`, value); };
function deletePlayerValue(key) { return GM_deleteValue(`${key}${PlayerId}`); };
function listValues() { return GM_listValues(); }
function getPlayerBool(valueName, defaultValue = false) { return getBool(valueName + PlayerId, defaultValue); }
function getBool(valueName, defaultValue = false) {
const value = getValue(valueName);
//console.log(`valueName: ${valueName}, value: ${value}, ${typeof(value)}`)
if(value != undefined) {
if(typeof(value) == "string") {
return value == "true";
}
if(typeof(value) == "boolean") {
return value;
}
}
return defaultValue;
}
function GM_addStyle(css) { addElement("style", { type: "text/css", innerHTML: css }, document.head); }
function addElement(type, data = {}, parent = undefined, insertPosition = "beforeend") {
const el = document.createElement(type);
for(const key in data) {
if(key == "innerText" || key == "innerHTML") {
el[key] = data[key];
} else {
el.setAttribute(key, data[key]);
}
}
if(parent) {
parent.insertAdjacentElement(insertPosition, el);
}
return el;
}
function getScriptLastAuthor() {
let authors = GM_info.script.author;
if(!authors) {
const authorsMatch = GM_info.scriptMetaStr.match(/@author(.+)\n/);
authors = authorsMatch ? authorsMatch[1] : "";
}
const authorsArr = authors.split(",").map(x => x.trim()).filter(x => x);
return authorsArr[authorsArr.length - 1];
}
function getDownloadUrl() {
let result = GM_info.script.downloadURL;
if(!result) {
const downloadURLMatch = GM_info.scriptMetaStr.match(/@downloadURL(.+)\n/);
result = downloadURLMatch ? downloadURLMatch[1] : "";
result = result.trim();
}
return result;
}
function getScriptReferenceHtml() { return `<a href="${getDownloadUrl()}" title="${isEn ? "Check for update" : "Проверить обновление скрипта"}" target=_blanc>${GM_info.script.name} ${GM_info.script.version}</a>`; }
function getSendErrorMailReferenceHtml() { return `<a href="sms-create.php?mailto=${getScriptLastAuthor()}&subject=${isEn ? "Error in" : "Ошибка в"} ${GM_info.script.name} ${GM_info.script.version} (${GM_info.scriptHandler} ${GM_info.version})" target=_blanc>${isEn ? "Bug report" : "Сообщить об ошибке"}</a>`; }