Commits

Richard Shea  committed a8a1f6b Draft

Massive tabs for spaces exercies

  • Participants
  • Parent commits e1c2fbe

Comments (0)

Files changed (20)

File MathsMish/MMDBConstants.py

 class MMDBConstants:
-	VALID_OPERATORS = ["+","x","-"]
-	LHS_CANDIDATES = [1,2,3,4,5,6,7,8,9,10,11,12]
-	LHS_STARTOFFSET = 6
-	LHS_THRESHOLD = 0.9
-	RHS_CANDIDATES = [2,3,4,5,8,6,10,8,7,11,12]
-	RHS_STARTOFFSET = 2
-	RHS_THRESHOLD = 0.4
-	NEVERASKED_PROB = 0.5
-	MOSTRECENTOK_PROB = 0.1
-	MOSTRECENTNOTOK_PROB = 0.4
+    VALID_OPERATORS = ["+","x","-"]
+    LHS_CANDIDATES = [1,2,3,4,5,6,7,8,9,10,11,12]
+    LHS_STARTOFFSET = 6
+    LHS_THRESHOLD = 0.9
+    RHS_CANDIDATES = [2,3,4,5,8,6,10,8,7,11,12]
+    RHS_STARTOFFSET = 2
+    RHS_THRESHOLD = 0.4
+    NEVERASKED_PROB = 0.5
+    MOSTRECENTOK_PROB = 0.1
+    MOSTRECENTNOTOK_PROB = 0.4

File MathsMish/Question.py

 from MathsMish import MMDBConstants
 
 class Question(object):
-	pass
+    pass
 '''
 
-	def __init__(self, lhs, rhs, operator, id=None): 
-		if operator == "*":
-			operator = "x"
+    def __init__(self, lhs, rhs, operator, id=None): 
+        if operator == "*":
+            operator = "x"
 
-		self.__validateInitArgs(lhs, rhs, operator)
+        self.__validateInitArgs(lhs, rhs, operator)
 
-		self.__lhs = lhs
-		self.__rhs = rhs
-		self.__operator = operator 
-		self.__suppliedAnswer = None
+        self.__lhs = lhs
+        self.__rhs = rhs
+        self.__operator = operator 
+        self.__suppliedAnswer = None
 
-	def __str__(self):
-		return "%s %s %s" % (self.__lhs, self.__operator, self.__rhs)
+    def __str__(self):
+        return "%s %s %s" % (self.__lhs, self.__operator, self.__rhs)
 
-	def getHash(self):
-		return "%s_%s_%s" % (self.__lhs, self.__operator, self.__rhs)
+    def getHash(self):
+        return "%s_%s_%s" % (self.__lhs, self.__operator, self.__rhs)
 
-	def getSuppliedAnswer(self):
-		return self.__suppliedAnswer
+    def getSuppliedAnswer(self):
+        return self.__suppliedAnswer
 
-	def setSuppliedAnswer(self, value):
-		self.__suppliedAnswer = value
+    def setSuppliedAnswer(self, value):
+        self.__suppliedAnswer = value
 
-	suppliedAnswer = property(getSuppliedAnswer, setSuppliedAnswer, "I'm the 'SuppliedAnswer' property.")
+    suppliedAnswer = property(getSuppliedAnswer, setSuppliedAnswer, "I'm the 'SuppliedAnswer' property.")
 
-	def getlhs(self):
-		return self.__lhs
+    def getlhs(self):
+        return self.__lhs
 
-	def setlhs(self, value):
-		self.__lhs = value
+    def setlhs(self, value):
+        self.__lhs = value
 
-	lhs = property(getlhs, setlhs, "I'm the 'lhs' property.")
+    lhs = property(getlhs, setlhs, "I'm the 'lhs' property.")
 
-	def getrhs(self):
-		return self.__rhs
+    def getrhs(self):
+        return self.__rhs
 
-	def setrhs(self, value):
-		self.__rhs = value
+    def setrhs(self, value):
+        self.__rhs = value
 
-	rhs = property(getrhs, setrhs, "I'm the 'rhs' property.")
+    rhs = property(getrhs, setrhs, "I'm the 'rhs' property.")
 
-	def getoperator(self):
-		return self.__operator
+    def getoperator(self):
+        return self.__operator
 
-	def setoperator(self, value):
-		self.__operator = value
+    def setoperator(self, value):
+        self.__operator = value
 
-	operator = property(getoperator, setoperator, "I'm the 'operator' property.")
+    operator = property(getoperator, setoperator, "I'm the 'operator' property.")
 
-	def getoperatorRaw(self):
-		return self.__operator
+    def getoperatorRaw(self):
+        return self.__operator
 
-	def setoperatorRaw(self, value):
-		self.__operator = value
+    def setoperatorRaw(self, value):
+        self.__operator = value
 
-	operatorRaw = property(getoperatorRaw, setoperatorRaw, "I'm the 'operatorRaw' property.")
-	def goodAnswer(self):
-		if self.getSuppliedAnswer() == None:
-			raise MMDBExceptions.QuestionNotYetAnswered
-		elif isinstance(self.getSuppliedAnswer(), int):
-			pass
-		else:
-			raise MMDBExceptions.AnswerNotAnInteger
+    operatorRaw = property(getoperatorRaw, setoperatorRaw, "I'm the 'operatorRaw' property.")
+    def goodAnswer(self):
+        if self.getSuppliedAnswer() == None:
+            raise MMDBExceptions.QuestionNotYetAnswered
+        elif isinstance(self.getSuppliedAnswer(), int):
+            pass
+        else:
+            raise MMDBExceptions.AnswerNotAnInteger
 
-		a = eval(self.__str__().replace("x","*"))
-		if a ==  self.getSuppliedAnswer():
-			return True
-		else:
-			return False
+        a = eval(self.__str__().replace("x","*"))
+        if a ==  self.getSuppliedAnswer():
+            return True
+        else:
+            return False
 
-	def __validateInitArgs(self, lhs, rhs, operator):
-		try:
-			operand = int(lhs)
-		except ValueError:
-			raise MMDBExceptions.NotInteger("LHS parameter is not an integer")
-		except TypeError:
-			raise MMDBExceptions.NotInteger("LHS parameter is not an integer")
+    def __validateInitArgs(self, lhs, rhs, operator):
+        try:
+            operand = int(lhs)
+        except ValueError:
+            raise MMDBExceptions.NotInteger("LHS parameter is not an integer")
+        except TypeError:
+            raise MMDBExceptions.NotInteger("LHS parameter is not an integer")
 
-		try:
-			operand = int(rhs)
-		except ValueError:
-			raise MMDBExceptions.NotInteger("RHS parameter is not an integer")
-		except TypeError:
-			raise MMDBExceptions.NotInteger("RHS parameter is not an integer")
+        try:
+            operand = int(rhs)
+        except ValueError:
+            raise MMDBExceptions.NotInteger("RHS parameter is not an integer")
+        except TypeError:
+            raise MMDBExceptions.NotInteger("RHS parameter is not an integer")
 
-		if operator not in MMDBConstants.VALID_OPERATORS:
-			raise MMDBExceptions.NotValidOperator
+        if operator not in MMDBConstants.VALID_OPERATORS:
+            raise MMDBExceptions.NotValidOperator
 
 '''

File MathsMish/QuestionMachine.py

 import logging
 import datetime, time
 class QuestionSelectionMethod(object):
-	RANDOM = 0
-	WEIGHTED = 1
+    RANDOM = 0
+    WEIGHTED = 1
 class OperandType(object):
-	LHS = 0
-	RHS = 1
+    LHS = 0
+    RHS = 1
 class QuestionMachine(object):
-	def __init__(self, userid, operator):
-		self.__module_logger = logging.getLogger("MMDB.primary")
-		if operator not in ['x']: 
-			raise MathsMish.MMDBExceptions.NotValidOperator
-		if isinstance(userid, int): 
-			pass
-		else:
-			raise MathsMish.MMDBExceptions.NotInteger
+    def __init__(self, userid, operator):
+        self.__module_logger = logging.getLogger("MMDB.primary")
+        if operator not in ['x']: 
+            raise MathsMish.MMDBExceptions.NotValidOperator
+        if isinstance(userid, int): 
+            pass
+        else:
+            raise MathsMish.MMDBExceptions.NotInteger
 
-		self.__userid = userid
-		self.__operator = operator
-		self.__lhsCandidates = [] 
-		self.__rhsCandidates = [] 
+        self.__userid = userid
+        self.__operator = operator
+        self.__lhsCandidates = [] 
+        self.__rhsCandidates = [] 
                 #In the longer term __dicCandidateQuestions should
                 #probably be initialized within __maintainCandidateAndQuestionSpace
-		self.__dicCandidateQuestions = [] 
+        self.__dicCandidateQuestions = [] 
                 #I think it's possible that __dicCandidateQuestions is redundant
                 #due to it now having been replaced with the CandidateSpace 
                 #property
                 self.__CandidateQuestions = []
 
-		self.__rhsDefaultsInUse = MMDBConstants.RHS_STARTOFFSET
-		self.__lhsDefaultsInUse = MMDBConstants.LHS_STARTOFFSET
+        self.__rhsDefaultsInUse = MMDBConstants.RHS_STARTOFFSET
+        self.__lhsDefaultsInUse = MMDBConstants.LHS_STARTOFFSET
 
-		self.__maintainCandidateAndQuestionSpace()
+        self.__maintainCandidateAndQuestionSpace()
 
-		self.__questionSelectionMethod = QuestionSelectionMethod.WEIGHTED
-		self.__candidateOperators = ['x'] 
+        self.__questionSelectionMethod = QuestionSelectionMethod.WEIGHTED
+        self.__candidateOperators = ['x'] 
 
-		pass
+        pass
 
-	def __del__(self):
-		pass
+    def __del__(self):
+        pass
 
-	#----------------------------------------------------------------------------------------------------------
-	def getuserid(self):
-		return self.__userid
-	def setuserid(self, value):
-		self.__userid = value
+    #----------------------------------------------------------------------------------------------------------
+    def getuserid(self):
+        return self.__userid
+    def setuserid(self, value):
+        self.__userid = value
 
-	userid = property(getuserid, setuserid, "I'm the 'userid' property.")
+    userid = property(getuserid, setuserid, "I'm the 'userid' property.")
 
-	#----------------------------------------------------------------------------------------------------------
-	def getCandidateQuestions(self):
-		return self.__CandidateQuestions
-	def setCandidateQuestions(self, value):
-		self.__CandidateQuestions = value
+    #----------------------------------------------------------------------------------------------------------
+    def getCandidateQuestions(self):
+        return self.__CandidateQuestions
+    def setCandidateQuestions(self, value):
+        self.__CandidateQuestions = value
 
-	CandidateQuestions = property(getCandidateQuestions, setCandidateQuestions, "I'm the 'CandidateSpace' property.")
+    CandidateQuestions = property(getCandidateQuestions, setCandidateQuestions, "I'm the 'CandidateSpace' property.")
 
