DripStat DropOut

Calculates stats in DripStat, and provides a control panel for automation.

当前为 2014-06-22 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name DripStat DropOut
  3. // @namespace anonycat
  4. // @version 0.5.303
  5. // @description Calculates stats in DripStat, and provides a control panel for automation.
  6. // @match https://dripstat.com/game/
  7. // @grant none
  8. // ==/UserScript==
  9.  
  10. //Throttle auto purchases to one every 5 seconds, to minimize risk of desyncs with the server
  11. var lastBuy = 0;
  12.  
  13. //Track how many manual clicks have been made by second over the last 60 seconds
  14. var clickHistory = [];
  15. while (lastBuy < 60)
  16. {clickHistory[lastBuy++] = 0;}
  17. var oldByteCount = 0;
  18. var first = 1;
  19.  
  20. function init()
  21. {
  22. //Should powerups and upgrades be automatically purchased as they become affordable?
  23. //(As of level 5, also includes facilities for grabbing spring beans that appear)
  24. crypto.autoPurchase=0;
  25. //Should the BPS rate be increased to simulate automatic cup clicks?
  26. crypto.autoClick=0;
  27. //Should memory automatically be dripped?
  28. //0 = no auto-drip, 1 = auto-drip when buffer is full, 2 = auto-drip as needed to create enough space to pay for upgrades
  29. crypto.autoDrip=0;
  30.  
  31. //Should we take manual clicks into account when figuring out the payback rate of powerups?
  32. crypto.clickRate=1;
  33.  
  34. //If autoclicking is enabled, each second will pick a random multiplier and count off that many cup clicks.
  35. //A multiplier of 0 means no clicking, only natural BPS intake.
  36. //Multipliers greater than 20 are rejected by the server, so we won't ever generate such a thing here.
  37. //Lowest possible multiplier to select
  38. crypto.cupmultl = 0;
  39. //Average multiplier
  40. crypto.cupmultm = 5;
  41. //There is no variable for the highest multiplier; it's automatically figured as 2*Middle - Low (but capped at 20).
  42. //Keep track of the original names and descriptions
  43. localStats.powerUps.slice(0).forEach(function(powerUp){
  44. powerUp.upgrades.forEach(function(upgrade){
  45. upgrade.originalName = upgrade.name;
  46. upgrade.originalDesc = upgrade.desc;
  47. });
  48. powerUp.originalName = powerUp.name;
  49. powerUp.originalDesc = powerUp.desc;
  50. });
  51. //string (int) seconds to formatted time
  52. String.prototype.toHHMMSS = function () {
  53. var seconds = parseInt(this, 10); // don't forget the second param
  54. if(seconds <= 0)
  55. return "no time";
  56. var days = Math.floor(seconds / 86400);
  57. seconds -= days*86400;
  58. var hours = Math.floor(seconds / 3600);
  59. seconds -= hours*3600;
  60. var minutes = Math.floor(seconds / 60);
  61. seconds -= minutes*60;
  62. if (hours < 10 && days) {hours = "0"+hours;}
  63. if (minutes < 10 && hours) {minutes = "0"+minutes;}
  64. if (seconds < 10) {seconds = "0"+seconds;}
  65. var output = "";
  66. if(days)
  67. output = days+"d "+hours+":"+minutes+":"+seconds;
  68. else if(hours)
  69. output = hours+":"+minutes+":"+seconds;
  70. else
  71. output = minutes+":"+seconds;
  72. return output;
  73. }
  74. //function to update the control panel
  75. crypto.updatehud = function(type) {
  76. if(type & 1)
  77. {
  78. if(this.autoPurchase)
  79. {
  80. $(".apn").css('background-color', '');
  81. $(".apy").css('background-color', '#AFA');
  82. }
  83. else
  84. {
  85. $(".apy").css('background-color', '');
  86. $(".apn").css('background-color', '#FAA');
  87. }
  88. }
  89. if(type & 2)
  90. {
  91. if(crypto.autoClick)
  92. {
  93. $(".acn").css('background-color', '');
  94. $(".acy").css('background-color', '#AFA');
  95. }
  96. else
  97. {
  98. $(".acy").css('background-color', '');
  99. $(".acn").css('background-color', '#FAA');
  100. }
  101. }
  102. if(type & 4)
  103. {
  104. if(crypto.autoDrip==2)
  105. {
  106. $(".drip0").css('background-color', '');
  107. $(".drip1").css('background-color', '');
  108. $(".drip2").css('background-color', '#AFA');
  109. }
  110. else if(crypto.autoDrip)
  111. {
  112. $(".drip2").css('background-color', '');
  113. $(".drip0").css('background-color', '');
  114. $(".drip1").css('background-color', '#AAF');
  115. }
  116. else
  117. {
  118. $(".drip2").css('background-color', '');
  119. $(".drip1").css('background-color', '');
  120. $(".drip0").css('background-color', '#FAA');
  121. }
  122. }
  123. if(type & 8)
  124. {
  125. if(crypto.clickRate)
  126. {
  127. $(".crn").css('background-color', '');
  128. $(".cry").css('background-color', '#AFA');
  129. }
  130. else
  131. {
  132. $(".cry").css('background-color', '');
  133. $(".crn").css('background-color', '#FAA');
  134. }
  135. }
  136. if(type & 16)
  137. $("#multl").html("Min. Rate: "+String(crypto.cupmultl));
  138. if(type & 32)
  139. $("#multm").html("Avg. Rate: "+String(crypto.cupmultm));
  140. }
  141. //Create the control panel with divs
  142. $('#bpsChartContainer').parent().append("<table style='width:100%; height:105px; border-collapse: collapse;'><tr>"
  143. +"<td rowspan=2 style='width:30%; border: 2px solid black;'><div id='next-purchase-container'></div></td>"
  144. +"<td colspan=2 style='width:12%; height:35px; border: 2px solid black; border-bottom: none;' class='apy apn' onclick='crypto.autoPurchase = 1 - crypto.autoPurchase; crypto.updatehud(1)'>Auto Buy</td>"
  145. +"<td colspan=3 style='width:21%; border: 2px solid black; border-bottom: none' class='drip0 drip1 drip2' onclick='crypto.autoDrip = (1 + crypto.autoDrip) % 3; crypto.updatehud(4)'>Auto Drip</td>"
  146. +"<td colspan=2 style='width:12%; border: 2px solid black; border-bottom: none' class='acy acn' onclick='crypto.autoClick = 1 - crypto.autoClick; crypto.updatehud(2)'>Auto Click</td>"
  147. +"<td style='width:15%; border: 2px solid black; border-right:1px solid black'> Auto Click <div id='multl'></div></td>"
  148. +"<td style='width:5%; border-top: 2px solid black; border-bottom: 2px solid black; background-color: #AFA;' onclick='crypto.cupmultl = Math.min(crypto.cupmultl + 1, crypto.cupmultm); crypto.updatehud(16)'> + </td>"
  149. +"<td style='width:5%; border: 2px solid black; border-left: 1px solid black; background-color: #FAA;' onclick='crypto.cupmultl = Math.max(crypto.cupmultl - 1, 0); crypto.updatehud(16)'> - </td></tr>"
  150. +"<tr><td style='width:6%; height:35px; border: 2px solid black; border-top: 1px solid black;' class='apn' onclick='crypto.autoPurchase = 0; crypto.updatehud(1)'> Off </td>"
  151. +"<td style='width:6%; border: 2px solid black; border-top: 1px solid black;' class='apy' onclick='crypto.autoPurchase = 1; crypto.updatehud(1)'> On </td>"
  152. +"<td style='width:7%; border: 2px solid black; border-top: 1px solid black;' class='drip0' onclick='crypto.autoDrip = 0; crypto.updatehud(4)'> Never </td>"
  153. +"<td style='width:7%; border: 2px solid black; border-top: 1px solid black;' class='drip1' onclick='crypto.autoDrip = 1; crypto.updatehud(4)'> At <br /> Limit </td>"
  154. +"<td style='width:7%; border: 2px solid black; border-top: 1px solid black;' class='drip2' onclick='crypto.autoDrip = 2; crypto.updatehud(4)'> For <br /> Costs </td>"
  155. +"<td style='width:6%; border: 2px solid black; border-top: 1px solid black;' class='acn' onclick='crypto.autoClick = 0; crypto.updatehud(2)'> Off </td>"
  156. +"<td style='width:6%; border: 2px solid black; border-top: 1px solid black;' class='acy' onclick='crypto.autoClick = 1; crypto.updatehud(2)'> On </td>"
  157. +"<td style='width:15%; border: 2px solid black; border-right:1px solid black'> Auto Click <div id='multm'></div></td>"
  158. +"<td style='width:5%; border-top: 2px solid black; border-bottom: 2px solid black; background-color: #AFA;' onclick='crypto.cupmultm = Math.min(crypto.cupmultm + 1, 20); crypto.updatehud(32)'> + </td>"
  159. +"<td style='width:5%; border: 2px solid black; border-left: 1px solid black; background-color: #FAA;' onclick='crypto.cupmultm = Math.max(crypto.cupmultm - 1, crypto.cupmultl); crypto.updatehud(32)'> - </td></tr>"
  160. +"<tr><td style='height:35px; border: 2px solid black; border-right: none'> Average Click Rate - Last 10s: </td>"
  161. +"<td style='border: 2px solid black; border-left: none'><strong><div id='click-rate-10'></div></strong></td>"
  162. +"<td colspan=2 style='border: 2px solid black; border-right: none'> Last 60s: </td>"
  163. +"<td style='border: 2px solid black; border-left: none'><strong><div id='click-rate-60'></div></strong></td>"
  164. +"<td colspan=4 style='border: 2px solid black; border-right: none' class='cry crn' onclick='crypto.clickRate = 1 - crypto.clickRate; crypto.updatehud(8)'> Take click rate into account? </td>"
  165. +"<td style='border: 2px solid black; border-left: 1px solid black; border-right: 1px solid black' class='cry' onclick='crypto.clickRate = 1; crypto.updatehud(8)'> Yes </td>"
  166. +"<td style='border: 2px solid black; border-left: none' class='crn' onclick='crypto.clickRate = 0; crypto.updatehud(8)'> No </td></tr></table>");
  167. $("#next-purchase-container").html("<div id='next-purchase-label'></div><div id='next-purchase-payback'></div><div id='next-purchase-time'></div><div id='max-space-label'></div>");
  168. crypto.updatehud(63);
  169. }
  170. function loop()
  171. {
  172. var upgradeCounter = 1;
  173. var powerupCounter = 1;
  174. var mult = 0;
  175. var multm = 0;
  176. var bpc = CoffeeCup.calcBytesPerClick();
  177. var bpcBoosts = localStats.powerUps[0].purchasedUpgrades.length;
  178. var bpsDiff = localStats.byteCount - oldByteCount;
  179. if(first)
  180. first=0;
  181. else
  182. {
  183. clickHistory.shift();
  184. clickHistory.push(Math.round(Math.max(0,(bpsDiff - localStats.bps)/bpc)));
  185. }
  186. var avg10 = 0;
  187. var avg60 = 0;
  188. for(var a = 0; a < 60; a++)
  189. {
  190. avg60 += clickHistory[a];
  191. if(a>49)
  192. avg10 += clickHistory[a];
  193. }
  194. avg10 /= 10;
  195. avg60 /= 60;
  196. if (crypto.autoClick)
  197. {
  198. multm = crypto.cupmultm;
  199. mult = Math.min(20,Math.floor(Math.random()*(2 * multm - crypto.cupmultl)+crypto.cupmultl));
  200. if(mult)
  201. localStats.byteCount += bpc * mult;
  202. if(localStats.byteCount >= localStats.memoryCapacity)
  203. localStats.byteCount = localStats.memoryCapacity;
  204. }
  205. if (crypto.clickRate)
  206. var bps = bpc * (multm + avg60) + localStats.bps;
  207. else
  208. var bps = bpc * multm + localStats.bps;
  209. if (crypto.autoDrip && localStats.byteCount == localStats.memoryCapacity)
  210. dripper.dripGlobal();
  211. var data = Array();
  212. var min = 1e+308;
  213. var bytesNeeded=0;
  214. var next = min;
  215. var minObj = {};
  216. localStats.powerUps.slice(0).forEach(function(powerUp) {
  217. powerUp.position = "pu"+powerupCounter;
  218. var hasUpgrade = false;
  219. powerUp.upgrades.forEach(function(upgrade) {
  220. hasUpgrade = true;
  221. upgrade.position = "upg"+upgradeCounter;
  222. //Let's see which upgrade provides the biggest bang for the buck
  223. //(computed as "time taken before this upgrade will recoup its own cost").
  224. //If the price is so high that the current buffer can't possibly hold enough
  225. //(even if we cashed out for more space right now),
  226. //the "real" price includes what it takes to earn that extra buffer space.
  227. //If there's an object we can afford right now,
  228. //which will pay itself back in 2 hours,
  229. //and another object that would nominally pay itself back in 1h50m,
  230. //except that we can't afford it for 20 more minutes,
  231. //we should account for that in the time before recouping.
  232. //Add the time spent waiting to accrue sufficient funds.
  233. //Oh, and if we need 100MB for something, but can only hold 80MB
  234. //(with 70MB of it filled already), we can't just drip 20MB and keep the rest.
  235. //We have to drip everything at once, shooting all the way to 150MB.
  236. //Thus we can't make any progress on affording the item until a drip,
  237. //and then it costs a full additional 100MB after starting from scratch.
  238.  
  239. if(upgrade.price > localStats.byteCount + localStats.memoryCapacity)
  240. bytesNeeded = 2 * upgrade.price - (localStats.memoryCapacity + localStats.byteCount);
  241. else if(upgrade.price > localStats.memoryCapacity)
  242. bytesNeeded = upgrade.price;
  243. else if(upgrade.price > localStats.byteCount)
  244. bytesNeeded = upgrade.price - localStats.byteCount;
  245. else
  246. bytesNeeded = 0;
  247. //Cursor upgrades boost clicking too, so if autoclicks are on, take the rate
  248. //and overall BPS into account when determining its value.
  249. if(powerupCounter == 1)
  250. upgrade.value = upgrade.price/((powerUp.totalBps * (1 + crypto.clickRate * (avg60 + multm) * bpcBoosts * 0.1) + (crypto.clickRate * avg60 + multm) * bpc) / 10) + bytesNeeded / bps;
  251. else
  252. upgrade.value = upgrade.price/(powerUp.totalBps * (0.1 + crypto.clickRate * (avg60 + multm) * bpcBoosts * 0.01)) + bytesNeeded / bps;
  253. min = Math.min(min, upgrade.value);
  254. if(upgrade.value == min)
  255. minObj = upgrade;
  256. upgrade.desc = "Pays for itself in "+String(upgrade.value).toHHMMSS() + "<br>" + upgrade.originalDesc;
  257. });
  258. if(hasUpgrade)
  259. upgradeCounter++;
  260. powerupCounter++;
  261. //Same procedure on the main power-ups themselves.
  262. if(powerUp.currentPrice > localStats.byteCount + localStats.memoryCapacity)
  263. bytesNeeded = 2 * powerUp.currentPrice - (localStats.memoryCapacity + localStats.byteCount);
  264. else if(powerUp.currentPrice > localStats.memoryCapacity)
  265. bytesNeeded = powerUp.currentPrice;
  266. else if(powerUp.currentPrice > localStats.byteCount)
  267. bytesNeeded = powerUp.currentPrice - localStats.byteCount;
  268. else
  269. bytesNeeded = 0;
  270. powerUp.value = powerUp.currentPrice/(powerUp.currentBps * (1 + crypto.clickRate * (avg60 + multm) * bpcBoosts * 0.1)) + bytesNeeded / bps;
  271. data.push(powerUp.value);
  272. if(!(powerUp.name == "Spring Framework" && springPowerup.isLocked))
  273. {
  274. min = Math.min(min, powerUp.value);
  275. if(powerUp.value == min)
  276. minObj = powerUp;
  277. }
  278. });
  279. $('.storeItem, .upgcontainer').css('background-color', '');
  280. var selector = minObj.position;
  281. $("#"+selector).css('background-color', '#B2EDED');
  282. $('.storePrice').each(function(index){
  283. $(this).find('p').remove();
  284. var content = "<p style=\"display:inline; font-size:0.7em;\"> ("+String(data[index]).toHHMMSS()+")</p>";
  285. $(this).append(content);
  286. });
  287. var label = minObj.name;
  288. if(minObj.powerup) //Is our best deal an upgrade or a powerup? They use different syntax.
  289. {
  290. label += " (Upgrade)";
  291. var price = minObj.price;
  292. }
  293. else
  294. var price = minObj.currentPrice;
  295. var limitTime = Number((localStats.memoryCapacity - localStats.byteCount)/bps).toFixed(0);
  296. var limitstr = "";
  297. if(price > localStats.byteCount + localStats.memoryCapacity)
  298. {
  299. var time = Number((2 * price - (localStats.memoryCapacity + localStats.byteCount))/bps).toFixed(0);
  300. if(localStats.memoryCapacity==localStats.byteCount)
  301. limitstr = " (Drip NOW!)";
  302. }
  303. else if(price > localStats.memoryCapacity)
  304. {
  305. var time = Number(price/bps).toFixed(0);
  306. limitstr = " (Drip NOW!)";
  307. if(crypto.autoDrip >= 2)
  308. dripper.dripGlobal();
  309. }
  310. else
  311. var time = Number((price - localStats.byteCount)/bps).toFixed(0);
  312. //Now to fill the control panel.
  313. $("#next-purchase-label").html("Next Purchase: <strong>"+label+"</strong>");
  314. $("#next-purchase-payback").html("Pays for itself in "+String(minObj.value).toHHMMSS());
  315. if(time <= 0)
  316. $("#next-purchase-time").html("Affordable now");
  317. else
  318. $("#next-purchase-time").html("Affordable in "+String(time).toHHMMSS()+limitstr);
  319. if(limitTime <= 0)
  320. $("#max-space-label").html("Capacity is maxed out!");
  321. else
  322. $("#max-space-label").html("Capacity maxes out in "+String(limitTime).toHHMMSS());
  323. $("#click-rate-10").html(String(avg10.toFixed(1)));
  324. $("#click-rate-60").html(String(avg60.toFixed(1)));
  325. if(crypto.autoPurchase && price<=localStats.byteCount && lastBuy >= 5)
  326. {
  327. minObj.buy(localStats);
  328. lastBuy = 0;
  329. }
  330. else if (lastBuy < 5)
  331. lastBuy += 1;
  332. if(crypto.autoPurchase && springPowerup.isLocked && mine.beanCount > 0 && AnonymousUserManager.canGrabBean())
  333. {
  334. if($('.vex').length)
  335. vex.closeAll();
  336. Mine.onGrab();
  337. }
  338. if($("#networkError")[0].style['cssText'] == "display: block;")
  339. window.location.reload(false);
  340. oldByteCount = localStats.byteCount;
  341. }
  342. init();
  343. setInterval(function(){loop();}, 1000);