DripStat DropOut

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

Verze ze dne 09. 07. 2014. Zobrazit nejnovější verzi.

K instalaci tototo skriptu si budete muset nainstalovat rozšíření jako Tampermonkey, Greasemonkey nebo Violentmonkey.

K instalaci tohoto skriptu si budete muset nainstalovat rozšíření jako Tampermonkey nebo Violentmonkey.

K instalaci tohoto skriptu si budete muset nainstalovat rozšíření jako Tampermonkey nebo Violentmonkey.

K instalaci tohoto skriptu si budete muset nainstalovat rozšíření jako Tampermonkey nebo Userscripts.

You will need to install an extension such as Tampermonkey to install this script.

K instalaci tohoto skriptu si budete muset nainstalovat manažer uživatelských skriptů.

(Už mám manažer uživatelských skriptů, nechte mě ho nainstalovat!)

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

(Už mám manažer uživatelských stylů, nechte mě ho nainstalovat!)

// ==UserScript==
// @name       DripStat DropOut
// @namespace	anonycat
// @version    0.7.260
// @description  Calculates stats in DripStat, and provides a control panel for automation.
// @match      https://dripstat.com/game/
// @grant      none
// ==/UserScript==

//Throttle auto purchases to one every 3 seconds, to minimize risk of desyncs with the server
var lastBuy = 0;

//Track how many manual clicks have been made by second over the last 60 seconds
var clickHistory = [];
while (lastBuy < 60)
	{clickHistory[lastBuy++] = 0;}

//Convert upgrade indices to their order in the shop
var upgIndex = [1,1,1,1,1,1,1,1,1,1,1];

var oldByteCount = 0;
var first = 1;

