#-------------------------------------------------------------------------------
# Name:        Mash.py
# Purpose:     Calculates Strike Temp, Strike Volume, Sparge Volume, Sparge Temp, 
#              Total Water needed as well as of factors affecting the and predicting 
#              the home brewing process
#
# Author:      Peter K
#
# Credits: code for this script has adapted from documentation from the brew365 website at
# chttp://www.brew365.com/technique_calculating_mash_water_volume.php
#
# Created:     2015/04/02
#-------------------------------------------------------------------------------

class Mash(object):
	def __init__(self, ratio, targetTemp, grainWeight, grainTemp, boilTime, batchSize, trubLoss, tunLoss):
		self.ratio = ratio
		self.targetTemp = targetTemp
		self.grainWeight = grainWeight
		self.grainTemp = grainTemp
		self.boilTime = boilTime
		self.batchSize = batchSize
		self.trubLoss = trubLoss
		self.tunLoss = tunLoss
		
	def strikeTemp(self):
		'''method to calculate strike water temperature for mash'''
		return round(((.2/(float(self.ratio))*(float(self.targetTemp) - float(self.grainTemp)) + float(self.targetTemp))),2)
	
	def strikeVol(self):
		'''method to calculate the volume of water needed for the mash'''
		return round(((self.ratio * self.grainWeight)/4), 2)
	
	def spargeVol(self):
		'''method to calculate the volume of water needed for sparging'''
		return  self.totalWaterNeeded() - self.strikeVol()
	
	def totalWaterNeeded(self):
		'''method to calculate the total volume of water needed for the
		whole brew session with losses included'''
		return round((self._preBoilVol() + self.tunLoss + self._absorbtion()),2)
		
	def _absorbtion(self):
		'''method to calculate the total volume of water lost to absorbtion 
		from the grain'''
		return (self.grainWeight *.15)
	
	def _mashTunLoss(self):
		'''method to calculate the total volume of water lost in the bottom of 
		the mash tun after transfer to boil kettle'''
		return (((self.strikeVol() - (self._absorbtion()) - self.tunLoss)))
	
	def _evaporationRate(self):
		'''method to calculate the total volume of water to lost to 
		evaporation durring the boil'''
		evapRate = .10 #Rate of evaporation per hour
		return round(1-(evapRate*(self.boilTime/60)), 2)
		
	def _shrinkLoss(self):
		'''method to calculate the total volume of water lost due to shrinking 
		after cooling the wort'''
		#using standard shrink factor of 4 percent
		return 1 - .04
	
	def _preBoilVol(self):
		'''method to calculate the total volume of water needed pre boil'''
		return round((((self.batchSize + self.trubLoss)/self._shrinkLoss())/self._evaporationRate()),2)
	
	
if __name__ == "__main__":
	batchSize = 5    #Gallons
	ratio = 1.25     #Quarts
	mashTemp = 152   #Fahrenheit
	grainWeight = 11 #Pounds
	grainTemp = 70   #Fahrenheit
	boilTime = 60    #Minutes
	#This will depent on your system and how you do things
	trubLoss = 0     #Gallons
	tunLoss = 0      #Gallons

	mash = Mash(ratio, mashTemp, grainWeight, grainTemp, boilTime, batchSize, trubLoss, tunLoss) 

	print "{0} Fahrenheit - Strike Water Temp".format(mash.strikeTemp())
	print "{0} Gallons - Strike Water Volume".format(mash.strikeVol())
	print "{0} Gallons - Sparge Water Volume".format(mash.spargeVol())
	print "{0} Gallons - Total Water Needed".format(mash.totalWaterNeeded())
	print "{0} Gallons - absorbed by grain durring mash".format(mash._absorbtion()) 
	print "{0} Gallons - First Runnings".format(mash._mashTunLoss())
	print "{0} Gallons - Pre Boil Volume".format(mash._preBoilVol()) 
	print "{0} Gallons - Lost to evaporation during {1} minute boil".format(mash._preBoilVol()-(mash._preBoilVol()*mash._evaporationRate()),mash.boilTime)
	print "{0} Gallons - Lost to shrinking after cooling wort.".format(mash._preBoilVol()*mash._evaporationRate()-5)