-	def getNextRHSOperand(self):
-		return self.__getNextOperand(OperandType.RHS)
+    def getNextRHSOperand(self):
+        return self.__getNextOperand(OperandType.RHS)
 
-	def getNextLHSOperand(self):
-		return self.__getNextOperand(OperandType.LHS)
+    def getNextLHSOperand(self):
+        return self.__getNextOperand(OperandType.LHS)
 
 
-	def getNextQuestion(self):
-		if self.__questionSelectionMethod == QuestionSelectionMethod.RANDOM:
-			myQuestion = self.__getNextQuestionRandom()
-		elif self.__questionSelectionMethod == QuestionSelectionMethod.WEIGHTED:
-			myQuestion = self.__getNextQuestionWeighted()
-			#return self.__getNextQuestionWeighted()
-		else:
-			raise MMDBExceptions.NotYetImplemented
-		
-		#q = Question(s.sum.lhs, s.sum.rhs, s.sum.operator, None, None, None)
-		return myQuestion 
+    def getNextQuestion(self):
+        if self.__questionSelectionMethod == QuestionSelectionMethod.RANDOM:
+            myQuestion = self.__getNextQuestionRandom()
+        elif self.__questionSelectionMethod == QuestionSelectionMethod.WEIGHTED:
+            myQuestion = self.__getNextQuestionWeighted()
+            #return self.__getNextQuestionWeighted()
+        else:
+            raise MMDBExceptions.NotYetImplemented
+        
+        #q = Question(s.sum.lhs, s.sum.rhs, s.sum.operator, None, None, None)
+        return myQuestion 
 
-	def answerQuestion(self, proposedAnswer, myQuestion):
-		'''
-		This method is used to supply the answer to a question
-		and to reflect that answer into the database. Once the
-		attempt at an answer has been added into the database
-		the 'candidate space' and 'question space' is 
-		refreshed
-		'''
-		myAttempt = Attempt(datetime.datetime.now(), myQuestion.sum.lhs, myQuestion.sum.rhs, myQuestion.sum.operator, None, self.userid, proposedAnswer)
-		AttemptManager.Insert(myAttempt)
-		self.__maintainCandidateAndQuestionSpace()
+    def answerQuestion(self, proposedAnswer, myQuestion):
+        '''
+        This method is used to supply the answer to a question
+        and to reflect that answer into the database. Once the
+        attempt at an answer has been added into the database
+        the 'candidate space' and 'question space' is 
+        refreshed
+        '''
+        myAttempt = Attempt(datetime.datetime.now(), myQuestion.sum.lhs, myQuestion.sum.rhs, myQuestion.sum.operator, None, self.userid, proposedAnswer)
+        AttemptManager.Insert(myAttempt)
+        self.__maintainCandidateAndQuestionSpace()
 
-	#----------------------------------------------------------------------------------------------------------
-		
+    #----------------------------------------------------------------------------------------------------------
+        
 
-	def __maintainCandidateAndQuestionSpace(self):
+    def __maintainCandidateAndQuestionSpace(self):
 
-		self.__QuestionPool = [] 
-		self.__lstAskedMostRecentlyFailed = []
-		self.__lstAskedMostRecentlySucceeded = []
-		self.__lstNeverAsked = []
+        self.__QuestionPool = [] 
+        self.__lstAskedMostRecentlyFailed = []
+        self.__lstAskedMostRecentlySucceeded = []
+        self.__lstNeverAsked = []
 
-		self.CandidateSpace = self.__buildCandidateSpace()
+        self.CandidateSpace = self.__buildCandidateSpace()
 
-		self.__buildQuestionPool()
+        self.__buildQuestionPool()
 
-	def __getNextOperand(self, operandType):
-		assert operandType in (OperandType.LHS, OperandType.RHS)
+    def __getNextOperand(self, operandType):
+        assert operandType in (OperandType.LHS, OperandType.RHS)
 
-		try:
-			if operandType == OperandType.LHS:
-				self.__lhsDefaultsInUse += 1
-				nextOperand = MMDBConstants.LHS_CANDIDATES[self.__lhsDefaultsInUse] 
-			elif operandType == OperandType.RHS:
-				self.__rhsDefaultsInUse += 1
-				nextOperand = MMDBConstants.RHS_CANDIDATES[self.__rhsDefaultsInUse] 
-			else:
-				raise MMDBExceptions.FallingOutOfIfStatement 
-		except IndexError:
-			if operandType == OperandType.LHS:
-				self.__lhsDefaultsInUse -= 1
-				nextOperand = MMDBConstants.LHS_CANDIDATES[self.__lhsDefaultsInUse] 
-			elif operandType == OperandType.RHS:
-				self.__rhsDefaultsInUse -= 1
-				nextOperand = MMDBConstants.RHS_CANDIDATES[self.__rhsDefaultsInUse] 
-			else:
-				raise MMDBExceptions.FallingOutOfIfStatement 
+        try:
+            if operandType == OperandType.LHS:
+                self.__lhsDefaultsInUse += 1
+                nextOperand = MMDBConstants.LHS_CANDIDATES[self.__lhsDefaultsInUse] 
+            elif operandType == OperandType.RHS:
+                self.__rhsDefaultsInUse += 1
+                nextOperand = MMDBConstants.RHS_CANDIDATES[self.__rhsDefaultsInUse] 
+            else:
+                raise MMDBExceptions.FallingOutOfIfStatement 
+        except IndexError:
+            if operandType == OperandType.LHS:
+                self.__lhsDefaultsInUse -= 1
+                nextOperand = MMDBConstants.LHS_CANDIDATES[self.__lhsDefaultsInUse] 
+            elif operandType == OperandType.RHS:
+                self.__rhsDefaultsInUse -= 1
+                nextOperand = MMDBConstants.RHS_CANDIDATES[self.__rhsDefaultsInUse] 
+            else:
+                raise MMDBExceptions.FallingOutOfIfStatement 
 
-		return nextOperand
+        return nextOperand
 
-	def __buildCandidateSpace(self):
-		'''
-		Iterates over the lhs and rhs candidates to produce a set
-		of questions which are candidates for asking. The set is limited
-		by the rules around when lhs and rhs values may enter the numbering
-		space (which in turn are based upon how many questions have been 
-		successfully answered using a given values as lhs/rhs)
-		'''
+    def __buildCandidateSpace(self):
+        '''
+        Iterates over the lhs and rhs candidates to produce a set
+        of questions which are candidates for asking. The set is limited
+        by the rules around when lhs and rhs values may enter the numbering
+        space (which in turn are based upon how many questions have been 
+        successfully answered using a given values as lhs/rhs)
+        '''
 
-		#Create 'base level' operand lists based upon hardcoded defaults
-		self.__addToCandidateSpaceFromDefaults()
-		#... now add extra operands based upon past successful answers
-		self.__addToCandidateSpaceBasedUponPastSuccesses()
+        #Create 'base level' operand lists based upon hardcoded defaults
+        self.__addToCandidateSpaceFromDefaults()
+        #... now add extra operands based upon past successful answers
+        self.__addToCandidateSpaceBasedUponPastSuccesses()
 
-		#Using the lhs/rhs operand candidates we have found build a set of questions
+        #Using the lhs/rhs operand candidates we have found build a set of questions
 
-		lq=[]
-		for lhs in self.__lhsCandidates:
-			for rhs in self.__rhsCandidates:
-				lq.append(Question(lhs, rhs, self.__operator))
+        lq=[]
+        for lhs in self.__lhsCandidates:
+            for rhs in self.__rhsCandidates:
+                lq.append(Question(lhs, rhs, self.__operator))
 
-		#... now add extra operands based upon past successful answers
-		self.__addToCandidateSpaceBasedUponPastSuccessesNew(lq)
+        #... now add extra operands based upon past successful answers
+        self.__addToCandidateSpaceBasedUponPastSuccessesNew(lq)
 
-		#Ensure all Sums in the proposed space are in the database
-		#if not add them in
+        #Ensure all Sums in the proposed space are in the database
+        #if not add them in
 
-		SumManager.InsertIfNecessary(lq)
+        SumManager.InsertIfNecessary(lq)
 
-		return lq
+        return lq
 
-	def __addToCandidateSpaceBasedUponPastSuccesses(self):
-		'''
-		Add to the two lists of candidate operands based upon past
-		successful answers
-		'''
-		#append those extras which meet the threshold
-		#self.__lhsCandidates += self.__getLHSValuesOverThreshold()
-		#... then append those extras which meet the threshold
+    def __addToCandidateSpaceBasedUponPastSuccesses(self):
+        '''
+        Add to the two lists of candidate operands based upon past
+        successful answers
+        '''
+        #append those extras which meet the threshold
+        #self.__lhsCandidates += self.__getLHSValuesOverThreshold()
+        #... then append those extras which meet the threshold
 
-		#This is the current technique just going to try 
-		self.__getRHSValuesOverThreshold()
-		self.__getLHSValuesOverThreshold()
+        #This is the current technique just going to try 
+        self.__getRHSValuesOverThreshold()
+        self.__getLHSValuesOverThreshold()
 
 
-	def __addToCandidateSpaceBasedUponPastSuccessesNew(self, lq):
-		'''
-		Add to the two lists of candidate operands based upon past
-		successful answers
-		'''
-		lqNew = []
-		dicLHS, dicRHS = AttemptManager.GetCountOfAllSuccesses(self.userid) 
+    def __addToCandidateSpaceBasedUponPastSuccessesNew(self, lq):
+        '''
+        Add to the two lists of candidate operands based upon past
+        successful answers
+        '''
+        lqNew = []
+        dicLHS, dicRHS = AttemptManager.GetCountOfAllSuccesses(self.userid) 
 
-		#Review the previously successful attempts from a point
-		#of view of the LHS operand. The dicLHS dictionary is a
-		#dictionary of dictionaries. The 'outer' key is the LHS
-		#value. Iterate over the 'outer' keys and determine whether
-		#we need to add more lhs operands based on past successes
+        #Review the previously successful attempts from a point
+        #of view of the LHS operand. The dicLHS dictionary is a
+        #dictionary of dictionaries. The 'outer' key is the LHS
+        #value. Iterate over the 'outer' keys and determine whether
+        #we need to add more lhs operands based on past successes
 
-		for lhsOperand in dicLHS.iterkeys():
-			#If the lhsoperand is already represented in the 
-			#list of questions we can ignore it
-			if not self.__lhsValueInQuestionList(lq, lhsOperand):
-				#Make a count of successful attempts for this LHS
-				#operand that have been successful
-				cntSuccesses = 0
-				for rhsOperand in dicLHS[lhsOperand].iterkeys():
-					cntSuccesses += 1
-				#For every success we add a new question to the
-				#list with lhs equal to the current lhsOperand
-				#and rhs being one of the not yet used rhs defaults
+        for lhsOperand in dicLHS.iterkeys():
+            #If the lhsoperand is already represented in the 
+            #list of questions we can ignore it
+            if not self.__lhsValueInQuestionList(lq, lhsOperand):
+                #Make a count of successful attempts for this LHS
+                #operand that have been successful
+                cntSuccesses = 0
+                for rhsOperand in dicLHS[lhsOperand].iterkeys():
+                    cntSuccesses += 1
+                #For every success we add a new question to the
+                #list with lhs equal to the current lhsOperand
+                #and rhs being one of the not yet used rhs defaults
 
 
 
 
 