function init()
{	
	localStats.dropout = new Object;
	//Should powerups and upgrades be automatically purchased as they become affordable?
	//(As of level 5, also includes facilities for grabbing spring beans that appear)
	localStats.dropout.autoBuy=0;
	//Should the BPS rate be increased to simulate automatic cup clicks?
	localStats.dropout.autoClick=0;
	//Should memory automatically be dripped?
	//0 = no auto-drip, 1 = auto-drip when buffer is full, 2 = auto-drip as needed to create enough space to pay for upgrades
	localStats.dropout.autoDrip=0;

	//Should we take manual clicks into account when figuring out the payback rate of powerups?
	localStats.dropout.clickRate=1;

	//If autoclicking is enabled, each second will pick a random multiplier and count off that many cup clicks.
	//A multiplier of 0 means no clicking, only natural BPS intake.
	//Multipliers greater than 20 are rejected by the server, so we won't ever generate such a thing here.
	
	//Lowest possible multiplier to select
	localStats.dropout.cupmultl = 0;
	//Average multiplier
	localStats.dropout.cupmultm = 5;
	//There is no variable for the highest multiplier; it's automatically figured as 2*Middle - Low (but capped at 20).
	
	//string (int) seconds to formatted time
	String.prototype.toHHMMSS = function () {
		var seconds = parseInt(this, 10); // don't forget the second param
		if(seconds <= 0)
			return "no time";
		
		var days   = Math.floor(seconds / 86400);
		seconds -= days*86400;
		var hours   = Math.floor(seconds / 3600);
		seconds -= hours*3600;
		var minutes = Math.floor(seconds / 60);
		seconds -= minutes*60;
		
		if (hours   < 10 && days) {hours   = "0"+hours;}
		if (minutes < 10 && hours) {minutes = "0"+minutes;}
		if (seconds < 10) {seconds = "0"+seconds;}
       
		//note: this output contains zero-width spaces before each colon, mostly to fit in upgrade boxes
		if(days)
			return days+"d "+hours+"​:"+minutes+"​:"+seconds;
		else if(hours)
			return hours+"​:"+minutes+"​:"+seconds;
		else
			return minutes+"​:"+seconds;
	}
		
	//function to update the control panel
	localStats.dropout.updatehud = function(type) {
		if(type & 1)
		{
			if(this.autoBuy)
			{
				$(".apn").css('background-color', '');
				$(".apy").css('background-color', '#AFA');
			}
			else
			{
				$(".apy").css('background-color', '');
				$(".apn").css('background-color', '#FAA');
			}
		}
		if(type & 2)
		{
			if(localStats.dropout.autoClick)
			{
				$(".acn").css('background-color', '');
				$(".acy").css('background-color', '#AFA');
			}
			else
			{
				$(".acy").css('background-color', '');
				$(".acn").css('background-color', '#FAA');
			}
		}
		if(type & 4)
		{
			if(localStats.dropout.autoDrip==2)
			{
				$(".drip0").css('background-color', '');
				$(".drip1").css('background-color', '');
				$(".drip2").css('background-color', '#AFA');
			}
			else if(localStats.dropout.autoDrip)
			{
				$(".drip2").css('background-color', '');
				$(".drip0").css('background-color', '');
				$(".drip1").css('background-color', '#AAF');
			}
			else
			{
				$(".drip2").css('background-color', '');
				$(".drip1").css('background-color', '');
				$(".drip0").css('background-color', '#FAA');
			}
		}
		if(type & 8)
		{
			if(localStats.dropout.clickRate)
			{
				$(".crn").css('background-color', '');
				$(".cry").css('background-color', '#AFA');
			}
			else
			{
				$(".cry").css('background-color', '');
				$(".crn").css('background-color', '#FAA');
			}
		}
		if(type & 16)
			$("#multl").html("Min. Rate: "+String(localStats.dropout.cupmultl));
		if(type & 32)
			$("#multm").html("Avg. Rate: "+String(localStats.dropout.cupmultm));
	}
   
	//Create the control panel with divs
	$('#bpsChartContainer').parent().append("<table style='width:100%; height:105px; line-height:1.3; border-collapse: collapse'><tr>"
									+"<td rowspan=2 style='width:33%; border: 2px solid black'><div id='next-purchase-container'></div></td>"
									+"<td colspan=2 style='width:12%; height:35px; border: 2px solid black; border-bottom: none' class='apy apn' onclick='localStats.dropout.autoBuy = 1 - localStats.dropout.autoBuy; localStats.dropout.updatehud(1)'>Auto Buy</td>"
									+"<td colspan=3 style='width:18%; border: 2px solid black; border-bottom: none' class='drip0 drip1 drip2' onclick='localStats.dropout.autoDrip = (1 + localStats.dropout.autoDrip) % 3; localStats.dropout.updatehud(4)'>Auto Drip</td>"
									+"<td colspan=2 style='width:12%; border: 2px solid black; border-bottom: none' class='acy acn' onclick='localStats.dropout.autoClick = 1 - localStats.dropout.autoClick; localStats.dropout.updatehud(2)'>Auto Click</td>"
									+"<td style='width:15%; border: 2px solid black; border-right:1px solid black'> Auto Click <div id='multl'></div></td>"
									+"<td style='width:5%; border-top: 2px solid black; border-bottom: 2px solid black; background-color: #AFA' onclick='localStats.dropout.cupmultl = Math.min(localStats.dropout.cupmultl + 1, localStats.dropout.cupmultm); localStats.dropout.updatehud(16)'> + </td>"
									+"<td style='width:5%; border: 2px solid black; border-left: 1px solid black; background-color: #FAA' onclick='localStats.dropout.cupmultl = Math.max(localStats.dropout.cupmultl - 1, 0); localStats.dropout.updatehud(16)'> - </td></tr>"
									+"<tr><td style='width:6%; height:35px; border: 2px solid black; border-top: 1px solid black' class='apn' onclick='localStats.dropout.autoBuy = 0; localStats.dropout.updatehud(1)'> Off </td>"
									+"<td style='width:6%; border: 2px solid black; border-top: 1px solid black' class='apy' onclick='localStats.dropout.autoBuy = 1; localStats.dropout.updatehud(1)'> On </td>"
									+"<td style='width:6%; border: 2px solid black; border-top: 1px solid black' class='drip0' onclick='localStats.dropout.autoDrip = 0; localStats.dropout.updatehud(4)'> Never </td>"
									+"<td style='width:6%; border: 2px solid black; border-top: 1px solid black' class='drip1' onclick='localStats.dropout.autoDrip = 1; localStats.dropout.updatehud(4)'> At <br /> Limit </td>"
									+"<td style='width:6%; border: 2px solid black; border-top: 1px solid black' class='drip2' onclick='localStats.dropout.autoDrip = 2; localStats.dropout.updatehud(4)'> For <br /> Costs </td>"
									+"<td style='width:6%; border: 2px solid black; border-top: 1px solid black' class='acn' onclick='localStats.dropout.autoClick = 0; localStats.dropout.updatehud(2)'> Off </td>"
									+"<td style='width:6%; border: 2px solid black; border-top: 1px solid black' class='acy' onclick='localStats.dropout.autoClick = 1; localStats.dropout.updatehud(2)'> On </td>"
									+"<td style='width:15%; border: 2px solid black; border-right:1px solid black'> Auto Click <div id='multm'></div></td>"
									+"<td style='width:5%; border-top: 2px solid black; border-bottom: 2px solid black; background-color: #AFA' onclick='localStats.dropout.cupmultm = Math.min(localStats.dropout.cupmultm + 1, 20); localStats.dropout.updatehud(32)'> + </td>"
									+"<td style='width:5%; border: 2px solid black; border-left: 1px solid black; background-color: #FAA' onclick='localStats.dropout.cupmultm = Math.max(localStats.dropout.cupmultm - 1, localStats.dropout.cupmultl); localStats.dropout.updatehud(32)'> - </td></tr>"
									+"<tr><td style='height:35px; border: 2px solid black; border-right: none'> Average Click Rate - Last 10s: </td>"
									+"<td style='border: 2px solid black; border-left: none'><strong><div id='click-rate-10'></div></strong></td>"
									+"<td colspan=2 style='border: 2px solid black; border-right: none'> Last 60s: </td>"
									+"<td style='border: 2px solid black; border-left: none'><strong><div id='click-rate-60'></div></strong></td>"
									+"<td colspan=4 style='border: 2px solid black; border-right: none' class='cry crn' onclick='localStats.dropout.clickRate = 1 - localStats.dropout.clickRate; localStats.dropout.updatehud(8)'> Take click rate into account? </td>"
									+"<td style='border: 2px solid black; border-left: 1px solid black; border-right: 1px solid black' class='cry' onclick='localStats.dropout.clickRate = 1; localStats.dropout.updatehud(8)'> Yes </td>"
									+"<td style='border: 2px solid black; border-left: none' class='crn' onclick='localStats.dropout.clickRate = 0; localStats.dropout.updatehud(8)'> No </td></tr></table>");
	$("#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>");
	
	$("head").append("<style id='tweaks'></style>");
	$("#tweaks").text('#upgrades .item {height: 50px}'
	+'#bpsChartContainer {padding-bottom: 2px}'
	+'#upgrades {height: 85px; line-height: 1.2}'
	+'#upgrades .upgcontainer {height: 85px; overflow-y: hidden}'
	+'#upgrades .upgROI {font-weight: bolder; text-align: center; color:#F00}'
	+'.storeItem {position: relative}'
	+'.storeItemName {font-size: 18px}'
	+'.storePriceRow {display: table}'
	+'.storeROI {display: table-cell; padding-left: 4px; font-size: 0.9em; font-weight: bolder; color: #F00}'
	+'.powerup-one {position: absolute; text-align: right; font-weight: bolder; font-size: 18px; top: 1px; right: 67px}'
	+'.powerup-all {position: absolute; text-align: right; font-weight: bolder; font-size: 18px; top: 26px; right: 70px; color: #BD511E}');
	
	localStats.dropout.updatehud(63);
}

