Busting reminder

Guess how many busts you can do without getting jailed

  1. // ==UserScript==
  2. // @name Busting reminder
  3. // @namespace http://torn.city.com.dot.com.com
  4. // @version 0.7.2
  5. // @description Guess how many busts you can do without getting jailed
  6. // @author Adobi
  7. // @match https://www.torn.com/*
  8. // @grant GM_setValue
  9. // @grant GM_getValue
  10. // @license MIT
  11. // ==/UserScript==
  12.  
  13. (function() {
  14. 'use strict';
  15.  
  16. ////// USER DEFINED VARIABLES
  17. let maxScore = 0; // If set to 0, script will determine your max bust capacity based on log.
  18. // END OF USER DEFINED VARIABLES
  19.  
  20. function findLongestSequence(timestampArray) {
  21. const period = 24 * 60 * 60 * 3
  22. let longestSequence = 0;
  23. let currentSequence = 1;
  24. let currentMin = timestampArray[0];
  25. let currentMax = timestampArray[0];
  26. let firstTimestamp = 0;
  27.  
  28. for (let i = 1; i < timestampArray.length; i++) {
  29. const TS = timestampArray[i];
  30. if ((currentMin - TS) <= period && (currentMax - TS) <= period) {
  31. currentSequence++;
  32. currentMin = Math.min(currentMin, TS);
  33. currentMax = Math.max(currentMax, TS);
  34. } else {
  35. if (longestSequence < currentSequence) { firstTimestamp = currentMin; }
  36. longestSequence = Math.max(longestSequence, currentSequence);
  37. currentSequence = 1;
  38. currentMin = TS;
  39. currentMax = TS;
  40. }
  41. }
  42. console.log(firstTimestamp)
  43.  
  44. /*
  45. let score = 0;
  46. let localScore = 0
  47.  
  48. for (let i = 0; i < timestampArray.length; i++) {
  49. if (firstTimestamp <= timestampArray[i]) {
  50. const hours = (timestampArray[i] - firstTimestamp) / 60 / 60;
  51. const tenHours = hours / 7.2;
  52. if (hours <= 72) {
  53. localScore = 128 / Math.pow(2, tenHours);
  54. score += localScore;
  55. console.log(hours + " - " + localScore)
  56. }
  57. }
  58. } */
  59. let currentMaxScore = 0;
  60. for (let i = 0; i < timestampArray.length - longestSequence; i++) {
  61. let score = 0;
  62. let localScore = 0
  63. const initial_timestamp = timestampArray[i];
  64. for (let j = 0; j < longestSequence; j++) {
  65. const hours = (initial_timestamp - timestampArray[i+j]) / 60 / 60;
  66. const tenHours = hours / 7.2;
  67. localScore = 128 / Math.pow(2, tenHours);
  68. score += localScore;
  69. }
  70. currentMaxScore = Math.max(currentMaxScore, score);
  71. }
  72. return [Math.max(longestSequence, currentSequence), currentMaxScore];
  73. }
  74.  
  75.  
  76.  
  77. // Function to create and display yellow square with the option to enter API key
  78. function displayYellowSquare() {
  79. const yellowSquare = document.createElement('div');
  80. yellowSquare.id = 'yellowSquare';
  81. yellowSquare.style.position = 'fixed';
  82. yellowSquare.style.left = '0';
  83. yellowSquare.style.top = '0';
  84. yellowSquare.style.color = 'black';
  85. yellowSquare.style.top = '100px';
  86. yellowSquare.style.width = '100px';
  87. yellowSquare.style.height = '100px';
  88. yellowSquare.style.backgroundColor = 'yellow';
  89. yellowSquare.style.zIndex = '99999999';
  90. yellowSquare.style.display = 'flex'; // Use flexbox for centering
  91. yellowSquare.style.cursor = 'pointer'; // Change cursor to pointer
  92.  
  93. // Create a container div for centered text
  94. const textContainer = document.createElement('div');
  95. textContainer.style.margin = 'auto'; // Center horizontally
  96. textContainer.style.textAlign = 'center'; // Center text
  97. textContainer.style.display = 'flex';
  98. textContainer.style.flexDirection = 'column'; // Center vertically
  99.  
  100. // Create text nodes for the yellow square with a line break
  101. const yellowTextNode0 = document.createTextNode('Busting reminder');
  102. const lineBreak = document.createElement('br');
  103. const yellowTextNode1 = document.createTextNode('Click here to supply full access API key');
  104.  
  105.  
  106. // Append the text nodes and line break to the text container
  107. textContainer.appendChild(yellowTextNode0);
  108. textContainer.appendChild(lineBreak);
  109. textContainer.appendChild(yellowTextNode1);
  110.  
  111. // Append the text container to the yellow square
  112. yellowSquare.appendChild(textContainer);
  113.  
  114. // Append the yellow square to the body (if it's not already added)
  115. if (!document.getElementById('yellowSquare')) {
  116. document.body.appendChild(yellowSquare);
  117. }
  118.  
  119. // Add a click event listener to the yellow square
  120. yellowSquare.addEventListener('click', () => {
  121. const apiKey = prompt('Enter your full access API key:');
  122. if (apiKey) {
  123. // Store the API key with GM_setValue
  124. GM_setValue('busting_api_key', apiKey);
  125. yellowSquare.remove(); // Remove the yellow square after entering the API key
  126. fetchAndDisplayData(); // Run an API call with the new key
  127. }
  128. });
  129. }
  130.  
  131. // Function to fetch API data
  132. function fetchAndDisplayData() {
  133. const currentTime = Date.now()/1000;
  134. const apiKey = GM_getValue('busting_api_key', '');
  135. // If the API key is not stored, display the yellow square
  136. if (!apiKey) {
  137. displayYellowSquare();
  138. return;
  139. }
  140. const url = `https://api.torn.com/user/?selections=log&log=5360&key=${apiKey}`
  141. const timestamps = [];
  142. let mostBustsIn72h = 0;
  143. let last24h = 0;
  144. let last72h = 0;
  145. fetch(url)
  146. .then(response => response.json())
  147. .then(data => {
  148. if (data.error) {
  149. if (data.error.error === "Incorrect key" || data.error.error === "Access level of this key is not high enough") {
  150. GM_setValue('busting_api_key', "");
  151. displayYellowSquare();
  152. } else { return; }
  153. } else {
  154. // Counts how many busts you've done in last 72h and 24h.
  155. let score = 0;
  156. let localScore = 0
  157. for (const entry in data['log']) {
  158. timestamps.push(data['log'][entry]['timestamp']);
  159. const hours = (currentTime - data['log'][entry]['timestamp']) / 60 / 60;
  160. const tenHours = hours / 7.2;
  161. if (hours <= 72) {
  162. localScore = 128 / Math.pow(2, tenHours);
  163. score += localScore;
  164. }
  165. if (data['log'][entry]['timestamp'] > currentTime - 24 * 60 * 60 * 3) {
  166. last72h++;
  167. if (data['log'][entry]['timestamp'] > currentTime - 24 * 60 * 60) {
  168. last24h++;
  169. }
  170. }
  171. }
  172.  
  173. if (maxScore === 0) {
  174. const sequenceAndScore = findLongestSequence(timestamps);
  175. mostBustsIn72h = sequenceAndScore[0];
  176. maxScore = Math.floor(sequenceAndScore[1]);
  177. }
  178. const currentAvailableBusts = (maxScore - score) / 128;
  179. console.log(score.toFixed(0) + " current bust score out of a maximum " + maxScore + ", " + currentAvailableBusts.toFixed(2) + " busts available.");
  180.  
  181. let jailLink = document.querySelector('div#nav-jail');
  182. let jailLinkText = jailLink.querySelector('.linkName___FoKha');
  183.  
  184. // Check if there's an existing text element and remove it
  185. let existingTextElement = jailLinkText.parentNode.querySelector('.bust-guesser');
  186. if (existingTextElement) {
  187. existingTextElement.remove();
  188. }
  189.  
  190. const newSpan = document.createElement('p');
  191. newSpan.className = 'linkName___FoKha bust-guesser';
  192. newSpan.style.color = 'red';
  193. if (currentAvailableBusts <= 0) { newSpan.style.color = 'green'; }
  194. newSpan.style.float = 'right';
  195. newSpan.style.paddingRight = '5px';
  196. newSpan.textContent = Math.floor(score) + "/" + maxScore + ": " + Math.floor(currentAvailableBusts);
  197. jailLinkText.parentNode.appendChild(newSpan);
  198. }
  199. });
  200. }
  201.  
  202. fetchAndDisplayData()
  203. setInterval(fetchAndDisplayData, 10 * 60 * 1000);
  204. //displayYellowSquare() //debugging
  205. })();