# Daniel L. Ensign
# Pande Group
# Department of Chemistry
# Stanford University
# 
# 9/11/07
#
# FidoProject.py
# Contains a class for internal representation of adaptive Folding@home (Fido) projects.

### IMPORTS ###
from os.path import exists
from os import mkdir, system
import pickle # so that project objects may save themselves
from FAHProject import FAHProject

class FidoProject( object ):

	def __init__ ( self, parameters, path = "~", server2path = "/home/server/server2/", debug = False,
			buildOutput = "BUILD_OUTPUT", updateOutput = "UPDATE_OUTPUT", 
			analysisOutput = "GROFILELIST" ) :

		# this is a dictionary generated, eg, by the FidoConfig parser.
		# keys are 'name', 'conf', etc.
		self.parameters = parameters

		# this determines where the project binary is saved and where model ouputs are printed
		# is modified a little below, after self.name is determined
		self.path = path

		# location of /home/server_x/server2 so that conf file can be found
		self.server2path = server2path

		# if true, prints extra info
		self.debug = debug

		# output file names
		# will be written (by object's script) to self.path
		# buildOutput - results for initial model building
		# updateOutput - results for model updates
		# analysisOutput - list of gro files to add to the FAH project
		self.buildOutput = buildOutput
		self.updateOutput = updateOutput
		self.analysisOutput = analysisOutput

		### PARAMETERS -> ATTRIBUTES
		# name of project, which is the name of the file stored on disk
		self.name = self.parameters[ 'name' ]
	
		# location of projectX.conf file
		self.conf = "%s/%s" % ( self.server2path , self.parameters[ 'conf' ] )
	
		# minimum number of returned WUs for model building to occur
		self.min = int( self.parameters[ 'min' ] )

		# number of returned WUs (beyond min) for model update to occur
		self.add = int( self.parameters[ 'add' ] )

		# location of script for building and updating models
		# if useGlobalPath == True, will use the path passed in above for script location
		# otherwise this should be the absolute path to the script or the script should
		# be in the path
		self.script = self.parameters[ 'script' ]
	
		# store everything in this directory:
		self.path = "%s/%s" % ( self.path, self.name )
		if not exists( self.path ): mkdir ( self.path )

		# file to store the pickled form of the project
		self.filename = "%s/.%s" % ( self.path,  self.name )

		# need to generate right path before accessing these
		self.fahproject = FAHProject( self.conf )

		# if we're here in the generator, then this is a brand new FidoProject
		self.lastnWUs = 0
		self.modelExists = False # set to true in self.buildModel()

	def save( self ):
		FILE = open ( self.filename, "w" ) 
		p = pickle.Pickler( FILE )
		p.dump( self )
		FILE.close()	

	def countReturnedWUs( self ):
		return self.fahproject.countReturnedWUs()

	# this method generates an initial model
	def buildModel( self ):
		fields = ( self.script, self.path, self.buildOutput )
		cmd = "%s mode=BUILD dir=%s outfile=%s" % fields
		system( cmd ) 
		self.modelExists = True

	# this method updates a model that already exists
	def updateModel( self ):
		fields = ( self.script, self.path, self.updateOutput )
		cmd = "%s mode=UPDATE dir=%s outfile=%s" % fields
		system( cmd )

	# this method generates, from the model, a list of
	# gro files which may be added to a FAH project
	def analyze( self ):
		fields = ( self.script, self.path, self.analysisOutput )
		cmd = "%s --mode=ANALYZE --dir=%s --outfile=%s" % fields
		system( cmd ) 

		results = "%s/%s" % ( fields[1:] )
		RESULTS = open( results )
		results = RESULTS.readlines()
		nresults = []
		for gro in results :
			nresults.append( gro.strip() )

		if len( nresults ) > 0 :
			self.newGroList = nresults
		else :
			self.newGroList = [ "none" ]

	def addNewRuns( self ):
		for gro in self.newGroList :
			if exists( gro ) :
				print "FidoProject objects currently cannot add new RUNs!"
				print "If script worked, would be adding '%s' to %s" % ( gro, self.fahproject.projectnumber )
			else:
				print "gro '%s' not found" % ( gro )