function byteConvert(val)
{
	if(val < 1000)
		return +val.toFixed(2)+" B";
	else
		return NumUtils.byteConvert(val,2);
}

function byteConvert2(val)
{
	if(val < 1000)
		return val.toFixed(0)+" B";
	else
		return NumUtils.byteConvert(val,2);
}

function loop()
{
	var powerupCounter = 1;
	
	var mult = 0;
	var multm = 0;
	var bpc = CoffeeCup.calcBytesPerClick();
	var bpcBoosts = localStats.powerUps[0].purchasedUpgrades.length;
	var bpsDiff = localStats.byteCount - oldByteCount;
	
	if(first)
	{
		first=0;
		$('.storeItem').each(function(index){
			$(this).html("<div class='storeItemAmount'>"+localStats.powerUps[index].count+"</div>"
			+"<div class='storeItemName'>"+localStats.powerUps[index].name+"</div>"
			+"<div class='storePriceRow'>"
			+"<div class='storePrice'>"+byteConvert2(localStats.powerUps[index].currentPrice)+"</div>"
			+"<div class='storeROI'>(--:--)</div></div>"
			+"<div class='powerup-one'>"+byteConvert(localStats.powerUps[index].currentBps)+"ps each</div>"
			+"<div class='powerup-all'>"+byteConvert2(localStats.powerUps[index].totalBps)+"ps total</div>");
		});
	}
	else
	{
		clickHistory.pop();
		clickHistory.unshift(Math.round(Math.max(0,(bpsDiff - localStats.bps)/bpc)));
	}
	
	var avg10 = 0;
	var avg60 = 0;
	for(var a = 0; a < 60; a++)
	{
		avg60 += clickHistory[a];
		if(a<10)
			avg10 += clickHistory[a];
	}
	avg10 /= 10;
	avg60 /= 60;
	
	if (localStats.dropout.autoClick)
	{
		multm = localStats.dropout.cupmultm;
		mult = Math.min(20-clickHistory[0],Math.floor(Math.random()*(2 * multm - localStats.dropout.cupmultl)+localStats.dropout.cupmultl));
        
		if(mult)
			localStats.byteCount += bpc * mult;
        
		if(localStats.byteCount >= localStats.memoryCapacity)
			localStats.byteCount = localStats.memoryCapacity;
	}
	
	var bps = bpc * localStats.dropout.clickRate * (avg60 + multm) + localStats.bps;
    
	if (localStats.dropout.autoDrip && localStats.byteCount == localStats.memoryCapacity)
		dripper.dripGlobal();
	
	//Upgrades aren't necessarily in order, so untangle their order first
	$(".upgcontainer").each(function(upg) {
		if(this.children[0].className == "item")
		{
			var pos = Number(this.children[0].style.backgroundPosition.split(' ')[1].split('px')[0]) / -50;
			upgIndex[pos] = upg+1;
			if($(this).find('.upgROI').length==0)
				$(this).append("<div class='upgROI'></div>");
		}
	})
    
	var data = Array();
	var upgdata = [1,1,1,1,1,1,1,1,1,1,1];
	var min = 1e+38;
	var bytesNeeded=0;
	var minObj = {};
	localStats.powerUps.slice(0).forEach(function(powerUp) {
		powerUp.position = "pu"+powerupCounter;
           
		var hasUpgrade = false;
		
		//Don't calculate ROI on upgrades that have zero powerups fueling them
		if(powerUp.count)
		powerUp.upgrades.forEach(function(upgrade) {
			if(hasUpgrade)
				return;
			hasUpgrade = true;
			upgrade.position = "upg"+upgIndex[powerupCounter-1];
			
			//Let's see which upgrade provides the biggest bang for the buck
			//(computed as "time taken before this upgrade will recoup its own cost").
			
			//If the price is so high that the current buffer can't possibly hold enough
			//(even if we cashed out for more space right now),
			//the "real" price includes what it takes to earn that extra buffer space.
			
			//If there's an object we can afford right now,
			//which will pay itself back in 2 hours,
			//and another object that would nominally pay itself back in 1h50m,
			//except that we can't afford it for 20 more minutes,
			//we should account for that in the time before recouping.
			//Add the time spent waiting to accrue sufficient funds.
			
			//Oh, and if we need 100MB for something, but can only hold 80MB
			//(with 70MB of it filled already), we can't just drip 20MB and keep the rest.
			//We have to drip everything at once, shooting all the way to 150MB.
			//Thus we can't make any progress on affording the item until a drip,
			//and then it costs a full additional 100MB after starting from scratch.

			if(upgrade.price > localStats.byteCount + localStats.memoryCapacity)
				bytesNeeded = 2 * upgrade.price - (localStats.memoryCapacity + localStats.byteCount);
			else if(upgrade.price > localStats.memoryCapacity)
				bytesNeeded = upgrade.price;
			else if(upgrade.price > localStats.byteCount)
				bytesNeeded = upgrade.price - localStats.byteCount;
			else
				bytesNeeded = 0;
			
			//Cursor upgrades boost clicking too, so if autoclicks are on, take the rate
			//and overall BPS into account when determining its value.
			if(powerupCounter == 1)
				upgrade.value = upgrade.price/((powerUp.totalBps * (1 + localStats.dropout.clickRate * (avg60 + multm) * bpcBoosts * 0.1) + localStats.dropout.clickRate * (avg60 + multm) * bpc) / 10) + bytesNeeded / bps;
			else
				upgrade.value = upgrade.price/(powerUp.totalBps * (0.1 + localStats.dropout.clickRate * (avg60 + multm) * bpcBoosts * 0.01)) + bytesNeeded / bps;
			
			min = Math.min(min, upgrade.value);
			if(upgrade.value == min)
				minObj = upgrade;
 
			upgdata[upgIndex[powerupCounter-1]-1]=upgrade.value;
		});
				
		powerupCounter++;
		
		//Same procedure on the main power-ups themselves.
		
		if(powerUp.currentPrice > localStats.byteCount + localStats.memoryCapacity)
			bytesNeeded = 2 * powerUp.currentPrice - (localStats.memoryCapacity + localStats.byteCount);
		else if(powerUp.currentPrice > localStats.memoryCapacity)
			bytesNeeded = powerUp.currentPrice;
		else if(powerUp.currentPrice > localStats.byteCount)
			bytesNeeded = powerUp.currentPrice - localStats.byteCount;
		else
			bytesNeeded = 0;
		
		powerUp.value = powerUp.currentPrice/(powerUp.currentBps * (1 + localStats.dropout.clickRate * (avg60 + multm) * bpcBoosts * 0.1)) + bytesNeeded / bps;
            
		data.push(powerUp.value);
 
		if(!(powerUp.name == "Spring Framework" && springPowerup.isLocked))
		{
			min = Math.min(min, powerUp.value);
			if(powerUp.value == min)
				minObj = powerUp;
		}
 
	});
       
	$('.storeItem, .upgcontainer').css('background-color', '');
       
	var selector = minObj.position;
	$("#"+selector).css('background-color', '#B2EDED');
 
	$('.storeItem').each(function(index){
		$(this).find('.storeROI').html("("+String(data[index]).toHHMMSS()+")");
		$(this).find('.powerup-one').html(byteConvert(localStats.powerUps[index].currentBps)+'ps each');
		$(this).find('.powerup-all').html(byteConvert2(localStats.powerUps[index].totalBps)+'ps total');
	});
	$('.upgROI').each(function(index){
		$(this).html(String(upgdata[index]).toHHMMSS());
	});
       
	var label = minObj.name;
	
	if(minObj.powerup) //Is our best deal an upgrade or a powerup? They use different syntax.
	{
		label = "<span style='color:#F00'>"+label+"</span>";
		var price = minObj.price;
	}
	else
		var price = minObj.currentPrice;
	
	var limitTime = Number((localStats.memoryCapacity - localStats.byteCount)/bps).toFixed(0);
	var limitstr = "";
   
	if(price > localStats.byteCount + localStats.memoryCapacity)
	{
		var time = Number((2 * price - (localStats.memoryCapacity + localStats.byteCount))/bps).toFixed(0);
		if(localStats.memoryCapacity==localStats.byteCount)
			limitstr = " (Drip NOW!)";
	}
	else if(price > localStats.memoryCapacity)
	{
		var time = Number(price/bps).toFixed(0);
		limitstr = " (Drip NOW!)";
		if(localStats.dropout.autoDrip >= 2)
			dripper.dripGlobal();
	}
	else
		var time = Number((price - localStats.byteCount)/bps).toFixed(0);
	
	//Now to fill the control panel.
   
	$("#next-purchase-label").html("Next purchase: <strong>"+label+"</strong>");
	$("#next-purchase-payback").html("Pays for itself in "+String(minObj.value).toHHMMSS());
	
	if(time <= 0)
		$("#next-purchase-time").html("Affordable now");
	else
		$("#next-purchase-time").html("Affordable in "+String(time).toHHMMSS()+limitstr);
	
	if(limitTime <= 0)
		$("#max-space-label").html("Capacity is maxed out!");
	else
		$("#max-space-label").html("Capacity maxes out in "+String(limitTime).toHHMMSS());
	
	$("#click-rate-10").html(String(avg10.toFixed(1)));
	$("#click-rate-60").html(String(avg60.toFixed(1)));
	
	if(localStats.dropout.autoBuy && price<=localStats.byteCount && lastBuy >= 3)
	{
		minObj.buy(localStats);
		lastBuy = 0;
	}
	else if (lastBuy < 3)
		lastBuy += 1;
	
	if(springPowerup.isLocked && mine.beanCount > 0 && AnonymousUserManager.canGrabBean() && localStats.byteCount > 0)
	{
		if($('.vex').length)
			vex.closeAll();
		Mine.onGrab();
	}
	
	if($("#networkError")[0].style['cssText'] == "display: block;")
		window.location.reload(false);
	
	oldByteCount = localStats.byteCount;
}
 
init();
setInterval(function(){loop();}, 1000);