Advertisement
Guest User

Untitled

a guest
Jun 19th, 2019
88
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 19.58 KB | None | 0 0
  1. // ==UserScript==
  2. // @name Special Gym Ratios
  3. // @namespace RGiskard.hanksRatio
  4. // @version 2.3.1
  5. // @description Monitors battle stat ratios and provides warnings if they approach levels that would preclude access to special gyms
  6. // @author RGiskard [1953860], assistance by Xiphias [187717]
  7. // @include *.torn.com/gym.php*
  8. // @require http://code.jquery.com/jquery-latest.js
  9. // @grant none
  10. // ==/UserScript==
  11.  
  12. // Based off of Torn Gym Pony by Zanoab (http://puu.sh/jFtro/1af393771e.user.js).
  13.  
  14.  
  15. // Maximum amount below the stat limit another stat can be before we start warning the player.
  16. var statSafeDistance = localStorage.statSafeDistance;
  17. if (statSafeDistance === null) {
  18. statSafeDistance = 1000000;
  19. }
  20.  
  21.  
  22. // A second method, "Baldr's Ratio", is in this code, but the ability to select it has been
  23. // deliberately excluded for public release. This has been done for clarity, as there is
  24. // no accompanying information about what this ratio is. Those who would like to use it,
  25. // which unlocks a specialty gym that is one of the same stats as a combo gym
  26. // (e.g.: Frontline Fitness (str/spd) and Gym 3000 (str), can uncomment the lines of code
  27. // adding those options to $specialistGymBuild.
  28.  
  29.  
  30. jQuery.noConflict(true)(document).ready(function($) {
  31. var cleanNumber = function(a) {
  32. return Number(a.replace(/[$,]/g, "").trim());
  33. };
  34.  
  35. /**
  36. * Formats a number into an abbreviated string with an appropriate trailing descriptive unit
  37. * up to 't' for trillion.
  38. * @param {float} number the number to be formatted
  39. * @param {int} maxFractionDigits the maximum number of fractional digits to display
  40. * @returns a string representing the number, abbreviated if appropriate
  41. **/
  42. var FormatAbbreviatedNumber = function(number, maxFractionDigits) {
  43. var abbreviations = [];
  44. abbreviations[0] = '';
  45. abbreviations[1] = 'k';
  46. abbreviations[2] = 'm';
  47. abbreviations[3] = 'b';
  48. abbreviations[4] = 't';
  49.  
  50. var outputNumber = number;
  51. var abbreviationIndex = 0;
  52. for (; outputNumber >= 1000 && abbreviationIndex < abbreviations.length; ++abbreviationIndex) {
  53. outputNumber = outputNumber / 1000;
  54. }
  55.  
  56. return outputNumber.toLocaleString('EN', { maximumFractionDigits : maxFractionDigits }) + abbreviations[abbreviationIndex];
  57. };
  58.  
  59. var getStats = function($doc) {
  60. var ReplaceStatValueAndReturnCleanNumber = function(elementId) {
  61. var $statTotalElement = $doc.find('#' + elementId);
  62. if ($statTotalElement.size() === 0) throw 'No element found with id "' + elementId + '".';
  63. var numericalValue = cleanNumber($statTotalElement.text());
  64. return numericalValue;
  65. };
  66. $doc = $($doc || document);
  67. return {
  68. strength: ReplaceStatValueAndReturnCleanNumber('strength-val'),
  69. defense: ReplaceStatValueAndReturnCleanNumber('defense-val'),
  70. speed: ReplaceStatValueAndReturnCleanNumber('speed-val'),
  71. dexterity: ReplaceStatValueAndReturnCleanNumber('dexterity-val'),
  72. };
  73. };
  74.  
  75. var noBuildKeyValue = {value: 'none', text: 'No specialty gyms'};
  76. var defenseDexterityGymKeyValue = {value: 'balboas', text: 'Defense and dexterity specialist',
  77. stat1: 'defense', stat2: 'dexterity', secondarystat1: 'strength', secondarystat2: 'speed'};
  78. var strengthSpeedGymKeyValue = {value: 'frontline', text: 'Strength and speed specialist',
  79. stat1: 'strength', stat2: 'speed', secondarystat1: 'defense', secondarystat2: 'dexterity'};
  80. var strengthComboGymKeyValue = {value: 'frontlinegym3000', text: 'Strength combo specialist (Baldr\'s Ratio)', stat: 'strength', combogym: strengthSpeedGymKeyValue};
  81. var defenseComboGymKeyValue = {value: 'balboasisoyamas', text: 'Defense combo specialist (Baldr\'s Ratio)', stat: 'defense', combogym: defenseDexterityGymKeyValue};
  82. var speedComboGymKeyValue = {value: 'frontlinetotalrebound', text: 'Speed combo specialist (Baldr\'s Ratio)', stat: 'speed', combogym: strengthSpeedGymKeyValue};
  83. var dexterityComboGymKeyValue = {value: 'balboaselites', text: 'Dexterity combo specialist (Baldr\'s Ratio)', stat: 'dexterity', combogym: defenseDexterityGymKeyValue};
  84. var strengthGymKeyValue = {value: 'gym3000', text: 'Strength specialist (Hank\'s Ratio)', stat: 'strength', combogym: defenseDexterityGymKeyValue};
  85. var defenseGymKeyValue = {value: 'isoyamas', text: 'Defense specialist (Hank\'s Ratio)', stat: 'defense', combogym: strengthSpeedGymKeyValue};
  86. var speedGymKeyValue = {value: 'totalrebound', text: 'Speed specialist (Hank\'s Ratio)', stat: 'speed', combogym: defenseDexterityGymKeyValue};
  87. var dexterityGymKeyValue = {value: 'elites', text: 'Dexterity specialist (Hank\'s Ratio)', stat: 'dexterity', combogym: strengthSpeedGymKeyValue};
  88. function GetStoredGymKeyValuePair() {
  89. if (localStorage.specialistGymType == defenseDexterityGymKeyValue.value) return defenseDexterityGymKeyValue;
  90. if (localStorage.specialistGymType == strengthSpeedGymKeyValue.value) return strengthSpeedGymKeyValue;
  91. if (localStorage.specialistGymType == strengthComboGymKeyValue.value) return strengthComboGymKeyValue;
  92. if (localStorage.specialistGymType == defenseComboGymKeyValue.value) return defenseComboGymKeyValue;
  93. if (localStorage.specialistGymType == speedComboGymKeyValue.value) return speedComboGymKeyValue;
  94. if (localStorage.specialistGymType == dexterityComboGymKeyValue.value) return dexterityComboGymKeyValue;
  95. if (localStorage.specialistGymType == strengthGymKeyValue.value) return strengthGymKeyValue;
  96. if (localStorage.specialistGymType == defenseGymKeyValue.value) return defenseGymKeyValue;
  97. if (localStorage.specialistGymType == speedGymKeyValue.value) return speedGymKeyValue;
  98. if (localStorage.specialistGymType == dexterityGymKeyValue.value) return dexterityGymKeyValue;
  99. return noBuildKeyValue;
  100. }
  101.  
  102.  
  103. var $hanksRatioDiv = $('<div></div>');
  104. var $titleDiv = $('<div>', {'class': 'title-black top-round', 'aria-level': '5', 'text': 'Special Gym Ratios'})
  105. .css('margin-top', '10px');
  106. $hanksRatioDiv.append($titleDiv);
  107. var $bottomDiv = $('<div class="bottom-round gym-box cont-gray p10"></div>');
  108. $bottomDiv.append($('<p class="sub-title">Select desired specialist build:</p>'));
  109. var $specialistGymBuild = $('<select>', {'class': 'vinkuun-enemeyDifficulty'}).css('margin-top', '10px').on('change', function() {
  110. localStorage.specialistGymType = $specialistGymBuild.val();
  111. });
  112. $specialistGymBuild.append($('<option>', noBuildKeyValue));
  113. $specialistGymBuild.append($('<option>', defenseDexterityGymKeyValue));
  114. $specialistGymBuild.append($('<option>', strengthSpeedGymKeyValue));
  115. $specialistGymBuild.append($('<option>', strengthComboGymKeyValue));
  116. $specialistGymBuild.append($('<option>', defenseComboGymKeyValue));
  117. $specialistGymBuild.append($('<option>', speedComboGymKeyValue));
  118. $specialistGymBuild.append($('<option>', dexterityComboGymKeyValue));
  119. $specialistGymBuild.append($('<option>', strengthGymKeyValue));
  120. $specialistGymBuild.append($('<option>', defenseGymKeyValue));
  121. $specialistGymBuild.append($('<option>', speedGymKeyValue));
  122. $specialistGymBuild.append($('<option>', dexterityGymKeyValue));
  123. localStorage.specialistGymType = GetStoredGymKeyValuePair().value; // In case there is bad data, replace it.
  124. $specialistGymBuild.val(GetStoredGymKeyValuePair().value);
  125. $bottomDiv.append($specialistGymBuild);
  126. $hanksRatioDiv.append($bottomDiv);
  127. $('#gymroot').append($hanksRatioDiv);
  128.  
  129. var oldTotal = 0;
  130. var oldBuild = '';
  131. setInterval(function() {
  132. var stats = getStats();
  133. var total = 0;
  134. var highestSecondaryStat = 0;
  135. for (var stat in stats) {
  136. total += stats[stat];
  137. if (GetStoredGymKeyValuePair().stat && GetStoredGymKeyValuePair().stat != stat && stats[stat] > highestSecondaryStat) {
  138. highestSecondaryStat = stats[stat];
  139. }
  140. }
  141. var currentBuild = $specialistGymBuild.val();
  142.  
  143. if (oldTotal == total && oldBuild == currentBuild && $('.gymstatus').size() != 0) {
  144. return;
  145. }
  146.  
  147. var $statContainers = $('[class^="gymContent__"], [class*=" gymContent__"]').find('li');
  148.  
  149. if (currentBuild == noBuildKeyValue.value) {
  150. // Clear the training info in case it exists.
  151. $statContainers.each(function(index, element) {
  152. var $statInfoDiv = $(element).find('[class^="description__"], [class*=" description__"]');
  153. var $insertedElement = $statInfoDiv.find('.gymstatus');
  154. $insertedElement.remove();
  155. });
  156. return;
  157. }
  158.  
  159. var isComboGymOnlyRatio = (
  160. localStorage.specialistGymType == defenseDexterityGymKeyValue.value ||
  161. localStorage.specialistGymType == strengthSpeedGymKeyValue.value);
  162. var isComboGymCombinedRatio = (
  163. localStorage.specialistGymType == strengthComboGymKeyValue.value ||
  164. localStorage.specialistGymType == defenseComboGymKeyValue.value ||
  165. localStorage.specialistGymType == speedComboGymKeyValue.value ||
  166. localStorage.specialistGymType == dexterityComboGymKeyValue.value);
  167. var isSingleGymRatio = (
  168. localStorage.specialistGymType == strengthGymKeyValue.value ||
  169. localStorage.specialistGymType == defenseGymKeyValue.value ||
  170. localStorage.specialistGymType == speedGymKeyValue.value ||
  171. localStorage.specialistGymType == dexterityGymKeyValue.value);
  172.  
  173. // The combined total of the primary stats must be 25% higher than the total of the secondary stats.
  174. var minPrimaryComboSum = 0; // The minimum amount the combined primary stats must be to unlock the gym based on the secondary stat sum.
  175. var maxSecondaryComboSum = 0; // The maximum amount the combined secondary stats must be to unlock the gym based on the primary stat sum.
  176. // The primary stat needs to be 25% higher than the second highest stat.
  177. var minPrimaryStat = 0;
  178. var maxSecondaryStat = 0;
  179. var comboGymKeyValuePair = noBuildKeyValue;
  180. var primaryGymKeyValuePair = noBuildKeyValue;
  181. if (isComboGymOnlyRatio) {
  182. comboGymKeyValuePair = GetStoredGymKeyValuePair();
  183. } else if (isComboGymCombinedRatio || isSingleGymRatio) {
  184. primaryGymKeyValuePair = GetStoredGymKeyValuePair();
  185. comboGymKeyValuePair = primaryGymKeyValuePair.combogym;
  186. minPrimaryStat = highestSecondaryStat * 1.25;
  187. maxSecondaryStat = stats[primaryGymKeyValuePair.stat] / 1.25;
  188. } else {
  189. console.debug('Somehow attempted to calculate stat requirements for invalid gym: ' + GetStoredGymKeyValuePair());
  190. return;
  191. }
  192. minPrimaryComboSum = (stats[comboGymKeyValuePair.secondarystat1] + stats[comboGymKeyValuePair.secondarystat2]) * 1.25;
  193. maxSecondaryComboSum = (stats[comboGymKeyValuePair.stat1] + stats[comboGymKeyValuePair.stat2]) / 1.25;
  194.  
  195. var distanceFromComboGymMin = minPrimaryComboSum - stats[comboGymKeyValuePair.stat1] - stats[comboGymKeyValuePair.stat2];
  196. var distanceToComboGymMax = maxSecondaryComboSum - stats[comboGymKeyValuePair.secondarystat1] - stats[comboGymKeyValuePair.secondarystat2];
  197.  
  198. $statContainers.each(function(index, element) {
  199. var $element = $(element);
  200. var title = $element.find('[class^="title__"], [class*=" title__"]');
  201. var stat = $element.attr('zStat');
  202. if (!stat) {
  203. stat = title.text().toLowerCase();
  204. $element.attr('zStat', stat);
  205. }
  206. if (stats[stat]) {
  207. var gymStatus;
  208. var statIdentifierString;
  209. if (isComboGymOnlyRatio) {
  210. if (stat == comboGymKeyValuePair.stat1 || stat == comboGymKeyValuePair.stat2) {
  211. statIdentifierString = GetStatAbbreviation(comboGymKeyValuePair.stat1).capitalizeFirstLetter() +
  212. ' + ' + GetStatAbbreviation(comboGymKeyValuePair.stat2);
  213. if (distanceFromComboGymMin > 0) {
  214. gymStatus = '<span class="gymstatus t-red bold">' + statIdentifierString + ' is ' + FormatAbbreviatedNumber(distanceFromComboGymMin, 1) + ' too low!</span>';
  215. } else if (distanceFromComboGymMin < statSafeDistance) {
  216. gymStatus = '<span class="gymstatus t-red bold">' + statIdentifierString + ' is ' + FormatAbbreviatedNumber(-distanceFromComboGymMin, 1) + ' above the limit.</span>';
  217. } else {
  218. gymStatus = '<span class="gymstatus t-green">' + statIdentifierString + ' is ' + FormatAbbreviatedNumber(-distanceFromComboGymMin, 1) + ' above the limit.</span>';
  219. }
  220. } else {
  221. statIdentifierString = GetStatAbbreviation(comboGymKeyValuePair.secondarystat1).capitalizeFirstLetter() +
  222. ' + ' + GetStatAbbreviation(comboGymKeyValuePair.secondarystat2);
  223. if (distanceToComboGymMax < 0) {
  224. gymStatus = '<span class="gymstatus t-red bold">' + statIdentifierString + ' is ' + FormatAbbreviatedNumber(-distanceToComboGymMax, 1) + ' too high!</span>';
  225. } else if (distanceToComboGymMax < statSafeDistance) {
  226. gymStatus = '<span class="gymstatus t-red bold">' + statIdentifierString + ' is ' + FormatAbbreviatedNumber(distanceToComboGymMax, 1) + ' below the limit.</span>';
  227. } else {
  228. gymStatus = '<span class="gymstatus t-green">' + statIdentifierString + ' is ' + FormatAbbreviatedNumber(distanceToComboGymMax, 1) + ' below the limit.</span>';
  229. }
  230. }
  231. } else {
  232. var distanceFromSpecialistGymMin = minPrimaryStat - stats[stat];
  233. var distanceToSpecialistGymMax = maxSecondaryStat - stats[stat];
  234.  
  235. var distanceToMax = 0;
  236. statIdentifierString = stat.capitalizeFirstLetter();
  237. if (stat == primaryGymKeyValuePair.stat) {
  238. if (distanceFromSpecialistGymMin <= 0) {
  239. if (isSingleGymRatio) {
  240. // Specialist stat for Hank's Gym Ratio is never one of the primary combo stats.
  241. // Only set the identifier if we don't already know this stat is too low to unlock its own specific gym.
  242. distanceToMax = distanceToComboGymMax;
  243. if (distanceToMax < 0) {
  244. statIdentifierString = GetStatAbbreviation(comboGymKeyValuePair.secondarystat1).capitalizeFirstLetter() +
  245. ' + ' + GetStatAbbreviation(comboGymKeyValuePair.secondarystat2);
  246. }
  247. } else {
  248. // Specialist stat IS the combo stat; we only care to show how it's doing in relation to the specialist gym.
  249. distanceToMax = distanceFromSpecialistGymMin;
  250. }
  251. }
  252. } else if (stat == comboGymKeyValuePair.stat1 || stat == comboGymKeyValuePair.stat2) {
  253. // We don't have to worry about this stat going too high for the combo gym.
  254. distanceToMax = distanceToSpecialistGymMax;
  255. } else {
  256. // This stat is neither the primary stat nor a combo gym stat, so it's limited by both.
  257. distanceToMax = Math.min(distanceToSpecialistGymMax, distanceToComboGymMax);
  258. if (distanceToComboGymMax < distanceToSpecialistGymMax && distanceToMax < 0) {
  259. statIdentifierString = GetStatAbbreviation(comboGymKeyValuePair.secondarystat1).capitalizeFirstLetter() +
  260. ' + ' + GetStatAbbreviation(comboGymKeyValuePair.secondarystat2);
  261. }
  262. }
  263.  
  264. if (stat == primaryGymKeyValuePair.stat) {
  265. console.debug(stat + ' distanceFromSpecialistGymMin: ' + distanceFromSpecialistGymMin);
  266. console.debug(stat + ' distanceToComboGymMax: ' + distanceToComboGymMax);
  267. } else if (stat == comboGymKeyValuePair.stat1 || stat == comboGymKeyValuePair.stat2) {
  268. console.debug(stat + ' distanceToSpecialistGymMax: ' + distanceToSpecialistGymMax);
  269. console.debug(stat + ' distanceFromComboGymMin: ' + distanceFromComboGymMin);
  270. } else {
  271. console.debug(stat + ' distanceToSpecialistGymMax: ' + distanceToSpecialistGymMax);
  272. console.debug(stat + ' distanceToComboGymMax: ' + distanceToComboGymMax);
  273. }
  274. console.debug(stat + ' distanceToMax: ' + distanceToMax);
  275.  
  276. if (stat == primaryGymKeyValuePair.stat && distanceFromSpecialistGymMin > 0) {
  277. gymStatus = '<span class="gymstatus t-red bold">' + statIdentifierString + ' is ' + FormatAbbreviatedNumber(distanceFromSpecialistGymMin, 1) + ' too low!</span>';
  278. } else if (distanceToMax < 0) {
  279. if (stat == primaryGymKeyValuePair.stat && isComboGymCombinedRatio) {
  280. gymStatus = '<span class="gymstatus t-green">' + statIdentifierString + ' is ' + FormatAbbreviatedNumber(-distanceToMax, 1) + ' above the limit.</span>';
  281. } else {
  282. gymStatus = '<span class="gymstatus t-red bold">' + statIdentifierString + ' is ' + FormatAbbreviatedNumber(-distanceToMax, 1) + ' too high!</span>';
  283. }
  284. } else if (distanceToMax < statSafeDistance) {
  285. gymStatus = '<span class="gymstatus t-red bold">' + statIdentifierString + ' is ' + FormatAbbreviatedNumber(distanceToMax, 1) + ' below the limit.</span>';
  286. } else {
  287. gymStatus = '<span class="gymstatus t-green">' + statIdentifierString + ' is ' + FormatAbbreviatedNumber(distanceToMax, 1) + ' below the limit.</span>';
  288. }
  289. }
  290.  
  291. var $statInfoDiv = $element.find('[class^="description__"], [class*=" description__"]');
  292. var $insertedElement = $statInfoDiv.find('.gymstatus');
  293. $insertedElement.remove();
  294. $statInfoDiv.append(gymStatus);
  295. }
  296. });
  297. oldTotal = total;
  298. oldBuild = currentBuild;
  299. console.debug("Stat spread updated!");
  300. }, 400);
  301. });
  302.  
  303.  
  304. String.prototype.capitalizeFirstLetter = function() {
  305. return this.charAt(0).toUpperCase() + this.slice(1);
  306. };
  307.  
  308.  
  309. function GetStatAbbreviation(statString) {
  310. if (statString == 'strength') {
  311. return 'str';
  312. } else if (statString == 'defense') {
  313. return 'def';
  314. } else if (statString == 'speed') {
  315. return 'spd';
  316. } else if (statString == 'dexterity') {
  317. return 'dex';
  318. }
  319. return statString;
  320. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement