您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Статистика карточных игр персонажа
// ==UserScript== // @name GN_CardState // @namespace Gradient // @description Статистика карточных игр персонажа // @include /^https{0,1}:\/\/(www\.heroeswm\.ru|178\.248\.235\.15)\/pl_info\.php\?id=\d+/ // @version 1.1.8 // ==/UserScript== "use strict"; //----------------------------------------------------------------------------// var script_name = 'GN_CardState'; // Enter your script name here var script_version = '1.1.8'; //----------------------------------------------------------------------------// (function(){ try{ // wrapper start //----------------------------------------------------------------------------// // UnifiedLibrary 1.7.0 start //----------------------------------------------------------------------------// //----------------------------------------------------------------------------// // SysUtils //----------------------------------------------------------------------------// var GN_SysUtils = new SysUtils(script_name); var SU = GN_SysUtils; //----------------------------------------------------------------------------// function SysUtils(name){ // wrapper start //----------------------------------------------------------------------------// this.show_error = function(error_string, use_alert){ if(use_alert) alert(error_string); throw new Error(error_string); }; if(arguments.length != 1) this.show_error('Wrong SysUtils arguments'); if(!arguments[0]) this.show_error('Empty SysUtils argument'); //----------------------------------------------------------------------------// this.compare = function(a, b){ return (a == b) ? 0 : (a > b ? 1 : -1); }; //----------------------------------------------------------------------------// this.send_get = function(url) { var xhr = new XMLHttpRequest(); xhr.open('GET', url, false); xhr.overrideMimeType('text/plain; charset=windows-1251'); xhr.send(null); if(xhr.status == 200) return xhr.responseText; return null; }; //----------------------------------------------------------------------------// this.save_value = function(desc, value){ var div = document.getElementById('GN_GM_Handler'); div.setAttribute('desc', desc); div.setAttribute('value', value); div.setAttribute('operation', 'save'); div.click(); if(div.getAttribute('state') != 'complete') this.show_error('Ошибка при сохранении значения'); }; //----------------------------------------------------------------------------// this.load_value = function(value, def){ var div = document.getElementById('GN_GM_Handler'); div.setAttribute('desc', value); div.setAttribute('operation', 'load'); div.click(); if(div.getAttribute('state') != 'complete') this.show_error('Ошибка при загрузке значения'); return (div.getAttribute('is_null') == 'true' ? def : div.getAttribute('value')); }; //----------------------------------------------------------------------------// this.remove_value = function(value){ var div = document.getElementById('GN_GM_Handler'); div.setAttribute('desc', value); div.setAttribute('operation', 'remove'); div.click(); if(div.getAttribute('state') != 'complete') this.show_error('Ошибка при удалении значения'); }; //----------------------------------------------------------------------------// var current_id = null; //----------------------------------------------------------------------------// function check_mandatory_scripts(alerter){ var persistent_storage_sign = document.getElementById('GN_GM_Handler'); var common_values_sign = document.getElementById('GN_CommonValuesSign'); var alert_sign = document.getElementById('GN_AlertSign'); if(!alert_sign){ alert_sign = document.createElement('div'); alert_sign.id = 'GN_AlertSign'; alert_sign.setAttribute('alerted', 'false'); document.body.appendChild(alert_sign); } var alerted = alert_sign.getAttribute('alerted') != 'false'; if(!persistent_storage_sign){ alert_sign.setAttribute('alerted', 'true'); alerter('Скрипт ' + name + ' требует для своей работы скрипт управления данными (GN_PersistentStorage), который должен стоять первым в порядке выполнения скриптов.\n' + 'Подробнее здесь: "https://gf.qytechs.cn/ru/scripts/14049-Как-устанавливать-скрипты-читать-здесь"', !alerted); } if(!common_values_sign){ alert_sign.setAttribute('alerted', 'true'); alerter('Скрипт ' + name + ' требует для своей работы скрипт, хранящий данные (GN_CommonValuesFiller), который должен стоять вторым в порядке выполнения скриптов.\n' + 'Подробнее здесь: "https://gf.qytechs.cn/ru/scripts/14049-Как-устанавливать-скрипты-читать-здесь"', !alerted); } } this.check_login = function(){ var re = /.*?pl_id=(\d+)[^\d]*?/gmi; var matches = re.exec(document.cookie.toString()); if(matches){ current_id = +matches[1]; check_mandatory_scripts(this.show_error); } }; //----------------------------------------------------------------------------// this.save_file = function(text, info){ var res = 'data:text/csv;charset=utf-8,' + encodeURI(text); if(info) alert(info); window.open(res); }; //----------------------------------------------------------------------------// this.string_to_date = function(str){ var matches = /(\d{2})-(\d{2})-(\d{2})\s(\d{2}):(\d{2})/.exec(str); return new Date(2000 + +matches[3], +matches[2] - 1, +matches[1], +matches[4], +matches[5]); }; //----------------------------------------------------------------------------// this.show_el = function(el, visible){ el.style.display = visible ? '' : 'none'; }; //----------------------------------------------------------------------------// this.reload_page = function(){ document.location.href = document.location.href; }; //----------------------------------------------------------------------------// this.check_login(); //----------------------------------------------------------------------------// } // wrapper end //----------------------------------------------------------------------------// // CommonValues //----------------------------------------------------------------------------// var GN_CommonValues = new CommonValues(); //----------------------------------------------------------------------------// function CommonValues(){ // wrapper start //----------------------------------------------------------------------------// // Card types //----------------------------------------------------------------------------// this.enum_sct = { // sync? tavern: 0, tour_pvp: 1, tour_pve: 2 }; this.sorted_card_types = JSON.parse(SU.load_value('GN_CommonValues_SortedCardTypes', '[]')); this.card_types = JSON.parse(SU.load_value('GN_CommonValues_CardTypes', '[]')); //----------------------------------------------------------------------------// this.get_card_type = function(id){ for(var i = 0; i < this.card_types.length; ++i) if(this.card_types[i].id == id) return this.card_types[i]; return null; }; //----------------------------------------------------------------------------// this.get_sorted_card_type = function(id){ for(var i = 0; i < this.sorted_card_types.length; ++i) if(this.sorted_card_types[i].id == id) return this.sorted_card_types[i]; return null; }; //----------------------------------------------------------------------------// } // wrapper end //----------------------------------------------------------------------------// // UnifiedLibrary end //----------------------------------------------------------------------------// var show_error = SU.show_error; var load_value = SU.load_value; var save_value = SU.save_value; var remove_value = SU.remove_value; var send_get = SU.send_get; var compare = SU.compare; var save_file = SU.save_file; var show_el = SU.show_el; var string_to_date = SU.string_to_date; var reload_page = SU.reload_page; var CV = GN_CommonValues; var sorted_card_types = CV.sorted_card_types; var enum_sct = CV.enum_sct; //----------------------------------------------------------------------------// var card_states = load_states(); var parser_info = load_parser_info(); var is_parser_running = false; //----------------------------------------------------------------------------// var table_width = 0; start_work(); //----------------------------------------------------------------------------// function start_work(){ var prev_sibling = get_sibling(); if(!prev_sibling) show_error('Не найден элемент привязки'); table_width = prev_sibling.width; var header = draw_header_table(prev_sibling); draw_table(header); draw_expand_all(header); } //----------------------------------------------------------------------------// function get_sibling(){ var transfer = document.querySelector('table > tbody > tr > td > a[href*="pl_transfers.php?id="]'); return transfer ? transfer.parentNode.parentNode.parentNode.parentNode : null; } //----------------------------------------------------------------------------// function draw_expand_all(next_sibling){ var table = document.createElement('table'); table.className = 'wblight'; table.width = table_width; table.align = 'center'; next_sibling.parentNode.insertBefore(table, next_sibling); var tr = document.createElement('tr'); table.appendChild(tr); var script_desc = 'Карточная статистика ' + script_version; var expander = document.createElement('td'); expander.setAttribute('align', 'center'); expander.setAttribute('colspan', '6'); var is_expanded = load_value(script_name + 'Expand', 'false') == 'true'; expander.setAttribute('expand', is_expanded ? 'true' : 'false'); expander.textContent = script_desc + (is_expanded ? ' (скрыть)' : ' (показать)'); expander.addEventListener('click', function(e){ e.preventDefault(); var expanded = expander.getAttribute('expand') == 'false'; show_el(next_sibling, expanded); show_el(next_sibling.nextSibling, expanded); save_value(script_name + 'Expand', expanded ? 'true' : 'false'); expander.setAttribute('expand', expanded ? 'true' : 'false'); expander.textContent = expanded ? (script_desc + ' (скрыть)') : (script_desc + ' (показать)'); }); tr.appendChild(expander); show_el(next_sibling, is_expanded); show_el(next_sibling.nextSibling, is_expanded); } //----------------------------------------------------------------------------// function draw_header_table(prev_sibling){ var table = document.createElement('table'); table.className = 'wblight'; table.width = table_width; table.align = 'center'; table.id = script_name + 'ContentHeader'; prev_sibling.parentNode.insertBefore(table, prev_sibling.nextSibling); var tr = document.createElement('tr'); table.appendChild(tr); var td = document.createElement('td'); td.id = script_name + 'RefreshDate'; tr.appendChild(td); td.textContent = 'Дата последнего обновления: ' + (parser_info.refresh_date ? parser_info.refresh_date.toLocaleString() : 'еще не считывалось'); td = document.createElement('td'); td.align = 'right'; tr.appendChild(td); var refresh_button = document.createElement('input'); refresh_button.type = 'button'; refresh_button.value = 'Обновить данные'; refresh_button.id = script_name + 'Refresh'; refresh_button.addEventListener('click', parse_data); td.appendChild(refresh_button); tr = document.createElement('tr'); table.appendChild(tr); td = document.createElement('td'); td.id = script_name + 'ParseDate'; tr.appendChild(td); td.textContent = 'Дата последней считанной игры: ' + (parser_info.parse_date ? parser_info.parse_date.toLocaleString() : 'еще не считывалось'); td = document.createElement('td'); td.align = 'right'; tr.appendChild(td); var export_button = document.createElement('input'); export_button.type = 'button'; export_button.value = 'Экспорт в файл'; export_button.id = script_name + 'Export'; export_button.addEventListener('click', export_to_file); td.appendChild(export_button); var remove_button = document.createElement('input'); remove_button.type = 'button'; remove_button.value = 'Очистить статистику'; remove_button.id = script_name + 'Remove'; remove_button.addEventListener('click', remove_data); td.appendChild(remove_button); return table; } //----------------------------------------------------------------------------// function draw_table(prev_sibling){ var table = document.createElement('table'); table.className = 'wblight'; table.width = table_width; table.align = 'center'; table.id = script_name + 'Content'; prev_sibling.parentNode.insertBefore(table, prev_sibling.nextSibling); update_content(table, false); return table; } //----------------------------------------------------------------------------// function update_content(parent, remove_childs){ if(remove_childs) while(parent.lastChild) parent.removeChild(parent.lastChild); if(card_states.length){ draw_header(parent); sorted_card_types.forEach(function(current){ current.win = current.loss = current.total = 0; }); card_states.forEach(function(current){ var card_type = CV.get_card_type(current.id); var sorted_card_type = CV.get_sorted_card_type(card_type.type); sorted_card_type.win += current.win; sorted_card_type.loss += current.loss; sorted_card_type.total += current.total; }); sorted_card_types.sort(function(a, b){ var a_pt = a.win*100/(a.win + a.loss); var b_pt = b.win*100/(b.win + b.loss); if(isNaN(a_pt) || isNaN(b_pt)) return isNaN(a_pt) ? 1 : -1; if(a_pt == b_pt) return compare(b.win, a.win); return compare(b_pt, a_pt); }); sorted_card_types.forEach(function(current){ if(current.win + current.loss > 0) draw_sorted_row(parent, current); }); draw_bottom_header(parent); } } //----------------------------------------------------------------------------// function draw_header(parent){ var tr = document.createElement('tr'); parent.appendChild(tr); ['Тип игры', 'Баланс', 'Победы', 'Поражения', 'Процент побед', 'Итого'].forEach(function(current){ var td = document.createElement('td'); tr.appendChild(td); var b = document.createElement('b'); td.appendChild(b); b.textContent = current; }); } //----------------------------------------------------------------------------// function draw_sorted_row(parent, content){ var tr = document.createElement('tr'); tr.setAttribute('bgcolor', content.color); parent.appendChild(tr); var td = document.createElement('td'); tr.appendChild(td); var a = document.createElement('a'); a.setAttribute('expanded', 'false'); a.addEventListener('click', function(){ var expanded = a.getAttribute('expanded') == 'false'; if(expanded){ card_states.sort(function(a, b){ var a_pt = a.win*100/(a.win + a.loss); var b_pt = b.win*100/(b.win + b.loss); if(a_pt == b_pt) return compare(a.win, b.win); return compare(a_pt, b_pt); }); var count = 0; card_states.forEach(function(current){ var card_type = CV.get_card_type(current.id); if(card_type.type == content.id){ draw_row(tr, content.id, current, count % 2 === 0 ? '#ffffff' : '#eeeeee'); ++count; } }); } else while(tr.nextSibling && tr.nextSibling.getAttribute('id') && tr.nextSibling.getAttribute('id').indexOf(script_name + '_' + content.id + '_') != -1) parent.removeChild(tr.nextSibling); a.setAttribute('expanded', expanded ? 'true' : 'false'); }); td.appendChild(a); var type = CV.get_sorted_card_type(content.id); var u = document.createElement('u'); u.textContent = type.desc; a.appendChild(u); var sum = content.win + content.loss; var percent = content.win*100/sum; [content.total, content.win, content.loss, percent.toFixed(2) + '%', sum].forEach(function(current){ td = document.createElement('td'); tr.appendChild(td); td.textContent = current; }); } //----------------------------------------------------------------------------// function draw_row(prev_sibling, sibling_id, content, color){ var tr = document.createElement('tr'); tr.id = script_name + '_' + sibling_id + '_' + content.id; tr.setAttribute('bgcolor', color); prev_sibling.parentNode.insertBefore(tr, prev_sibling.nextSibling); var type = CV.get_card_type(content.id); var sum = content.win + content.loss; var percent = content.win*100/sum; [type.desc, content.total, content.win, content.loss, percent.toFixed(2) + '%', sum].forEach(function(current){ var td = document.createElement('td'); tr.appendChild(td); td.textContent = current; }); } //----------------------------------------------------------------------------// function draw_bottom_header(parent){ var tr = document.createElement('tr'); tr.id = script_name + 'BottomHeader'; parent.appendChild(tr); var win_sum = 0, loss_sum = 0, total_sum = 0; card_states.forEach(function(current){ win_sum += current.win; loss_sum += current.loss; total_sum += current.total; }); var sum = win_sum + loss_sum; var percent = win_sum*100/sum; ['Все игры', total_sum, win_sum, loss_sum, percent.toFixed(2) + '%', sum].forEach(function(current){ var td = document.createElement('td'); tr.appendChild(td); var b = document.createElement('b'); td.appendChild(b); b.textContent = current; }); } //----------------------------------------------------------------------------// function export_to_file(){ if(!card_states.length) return; var linebreak = '%0D%0A'; var res = ['Тип игры', 'Баланс', 'Победы', 'Поражения', 'Процент побед', 'Итого'].join(';') + linebreak; card_states.forEach(function(current){ var card_type = CV.get_card_type(current.id); var sum = current.win + current.loss; var percent = current.win*100/sum; res += [card_type.desc, current.total, current.win, current.loss, percent.toFixed(2) + '%', sum].join(';') + linebreak; }); save_file(res, 'Сейчас будет предложено сохранить файл с результатами. Переименуйте его в формат .csv, разделитель - ";"'); } //----------------------------------------------------------------------------// function parse_data(){ if(is_parser_running) return; document.body.style.cursor = 'wait'; ['Refresh', 'Export', 'Remove'].forEach(function(current){ var el = document.getElementById(script_name + current); el.setAttribute('disabled', ''); }); is_parser_running = true; var last_page = get_last_page(); var counter = { current_page: last_page - parser_info.parse_page_count + (parser_info.parse_page_count === 0 ? 0 : 2), last_page: last_page }; search_next(counter); } //----------------------------------------------------------------------------// function search_next(counter){ var refresh_button = document.getElementById(script_name + 'Refresh'); var diff = counter.last_page - counter.current_page + 1; refresh_button.value = 'Обработано ' + diff + '/' + (counter.last_page + 1) + ' страниц (' + Math.round(diff*100/(counter.last_page + 1)) + '%)'; var url = '/pl_cardlog.php?id=' + get_id() + '&page=' + counter.current_page; send_async_get(url, counter); } //----------------------------------------------------------------------------// function send_async_get(url, counter) { var xhr = new XMLHttpRequest(); xhr.open('GET', url, true); xhr.overrideMimeType('text/plain; charset=windows-1251'); xhr.onreadystatechange = function(){ if(xhr.readyState == 4){ if(xhr.status == 200){ --counter.current_page; search_value(xhr.response); if(counter.current_page >= 0) search_next(counter); else { parser_info.refresh_date = new Date(); parser_info.parse_page_count = counter.last_page + 1; var refresh_td = document.getElementById(script_name + 'RefreshDate'); refresh_td.textContent = 'Дата последнего обновления: ' + parser_info.refresh_date.toLocaleString(); var parse_td = document.getElementById(script_name + 'ParseDate'); parse_td.textContent = 'Дата последней считанной игры: ' + (parser_info.parse_date ? parser_info.parse_date.toLocaleString() : 'еще не считывалось'); var refresh_button = document.getElementById(script_name + 'Refresh'); refresh_button.value = 'Обновить данные'; var content_table = document.getElementById(script_name + 'Content'); update_content(content_table, true); save_value(script_name + '_States' + get_id(), JSON.stringify(card_states)); save_value(script_name + '_ParserInfo' + get_id(), JSON.stringify(parser_info)); ['Refresh', 'Export', 'Remove'].forEach(function(current){ document.getElementById(script_name + current).removeAttribute('disabled'); }); document.body.style.cursor = 'default'; is_parser_running = false; } } } }; xhr.send(null); } //----------------------------------------------------------------------------// function search_value(response_){ var re = /.*?<a href="cgame\.php\?gameid=(\d+)">(\d{2}-\d{2}-\d{2}\s\d{2}:\d{2})(.+?)([+\-0-9]*)<\/td><\/tr>.*?/gmi; var raw_data = [], matches = []; while(matches = re.exec(response_)) raw_data.push({ id: +matches[1], game_date: string_to_date(matches[2]), game_str: matches[3], game_bet: matches[4] ? +matches[4] : 0}); raw_data.sort(function(a, b){ return compare(a.id, b.id); }); raw_data = raw_data.filter(function(current){ if(!parser_info.last_id) return true; return current.id > parser_info.last_id; }); if(!raw_data.length) return; raw_data.forEach(function(current){ re = /.*?arc_tour_hist\.php.*?/gmi; var type_id = (re.test(current.game_str) ? enum_sct.tour_pvp : enum_sct.tavern); if(type_id == enum_sct.tour_pvp){ re = /.*?(pl_info\.php\?id=).*?/gmi; var count = 0; while(re.test(current.game_str)) ++count; type_id = count == 1 ? enum_sct.tour_pve : enum_sct.tour_pvp; } var state_id = null; switch(type_id){ case enum_sct.tavern: state_id = "bet" + Math.abs(current.game_bet); break; case enum_sct.tour_pvp: case enum_sct.tour_pve: { var stage = 0; re = />1\/(\d+)</; matches = re.exec(current.game_str); if(matches) stage = +matches[1]; if(/>Полуфинал</.test(current.game_str)) stage = 2; if(/>Финал</.test(current.game_str)) stage = 1; state_id = ((type_id == enum_sct.tour_pvp) ? "stage" : "bstage") + stage; } break; } var state = get_card_state(state_id); re = new RegExp('<a href="pl_info\\.php\\?id=' + get_id() + '" class=pi><b>'); var win = re.test(current.game_str); win ? ++state.win : ++state.loss; state.total += (type_id == enum_sct.tavern && win ? current.game_bet*0.95 : current.game_bet); }); parser_info.parse_date = raw_data[raw_data.length - 1].game_date; parser_info.last_id = raw_data[raw_data.length - 1].id; } //----------------------------------------------------------------------------// function load_states(){ var states = load_value(script_name + '_States' + get_id()); return states ? JSON.parse(states) : []; } //----------------------------------------------------------------------------// function load_parser_info(){ var info = load_value(script_name + '_ParserInfo' + get_id()); if(!info) return { refresh_date: null, last_id: null, parse_date: null, parse_page_count : 0 }; info = JSON.parse(info); info.refresh_date = new Date(Date.parse(info.refresh_date)); info.parse_date = new Date(Date.parse(info.parse_date)); return info; } //----------------------------------------------------------------------------// function remove_data(){ if(!confirm('Все данные по этому игроку будут удалены. Вы уверены?')) return; remove_value(script_name + '_ParserInfo' + get_id()); remove_value(script_name + '_States' + get_id()); reload_page(); } //----------------------------------------------------------------------------// function get_last_page(){ var url = '/pl_cardlog.php?id=' + get_id() + '&page=999999'; var response = send_get(url); var page = /<\/a>\|<b><font color=red>(\d+?)<\/font><\/b><\/center>/gmi.exec(response); return page ? (+page[1] - 1) : 0; } //----------------------------------------------------------------------------// function get_id(){ return /.+id=(\d+)/.exec(document.location)[1]; } //----------------------------------------------------------------------------// function get_card_state(id){ for(var i = 0; i < card_states.length; ++i) if(card_states[i].id == id) return card_states[i]; var new_state = { id: id, total: 0, win: 0, loss: 0 }; card_states.push(new_state); return new_state; } //----------------------------------------------------------------------------// } catch(e){ alert('Ошибка в скрипте ' + script_name + ', обратитесь к разработчику:\n' + e); throw e; }}()); // wrapper end //----------------------------------------------------------------------------//
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址