Commit 84a1054c11302b9054394629529b2363450a5d45
1 parent
64f0b75c
Exists in
master
and in
1 other branch
- 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
app.py
1 | 1 | |
2 | -import random | |
2 | +# python standard library | |
3 | 3 | from contextlib import contextmanager # `with` statement in db sessions |
4 | -from datetime import datetime | |
5 | 4 | import logging |
6 | 5 | |
7 | 6 | # user installed libraries |
... | ... | @@ -14,8 +13,8 @@ except ImportError: |
14 | 13 | sys.exit(1) |
15 | 14 | |
16 | 15 | # this project |
17 | -import questions | |
18 | 16 | from models import Student, Answer |
17 | +from knowledge import Knowledge | |
19 | 18 | |
20 | 19 | # setup logger for this module |
21 | 20 | logger = logging.getLogger(__name__) |
... | ... | @@ -25,18 +24,15 @@ logger = logging.getLogger(__name__) |
25 | 24 | # ============================================================================ |
26 | 25 | class LearnApp(object): |
27 | 26 | def __init__(self): |
28 | - self.factory = questions.QuestionFactory() | |
29 | - self.factory.load_files(['questions.yaml'], 'demo') # FIXME | |
30 | 27 | self.online = {} |
31 | 28 | |
32 | 29 | # connect to database and check registered students |
33 | 30 | db = 'students.db' # FIXME |
34 | 31 | engine = create_engine(f'sqlite:///{db}', echo=False) |
35 | - # self.Session = scoped_session(sessionmaker(bind=engine)) | |
36 | 32 | self.Session = sessionmaker(bind=engine) |
37 | 33 | try: |
38 | 34 | with self.db_session() as s: |
39 | - n = s.query(Student).count() # filter(Student.id != '0'). | |
35 | + n = s.query(Student).count() | |
40 | 36 | except Exception as e: |
41 | 37 | logger.critical('Database not usable.') |
42 | 38 | raise e |
... | ... | @@ -61,68 +57,37 @@ class LearnApp(object): |
61 | 57 | self.online[uid] = { |
62 | 58 | 'name': student.name, |
63 | 59 | 'number': student.id, |
64 | - 'current': None, | |
60 | + 'knowledge': Knowledge(), # FIXME initial state? | |
65 | 61 | } |
66 | - print(self.online) | |
62 | + # print(self.online) | |
67 | 63 | return True |
68 | 64 | |
69 | 65 | # ------------------------------------------------------------------------ |
70 | 66 | # logout |
71 | 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 | 71 | def get_student_name(self, uid): |
80 | 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 | 75 | # check answer and if correct returns new question, otherise returns None |
94 | 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 | 81 | with self.db_session() as s: |
104 | 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 | 87 | student_id=uid)) |
110 | 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 | 93 | # helper to manage db sessions using the `with` statement, for example | ... | ... |
... | ... | @@ -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 | ... | ... |
serve.py
... | ... | @@ -130,11 +130,9 @@ class QuestionHandler(BaseHandler): |
130 | 130 | |
131 | 131 | @tornado.web.authenticated |
132 | 132 | def post(self): |
133 | - print('================= POST ==============') | |
134 | 133 | # ref = self.get_body_arguments('question_ref') |
135 | 134 | user = self.current_user |
136 | 135 | answer = self.get_body_arguments('answer') |
137 | - | |
138 | 136 | next_question = self.learn.check_answer(user, answer) |
139 | 137 | |
140 | 138 | if next_question is not None: | ... | ... |