Commit 9161ff755aa99eb0ba6ef8e0cd109e56a68422fd
1 parent
c1422ade
Exists in
master
and in
1 other branch
choose number of questions per topic in the yaml configuration
Showing
5 changed files
with
18 additions
and
42 deletions
Show diff stats
BUGS.md
... | ... | @@ -5,10 +5,6 @@ |
5 | 5 | "file: questions.yaml" (default questions.yaml) |
6 | 6 | "shuffle: True/False" (default False) |
7 | 7 | "choose: 6" (default tudo) |
8 | -- SQLAlchemy error (rollback em accao no final de um topico): | |
9 | - Users/mjsb/Library/Python/3.7/lib/python/site-packages/sqlalchemy/sql/crud.py:700: SAWarning: Column 'studenttopic.student_id' is marked as a member of the primary key for table 'studenttopic', but has no Python-side or server-side default generator indicated, nor does it indicate 'autoincrement=True' or 'nullable=True', and no explicit value is passed. Primary key columns typically may not store NULL. Note that as of SQLAlchemy 1.1, 'autoincrement=True' must be indicated explicitly for composite (e.g. multicolumn) primary keys if AUTO_INCREMENT/SERIAL/IDENTITY behavior is expected for one of the columns in the primary key. CREATE TABLE statements are impacted by this change as well on most backends. | |
10 | - util.warn(msg) | |
11 | - | |
12 | 8 | - quando a pergunta devolve comments, este é apresentado, mas fica persistente nas tentativas seguintes. devia ser limpo apos a segunda submissao. |
13 | 9 | - a opcao max_tries na especificacao das perguntas é cumbersome... usar antes tries? |
14 | 10 | - tabelas nas perguntas radio/checkbox não ocupam todo o espaço como em question. | ... | ... |
demo/demo.yaml
1 | 1 | title: Example |
2 | 2 | database: students.db |
3 | 3 | |
4 | +# default global values | |
5 | +file: questions.yaml | |
6 | +shuffle: True | |
7 | +choose: 6 | |
8 | + | |
4 | 9 | # path prefix applied to the topics |
5 | 10 | path: ./demo |
6 | 11 | |
... | ... | @@ -16,6 +21,9 @@ topics: |
16 | 21 | # topic without dependencies |
17 | 22 | math: |
18 | 23 | name: Matemática |
24 | + file: questions.yaml | |
25 | + choose: 6 | |
26 | + shuffle: True | |
19 | 27 | |
20 | 28 | # topic with one dependency |
21 | 29 | solar_system: | ... | ... |
knowledge.py
... | ... | @@ -32,8 +32,8 @@ class StudentKnowledge(object): |
32 | 32 | self.topic_sequence = self.recommend_topic_sequence() # ['a', 'b', ...] |
33 | 33 | self.unlock_topics() # whose dependencies have been done |
34 | 34 | self.current_topic = None |
35 | - | |
36 | - self.MAX_QUESTIONS = 6 # FIXME get from yaml configuration file?? | |
35 | + print(deps.graph) | |
36 | + self.MAX_QUESTIONS = deps.graph['config'].get('choose', 10) | |
37 | 37 | |
38 | 38 | # ------------------------------------------------------------------------ |
39 | 39 | # Updates the proficiency levels of the topics, with forgetting factor | ... | ... |
learnapp.py
... | ... | @@ -29,11 +29,9 @@ class LearnAppException(Exception): |
29 | 29 | # ============================================================================ |
30 | 30 | # helper functions |
31 | 31 | # ============================================================================ |
32 | -async def check_password(try_pw, password): | |
33 | - try_pw = try_pw.encode('utf-8') | |
32 | +async def check_password(try_pw, pw): | |
34 | 33 | loop = asyncio.get_running_loop() |
35 | - hashed_pw = await loop.run_in_executor(None, bcrypt.hashpw, try_pw, password) | |
36 | - return password == hashed_pw | |
34 | + return pw == await loop.run_in_executor(None, bcrypt.hashpw, try_pw.encode('utf-8'), pw) | |
37 | 35 | |
38 | 36 | def bcrypt_hash_gen(pw): |
39 | 37 | return bcrypt.hashpw(pw.encode('utf-8'), bcrypt.gensalt()) |
... | ... | @@ -62,16 +60,9 @@ class LearnApp(object): |
62 | 60 | def __init__(self, config_file): |
63 | 61 | # state of online students |
64 | 62 | self.online = {} |
65 | - | |
66 | - config = load_yaml(config_file) | |
67 | - | |
68 | - # connect to database and checks for registered students | |
69 | - self.db_setup(config['database']) | |
70 | - | |
71 | - # dependency graph shared by all students | |
63 | + config = load_yaml(config_file[0]) | |
64 | + self.db_setup(config['database']) # setup and check students | |
72 | 65 | self.deps = build_dependency_graph(config) |
73 | - | |
74 | - # add topics from dependency graph to the database, if missing | |
75 | 66 | self.db_add_missing_topics(self.deps.nodes()) |
76 | 67 | |
77 | 68 | # ------------------------------------------------------------------------ |
... | ... | @@ -98,8 +89,7 @@ class LearnApp(object): |
98 | 89 | with self.db_session() as s: |
99 | 90 | tt = s.query(StudentTopic).filter_by(student_id=uid) |
100 | 91 | |
101 | - state = {t.topic_id: | |
102 | - { | |
92 | + state = {t.topic_id: { | |
103 | 93 | 'level': t.level, |
104 | 94 | 'date': datetime.strptime(t.date, "%Y-%m-%d %H:%M:%S.%f") |
105 | 95 | } for t in tt} |
... | ... | @@ -108,8 +98,7 @@ class LearnApp(object): |
108 | 98 | 'number': uid, |
109 | 99 | 'name': name, |
110 | 100 | 'state': StudentKnowledge(self.deps, state=state), |
111 | - # 'learning': None, # current topic learning | |
112 | - } | |
101 | + } | |
113 | 102 | |
114 | 103 | else: |
115 | 104 | logger.info(f'User "{uid}" wrong password!') |
... | ... | @@ -209,23 +198,6 @@ class LearnApp(object): |
209 | 198 | logger.info(f'User "{uid}" started "{topic}"') |
210 | 199 | |
211 | 200 | # ------------------------------------------------------------------------ |
212 | - # Start new topic | |
213 | - # ------------------------------------------------------------------------ | |
214 | - # def start_learning(self, uid, topic): | |
215 | - # try: | |
216 | - # ok = self.online[uid]['state'].init_learning(topic) | |
217 | - # except KeyError as e: | |
218 | - # logger.warning( | |
219 | - # f'User "{uid}" tried to open nonexistent topic: "{topic}"') | |
220 | - # raise e | |
221 | - # else: | |
222 | - # if ok: | |
223 | - # logger.info(f'User "{uid}" started "{topic}"') | |
224 | - # else: | |
225 | - # logger.warning(f'User "{uid}" denied locked "{topic}"') | |
226 | - # return ok | |
227 | - | |
228 | - # ------------------------------------------------------------------------ | |
229 | 201 | # Fill db table 'Topic' with topics from the graph if not already there. |
230 | 202 | # ------------------------------------------------------------------------ |
231 | 203 | def db_add_missing_topics(self, nn): |
... | ... | @@ -330,7 +302,7 @@ def build_dependency_graph(config={}): |
330 | 302 | prefix = config.get('path', '.') |
331 | 303 | title = config.get('title', '') |
332 | 304 | database = config.get('database', 'students.db') |
333 | - g = nx.DiGraph(path=prefix, title=title, database=database) | |
305 | + g = nx.DiGraph(path=prefix, title=title, database=database, config=config) | |
334 | 306 | |
335 | 307 | # iterate over topics and build graph |
336 | 308 | topics = config.get('topics', {}) | ... | ... |
serve.py
... | ... | @@ -356,7 +356,7 @@ def main(): |
356 | 356 | # --- start application |
357 | 357 | logging.info('Starting App') |
358 | 358 | try: |
359 | - learnapp = LearnApp(arg.conffile[0]) | |
359 | + learnapp = LearnApp(arg.conffile) | |
360 | 360 | except Exception as e: |
361 | 361 | logging.critical('Failed to start backend application') |
362 | 362 | raise e | ... | ... |