Warcraft Logs Enhancement

Some Enhancement Scripts of Warcraft Logs

当前为 2017-07-20 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name Warcraft Logs Enhancement
  3. // @namespace https://github.com/icyblade/warcraftlogs_enhancement
  4. // @version 1.0
  5. // @description Some Enhancement Scripts of Warcraft Logs
  6. // @author swqsldz, kingofpowers, icyblade
  7. // @match https://*.warcraftlogs.com/*
  8. // @run-at document-idle
  9. // ==/UserScript==
  10. const PRESTIGE_SPELL_ID = 239042; // Concordance of the Legionfall
  11. const columnNames = ['Artifact', 'Prestige', 'MainStat', 'Crit', 'Haste', 'Mastery', 'Versatility'];
  12. const attributes = ['Prestige', 'MainStat', 'Crit', 'Haste', 'Mastery', 'Versatility'];
  13. const regex = /\/reports\/([\S\s]+?)#fight=([0-9]+)/;
  14.  
  15. const attrToPercent = {
  16. 0: {
  17. 'Crit': 5,
  18. 'perCrit': 400,
  19. 'Haste': 0,
  20. 'perHaste': 375,
  21. 'Mastery': 8,
  22. 'perMastery': 712,
  23. 'Versatility': 0,
  24. 'perVersatility': 475
  25. },
  26. 63: {
  27. 'Crit': 20,
  28. 'Mastery': 6,
  29. 'perMastery': 533.1
  30. }
  31. };
  32.  
  33. const HOST = 'https://' + window.location.hostname;
  34.  
  35.  
  36. var PlayerList = new Array();
  37.  
  38. function initialize() {
  39. 'use strict';
  40.  
  41. // initialize attribute columns
  42. for (let i = 0; i < columnNames.length; i++) {
  43. $('<th class="sorting ui-state-default">' + columnNames[i] + '</th>').insertBefore('th.zmdi.zmdi-flag.sorting.ui-state-default');
  44. }
  45. for (let i = 0; i < columnNames.length; i++) {
  46. $('<td class="' + columnNames[i] + '"></td>').insertBefore('td.zmdi.zmdi-flag');
  47. }
  48.  
  49. // extract fights from ranking page
  50. $('td.unique-gear').parent().each(function() {
  51. var player = new Object();
  52.  
  53. player.rowID = $(this).attr('id');
  54. player.name = $(this).find('.players-table-name .main-table-player').text();
  55.  
  56. var href = $(this).find('.players-table-name .main-table-player').attr('href');
  57. if (typeof(href) == 'undefined') {
  58. return;
  59. }
  60. player.logID = href.match(regex)[1];
  61. player.fightID = href.match(regex)[2];
  62.  
  63. PlayerList.push(player);
  64. });
  65. }
  66.  
  67. function loadPlayerSummary(index) {
  68. $.ajax({
  69. type: 'GET',
  70. url: HOST+'/reports/summary/' + PlayerList[index].logID + '/' + PlayerList[index].fightID + '/' + PlayerList[index].timestamp + '/' + (PlayerList[index].timestamp + 3000) + '/' + PlayerList[index].sourceID + '/0/Any/0/-1.0.-1/0',
  71. dataType: 'text',
  72. success: function(data) {
  73. callback_playerSummary(data, index);
  74. }
  75. });
  76. }
  77.  
  78. function callback_playerSummary(data, index) {
  79. var summary = new Array();
  80.  
  81. // handle main and enhancement attributes
  82. var regex_attr = /<span class="composition-entry">([a-zA-Z]+): <span class=estimate><span class=estimate>([0-9\,]+)<\/span>/g;
  83.  
  84. while ((stat = regex_attr.exec(data)) != null) {
  85. switch (stat[1]) {
  86. case 'Strength':
  87. case 'Agility':
  88. case 'Intellect':
  89. summary['MainStat'] = stat[2];
  90. break;
  91. case 'Crit':
  92. summary['Crit'] = stat[2];
  93. break;
  94. case 'Haste':
  95. summary['Haste'] = stat[2];
  96. break;
  97. case 'Mastery':
  98. summary['Mastery'] = stat[2];
  99. break;
  100. case 'Versatility':
  101. summary['Versatility'] = stat[2];
  102. break;
  103. case 'Stamina':
  104. break;
  105. default:
  106. break;
  107. }
  108. }
  109.  
  110. // handle artifact
  111. var regex_trait = /<a target="_new" href="\/\/www.wowhead.com\/spell=([0-9]+)\?rank=[0-9]+"[^<]+<img src="([^"]+)"[^<]+<span[^<]+<\/span[^<]+<\/a[^<]+<td class="primary rank">([0-9]+)<\/td[^<]+<\/tr>/g;
  112.  
  113. var relicnum = 0;
  114. while ((trait = regex_trait.exec(data)) != null) {
  115. if (trait[3] > 4 && trait[1] != PRESTIGE_SPELL_ID) {
  116. var t = trait[3];
  117. var spid = {
  118. 'spellid': trait[1],
  119. 'img': trait[2]
  120. };
  121. if (typeof(summary['relic']) == 'undefined') {
  122. summary['relic'] = new Array();
  123. }
  124. while (t > 4) {
  125. t--;
  126. relicnum++;
  127. summary['relic'].push(spid);
  128. }
  129. }
  130. if (trait[1] == PRESTIGE_SPELL_ID) {
  131. summary['Prestige'] = trait[3];
  132. }
  133. }
  134.  
  135. // handle items
  136. var regex_item = /<td class="primary rank">([0-9]+)<\/td[^<]+<td nowrap class="num">(Trinket|Weapon)<td [^<]+<a target="_new" href="\/\/legion.wowhead.com\/item=([0-9]+)" rel="(?:(?:[^"]+|)bonus=([0-9:]+);|)"/g;
  137.  
  138. var trinketnum = 0;
  139. while ((item = regex_item.exec(data)) != null) {
  140. if (item[2] == 'Trinket') {
  141. trinketnum++;
  142. summary['Trinket' + trinketnum] = {
  143. 'id': item[3],
  144. 'level': item[1],
  145. 'bonus': item[4] || ""
  146. };
  147. } else {
  148. summary['WeaponLevel'] = item[1];
  149. }
  150. }
  151. PlayerList[index].summary = summary;
  152. updateRowSummary(index);
  153. }
  154.  
  155. function updateRowSummary(index) {
  156.  
  157. try {
  158. relics = '';
  159. if (typeof(PlayerList[index].summary['relic']) != 'undefined') {
  160. $.each(PlayerList[index].summary['relic'], function(i, relic) {
  161. relics += '<a target="_new" href="//www.wowhead.com/spell=' + relic['spellid'] + '"><img src="' + relic['img'] + '" class="tiny-icon"></a>';
  162. });
  163. }
  164. $('#' + PlayerList[index].rowID + ' .Artifact').html('<div style="align-items: center;justify-content: space-between;display: flex;">' + PlayerList[index].summary['WeaponLevel'] + ':' + relics + '</div>');
  165. for (let i = 0; i < attributes.length; i++) {
  166. $('#' + PlayerList[index].rowID + ' .' + attributes[i]).html(PlayerList[index].summary[attributes[i]]);
  167. }
  168.  
  169. //Trinket
  170. var regex_tditem = /wowhead.com\/item=([0-9]+)/;
  171. for (let trinketid = 1; trinketid <= 2; trinketid++) {
  172. if (typeof(PlayerList[index].summary['Trinket' + trinketid]) != 'undefined') {
  173. $('#' + PlayerList[index].rowID + '>.unique-gear>div>a[href$="item=' + PlayerList[index].summary['Trinket' + trinketid]['id'] + '"]').each(
  174. function(i, a) {
  175. $(a).html($(a).html() + '<span style="position: absolute; bottom: -6px; text-shadow: -2px 0 black, 0 2px black, 2px 0 black, 0 -2px black;">' + PlayerList[index].summary['Trinket' + trinketid]['level'] + '</span>');
  176. $(a).attr('href', a.href + '&bonus=' + PlayerList[index].summary['Trinket' + trinketid]['bonus']);
  177. $(a).css('position', 'relative');
  178. }
  179. );
  180. }
  181. }
  182. } catch (e) {
  183. console.error(e);
  184. console.error(PlayerList[index]);
  185. }
  186. }
  187.  
  188. function loadFights(index) {
  189. $.ajax({
  190. type: 'GET',
  191. url: HOST + '/reports/fights_and_participants/' + PlayerList[index].logID + '/0',
  192. dataType: 'json',
  193. success: function(data) {
  194. callback_fights(data, index);
  195. }
  196. });
  197. }
  198.  
  199. function callback_stats(data, rowID, logID, fightID, timestamp, sourceID) {
  200. for (var key in columnNames) {
  201. try {
  202. $('#' + rowID + ' .attr-' + columnNames[key]).html(data.events[0][columnNames[key]]);
  203. } catch (e) {
  204. console.error(e);
  205. console.error(rowID);
  206. console.error(data);
  207. }
  208. }
  209. }
  210.  
  211. function callback_fights(data, idx) {
  212. 'use strict';
  213. PlayerList[idx].fight = data;
  214.  
  215. for (let j in PlayerList[idx].fight.friendlies) {
  216. if (PlayerList[idx].fight.friendlies[j].name == PlayerList[idx].name) {
  217. PlayerList[idx].sourceID = PlayerList[idx].fight.friendlies[j].id;
  218. break;
  219. }
  220. }
  221.  
  222. for (let j in PlayerList[idx].fight.fights) {
  223. if (PlayerList[idx].fight.fights[j].id == PlayerList[idx].fightID) {
  224. PlayerList[idx].timestamp = PlayerList[idx].fight.fights[j].start_time;
  225. break;
  226. }
  227. }
  228.  
  229. loadPlayerSummary(idx);
  230. idx++;
  231.  
  232. if (idx >= PlayerList.length) {
  233. return;
  234. }
  235.  
  236. loadFights(idx);
  237. }
  238.  
  239. function loadAttributes() {
  240. initialize();
  241. loadFights(0);
  242. }
  243.  
  244. function delayLoadAttributes() {
  245. if ($('.ranking-table tr:eq(1)').length === 0) {
  246. setTimeout(delayLoadAttributes, 1000);
  247. } else {
  248. loadAttributes();
  249. }
  250. }
  251.  
  252. delayLoadAttributes();