Richard Shea avatar Richard Shea committed fc7ecfa Draft

This set of changes resolves problems that previously occurred with determing
the correct question to ask next. Previously the 'weighted distribution' of
question asking (based upon previous successes and whether the question had
been asked at all previously) was not working as it should have.

A part of this release is the mechanism for expanding the set of potential
questions based upon successes to date is currently disabled. This will be
re-enabled in a future release.

Comments (0)

Files changed (8)

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_STARTOFFSET = 6
+    LHS_STARTOFFSET = 7 
     LHS_THRESHOLD = 0.9
     RHS_CANDIDATES = [2,3,4,5,8,6,10,8,7,11,12]
+    #RHS_STARTOFFSET = 2
     RHS_STARTOFFSET = 2
     RHS_THRESHOLD = 0.4
     NEVERASKED_PROB = 0.5

MathsMish/MMDBExceptions.py

 class MathsMishError(Exception): pass
 class NoAnswerError(MathsMishError): pass
 class NotInteger(MathsMishError): pass
+class NotTrueOrFalse(MathsMishError): pass
 class NotValidOperator(MathsMishError): pass
 class NotYetImplemented(MathsMishError): pass
 class FallingOutOfIfStatement(MathsMishError): pass

MathsMish/QuestionMachine.py

         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)
+        myAttempt = Attempt(datetime.datetime.now(), myQuestion.sum.lhs, myQuestion.sum.rhs, myQuestion.sum.operator, None, self.userid, proposedAnswer, completed=True)
         AttemptManager.Insert(myAttempt)
         self.__maintainCandidateAndQuestionSpace()
 
 
     def __maintainCandidateAndQuestionSpace(self):
 
-        self.__QuestionPool = [] 
-        self.__lstAskedMostRecentlyFailed = []
-        self.__lstAskedMostRecentlySucceeded = []
-        self.__lstNeverAsked = []
+        self.QuestionPool = [] 
+        self.lstAskedMostRecentlyFailed = []
+        self.lstAskedMostRecentlySucceeded = []
+        self.lstNeverAsked = []
 
         self.CandidateSpace = self.__buildCandidateSpace()
 
         #Create 'base level' operand lists based upon hardcoded defaults
         self.__addToCandidateSpaceFromDefaults()
         #... now add extra operands based upon past successful answers
-        self.__addToCandidateSpaceBasedUponPastSuccesses()
+
+        #Temporarily remove this while concentrating on the process of feeding
+        #the optimal next question
+        #self.__addToCandidateSpaceBasedUponPastSuccesses()
 
         #Using the lhs/rhs operand candidates we have found build a set of questions
 
                 lq.append(Question(lhs, rhs, self.__operator))
 
         #... now add extra operands based upon past successful answers
-        self.__addToCandidateSpaceBasedUponPastSuccessesNew(lq)
+        #Temporarily remove this while concentrating on the process of feeding
+        #the optimal next question
+        #self.__addToCandidateSpaceBasedUponPastSuccessesNew(lq)
 
         #Ensure all Sums in the proposed space are in the database
         #if not add them in
         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)
+        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:
+        if len(self.lstNeverAsked) == 0:
             raise MathsMishError
 
         if ((lenMostRecentSucceeded > 0) & (lenMostRecentFailed > 0)):
                 neverAskedThreshold = mostRecentlyFailedThreshold
 
 
-            if len(self.__lstAskedMostRecentlySucceeded) == 0:
+            if len(self.lstAskedMostRecentlySucceeded) == 0:
                 neverAskedThreshold = mostRecentlySucceededThreshold
-            if len(self.__lstAskedMostRecentlyFailed) == 0:
+            if len(self.lstAskedMostRecentlyFailed) == 0:
                 neverAskedThreshold = mostRecentlyFailedThreshold
 
 
