// ==UserScript==
// @name GN_BattleLogAnalyzer
// @namespace Gradient
// @description Анализатор протокола боев
// @include /^https{0,1}:\/\/(www\.heroeswm\.ru|178\.248\.235\.15)\/.+/
// @exclude /^https{0,1}:\/\/(www\.heroeswm\.ru|178\.248\.235\.15)\/(login|war|cgame|frames|chat|chatonline|ch_box|chat_line|ticker|chatpost|chat2020|battlechat|campaign)\.php.*/
// @version 1.0.15
// ==/UserScript==
"use strict";
//----------------------------------------------------------------------------//
var script_name = 'GN_BattleLogAnalyzer'; // Enter your script name here
//----------------------------------------------------------------------------//
(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://greasyfork.org/ru/scripts/14049-Как-устанавливать-скрипты-читать-здесь"', !alerted);
}
if(!common_values_sign){
alert_sign.setAttribute('alerted', 'true');
alerter('Скрипт ' + name + ' требует для своей работы скрипт, хранящий данные (GN_CommonValuesFiller), который должен стоять вторым в порядке выполнения скриптов.\n'
+ 'Подробнее здесь: "https://greasyfork.org/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]);
};
//----------------------------------------------------------------------------//
function get_char(e){
if(e.which && e.charCode){
if(e.which < 32)
return null;
return String.fromCharCode(+e.which)
}
return null;
}
this.number_input = function(e){
if(e.ctrlKey || e.altKey || e.metaKey)
return false;
var chr = get_char(e);
return chr == null || (chr >= '0' && chr <= '9');
};
//----------------------------------------------------------------------------//
this.check_login();
//----------------------------------------------------------------------------//
} // wrapper end
//----------------------------------------------------------------------------//
// CommonValues
//----------------------------------------------------------------------------//
var GN_CommonValues = new CommonValues();
//----------------------------------------------------------------------------//
function CommonValues(){ // wrapper start
//----------------------------------------------------------------------------//
// Battle types
//----------------------------------------------------------------------------//
this.enum_sbt = { // sync?
pvp: 0,
hunter: 1,
mercenary: 2,
thief: 3,
ranger: 4,
war: 5,
event: 6,
instance: 7,
other: 8,
guardian: 9,
campaign: 10,
leader: 11,
unknown: 12
};
this.sorted_battle_types = JSON.parse(SU.load_value('GN_CommonValues_SortedBattleTypes', '[]'));
this.battle_types = JSON.parse(SU.load_value('GN_CommonValues_BattleTypes', '[]'));
//----------------------------------------------------------------------------//
this.get_battle_type = function(id){
for(var i = 0; i < this.battle_types.length; ++i)
if(this.battle_types[i].id == id)
return this.battle_types[i];
var new_type = { id: id, sbt: this.enum_sbt.unknown, name: id }; // sync?
this.battle_types.push(new_type);
return new_type;
};
//----------------------------------------------------------------------------//
} // wrapper end
//----------------------------------------------------------------------------//
// GUIController
//----------------------------------------------------------------------------//
var GN_GUIController = new GUIController();
//----------------------------------------------------------------------------//
function GUIController(){ // wrapper start
//----------------------------------------------------------------------------//
clear_flash_z_index();
//----------------------------------------------------------------------------//
var script_name = 'GN_GUIController';
this.script_name = function(){
return script_name;
};
//----------------------------------------------------------------------------//
this.registerObject = function(object){
root_div = document.getElementById(root.div.id);
if(!root_div)
root_div = create_node(root, document.body);
else{
var custom = root_div.getAttribute('custom').split('|');
root.div.top = +custom[0];
root.div.left = +custom[1];
root.div.width = +custom[2];
root.div.height = +custom[3];
}
object.div.left = root.div.left + left;
object.div.top = top;
var childs = root_div.childNodes;
for(var i = 0; i < childs.length; ++i)
if(childs[i].nodeName.toLowerCase() == 'div'){
var height = +childs[i].getAttribute('custom').split('|')[3];
object.div.top += height;
}
create_node(object, root_div);
align_childs(root_div);
collapse_childs(root_div);
};
//----------------------------------------------------------------------------//
this.hide_all = function(){
if(!root_div)
return;
var childs = root_div.childNodes;
for(var i = 0; i < childs.length; ++i)
if(childs[i].nodeName.toLowerCase() == 'div')
childs[i].style.top = +childs[i].getAttribute('custom').split('|')[0];
align_childs(root_div);
collapse_childs(root_div);
};
var hide_all = this.hide_all;
//----------------------------------------------------------------------------//
const left = 10;
const top = 10;
var root = {
div: {
id: script_name + 'MainDiv',
top: top,
left: left,
width: 0,
height: 0
},
input: {
id: script_name + 'MainInput',
value: 'Скрипты',
title: 'Конфигурация и запуск скриптов, не относящихся к определенной странице'
},
child_divs: []
};
var root_div = document.getElementById(root.div.id);
//----------------------------------------------------------------------------//
function create_node(object, parent){
var div_ = div(object.div);
div_.setAttribute('expanded', 'false');
parent.appendChild(div_);
set_div_style(object.div);
var input_ = input(object.input);
div_.appendChild(input_);
set_input_style(object.input);
object.div.left += div_.clientWidth;
object.div.width = div_.clientWidth;
object.div.height = div_.clientHeight;
var custom = [ object.div.top, object.div.left, object.div.width, object.div.height ];
div_.setAttribute('custom', custom.join('|'));
if(object.child_divs.length || object.div.id == root.div.id){
input_.addEventListener('click', function(){
expand_childs(div_);
});
create_child_nodes(object, div_);
}
return div_;
}
//----------------------------------------------------------------------------//
function create_child_nodes(object, parent){
var childs = object.child_divs;
for(var i = 0; i < childs.length; ++i){
var child = childs[i];
child.div.top = top;
child.div.left = left;
if(i){
var total_height = 0;
for(var j = 0; j < i; ++j){
var sibling = childs[j];
var sibling_div = document.getElementById(sibling.div.id);
total_height += sibling_div.clientHeight;
}
child.div.top += total_height;
}
child.div.left += object.div.left;
create_node(child, parent);
}
}
//----------------------------------------------------------------------------//
function expand_childs(el){
var now_expanded = (el.getAttribute('expanded') == 'true');
if(now_expanded && el == root_div){
hide_all();
return;
}
var childs = el.childNodes;
for(var i = 0; i < childs.length; ++i)
if(childs[i].nodeName.toLowerCase() == 'div')
childs[i].style.display = !now_expanded ? 'block' : 'none';
if(now_expanded){
collapse_childs(el);
if(el.parentNode == root_div){
childs = root_div.childNodes;
for(i = 0; i < childs.length; ++i)
if(childs[i].nodeName.toLowerCase() == 'div' && childs[i] != el)
childs[i].style.display = 'block';
el.style.top = +el.getAttribute('custom').split('|')[0];
el.style.width = +el.getAttribute('custom').split('|')[2];
align_childs(root_div);
}
}
if(!now_expanded && el.parentNode == root_div){
childs = root_div.childNodes;
for(i = 0; i < childs.length; ++i){
if(childs[i].nodeName.toLowerCase() == 'div' && childs[i] != el)
childs[i].style.display = 'none';
}
el.style.top = top;
el.style.width = +el.getAttribute('custom').split('|')[2];
}
el.setAttribute('expanded', now_expanded ? 'false' : 'true');
}
//----------------------------------------------------------------------------//
function align_childs(el){
var max_width = 0;
var childs = el.childNodes;
for(var i = 0; i < childs.length; ++i)
if(childs[i].nodeName.toLowerCase() == 'div'){
var width = +childs[i].getAttribute('custom').split('|')[2];
if(width >= max_width)
max_width = width;
}
for(i = 0; i < childs.length; ++i)
if(childs[i].nodeName.toLowerCase() == 'div')
childs[i].style.width = max_width;
}
//----------------------------------------------------------------------------//
function collapse_childs(el){
var divs = el.querySelectorAll('div');
for(var i = 0; i < divs.length; ++i){
divs[i].setAttribute('expanded', 'false');
divs[i].style.display = 'none';
}
el.setAttribute('expanded', 'false');
}
//----------------------------------------------------------------------------//
function div(object){
var div = document.createElement('div');
div.id = object.id;
return div;
}
//----------------------------------------------------------------------------//
function set_div_style(object){
var div = document.getElementById(object.id);
var style = div.style;
style.position = 'fixed';
style.top = object.top + 'px';
style.left = object.left + 'px';
style.zIndex = 100;
}
//----------------------------------------------------------------------------//
function input(object){
var input = document.createElement('input');
input.type = 'button';
input.id = object.id;
input.value = object.value;
input.title = object.title;
return input;
}
//----------------------------------------------------------------------------//
function set_input_style(object){
var input = document.getElementById(object.id);
var style = input.style;
style.display = 'block';
style.width = '95%';
style.border = '1px solid rgb(153, 153, 153)';
style.padding = '1px';
style.margin = '2px';
style.background = 'none repeat scroll 0% 0% rgb(204, 204, 204)';
style.fontSize = '12px';
style.cursor = 'pointer';
style.zIndex = 100;
}
//----------------------------------------------------------------------------//
function clear_flash_z_index(){
var objects = document.querySelectorAll('object');
for(var i = 0; i < objects.length; ++i){
var o = objects[i];
if(!o.querySelector('param[name="wmode"]')){
var param = document.createElement('param');
param.setAttribute('name', 'wmode');
param.setAttribute('value', 'opaque');
o.insertBefore(param, o.firstChild);
}
}
}
//----------------------------------------------------------------------------//
} // wrapper end
//----------------------------------------------------------------------------//
// UnifiedLibrary end
//----------------------------------------------------------------------------//
var compare = SU.compare;
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 number_input = SU.number_input;
var string_to_date = SU.string_to_date;
var save_file = SU.save_file;
var CV = GN_CommonValues;
var sorted_battle_types = CV.sorted_battle_types;
sorted_battle_types.sort(function(a, b){
return compare(a.name, b.name);
});
var battle_types = CV.battle_types;
battle_types.sort(function(a, b){
return compare(a.name, b.name);
});
var is_parser_running = false;
var searched = [];
var colspan = '4';
var empty_option = 'all_values';
var count_counter = 0;
var mercenaries = [];
var hunters = [];
var settings = load_settings();
var save_to_file = false;
var enum_exodus = {
win: 0,
draw: 1,
loss: 2
};
var GC = GN_GUIController;
GC.registerObject(
{
div: { id: GC.script_name() + '_' + script_name + 'Div' },
input: {
id: GC.script_name() + '_' + script_name + 'Input',
value: 'Анализатор протокола боев',
title: 'Анализатор протокола боев'
},
child_divs: []
}
);
var start_button = document.getElementById(GC.script_name() + '_' + script_name + 'Input');
start_button.addEventListener('click', function(e){
draw_div(document.body);
});
//----------------------------------------------------------------------------//
function draw_div(parent){
var div = document.createElement('div');
div.id = script_name + 'Div';
div.style.position = 'fixed';
div.style.display = 'block';
div.style.top = '50px';
div.style.zIndex = 100;
div.style.overflowX = 'hidden';
var width = 700;
div.style.width = width + 'px';
div.style.left = (document.body.clientWidth - width)/2;
div.style.background = start_button.style.backgroundColor;
parent.appendChild(div);
draw_content(div);
set_settings();
}
//----------------------------------------------------------------------------//
function draw_content(parent){
var table = document.createElement('table');
table.style.width = '100%';
table.style.border = 'medium none';
parent.appendChild(table);
draw_header(table);
draw_first_row(table);
draw_second_row(table);
draw_third_row(table);
draw_fourth_row(table);
draw_fifth_row(table);
var tr = document.createElement('tr');
table.appendChild(tr);
var td = document.createElement('td');
td.setAttribute('align', 'center');
td.setAttribute('colspan', '5');
tr.appendChild(td);
var input = document.createElement('input');
input.id = script_name + 'StartInput';
input.type = 'button';
input.value = 'Начать поиск';
input.addEventListener('click', function(e){
e.preventDefault();
if(!save_settings())
return;
save_to_file = settings.save_file;
searched = [];
enable_settings(false);
draw_search_table(parent);
recheck_rect();
parse_data();
});
td.appendChild(input);
}
//----------------------------------------------------------------------------//
function draw_header(parent){
var tr = document.createElement('tr');
parent.appendChild(tr);
var td = document.createElement('td');
td.setAttribute('colspan', '5');
tr.appendChild(td);
var table = document.createElement('table');
table.style.width = '100%';
td.appendChild(table);
tr = document.createElement('tr');
table.appendChild(tr);
td = document.createElement('td');
td.setAttribute('align', 'center');
td.textContent = 'Панель настроек';
tr.appendChild(td);
td = document.createElement('td');
td.setAttribute('align', 'center');
td.style.width = '100px';
var a = document.createElement('a');
a.href = '';
a.textContent = '(очистить все)';
a.addEventListener('click', function(e){
e.preventDefault();
clear_settings();
});
td.appendChild(a);
tr.appendChild(td);
td = document.createElement('td');
td.setAttribute('align', 'center');
td.style.width = '25px';
td.textContent = 'x';
td.style.backgroundColor = 'red';
td.style.fontSize = '16';
td.title = 'Закрыть окно';
td.addEventListener('click', function(e){
remove_div();
});
tr.appendChild(td);
}
//----------------------------------------------------------------------------//
function draw_first_row(parent){
var tr = document.createElement('tr');
parent.appendChild(tr);
var td = document.createElement('td');
tr.appendChild(td);
td.appendChild(document.createTextNode('ID персонажа:'));
td = document.createElement('td');
tr.appendChild(td);
var input = document.createElement('input');
input.id = script_name + 'IDInput';
input.type = 'text';
input.style.width = '150px';
input.onkeypress = number_input;
input.title = 'Идентификатор персонажа, по чьему протоколу будет вестись поиск';
td.appendChild(input);
td = document.createElement('td');
tr.appendChild(td);
td.appendChild(document.createTextNode('Что ищем:'));
td = document.createElement('td');
tr.appendChild(td);
input = document.createElement('input');
input.id = script_name + 'SearchInput';
input.type = 'text';
input.style.width = '150px';
input.title = 'Фраза для поиска. Может не указываться, если включен поиск и фильтр по всем боям';
td.appendChild(input);
td = document.createElement('td');
tr.appendChild(td);
var chb = document.createElement('input');
chb.type = 'checkbox';
chb.title = 'Поиск будет осуществляться без учета регистра';
chb.id = script_name + 'CIChb';
td.appendChild(chb);
td.appendChild(document.createTextNode('без учета регистра'));
}
//----------------------------------------------------------------------------//
function draw_second_row(parent){
var tr = document.createElement('tr');
parent.appendChild(tr);
var td = document.createElement('td');
tr.appendChild(td);
td.appendChild(document.createTextNode('Тип боя:'));
td = document.createElement('td');
tr.appendChild(td);
var select = document.createElement('select');
select.id = script_name + 'SBTSelect';
select.style.width = '150px';
select.title = 'Поиск по общему типу боя';
select.addEventListener('change', function(e){
reload_battle_types();
});
td.appendChild(select);
var option = document.createElement('option');
option.setAttribute('value', empty_option);
select.appendChild(option);
sorted_battle_types.forEach(function(current){
option = document.createElement('option');
option.setAttribute('value', current.id);
option.appendChild(document.createTextNode(current.name));
select.appendChild(option);
});
td = document.createElement('td');
tr.appendChild(td);
td.appendChild(document.createTextNode('Вид боя:'));
td = document.createElement('td');
tr.appendChild(td);
select = document.createElement('select');
select.id = script_name + 'BTSelect';
select.style.width = '150px';
select.title = 'Поиск по конкретному виду боя';
td.appendChild(select);
option = document.createElement('option');
option.setAttribute('value', empty_option);
select.appendChild(option);
battle_types.forEach(function(current){
option = document.createElement('option');
option.setAttribute('value', current.id);
option.appendChild(document.createTextNode(current.name));
select.appendChild(option);
});
td = document.createElement('td');
tr.appendChild(td);
var chb = document.createElement('input');
chb.type = 'checkbox';
chb.title = 'При включении будет использоваться фильтр по типу и/или виду боя';
chb.id = script_name + 'BTChb';
td.appendChild(chb);
td.appendChild(document.createTextNode('использовать фильтр'));
}
//----------------------------------------------------------------------------//
function draw_third_row(parent){
var tr = document.createElement('tr');
parent.appendChild(tr);
var td = document.createElement('td');
tr.appendChild(td);
td.appendChild(document.createTextNode('До Х дней:'));
td = document.createElement('td');
tr.appendChild(td);
var input = document.createElement('input');
input.id = script_name + 'DaysInput';
input.type = 'text';
input.style.width = '150px';
input.onkeypress = number_input;
input.title = 'Поиск по количеству дней от текущей даты';
td.appendChild(input);
td = document.createElement('td');
tr.appendChild(td);
td.appendChild(document.createTextNode('До Y боев:'));
td = document.createElement('td');
tr.appendChild(td);
input = document.createElement('input');
input.id = script_name + 'CountInput';
input.type = 'text';
input.style.width = '150px';
input.onkeypress = number_input;
input.title = 'Поиск по количеству боев';
td.appendChild(input);
td = document.createElement('td');
tr.appendChild(td);
var chb = document.createElement('input');
chb.type = 'checkbox';
chb.title = 'При включении будет использоваться фильтр по количеству дней от текущей даты и/или числу боев. Если указан 0 или пусто, поиск осуществляться не будет';
chb.id = script_name + 'DCChb';
td.appendChild(chb);
td.appendChild(document.createTextNode('использовать фильтр'));
}
//----------------------------------------------------------------------------//
function draw_fourth_row(parent){
var tr = document.createElement('tr');
parent.appendChild(tr);
var td = document.createElement('td');
td.setAttribute('colspan', '2');
td.setAttribute('align', 'left');
tr.appendChild(td);
var chb = document.createElement('input');
chb.type = 'checkbox';
chb.title = 'Искать только максимальный результат в боях (только для ГО/ГН). Например: армия(макс) будет показана, армия(макс-1) уже проигнорируется';
chb.id = script_name + 'MaxBTChb';
td.appendChild(chb);
td.appendChild(document.createTextNode('только максимальные бои(ГН/ГО)'));
td = document.createElement('td');
td.setAttribute('colspan', '3');
td.setAttribute('align', 'left');
tr.appendChild(td);
chb = document.createElement('input');
chb.setAttribute('disabled', ''); // NB: future
chb.type = 'checkbox';
chb.title = 'Зарезервировано на будущее';
chb.id = script_name + 'MaxWinBTChb';
td.appendChild(chb);
td.appendChild(document.createTextNode('только выигрышные макс. бои(ГН/ГО)'));
}
//----------------------------------------------------------------------------//
function draw_fifth_row(parent){
var tr = document.createElement('tr');
parent.appendChild(tr);
var td = document.createElement('td');
td.setAttribute('colspan', '5');
td.setAttribute('align', 'left');
tr.appendChild(td);
var chb = document.createElement('input');
chb.type = 'checkbox';
chb.title = 'Сохранение результатов поиска в файл (если что-то нашлось)';
chb.id = script_name + 'SaveFileChb';
td.appendChild(chb);
td.appendChild(document.createTextNode('сохранять результаты поиска'));
}
//----------------------------------------------------------------------------//
function remove_div(){
var div = document.getElementById(script_name + 'Div');
div.parentNode.removeChild(div);
}
//----------------------------------------------------------------------------//
function draw_search_table(parent){
var table = document.getElementById(script_name + 'SearchTable');
if(table){
set_search_info();
var trs = table.querySelectorAll('tr:not([id])');
for(var i = 0; i < trs.length; ++i)
table.removeChild(trs[i]);
var el = document.getElementById(script_name + 'Stopper');
el.removeAttribute('disabled');
} else {
table = document.createElement('table');
table.style.width = '100%';
table.id = script_name + 'SearchTable';
parent.appendChild(table);
draw_search_header(table);
set_search_info();
}
}
//----------------------------------------------------------------------------//
function set_search_info(){
var el = document.getElementById(script_name + 'SearchInfo');
while(el.firstChild)
el.removeChild(el.firstChild);
if(!is_parser_running){
el.textContent = '';
return;
}
var chapters = [];
chapters.push('Идет поиск по протоколу игрока [ID = ' + settings.id + ']');
chapters.push('Фраза для поиска: "' + settings.search + (settings.ci_c ? '" (без учета регистра)' : '" (с учетом регистра)'));
if(settings.bt_c){
var str = '';
if(settings.sbt != empty_option){
var select = document.getElementById(script_name + 'SBTSelect');
str = 'Тип боя: ' + select.options[select.selectedIndex].text;
}
if(settings.bt != empty_option){
var select = document.getElementById(script_name + 'BTSelect');
str += (str.length ? ', вид боя: ' : 'Вид боя: ') + select.options[select.selectedIndex].text;
}
if(str.length)
chapters.push(str);
}
if(settings.dc_c)
chapters.push('До ' + settings.days + ' дней, до ' + settings.count + ' боев');
chapters.forEach(function(current){
el.appendChild(document.createTextNode(current));
el.appendChild(document.createElement('br'));
});
}
//----------------------------------------------------------------------------//
function set_progress_info(counter){
var el = document.getElementById(script_name + 'ProgressInfo');
while(el.firstChild)
el.removeChild(el.firstChild);
var wins = searched.filter(function(current){
return current.exodus == enum_exodus.win;
});
var b_str = 'Найдено записей: ' + searched.length;
if(searched.length)
b_str += ', побед: ' + wins.length + ', процент побед: ' + (100*wins.length/searched.length).toFixed(2) + '%';
if(!is_parser_running){
el.textContent = 'Поиск завершен. ' + b_str;
return;
}
var p_str = 'Обработано ' + counter.current + '/' + counter.last + ' страниц(' + (100*counter.current/counter.last).toFixed(2) + '%)';
el.appendChild(document.createTextNode(p_str));
el.appendChild(document.createElement('br'));
el.appendChild(document.createTextNode(b_str));
}
//----------------------------------------------------------------------------//
function draw_search_header(parent){
var tr = document.createElement('tr');
tr.id = script_name + 'SearchInfoTR';
parent.appendChild(tr);
var td = document.createElement('td');
td.id = script_name + 'SearchInfo';
td.setAttribute('colspan', colspan);
td.setAttribute('align', 'center');
tr.appendChild(td);
tr = document.createElement('tr');
tr.id = script_name + 'ProgressInfoTR';
parent.appendChild(tr);
td = document.createElement('td');
td.id = script_name + 'ProgressInfo';
td.setAttribute('colspan', colspan);
td.setAttribute('align', 'center');
tr.appendChild(td);
tr = document.createElement('tr');
tr.id = script_name + 'StopperTR';
parent.appendChild(tr);
td = document.createElement('td');
td.setAttribute('colspan', colspan);
td.setAttribute('align', 'center');
tr.appendChild(td);
var input = document.createElement('input');
input.id = script_name + 'Stopper';
input.type = 'button';
input.value = 'Окончить поиск';
input.addEventListener('click', function(e){
on_stop();
});
td.appendChild(input);
tr = document.createElement('tr');
tr.setAttribute('bgColor', '#DCDCDC');
tr.id = script_name + 'SearchHeaderTR';
parent.appendChild(tr);
['ID боя', 'Дата', 'Описание', 'Исход'].forEach(function(current){
td = document.createElement('td');
td.textContent = current;
tr.appendChild(td);
});
}
//----------------------------------------------------------------------------//
function draw_search_row(parent, obj){
var tr = document.createElement('tr');
parent.appendChild(tr);
var td = document.createElement('td');
var a = document.createElement('a');
a.href = '/war.php?lt=-1&warid=' + obj.id + (obj.id_append ? obj.id_append : '');
a.textContent = obj.id;
td.appendChild(a);
td.style.width = '90px';
tr.appendChild(td);
td = document.createElement('td');
td.textContent = obj.date.toLocaleString();
td.style.width = '90px';
tr.appendChild(td);
td = document.createElement('td');
td.textContent = obj.desc;
tr.appendChild(td);
td = document.createElement('td');
td.setAttribute('align', 'center');
td.style.width = '25px';
td.textContent = obj.exodus == enum_exodus.draw ? 'Н' : (obj.exodus == enum_exodus.win ? 'В' : 'П');
td.style.backgroundColor = obj.exodus == enum_exodus.draw ? 'grey' : (obj.exodus == enum_exodus.win ? 'green' : 'red');
tr.appendChild(td);
recheck_rect();
}
//----------------------------------------------------------------------------//
function on_stop(){
is_parser_running = false;
enable_settings(true);
set_search_info();
set_progress_info(null);
recheck_rect();
count_counter = 0;
mercenaries = [];
hunters = [];
document.body.style.cursor = 'default';
var el = document.getElementById(script_name + 'Stopper');
el.setAttribute('disabled', '');
if(save_to_file){
save_to_file = false;
export_to_file();
}
}
//----------------------------------------------------------------------------//
function parse_data(){
if(is_parser_running)
return;
document.body.style.cursor = 'wait';
is_parser_running = true;
var counter = {
current: 0,
last: get_last_page()
};
search_next(counter);
}
//----------------------------------------------------------------------------//
function search_next(counter){
if(!is_parser_running){
on_stop();
return;
}
set_progress_info(counter);
var url = '/pl_warlog.php?id=' + settings.id + '&page=' + counter.current;
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;
search_value(xhr.response);
if(counter.current <= counter.last)
search_next(counter);
else
on_stop();
}
}
};
xhr.send(null);
}
//----------------------------------------------------------------------------//
function search_value(response_){
var re = /.*?<a href="warlog\.php\?warid=(\d+)(&show_for_all=[^"]+|&show=[^"]+)*">(\d{2}-\d{2}-\d{2}\s\d{2}:\d{2})(.+?)<!--(\d+?)--><br>.*?/gmi;
var raw_data = [],
matches = [];
while(matches = re.exec(response_))
raw_data.push({ id: +matches[1], id_append: matches[2], battle_date: string_to_date(matches[3]), battle_str: matches[4], battle_type: +matches[5] });
raw_data.sort(function(a, b){
return compare(b.id, a.id);
});
var table = document.getElementById(script_name + 'SearchTable');
raw_data.forEach(function(current){
//any specific cases
var battle_type = current.battle_type;
switch(battle_type){
case 0:
var hunt_re = /<i>.+?\(\d+\)(<\/b>)?<\/i>/gmi;
battle_type = hunt_re.test(current.battle_str) ? 0 : -1; // from CommonValuesFiller - hunt or old battles
break;
case 40: // from CommonValuesFiller - tactic guild
var ai_re = /<i>(<b>)?\*.+?\*(<\/b>)?<\//gmi;
var count = 0;
while(ai_re.test(current.battle_str))
++count;
if(count)
battle_type = count == 3 ? -3 : -4; // from CommonValuesFiller - 3 ai or 2 ai
else {
var splitted = split_pvp_helper(current.battle_str);
var levels_before = splitted[0], levels_after = splitted[1];
if(levels_before.length == 1 && levels_after.length == 1)
battle_type = -5; // from CommonValuesFiller - duel
else if(JSON.stringify(levels_before) == JSON.stringify(levels_after))
battle_type = -6; // from CommonValuesFiller - pair vs pair
else
battle_type = -7; // from CommonValuesFiller - mixed
}
break;
case 61: // from CommonValuesFiller - ranger guild
var pvp_re = /.*?pl_info\.php\?id=.*?/gmi;
var count = 0;
while(pvp_re.test(current.battle_str))
++count;
battle_type = count == 1 ? 61 : -2; // from CommonValuesFiller - ai or pvp
break;
case 89: // from CommonValuesFiller - KBO
var splitted = split_pvp_helper(current.battle_str);
var levels_before = splitted[0], levels_after = splitted[1];
var hero_on_left_side = splitted[2];
if(levels_before.length == levels_after.length)
if(levels_before.length == 1)
battle_type = hero_on_left_side ? -12 : -13; // from CommonValuesFiller - attack or defence vs solo player
else
battle_type = hero_on_left_side ? -8 : -9; // from CommonValuesFiller - attack or defence
else {
if(levels_before.length > levels_after.length)
battle_type = hero_on_left_side ? -12 : -11; // from CommonValuesFiller - attack or defence vs solo player
else
battle_type = hero_on_left_side ? -10 : -13; // from CommonValuesFiller - solo attack or defence
}
break;
case 104: // from CommonValuesFiller - tax battles
var splitted = split_pvp_helper(current.battle_str);
var levels_before = splitted[0], levels_after = splitted[1];
var hero_on_left_side = splitted[2];
if(levels_before.length == levels_after.length)
battle_type = hero_on_left_side ? -14 : -15; // from CommonValuesFiller - attack or defence
else
battle_type = hero_on_left_side ? -16 : -17; // from CommonValuesFiller - attack or defence vs/as solo player
break;
}
var win_re = /<b>(.+?)<\/b>/gmi;
var win_matches = win_re.exec(current.battle_str);
var exodus = enum_exodus.win;
if(!win_matches)
exodus = enum_exodus.draw;
else{
var win = win_matches[1].indexOf(settings.id) != -1;
while(win_matches = win_re.exec(current.battle_str))
if(!win)
win = win_matches[1].indexOf(settings.id) != -1;
exodus = win ? enum_exodus.win : enum_exodus.loss;
}
var text_re = /.*?>([^<]+?)<.*?/gmi;
var desc = '';
var text_matches = [];
while(text_matches = text_re.exec(current.battle_str))
desc += text_matches[1];
var obj = { id: current.id, id_append: current.id_append, date: current.battle_date, desc: clear_specific_symbols(desc), exodus: exodus, bt: battle_type, original_bt: current.battle_type, raw_desc: current.battle_str };
var is_suit = is_suitable(obj);
if(is_parser_running && is_suit){
searched.push(obj);
draw_search_row(table, obj);
}
if(settings.dc_c){
if(settings.count && is_suit && settings.count <= ++count_counter)
is_parser_running = false;
var date = new Date();
date.setDate(date.getDate() - settings.days);
if(settings.days && obj.date <= date)
is_parser_running = false;
}
});
}
//----------------------------------------------------------------------------//
function split_pvp_helper(text){
var splitter = text.split('> vs <');
if(splitter.length != 2)
throw new Error('Incorrect splitter length');
var levels_before = [], levels_after = [];
var pvp_re = /.*?pl_info\.php\?id=.*?>.+?\[(\d+)]/gmi;
var pvp_matches = [];
while(pvp_matches = pvp_re.exec(splitter[0]))
levels_before.push(pvp_matches[1]);
while(pvp_matches = pvp_re.exec(splitter[1]))
levels_after.push(pvp_matches[1]);
if(!(levels_before.length && levels_after.length))
throw new Error('Incorrect levels length');
var hero_on_left = splitter[0].indexOf('font color=red') != -1;
return [levels_before, levels_after, hero_on_left];
}
//----------------------------------------------------------------------------//
function clear_specific_symbols(str){
var res = str;
[': ', '• ', 'ω ', 'π ', 'τ ', '° ', '•• ', '◊ '].forEach(function(current){
if(!res.indexOf(current))
res = res.substring(current.length);
});
return res;
}
//----------------------------------------------------------------------------//
function is_suitable(obj){
if(settings.search.length){
var desc = settings.ci_c ? obj.desc.toLowerCase() : obj.desc;
var search = settings.ci_c ? settings.search.toLowerCase() : settings.search;
if(desc.indexOf(search) == -1)
return false;
}
var bt = CV.get_battle_type(obj.bt);
if(settings.bt_c){
if(settings.sbt != empty_option)
if(bt.sbt != +settings.sbt)
return false;
if(settings.bt != empty_option && +settings.bt != obj.bt && +settings.bt != obj.original_bt)
return false;
}
if(settings.dc_c){
if(settings.count && settings.count <= count_counter)
return false;
var date = new Date();
date.setDate(date.getDate() - settings.days);
if(settings.days && obj.date <= date)
return false;
}
var max_choosed = (settings.max_bt_c || settings.max_win_bt_c),
suitable_type = (bt.sbt == CV.enum_sbt.hunter || bt.sbt == CV.enum_sbt.mercenary);
if(max_choosed && suitable_type){
if(bt.sbt == CV.enum_sbt.mercenary){
var re = obj.exodus == enum_exodus.loss ? /<i><b>(.+?)\s{(\d+)}<\/b><\/i>/gmi : /<i>(.+?)\s{(\d+)}<\/i>/gmi;
var matches = re.exec(obj.raw_desc);
if(!matches){
re = obj.exodus == enum_exodus.loss ? /<b><i>(.+?)\s{(\d+)}<\/i><\/b>/gmi : /<i>(.+?)\s{(\d+)}<\/i>/gmi;
matches = re.exec(obj.raw_desc);
}
if(!matches && obj.exodus == enum_exodus.draw){
re = /<i>(.+?)\s{(\d+)}<\/i>/gmi;
matches = re.exec(obj.raw_desc);
}
var merc = get_mercenary(matches[1]);
if(merc)
return false;
mercenaries.push({ str: matches[1], lvl: +matches[2], exodus: obj.exodus });
}
else if(bt.sbt == CV.enum_sbt.hunter){
var re = obj.exodus == enum_exodus.loss ? /<i><b>(.+?)\s\((\d+)\)<\/b><\/i>/gmi : /<i>(.+?)\s\((\d+)\)<\/i>/gmi;
var matches = re.exec(obj.raw_desc);
if(!matches){
re = obj.exodus == enum_exodus.loss ? /<b><i>(.+?)\s\((\d+)\)<\/i><\/b>/gmi : /<i>(.+?)\s\((\d+)\)<\/i>/gmi;
matches = re.exec(obj.raw_desc);
}
if(!matches && obj.exodus == enum_exodus.draw){
re = /<i>(.+?)\s\((\d+)\)<\/i>/gmi;
matches = re.exec(obj.raw_desc);
}
var hunt = get_hunter(matches[1]);
if(hunt)
return false;
hunters.push({ str: matches[1], count: +matches[2], exodus: obj.exodus });
}
}
return true;
}
//----------------------------------------------------------------------------//
function get_mercenary(str){
for(var i = 0; i < mercenaries.length; ++i)
if(mercenaries[i].str == str)
return mercenaries[i];
return null;
}
//----------------------------------------------------------------------------//
function get_hunter(str){
for(var i = 0; i < hunters.length; ++i)
if(hunters[i].str == str)
return hunters[i];
return null;
}
//----------------------------------------------------------------------------//
function enable_settings(enable){
['IDInput', 'SearchInput', 'CIChb', 'SBTSelect', 'BTSelect', 'BTChb', 'DaysInput',
'CountInput', 'DCChb', 'MaxBTChb', /*'MaxWinBTChb', */'StartInput', 'SaveFileChb'].forEach(function(current){
var el = document.getElementById(script_name + current);
enable ? el.removeAttribute('disabled') : el.setAttribute('disabled', '');
});
}
//----------------------------------------------------------------------------//
function reload_battle_types(){
var el = document.getElementById(script_name + 'SBTSelect');
var val = el.options[el.selectedIndex].value;
el = document.getElementById(script_name + 'BTSelect');
while(el.options.length)
el.removeChild(el.options[0]);
var tmp_bt = battle_types;
if(val != empty_option)
tmp_bt = tmp_bt.filter(function(current){
return current.sbt == val;
});
var option = document.createElement('option');
option.setAttribute('value', empty_option);
el.appendChild(option);
tmp_bt.forEach(function(current){
option = document.createElement('option');
option.setAttribute('value', current.id);
var text = document.createTextNode(current.name);
option.appendChild(text);
el.appendChild(option);
});
}
//----------------------------------------------------------------------------//
function load_settings(){
var settings_ = load_value(script_name + 'Settings');
if(settings_)
return JSON.parse(settings_);
settings_ = {
id: '',
search: '',
sbt: empty_option,
bt: empty_option,
days: '',
count: '',
ci_c: false,
bt_c: false,
dc_c: false,
max_bt_c: false,
max_win_bt_c: false
};
return settings_;
}
//----------------------------------------------------------------------------//
function save_settings(){
var errors = [];
var id = +document.getElementById(script_name + 'IDInput').value;
if(isNaN(id) || id < 1)
errors.push('Идентификатор игрока выражается положительным числом');
var search = document.getElementById(script_name + 'SearchInput').value.trim();
var bt_c = document.getElementById(script_name + 'BTChb').checked;
if(!bt_c && !search.length)
errors.push('Не указаны условия поиска');
var dc_c = document.getElementById(script_name + 'DCChb').checked;
var days = +document.getElementById(script_name + 'DaysInput').value;
var count = +document.getElementById(script_name + 'CountInput').value;
if(dc_c){
var days_correct = !isNaN(days) && days >= 1;
var count_correct = !isNaN(count) && count >= 1;
if(!days_correct && !count_correct)
errors.push('Не указано количество дней и/или боев поиска');
}
var max_bt_c = document.getElementById(script_name + 'MaxBTChb').checked;
var max_win_bt_c = document.getElementById(script_name + 'MaxWinBTChb').checked;
if(max_bt_c && max_win_bt_c)
errors.push('Поиск макс. и макс. выигрышных боев не может осуществляться одновременно');
if(errors.length){
alert('Ошибки при сохранении:\n\n' + errors.join('\n'));
return false;
}
var select = document.getElementById(script_name + 'SBTSelect');
settings.sbt = select.options[select.selectedIndex].value;
select = document.getElementById(script_name + 'BTSelect');
settings.bt = select.options[select.selectedIndex].value;
settings.id = id;
settings.search = search;
settings.days = days;
settings.count = count;
settings.ci_c = document.getElementById(script_name + 'CIChb').checked;
settings.bt_c = bt_c;
settings.dc_c = dc_c;
settings.max_bt_c = max_bt_c;
settings.max_win_bt_c = max_win_bt_c;
settings.save_file = document.getElementById(script_name + 'SaveFileChb').checked;
save_value(script_name + 'Settings', JSON.stringify(settings));
return true;
}
//----------------------------------------------------------------------------//
function set_settings(){
var el = document.getElementById(script_name + 'IDInput');
el.value = settings.id;
el = document.getElementById(script_name + 'SearchInput');
el.value = settings.search;
el = document.getElementById(script_name + 'CIChb');
el.checked = settings.ci_c;
el = document.getElementById(script_name + 'SBTSelect');
for(var i = 0; i < el.options.length; ++i)
if(el.options[i].value == settings.sbt){
el.options[i].selected = true;
break;
}
reload_battle_types();
el = document.getElementById(script_name + 'BTSelect');
for(var i = 0; i < el.options.length; ++i)
if(el.options[i].value == settings.bt){
el.options[i].selected = true;
break;
}
el = document.getElementById(script_name + 'BTChb');
el.checked = settings.bt_c;
el = document.getElementById(script_name + 'DaysInput');
el.value = settings.days;
el = document.getElementById(script_name + 'CountInput');
el.value = settings.count;
el = document.getElementById(script_name + 'DCChb');
el.checked = settings.dc_c;
el = document.getElementById(script_name + 'MaxBTChb');
el.checked = settings.max_bt_c;
el = document.getElementById(script_name + 'MaxWinBTChb');
el.checked = settings.max_win_bt_c;
el = document.getElementById(script_name + 'SaveFileChb');
el.checked = settings.save_file;
}
//----------------------------------------------------------------------------//
function clear_settings(){
if(is_parser_running)
return;
remove_value(script_name + 'Settings');
settings = load_settings();
set_settings();
}
//----------------------------------------------------------------------------//
function get_last_page(){
var url = '/pl_warlog.php?id=' + settings.id + '&page=999999';
var response = send_get(url);
var page = /a class="active" href="#">(\d+?)</gmi.exec(response);
return page ? (+page[1] - 1) : 0;
}
//----------------------------------------------------------------------------//
function recheck_rect(){
var div = document.getElementById(script_name + 'Div');
var trs = div.querySelectorAll('tr');
var height = 40;
for(var i = 0; i < trs.length; ++i)
height += trs[i].clientHeight;
div.style.height = height > 700 ? 700 : height;
div.style.overflowY = height > 700 ? 'scroll' : 'hidden';
}
//----------------------------------------------------------------------------//
function export_to_file(){
if(!searched.length)
return;
var linebreak = '\n';
var res = ['ID боя', 'Описание', 'Результат'].join(';') + linebreak;
searched.forEach(function(current){
res += [current.id + (current.id_append ? current.id_append : ''), current.desc, current.exodus].join(';') + linebreak;
});
save_file(res, 'Сейчас будет предложено сохранить файл с результатами. Переименуйте его в формат .csv, разделитель - ";"');
}
//----------------------------------------------------------------------------//
} catch(e){
alert('Ошибка в скрипте ' + script_name + ', обратитесь к разработчику:\n' + e);
throw e;
}}()); // wrapper end
//----------------------------------------------------------------------------//