app.py
3.94 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
import random
from contextlib import contextmanager # `with` statement in db sessions
# libs
import bcrypt
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker, scoped_session
# this project
import questions
from models import Student
# ============================================================================
# LearnApp - application logic
# ============================================================================
class LearnApp(object):
def __init__(self):
self.factory = questions.QuestionFactory()
self.factory.load_files(['questions.yaml'], 'demo') # FIXME
self.online = {}
# connect to database and check registered students
engine = create_engine('sqlite:///{}'.format('students.db'), echo=False)
self.Session = scoped_session(sessionmaker(bind=engine))
try:
with self.db_session() as s:
n = s.query(Student).filter(Student.id != '0').count()
except Exception as e:
print('Database not usable.')
raise e
else:
print('Database has {} students registered.'.format(n))
# ------------------------------------------------------------------------
def login_ok(self, uid, try_pw):
print('LearnApp.login')
with self.db_session() as s:
student = s.query(Student).filter(Student.id == uid).one_or_none()
if student is None or student in self.online:
# student does not exist
return False
# hashedtry = yield executor.submit(bcrypt.hashpw,
# try_pw.encode('utf-8'), student.password)
hashedtry = bcrypt.hashpw(try_pw.encode('utf-8'), student.password)
if hashedtry != student.password:
# wrong password
return False
# success
self.online[uid] = {
'name': student.name,
'number': student.id,
'current': None,
}
print(self.online)
return True
# ------------------------------------------------------------------------
# logout
def logout(self, uid):
del self.online[uid] # FIXME save current question?
# ------------------------------------------------------------------------
# given the currect state, generates a new question for the student
def new_question_for(self, uid):
questions = list(self.factory)
nextquestion = self.factory.generate(random.choice(questions))
self.online[uid]['current'] = nextquestion
return nextquestion
# ------------------------------------------------------------------------
def get_current_question(self, uid):
return self.online[uid].get('current', None)
# ------------------------------------------------------------------------
def get_student_name(self, uid):
return self.online[uid].get('name', '')
# ------------------------------------------------------------------------
# check answer and if correct returns new question, otherise returns None
def check_answer(self, uid, answer):
question = self.get_current_question(uid)
print('------------------------------')
print(question)
print(answer)
if question is not None:
grade = question.correct(answer) # correct answer
correct = grade > 0.99999
if correct:
print('CORRECT')
return self.new_question_for(uid)
else:
print('WRONG')
return None
else:
print('FIRST QUESTION')
return self.new_question_for(uid)
# ------------------------------------------------------------------------
# helper to manage db sessions using the `with` statement, for example
# with self.db_session() as s: s.query(...)
@contextmanager
def db_session(self):
try:
yield self.Session()
finally:
self.Session.remove()