-	def __lhsValueInQuestionList(self, lq, value):
-		'''
-		lq: a list of Question objects
-		value: an integer
-		'''
+    def __lhsValueInQuestionList(self, lq, value):
+        '''
+        lq: a list of Question objects
+        value: an integer
+        '''
 
-		rv = False
-		for q in lq:
-			if q.sum.lhs == value:
-				rv = True
-				break
-		return rv
+        rv = False
+        for q in lq:
+            if q.sum.lhs == value:
+                rv = True
+                break
+        return rv
 
 
-	def __addToCandidateSpaceFromDefaults(self):
-		'''
-		Build two list of candidate operands based upon the base operands which
-		are constants and independent of previous success/failures
-		'''
-		#Establish a minimal list of lhs candidates
-		self.__lhsCandidates = MMDBConstants.LHS_CANDIDATES[:self.__lhsDefaultsInUse]
-		#Establish a minimal list of rhs candidates
-		self.__rhsCandidates = MMDBConstants.RHS_CANDIDATES[:self.__rhsDefaultsInUse] 
+    def __addToCandidateSpaceFromDefaults(self):
+        '''
+        Build two list of candidate operands based upon the base operands which
+        are constants and independent of previous success/failures
+        '''
+        #Establish a minimal list of lhs candidates
+        self.__lhsCandidates = MMDBConstants.LHS_CANDIDATES[:self.__lhsDefaultsInUse]
+        #Establish a minimal list of rhs candidates
+        self.__rhsCandidates = MMDBConstants.RHS_CANDIDATES[:self.__rhsDefaultsInUse] 
 
 
-	def __getRHSValuesOverThreshold(self):
-		'''
-		Returns a list of integers which are outside the base set but which due to 
-		past successful answer by this user may be included in the question set
-		as lhs operands
-		'''
+    def __getRHSValuesOverThreshold(self):
+        '''
+        Returns a list of integers which are outside the base set but which due to 
+        past successful answer by this user may be included in the question set
+        as lhs operands
+        '''
 
-		#For each RHS operator we currently have determine if > 50% of the possible
-		#questions (based upon the current self.__lhsCandidates) have been answered
-		#correctly. If they have we add one extra RHS operand to the self.__rhsCandidates
-		#list
+        #For each RHS operator we currently have determine if > 50% of the possible
+        #questions (based upon the current self.__lhsCandidates) have been answered
+        #correctly. If they have we add one extra RHS operand to the self.__rhsCandidates
+        #list
 
-		countOfLHSOperands = len(self.__lhsCandidates)
-		for rhs in self.__rhsCandidates:
-			countOfSuccessfulAttemptsUsingRHSOperands = AttemptManager.GetCountOfRHSSuccesses(self.getuserid(),rhs)
-			if float(len(countOfSuccessfulAttemptsUsingRHSOperands)) / countOfLHSOperands > 0.5:
-				try:
-					nextOperand = self.getNextRHSOperand()
-					if nextOperand not in self.__rhsCandidates:
-						self.__rhsCandidates.append(nextOperand)
-				except IndexError:
-					pass
+        countOfLHSOperands = len(self.__lhsCandidates)
+        for rhs in self.__rhsCandidates:
+            countOfSuccessfulAttemptsUsingRHSOperands = AttemptManager.GetCountOfRHSSuccesses(self.getuserid(),rhs)
+            if float(len(countOfSuccessfulAttemptsUsingRHSOperands)) / countOfLHSOperands > 0.5:
+                try:
+                    nextOperand = self.getNextRHSOperand()
+                    if nextOperand not in self.__rhsCandidates:
+                        self.__rhsCandidates.append(nextOperand)
+                except IndexError:
+                    pass
 
 
-	def __getLHSValuesOverThreshold(self):
-		'''
-		Returns a list of integers which are outside the base set but which due to 
-		past successful answer by this user may be included in the question set
-		as rhs operands
-		'''
-		#For each LHS operator we currently have determine if > 90% of the possible
-		#questions (based upon the current self.__rhsCandidates) have been answered
-		#correctly. If they have we add one extra LHS operand to the self.__lhsCandidates
-		#list
+    def __getLHSValuesOverThreshold(self):
+        '''
+        Returns a list of integers which are outside the base set but which due to 
+        past successful answer by this user may be included in the question set
+        as rhs operands
+        '''
+        #For each LHS operator we currently have determine if > 90% of the possible
+        #questions (based upon the current self.__rhsCandidates) have been answered
+        #correctly. If they have we add one extra LHS operand to the self.__lhsCandidates
+        #list
 
-		countOfRHSOperands = len(self.__rhsCandidates)
-		for lhs in self.__lhsCandidates:
-			countOfSuccessfulAttemptsUsingLHSOperands = AttemptManager.GetCountOfLHSSuccesses(self.getuserid(),lhs)
-			if float(len(countOfSuccessfulAttemptsUsingLHSOperands)) / countOfRHSOperands > 0.9:
-				try:
-					nextOperand = self.getNextLHSOperand()
-					if nextOperand not in self.__lhsCandidates:
-						self.__lhsCandidates.append(nextOperand)
-				except IndexError:
-					pass
+        countOfRHSOperands = len(self.__rhsCandidates)
+        for lhs in self.__lhsCandidates:
+            countOfSuccessfulAttemptsUsingLHSOperands = AttemptManager.GetCountOfLHSSuccesses(self.getuserid(),lhs)
+            if float(len(countOfSuccessfulAttemptsUsingLHSOperands)) / countOfRHSOperands > 0.9:
+                try:
+                    nextOperand = self.getNextLHSOperand()
+                    if nextOperand not in self.__lhsCandidates:
+                        self.__lhsCandidates.append(nextOperand)
+                except IndexError:
+                    pass
 
-	def __isOperandOverThreshold(self,operandCandidate, operandType, thresholdProportion):
-		'''
-		Given an operand value, whether it's a LHS or a RHS and a proportion of answers
-		that need to be correct to pass the threshold this method provides a YES/NO
-		answer
-		'''
-		if operandType == OperandType.LHS:
-			raise MMDBExceptions.NotYetImplemented
-		elif operandType == OperandType.RHS:
-			raise MMDBExceptions.NotYetImplemented
-		else:
-			raise MMDBExceptions.MathsMishError   
+    def __isOperandOverThreshold(self,operandCandidate, operandType, thresholdProportion):
+        '''
+        Given an operand value, whether it's a LHS or a RHS and a proportion of answers
+        that need to be correct to pass the threshold this method provides a YES/NO
+        answer
+        '''
+        if operandType == OperandType.LHS:
+            raise MMDBExceptions.NotYetImplemented
+        elif operandType == OperandType.RHS:
+            raise MMDBExceptions.NotYetImplemented
+        else:
+            raise MMDBExceptions.MathsMishError   
 
-	def __getNextQuestionRandom(self):
-		'''
-		Selects a question at random from the list of candidate questions
-		'''
-		lhsidx = random.randint(0, len(self.__lhsCandidates) - 1)
-		rhsidx = random.randint(0, len(self.__rhsCandidates) - 1)
+    def __getNextQuestionRandom(self):
+        '''
+        Selects a question at random from the list of candidate questions
+        '''
+        lhsidx = random.randint(0, len(self.__lhsCandidates) - 1)
+        rhsidx = random.randint(0, len(self.__rhsCandidates) - 1)
 
-		lhs = self.__lhsCandidates[lhsidx]
-		rhs = self.__rhsCandidates[rhsidx]
+        lhs = self.__lhsCandidates[lhsidx]
+        rhs = self.__rhsCandidates[rhsidx]
 
 
-		return Question(lhs, rhs, self.__operator)
+        return Question(lhs, rhs, self.__operator)
 
-	def __getNextQuestionWeighted(self):
-		'''
-		Selects a question at using a 'weighted random' whereby
-		it's more likely we will get some sort of questions than others
-		'''
+    def __getNextQuestionWeighted(self):
+        '''
+        Selects a question at using a 'weighted random' whereby
+        it's more likely we will get some sort of questions than others
+        '''
 
 
-		#Establish the cumulative probablities based upon the default values
-		neverAskedThreshold = MMDBConstants.NEVERASKED_PROB
-		mostRecentlySucceededThreshold = MMDBConstants.NEVERASKED_PROB + MMDBConstants.MOSTRECENTOK_PROB
-		mostRecentlyFailedThreshold = MMDBConstants.NEVERASKED_PROB + MMDBConstants.MOSTRECENTOK_PROB + MMDBConstants.MOSTRECENTNOTOK_PROB
+        #Establish the cumulative probablities based upon the default values
+        neverAskedThreshold = MMDBConstants.NEVERASKED_PROB
+        mostRecentlySucceededThreshold = MMDBConstants.NEVERASKED_PROB + MMDBConstants.MOSTRECENTOK_PROB
+        mostRecentlyFailedThreshold = MMDBConstants.NEVERASKED_PROB + MMDBConstants.MOSTRECENTOK_PROB + MMDBConstants.MOSTRECENTNOTOK_PROB
 
-		'''
-		#Establish the cumulative probablities based upon the default values
+        '''
+        #Establish the cumulative probablities based upon the default values
 
-		neverAskedThresholdRange = (0,MMDBConstants.NEVERASKED_PROB)
-		mostRecentlySucceededThresholdRange = (neverAskedThreshold, MMDBConstants.NEVERASKED_PROB + MMDBConstants.MOSTRECENTOK_PROB)
-		mostRecentlyFailedThresholdRange = (mostRecentlySucceededThreshold, MMDBConstants.NEVERASKED_PROB + MMDBConstants.MOSTRECENTOK_PROB + MMDBConstants.MOSTRECENTNOTOK_PROB)
+        neverAskedThresholdRange = (0,MMDBConstants.NEVERASKED_PROB)
+        mostRecentlySucceededThresholdRange = (neverAskedThreshold, MMDBConstants.NEVERASKED_PROB + MMDBConstants.MOSTRECENTOK_PROB)
+        mostRecentlyFailedThresholdRange = (mostRecentlySucceededThreshold, MMDBConstants.NEVERASKED_PROB + MMDBConstants.MOSTRECENTOK_PROB + MMDBConstants.MOSTRECENTNOTOK_PROB)
 
