Commit 9161ff755aa99eb0ba6ef8e0cd109e56a68422fd

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

choose number of questions per topic in the yaml configuration

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
... ...