GN_ElementPriceLoader

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

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

  1. // ==UserScript==
  2. // @name GN_ElementPriceLoader
  3. // @namespace Gradient
  4. // @description Обновление цен на элементы
  5. // @include /.+(heroeswm|178\.248\.235\.15).+/
  6. // @exclude /.+(heroeswm|178\.248\.235\.15).*?\/(login|war|cgame|frames|chat|chatonline|ch_box|chat_line|ticker|chatpost)\.php.*/
  7. // @exclude /.+daily\.heroeswm\.ru.+/
  8. // @version 1.0.3
  9. // ==/UserScript==
  10.  
  11. "use strict";
  12.  
  13. //----------------------------------------------------------------------------//
  14.  
  15. (function(){ // wrapper start
  16. //----------------------------------------------------------------------------//
  17. // UnifiedLibrary 1.4.0 start
  18. //----------------------------------------------------------------------------//
  19.  
  20. //----------------------------------------------------------------------------//
  21. // SysUtils
  22. //----------------------------------------------------------------------------//
  23.  
  24. var GN_SysUtils = new SysUtils();
  25. var SU = GN_SysUtils;
  26.  
  27. //----------------------------------------------------------------------------//
  28.  
  29. function SysUtils(){ // wrapper start
  30. //----------------------------------------------------------------------------//
  31. this.show_error = function(error_string){
  32. throw new Error(error_string);
  33. };
  34.  
  35. //----------------------------------------------------------------------------//
  36. this.save_value = function(desc, value){
  37. var div = document.getElementById('GN_GM_Handler');
  38. div.setAttribute('desc', desc);
  39. div.setAttribute('value', value);
  40. div.setAttribute('operation', 'save');
  41. div.click();
  42. if(div.getAttribute('state') != 'complete')
  43. this.show_error('Ошибка при сохранении значения');
  44. };
  45. //----------------------------------------------------------------------------//
  46.  
  47. this.load_value = function(value, def){
  48. var div = document.getElementById('GN_GM_Handler');
  49. div.setAttribute('desc', value);
  50. div.setAttribute('operation', 'load');
  51. div.click();
  52. if(div.getAttribute('state') != 'complete')
  53. this.show_error('Ошибка при загрузке значения');
  54.  
  55. return (div.getAttribute('is_null') == 'true' ? def : div.getAttribute('value'));
  56. };
  57.  
  58. //----------------------------------------------------------------------------//
  59.  
  60. this.check_login = function(){
  61. var re = /.*?pl_id=\d+?.*?/gmi;
  62.  
  63. if(!re.test(document.cookie.toString()))
  64. this.show_error('Пользователь не авторизован');
  65. };
  66.  
  67. //----------------------------------------------------------------------------//
  68.  
  69. this.check_login();
  70.  
  71. //----------------------------------------------------------------------------//
  72. } // wrapper end
  73.  
  74. //----------------------------------------------------------------------------//
  75. // CommonValues
  76. //----------------------------------------------------------------------------//
  77.  
  78. var GN_CommonValues = new CommonValues();
  79.  
  80. //----------------------------------------------------------------------------//
  81.  
  82. function CommonValues(){ // wrapper start
  83.  
  84. //----------------------------------------------------------------------------//
  85. // Elements
  86. //----------------------------------------------------------------------------//
  87.  
  88. this.elements = JSON.parse(SU.load_value('GN_CommonValues_Elements', '[]'));
  89. //----------------------------------------------------------------------------//
  90. } // wrapper end
  91.  
  92. //----------------------------------------------------------------------------//
  93. // GUIController
  94. //----------------------------------------------------------------------------//
  95.  
  96. var GN_GUIController = new GUIController();
  97.  
  98. //----------------------------------------------------------------------------//
  99.  
  100. function GUIController(){ // wrapper start
  101. //----------------------------------------------------------------------------//
  102. clear_flash_z_index();
  103. //----------------------------------------------------------------------------//
  104. this.script_name = function(){
  105. return 'GN_GUIController';
  106. };
  107. const script_name = this.script_name();
  108.  
  109. //----------------------------------------------------------------------------//
  110.  
  111. this.registerObject = function(object){
  112. root_div = document.getElementById(root.div.id);
  113. if(!root_div)
  114. root_div = create_node(root, document.body);
  115. else{
  116. var custom = root_div.getAttribute('custom').split('|');
  117. root.div.top = +custom[0];
  118. root.div.left = +custom[1];
  119. root.div.width = +custom[2];
  120. root.div.height = +custom[3];
  121. }
  122. object.div.left = root.div.left + left;
  123. object.div.top = top;
  124. var childs = root_div.childNodes;
  125. for(var i = 0; i < childs.length; ++i)
  126. if(childs[i].nodeName.toLowerCase() == 'div'){
  127. var height = +childs[i].getAttribute('custom').split('|')[3];
  128. object.div.top += height;
  129. }
  130. create_node(object, root_div);
  131. align_childs(root_div);
  132. collapse_childs(root_div);
  133. };
  134.  
  135. //----------------------------------------------------------------------------//
  136. this.hide_all = function(){
  137. if(!root_div)
  138. return;
  139. var childs = root_div.childNodes;
  140. for(var i = 0; i < childs.length; ++i)
  141. if(childs[i].nodeName.toLowerCase() == 'div')
  142. childs[i].style.top = +childs[i].getAttribute('custom').split('|')[0];
  143. align_childs(root_div);
  144. collapse_childs(root_div);
  145. };
  146.  
  147. var hide_all = this.hide_all;
  148.  
  149. //----------------------------------------------------------------------------//
  150.  
  151. const left = 10;
  152. const top = 10;
  153. var root = {
  154. div: {
  155. id: script_name + 'MainDiv',
  156. top: top,
  157. left: left,
  158. width: 0,
  159. height: 0
  160. },
  161.  
  162. input: {
  163. id: script_name + 'MainInput',
  164. value: 'Скрипты',
  165. title: 'Конфигурация и запуск скриптов, не относящихся к определенной странице'
  166. },
  167. child_divs: []
  168. };
  169. var root_div = document.getElementById(root.div.id);
  170. //----------------------------------------------------------------------------//
  171. function create_node(object, parent){
  172. var div_ = div(object.div);
  173. div_.setAttribute('expanded', 'false');
  174. parent.appendChild(div_);
  175. set_div_style(object.div);
  176. var input_ = input(object.input);
  177. div_.appendChild(input_);
  178. set_input_style(object.input);
  179. object.div.left += div_.clientWidth;
  180. object.div.width = div_.clientWidth;
  181. object.div.height = div_.clientHeight;
  182. var custom = [ object.div.top, object.div.left, object.div.width, object.div.height ];
  183. div_.setAttribute('custom', custom.join('|'));
  184. if(object.child_divs.length || object.div.id == root.div.id){
  185. input_.addEventListener('click', function(){
  186. expand_childs(div_);
  187. });
  188. create_child_nodes(object, div_);
  189. }
  190. return div_;
  191. }
  192.  
  193. //----------------------------------------------------------------------------//
  194. function create_child_nodes(object, parent){
  195. var childs = object.child_divs;
  196. for(var i = 0; i < childs.length; ++i){
  197. var child = childs[i];
  198. child.div.top = top;
  199. child.div.left = left;
  200. if(i){
  201. var total_height = 0;
  202. for(var j = 0; j < i; ++j){
  203. var sibling = childs[j];
  204. var sibling_div = document.getElementById(sibling.div.id);
  205. total_height += sibling_div.clientHeight;
  206. }
  207. child.div.top += total_height;
  208. }
  209. child.div.left += object.div.left;
  210. create_node(child, parent);
  211. }
  212. }
  213. //----------------------------------------------------------------------------//
  214.  
  215. function expand_childs(el){
  216. var now_expanded = (el.getAttribute('expanded') == 'true');
  217. if(now_expanded && el == root_div){
  218. hide_all();
  219. return;
  220. }
  221. var childs = el.childNodes;
  222.  
  223. for(var i = 0; i < childs.length; ++i)
  224. if(childs[i].nodeName.toLowerCase() == 'div')
  225. childs[i].style.display = !now_expanded ? 'block' : 'none';
  226. if(now_expanded){
  227. collapse_childs(el);
  228. if(el.parentNode == root_div){
  229. childs = root_div.childNodes;
  230.  
  231. for(i = 0; i < childs.length; ++i)
  232. if(childs[i].nodeName.toLowerCase() == 'div' && childs[i] != el)
  233. childs[i].style.display = 'block';
  234.  
  235. el.style.top = +el.getAttribute('custom').split('|')[0];
  236. el.style.width = +el.getAttribute('custom').split('|')[2];
  237. align_childs(root_div);
  238. }
  239. }
  240. if(!now_expanded && el.parentNode == root_div){
  241. childs = root_div.childNodes;
  242. for(i = 0; i < childs.length; ++i){
  243. if(childs[i].nodeName.toLowerCase() == 'div' && childs[i] != el)
  244. childs[i].style.display = 'none';
  245. }
  246. el.style.top = top;
  247. el.style.width = +el.getAttribute('custom').split('|')[2];
  248. }
  249. el.setAttribute('expanded', now_expanded ? 'false' : 'true');
  250. }
  251. //----------------------------------------------------------------------------//
  252. function align_childs(el){
  253. var max_width = 0;
  254. var childs = el.childNodes;
  255. for(var i = 0; i < childs.length; ++i)
  256. if(childs[i].nodeName.toLowerCase() == 'div'){
  257. var width = +childs[i].getAttribute('custom').split('|')[2];
  258.  
  259. if(width >= max_width)
  260. max_width = width;
  261. }
  262.  
  263. for(i = 0; i < childs.length; ++i)
  264. if(childs[i].nodeName.toLowerCase() == 'div')
  265. childs[i].style.width = max_width;
  266. }
  267. //----------------------------------------------------------------------------//
  268. function collapse_childs(el){
  269. var divs = el.querySelectorAll('div');
  270.  
  271. for(var i = 0; i < divs.length; ++i){
  272. divs[i].setAttribute('expanded', 'false');
  273. divs[i].style.display = 'none';
  274. }
  275. el.setAttribute('expanded', 'false');
  276. }
  277. //----------------------------------------------------------------------------//
  278.  
  279. function div(object){
  280. var div = document.createElement('div');
  281. div.setAttribute('id', object.id);
  282.  
  283. return div;
  284. }
  285. //----------------------------------------------------------------------------//
  286. function set_div_style(object){
  287. var div = document.getElementById(object.id);
  288. var style = div.style;
  289. style.position = 'fixed';
  290. style.top = object.top + 'px';
  291. style.left = object.left + 'px';
  292. style.zIndex = 100;
  293. }
  294. //----------------------------------------------------------------------------//
  295. function input(object){
  296. var input = document.createElement('input');
  297. input.type = 'button';
  298. input.id = object.id;
  299. input.value = object.value;
  300. input.title = object.title;
  301. return input;
  302. }
  303. //----------------------------------------------------------------------------//
  304. function set_input_style(object){
  305. var input = document.getElementById(object.id);
  306. var style = input.style;
  307. style.display = 'block';
  308. style.width = '95%';
  309. style.border = '1px solid rgb(153, 153, 153)';
  310. style.padding = '1px';
  311. style.margin = '2px';
  312. style.background = 'none repeat scroll 0% 0% rgb(204, 204, 204)';
  313. style.fontSize = '12px';
  314. style.cursor = 'pointer';
  315. style.zIndex = 100;
  316. }
  317. //----------------------------------------------------------------------------//
  318. function clear_flash_z_index(){
  319. var objects = document.querySelectorAll('object');
  320.  
  321. for(var i = 0; i < objects.length; ++i){
  322. var o = objects[i];
  323. var param = document.createElement('param');
  324. param.setAttribute('name', 'wmode');
  325. param.setAttribute('value', 'opaque');
  326.  
  327. o.insertBefore(param, o.firstChild);
  328. }
  329. }
  330.  
  331. //----------------------------------------------------------------------------//
  332. } // wrapper end
  333.  
  334. //----------------------------------------------------------------------------//
  335. // UnifiedLibrary end
  336. //----------------------------------------------------------------------------//
  337. var CV = GN_CommonValues;
  338. var elements = CV.elements;
  339.  
  340. var save_value = SU.save_value;
  341. var load_value = SU.load_value;
  342. var show_error = SU.show_error;
  343. var script_name = 'ElementPriceLoader';
  344. var GC = GN_GUIController;
  345. GC.registerObject(
  346. {
  347. div: { id: GC.script_name() + '_' + script_name + 'Div' },
  348.  
  349. input: {
  350. id: GC.script_name() + '_' + script_name + 'Input',
  351. value: 'Обновление цен элементов',
  352. title: 'Обновление цен элементов'
  353. },
  354.  
  355. child_divs: []
  356. }
  357. );
  358. var start_button = document.getElementById(GC.script_name() + '_' + script_name + 'Input');
  359. start_button.addEventListener('click', function(e){
  360. draw_div(document.body);
  361. });
  362.  
  363. //----------------------------------------------------------------------------//
  364. function draw_div(parent){
  365. var div = document.createElement('div');
  366. div.id = script_name + 'Div';
  367. div.style.position = 'fixed';
  368. div.style.display = 'block';
  369. div.style.top = start_button.parentNode.style.top;
  370. div.style.zIndex = 100;
  371. var left = /(\d+)px/.exec(start_button.parentNode.style.left);
  372. div.style.left = +left[1] + start_button.parentNode.clientWidth + 'px';
  373. div.style.width = '300px';
  374. div.style.background = start_button.style.backgroundColor;
  375. parent.appendChild(div);
  376.  
  377. draw_content(div);
  378. }
  379. //----------------------------------------------------------------------------//
  380. function draw_content(parent){
  381. var table = document.createElement('table');
  382. table.style.width = '100%';
  383. table.style.border = 'medium none';
  384. parent.appendChild(table);
  385. draw_header(table);
  386. elements.forEach(function(current){
  387. draw_row(table, current);
  388. });
  389. draw_buttons(table);
  390. }
  391. //----------------------------------------------------------------------------//
  392. function draw_header(parent){
  393. var upd_date = JSON.parse(load_value(script_name + '_LastUpdate', '0'));
  394. if(upd_date)
  395. upd_date = new Date(Date.parse(upd_date));
  396. var tr = document.createElement('tr');
  397. parent.appendChild(tr);
  398. var td = document.createElement('td');
  399. td.setAttribute('colspan', '4');
  400. td.id = script_name + '_LastUpdate';
  401. td.textContent = 'Дата последнего обновления: ' + (upd_date ? upd_date.toLocaleString() : 'еще не считывалось');
  402. tr.appendChild(td);
  403.  
  404. tr = document.createElement('tr');
  405. tr.setAttribute('bgColor', '#DCDCDC');
  406. parent.appendChild(tr);
  407. td = document.createElement('td');
  408. td.textContent = 'Наименование';
  409. tr.appendChild(td);
  410. td = document.createElement('td');
  411. td.textContent = 'Текущее значение';
  412. tr.appendChild(td);
  413. td = document.createElement('td');
  414. td.textContent = 'Новое значение';
  415. tr.appendChild(td);
  416. td = document.createElement('td');
  417. td.textContent = 'Разница';
  418. tr.appendChild(td);
  419. }
  420. //----------------------------------------------------------------------------//
  421. function draw_row(parent, object_){
  422. var tr = document.createElement('tr');
  423. tr.id = object_.id;
  424. parent.appendChild(tr);
  425. var td = document.createElement('td');
  426. td.textContent = object_.name + ':';
  427. tr.appendChild(td);
  428. td = document.createElement('td');
  429. td.textContent = object_.average_price;
  430. tr.appendChild(td);
  431. td = document.createElement('td');
  432. var input = document.createElement('input');
  433. input.type = 'text';
  434. input.style.width = 40;
  435. input.value = object_.average_price;
  436. input.onkeypress = number_input;
  437. input.addEventListener('input', function(e){
  438. show_difference(input);
  439. });
  440. td.appendChild(input);
  441. tr.appendChild(td);
  442. td = document.createElement('td');
  443. var font = document.createElement('font');
  444. font.color = 'black';
  445. font.textContent = 0;
  446. td.appendChild(font);
  447. tr.appendChild(td);
  448. }
  449. //----------------------------------------------------------------------------//
  450. function draw_buttons(parent){
  451. var tr = document.createElement('tr');
  452. parent.appendChild(tr);
  453. var td = document.createElement('td');
  454. td.setAttribute('align', 'right');
  455. td.setAttribute('colspan', '4');
  456. tr.appendChild(td);
  457. var button = document.createElement('input');
  458. button.type = 'button';
  459. button.value = 'Применить';
  460. button.addEventListener('click', function(e){
  461. save_prices();
  462. });
  463. td.appendChild(button);
  464. button = document.createElement('input');
  465. button.type = 'button';
  466. button.value = 'Обновить';
  467. button.addEventListener('click', function(e){
  468. load_prices();
  469. });
  470. td.appendChild(button);
  471. button = document.createElement('input');
  472. button.type = 'button';
  473. button.value = 'Отмена';
  474. button.addEventListener('click', function(e){
  475. remove_div();
  476. });
  477. td.appendChild(button);
  478. }
  479. //----------------------------------------------------------------------------//
  480. function save_prices(){
  481. var errors = [];
  482. var div = document.getElementById(script_name + 'Div');
  483. var trs = div.querySelectorAll('table > tr[id]');
  484.  
  485. for(var i = 0; i < trs.length; ++i){
  486. var input = trs[i].querySelector('input');
  487. if(isNaN(+input.value) || +input.value <= 0){
  488. errors.push('Цена элемента должна быть положительной');
  489. break;
  490. }
  491. }
  492.  
  493. if(errors.length){
  494. alert('Ошибки при сохранении:\n\n' + errors.join('\n'));
  495. return;
  496. }
  497. var el_prices = [];
  498. for(var i = 0; i < trs.length; ++i){
  499. var input = trs[i].querySelector('input');
  500. el_prices.push({ id: trs[i].id, price: input.value });
  501. }
  502.  
  503. save_value('GN_CommonValues_ElementPrices', JSON.stringify(el_prices));
  504. document.location = document.location;
  505. }
  506. //----------------------------------------------------------------------------//
  507. function load_prices(){
  508. document.body.style.cursor = 'wait';
  509. var xhr = new XMLHttpRequest();
  510. xhr.open('GET', '/auction.php?cat=elements&sort=0', true);
  511. xhr.overrideMimeType('text/plain; charset=windows-1251');
  512. xhr.onreadystatechange = function(){
  513. if(xhr.readyState == 4)
  514. if(xhr.status == 200){
  515. var objects = parse_page(xhr.response);
  516. objects = filter_objects(objects);
  517.  
  518. var div = document.getElementById(script_name + 'Div');
  519. objects.forEach(function(current){
  520. var tr = div.querySelector('table > tr[id="' + current.id + '"]');
  521.  
  522. if(tr){
  523. var input = tr.querySelector('input');
  524. input.value = Math.floor(current.sum/current.count);
  525. show_difference(input);
  526. }
  527. });
  528. var upd_date = new Date();
  529. var td = document.getElementById(script_name + '_LastUpdate');
  530. td.textContent = 'Дата последнего обновления: ' + upd_date.toLocaleString();
  531. save_value(script_name + '_LastUpdate', JSON.stringify(upd_date));
  532. document.body.style.cursor = 'default';
  533. }
  534. };
  535.  
  536. xhr.send(null);
  537. }
  538. //----------------------------------------------------------------------------//
  539. function parse_page(response){
  540. var all_objects = [];
  541. response = response.replace(/(\n(\r)?)/g, ' ');
  542. var re = /.*?(<tr bgcolor='#(?:ffffff|eeeeee)' class=wb>.+?gold.gif.+?show_button.+?<\/tr>).*?/gmi;
  543. var matches = [];
  544. while(matches = re.exec(response))
  545. {
  546. var el_re = /.+\/i\/(.+?)\.gif'.+?gold.gif.+?<td>([0-9,]+?)<\/td>.+?onclick=.+?/i;
  547. var el_matches = el_re.exec(matches[1]);
  548.  
  549. if(!el_matches)
  550. show_error('Ошибка при парсинге ' + matches[1]);
  551.  
  552. var object = {
  553. id: el_matches[1],
  554. price: +(el_matches[2].replace(/,/g, '')),
  555. count: 1
  556. };
  557.  
  558. var count_re = /.*<b>(\d+?) шт.<\/b>/i;
  559. var c_matches = count_re.exec(matches[1]);
  560. if(c_matches)
  561. object.count = +c_matches[1];
  562.  
  563. all_objects.push(object);
  564. }
  565. return all_objects;
  566. }
  567. //----------------------------------------------------------------------------//
  568. function filter_objects(objects){
  569. var el_objects = [];
  570. var step = 1.1;
  571. var max_count = 45;
  572.  
  573. objects.forEach(function(current){
  574. var el = get_object(current.id, el_objects);
  575. if(!el)
  576. el_objects.push({ id: current.id, max_price: current.price, sum: current.price*current.count, count: current.count });
  577. else{
  578. if(current.price >= el.max_price && current.price <= el.max_price*step)
  579. el.max_price = current.price;
  580. if(current.price <= el.max_price*step && el.count < max_count){
  581. el.count += current.count;
  582. el.sum += current.price*current.count;
  583. }
  584. }
  585. });
  586. return el_objects;
  587. }
  588. //----------------------------------------------------------------------------//
  589. function show_difference(input){
  590. var diff = +input.parentNode.previousSibling.textContent - +input.value;
  591. var font = input.parentNode.nextSibling.firstChild;
  592. font.color = diff == 0 ? 'black' : diff > 0 ? 'green' : 'red';
  593. font.textContent = diff;
  594. }
  595. //----------------------------------------------------------------------------//
  596. function get_object(id, array_){
  597. for(var i = 0; i < array_.length; ++i)
  598. if(array_[i].id == id)
  599. return array_[i];
  600.  
  601. return null;
  602. }
  603. //----------------------------------------------------------------------------//
  604. function remove_div(){
  605. var div = document.getElementById(script_name + 'Div');
  606. div.parentNode.removeChild(div);
  607. }
  608. //----------------------------------------------------------------------------//
  609. function get_char(e) {
  610. if(e.which && e.charCode){
  611. if(e.which < 32)
  612. return null;
  613. return String.fromCharCode(e.which)
  614. }
  615.  
  616. return null;
  617. }
  618. //----------------------------------------------------------------------------//
  619. function number_input(e){
  620. if(e.ctrlKey || e.altKey || e.metaKey)
  621. return false;
  622. var chr = get_char(e);
  623.  
  624. return chr == null || (chr >= '0' && chr <= '9');
  625. }
  626. //----------------------------------------------------------------------------//
  627. }()); // wrapper end
  628.  
  629. //----------------------------------------------------------------------------//