GN_ElementPriceLoader

Обновление цен на элементы

当前为 2015-11-20 提交的版本,查看 最新版本

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Userscripts ,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name        GN_ElementPriceLoader
// @namespace   Gradient
// @description Обновление цен на элементы
// @include     /.+(heroeswm|178\.248\.235\.15).+/
// @exclude     /.+(heroeswm|178\.248\.235\.15).*?\/(login|war|cgame|frames|chat|chatonline|ch_box|chat_line|ticker|chatpost)\.php.*/
// @exclude     /.+daily\.heroeswm\.ru.+/
// @version     1.0.3
// ==/UserScript==

"use strict";

//----------------------------------------------------------------------------//

(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.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

//----------------------------------------------------------------------------//
// Elements
//----------------------------------------------------------------------------//

this.elements = JSON.parse(SU.load_value('GN_CommonValues_Elements', '[]'));
    
//----------------------------------------------------------------------------//
  
} // wrapper end

//----------------------------------------------------------------------------//
// GUIController
//----------------------------------------------------------------------------//

var GN_GUIController = new GUIController();

//----------------------------------------------------------------------------//

function GUIController(){  // wrapper start
  
//----------------------------------------------------------------------------//
  
clear_flash_z_index();
  
//----------------------------------------------------------------------------//
  
this.script_name = function(){
  return 'GN_GUIController';
};
  
const script_name = this.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.setAttribute('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];
    var param = document.createElement('param');
    param.setAttribute('name', 'wmode');
    param.setAttribute('value', 'opaque');

    o.insertBefore(param, o.firstChild);
  }
}

//----------------------------------------------------------------------------//  
  
} // wrapper end

//----------------------------------------------------------------------------//
// UnifiedLibrary end
//----------------------------------------------------------------------------//
  
var CV = GN_CommonValues;
var elements = CV.elements;

var save_value = SU.save_value;
var load_value = SU.load_value;
var show_error = SU.show_error;
  
var script_name = 'ElementPriceLoader';
  
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  = start_button.parentNode.style.top;
  div.style.zIndex = 100;
  
  var left = /(\d+)px/.exec(start_button.parentNode.style.left);
  div.style.left = +left[1] + start_button.parentNode.clientWidth + 'px';
  div.style.width = '300px';
  div.style.background = start_button.style.backgroundColor;
  
  parent.appendChild(div);

  draw_content(div);
}
  
//----------------------------------------------------------------------------//
  
function draw_content(parent){
  var table = document.createElement('table');
  table.style.width  = '100%';
  table.style.border = 'medium none';  
  
  parent.appendChild(table);
  
  draw_header(table);
  
  elements.forEach(function(current){
    draw_row(table, current);
  });
  
  draw_buttons(table);
}
  
//----------------------------------------------------------------------------//
  
function draw_header(parent){
  var upd_date = JSON.parse(load_value(script_name + '_LastUpdate', '0'));
  if(upd_date)
    upd_date = new Date(Date.parse(upd_date));
  
  var tr = document.createElement('tr');
  parent.appendChild(tr);
  
  var td = document.createElement('td');
  td.setAttribute('colspan', '4');
  td.id = script_name + '_LastUpdate';
  td.textContent = 'Дата последнего обновления: ' + (upd_date ? upd_date.toLocaleString() : 'еще не считывалось');
  tr.appendChild(td);

  tr = document.createElement('tr');
  tr.setAttribute('bgColor', '#DCDCDC');
  parent.appendChild(tr);
  
  td = document.createElement('td');
  td.textContent = 'Наименование';
  tr.appendChild(td);
  
  td = document.createElement('td');
  td.textContent = 'Текущее значение';
  tr.appendChild(td);
  
  td = document.createElement('td');
  td.textContent = 'Новое значение';
  tr.appendChild(td);
  
  td = document.createElement('td');
  td.textContent = 'Разница';
  tr.appendChild(td);
}
  
//----------------------------------------------------------------------------//
  
function draw_row(parent, object_){
  var tr = document.createElement('tr');
  tr.id = object_.id;
  parent.appendChild(tr);
  
  var td = document.createElement('td');
  td.textContent = object_.name + ':';
  tr.appendChild(td);
  
  td = document.createElement('td');
  td.textContent = object_.average_price;
  tr.appendChild(td);
  
  td = document.createElement('td');
  var input = document.createElement('input');
  input.type        = 'text';
  input.style.width = 40;
  input.value       = object_.average_price;
  input.onkeypress  = number_input;
  input.addEventListener('input', function(e){
    show_difference(input);
  });
  td.appendChild(input);
  tr.appendChild(td);
  
  td = document.createElement('td');
  var font = document.createElement('font');
  font.color = 'black';
  font.textContent = 0;
  td.appendChild(font);
  tr.appendChild(td);
}
  
//----------------------------------------------------------------------------//
  
function draw_buttons(parent){
  var tr = document.createElement('tr');
  parent.appendChild(tr);
  
  var td = document.createElement('td');
  td.setAttribute('align', 'right');
  td.setAttribute('colspan', '4');
  tr.appendChild(td);
  
  var button = document.createElement('input');
  button.type = 'button';
  button.value = 'Применить';
  button.addEventListener('click', function(e){  
    save_prices();
  });
  td.appendChild(button);
  
  button = document.createElement('input');
  button.type = 'button';
  button.value = 'Обновить';
  button.addEventListener('click', function(e){  
    load_prices();
  });
  td.appendChild(button);
  
  button = document.createElement('input');
  button.type = 'button';
  button.value = 'Отмена';
  button.addEventListener('click', function(e){  
    remove_div();
  });
  td.appendChild(button);
}
  