-        if len(self.__lstNeverAsked) == 0:
+        if len(self.lstNeverAsked) == 0:
             raise MMDBExceptions.MathsMishError
         '''
         
             questionSelector = random.random()
             try:
                 if questionSelector < neverAskedThreshold:
-                    return random.choice(self.__lstNeverAsked)
+                    return random.choice(self.lstNeverAsked)
                 elif questionSelector < mostRecentlySucceededThreshold:
-                    return random.choice(self.__lstAskedMostRecentlySucceeded)
+                    return random.choice(self.lstAskedMostRecentlySucceeded)
                 elif questionSelector < mostRecentlyFailedThreshold:
-                    return random.choice(self.__lstAskedMostRecentlyFailed)
+                    return random.choice(self.lstAskedMostRecentlyFailed)
                 else:
                     raise MMDBExceptions.FallingOutOfIfStatement 
             except IndexError:
             #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)
+            self.QuestionPool.append(myQuestion)
+            if (myAttempt.when == None) or (myAttempt.question.completed == False):
+                self.lstNeverAsked.append(myQuestion)
             else:
-                if myAttempt.question.goodAnswer() == True:
-                    self.__lstAskedMostRecentlySucceeded.append(myQuestion)
-                elif myAttempt.question.goodAnswer() == False: 
-                    self.__lstAskedMostRecentlyFailed.append(myQuestion)
+                if myAttempt.correctAnswer == True:
+                    self.lstAskedMostRecentlySucceeded.append(myQuestion)
+                elif myAttempt.correctAnswer == False: 
+                    self.lstAskedMostRecentlyFailed.append(myQuestion)
                 else:
                     raise MMDBExceptions.FallingOutOfIfStatement 
 
         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)))
+        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))
 

MathsMish/mmdb/BusinessObject/Attempt.py

 from MathsMish.mmdb.BusinessObject.Player import Player 
 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):
+    def __init__(self, whn = None, lhs = None, rhs = None, op = None, correct = None, uid = None, suppAns = None, completed = None):
         self._player = Player(uid)
-        self._question = Question(lhs, rhs, op, suppliedAnswer= suppAns)
+        self._question = Question(lhs, rhs, op, suppliedAnswer = suppAns, completed = completed)
         self._when = whn 
-        self._correct = None 
+        self._correct = correct
 
     def getsum(self):
         return self._question
     when = property(getwhen, setwhen, "I'm the 'when' property.")
 
     def getcorrect(self):
-        return self.question.calculateAnswer()
+        return self._correct
+        #return self.question.calculateAnswer()
 
     correctAnswer = property(getcorrect, None, "I'm the 'correct' property.")
     

MathsMish/mmdb/BusinessObject/Player.py

         self._username = username 
         self._fullname = fullname 
 
+    def __repr__(self):
+        return "Player(id = %s, username = %s, fullname = %s)" % (self._id, self._username, self._fullname)
+
     def getid(self):
         return self._id
     def setid(self, value):

MathsMish/mmdb/BusinessObject/Question.py

 from MathsMish.MMDBConstants import MMDBConstants
 from MathsMish.mmdb.BusinessObject.Sum import Sum 
 class Question(object):
-    def __init__(self, lhs, rhs, operator, inuse = None, order = None, userid = None, suppliedAnswer = None):
+    def __init__(self, lhs, rhs, operator, completed = False, inuse = None, order = None, userid = None, suppliedAnswer = None):
         if operator == "*":
             operator = "x"
-        self.__validateInitArgs(lhs, rhs, operator)
+
+        self.__validateInitArgs(lhs, rhs, operator, completed)
     
         self.__sum = Sum(lhs, rhs, operator)
         self.__inuse = inuse 
         self.__order = order 
         self.__userid = userid 
         self.__suppliedAnswer = suppliedAnswer 
+        self.__completed = completed
     
     def __str__(self):
         return "%s %s %s" % (self.sum.lhs, self.sum.operator, self.sum.rhs)
 
+    def __repr__(self):
+        return "Question(lhs=%s,rhs=%s,operator=%s)" % (self.sum.lhs, self.sum.rhs, self.sum.operator)
+
     def getsum(self):
         return self.__sum
 
 
     suppliedAnswer = property(getSuppliedAnswer, setSuppliedAnswer, "I'm the 'SuppliedAnswer' property.")   
 
+    def getCompleted(self):
+        return self.__completed
+
+    def setCompleted(self, value):
+        self.__completed = value
+
+    completed = property(getCompleted, setCompleted, "I'm the 'Completed' property.")   
 
     def getinuse(self):
         return self.__inuse
         else:
             return True
     
-    def __validateInitArgs(self, lhs, rhs, operator):
+    def __validateInitArgs(self, lhs, rhs, operator, completed):
         try:
                 operand = int(lhs)
         except ValueError:
         try:
                 operand = int(rhs)
         except ValueError:
-                raise MMDBExceptions.NotInteger("RHS parameter is not an integer")
+                raise MathsMish.MMDBExceptions.NotInteger("RHS parameter is not an integer")
         except TypeError:
-                raise MMDBExceptions.NotInteger("RHS parameter is not an integer")
+                raise MathsMish.MMDBExceptions.NotInteger("RHS parameter is not an integer")
 
         if operator not in MMDBConstants.VALID_OPERATORS:
-                raise MMDBExceptions.NotValidOperator
+                raise MathsMish.MMDBExceptions.NotValidOperator
+
+        if completed not in [True, False]:
+                raise MathsMish.MMDBExceptions.NotTrueOrFalse

MathsMish/mmdb/BusinessObject/Sum.py

         self._lhs = lhs 
         self._rhs = rhs 
         self._operator = operator 
-        self.__id =  id
+        self._id =  id
     
     def __str__(self):
         return "%s %s %s" % (self.lhs, self.operator, self.rhs)
+
+    def __repr__(self):
+        return "Sum(lhs=%s,rhs=%s,operator=%s)" % (self._lhs, self._rhs, self._operator)
     
 
     def getlhs(self):

MathsMish/mmdb/DataAccess/AttemptDB.py

 
     @staticmethod
     def __GetCountsSuccessesForUserAndSpecifiedOperand(user, lstOperands, operandType):
-        #import pdb; pdb.set_trace()
         if operandType == Operand.RightHandSide:
             sql = SELECTATTWHENMOSTRECENTRESULTSUCCESSFULRHS
         elif operandType == Operand.LeftHandSide:
                 blnCorrect = False              
             else:
                 raise MMDBExceptions.FallingOutOfIfStatement                
-            lstAttempts.append(Attempt(row['ATT_TIMESTAMP'], row['SUM_LHS'], row['SUM_RHS'], opAsString, blnCorrect))
+
+            blnCompleted = None
+            if row['ATT_COMPLETED'] == SQLLITETRUE:
+                blnCompleted = True
+            elif row['ATT_COMPLETED'] == SQLLITEFALSE:
+                blnCompleted = False
+            elif row['ATT_COMPLETED'] == None:
+                blnCompleted = False              
+            else:
+                raise MMDBExceptions.FallingOutOfIfStatement                
+            lstAttempts.append(Attempt(row['ATT_TIMESTAMP'], row['SUM_LHS'], row['SUM_RHS'], opAsString, blnCorrect, completed=blnCompleted))
         return lstAttempts      
 
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.