-		#Establish lengths of lists		
-		lenNeverAsked = len(self.__lstNeverAsked)
-		lenMostRecentSucceeded = len(self.__lstAskedMostRecentlySucceeded)
-		lenMostRecentFailed = len(self.__lstAskedMostRecentlyFailed)
+        #Establish lengths of lists     
+        lenNeverAsked = len(self.__lstNeverAsked)
+        lenMostRecentSucceeded = len(self.__lstAskedMostRecentlySucceeded)
+        lenMostRecentFailed = len(self.__lstAskedMostRecentlyFailed)
 
-		#Adjust the cumulative probablities if we have no 
-		if len(self.__lstNeverAsked) == 0:
-			raise MathsMishError
+        #Adjust the cumulative probablities if we have no 
+        if len(self.__lstNeverAsked) == 0:
+            raise MathsMishError
 
-		if ((lenMostRecentSucceeded > 0) & (lenMostRecentFailed > 0)):
-			#Entries in all three lists so leave things as they are
-			neverAskedThresholdRange = (0,MMDBConstants.NEVERASKED_PROB)
-			mostRecentlySucceededThresholdRange = (neverAskedThreshold, MMDBConstants.NEVERASKED_PROB + MMDBConstants.MOSTRECENTOK_PROB)
-			mostRecentlyFailedThresholdRange = (mostRecentlySucceededThreshold, MMDBConstants.NEVERASKED_PROB + MMDBConstants.MOSTRECENTOK_PROB + MMDBConstants.MOSTRECENTNOTOK_PROB)
-		else:
-			if ((lenMostRecentSucceeded == 0) & (lenMostRecentFailed == 0)):
-				neverAskedThresholdRange = (0,MMDBConstants.NEVERASKED_PROB)
-				mostRecentlySucceededThresholdRange = (neverAskedThreshold, MMDBConstants.NEVERASKED_PROB + MMDBConstants.MOSTRECENTOK_PROB)
-				mostRecentlyFailedThresholdRange = (mostRecentlySucceededThreshold, MMDBConstants.NEVERASKED_PROB + MMDBConstants.MOSTRECENTOK_PROB + MMDBConstants.MOSTRECENTNOTOK_PROB)
-				#No entry in either succeeded of failed, adjust the 
-				#neverAskedThreshold so it goes right to top of the
-				#range
-				neverAskedThreshold = mostRecentlyFailedThreshold
-			if ((lenMostRecentSucceeded == 0) & (lenMostRecentFailed > 0)):
-				neverAskedThreshold = mostRecentlyFailedThreshold
-				neverAskedThreshold = mostRecentlyFailedThreshold
+        if ((lenMostRecentSucceeded > 0) & (lenMostRecentFailed > 0)):
+            #Entries in all three lists so leave things as they are
+            neverAskedThresholdRange = (0,MMDBConstants.NEVERASKED_PROB)
+            mostRecentlySucceededThresholdRange = (neverAskedThreshold, MMDBConstants.NEVERASKED_PROB + MMDBConstants.MOSTRECENTOK_PROB)
+            mostRecentlyFailedThresholdRange = (mostRecentlySucceededThreshold, MMDBConstants.NEVERASKED_PROB + MMDBConstants.MOSTRECENTOK_PROB + MMDBConstants.MOSTRECENTNOTOK_PROB)
+        else:
+            if ((lenMostRecentSucceeded == 0) & (lenMostRecentFailed == 0)):
+                neverAskedThresholdRange = (0,MMDBConstants.NEVERASKED_PROB)
+                mostRecentlySucceededThresholdRange = (neverAskedThreshold, MMDBConstants.NEVERASKED_PROB + MMDBConstants.MOSTRECENTOK_PROB)
+                mostRecentlyFailedThresholdRange = (mostRecentlySucceededThreshold, MMDBConstants.NEVERASKED_PROB + MMDBConstants.MOSTRECENTOK_PROB + MMDBConstants.MOSTRECENTNOTOK_PROB)
+                #No entry in either succeeded of failed, adjust the 
+                #neverAskedThreshold so it goes right to top of the
+                #range
+                neverAskedThreshold = mostRecentlyFailedThreshold
+            if ((lenMostRecentSucceeded == 0) & (lenMostRecentFailed > 0)):
+                neverAskedThreshold = mostRecentlyFailedThreshold
+                neverAskedThreshold = mostRecentlyFailedThreshold
 
 
-			if len(self.__lstAskedMostRecentlySucceeded) == 0:
-				neverAskedThreshold = mostRecentlySucceededThreshold
-			if len(self.__lstAskedMostRecentlyFailed) == 0:
-				neverAskedThreshold = mostRecentlyFailedThreshold
+            if len(self.__lstAskedMostRecentlySucceeded) == 0:
+                neverAskedThreshold = mostRecentlySucceededThreshold
+            if len(self.__lstAskedMostRecentlyFailed) == 0:
+                neverAskedThreshold = mostRecentlyFailedThreshold
 
 
-		if len(self.__lstNeverAsked) == 0:
-			raise MMDBExceptions.MathsMishError
-		'''
-		
-		#To deal with having an empty recently succeeded and/or recently failed
-		#we loop up to 100 times whilst absorbing IndexError we encounter
-		for attemptCnt in range(100):
-			questionSelector = random.random()
-			try:
-				if questionSelector < neverAskedThreshold:
-					return random.choice(self.__lstNeverAsked)
-				elif questionSelector < mostRecentlySucceededThreshold:
-					return random.choice(self.__lstAskedMostRecentlySucceeded)
-				elif questionSelector < mostRecentlyFailedThreshold:
-					return random.choice(self.__lstAskedMostRecentlyFailed)
-				else:
-					raise MMDBExceptions.FallingOutOfIfStatement 
-			except IndexError:
-				self.__module_logger.debug("AbsorbingIndex Error when attemptCnt was %s " % (attemptCnt)) 
+        if len(self.__lstNeverAsked) == 0:
+            raise MMDBExceptions.MathsMishError
+        '''
+        
+        #To deal with having an empty recently succeeded and/or recently failed
+        #we loop up to 100 times whilst absorbing IndexError we encounter
+        for attemptCnt in range(100):
+            questionSelector = random.random()
+            try:
+                if questionSelector < neverAskedThreshold:
+                    return random.choice(self.__lstNeverAsked)
+                elif questionSelector < mostRecentlySucceededThreshold:
+                    return random.choice(self.__lstAskedMostRecentlySucceeded)
+                elif questionSelector < mostRecentlyFailedThreshold:
+                    return random.choice(self.__lstAskedMostRecentlyFailed)
+                else:
+                    raise MMDBExceptions.FallingOutOfIfStatement 
+            except IndexError:
+                self.__module_logger.debug("AbsorbingIndex Error when attemptCnt was %s " % (attemptCnt)) 
 
-		raise MMDBExceptions.MathsMishError
+        raise MMDBExceptions.MathsMishError
 
-	def __buildQuestionPool(self):
-		'''
-		Review each question and populate the output list based upon whether
-		it fits the ...
+    def __buildQuestionPool(self):
+        '''
+        Review each question and populate the output list based upon whether
+        it fits the ...
 
-		* 'never asked'
-		* 'most recent OK'
-		* 'most recent not OK'
+        * 'never asked'
+        * 'most recent OK'
+        * 'most recent not OK'
 
-		... category.
+        ... category.
 
-		The output list is a list of strings each of which is the output of the
-		getHash property of the corresponding Question. Depending on which category
-		we find a question to fit the value is entered into the list multiple times as
-		follows ...
+        The output list is a list of strings each of which is the output of the
+        getHash property of the corresponding Question. Depending on which category
+        we find a question to fit the value is entered into the list multiple times as
+        follows ...
 
-		* 'never asked' - NEVERASKED_PROB * 10
-		* 'most recent OK' - MOSTRECENTOK_PROB * 10
-		* 'most recent not OK' - MOSTRECENTNOTOK_PROB * 10
+        * 'never asked' - NEVERASKED_PROB * 10
+        * 'most recent OK' - MOSTRECENTOK_PROB * 10
+        * 'most recent not OK' - MOSTRECENTNOTOK_PROB * 10
 
-		... in this way when a entitity is picked at random from the list the chances
-		of getting a member of a given category reflect the value 
-		'''
-		#Get all Sum/Attempt details for a given user
-		lstAttempts = AttemptManager.GetAllWithAttemptDetailsForUser(self.getuserid())
+        ... in this way when a entitity is picked at random from the list the chances
+        of getting a member of a given category reflect the value 
+        '''
+        #Get all Sum/Attempt details for a given user
+        lstAttempts = AttemptManager.GetAllWithAttemptDetailsForUser(self.getuserid())
 
-		#Produce a list of Questions objects from the database rows
-		for myAttempt in lstAttempts:
-			#Q = Question(summAttRow[2], summAttRow[3], summAttRow[1])
-			#Q = Question(summAttRow.question.lhs, summAttRow.question.rhs, summAttRow.question.operator)
-			myQuestion = myAttempt.question
-			self.__QuestionPool.append(myQuestion)
-			if (myAttempt.when == None) or (myAttempt.question.hasBeenAnswered() == False):
-				self.__lstNeverAsked.append(myQuestion)
-			else:
-				if myAttempt.question.goodAnswer() == True:
-					self.__lstAskedMostRecentlySucceeded.append(myQuestion)
-				elif myAttempt.question.goodAnswer() == False: 
-					self.__lstAskedMostRecentlyFailed.append(myQuestion)
-				else:
-					raise MMDBExceptions.FallingOutOfIfStatement 
+        #Produce a list of Questions objects from the database rows
+        for myAttempt in lstAttempts:
+            #Q = Question(summAttRow[2], summAttRow[3], summAttRow[1])
+            #Q = Question(summAttRow.question.lhs, summAttRow.question.rhs, summAttRow.question.operator)
+            myQuestion = myAttempt.question
+            self.__QuestionPool.append(myQuestion)
+            if (myAttempt.when == None) or (myAttempt.question.hasBeenAnswered() == False):
+                self.__lstNeverAsked.append(myQuestion)
+            else:
+                if myAttempt.question.goodAnswer() == True:
+                    self.__lstAskedMostRecentlySucceeded.append(myQuestion)
+                elif myAttempt.question.goodAnswer() == False: 
+                    self.__lstAskedMostRecentlyFailed.append(myQuestion)
+                else:
+                    raise MMDBExceptions.FallingOutOfIfStatement 
 
-		self.__printPoolDiagnostics()
+        self.__printPoolDiagnostics()
 
