Commit 03210039c66bdcdc9623a43d47c8ffc8fe8e861d
1 parent
13773677
Exists in
master
and in
1 other branch
- main page ok.
Showing
4 changed files
with
71 additions
and
40 deletions
Show diff stats
knowledge.py
... | ... | @@ -42,45 +42,63 @@ class StudentKnowledge(object): |
42 | 42 | # select a topic to do and initialize questions |
43 | 43 | # self.start_topic() |
44 | 44 | |
45 | + | |
46 | + # ------------------------------------------------------------------------ | |
47 | + # Unlock all topics whose dependencies are satisfied | |
48 | + # ------------------------------------------------------------------------ | |
49 | + def unlock_topics(self): | |
50 | + min_level = 0.01 # minimum level to unlock | |
51 | + for topic in self.topic_sequence: | |
52 | + if topic not in self.state: # if locked | |
53 | + pred = self.deps.predecessors(topic) | |
54 | + if all(d in self.state and self.state[d]['level'] > min_level for d in pred): # dependencies done | |
55 | + self.state[topic] = { | |
56 | + 'level': 0.0, | |
57 | + 'date': datetime.now() | |
58 | + } | |
59 | + logger.debug(f'unlocked {topic}') | |
60 | + | |
61 | + | |
62 | + # ------------------------------------------------------------------------ | |
63 | + # Recommends a topic to practice/learn from the state | |
64 | + # ------------------------------------------------------------------------ | |
65 | + def recommend_topic(self): | |
66 | + pass # FIXME | |
67 | + | |
45 | 68 | # ------------------------------------------------------------------------ |
46 | 69 | # Start a new topic. If not provided, selects the first with level < 0.8 |
47 | 70 | # If all levels > 0.8, will stay in the last one forever... |
48 | 71 | # ------------------------------------------------------------------------ |
49 | 72 | def start_topic(self, topic=''): |
50 | 73 | # unlock topics whose dependencies are done |
51 | - unlocked_topics = [] | |
52 | - for t in self.topic_sequence: | |
53 | - if t not in self.state: # is locked | |
54 | - deps = self.depgraph.predecessors(t) | |
55 | - if all(d in self.state and self.state[d]['level'] > 0.01 for d in deps): # dependencies done | |
56 | - unlocked_topics.append(t) | |
74 | + logger.debug('start_topic ' + topic) | |
57 | 75 | |
58 | - for t in unlocked_topics: | |
59 | - self.state[t] = {'level': 0.0, 'date': datetime.now()} | |
60 | - logger.info(f'Unlocked "{t}"') | |
76 | + self.unlock_topics() | |
61 | 77 | |
62 | 78 | # choose topic |
63 | 79 | if not topic: |
64 | 80 | for topic in self.topic_sequence: |
65 | 81 | unlocked = topic in self.state |
66 | 82 | needs_work = unlocked and self.state[topic]['level'] < 0.8 |
67 | - factory = self.depgraph.node[topic]['factory'] | |
83 | + factory = self.deps.node[topic]['factory'] | |
68 | 84 | if factory and (not unlocked or needs_work): |
69 | 85 | break |
70 | 86 | |
71 | 87 | # use given topic if possible |
72 | 88 | else: |
73 | 89 | unlocked = topic in self.state |
74 | - factory = self.depgraph.node[topic]['factory'] | |
90 | + factory = self.deps.node[topic]['factory'] | |
75 | 91 | if not factory or not unlocked: |
76 | 92 | logger.debug(f'Can\'t start topic "{topic}".') |
77 | 93 | return |
78 | 94 | |
95 | + | |
96 | + | |
79 | 97 | self.current_topic = topic |
80 | 98 | logger.info(f'Topic set to "{topic}"') |
81 | 99 | |
82 | 100 | # generate question instances for current topic |
83 | - questionlist = self.depgraph.node[topic]['questions'] | |
101 | + questionlist = self.deps.node[topic]['questions'] | |
84 | 102 | self.questions = [factory[qref].generate() for qref in questionlist] |
85 | 103 | self.current_question = self.questions.pop(0) # FIXME crashes if questions==[] |
86 | 104 | self.current_question['start_time'] = datetime.now() |
... | ... | @@ -110,7 +128,7 @@ class StudentKnowledge(object): |
110 | 128 | else: |
111 | 129 | self.current_question['start_time'] = datetime.now() |
112 | 130 | else: |
113 | - factory = self.depgraph.node[self.current_topic]['factory'] | |
131 | + factory = self.deps.node[self.current_topic]['factory'] | |
114 | 132 | self.questions.append(factory[q['ref']].generate()) |
115 | 133 | |
116 | 134 | return q | ... | ... |
learnapp.py
... | ... | @@ -289,6 +289,6 @@ def build_dependency_graph(config_file): |
289 | 289 | q['path'] = fullpath |
290 | 290 | tnode['factory'][q['ref']] = QFactory(q) |
291 | 291 | |
292 | - logger.info(f' {len(tnode["questions"])} questions from "{tref}"') | |
292 | + logger.info(f'{len(tnode["questions"]):4} questions from {tref}') | |
293 | 293 | |
294 | 294 | return g | ... | ... |
serve.py
... | ... | @@ -33,7 +33,7 @@ class WebApplication(tornado.web.Application): |
33 | 33 | (r'/change_password', ChangePasswordHandler), |
34 | 34 | (r'/question', QuestionHandler), |
35 | 35 | (r'/', LearnHandler), |
36 | - (r'/topic', TopicHandler), | |
36 | + (r'/topic/(.+)', TopicHandler), | |
37 | 37 | (r'/(.+)', FileHandler), |
38 | 38 | ] |
39 | 39 | settings = { |
... | ... | @@ -109,7 +109,7 @@ class ChangePasswordHandler(BaseHandler): |
109 | 109 | self.write({'msg': notification}) |
110 | 110 | |
111 | 111 | # ---------------------------------------------------------------------------- |
112 | -# main page / | |
112 | +# Main page: / | |
113 | 113 | # Shows a list of topics and proficiency (stars, locked). |
114 | 114 | # ---------------------------------------------------------------------------- |
115 | 115 | class LearnHandler(BaseHandler): |
... | ... | @@ -122,12 +122,14 @@ class LearnHandler(BaseHandler): |
122 | 122 | state=self.learn.get_student_state(uid) |
123 | 123 | ) |
124 | 124 | |
125 | - | |
125 | +# ---------------------------------------------------------------------------- | |
126 | +# Start a given topic: /topic | |
127 | +# ---------------------------------------------------------------------------- | |
126 | 128 | class TopicHandler(BaseHandler): |
127 | 129 | @tornado.web.authenticated |
128 | - def get(self): | |
130 | + def get(self, topic): | |
129 | 131 | uid = self.current_user |
130 | - topic = self.get_query_argument('topic', default='') | |
132 | + # topic = self.get_query_argument('topic', default='') | |
131 | 133 | self.learn.start_topic(uid, topic) |
132 | 134 | self.render('topic.html', |
133 | 135 | uid=uid, | ... | ... |
templates/maintopics.html
... | ... | @@ -42,28 +42,39 @@ |
42 | 42 | </nav> |
43 | 43 | <div class="container"> |
44 | 44 | |
45 | - <h3>Tópicos</h3> | |
45 | + <h3>Tópicos</h3> | |
46 | 46 | |
47 | - <div class="list-group"> | |
48 | - {% for t in state %} | |
49 | - {% if t['level'] is None %} | |
50 | - <a class="list-group-item list-group-item-action disabled" href="#"> | |
51 | - {{ t['name'] }} | |
52 | - <i class="fa fa-lock" aria-hidden="true"></i> | |
53 | - </a> | |
54 | - {% else %} | |
55 | - <a class="list-group-item list-group-item-action" href="/?topic={{ t['ref'] }}"> | |
56 | - {{ t['name'] }} | |
57 | - {% if t['level'] < 0.01 %} | |
58 | - <i class="fa fa-unlock" aria-hidden="true"></i> | |
59 | - | |
60 | - {% else %} | |
61 | - {{ round(t['level']*5)*'<i class="fa fa-star text-success" aria-hidden="true"></i>' + round(5-t['level']*5)*'<i class="fa fa-star-o" aria-hidden="true"></i>' }} | |
62 | - {% end %} | |
63 | - </a> | |
64 | - {% end %} | |
65 | - {% end %} | |
66 | - </div> | |
47 | + <div class="list-group"> | |
48 | + {% for t in state %} | |
49 | + {% if t['level'] is None %} | |
50 | + <a class="list-group-item list-group-item-action disabled" href="#"> | |
51 | + <div class="d-flex justify-content-start"> | |
52 | + <div class="p-2"> | |
53 | + {{ t['name'] }} | |
54 | + </div> | |
55 | + <div class="ml-auto p-2"> | |
56 | + <i class="fa fa-lock" aria-hidden="true"></i> | |
57 | + </div> | |
58 | + </div> | |
59 | + </a> | |
60 | + {% else %} | |
61 | + <a class="list-group-item list-group-item-action" href="/topic/{{t['ref']}}"> | |
62 | + <div class="d-flex justify-content-start"> | |
63 | + <div class="p-2"> | |
64 | + {{ t['name'] }} | |
65 | + </div> | |
66 | + <div class="ml-auto p-2"> | |
67 | + {% if t['level'] < 0.01 %} | |
68 | + <i class="fa fa-unlock float-right" aria-hidden="true"></i> | |
69 | + {% else %} | |
70 | + {{ round(t['level']*5)*'<i class="fa fa-star text-success" aria-hidden="true"></i>' + round(5-t['level']*5)*'<i class="fa fa-star-o" aria-hidden="true"></i>' }} | |
71 | + {% end %} | |
72 | + </div> | |
73 | + </div> | |
74 | + </a> | |
75 | + {% end %} | |
76 | + {% end %} | |
77 | + </div> <!-- list-group --> | |
67 | 78 | </div> |
68 | 79 | |
69 | 80 | <!-- Scripts --> | ... | ... |