Commit 2ed48b705dc5fdb067b6d46d94f078999c3e4f26

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

- added two new fields to the test table in the database: state, comment

- the test state indicates if the test was corrected normally, the student quit, or the test is null because of cheating.
- tests are always stored in the database, even if the student quits.
- added support to review quit tests
@@ -144,7 +144,9 @@ class App(object): @@ -144,7 +144,9 @@ class App(object):
144 starttime=str(t['start_time']), 144 starttime=str(t['start_time']),
145 finishtime=str(t['finish_time']), 145 finishtime=str(t['finish_time']),
146 filename=fpath, 146 filename=fpath,
147 - student_id=t['student']['number'])) 147 + student_id=t['student']['number'],
  148 + state=t['state'],
  149 + comment=''))
148 s.add_all([Question( 150 s.add_all([Question(
149 ref=q['ref'], 151 ref=q['ref'],
150 grade=q['grade'], 152 grade=q['grade'],
@@ -159,13 +161,29 @@ class App(object): @@ -159,13 +161,29 @@ class App(object):
159 161
160 # ----------------------------------------------------------------------- 162 # -----------------------------------------------------------------------
161 def giveup_test(self, uid): 163 def giveup_test(self, uid):
162 - logger.info('Student {0}: gave up.'.format(uid))  
163 t = self.online[uid]['test'] 164 t = self.online[uid]['test']
164 grade = t.giveup() 165 grade = t.giveup()
165 - if t['save_answers']:  
166 - fname = ' -- '.join((t['student']['number'], t['ref'], str(t['finish_time']))) + '.json'  
167 - fpath = path.abspath(path.join(t['answers_dir'], fname))  
168 - t.save_json(fpath) 166 +
  167 + # save JSON with the test
  168 + fname = ' -- '.join((t['student']['number'], t['ref'], str(t['finish_time']))) + '.json'
  169 + fpath = path.abspath(path.join(t['answers_dir'], fname))
  170 + t.save_json(fpath)
  171 +
  172 + # insert test into database
  173 + with self.db_session() as s:
  174 + s.add(Test(
  175 + ref=t['ref'],
  176 + title=t['title'],
  177 + grade=t['grade'],
  178 + starttime=str(t['start_time']),
  179 + finishtime=str(t['finish_time']),
  180 + filename=fpath,
  181 + student_id=t['student']['number'],
  182 + state=t['state'],
  183 + comment=''))
  184 + s.commit()
  185 +
  186 + logger.info('Student {0}: gave up.'.format(uid))
169 return t 187 return t
170 188
171 # ----------------------------------------------------------------------- 189 # -----------------------------------------------------------------------
@@ -29,8 +29,10 @@ class Test(Base): @@ -29,8 +29,10 @@ class Test(Base):
29 __tablename__ = 'tests' 29 __tablename__ = 'tests'
30 id = Column(Integer, primary_key=True) # auto_increment 30 id = Column(Integer, primary_key=True) # auto_increment
31 ref = Column(String) 31 ref = Column(String)
32 - title = Column(String) 32 + title = Column(String) # FIXME depends on ref and should come from another table...
33 grade = Column(Float) 33 grade = Column(Float)
  34 + state = Column(String) # ONGOING, FINISHED, QUIT, NULL
  35 + comment = Column(String)
34 starttime = Column(String) 36 starttime = Column(String)
35 finishtime = Column(String) 37 finishtime = Column(String)
36 filename = Column(String) 38 filename = Column(String)
templates/grade.html
@@ -50,8 +50,16 @@ @@ -50,8 +50,16 @@
50 <div class="container"> 50 <div class="container">
51 <div class="jumbotron drop-shadow"> 51 <div class="jumbotron drop-shadow">
52 <h1>Resultado</h1> 52 <h1>Resultado</h1>
53 - <p>Teve <strong>${t['grade']}</strong> valores na escala de 0 a 20.</p>  
54 - <p>A prova está terminada, pode fechar o browser e desligar o computador.</p> 53 +
  54 + % if t['state'] == 'FINISHED':
  55 + <p>Teve <strong>${t['grade']}</strong> valores na escala de 0 a 20.</p>
  56 +
  57 + % elif t['state'] == 'QUIT':
  58 + <p>Foi registada a sua desistência da prova.</p>
  59 +
  60 + % endif
  61 +
  62 + <p>Pode fechar o browser e desligar o computador.</p>
55 </div> 63 </div>
56 64
57 <div class="panel panel-default drop-shadow"> 65 <div class="panel panel-default drop-shadow">
templates/review.html
@@ -62,7 +62,13 @@ @@ -62,7 +62,13 @@
62 % else: 62 % else:
63 <span class="label label-success">${t['grade']}</span> valores 63 <span class="label label-success">${t['grade']}</span> valores
64 % endif 64 % endif
  65 + % if t['state'] == 'QUIT':
  66 + (DESISTÊNCIA)
  67 + % endif
65 </dd> 68 </dd>
  69 + % if t['comment'] != '':
  70 + <dt>Comentário:</dt><dd>${t['comment']}</dd>
  71 + % endif
66 </dl> 72 </dl>
67 </big> 73 </big>
68 <small> 74 <small>
@@ -116,7 +122,6 @@ @@ -116,7 +122,6 @@
116 ${md_to_html_review(q['text'], q)} 122 ${md_to_html_review(q['text'], q)}
117 </p> 123 </p>
118 </div> 124 </div>
119 -  
120 % else: 125 % else:
121 <div class="panel panel-primary drop-shadow"> 126 <div class="panel panel-primary drop-shadow">
122 <div class="panel-heading clearfix"> 127 <div class="panel-heading clearfix">
@@ -224,6 +229,8 @@ @@ -224,6 +229,8 @@
224 % endif 229 % endif
225 230
226 </div> <!-- panel-body --> 231 </div> <!-- panel-body -->
  232 +
  233 + % if t['state'] == 'FINISHED':
227 <div class="panel-footer"> 234 <div class="panel-footer">
228 % if q['grade'] > 0.99: 235 % if q['grade'] > 0.99:
229 <p class="text-success"> 236 <p class="text-success">
@@ -245,8 +252,10 @@ @@ -245,8 +252,10 @@
245 </p> 252 </p>
246 % endif 253 % endif
247 </div> 254 </div>
  255 + % endif
  256 +
248 </div> <!-- panel --> 257 </div> <!-- panel -->
249 - % endif 258 + % endif # question type
250 </div> <!-- ui-corner-all custom-corners --> 259 </div> <!-- ui-corner-all custom-corners -->
251 % endfor 260 % endfor
252 </div> <!-- container --> 261 </div> <!-- container -->
@@ -202,6 +202,8 @@ class Test(dict): @@ -202,6 +202,8 @@ class Test(dict):
202 super().__init__(d) 202 super().__init__(d)
203 self['start_time'] = datetime.now() 203 self['start_time'] = datetime.now()
204 self['finish_time'] = None 204 self['finish_time'] = None
  205 + self['state'] = 'ONGOING'
  206 + self['comment'] = ''
205 logger.info('Student {}: starting test.'.format(self['student']['number'])) 207 logger.info('Student {}: starting test.'.format(self['student']['number']))
206 208
207 # ----------------------------------------------------------------------- 209 # -----------------------------------------------------------------------
@@ -224,6 +226,7 @@ class Test(dict): @@ -224,6 +226,7 @@ class Test(dict):
224 # Corrects all the answers and computes the final grade 226 # Corrects all the answers and computes the final grade
225 def correct(self): 227 def correct(self):
226 self['finish_time'] = datetime.now() 228 self['finish_time'] = datetime.now()
  229 + self['state'] = 'FINISHED'
227 230
228 grade = 0.0 231 grade = 0.0
229 total_points = 0.0 232 total_points = 0.0
@@ -237,7 +240,8 @@ class Test(dict): @@ -237,7 +240,8 @@ class Test(dict):
237 240
238 # ----------------------------------------------------------------------- 241 # -----------------------------------------------------------------------
239 def giveup(self): 242 def giveup(self):
240 - self['comments'] = 'DESISTIU' 243 + self['finish_time'] = datetime.now()
  244 + self['state'] = 'QUIT'
241 self['grade'] = 0.0 245 self['grade'] = 0.0
242 logger.info('Student {}: gave up.'.format(self['student']['number'])) 246 logger.info('Student {}: gave up.'.format(self['student']['number']))
243 return self['grade'] 247 return self['grade']