// ==UserScript== // @name HWM_MGRewardsStats // @namespace Небылица // @version 1.02 // @description Статистика золота и элементов, полученных в ГН // @author Небылица // @include /^https{0,1}:\/\/((www|qrator)\.heroeswm\.ru|178\.248\.235\.15)\/mercenary_guild\.php/ // @grant GM_setValue // @grant GM_getValue // @downloadURL none // ==/UserScript== (function() { "use strict"; // Вспомогательные функции function sendGETRequest(url, mimeType, callback){ // Универсалка для отправки GET-запроса к url с выставлением заданного MIME Type и исполнением функции callback при получении ответа var xhr = new XMLHttpRequest(); xhr.open("GET", url, true); if (typeof mimeType === "string"){ xhr.overrideMimeType(mimeType); } if (typeof callback === "function"){ xhr.onreadystatechange = function(){ if (xhr.readyState === 4 && xhr.status === 200){ callback.apply(xhr); } }; } xhr.send(); } function saveToFile(data, filename, type){ // Сохраняет данные data в файл с именем filename, используя blob-объект с типом type (на базе https://stackoverflow.com/a/30832210) var file = new Blob([data], {type: type}); if (window.navigator.msSaveOrOpenBlob){ // IE10+ window.navigator.msSaveOrOpenBlob(file, filename); } else{ // Others var a = document.createElement("a"), url = URL.createObjectURL(file); a.href = url; a.download = filename; document.body.appendChild(a); a.click(); setTimeout(function(){ document.body.removeChild(a); window.URL.revokeObjectURL(url); }, 0); } } function addLeadingZero(string){ // Вставляет ведущий ноль в строку с элементом даты/времени, если в ней только 1 цифра string = string.toString(); if (string.length === 1){string = "0" + string;} return string; } // // Забиваем дефолтные значения в хранилище if (GM_getValue("dataCollectionSince") === undefined){ // дата начала сбора статистики var currentMoment = new Date(), currentMomentOnServer = new Date(Date.now() + currentMoment.getTimezoneOffset()*60000 + 10800000); GM_setValue("dataCollectionSince", addLeadingZero(currentMomentOnServer.getDate()) + "." + addLeadingZero((currentMomentOnServer.getMonth() + 1)) + "." + currentMomentOnServer.getFullYear().toString().slice(2, 4) + " " + addLeadingZero(currentMomentOnServer.getHours()) + ":" + addLeadingZero(currentMomentOnServer.getMinutes()) ); } if (GM_getValue("rewardsList") === undefined){GM_setValue("rewardsList", "");} // полный список наград if (GM_getValue("tasksTotal") === undefined){GM_setValue("tasksTotal", 0);} // общее число заданий if (GM_getValue("tasksAccomplished") === undefined){GM_setValue("tasksAccomplished", 0);} // успешно выполненных if (GM_getValue("tasksFailed") === undefined){GM_setValue("tasksFailed", 0);} // проваленных if (GM_getValue("goldTotal") === undefined){GM_setValue("goldTotal", 0);} // всего золота получено if (GM_getValue("elementsTotal") === undefined){GM_setValue("elementsTotal", 0);} // всего элементов получено if (GM_getValue("elementsDouble") === undefined){GM_setValue("elementsDouble", 0);} // двойных выпадений // счётчики полученного золота по типам заданий if (GM_getValue("goldFromArmies") === undefined){GM_setValue("goldFromArmies", 0);} // армии if (GM_getValue("goldFromConspirators") === undefined){GM_setValue("goldFromConspirators", 0);} // заговорщики if (GM_getValue("goldFromInvaders") === undefined){GM_setValue("goldFromInvaders", 0);} // захватчики if (GM_getValue("goldFromMonsters") === undefined){GM_setValue("goldFromMonsters", 0);} // монстры if (GM_getValue("goldFromRaids") === undefined){GM_setValue("goldFromRaids", 0);} // набеги if (GM_getValue("goldFromVanguards") === undefined){GM_setValue("goldFromVanguards", 0);} // отряды if (GM_getValue("goldFromBrigands") === undefined){GM_setValue("goldFromBrigands", 0);} // разбойники // счётчики выполненных заданий по типам if (GM_getValue("accomplishedArmies") === undefined){GM_setValue("accomplishedArmies", 0);} // армии if (GM_getValue("accomplishedConspirators") === undefined){GM_setValue("accomplishedConspirators", 0);} // заговорщики if (GM_getValue("accomplishedInvaders") === undefined){GM_setValue("accomplishedInvaders", 0);} // захватчики if (GM_getValue("accomplishedMonsters") === undefined){GM_setValue("accomplishedMonsters", 0);} // монстры if (GM_getValue("accomplishedRaids") === undefined){GM_setValue("accomplishedRaids", 0);} // набеги if (GM_getValue("accomplishedVanguards") === undefined){GM_setValue("accomplishedVanguards", 0);} // отряды if (GM_getValue("accomplishedBrigands") === undefined){GM_setValue("accomplishedBrigands", 0);} // разбойники // счётчики полученных элементов по типам if (GM_getValue("gainedAbrasives") === undefined){GM_setValue("gainedAbrasives", 0);} // арбазивы if (GM_getValue("gainedViperVenoms") === undefined){GM_setValue("gainedViperVenoms", 0);} // змеиные яды if (GM_getValue("gainedTigerClaws") === undefined){GM_setValue("gainedTigerClaws", 0);} // клыки тигра if (GM_getValue("gainedIceCrystals") === undefined){GM_setValue("gainedIceCrystals", 0);} // ледяные кристаллы if (GM_getValue("gainedMoonstones") === undefined){GM_setValue("gainedMoonstones", 0);} // лунные камни if (GM_getValue("gainedFireCrystals") === undefined){GM_setValue("gainedFireCrystals", 0);} // огненные кристаллы if (GM_getValue("gainedMeteoriteShards") === undefined){GM_setValue("gainedMeteoriteShards", 0);} // осколки метеорита if (GM_getValue("gainedWitchBlooms") === undefined){GM_setValue("gainedWitchBlooms", 0);} // цветки ведьм if (GM_getValue("gainedWindflowers") === undefined){GM_setValue("gainedWindflowers", 0);} // цветки ветров if (GM_getValue("gainedFernFlowers") === undefined){GM_setValue("gainedFernFlowers", 0);} // цветки папоротника if (GM_getValue("gainedToadstools") === undefined){GM_setValue("gainedToadstools", 0);} // ядовитые грибы // var documentInnerHTHL = document.documentElement.innerHTML, currentTask = GM_getValue("currentTask"); // Код для страницы принятого задания if (documentInnerHTHL.indexOf("минут") !== -1 && documentInnerHTHL.indexOf("Принять") === -1 && documentInnerHTHL.indexOf("Вы еще не приняли это задание") === -1){ // получаем и запоминаем текущее задание var currentTaskArr = documentInnerHTHL.match(/'(.+?)<\/b>/); if (currentTaskArr !== null){ GM_setValue("currentTask", currentTaskArr[1]); } } else if (documentInnerHTHL.indexOf("мин.") === -1){ // если ни принятого, ни сданного (но ещё не обсчитанного) задания нет, то стираем сохранённое значение GM_setValue("currentTask", "-1"); } // Код для страницы сданного задания (с защитой от двойного прогона при обновлении страницы до появления нового) if (documentInnerHTHL.indexOf("мин.") !== -1 && currentTask !== "-1"){ // увеличиваем счётчик сданных заданий GM_setValue("tasksTotal", GM_getValue("tasksTotal") + 1); // получаем текст награды (без статуса) var rewardArr = documentInnerHTHL.match(/Вы\sполучаете\s(.+?)<\/b>/); if (rewardArr !== null){ // если награда есть var reward = rewardArr[1]; // увеличиваем счётчик успешно выполненных заданий GM_setValue("tasksAccomplished", GM_getValue("tasksAccomplished") + 1); // увеличиваем кол-во полученного золота var gainedGold = parseInt(reward.match(/([\d]+?)\sзолота/)[1]); GM_setValue("goldTotal", GM_getValue("goldTotal") + gainedGold); // получаем тип задания var taskTypeArr = (currentTask !== undefined) ? currentTask.match(/(Армия|заговорщики|захватчики|монстр|набеги|Отряд|разбойники)/) : null, subKey = ""; if (taskTypeArr !== null){ // выставляем кусок ключа в зависимости от типа задания switch (taskTypeArr[1]){ case "Армия": subKey = "Armies"; break; case "заговорщики": subKey = "Conspirators"; break; case "захватчики": subKey = "Invaders"; break; case "монстр": subKey = "Monsters"; break; case "набеги": subKey = "Raids"; break; case "Отряд": subKey = "Vanguards"; break; case "разбойники": subKey = "Brigands"; } // увеличиваем пару переменных (сумму полученного золота и счётчик выполненных), соответствующих типу задания if (subKey !== ""){ GM_setValue("goldFrom" + subKey, GM_getValue("goldFrom" + subKey) + gainedGold); GM_setValue("accomplished" + subKey, GM_getValue("accomplished" + subKey) + 1); } } // получаем выпавшие элементы var gainedElementsArr = reward.match(/(абразив|змеиный\sяд|клык\sтигра|ледяной\sкристалл|лунный\sкамень|огненный\sкристалл|осколок\sметеорита|цветок\sведьм|цветок\sветров|цветок\sпапоротника|ядовитый\sгриб)/g); if (gainedElementsArr !== null){ // если элементы есть var gainedElementsNumber = gainedElementsArr.length; // увеличиваем общий счётчик выпавших элементов GM_setValue("elementsTotal", GM_getValue("elementsTotal") + gainedElementsNumber); // если выпало 2 элемента, то увеличиваем счётчик двойных if (gainedElementsNumber === 2){ GM_setValue("elementsDouble", GM_getValue("elementsDouble") + 1); } // цикл по массиву с элементами var i, maxI = gainedElementsNumber; subKey = ""; for (i=0;i" + Math.round((elementsTotal-elementsDouble)/tasksAccomplished*100) + "%; " + (elementsTotal/tasksAccomplished).toFixed(2) + ")" : "", elementsDoublePercentageString = (tasksAccomplished !== 0) ? " (" + (elementsDouble/tasksAccomplished*100).toFixed(2) + "%)" : "", goldFromArmiesPerTaskString = (accomplishedArmies !== 0) ? " (" + Math.round(goldFromArmies/accomplishedArmies) + "/зад.)" : "", goldFromConspiratorsPerTaskString = (accomplishedConspirators !== 0) ? " (" + Math.round(goldFromConspirators/accomplishedConspirators) + "/зад.)" : "", goldFromInvadersPerTaskString = (accomplishedInvaders !== 0) ? " (" + Math.round(goldFromInvaders/accomplishedInvaders) + "/зад.)" : "", goldFromMonstersPerTaskString = (accomplishedMonsters !== 0) ? " (" + Math.round(goldFromMonsters/accomplishedMonsters) + "/зад.)" : "", goldFromRaidsPerTaskString = (accomplishedRaids !== 0) ? " (" + Math.round(goldFromRaids/accomplishedRaids) + "/зад.)" : "", goldFromVanguardsPerTaskString = (accomplishedVanguards !== 0) ? " (" + Math.round(goldFromVanguards/accomplishedVanguards) + "/зад.)" : "", goldFromBrigandsPerTaskString = (accomplishedBrigands !== 0) ? " (" + Math.round(goldFromBrigands/accomplishedBrigands) + "/зад.)" : "", gainedAbrasivesPercentageString = (elementsTotal !== 0) ? " (" + Math.round(gainedAbrasives/elementsTotal*100) + "%)" : "", gainedViperVenomsPercentageString = (elementsTotal !== 0) ? " (" + Math.round(gainedViperVenoms/elementsTotal*100) + "%)" : "", gainedTigerClawsPercentageString = (elementsTotal !== 0) ? " (" + Math.round(gainedTigerClaws/elementsTotal*100) + "%)" : "", gainedIceCrystalsPercentageString = (elementsTotal !== 0) ? " (" + Math.round(gainedIceCrystals/elementsTotal*100) + "%)" : "", gainedMoonstonesPercentageString = (elementsTotal !== 0) ? " (" + Math.round(gainedMoonstones/elementsTotal*100) + "%)" : "", gainedFireCrystalsPercentageString = (elementsTotal !== 0) ? " (" + Math.round(gainedFireCrystals/elementsTotal*100) + "%)" : "", gainedMeteoriteShardsPercentageString = (elementsTotal !== 0) ? " (" + Math.round(gainedMeteoriteShards/elementsTotal*100) + "%)" : "", gainedWitchBloomsPercentageString = (elementsTotal !== 0) ? " (" + Math.round(gainedWitchBlooms/elementsTotal*100) + "%)" : "", gainedWindflowersPercentageString = (elementsTotal !== 0) ? " (" + Math.round(gainedWindflowers/elementsTotal*100) + "%)" : "", gainedFernFlowersPercentageString = (elementsTotal !== 0) ? " (" + Math.round(gainedFernFlowers/elementsTotal*100) + "%)" : "", gainedToadstoolsPercentageString = (elementsTotal !== 0) ? " (" + Math.round(gainedToadstools/elementsTotal*100) + "%)" : ""; // задаём код элемента для вставки MGRewardsStatsHeaderDiv.innerHTML = "" + "
" + "
" + "Статистика наград ГН: " + "" + "показать информацию" + "" + "
" + "
" + "
" + "Сдано заданий: " + tasksTotal + "
" + "Выполнено: " + tasksAccomplished + "" + tasksAccomplishedPercentageString + "
" + "Провалено: " + tasksFailed + "" + tasksFailedPercentageString + "
" + "
" + "Золота получено: " + goldTotal + "" + goldTotalPerTaskString + "
" + "Элементов: " + elementsTotal + "" + elementsTotalPercentageString + "
" + "Двойных: " + elementsDouble + "" + elementsDoublePercentageString + "
" + "
" + "Сбор данных идёт с " + GM_getValue("dataCollectionSince") + "" + "
" + "
" + "
" + "Золото по заданиям" + "" + "показать" + "" + "
" + "
" + "Армии: " + goldFromArmies + "" + goldFromArmiesPerTaskString + "
" + "Заговорщики: " + goldFromConspirators + "" + goldFromConspiratorsPerTaskString + "
" + "Захватчики: " + goldFromInvaders + "" + goldFromInvadersPerTaskString + "
" + "Монстры: " + goldFromMonsters + "" + goldFromMonstersPerTaskString + "
" + "Набеги: " + goldFromRaids + "" + goldFromRaidsPerTaskString + "
" + "Отряды: " + goldFromVanguards + "" + goldFromVanguardsPerTaskString + "
" + "Разбойники: " + goldFromBrigands + "" + goldFromBrigandsPerTaskString + "
" + "
" + "
" + "
" + "
" + "Элементы по видам" + "" + "показать" + "" + "
" + "
" + "Абразив: " + gainedAbrasives + "" + gainedAbrasivesPercentageString + "
" + "Змеиный яд: " + gainedViperVenoms + "" + gainedViperVenomsPercentageString + "
" + "Клык тигра: " + gainedTigerClaws + "" + gainedTigerClawsPercentageString + "
" + "Ледяной кристалл: " + gainedIceCrystals + "" + gainedIceCrystalsPercentageString + "
" + "Лунный камень: " + gainedMoonstones + "" + gainedMoonstonesPercentageString + "
" + "Огненный кристалл: " + gainedFireCrystals + "" + gainedFireCrystalsPercentageString + "
" + "Осколок метеорита: " + gainedMeteoriteShards + "" + gainedMeteoriteShardsPercentageString + "
" + "Цветок ведьм: " + gainedWitchBlooms + "" + gainedWitchBloomsPercentageString + "
" + "Цветок ветров: " + gainedWindflowers + "" + gainedWindflowersPercentageString + "
" + "Цветок папоротника: " + gainedFernFlowers + "" + gainedFernFlowersPercentageString + "
" + "Ядовитый гриб: " + gainedToadstools + "" + gainedToadstoolsPercentageString + "
" + "
" + "
" + "
" + "
" + "Полный список наград" + "" + "показать" + "" + " / " + "" + "сохранить в файл" + "" + "" + "
" + "
" + "
" + "
" + "
"; // увеличиваем отступ на странице сданного задания и при наличии доступного, но не просмотренного задания и нахождении в другом районе if (documentInnerHTHL.indexOf("мин.") !== -1 || documentInnerHTHL.indexOf("Для Вас есть задание") !== -1){ MGRewardsStatsHeaderDiv.style.margin = "20px 0px 5px 0px"; } // убираем дублирование горизонтальной линии при просмотре из другого района страницы сданного задания (без награды, с таймером до нового) if (documentInnerHTHL.indexOf("Вы находитесь в другом районе") !== -1 && documentInnerHTHL.indexOf("минут") === -1 && documentInnerHTHL.indexOf("Для Вас есть задание") === -1){ var hr = document.querySelector("hr[width='90%']"); hr.parentNode.removeChild(hr); } // вставляем элемент в страницу document.querySelector("td[rowspan='2']").appendChild(MGRewardsStatsHeaderDiv); // задаём переменные для доступа к добавленным элементам var MGRewardsStatsInnerContainer = document.getElementById("MGRewardsStatsInnerContainer"), MGRewardsStatsHeaderTitleShowHide = document.getElementById("MGRewardsStatsHeaderTitleShowHide"), MGRewardsStatsInnerDiv2InnerContainer = document.getElementById("MGRewardsStatsInnerDiv2InnerContainer"), MGRewardsStatsInnerDiv2TitleShowHide = document.getElementById("MGRewardsStatsInnerDiv2TitleShowHide"), MGRewardsStatsInnerDiv3InnerContainer = document.getElementById("MGRewardsStatsInnerDiv3InnerContainer"), MGRewardsStatsInnerDiv3TitleShowHide = document.getElementById("MGRewardsStatsInnerDiv3TitleShowHide"), MGRewardsStatsInnerDiv4InnerContainer = document.getElementById("MGRewardsStatsInnerDiv4InnerContainer"), MGRewardsStatsInnerDiv4TitleShowHide = document.getElementById("MGRewardsStatsInnerDiv4TitleShowHide"), MGRewardsStatsInnerDiv4TitleExportToFile = document.getElementById("MGRewardsStatsInnerDiv4TitleExportToFile"); // по умолчанию скрываем внутренние блоки MGRewardsStatsInnerContainer.style.display = "none"; MGRewardsStatsInnerDiv2InnerContainer.style.display = "none"; MGRewardsStatsInnerDiv3InnerContainer.style.display = "none"; MGRewardsStatsInnerDiv4InnerContainer.style.display = "none"; // вешаем событие по клику на "показать/скрыть информацию" в заголовке главного информационного блока статистики MGRewardsStatsHeaderTitleShowHide.onclick = function(){ // если скрыто, то показываем; если открыто, то скрываем; ставим соответствующий текст на кнопке if (MGRewardsStatsInnerContainer.style.display === "none"){ MGRewardsStatsInnerContainer.style.display = "block"; MGRewardsStatsHeaderTitleShowHide.innerHTML = "скрыть информацию"; } else{ MGRewardsStatsInnerContainer.style.display = "none"; MGRewardsStatsHeaderTitleShowHide.innerHTML = "показать информацию"; } }; // задаём события по клику на "показать/скрыть" в заголовках внутренних блоков MGRewardsStatsInnerDiv2TitleShowHide.onclick = function(){ // если скрыто, то показываем; если открыто, то скрываем; ставим соответствующий текст на кнопке if (MGRewardsStatsInnerDiv2InnerContainer.style.display === "none"){ MGRewardsStatsInnerDiv2InnerContainer.style.display = "block"; MGRewardsStatsInnerDiv2TitleShowHide.innerHTML = "скрыть"; } else{ MGRewardsStatsInnerDiv2InnerContainer.style.display = "none"; MGRewardsStatsInnerDiv2TitleShowHide.innerHTML = "показать"; } }; MGRewardsStatsInnerDiv3TitleShowHide.onclick = function(){ // если скрыто, то показываем; если открыто, то скрываем; ставим соответствующий текст на кнопке if (MGRewardsStatsInnerDiv3InnerContainer.style.display === "none"){ MGRewardsStatsInnerDiv3InnerContainer.style.display = "block"; MGRewardsStatsInnerDiv3TitleShowHide.innerHTML = "скрыть"; } else{ MGRewardsStatsInnerDiv3InnerContainer.style.display = "none"; MGRewardsStatsInnerDiv3TitleShowHide.innerHTML = "показать"; } }; MGRewardsStatsInnerDiv4TitleShowHide.onclick = function(){ rewardsList = GM_getValue("rewardsList"); // задаём код элемента; если скрыт, то показываем; если открыт, то скрываем; ставим соответствующий текст на кнопке if (MGRewardsStatsInnerDiv4InnerContainer.style.display === "none"){ if (rewardsList !== ""){ // вставляем плейсхолдер при отсутствии сохранённых наград MGRewardsStatsInnerDiv4InnerContainer.innerHTML = rewardsList; } else{ MGRewardsStatsInnerDiv4InnerContainer.style.padding = "0px"; MGRewardsStatsInnerDiv4InnerContainer.innerHTML = "
(пока не сохранено ни одной награды)
"; } MGRewardsStatsInnerDiv4InnerContainer.style.display = "block"; MGRewardsStatsInnerDiv4TitleShowHide.innerHTML = "скрыть"; } else{ MGRewardsStatsInnerDiv4InnerContainer.style.display = "none"; MGRewardsStatsInnerDiv4TitleShowHide.innerHTML = "показать"; } }; // вешаем событие по клику на "сохранить в файл" в заголовке блока с полным списком наград MGRewardsStatsInnerDiv4TitleExportToFile.onclick = function(){ rewardsList = GM_getValue("rewardsList"); // получаем текущую дату в формате dd-mm-yy и сохраняем список наград в txt-файл var currentMoment = new Date(), currentMomentOnServer = new Date(Date.now() + currentMoment.getTimezoneOffset()*60000 + 10800000), filename = "Статистика наград ГН " + addLeadingZero(currentMomentOnServer.getDate()) + "-" + addLeadingZero(currentMomentOnServer.getMonth() + 1) + "-" + currentMomentOnServer.getFullYear().toString().slice(2, 4) + ".txt"; saveToFile(rewardsList.replace(/ /g, "\r\n"), filename, "text/plain"); }; })();