-	def __printPoolDiagnostics(self):
-		print "self.__QuestionPool = %s" % ( len(self.__QuestionPool))
-		print "self.__lstAskedMostRecentlyFailed =%s" % len(self.__lstAskedMostRecentlyFailed)
-		print "self.__lstAskedMostRecentlySucceeded =%s" % len(self.__lstAskedMostRecentlySucceeded) 
-		print "self.__lstNeverAsked = %s" % (len(self.__lstNeverAsked))
-		self.__module_logger.debug("self.__QuestionPool = %s" % ( len(self.__QuestionPool)))
-		self.__module_logger.debug("self.__lstAskedMostRecentlyFailed = %s" % len(self.__lstAskedMostRecentlyFailed))
-		self.__module_logger.debug("self.__lstAskedMostRecentlySucceeded = %s" % len(self.__lstAskedMostRecentlySucceeded)) 
-		self.__module_logger.debug("self.__lstNeverAsked = %s" % (len(self.__lstNeverAsked)))
-		self.__module_logger.debug("self.__lhsDefaultsInUse = %s" % (self.__lhsDefaultsInUse))
-		self.__module_logger.debug("self.__rhsDefaultsInUse = %s" % (self.__rhsDefaultsInUse))
+    def __printPoolDiagnostics(self):
+        print "self.__QuestionPool = %s" % ( len(self.__QuestionPool))
+        print "self.__lstAskedMostRecentlyFailed =%s" % len(self.__lstAskedMostRecentlyFailed)
+        print "self.__lstAskedMostRecentlySucceeded =%s" % len(self.__lstAskedMostRecentlySucceeded) 
+        print "self.__lstNeverAsked = %s" % (len(self.__lstNeverAsked))
+        self.__module_logger.debug("self.__QuestionPool = %s" % ( len(self.__QuestionPool)))
+        self.__module_logger.debug("self.__lstAskedMostRecentlyFailed = %s" % len(self.__lstAskedMostRecentlyFailed))
+        self.__module_logger.debug("self.__lstAskedMostRecentlySucceeded = %s" % len(self.__lstAskedMostRecentlySucceeded)) 
+        self.__module_logger.debug("self.__lstNeverAsked = %s" % (len(self.__lstNeverAsked)))
+        self.__module_logger.debug("self.__lhsDefaultsInUse = %s" % (self.__lhsDefaultsInUse))
+        self.__module_logger.debug("self.__rhsDefaultsInUse = %s" % (self.__rhsDefaultsInUse))
 
 
 

File MathsMish/__init__.py

 curs = None
 
 def setUpPackage():
-	global lock
-	#Setup a lock file as means to communicate to the DAO's
-	#that we are running in test mode
-	lock = flock('tmp.lock', False).acquire()		
-	if lock == False:
-		raise ValueError
+    global lock
+    #Setup a lock file as means to communicate to the DAO's
+    #that we are running in test mode
+    lock = flock('tmp.lock', False).acquire()       
+    if lock == False:
+        raise ValueError
 
-	mmdbConnLocal = mmdbConnection()
-	testDBConn = mmdbConnLocal.conn
+    mmdbConnLocal = mmdbConnection()
+    testDBConn = mmdbConnLocal.conn
 
-	#Insert data into our test database
-	insertTestData(testDBConn)
+    #Insert data into our test database
+    insertTestData(testDBConn)
 
 def tearDownPackage():
-	global lock
-	#Release the lock file used to indicate that we're testing
-	#to the DAO's
-	lock.release()
+    global lock
+    #Release the lock file used to indicate that we're testing
+    #to the DAO's
+    lock.release()
 
 def insertTestData(testDBConn):
-	'''
-	Create tables and insert test data
-	'''
-	curs = testDBConn.cursor()
-	clearDownDB(testDBConn, curs)
-	# Create User table and populate it
-	curs.execute('''create table MAM_PLAYER (PLA_AUTOID integer primary key, PLA_USERNAME text unique, PLA_REALNAME text)''')
-	curs.execute("insert into MAM_PLAYER values\
-		    (NULL,'dad','Richard Shea')")
-	curs.execute("insert into MAM_PLAYER values\
-		    (NULL,'jds','John Shea')")
-	curs.execute("insert into MAM_PLAYER values\
-		    (NULL,'ems','Emma Shea')")
-	curs.execute("insert into MAM_PLAYER values\
-		    (NULL,'mum','Kerry-Lynn Sorrell')")
-	testDBConn.commit()
-	##################################################
-	# Create Operations Table             
-	curs.execute('''create table MAM_OPERATIONS 
-	  (OPE_AUTOID integer primary key, OPE_OPERATOR text unique,
-		OPE_DESCRIPTION text)''')
-	curs.execute("insert into MAM_OPERATIONS values (NULL,'+','Adding')")
-	curs.execute("insert into MAM_OPERATIONS values (NULL,'-','Subtracting')")
-	curs.execute("insert into MAM_OPERATIONS values (NULL,'x','Multiplying')")
-	testDBConn.commit()
-	##################################################
-	curs.execute('''create table MAM_SUMS (SUM_AUTOID integer primary key, SUM_OPE_ID integer, SUM_LHS integer, SUM_RHS integer)''')
-	insertSums(testDBConn, curs)
-	##################################################
-	curs.execute('''create table MAM_ATTEMPT (ATT_AUTOID integer primary key, ATT_PLA_ID integer, ATT_SUM_ID integer, ATT_TIMESTAMP timestamp, ATT_COMPLETED boolean, ATT_CORRECT boolean, FOREIGN KEY(ATT_SUM_ID) REFERENCES MAM_SUMS(SUM_AUTOID))''')
-	insertAttempts(testDBConn, curs)
-	##################################################
-	curs.execute('''create table MAM_QUESTION (QUE_AUTOID integer primary key, QUE_PLA_ID integer, QUE_ORDER integer, QUE_INUSE boolean, QUE_OPERATION text, QUE_LHS integer, QUE_RHS integer)''')
-	##################################################
-	curs.execute('''DROP VIEW [VW_SUM_ATT]''')
-	curs.execute('''CREATE VIEW [VW_SUM_ATT] AS SELECT * FROM MAM_ATTEMPT LEFT JOIN MAM_SUMS ON MAM_ATTEMPT.ATT_SUM_ID = MAM_SUMS.SUM_AUTOID''')
-	reviewVWSUMATTOutput(testDBConn, curs)
-	
+    '''
+    Create tables and insert test data
+    '''
+    curs = testDBConn.cursor()
+    clearDownDB(testDBConn, curs)
+    # Create User table and populate it
+    curs.execute('''create table MAM_PLAYER (PLA_AUTOID integer primary key, PLA_USERNAME text unique, PLA_REALNAME text)''')
+    curs.execute("insert into MAM_PLAYER values\
+            (NULL,'dad','Richard Shea')")
+    curs.execute("insert into MAM_PLAYER values\
+            (NULL,'jds','John Shea')")
+    curs.execute("insert into MAM_PLAYER values\
+            (NULL,'ems','Emma Shea')")
+    curs.execute("insert into MAM_PLAYER values\
+            (NULL,'mum','Kerry-Lynn Sorrell')")
+    testDBConn.commit()
+    ##################################################
+    # Create Operations Table             
+    curs.execute('''create table MAM_OPERATIONS 
+      (OPE_AUTOID integer primary key, OPE_OPERATOR text unique,
+        OPE_DESCRIPTION text)''')
+    curs.execute("insert into MAM_OPERATIONS values (NULL,'+','Adding')")
+    curs.execute("insert into MAM_OPERATIONS values (NULL,'-','Subtracting')")
+    curs.execute("insert into MAM_OPERATIONS values (NULL,'x','Multiplying')")
+    testDBConn.commit()
+    ##################################################
+    curs.execute('''create table MAM_SUMS (SUM_AUTOID integer primary key, SUM_OPE_ID integer, SUM_LHS integer, SUM_RHS integer)''')
+    insertSums(testDBConn, curs)
+    ##################################################
+    curs.execute('''create table MAM_ATTEMPT (ATT_AUTOID integer primary key, ATT_PLA_ID integer, ATT_SUM_ID integer, ATT_TIMESTAMP timestamp, ATT_COMPLETED boolean, ATT_CORRECT boolean, FOREIGN KEY(ATT_SUM_ID) REFERENCES MAM_SUMS(SUM_AUTOID))''')
+    insertAttempts(testDBConn, curs)
+    ##################################################
+    curs.execute('''create table MAM_QUESTION (QUE_AUTOID integer primary key, QUE_PLA_ID integer, QUE_ORDER integer, QUE_INUSE boolean, QUE_OPERATION text, QUE_LHS integer, QUE_RHS integer)''')
+    ##################################################
+    curs.execute('''DROP VIEW [VW_SUM_ATT]''')
+    curs.execute('''CREATE VIEW [VW_SUM_ATT] AS SELECT * FROM MAM_ATTEMPT LEFT JOIN MAM_SUMS ON MAM_ATTEMPT.ATT_SUM_ID = MAM_SUMS.SUM_AUTOID''')
+    reviewVWSUMATTOutput(testDBConn, curs)
+    
 def reviewVWSUMATTOutput(conn, curs):
-	curs.execute('''SELECT * FROM VW_SUM_ATT''')
-	f = open('VWSUMATTDump.txt', 'w+')
-	lstSQL = curs.fetchall()
-	f.write(str(curs.description))
-	f.write('\n')
-	for r in lstSQL:
-		f.write(str(r))
-		f.write('\n')
-	f.close()
+    curs.execute('''SELECT * FROM VW_SUM_ATT''')
+    f = open('VWSUMATTDump.txt', 'w+')
+    lstSQL = curs.fetchall()
+    f.write(str(curs.description))
+    f.write('\n')
+    for r in lstSQL:
+        f.write(str(r))
+        f.write('\n')
+    f.close()
 
 def insertSums(conn, curs):
-	curs.execute('''DELETE FROM MAM_SUMS''')
-	conn.commit()		
-	#for rhs in range(2,12):
-	for lhs in MMDBConstants.LHS_CANDIDATES[:MMDBConstants.LHS_STARTOFFSET]:
-		for rhs in MMDBConstants.RHS_CANDIDATES[:MMDBConstants.RHS_STARTOFFSET]: 
-			curs.execute('''insert into MAM_SUMS values (NULL, 3, %s, %s)''' % (lhs,rhs))
-	conn.commit()		
-	#
-	curs.execute('''SELECT * FROM MAM_SUMS''')
-	f = open('SUMDumpFromInsertSums.txt', 'w')
-	lstSQL = curs.fetchall()
+    curs.execute('''DELETE FROM MAM_SUMS''')
+    conn.commit()       
+    #for rhs in range(2,12):
+    for lhs in MMDBConstants.LHS_CANDIDATES[:MMDBConstants.LHS_STARTOFFSET]:
+        for rhs in MMDBConstants.RHS_CANDIDATES[:MMDBConstants.RHS_STARTOFFSET]: 
+            curs.execute('''insert into MAM_SUMS values (NULL, 3, %s, %s)''' % (lhs,rhs))
+    conn.commit()       
+    #
+    curs.execute('''SELECT * FROM MAM_SUMS''')
+    f = open('SUMDumpFromInsertSums.txt', 'w')
+    lstSQL = curs.fetchall()
 
-	for r in lstSQL:
-		f.write(str(r))
-		f.write('\n')
-	f.close()
+    for r in lstSQL:
+        f.write(str(r))
+        f.write('\n')
+    f.close()
 
 def insertAttempts(conn, curs):