//----------------------------------------------------------------------------//
  
function save_prices(){
  var errors = [];
  
  var div = document.getElementById(script_name + 'Div');
  var trs = div.querySelectorAll('table > tr[id]');

  for(var i = 0; i < trs.length; ++i){
    var input = trs[i].querySelector('input');
    if(isNaN(+input.value) || +input.value <= 0){
      errors.push('Цена элемента должна быть положительной');
      break;
    }
  }

  if(errors.length){
    alert('Ошибки при сохранении:\n\n' + errors.join('\n'));
    return;
  }  
  
  var el_prices = [];
  
  for(var i = 0; i < trs.length; ++i){
    var input = trs[i].querySelector('input');
    el_prices.push({ id: trs[i].id, price: input.value });
  }

  save_value('GN_CommonValues_ElementPrices', JSON.stringify(el_prices));
  
  document.location = document.location;
}
  
//----------------------------------------------------------------------------//
  
function load_prices(){
  document.body.style.cursor = 'wait';
  
  var xhr = new XMLHttpRequest();
  xhr.open('GET', '/auction.php?cat=elements&sort=0', true);
  xhr.overrideMimeType('text/plain; charset=windows-1251');
  xhr.onreadystatechange = function(){
    if(xhr.readyState == 4)
      if(xhr.status == 200){
        var objects = parse_page(xhr.response);
        objects = filter_objects(objects);

        var div = document.getElementById(script_name + 'Div');
        objects.forEach(function(current){
          var tr = div.querySelector('table > tr[id="' + current.id + '"]');

          if(tr){
            var input = tr.querySelector('input');
            input.value = Math.floor(current.sum/current.count);
            show_difference(input);
          }
        });
        
        var upd_date = new Date();
        var td = document.getElementById(script_name + '_LastUpdate');
        td.textContent = 'Дата последнего обновления: ' + upd_date.toLocaleString();
        
        save_value(script_name + '_LastUpdate', JSON.stringify(upd_date));
        
        document.body.style.cursor = 'default';
      }
  };

  xhr.send(null);  
}
  
//----------------------------------------------------------------------------//
  
function parse_page(response){  
  var all_objects = [];
  
  response = response.replace(/(\n(\r)?)/g, ' ');
  
  var re = /.*?(<tr bgcolor='#(?:ffffff|eeeeee)' class=wb>.+?gold.gif.+?show_button.+?<\/tr>).*?/gmi;
  var matches = [];
  
  while(matches = re.exec(response))
  {
    var el_re = /.+\/i\/(.+?)\.gif'.+?gold.gif.+?<td>([0-9,]+?)<\/td>.+?onclick=.+?/i;
    var el_matches = el_re.exec(matches[1]);

    if(!el_matches)
      show_error('Ошибка при парсинге ' + matches[1]);

    var object = {
      id:    el_matches[1],
      price: +(el_matches[2].replace(/,/g, '')),
      count: 1
    };

    var count_re = /.*<b>(\d+?) шт.<\/b>/i;
    var c_matches = count_re.exec(matches[1]);
      
    if(c_matches)
      object.count = +c_matches[1];

    all_objects.push(object);
  }
  
  return all_objects;
}
  
//----------------------------------------------------------------------------//
  
function filter_objects(objects){
  var el_objects = [];
  var step      = 1.1;
  var max_count = 45;

  objects.forEach(function(current){
    var el = get_object(current.id, el_objects);
    
    if(!el)
      el_objects.push({ id: current.id, max_price: current.price, sum: current.price*current.count, count: current.count });
    else{
      if(current.price >= el.max_price && current.price <= el.max_price*step)
        el.max_price = current.price;
      
      if(current.price <= el.max_price*step && el.count < max_count){
        el.count += current.count;
        el.sum += current.price*current.count;
      }
    }
  });
  
  return el_objects;
}
  
//----------------------------------------------------------------------------//
  
function show_difference(input){
  var diff = +input.parentNode.previousSibling.textContent - +input.value;
  
  var font = input.parentNode.nextSibling.firstChild;
  font.color = diff == 0 ? 'black' : diff > 0 ? 'green' : 'red';
  font.textContent = diff; 
}
  
//----------------------------------------------------------------------------//
  
function get_object(id, array_){
  for(var i = 0; i < array_.length; ++i)
    if(array_[i].id == id)
      return array_[i];

  return null;
}
  
//----------------------------------------------------------------------------//
  
function remove_div(){
  var div = document.getElementById(script_name + 'Div');
  div.parentNode.removeChild(div);
}
  
//----------------------------------------------------------------------------//
  
function get_char(e) {
  if(e.which && e.charCode){
    if(e.which < 32) 
      return null;
    
    return String.fromCharCode(e.which)
  }

  return null;
}
  
//----------------------------------------------------------------------------//
  
function number_input(e){
  if(e.ctrlKey || e.altKey || e.metaKey) 
    return false;
  
  var chr = get_char(e);

  return chr == null || (chr >= '0' && chr <= '9');
}
  
//----------------------------------------------------------------------------//
  
}());  // wrapper end

//----------------------------------------------------------------------------//