diff --git a/BUGS.md b/BUGS.md index 79c7338..2ae79a1 100644 --- a/BUGS.md +++ b/BUGS.md @@ -1,7 +1,7 @@ + BUGS: - guardar state cada vez que topico termina -- logs mostram que está a gerar cada pergunta 2 vezes...?? - reload da página rebenta o estado. - indicar o topico actual no sidebar - session management. close after inactive time. @@ -9,7 +9,6 @@ BUGS: TODO: -- letsencrypt.org - logs de debug devem indicar o user. - implementar http com redirect para https. - topicos no sidebar devem ser links para iniciar um topico acessivel. os inacessiveis devem estar inactivos. @@ -17,8 +16,10 @@ TODO: - mostrar comments quando falha a resposta - generators not working: bcrypt (ver blog) -SOLVED: +FIXED: +- logs mostram que está a gerar cada pergunta 2 vezes...?? +- letsencrypt.org - alterar password. - barra de progresso a funcionar - mostra tópicos do lado esquerdo, indicando quais estão feitos diff --git a/README.md b/README.md index 9d8be8d..5f15e17 100644 --- a/README.md +++ b/README.md @@ -71,12 +71,28 @@ First we need to create a database: ### SSL Certificates +#### Selfsigned We also need certificates for https. Generate selfsigned certificates using openssl: openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 365 -nodes and place them in `aprendizations/certs`. +#### LetsEcrypt + + sudo pkg install py27-certbot # FreeBSD + +Shutdown any server running and the firewall, and then run the script to generate the certificate: + + sudo pfctl -d # disable pf firewall + sudo certbot certonly --standalone -d bit.xdi.uevora.pt + sudo pfctl -e; sudo pfctl -f /etc/pf.conf # enable pf firewall + +Certificates are saved under `/usr/local/etc/letsencrypt/live/bit.xdi.uevora.pt/` which is readable only by root. + +Copy them to `aprendizations/certs` with names `cert.pem` and `key.pem`. And change permissions to be readble (FIXME how to do it with security?) + + ### Testing Run a demonstration: @@ -126,16 +142,16 @@ To correct in FreeBSD, edit `~/.login_conf` to use UTF-8, for example: ## Useful sqlite3 queries -- Which students have already done at least one topic? +Which students have already done at least one topic? sqlite3 students.db "select distinct student_id from studenttopic" -- How many topics have done each student? +How many topics have done each student? sqlite3 students.db "select student_id, count(topic_id) from studenttopic group by student_id" -- What questions have more wrong answers? +What 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/knowledge.py b/knowledge.py index 73c790b..da0d844 100644 --- a/knowledge.py +++ b/knowledge.py @@ -20,27 +20,30 @@ class Knowledge(object): self.depgraph = depgraph self.state = state # {node: level, node: level, ...} - self.topic = self.topic_generator() - self.current_topic = next(self.topic) + self.topic_sequence = nx.topological_sort(self.depgraph) # FIXME - self.questions = self.generate_questions_for_topic(self.current_topic) - self.current_question = None - self.finished_questions = [] + # select a topic to do + self.new_topic() # ------------------------------------------------------------------------ - def topic_generator(self): - self.topic_sequence = nx.topological_sort(self.depgraph) # FIXME for now... - for t in self.topic_sequence: - if self.state.get(t, 0.0) > 0.999: - continue - self.questions = self.generate_questions_for_topic(t) - logger.info(f'Generated {len(self.questions)} questions for topic "{t}"') - yield t + def new_topic(self, topic=None): + if topic is None: + # select the first topic that has level < 0.9 + for topic in self.topic_sequence: + if self.state.get(topic, 0.0) < 0.9: + break + + # FIXME if all are > 0.9, will stay in the last one forever... + self.current_topic = topic + self.current_topic_idx = self.topic_sequence.index(topic) + self.questions = self.generate_questions_for_topic(topic) + self.current_question = None + self.finished_questions = [] # ------------------------------------------------------------------------ def generate_questions_for_topic(self, topic): - factory = self.depgraph.node[topic]['factory'] - return [q.generate() for q in factory] + factory_list = self.depgraph.node[topic]['factory'] + return [q.generate() for q in factory_list] # ------------------------------------------------------------------------ def get_current_question(self): @@ -58,26 +61,24 @@ class Knowledge(object): def get_topic_progress(self): return len(self.finished_questions) / (len(self.finished_questions) + len(self.questions)) - # --- generates a new question given the current state ------------------- + # ------------------------------------------------------------------------ + # if answer to current question is correct generates a new question + # otherwise returns none def new_question(self): logger.debug('Knowledge.new_question()') - if self.current_question is None or self.current_question.get('grade', 0.0) > 0.9999: + if self.current_question is None or \ + self.current_question.get('grade', 0.0) > 0.9: + # if no more questions in this topic, go to the next one + # keep going if there are no questions in the next topics while not self.questions: - # finished topic! self.state[self.current_topic] = 1.0 - self.finished_questions = [] - try: - self.current_topic = next(self.topic) - except StopIteration: - self.topic = self.topic_generator() - self.current_topic = next(self.topic) - self.questions = self.generate_questions_for_topic(self.current_topic) + self.new_topic() self.current_question = self.questions.pop(0) self.current_question['start_time'] = datetime.now() - self.finished_questions.append(self.current_question) # FIXME not yet finished... + self.finished_questions.append(self.current_question) return self.current_question -- libgit2 0.21.2