-	import datetime, time
-	from datetime import timedelta
-	import random		
-	#===========================================================
-	curs.execute('''SELECT * FROM MAM_SUMS''')
-	f = open('SUMDumpFromInsertAttempts.txt', 'w')
-	lstSQL = curs.fetchall()
-	for r in lstSQL:
-		f.write(str(r))
-		f.write('\n')
-	f.close()
-	#===========================================================
+    import datetime, time
+    from datetime import timedelta
+    import random       
+    #===========================================================
+    curs.execute('''SELECT * FROM MAM_SUMS''')
+    f = open('SUMDumpFromInsertAttempts.txt', 'w')
+    lstSQL = curs.fetchall()
+    for r in lstSQL:
+        f.write(str(r))
+        f.write('\n')
+    f.close()
+    #===========================================================
 
-	curs.execute('''DELETE FROM MAM_ATTEMPT''')
-	conn.commit()		
-	curs.execute('''SELECT * FROM MAM_SUMS''')
-	lstSUM = curs.fetchall()
+    curs.execute('''DELETE FROM MAM_ATTEMPT''')
+    conn.commit()       
+    curs.execute('''SELECT * FROM MAM_SUMS''')
+    lstSUM = curs.fetchall()
 
-	iCount = 0
-	for sumrow in lstSUM:
-		sumid = sumrow[0]
-		now = datetime.datetime.now()
-		now = now - timedelta(minutes=12)
-		for minoffset in [1,1,2,1]:
-			secoffset = random.randrange(0, 59)
-			millisecondsoffset = random.randrange(0,999)
-			microsecondsoffset = random.randrange(0,999)
-			now = now + timedelta(minutes=minoffset, seconds=secoffset, milliseconds=millisecondsoffset, microseconds=microsecondsoffset)
-			if iCount % 3 == 0:
-				blnCorrect = 0
-			else:
-				blnCorrect = 1
-			iCount += 1
-			curs.execute('''insert into MAM_ATTEMPT values (NULL, 1 , ?, ?, 1, ?)''',(sumid, now, blnCorrect))
-	conn.commit()		
-	curs.execute('''SELECT * FROM MAM_ATTEMPT''')
-	f = open('ATTDumpFromInsertAttempts.txt', 'w')
-	lstSQL = curs.fetchall()
-	for r in lstSQL:
-		f.write(str(r))
-		f.write('\n')
-	f.close()
+    iCount = 0
+    for sumrow in lstSUM:
+        sumid = sumrow[0]
+        now = datetime.datetime.now()
+        now = now - timedelta(minutes=12)
+        for minoffset in [1,1,2,1]:
+            secoffset = random.randrange(0, 59)
+            millisecondsoffset = random.randrange(0,999)
+            microsecondsoffset = random.randrange(0,999)
+            now = now + timedelta(minutes=minoffset, seconds=secoffset, milliseconds=millisecondsoffset, microseconds=microsecondsoffset)
+            if iCount % 3 == 0:
+                blnCorrect = 0
+            else:
+                blnCorrect = 1
+            iCount += 1
+            curs.execute('''insert into MAM_ATTEMPT values (NULL, 1 , ?, ?, 1, ?)''',(sumid, now, blnCorrect))
+    conn.commit()       
+    curs.execute('''SELECT * FROM MAM_ATTEMPT''')
+    f = open('ATTDumpFromInsertAttempts.txt', 'w')
+    lstSQL = curs.fetchall()
+    for r in lstSQL:
+        f.write(str(r))
+        f.write('\n')
+    f.close()
 
 def clearDownDB(testDBConn, curs):
-	'''
-	Drop all tables from the database to all facilitate repopulation
-	'''
-	curs.execute('''select name from sqlite_master where type = "table"''')
-	lstSQL = curs.fetchall()
-	print lstSQL 
-	for tableName in lstSQL:
-		print tableName
-		print('''drop table %s''' % tableName)
-		curs.execute('''drop table %s''' % tableName)
-	testDBConn.commit()
+    '''
+    Drop all tables from the database to all facilitate repopulation
+    '''
+    curs.execute('''select name from sqlite_master where type = "table"''')
+    lstSQL = curs.fetchall()
+    print lstSQL 
+    for tableName in lstSQL:
+        print tableName
+        print('''drop table %s''' % tableName)
+        curs.execute('''drop table %s''' % tableName)
+    testDBConn.commit()

File MathsMish/diagnostic.py

 import MathsMish.MMDBLogger
 import logging
 def mmeval(s):
-	s = s.replace("x", "*")
-	answer = eval(s)
-	return answer
+    s = s.replace("x", "*")
+    answer = eval(s)
+    return answer
 module_logger = logging.getLogger("MMDB.primary")
 qMachine=QuestionMachine(1,'x')
 l = qMachine.CandidateSpace
 for ll in l:
-	print ll
+    print ll
 print len(qMachine.CandidateSpace)
 print "About to start getting questions"
 for i in range(20):
-	aQuestion = qMachine.getNextQuestion()
-	questionInString = "%s %s %s" % (aQuestion.sum.lhs, aQuestion.sum.operator, aQuestion.sum.rhs)
-	print questionInString
-	logging.debug(questionInString)
-	answer = mmeval(questionInString)
-	if i % 3 == 0:
-		Adjustedanswer = answer + 1
-	else:
-		Adjustedanswer = answer
-	module_logger.debug("Question is : %s. Calculated Answer is %s. Adjusted Answer is %s" % (questionInString, answer, Adjustedanswer))
-	module_logger.debug("dir(qq) = " % (dir(aQuestion)))
-	aQuestion.suppliedAnswer = Adjustedanswer
-	qMachine.answerQuestion(Adjustedanswer, aQuestion)
+    aQuestion = qMachine.getNextQuestion()
+    questionInString = "%s %s %s" % (aQuestion.sum.lhs, aQuestion.sum.operator, aQuestion.sum.rhs)
+    print questionInString
+    logging.debug(questionInString)
+    answer = mmeval(questionInString)
+    if i % 3 == 0:
+        Adjustedanswer = answer + 1
+    else:
+        Adjustedanswer = answer
+    module_logger.debug("Question is : %s. Calculated Answer is %s. Adjusted Answer is %s" % (questionInString, answer, Adjustedanswer))
+    module_logger.debug("dir(qq) = " % (dir(aQuestion)))
+    aQuestion.suppliedAnswer = Adjustedanswer
+    qMachine.answerQuestion(Adjustedanswer, aQuestion)
 print "Finished in loop"
 
 

File MathsMish/mmdb/BusinessLogic/AttemptManager.py

 from MathsMish.mmdb.BusinessLogic.SumManager import SumManager
 import datetime, time
 class AttemptManager:
-	"""Business Logic Layer intermediary for Attempt objects"""
-	def __init__(self):
-		self.data = []
+    """Business Logic Layer intermediary for Attempt objects"""
+    def __init__(self):
+        self.data = []
 
-	@staticmethod
-	def GetAllForUser(user):
-		return AttemptDB.GetAllForUser(user)
+    @staticmethod
+    def GetAllForUser(user):
+        return AttemptDB.GetAllForUser(user)
 
-	@staticmethod
-	def GetCountOfRHSSuccesses(user, lstRHS):
-		'''
-		Returns a list of lists. The first element in each list is a value which
-		has previously been used as LHS operand. The second element is a count
-		of how many of the possible RHS candidates, previously used with the LHS
-		have been answered succesfully by this user
-		'''
-		if isinstance(lstRHS, list):
-			pass
-		else:
-			lstRHS = [lstRHS]
+    @staticmethod
+    def GetCountOfRHSSuccesses(user, lstRHS):
+        '''
+        Returns a list of lists. The first element in each list is a value which
+        has previously been used as LHS operand. The second element is a count
+        of how many of the possible RHS candidates, previously used with the LHS
+        have been answered succesfully by this user
+        '''
+        if isinstance(lstRHS, list):
+            pass
+        else:
+            lstRHS = [lstRHS]
 
-		return AttemptDB.GetCountsSuccessesForUserAndRHSOperands(user, lstRHS)
+        return AttemptDB.GetCountsSuccessesForUserAndRHSOperands(user, lstRHS)
 
-	@staticmethod
-	def GetCountOfLHSSuccesses(user, lstLHS):
-		'''
-		Returns a list of lists. The first element in each list is a value which
-		has previously been used as LHS operand. The second element is a count
-		of how many of the possible RHS candidates, previously used with the LHS
-		have been answered succesfully by this user
-		'''
-		if isinstance(lstLHS, list):
-			pass
-		else:
-			lstLHS = [lstLHS]
+    @staticmethod
+    def GetCountOfLHSSuccesses(user, lstLHS):
+        '''
+        Returns a list of lists. The first element in each list is a value which
+        has previously been used as LHS operand. The second element is a count
+        of how many of the possible RHS candidates, previously used with the LHS
+        have been answered succesfully by this user
+        '''
+        if isinstance(lstLHS, list):
+            pass
+        else:
+            lstLHS = [lstLHS]
 
-		return AttemptDB.GetCountsSuccessesForUserAndLHSOperands(user, lstLHS)
+        return AttemptDB.GetCountsSuccessesForUserAndLHSOperands(user, lstLHS)
 
-	@staticmethod
-	def Insert(myAttempt):
-		'''
-		Add to the ATT table to reflect this answer
+    @staticmethod
+    def Insert(myAttempt):
+        '''
+        Add to the ATT table to reflect this answer
 
-		myAttempt: An Attempt object
-		user: The userid of the person who's made the attempt 
-		'''
-		
-		lstSUM = SumManager.GetForOperands(myAttempt.question.sum.lhs, myAttempt.question.sum.rhs, myAttempt.question.sum.operator)
-		if len(lstSUM) != 1:
-			raise DatabaseIntegrityError
-		else:
-			myAttempt.question.sum.id = lstSUM[0][0]
-			
-		AttemptDB.Insert(myAttempt)
+        myAttempt: An Attempt object
+        user: The userid of the person who's made the attempt 
+        '''
+        
+        lstSUM = SumManager.GetForOperands(myAttempt.question.sum.lhs, myAttempt.question.sum.rhs, myAttempt.question.sum.operator)
+        if len(lstSUM) != 1:
+            raise DatabaseIntegrityError
+        else:
+            myAttempt.question.sum.id = lstSUM[0][0]
+            
+        AttemptDB.Insert(myAttempt)
 
-	@staticmethod
-	def GetCountOfAllSuccesses(user):
-		'''
-		Returns two dictionaries which contain counts of successful attempts
-		keyed by LHS and RHS operand. One dictionary has an initial key of 
-		the LHS operand, the other has an initial key of the RHS operand
-		'''
+    @staticmethod
+    def GetCountOfAllSuccesses(user):
+        '''
+        Returns two dictionaries which contain counts of successful attempts
+        keyed by LHS and RHS operand. One dictionary has an initial key of 
+        the LHS operand, the other has an initial key of the RHS operand
+        '''
 
