// ==UserScript==
// @name GN_SortClanStorage
// @namespace Gradient
// @description Сортировка кланового склада
// @include /.+(heroeswm|178\.248\.235\.15).*?\/sklad_info\.php\?id=\d+&cat=[0-3]/
// @version 1.2.4
// ==/UserScript==
//----------------------------------------------------------------------------//
(function(){ // wrapper start
//----------------------------------------------------------------------------//
// UnifiedLibrary 1.4.0 start
//----------------------------------------------------------------------------//
//----------------------------------------------------------------------------//
// SysUtils
//----------------------------------------------------------------------------//
var GN_SysUtils = new SysUtils();
var SU = GN_SysUtils;
//----------------------------------------------------------------------------//
function SysUtils(){ // wrapper start
//----------------------------------------------------------------------------//
this.show_error = function(error_string){
throw new Error(error_string);
};
//----------------------------------------------------------------------------//
this.compare = function(a, b){
return (a == b) ? 0 : (a > b ? 1 : -1);
};
//----------------------------------------------------------------------------//
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.check_login = function(){
var re = /.*?pl_id=\d+?.*?/gmi;
if(!re.test(document.cookie.toString()))
this.show_error('Пользователь не авторизован');
};
//----------------------------------------------------------------------------//
this.check_login();
//----------------------------------------------------------------------------//
} // wrapper end
//----------------------------------------------------------------------------//
// CommonValues
//----------------------------------------------------------------------------//
var GN_CommonValues = new CommonValues();
//----------------------------------------------------------------------------//
function CommonValues(){ // wrapper start
//----------------------------------------------------------------------------//
// Artefacts
//----------------------------------------------------------------------------//
this.enum_as = { // sync?
right_arm: 0,
left_arm: 1,
foots: 2,
ring: 3,
head: 4,
neck: 5,
rear: 6,
body: 7,
backpack: 8
};
this.artefacts = JSON.parse(SU.load_value('GN_CommonValues_Artefacts', '[]'));
//----------------------------------------------------------------------------//
this.get_artefact = function(id){
for(var i = 0; i < this.artefacts.length; ++i)
if(this.artefacts[i].id == id)
return this.artefacts[i];
return null;
};
//----------------------------------------------------------------------------//
} // wrapper end
//----------------------------------------------------------------------------//
// UnifiedLibrary end
//----------------------------------------------------------------------------//
var script_name = 'GN_SortClanStorage';
var show_error = SU.show_error;
var load_value = SU.load_value;
var save_value = SU.save_value;
var compare = SU.compare;
var CV = GN_CommonValues;
var slot_type = CV.enum_as;
slot_type.unknown = -1;
slot_type.complect = -2;
var options = [
{ label: 'Показ только выбранных:', id: 'OnlyChoosedChb', title: 'Показывать только указанные внутри скрипта артефакты' },
{ label: 'Сортировка по крафту/цене:', id: 'SortByPriceChb', title: 'Сортировать артефакты по цене, если цены одинаковы - по крафту' },
//{ label: 'Сортировать по КПД:', id: 'SortByOptimumChb', title: 'Сортировка по КПД, где КПД - статы и крафт артефакта' }, //NB maybe later
{ label: 'Одевать при аренде:', id: 'DressChb', title: 'Артефакты будут сразу одеваться на персонажа' },
{ label: 'Перезагружать страницу:', id: 'ReloadChb', title: 'После каждой аренды страница будет перезагружаться' },
{ label: 'Показ цен:', id: 'ShowPriceChb', title: 'Показ цен на кнопках' }
];
//----------------------------------------------------------------------------//
var settings = load_settings();
var unknown_arts = [];
var right_arm_arts = [];
var left_arm_arts = [];
var head_arts = [];
var body_arts = [];
var foots_arts = [];
var neck_arts = [];
var rear_arts = [];
var ring_arts = [];
var backpack_arts = [];
var complect_arts = [];
var choosed = [
'cold_sword2014'
];
start_work();
//----------------------------------------------------------------------------//
function start_work(){
var content = get_content_element();
var childs = content.querySelectorAll('tr[bgcolor]');
var elements = [];
for(var i = 0; i < childs.length; ++i)
elements.push(childs[i]);
elements.forEach(function(current){
insert_converted(convert_element(current));
});
while(content.firstChild)
content.removeChild(content.firstChild);
add_new_content(content);
draw_header(content);
draw_undress_button(content);
}
//----------------------------------------------------------------------------//
function get_content_element(){
var matches = /.*\?id=(\d+).*/.exec(document.location);
var header_sign = document.querySelector('table > tbody > tr > td > a[href*="sklad_info.php?id=' + matches[1] + '&cat="]');
if(!header_sign)
show_error('Не найден элемент для поиска заголовка таблицы');
var prev_table = header_sign.parentNode.parentNode.parentNode.parentNode;
if(!prev_table)
show_error('Не найден заголовок таблицы');
var parent_table = prev_table.nextSibling;
if(!parent_table)
show_error('Не найдена таблица с содержимым(1)');
var content = parent_table.firstChild.querySelector('table > tbody');
if(!content)
show_error('Не найдена таблица с содержимым(2)');
return content;
}
//----------------------------------------------------------------------------//
function convert_element(element){
//length = 20 - complects or 21 (artefact);
var art_count = 21;
var complect_count = 20;
var childs = element.childNodes;
if(childs.length != art_count && childs.length != complect_count)
return null;
var is_c = childs[0].querySelectorAll('table[background]').length > 1;
var converted = {
id: '',
uids: [],
name: '',
craft: 0,
price: 0,
b_count: 0,
lvl: 0,
slot: slot_type.unknown,
is_c: is_c,
node: null,
form: {
depository: 0,
sign: '',
category: 0,
inv_id: 0,
set_id: 0
}
};
var re = /uid=(\d+?)&/gmi;
var matches = [];
while(matches = re.exec(childs[0].innerHTML)){
var uid = matches[1];
if(converted.uids.indexOf(uid) == -1)
converted.uids.push(uid);
}
if(!is_c)
{
matches = /.+?art_info\.php\?id=([^&"]*)/.exec(childs[0].innerHTML);
converted.id = matches[1];
matches = /.+>'(.+)'.+/.exec(childs[1].innerHTML);
converted.name = matches[1];
matches = /.+\[(.+)]/.exec(converted.name);
if(matches)
converted.craft = craft_to_int(matches[1]);
}
matches = />(\d+)</.exec(childs[is_c ? 16 : 17].innerHTML);
converted.price = +matches[1];
matches = /.*(<option\svalue="(\d+)">).*/.exec(childs[is_c ? 17 : 18].innerHTML);
converted.b_count = +matches[2];
if(!is_c)
{
var abstract = CV.get_artefact(converted.id);
if(abstract)
{
converted.lvl = abstract.lvl;
converted.slot = abstract.slot;
}
}
else
converted.slot = slot_type.complect;
converted.form.depository = childs[is_c ? 4 : 5].value;
converted.form.sign = childs[is_c ? 6 : 7].value;
converted.form.category = childs[is_c ? 8 : 9].value;
converted.form.inv_id = childs[is_c ? 12: 13].value;
converted.form.set_id = childs[is_c ? 14: 15].value;
if(!converted.uids.length)
converted.uids.push(converted.form.inv_id);
convert_node(element, converted);
return converted;
}
//----------------------------------------------------------------------------//
function craft_to_int(mod){
var count = 0;
var crafts = ['A', 'D', 'E', 'F', 'I', 'N', 'W'];
crafts.forEach(function(current){
var result = new RegExp(current + '(\\d+)').exec(mod);
count += result ? +result[1] : 0;
});
return count;
}
//----------------------------------------------------------------------------//
function convert_node(element, converted){
//appendChild - live operation
var tr = document.createElement('tr');
tr.appendChild(element.firstChild); //img
if(!converted.is_c)
tr.appendChild(element.firstChild); //name
tr.appendChild(element.childNodes[15]); //price
var b_count = converted.b_count;
tr.appendChild(b_count >= 1 ? create_button(1, converted) : create_empty_td());
tr.appendChild(b_count >= 2 ? create_button(2, converted) : create_empty_td());
tr.appendChild(b_count >= 3 ? create_button(3, converted) : create_empty_td());
var select = create_select(b_count, converted.form.inv_id, converted.slot);
tr.appendChild(select ? select : create_empty_td());
tr.appendChild(select ? create_button(4, converted) : create_empty_td());
converted.node = tr;
}
//----------------------------------------------------------------------------//
function create_button(b_count, converted){
var td = document.createElement('td');
td.align = 'center';
var button = document.createElement('button');
button.textContent = 'На ' + b_count + (settings.ShowPriceChb ? '[' + Math.floor(+converted.price*1.01)*b_count + ']' : '');
button.addEventListener('click', function(e){
e.preventDefault();
var form = converted.form;
var url = 'sklad_info.php?id=' + form.depository +
'&sign=' + form.sign +
'&cat=' + form.category +
'&action=rent&inv_id=' + form.inv_id +
'&set_id=' + form.set_id +
'&bcnt' + form.inv_id + '=' + b_count;
settings.DressChb ? dress_artefacts(url, converted) : send_async_get(url);
});
td.appendChild(button);
return td;
}
//----------------------------------------------------------------------------//
function create_empty_td(){
var td = document.createElement('td');
td.align = 'center';
td.textContent = '';
return td;
}
//----------------------------------------------------------------------------//
function create_select(b_count, inv_id, slot){
if(b_count < 4)
return null;
var td = document.createElement('td');
td.align = 'center';
var select = document.createElement('select');
select.setAttribute('inv_id', inv_id);
select.setAttribute('slot', slot);
for(var i = 4, e = b_count; i <= e; ++i)
{
var option = document.createElement('option');
option.value = i;
option.textContent = i;
select.appendChild(option);
}
select.addEventListener('change', function(e){
e.preventDefault();
var select = e.target;
var array_ = find_array_by_type(+select.getAttribute('slot'));
if(!array_){
alert('Внутренняя ошибка, обратитесь к разработчику [select handler1]');
return;
}
var converted = find_converted(array_, +select.getAttribute('inv_id'));
if(!converted){
alert('Внутренняя ошибка, обратитесь к разработчику [select handler2]');
return;
}
var btn = select.parentNode.nextSibling.firstChild;
var new_btn = create_button(select.options[select.selectedIndex].value, converted);
btn.parentNode.replaceChild(new_btn, btn);
});
td.appendChild(select);
return td;
}
//----------------------------------------------------------------------------//
function insert_converted(object_){
if(!object_)
return;
if(object_.is_c)
complect_arts.push(object_);
else
find_array_by_type(object_.slot).push(object_);
}
//----------------------------------------------------------------------------//
function find_array_by_type(slot){
switch(slot)
{
case slot_type.unknown:
return unknown_arts;
case slot_type.complect:
return complect_arts;
case slot_type.right_arm:
return right_arm_arts;
case slot_type.ring:
return ring_arts;
case slot_type.head:
return head_arts;
case slot_type.body:
return body_arts;
case slot_type.foots:
return foots_arts;
case slot_type.neck:
return neck_arts;
case slot_type.rear:
return rear_arts;
case slot_type.left_arm:
return left_arm_arts;
case slot_type.backpack:
return backpack_arts;
}
return null;
}
//----------------------------------------------------------------------------//
function sort_all(){
sort_artefacts(right_arm_arts);
sort_artefacts(ring_arts);
sort_artefacts(head_arts);
sort_artefacts(body_arts);
sort_artefacts(foots_arts);
sort_artefacts(neck_arts);
sort_artefacts(rear_arts);
sort_artefacts(left_arm_arts);
sort_artefacts(backpack_arts);
sort_artefacts(unknown_arts);
sort_artefacts(complect_arts);
}
//----------------------------------------------------------------------------//
function sort_artefacts(array_){
array_.sort(function(a, b){
if(a.price == b.price){
if(a.craft == b.craft){
if(a.lvl == b.lvl)
return compare(b.b_count, a.b_count);
return compare(b.lvl, a.lvl);
}
return compare(b.craft, a.craft);
}
return compare(a.price, b.price);
});
}
//----------------------------------------------------------------------------//
function add_new_content(content){
if(settings.SortByPriceChb)
sort_all();
var counter = { val: 0 };
add_array_content(content, unknown_arts, slot_type.unknown, 'Неизвестные артефакты', counter);
add_array_content(content, right_arm_arts, slot_type.right_arm, 'В правую руку', counter);
add_array_content(content, ring_arts, slot_type.ring, 'Кольца', counter);
add_array_content(content, head_arts, slot_type.head, 'Головные уборы', counter);
add_array_content(content, body_arts, slot_type.body, 'Броня/одежда', counter);
add_array_content(content, foots_arts, slot_type.foots, 'Обувь', counter);
add_array_content(content, neck_arts, slot_type.neck, 'Ожерелья/амулеты', counter);
add_array_content(content, rear_arts, slot_type.rear, 'Оружие на спину/плащи', counter);
add_array_content(content, left_arm_arts, slot_type.left_arm, 'В левую руку', counter);
add_array_content(content, backpack_arts, slot_type.backpack, 'В рюкзак', counter);
add_array_content(content, complect_arts, slot_type.complect, 'Комплекты', counter);
}
//----------------------------------------------------------------------------//
function add_array_content(content, array_, type, caption, counter){
if(settings.OnlyChoosedChb){
array_ = array_.filter(function(current){
if(!current.id)
return true;
return choosed.indexOf(current.id) != -1;
});
}
if(!array_.length)
return;
var e_color = '#eeeeee';
var f_color = '#ffffff';
//caption
var tr = document.createElement('tr');
var td = document.createElement('td');
td.class = 'wblight';
td.align = 'center';
var is_expanded = load_value(script_name + 'SlotExpand' + type, 'false') == 'true';
var b = document.createElement('b');
var a = document.createElement('a');
a.textContent = caption + '[' + array_.length + ']';
a.href = "#";
a.style = 'text-decoration: none;';
a.setAttribute('expand', is_expanded ? 'true' : 'false');
a.addEventListener('click', function(e){
e.preventDefault();
var expand = e.target.getAttribute('expand') == 'true';
show_content_table(e.target, !expand);
e.target.setAttribute('expand', expand ? 'false' : 'true');
save_value(script_name + 'SlotExpand' + type, expand ? 'false' : 'true');
});
tr.appendChild(td);
td.appendChild(b);
b.appendChild(a);
content.appendChild(tr);
//end caption
//content
tr = document.createElement('tr');
td = document.createElement('td');
var table = document.createElement('table');
table.width="100%";
for(var i = 0; i < array_.length; ++i){
array_[i].node.bgColor = (counter.val % 2 == 0) ? e_color : f_color;
table.appendChild(array_[i].node);
++counter.val;
}
td.appendChild(table);
tr.appendChild(td);
content.appendChild(tr);
//end content
show_content_table(a, is_expanded);
}
//----------------------------------------------------------------------------//
function show_content_table(element, visible){
var tr = element.parentNode.parentNode.parentNode;
var next = tr.nextSibling;
show_el(next, visible);
}
//----------------------------------------------------------------------------//
function find_converted(array_, inv_id){
for(var i = 0, size = array_.length; i < size; ++i)
if(inv_id == array_[i].form.inv_id)
return array_[i];
return null;
}
//----------------------------------------------------------------------------//
function send_async_get(url){
document.body.style.cursor = 'wait';
var xhr = new XMLHttpRequest();
xhr.open('GET', url, true);
xhr.overrideMimeType('text/plain; charset=windows-1251');
xhr.onreadystatechange = function(){
if(xhr.readyState == 4 && xhr.status == 200){
document.body.style.cursor = 'default';
if(settings.ReloadChb)
document.location = document.location;
}
};
xhr.send(null);
}
//----------------------------------------------------------------------------//
function dress_artefacts(url, object_){
document.body.style.cursor = 'wait';
var counter = { counter: object_.uids.length };
var xhr = new XMLHttpRequest();
xhr.open('GET', url, true);
xhr.overrideMimeType('text/plain; charset=windows-1251');
xhr.onreadystatechange = function(){
if(xhr.readyState == 4 && xhr.status == 200)
send_dress_async_get('/inventory.php?dress=' + object_.uids[counter.counter - 1] + '&js=1&rand=' + Math.random()*1000000, object_, counter);
};
xhr.send(null);
}
//----------------------------------------------------------------------------//
function send_dress_async_get(url, object_, counter){
var xhr = new XMLHttpRequest();
xhr.open('GET', url, true);
xhr.overrideMimeType('text/plain; charset=windows-1251');
xhr.onreadystatechange = function(){
if(xhr.readyState == 4 && xhr.status == 200){
--counter.counter;
if(counter.counter)
send_dress_async_get('/inventory.php?dress=' + object_.uids[counter.counter - 1] + '&js=1&rand=' + Math.random()*1000000, object_, counter);
else{
document.body.style.cursor = 'default';
if(settings.ReloadChb)
document.location = document.location;
}
}
};
xhr.send(null);
}
//----------------------------------------------------------------------------//
function draw_header(parent){
var header = document.createElement('tr');
parent.insertBefore(header, parent.firstChild);
var td = document.createElement('td');
td.setAttribute('colspan', '6');
header.appendChild(td);
var table = document.createElement('table');
table.style.width = '100%';
td.appendChild(table);
var tr = document.createElement('tr');
table.appendChild(tr);
var expander = document.createElement('td');
expander.setAttribute('align', 'center');
var is_expanded = load_value(script_name + 'SettingsExpand', 'false') == 'true';
expander.setAttribute('expand', is_expanded ? 'true' : 'false');
expander.textContent = is_expanded ? 'Скрыть настройки' : 'Показать настройки';
expander.addEventListener('click', function(e){
e.preventDefault();
var expanded = expander.getAttribute('expand') == 'false';
show_el(settings_table, expanded);
save_value(script_name + 'SettingsExpand', expanded ? 'true' : 'false');
expander.setAttribute('expand', expanded ? 'true' : 'false');
expander.textContent = expanded ? 'Скрыть настройки' : 'Показать настройки';
});
tr.appendChild(expander);
tr = document.createElement('tr');
table.appendChild(tr);
td = document.createElement('td');
tr.appendChild(td);
var settings_table = document.createElement('table');
td.appendChild(settings_table);
tr = document.createElement('tr');
settings_table.appendChild(tr);
td = document.createElement('td');
tr.appendChild(td);
options.forEach(function(current){
var text = document.createTextNode(current.label);
td.appendChild(text);
var chb = document.createElement('input');
chb.type = 'checkbox';
chb.title = current.title;
chb.id = script_name + current.id;
chb.checked = settings[current.id];
td.appendChild(chb);
});
tr = document.createElement('tr');
settings_table.appendChild(tr);
td = document.createElement('td');
td.setAttribute('align', 'right');
tr.appendChild(td);
var saver = document.createElement('input');
saver.type = 'button';
saver.value = 'Применить';
saver.addEventListener('click', function(e){
e.preventDefault();
save_settings();
});
td.appendChild(saver);
show_el(settings_table, is_expanded);
}
//----------------------------------------------------------------------------//
function draw_undress_button(content){
var table = content.parentNode.parentNode.parentNode.parentNode.parentNode.previousSibling.previousSibling;
if(table.firstChild.childNodes.length < 4)
return;
var your_arenda = table.firstChild.childNodes[2];
var a = document.createElement('a');
a.href = '';
a.textContent = '(вернуть все)';
your_arenda.firstChild.appendChild(a);
a.addEventListener('click', function(e){
e.preventDefault();
document.body.style.cursor = 'wait';
var xhr = new XMLHttpRequest();
xhr.open('GET', '/inventory.php?all_off=100', true);
xhr.overrideMimeType('text/plain; charset=windows-1251');
xhr.onreadystatechange = function(){
if(xhr.readyState == 4 && xhr.status == 200)
send_storage_async_get(document.location);
};
xhr.send(null);
});
}
//----------------------------------------------------------------------------//
function send_storage_async_get(url){
var xhr = new XMLHttpRequest();
xhr.open('GET', url, true);
xhr.overrideMimeType('text/plain; charset=windows-1251');
xhr.onreadystatechange = function(){
if(xhr.readyState == 4 && xhr.status == 200){
var response = xhr.response;
var re = /<a href="(inventory\.php\?art_return=.+?)">/gmi;
var matches = [];
var links = [];
while(matches = re.exec(response))
links.push(matches[1]);
var counter = { counter: links.length };
if(counter.counter)
send_return_async_get(links[counter.counter - 1], links, counter);
}
};
xhr.send(null);
}
//----------------------------------------------------------------------------//
function send_return_async_get(url, array_, counter){
var xhr = new XMLHttpRequest();
xhr.open('GET', url, true);
xhr.overrideMimeType('text/plain; charset=windows-1251');
xhr.onreadystatechange = function(){
if(xhr.readyState == 4 && xhr.status == 200){
--counter.counter;
if(counter.counter)
send_return_async_get(array_[counter.counter - 1], array_, counter);
else{
document.body.style.cursor = 'default';
if(settings.ReloadChb)
document.location = document.location;
}
}
};
xhr.send(null);
}
//----------------------------------------------------------------------------//
function show_el(el, visible){
el.style.display = visible ? '' : 'none';
}
//----------------------------------------------------------------------------//
function load_settings(){
var settings_ = load_value(script_name + 'Settings');
if(settings_)
return JSON.parse(settings_);
settings_ = {};
options.forEach(function(current){
settings_[current.id] = false;
});
return settings_;
}
//----------------------------------------------------------------------------//
function save_settings(){
/*var errors = [];
if(document.getElementById(script_name + 'SortByPriceChb').checked && document.getElementById(script_name + 'SortByOptimumChb').checked)
errors.push('Сортировки по цене/КПД не могут быть использованы одновременно');
if(errors.length){
alert('Ошибки при сохранении:\n\n' + errors.join('\n'));
return;
}*/
options.forEach(function(current){
var chb = document.getElementById(script_name + current.id);
settings[current.id] = chb.checked;
});
save_value(script_name + 'Settings', JSON.stringify(settings));
document.location = document.location;
}
//----------------------------------------------------------------------------//
})(); // wrapper end
//----------------------------------------------------------------------------//