From db04e658cdb955cc98823f2c1520a76c4076d104 Mon Sep 17 00:00:00 2001 From: Miguel Barão Date: Sat, 6 May 2017 19:36:28 +0100 Subject: [PATCH] - added option to select which questions go for a given topic instead of all of them. --- BUGS.md | 3 ++- README.md | 12 +++++++----- app.py | 44 ++++++++++++++++++++++++++++---------------- 3 files changed, 37 insertions(+), 22 deletions(-) diff --git a/BUGS.md b/BUGS.md index 9959fe2..df01047 100644 --- a/BUGS.md +++ b/BUGS.md @@ -1,7 +1,7 @@ BUGS: -- level depender do numero de respostas correctas +- nao permite perguntas repetidas. iterar questions da configuracao em vez das do ficheiro. ver app.py linha 223. - pymips: activar/desactivar instruções - tabs em textarea nao funcionam correctamente (insere 1 espaco em vez de 4) - reportar comentarios após submeter. @@ -27,6 +27,7 @@ TODO: FIXED: +- level depender do numero de respostas correctas - pymips a funcionar - logs mostram que está a gerar cada pergunta 2 vezes...?? - letsencrypt.org diff --git a/README.md b/README.md index 6495aaf..a33bdb1 100644 --- a/README.md +++ b/README.md @@ -72,7 +72,7 @@ First we need to create a database: ### SSL Certificates We need certificates for https. Certificates can be self-signed or certificates validated by a trusted authority. -Self-signed can be used for development, but browsers will complain. +Self-signed can be used for development, but browsers will complain. LetsEncrypt issues trusted and free certificates, but the served must have a fixed IP and a domain name (not dynamic). #### Selfsigned @@ -140,24 +140,26 @@ Reboot. The server should not generate this error, but when using external scripts to generate questions or to correct, these scripts can print unicode strings to stdout. If the terminal does not support unicode, python will generate this exception. -To correct in FreeBSD, edit `~/.login_conf` to use UTF-8, for example: +- FreeBSD fix: edit `~/.login_conf` to use UTF-8, for example: me:\ :charset=UTF-8:\ :lang=en_US.UTF-8: +- Debian fix: check `locale`... + ## Useful sqlite3 queries -Which students have already done at least one topic? +Which students did at least one topic? sqlite3 students.db "select distinct student_id from studenttopic" -How many topics have done each student? +How many topics had each student done? sqlite3 students.db "select student_id, count(topic_id) from studenttopic group by student_id order by count(topic_id) desc" -What questions have more wrong answers? +Which questions have more wrong answers? sqlite3 students.db "select count(ref), ref from answers where grade<1.0 group by ref order by count(ref) desc" diff --git a/app.py b/app.py index 5aad327..4a73149 100644 --- a/app.py +++ b/app.py @@ -146,7 +146,7 @@ class LearnApp(object): # return self.online[uid]['state'].current_question # ------------------------------------------------------------------------ - # check answer and if correct returns new question, otherise returns None + # check answer and if correct returns new question, otherwise returns None def check_answer(self, uid, answer): knowledge = self.online[uid]['state'] current_question = knowledge.check_answer(answer) @@ -168,7 +168,6 @@ class LearnApp(object): # Receives a set of topics (strings like "math/algebra"), # and recursively adds dependencies to the dependency graph def build_dependency_graph(self, config_file): - logger.debug(f'LearnApp.build_dependency_graph("{config_file}")') # Load configuration file try: @@ -189,36 +188,49 @@ class LearnApp(object): topics = config.get('topics', {}) for ref,attr in topics.items(): g.add_node(ref) - if isinstance(attr, list): - # if prop is a list, we assume it's just a list of dependencies - g.add_edges_from((d,ref) for d in attr) - - elif isinstance(attr, dict): + if isinstance(attr, dict): g.node[ref]['name'] = attr.get('name', ref) + g.node[ref]['questions'] = attr.get('questions', []) g.add_edges_from((d,ref) for d in attr.get('deps', [])) - elif isinstance(attr, str): + elif isinstance(attr, list): + # if prop is a list, we assume it's just a list of dependencies + g.add_edges_from((d,ref) for d in attr) + + elif isinstance(attr, str): # FIXME is this really useful?? g.node[ref]['name'] = attr # iterate over topics and create question factories logger.info('Loading:') for ref in g.nodes_iter(): g.node[ref].setdefault('name', ref) - fullpath = path.expanduser(path.join(prefix, ref)) + prefix_ref = path.join(prefix, ref) + fullpath = path.expanduser(prefix_ref) if path.isdir(fullpath): filename = path.join(fullpath, "questions.yaml") else: - logger.error(f'build_dependency_graph: "{fullpath}" is not a directory') + logger.error(f'Cant find directory "{prefix_ref}", ignored...') + continue if path.isfile(filename): - questions = load_yaml(filename, default=[]) - logger.info(f' {len(questions)} questions from "{ref}"') - for q in questions: - q['path'] = fullpath - g.node[ref]['factory'] = [QFactory(q) for q in questions] + loaded_questions = load_yaml(filename, default=[]) + + # if 'questions' is not provided in configuration, load all + if not g.node[ref]['questions']: + g.node[ref]['questions'] = [q['ref'] for q in loaded_questions] + + + # FIXME nao permite perguntas repetidas. iterar questions da configuracao em vez das do ficheiro. + g.node[ref]['factory'] = [] + for q in loaded_questions: + if q['ref'] in g.node[ref]['questions']: + q['path'] = fullpath + g.node[ref]['factory'].append(QFactory(q)) + logger.info(f' {len(g.node[ref]["factory"])} questions from "{ref}"') + else: g.node[ref]['factory'] = [] - logger.error(f'build_dependency_graph: "{filename}" does not exist') + logger.error(f'Cant load "{filename}"') self.depgraph = g return g -- libgit2 0.21.2