-		RHSCOL = 3
-		LHSCOL = 2
+        RHSCOL = 3
+        LHSCOL = 2
 
-		#if isinstance(lstLHS, list):
-		#	pass
-		#else:
-		#	lstLHS = [lstLHS]
+        #if isinstance(lstLHS, list):
+        #   pass
+        #else:
+        #   lstLHS = [lstLHS]
 
-		lstATT = AttemptDB.GetCountsSuccessesForUser(user)
+        lstATT = AttemptDB.GetCountsSuccessesForUser(user)
 
-		dicLHS = {}
-		dicRHS = {}
+        dicLHS = {}
+        dicRHS = {}
 
-		for row in lstATT:
-			#Load row into dicLHS 
-			if row[LHSCOL] not in  dicLHS:
-				dicLHS[row[LHSCOL]] = {}
-			dicLHS[row[LHSCOL]][row[RHSCOL]] = None 
-			#Load row into dicRHS 
-			if row[RHSCOL] not in  dicRHS:
-				dicRHS[row[RHSCOL]] = {}
-			dicRHS[row[RHSCOL]][row[LHSCOL]] = None 
+        for row in lstATT:
+            #Load row into dicLHS 
+            if row[LHSCOL] not in  dicLHS:
+                dicLHS[row[LHSCOL]] = {}
+            dicLHS[row[LHSCOL]][row[RHSCOL]] = None 
+            #Load row into dicRHS 
+            if row[RHSCOL] not in  dicRHS:
+                dicRHS[row[RHSCOL]] = {}
+            dicRHS[row[RHSCOL]][row[LHSCOL]] = None 
 
-		return [dicLHS, dicRHS]
-	@staticmethod
-	def GetAllWithAttemptDetailsForUser(user):
-		return AttemptDB.GetAllSumsWithAttemptDetailsForUser(user)
+        return [dicLHS, dicRHS]
+    @staticmethod
+    def GetAllWithAttemptDetailsForUser(user):
+        return AttemptDB.GetAllSumsWithAttemptDetailsForUser(user)
 

File MathsMish/mmdb/BusinessLogic/QuestionManager.py

 from MathsMish.mmdb.mmdbConnection import SQLLITETRUE 
 from MathsMish.mmdb.mmdbConnection import SQLLITEFALSE
 class QuestionManager(object):
-	"""Business Logic Layer intermediary for Question objects"""
-	def __init__(self):
-		Super.__init__()
-		self.data = []
+    """Business Logic Layer intermediary for Question objects"""
+    def __init__(self):
+        Super.__init__()
+        self.data = []
 
-	@staticmethod
-	def InsertIfNecessary(lq):
-		'''
-		Populate the SUM table with any sums not currently extant.
+    @staticmethod
+    def InsertIfNecessary(lq):
+        '''
+        Populate the SUM table with any sums not currently extant.
 
-		lq: List of Question objects
-		'''
-	
-		#Convert list of Questions to list of Dictionaries
-		lstIn = []
+        lq: List of Question objects
+        '''
+    
+        #Convert list of Questions to list of Dictionaries
+        lstIn = []
 
-		for q in lq:
-			inUseBln = None
-			if q[2] == True:
-				inUseBln = SQLLITETRUE
-			elif q[2] == False:
-				inUseBln = SQLLITEFALSE
-			else:
-				raise MMDBExceptions.FallingOutOfIfStatement 
-			lstIn.append({'userid':q[0], 'order': q[1], 'inuse': inUseBln, 'operator': q[3], 'lhs':q[4] ,'rhs':q[5]})
+        for q in lq:
+            inUseBln = None
+            if q[2] == True:
+                inUseBln = SQLLITETRUE
+            elif q[2] == False:
+                inUseBln = SQLLITEFALSE
+            else:
+                raise MMDBExceptions.FallingOutOfIfStatement 
+            lstIn.append({'userid':q[0], 'order': q[1], 'inuse': inUseBln, 'operator': q[3], 'lhs':q[4] ,'rhs':q[5]})
 
-		QuestionDB.InsertIfNecessary(lstIn)
+        QuestionDB.InsertIfNecessary(lstIn)
 

File MathsMish/mmdb/BusinessLogic/SumManager.py

 from MathsMish.mmdb.DataAccess.SumDB import SumDB
 class SumManager(object):
-	"""Business Logic Layer intermediary for Sum objects"""
-	def __init__(self):
-		Super.__init__()
-		self.data = []
+    """Business Logic Layer intermediary for Sum objects"""
+    def __init__(self):
+        Super.__init__()
+        self.data = []
 
-	@staticmethod
-	def GetForOperands(lhs, rhs, operator):
-		dicIn = {'lhs':lhs, 'rhs':rhs, 'operator':operator}
-		return SumDB.GetForOperands(dicIn)
+    @staticmethod
+    def GetForOperands(lhs, rhs, operator):
+        dicIn = {'lhs':lhs, 'rhs':rhs, 'operator':operator}
+        return SumDB.GetForOperands(dicIn)
 
-	@staticmethod
-	def InsertIfNecessary(lq):
-		'''
-		Populate the SUM table with any sums not currently extant.
+    @staticmethod
+    def InsertIfNecessary(lq):
+        '''
+        Populate the SUM table with any sums not currently extant.
 
-		lq: List of Question objects
-		'''
-	
-		#Convert list of Questions to list of Dictionaries
-		lstIn = []
-		for q in lq:
-			lstIn.append({'lhs':q.sum.lhs,'rhs':q.sum.rhs,'operator':q.sum.operator})
-		SumDB.InsertIfNecessary(lstIn)
+        lq: List of Question objects
+        '''
+    
+        #Convert list of Questions to list of Dictionaries
+        lstIn = []
+        for q in lq:
+            lstIn.append({'lhs':q.sum.lhs,'rhs':q.sum.rhs,'operator':q.sum.operator})
+        SumDB.InsertIfNecessary(lstIn)
 

File MathsMish/mmdb/BusinessObject/Attempt.py

 from MathsMish.mmdb.BusinessObject.Sum import Sum 
 class Attempt(object):
     def __init__(self, whn = None, lhs = None, rhs = None, op = None, correct = None, uid = None, suppAns = None):
-	self._player = Player(uid)
-	self._question = Question(lhs, rhs, op, suppliedAnswer= suppAns)
-        self._when = whn 
-	self._correct = None 
+        self._player = Player(uid)
+        self._question = Question(lhs, rhs, op, suppliedAnswer= suppAns)
+            self._when = whn 
+        self._correct = None 
 
     def getsum(self):
         return self._question

File MathsMish/mmdb/BusinessObject/Player.py

 class Player(object):
     def __init__(self, id = None, username = None, fullname = None):
-	self._id = id 
+        self._id = id 
         self._username = username 
-	self._fullname = fullname 
+        self._fullname = fullname 
 
     def getid(self):
         return self._id

File MathsMish/mmdb/BusinessObject/Question.py

         if operator == "*":
             operator = "x"
         self.__validateInitArgs(lhs, rhs, operator)
-	
-	self.__sum = Sum(lhs, rhs, operator)
-	self.__inuse = inuse 
-	self.__order = order 
-	self.__userid = userid 
-	self.__suppliedAnswer = suppliedAnswer 
-	
+    
+    self.__sum = Sum(lhs, rhs, operator)
+    self.__inuse = inuse 
+    self.__order = order 
+    self.__userid = userid 
+    self.__suppliedAnswer = suppliedAnswer 
+    
     def __str__(self):
         return "%s %s %s" % (self.sum.lhs, self.sum.operator, self.sum.rhs)
 
     def setsum(self, value):
         self.__sum = value
 
-    sum = property(getsum, setsum, "I'm the 'sum' property.")	
+    sum = property(getsum, setsum, "I'm the 'sum' property.")   
 
     def getSuppliedAnswer(self):
         return self.__suppliedAnswer
     def setSuppliedAnswer(self, value):
         self.__suppliedAnswer = value
 
-    suppliedAnswer = property(getSuppliedAnswer, setSuppliedAnswer, "I'm the 'SuppliedAnswer' property.")	
+    suppliedAnswer = property(getSuppliedAnswer, setSuppliedAnswer, "I'm the 'SuppliedAnswer' property.")   
 
 
     def getinuse(self):
                 pass
         else:
                 raise MathsMish.MMDBExceptions.AnswerNotAnInteger
-	    
-	if self.sum.correctAnswer == self.suppliedAnswer:
-	    return True
+        
+        if self.sum.correctAnswer == self.suppliedAnswer:
+            return True
         else:
-	    return False
+            return False
     
     def hasBeenAnswered(self):
         if self.suppliedAnswer == None:
-	    return False
-	else:
-	    return True
-	
+        return False
+    else:
+        return True
+    
     def __validateInitArgs(self, lhs, rhs, operator):
         try:
                 operand = int(lhs)

File MathsMish/mmdb/BusinessObject/Range.py

 class Range:
-	def __init__(self, lowlhs, highrhs, lowrhs, highrhs):
-		self.__lowlhs = lowlhs
-		self.__highlhs = highlhs
-		self.__lowrhs = lowrhs
-		self.__highrhs = highrhs
+    def __init__(self, lowlhs, highrhs, lowrhs, highrhs):
+        self.__lowlhs = lowlhs
+        self.__highlhs = highlhs
+        self.__lowrhs = lowrhs
+        self.__highrhs = highrhs
 
-	def getlowlhs(self):
-		return self.__lowlhs
-	def setlowlhs(self, value):
-		self.__lowlhs = value
+    def getlowlhs(self):
+        return self.__lowlhs
+    def setlowlhs(self, value):
+        self.__lowlhs = value
 
-	lowlhs = property(getlowlhs, setlowlhs, "I'm the 'lowlhs' property.")
+    lowlhs = property(getlowlhs, setlowlhs, "I'm the 'lowlhs' property.")
 
-	def gethighlhs(self):
-		return self.__highlhs
-	def sethighlhs(self, value):
-		self.__highlhs = value
+    def gethighlhs(self):
+        return self.__highlhs
+    def sethighlhs(self, value):
+        self.__highlhs = value
 
-	highlhs = property(gethighlhs, sethighlhs, "I'm the 'highlhs' property.")
+    highlhs = property(gethighlhs, sethighlhs, "I'm the 'highlhs' property.")
 
-	def getlowrhs(self):
-		return self.__lowrhs
-	def setlowrhs(self, value):
-		self.__lowrhs = value
+    def getlowrhs(self):
+        return self.__lowrhs
+    def setlowrhs(self, value):
+        self.__lowrhs = value
 
-	lowrhs = property(getlowrhs, setlowrhs, "I'm the 'lowrhs' property.")
+    lowrhs = property(getlowrhs, setlowrhs, "I'm the 'lowrhs' property.")
 
-	def gethighrhs(self):
-		return self.__highrhs
-	def sethighrhs(self, value):
-		self.__highrhs = value
+    def gethighrhs(self):
+        return self.__highrhs
+    def sethighrhs(self, value):
+        self.__highrhs = value
 
