Commit 84a1054c11302b9054394629529b2363450a5d45

Authored by Miguel Barão
1 parent 64f0b75c
Exists in master and in 1 other branch dev

- Each student is represented by a class Knowledge and checks answers and generates new questions..

- The learn app deals with multiple users, login/logout and database.
Showing 3 changed files with 51 additions and 51 deletions   Show diff stats
1 1
2 -import random 2 +# python standard library
3 from contextlib import contextmanager # `with` statement in db sessions 3 from contextlib import contextmanager # `with` statement in db sessions
4 -from datetime import datetime  
5 import logging 4 import logging
6 5
7 # user installed libraries 6 # user installed libraries
@@ -14,8 +13,8 @@ except ImportError: @@ -14,8 +13,8 @@ except ImportError:
14 sys.exit(1) 13 sys.exit(1)
15 14
16 # this project 15 # this project
17 -import questions  
18 from models import Student, Answer 16 from models import Student, Answer
  17 +from knowledge import Knowledge
19 18
20 # setup logger for this module 19 # setup logger for this module
21 logger = logging.getLogger(__name__) 20 logger = logging.getLogger(__name__)
@@ -25,18 +24,15 @@ logger = logging.getLogger(__name__) @@ -25,18 +24,15 @@ logger = logging.getLogger(__name__)
25 # ============================================================================ 24 # ============================================================================
26 class LearnApp(object): 25 class LearnApp(object):
27 def __init__(self): 26 def __init__(self):
28 - self.factory = questions.QuestionFactory()  
29 - self.factory.load_files(['questions.yaml'], 'demo') # FIXME  
30 self.online = {} 27 self.online = {}
31 28
32 # connect to database and check registered students 29 # connect to database and check registered students
33 db = 'students.db' # FIXME 30 db = 'students.db' # FIXME
34 engine = create_engine(f'sqlite:///{db}', echo=False) 31 engine = create_engine(f'sqlite:///{db}', echo=False)
35 - # self.Session = scoped_session(sessionmaker(bind=engine))  
36 self.Session = sessionmaker(bind=engine) 32 self.Session = sessionmaker(bind=engine)
37 try: 33 try:
38 with self.db_session() as s: 34 with self.db_session() as s:
39 - n = s.query(Student).count() # filter(Student.id != '0'). 35 + n = s.query(Student).count()
40 except Exception as e: 36 except Exception as e:
41 logger.critical('Database not usable.') 37 logger.critical('Database not usable.')
42 raise e 38 raise e
@@ -61,68 +57,37 @@ class LearnApp(object): @@ -61,68 +57,37 @@ class LearnApp(object):
61 self.online[uid] = { 57 self.online[uid] = {
62 'name': student.name, 58 'name': student.name,
63 'number': student.id, 59 'number': student.id,
64 - 'current': None, 60 + 'knowledge': Knowledge(), # FIXME initial state?
65 } 61 }
66 - print(self.online) 62 + # print(self.online)
67 return True 63 return True
68 64
69 # ------------------------------------------------------------------------ 65 # ------------------------------------------------------------------------
70 # logout 66 # logout
71 def logout(self, uid): 67 def logout(self, uid):
72 - del self.online[uid] # FIXME save current question?  
73 -  
74 - # ------------------------------------------------------------------------  
75 - def get_current_question(self, uid):  
76 - return self.online[uid].get('current', None) 68 + del self.online[uid] # FIXME save current state
77 69
78 # ------------------------------------------------------------------------ 70 # ------------------------------------------------------------------------
79 def get_student_name(self, uid): 71 def get_student_name(self, uid):
80 return self.online[uid].get('name', '') 72 return self.online[uid].get('name', '')
81 73
82 # ------------------------------------------------------------------------ 74 # ------------------------------------------------------------------------
83 - # given the currect state, generates a new question for the student  
84 - def new_question_for(self, uid):  
85 - # FIXME  
86 - questions = list(self.factory)  
87 - nextquestion = self.factory.generate(random.choice(questions))  
88 - print(nextquestion)  
89 - self.online[uid]['current'] = nextquestion  
90 - return nextquestion  
91 -  
92 - # ------------------------------------------------------------------------  
93 # check answer and if correct returns new question, otherise returns None 75 # check answer and if correct returns new question, otherise returns None
94 def check_answer(self, uid, answer): 76 def check_answer(self, uid, answer):
95 - question = self.get_current_question(uid)  
96 - print(question)  
97 - print(answer)  
98 -  
99 - if question is not None:  
100 - question['finish_time'] = datetime.now()  
101 - grade = question.correct(answer) # correct answer 77 + knowledge = self.online[uid]['knowledge']
  78 + current_question = knowledge.check_answer(answer)
