Commit 2b30310aa1ed2ecbeadddb8d279177df120d5f0b
1 parent
1ecfefbf
Exists in
master
and in
1 other branch
- path prefix is now given on commandline instead of configuration file. The ide…
…a is to avoid incompatible prefixes on multiple yaml files. - some changes in async functions
Showing
6 changed files
with
30 additions
and
38 deletions
Show diff stats
demo/demo.yaml
1 | 1 | title: Example |
2 | 2 | database: students.db |
3 | -path: ./demo | |
3 | +# path: ./demo | |
4 | 4 | |
5 | 5 | # values applie to each topic, if undefined there |
6 | 6 | # default values are: file=question.yaml, shuffle=True, choose: all |
... | ... | @@ -17,7 +17,6 @@ forgetting_factor: 0.99 |
17 | 17 | # - B |
18 | 18 | # - C |
19 | 19 | topics: |
20 | - | |
21 | 20 | # topic without dependencies |
22 | 21 | math: |
23 | 22 | name: Matemática | ... | ... |
demo/solar_system/questions.yaml
... | ... | @@ -38,13 +38,13 @@ |
38 | 38 | # correct: !regex '[Ss]aturno' |
39 | 39 | |
40 | 40 | # --------------------------------------------------------------------------- |
41 | -- ref: first_3_planets | |
42 | - type: textarea | |
43 | - title: Sistema solar | |
44 | - text: Escreva o nome dos três planetas mais próximos do Sol. (Exemplo `A, B e C`) | |
45 | - correct: correct-first_3_planets.py | |
46 | - # correct: correct-timeout.py | |
47 | - # opcional | |
48 | - answer: Vulcano, Krypton, Plutão | |
49 | - lines: 3 | |
50 | - timeout: 50 | |
41 | +# - ref: first_3_planets | |
42 | +# type: textarea | |
43 | +# title: Sistema solar | |
44 | +# text: Escreva o nome dos três planetas mais próximos do Sol. (Exemplo `A, B e C`) | |
45 | +# correct: correct-first_3_planets.py | |
46 | +# # correct: correct-timeout.py | |
47 | +# # opcional | |
48 | +# answer: Vulcano, Krypton, Plutão | |
49 | +# lines: 3 | |
50 | +# timeout: 50 | ... | ... |
knowledge.py
... | ... | @@ -70,7 +70,7 @@ class StudentKnowledge(object): |
70 | 70 | # questions: list of generated questions to do in the topic |
71 | 71 | # current_question: the current question to be presented |
72 | 72 | # ------------------------------------------------------------------------ |
73 | - def init_topic(self, topic): | |
73 | + async def init_topic(self, topic): | |
74 | 74 | logger.debug(f'StudentKnowledge.init_topic({topic})') |
75 | 75 | |
76 | 76 | # do not allow locked topics |
... | ... | @@ -88,7 +88,7 @@ class StudentKnowledge(object): |
88 | 88 | self.wrong_answers = 0 |
89 | 89 | |
90 | 90 | # select a random set of questions for this topic |
91 | - size = min(self.MAX_QUESTIONS, len(questionlist)) # number of questions | |
91 | + size = len(questionlist) # number of questions FIXME get from topic config | |
92 | 92 | questionlist = random.sample(questionlist, k=size) |
93 | 93 | logger.debug(f'Questions: {", ".join(questionlist)}') |
94 | 94 | ... | ... |
learnapp.py
... | ... | @@ -22,8 +22,8 @@ from tools import load_yaml |
22 | 22 | logger = logging.getLogger(__name__) |
23 | 23 | |
24 | 24 | # ============================================================================ |
25 | -class LearnAppException(Exception): | |
26 | - pass | |
25 | +# class LearnAppException(Exception): | |
26 | +# pass | |
27 | 27 | |
28 | 28 | |
29 | 29 | # ============================================================================ |
... | ... | @@ -61,11 +61,11 @@ class LearnApp(object): |
61 | 61 | session.close() |
62 | 62 | |
63 | 63 | # ------------------------------------------------------------------------ |
64 | - def __init__(self, config_files): | |
64 | + def __init__(self, config_files, prefix): | |
65 | 65 | self.db_setup() # setup database and check students |
66 | 66 | self.online = dict() # online students |
67 | 67 | |
68 | - self.deps = nx.DiGraph() | |
68 | + self.deps = nx.DiGraph(prefix=prefix) | |
69 | 69 | for c in config_files: |
70 | 70 | self.populate_graph(c) |
71 | 71 | |
... | ... | @@ -192,9 +192,9 @@ class LearnApp(object): |
192 | 192 | # Start new topic |
193 | 193 | # ------------------------------------------------------------------------ |
194 | 194 | async def start_topic(self, uid, topic): |
195 | - loop = asyncio.get_running_loop() | |
195 | + student = self.online[uid]['state'] | |
196 | 196 | try: |
197 | - await loop.run_in_executor(None, self.online[uid]['state'].init_topic, topic) | |
197 | + await student.init_topic(topic) | |
198 | 198 | except KeyError as e: |
199 | 199 | logger.warning(f'User "{uid}" tried to open nonexistent topic: "{topic}"') |
200 | 200 | raise e |
... | ... | @@ -277,9 +277,9 @@ class LearnApp(object): |
277 | 277 | # ------------------------------------------------------------------------ |
278 | 278 | def get_current_public_dir(self, uid): |
279 | 279 | topic = self.online[uid]['state'].get_current_topic() |
280 | - p = self.deps.graph['path'] | |
281 | - return path.join(p, topic, 'public') | |
280 | + p = self.deps.graph['prefix'] # FIXME not defined!!! | |
282 | 281 | |
282 | + return path.join(p, topic, 'public') | |
283 | 283 | |
284 | 284 | |
285 | 285 | # ============================================================================ |
... | ... | @@ -304,21 +304,12 @@ class LearnApp(object): |
304 | 304 | g = self.deps # the graph |
305 | 305 | config = load_yaml(conffile) # course configuration |
306 | 306 | |
307 | - # set attributes of the graph | |
308 | - prefix = path.expanduser(config.get('path', '.')) | |
309 | - # title = config.get('title', '') | |
310 | - # database = config.get('database', 'students.db') | |
311 | - | |
312 | 307 | # default attributes that apply to the topics |
313 | 308 | default_file = config.get('file', 'questions.yaml') |
314 | 309 | default_shuffle = config.get('shuffle', True) |
315 | 310 | default_choose = config.get('choose', 9999) |
316 | 311 | default_forgetting_factor = config.get('forgetting_factor', 1.0) |
317 | 312 | |
318 | - # create graph | |
319 | - # g = nx.DiGraph(path=prefix, title=title, database=database, config=config) | |
320 | - | |
321 | - | |
322 | 313 | # iterate over topics and populate graph |
323 | 314 | topics = config.get('topics', {}) |
324 | 315 | tcount = qcount = 0 # topic and question counters |
... | ... | @@ -331,12 +322,12 @@ class LearnApp(object): |
331 | 322 | g.add_node(tref) |
332 | 323 | t = g.node[tref] # current topic node |
333 | 324 | |
334 | - topicpath = path.join(prefix, tref) | |
325 | + topicpath = path.join(g.graph['prefix'], tref) | |
335 | 326 | |
336 | 327 | t['type'] = attr.get('type', 'topic') |
337 | 328 | t['name'] = attr.get('name', tref) |
338 | - t['path'] = topicpath | |
339 | - t['file'] = attr.get('file', default_file) | |
329 | + t['path'] = topicpath # prefix/topic | |
330 | + t['file'] = attr.get('file', default_file) # questions.yaml | |
340 | 331 | t['shuffle'] = attr.get('shuffle', default_shuffle) |
341 | 332 | t['forgetting_factor'] = attr.get('forgetting_factor', default_forgetting_factor) |
342 | 333 | g.add_edges_from((d,tref) for d in attr.get('deps', [])) | ... | ... |
questions.py
... | ... | @@ -154,7 +154,7 @@ class QuestionCheckbox(Question): |
154 | 154 | # set defaults if missing |
155 | 155 | self.set_defaults({ |
156 | 156 | 'text': '', |
157 | - 'correct': [0.0] * n, # useful for questionaries | |
157 | + 'correct': [1.0] * n, # Using 0.0 breaks the (right, wrong) options | |
158 | 158 | 'shuffle': True, |
159 | 159 | 'discount': True, |
160 | 160 | 'choose': n, # number of options | ... | ... |
serve.py
... | ... | @@ -304,9 +304,11 @@ def main(): |
304 | 304 | # --- Commandline argument parsing |
305 | 305 | argparser = argparse.ArgumentParser(description='Server for online learning. Enrolled students and topics have to be previously configured. Please read the documentation included with this software before running the server.') |
306 | 306 | argparser.add_argument('conffile', type=str, nargs='+', |
307 | - help='Topics configuration file in YAML format.') # FIXME only one | |
307 | + help='Topics configuration file in YAML format.') | |
308 | + argparser.add_argument('--prefix', type=str, default='demo', | |
309 | + help='Path prefix under which the topic directories can be found, e.g. ~/topics') | |
308 | 310 | argparser.add_argument('--port', type=int, default=8443, |
309 | - help='Port to be used by the HTTPS server') | |
311 | + help='Port to be used by the HTTPS server, e.g. 8443') | |
310 | 312 | argparser.add_argument('--debug', action='store_true', |
311 | 313 | help='Enable debug messages') |
312 | 314 | arg = argparser.parse_args() |
... | ... | @@ -327,7 +329,7 @@ def main(): |
327 | 329 | # --- start application |
328 | 330 | logging.info('Starting App') |
329 | 331 | try: |
330 | - learnapp = LearnApp(arg.conffile) | |
332 | + learnapp = LearnApp(arg.conffile, prefix=arg.prefix) | |
331 | 333 | except Exception as e: |
332 | 334 | logging.critical('Failed to start backend application') |
333 | 335 | raise e | ... | ... |