-	highrhs = property(gethighrhs, sethighrhs, "I'm the 'highrhs' property.")
+    highrhs = property(gethighrhs, sethighrhs, "I'm the 'highrhs' property.")

File MathsMish/mmdb/BusinessObject/Sum.py

 class Sum(object):
     
     def __init__(self, lhs = None, rhs = None, operator = None, id = None):
-	self._lhs = lhs 
-	self._rhs = rhs 
-	self._operator = operator 
-	self.__id =  id
-	
+    self._lhs = lhs 
+    self._rhs = rhs 
+    self._operator = operator 
+    self.__id =  id
+    
     def __str__(self):
         return "%s %s %s" % (self.lhs, self.operator, self.rhs)
-	
+    
 
     def getlhs(self):
         return self._lhs
 
 
     def getid(self):
-	return self.__operator
+        return self.__operator
 
     def setid(self, value):
-	self.__operator = value
+        self.__operator = value
 
     id = property(getid, setid, "I'm the 'id' property.")
     
     def getCorrectAnswer(self):
-	a = eval(self.__str__().replace("x","*"))
-	return a 
-	
+        a = eval(self.__str__().replace("x","*"))
+        return a 
+    
     correctAnswer = property(getCorrectAnswer, setoperator, "I'm the 'correctanswer' property.")

File MathsMish/mmdb/DataAccess/AttemptDB.py

 WHERE
 SUM_AUTOID IN
 (
-	Select A.[ATT_SUM_ID]
-	From [MAM_ATTEMPT] As A
-	Inner Join (
-	    Select [ATT_AUTOID]
-		  ,max(ATT_TIMESTAMP) as [ATT_TIMESTAMP]
-	    From [MAM_ATTEMPT]
-	    Group By [ATT_SUM_ID]) As [B]
-	On A.ATT_AUTOID = B.ATT_AUTOID
-	And A.ATT_TIMESTAMP = B.ATT_TIMESTAMP
-	WHERE
-	A.ATT_CORRECT = ?
-	AND
-	A.ATT_PLA_ID = ?
+    Select A.[ATT_SUM_ID]
+    From [MAM_ATTEMPT] As A
+    Inner Join (
+        Select [ATT_AUTOID]
+          ,max(ATT_TIMESTAMP) as [ATT_TIMESTAMP]
+        From [MAM_ATTEMPT]
+        Group By [ATT_SUM_ID]) As [B]
+    On A.ATT_AUTOID = B.ATT_AUTOID
+    And A.ATT_TIMESTAMP = B.ATT_TIMESTAMP
+    WHERE
+    A.ATT_CORRECT = ?
+    AND
+    A.ATT_PLA_ID = ?
 )
 AND
 SUM_RHS = ?
 WHERE
 SUM_AUTOID IN
 (
-	Select A.[ATT_SUM_ID]
-	From [MAM_ATTEMPT] As A
-	Inner Join (
-	    Select [ATT_AUTOID]
-		  ,max(ATT_TIMESTAMP) as [ATT_TIMESTAMP]
-	    From [MAM_ATTEMPT]
-	    Group By [ATT_SUM_ID]) As [B]
-	On A.ATT_AUTOID = B.ATT_AUTOID
-	And A.ATT_TIMESTAMP = B.ATT_TIMESTAMP
-	WHERE
-	A.ATT_CORRECT = ?
-	AND
-	A.ATT_PLA_ID = ?
+    Select A.[ATT_SUM_ID]
+    From [MAM_ATTEMPT] As A
+    Inner Join (
+        Select [ATT_AUTOID]
+          ,max(ATT_TIMESTAMP) as [ATT_TIMESTAMP]
+        From [MAM_ATTEMPT]
+        Group By [ATT_SUM_ID]) As [B]
+    On A.ATT_AUTOID = B.ATT_AUTOID
+    And A.ATT_TIMESTAMP = B.ATT_TIMESTAMP
+    WHERE
+    A.ATT_CORRECT = ?
+    AND
+    A.ATT_PLA_ID = ?
 )
 AND
 SUM_LHS = ?
 WHERE
 SUM_AUTOID IN
 (
-	Select A.[ATT_SUM_ID]
-	From [MAM_ATTEMPT] As A
-	Inner Join (
-	    Select [ATT_AUTOID]
-		  ,max(ATT_TIMESTAMP) as [ATT_TIMESTAMP]
-	    From [MAM_ATTEMPT]
-	    Group By [ATT_SUM_ID]) As [B]
-	On A.ATT_AUTOID = B.ATT_AUTOID
-	And A.ATT_TIMESTAMP = B.ATT_TIMESTAMP
-	WHERE
-	A.ATT_CORRECT = ?
-	AND
-	A.ATT_PLA_ID = ?
+    Select A.[ATT_SUM_ID]
+    From [MAM_ATTEMPT] As A
+    Inner Join (
+        Select [ATT_AUTOID]
+          ,max(ATT_TIMESTAMP) as [ATT_TIMESTAMP]
+        From [MAM_ATTEMPT]
+        Group By [ATT_SUM_ID]) As [B]
+    On A.ATT_AUTOID = B.ATT_AUTOID
+    And A.ATT_TIMESTAMP = B.ATT_TIMESTAMP
+    WHERE
+    A.ATT_CORRECT = ?
+    AND
+    A.ATT_PLA_ID = ?
 )
 ORDER BY SUM_LHS, SUM_RHS, SUM_AUTOID
 '''
 MAM_SUMS
 LEFT OUTER JOIN
 (
-	Select A.*
-	From [MAM_ATTEMPT] As A
-	Inner Join (
-	    Select [ATT_AUTOID]
-		  ,max(ATT_TIMESTAMP) as [ATT_TIMESTAMP]
-	    From [MAM_ATTEMPT]
-	    Group By [ATT_SUM_ID]) As [B]
-	On A.ATT_AUTOID = B.ATT_AUTOID
-	And A.ATT_TIMESTAMP = B.ATT_TIMESTAMP
-	WHERE
-	A.ATT_PLA_ID = ?
+    Select A.*
+    From [MAM_ATTEMPT] As A
+    Inner Join (
+        Select [ATT_AUTOID]
+          ,max(ATT_TIMESTAMP) as [ATT_TIMESTAMP]
+        From [MAM_ATTEMPT]
+        Group By [ATT_SUM_ID]) As [B]
+    On A.ATT_AUTOID = B.ATT_AUTOID
+    And A.ATT_TIMESTAMP = B.ATT_TIMESTAMP
+    WHERE
+    A.ATT_PLA_ID = ?
 ) T1
 ON MAM_SUMS.SUM_AUTOID = T1.ATT_SUM_ID
 ORDER BY SUM_AUTOID
 MAM_SUMS
 LEFT OUTER JOIN
 (
-	Select A.*
-	From [MAM_ATTEMPT] As A
-	Inner Join (
-	    Select [ATT_AUTOID]
-		  ,max(ATT_TIMESTAMP) as [ATT_TIMESTAMP]
-	    From [MAM_ATTEMPT]
-	    Group By [ATT_SUM_ID]) As [B]
-	On A.ATT_AUTOID = B.ATT_AUTOID
-	And A.ATT_TIMESTAMP = B.ATT_TIMESTAMP
-	WHERE
-	A.ATT_PLA_ID = ?
+    Select A.*
+    From [MAM_ATTEMPT] As A
+    Inner Join (
+        Select [ATT_AUTOID]
+          ,max(ATT_TIMESTAMP) as [ATT_TIMESTAMP]
+        From [MAM_ATTEMPT]
+        Group By [ATT_SUM_ID]) As [B]
+    On A.ATT_AUTOID = B.ATT_AUTOID
+    And A.ATT_TIMESTAMP = B.ATT_TIMESTAMP
+    WHERE
+    A.ATT_PLA_ID = ?
 ) T1
 ON MAM_SUMS.SUM_AUTOID = T1.ATT_SUM_ID
 ORDER BY SUM_AUTOID
 '''
-			
+            
 
 
 #
 
 class AttemptDB():
 
-	def __init__(self):
-		self.__module_logger = logging.getLogger("MMDB.primary")
-		Super.__init__()
-		pass
+    def __init__(self):
+        self.__module_logger = logging.getLogger("MMDB.primary")
+        Super.__init__()
+        pass
 
-	@staticmethod
-	def GetAllSuccessesForUser(user):
-		return AttemptDB.__GetAllForUserByResultCriteiria(user, Result.Success)
+    @staticmethod
+    def GetAllSuccessesForUser(user):
+        return AttemptDB.__GetAllForUserByResultCriteiria(user, Result.Success)
 
-	@staticmethod
-	def GetAllFailuresForUser(user):
-		return AttemptDB.__GetAllForUserByResultCriteiria(user, Result.Failure)
+    @staticmethod
+    def GetAllFailuresForUser(user):
+        return AttemptDB.__GetAllForUserByResultCriteiria(user, Result.Failure)
 
-	@staticmethod
-	def GetAllForUser(user):
-		return AttemptDB.__GetAllForUserByResultCriteiria(user, Result.SuccessOrFailure)
+    @staticmethod
+    def GetAllForUser(user):
+        return AttemptDB.__GetAllForUserByResultCriteiria(user, Result.SuccessOrFailure)
 
-	@staticmethod
-	def GetAll():
-		mmdbConn = mmdbConnection()
-		conn = mmdbConn.conn
-		c = conn.cursor()
-		c.execute(SELECTATT)
-		lstA = c.fetchmany()
-		return lstA
+    @staticmethod
+    def GetAll():
+        mmdbConn = mmdbConnection()
+        conn = mmdbConn.conn
+        c = conn.cursor()
+        c.execute(SELECTATT)
+        lstA = c.fetchmany()
+        return lstA
 
-	@staticmethod
-	def GetCountsSuccessesForUserAndRHSOperands(user, lstRHSOperands):
-		return AttemptDB.__GetCountsSuccessesForUserAndSpecifiedOperand(user, lstRHSOperands, Operand.RightHandSide)
-	@staticmethod
-	def GetCountsSuccessesForUserAndLHSOperands(user, lstLHSOperands):
-		return AttemptDB.__GetCountsSuccessesForUserAndSpecifiedOperand(user, lstLHSOperands, Operand.LeftHandSide)
-	@staticmethod
-	def Insert(myAttempt):
+    @staticmethod
+    def GetCountsSuccessesForUserAndRHSOperands(user, lstRHSOperands):
+        return AttemptDB.__GetCountsSuccessesForUserAndSpecifiedOperand(user, lstRHSOperands, Operand.RightHandSide)
+    @staticmethod
+    def GetCountsSuccessesForUserAndLHSOperands(user, lstLHSOperands):
+        return AttemptDB.__GetCountsSuccessesForUserAndSpecifiedOperand(user, lstLHSOperands, Operand.LeftHandSide)
+    @staticmethod