1 #!/usr/bin/env python2.4
2 # -*- encoding: iso-8859-1 -*-
3 # vim: set et sw=4 sts=4 :
13 from sercom.sqlo import *
16 conf, conn, log = sercom.init('cgi')
19 import cgitb; cgitb.enable()
22 PASSWD = conf.get('general', 'cgipw')
24 def cmp_correccion_padron(e1, e2):
25 'Compara 2 entregas, según el padrón del alumno.'
26 return cmp(e1.inscripto.padron, e2.inscripto.padron)
28 def http_header_html(req):
29 return 'Content-type: text/html\r\n\r\n'
31 def http_header_zip(req, filename):
32 return 'Content-type: application/zip\r\n' \
33 'Content-Disposition: attachment;filename=%s\r\n' \
37 return '''<!DOCTYPE html
38 PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
39 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd" >
42 <title>SUWI - Sercom Ugly Web Interface</title>
43 <style type="text/css">
47 font-family: sans-serif;
48 background-color: rgb(255, 255, 255);
52 border: medium black solid;
53 border-collapse: collapse;
62 border: thin black solid;
64 background-color: navy;
67 vertical-align: middle;
71 border: thin black solid;
73 vertical-align: middle;
93 def form(req, submit, str=None):
95 if submit is not None:
96 r = '<form method="post">\n'
98 r += '<input type="submit" value="%s">\n' % submit
103 return '<pre>%s</pre>' % cgi.escape(str(s))
105 def input_login(req):
106 return '<input type="hidden" name="pw" value="%s" />\n' % PASSWD
108 def input_curso(req, curso_id):
109 return input_login(req) \
110 + '<input type="hidden" name="curso" value="%d" />\n' % curso_id
112 def input_entrega(req, entrega_id):
113 e = Entrega.get(entrega_id, connection=conn)
114 return input_curso(req, e.curso.id) \
115 + '<input type="hidden" name="entrega" value="%d" />\n' % entrega_id
117 def input_zip(req, entrega_id):
118 return input_entrega(req, entrega_id) \
119 + '<input type="hidden" name="zip" value="1" />\n'
121 def input_zip_rechazados(req, entrega_id):
122 return input_entrega(req, entrega_id) \
123 + '<input type="hidden" name="zip" value="1" />\n' \
124 + '<input type="hidden" name="rechazados" value="1" />\n'
126 def input_inscripto(req, inscripto_id=None):
127 if inscripto_id is not None:
128 return '<input type="hidden" name="inscripto" value="%d" />\n' \
132 def input_pruebas(req, intento_id, inscripto_id=None):
133 i = Intento.get(intento_id, connection=conn)
134 r = input_entrega(req, i.entrega.id)
135 r += '<input type="hidden" name="intento" value="%d" />\n' % intento_id
136 r += input_inscripto(req, inscripto_id)
139 def input_intentos(req, entrega_id, inscripto_id):
140 return input_entrega(req, entrega_id) + input_inscripto(req, inscripto_id)
143 r = '<h1>Bienvenido a ' \
144 '<acronym title="Sercom Ugly Web Interface">SUWI</acronym></h1>\n'
145 r += '<p>Debe ingresar la contraseña para seguir...</p>\n'
146 return r + form(req, 'Entrar',
147 '<p>Contraseña: <input type="password" name="pw" /></p>')
150 cursos = [c for c in Curso.select(connection=conn) if len(c.entregas)]
151 r = '<h1>Elegir curso</h1>\n'
153 r += '<p>Curso: <select name="curso">\n'
155 r += '\t<option value="%d">%d-%d-%d</option>\n' \
156 % (c.id, c.anio, c.cuatrimestre, c.curso)
157 r += '</select></p>\n'
159 r += '<p>No hay cursos con entregas</p>\n'
160 return form(req, 'Ver', r + input_login(req))
162 def entrega(req, curso_id):
163 c = Curso.get(curso_id, connection=conn)
164 r = '<h1>Elegir entrega del curso %d-%d-%d</h1>\n' \
165 % (c.anio, c.cuatrimestre, c.curso)
166 r += '<p>Entrega: <select name="entrega">\n'
168 r += '\t<option value="%d">%d-%d</option>\n' \
169 % (e.id, e.nroEjercicio, e.entrega)
170 r += '</select></p>\n'
171 return form(req, 'Ver', r + input_curso(req, curso_id))
173 def pruebas(req, intento_id, inscripto_id=None):
183 <th>Observaciones</th>
188 r = '</table>\n<p>\n'
189 r += form(req, 'Volver', input_entrega(req, i.entrega.id)
190 + input_inscripto(req, inscripto_id))
191 #XXX Hack feo y muy hardcodeado para ver los fuentes (morirá con suwi)
192 r += '<a href="/intentos/%s.%s/%s.%s.%s/%s.%s/">ver fuentes</a></p>' \
193 % (i.inscripto.curso.anio, i.inscripto.curso.cuatrimestre,
194 i.inscripto.curso.curso, i.entrega.nroEjercicio, i.entrega.entrega,
195 i.inscripto.padron, i.numero)
209 ''' % (p.casoDePrueba.nombre, p.pasada, p.casoDePrueba.privado,
210 p.casoDePrueba.activo, p.inicio, p.fin,
211 pre(p.observaciones))
213 i = Intento.get(intento_id, connection=conn)
214 r = '<h1>Pruebas del intento %d del alumno %d</h1>\n' \
215 % (i.numero, i.inscripto.padron)
222 def intentos(req, entrega_id, inscripto_id):
230 <th>Observaciones</th>
235 r = '</table>\n<p>\n'
236 r += form(req, 'Volver', input_entrega(req, entrega_id))
240 if i.pruebasPasadas: pruebas = 'BIEN'
241 elif not i.compila: pruebas = None
242 else: pruebas = 'MAL'
251 ''' % (i.numero, i.llegada, i.compila,
252 form(req, pruebas, input_pruebas(req, i.id, inscripto_id)),
253 pre(i.observaciones))
255 r = '<h1>Intentos del alumno %d</h1>\n' \
256 % Inscripto.get(inscripto_id, connection=conn).padron
258 for i in Intento.selectBy(entregaID=entrega_id, inscriptoID=inscripto_id,
264 def zip(req, entrega_id, rechazados=False):
265 def zip_path(path, base, zipfd):
266 paths = os.listdir(path)
268 if os.path.isdir(os.path.join(path, p)):
269 zip_path(os.path.join(path, p), os.path.join(base, p), zipfd)
271 zipfd.write(os.path.join(path, p), os.path.join(base, p))
273 from zipfile import ZipFile, ZIP_DEFLATED
274 e = Entrega.get(entrega_id, connection=conn)
276 filename = 'entrega-%d.%d.%d-%d.%d' \
277 % (c.anio, c.cuatrimestre, c.curso, e.nroEjercicio, e.entrega)
279 filename += '-rechazados'
281 req.write(http_header_zip(req, filename))
282 tmpfname = os.tmpnam()
283 zipfd = ZipFile(tmpfname, 'w', ZIP_DEFLATED)
285 inscriptos_ok = set([c.inscripto for c in e.correcciones])
286 inscriptos = set([i.inscripto for i in e.intentos])
287 for i in inscriptos - inscriptos_ok:
288 intento = list(Intento.selectBy(entregaID=e.id, inscriptoID=i.id,
289 connection=conn))[-1]
290 zip_path(os.path.join(conf.get('general', 'data_dir'),
291 intento.path), str(i.padron), zipfd)
293 for c in e.correcciones:
294 zip_path(os.path.join(conf.get('general', 'data_dir'),
295 c.intento.path), str(c.intento.inscripto.padron), zipfd)
297 req.write(file(tmpfname, 'r').read())
300 def correcciones(req, entrega_id):
301 def correccion_header():
303 <caption>Entregas aceptadas</caption>
314 def correccion_footer():
315 return ' </tbody>\n</table>\n'
316 def correccion_row(c):
317 if c.intento.pruebasPasadas: pruebas = 'BIEN'
318 elif not c.intento.compila: prubas = None
319 else: pruebas = 'MAL'
320 intentos = int(Intento.selectBy(inscriptoID=c.inscriptoID,
321 entregaID=c.entregaID, connection=conn).count())
328 ''' % (c.inscripto.padron,
329 form(req, pruebas, input_pruebas(req, c.intento.id)),
330 form(req, intentos, input_intentos(req, c.entrega.id, c.inscripto.id)))
331 def problematico_header():
333 <caption>Entregas rechazadas</caption>
343 def problematico_footer():
344 return ' </tbody>\n</table>\n'
345 def problematico_row(inscripto, entrega):
346 intentos = int(Intento.selectBy(inscriptoID=inscripto.id,
347 entregaID=entrega.id, connection=conn).count())
353 ''' % (inscripto.padron,
354 form(req, intentos, input_intentos(req, entrega.id, inscripto.id)))
357 r += form(req, 'Elegir curso', input_login(req))
358 r += form(req, 'Elegir entrega', input_curso(req, e.curso.id))
359 r += form(req, 'Bajar entrega en .zip', input_zip(req, entrega_id))
360 r += form(req, 'Bajar entrega rechazadas en .zip',
361 input_zip_rechazados(req, entrega_id))
365 e = Entrega.get(entrega_id, connection=conn)
367 r = '<h1>Entrega %d.%d del curso %d-%d-%d</h1>\n' \
368 % (e.nroEjercicio, e.entrega, c.anio, c.cuatrimestre, c.curso)
369 correcciones = list(e.correcciones)
370 correcciones.sort(cmp_correccion_padron)
371 r += correccion_header()
372 for c in correcciones:
373 r += correccion_row(c)
374 r += correccion_footer()
375 inscriptos_ok = set([c.inscripto for c in correcciones])
376 inscriptos = set([i.inscripto for i in e.intentos])
377 r += problematico_header()
378 for i in inscriptos - inscriptos_ok:
379 r += problematico_row(i, e)
380 r += problematico_footer()
389 f = cgi.FieldStorage()
390 raw = f.has_key('zip')
394 print http_header_html(req)
397 path = os.getenv('PATH_INFO')
399 if not f.has_key('pw'):
401 elif f.has_key('pw') and f.getfirst('pw') <> PASSWD:
403 print '<p class="warn">Password Incorrecto!</p>\n'
404 elif not f.has_key('curso'):
406 elif not f.has_key('entrega'):
407 print entrega(req, int(f.getfirst('curso')))
408 elif f.has_key('intento'):
410 if f.has_key('inscripto'):
411 inscripto_id = int(f.getfirst('inscripto'))
412 print pruebas(req, int(f.getfirst('intento')), inscripto_id)
413 elif f.has_key('inscripto'):
414 print intentos(req, int(f.getfirst('entrega')), int(f.getfirst('inscripto')))
415 elif f.has_key('zip'):
416 zip(req, int(f.getfirst('entrega')), f.getfirst('rechazados', False))
418 print correcciones(req, int(f.getfirst('entrega')))