102 79
  80 + if current_question is not None:
103 with self.db_session() as s: 81 with self.db_session() as s:
104 s.add(Answer( 82 s.add(Answer(
105 - ref=question['ref'],  
106 - grade=question['grade'],  
107 - starttime=str(question['start_time']),  
108 - finishtime=str(question['finish_time']), 83 + ref=current_question['ref'],
  84 + grade=current_question['grade'],
  85 + starttime=str(current_question['start_time']),
  86 + finishtime=str(current_question['finish_time']),
109 student_id=uid)) 87 student_id=uid))
110 s.commit() 88 s.commit()
111 89
112 - correct = grade > 0.99999  
113 - if correct:  
114 - print('CORRECT')  
115 - question = self.new_question_for(uid)  
116 - question['start_time'] = datetime.now()  
117 - return question  
118 - else:  
119 - print('WRONG')  
120 - return None  
121 - else:  
122 - print('FIRST QUESTION')  
123 - question = self.new_question_for(uid)  
124 - question['start_time'] = datetime.now()  
125 - return question 90 + return knowledge.new_question()
126 91
127 # ------------------------------------------------------------------------ 92 # ------------------------------------------------------------------------
128 # helper to manage db sessions using the `with` statement, for example 93 # helper to manage db sessions using the `with` statement, for example
knowledge.py 0 → 100644
@@ -0,0 +1,37 @@ @@ -0,0 +1,37 @@
  1 +
  2 +# python standard library
  3 +import random
  4 +from datetime import datetime
  5 +
  6 +# this project
  7 +import questions
  8 +
  9 +
  10 +# contains the kowledge state of each student.
  11 +class Knowledge(object):
  12 + def __init__(self):
  13 + self.factory = questions.QuestionFactory()
  14 + self.factory.load_files(['questions.yaml'], 'demo') # FIXME
  15 + self.current_question = None
  16 +
  17 + def get_current_question(self):
  18 + return self.current_question
  19 +
  20 + # --- generates a new question given the current state
  21 + def new_question(self):
  22 + # FIXME
  23 + if self.current_question is None or self.current_question.get('grade', 0.0) > 0.9999:
  24 + questions = list(self.factory)
  25 + self.current_question = self.factory.generate(random.choice(questions))
  26 + self.current_question['start_time'] = datetime.now()
  27 +
  28 + return self.current_question
  29 +
  30 + # --- checks answer and updates knowledge state
  31 + # returns current question with correction, time and comments updated
  32 + def check_answer(self, answer):
  33 + question = self.current_question
  34 + if question is not None:
  35 + question['finish_time'] = datetime.now()
  36 + question.correct(answer)
  37 + return question
@@ -130,11 +130,9 @@ class QuestionHandler(BaseHandler): @@ -130,11 +130,9 @@ class QuestionHandler(BaseHandler):
130 130
131 @tornado.web.authenticated 131 @tornado.web.authenticated
132 def post(self): 132 def post(self):
133 - print('================= POST ==============')  
134 # ref = self.get_body_arguments('question_ref') 133 # ref = self.get_body_arguments('question_ref')
135 user = self.current_user 134 user = self.current_user
136 answer = self.get_body_arguments('answer') 135 answer = self.get_body_arguments('answer')
137 -  
138 next_question = self.learn.check_answer(user, answer) 136 next_question = self.learn.check_answer(user, answer)
139 137
140 if next_question is not None: 138 if next_question is not None: