]> git.llucax.com Git - software/sercom-old.git/blob - src/sc_suwi
Se ordenan correcciones por padron.
[software/sercom-old.git] / src / sc_suwi
1 #!/usr/bin/env python2.4
2 # -*- encoding: iso-8859-1 -*-
3 # vim: set et sw=4 sts=4 :
4
5 # Módulos estándar
6 import os
7 import sys
8 import cgi
9 # Módulos externos
10 import sqlobject
11 # Módulos locales
12 import sercom
13 from sercom.sqlo import *
14
15 # Inicializo
16 conf, conn, log = sercom.init('cgi')
17
18 # Para debug web
19 import cgitb; cgitb.enable()
20
21 #XXX HORRIBLE
22 PASSWD = conf.get('general', 'cgipw')
23
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)
27
28 def http_header_html(req):
29     return 'Content-type: text/html\r\n\r\n'
30
31 def http_header_zip(req, filename):
32     return 'Content-type: application/zip\r\n' \
33         'Content-Disposition: attachment;filename=%s\r\n' \
34         '\r\n' % filename
35
36 def header(req):
37     return '''<!DOCTYPE html
38     PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
39     "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd" >
40 <html>
41     <head>
42         <title>SUWI - Sercom Ugly Web Interface</title>
43         <style type="text/css">
44             <!--
45             body
46             {
47                 font-family: sans-serif;
48                 background-color: rgb(255, 255, 255);
49             }
50             table
51             {
52                 border: medium black solid;
53                 border-collapse: collapse;
54             }
55             th
56             {
57                 border: thin black solid;
58                 color: white;
59                 background-color: navy;
60                 padding: 3pt;
61                 text-align: center;
62                 vertical-align: middle;
63             }
64             td
65             {
66                 border: thin black solid;
67                 padding: 3pt;
68                 vertical-align: middle;
69             }
70             .warn
71             {
72                 color: red;
73             }
74             // -->
75         </style>
76     </head>
77     <body>
78 '''
79     pass
80
81 def footer(req):
82     return '''
83     </body>
84 </html>
85 '''
86     pass
87
88 def form(req, submit, str=None):
89     r = submit
90     if submit is not None:
91         r = '<form method="post">\n'
92         if str: r += str
93         r += '<input type="submit" value="%s">\n' % submit
94         r += '</form>\n'
95     return r
96
97 def pre(s):
98     return '<pre>%s</pre>' % cgi.escape(str(s))
99
100 def input_login(req):
101     return '<input type="hidden" name="pw" value="%s" />\n' % PASSWD
102
103 def input_curso(req, curso_id):
104     return input_login(req) \
105         + '<input type="hidden" name="curso" value="%d" />\n' % curso_id
106
107 def input_entrega(req, entrega_id):
108     e = Entrega.get(entrega_id, connection=conn)
109     return input_curso(req, e.curso.id) \
110         + '<input type="hidden" name="entrega" value="%d" />\n' % entrega_id
111
112 def input_zip(req, entrega_id):
113     return input_entrega(req, entrega_id) \
114         + '<input type="hidden" name="zip" value="1" />\n'
115
116 def input_inscripto(req, inscripto_id=None):
117     if inscripto_id is not None:
118         return '<input type="hidden" name="inscripto" value="%d" />\n' \
119             % inscripto_id
120     return ''
121
122 def input_pruebas(req, intento_id, inscripto_id=None):
123     i = Intento.get(intento_id, connection=conn)
124     r = input_entrega(req, i.entrega.id)
125     r += '<input type="hidden" name="intento" value="%d" />\n' % intento_id
126     r += input_inscripto(req, inscripto_id)
127     return r
128
129 def input_intentos(req, entrega_id, inscripto_id):
130     return input_entrega(req, entrega_id) + input_inscripto(req, inscripto_id)
131
132 def login(req):
133     r = '<h1>Bienvenido a ' \
134         '<acronym title="Sercom Ugly Web Interface">SUWI</acronym></h1>\n'
135     r += '<p>Debe ingresar la contraseña para seguir...</p>\n'
136     return r + form(req, 'Entrar',
137         '<p>Contraseña: <input type="password" name="pw" /></p>')
138
139 def curso(req):
140     cursos = [c for c in Curso.select(connection=conn) if len(c.entregas)]
141     r = '<h1>Elegir curso</h1>\n'
142     if cursos:
143         r += '<p>Curso: <select name="curso">\n'
144         for c in cursos:
145             r += '\t<option value="%d">%d-%d-%d</option>\n' \
146                 % (c.id, c.anio, c.cuatrimestre, c.curso)
147         r += '</select></p>\n'
148     else:
149         r += '<p>No hay cursos con entregas</p>\n'
150     return form(req, 'Ver', r + input_login(req))
151
152 def entrega(req, curso_id):
153     c = Curso.get(curso_id, connection=conn)
154     r = '<h1>Elegir entrega del curso %d-%d-%d</h1>\n' \
155         % (c.anio, c.cuatrimestre, c.curso)
156     r += '<p>Entrega: <select name="entrega">\n'
157     for e in c.entregas:
158         r += '\t<option value="%d">%d-%d</option>\n' \
159             % (e.id, e.nroEjercicio, e.entrega)
160     r += '</select></p>\n'
161     return form(req, 'Ver', r + input_curso(req, curso_id))
162
163 def pruebas(req, intento_id, inscripto_id=None):
164     def header():
165         return '''<table>
166     <tr>
167         <th>Nombre</th>
168         <th>Pasada</th>
169         <th>Privada</th>
170         <th>Activa</th>
171         <th>Inicio</th>
172         <th>Fin</th>
173         <th>Observaciones</th>
174     <tr>
175 '''
176         pass
177     def footer():
178         r = '</table>\n<p>\n'
179         r += form(req, 'Volver', input_entrega(req, i.entrega.id)
180             + input_inscripto(req, inscripto_id))
181         r += '</p>\n'
182         return r
183     def row(p):
184         return '''
185     <tr>
186         <td>%s</td>
187         <td>%s</td>
188         <td>%s</td>
189         <td>%s</td>
190         <td>%s</td>
191         <td>%s</td>
192         <td>%s</td>
193     </tr>
194 ''' % (p.casoDePrueba.nombre, p.pasada, p.casoDePrueba.privado,
195         p.casoDePrueba.activo, p.inicio, p.fin,
196         pre(p.observaciones))
197
198     i = Intento.get(intento_id, connection=conn)
199     r = '<h1>Pruebas del intento %d del alumno %d</h1>\n' \
200         % (i.numero, i.inscripto.padron)
201     r += header()
202     for p in i.pruebas:
203         r += row(p)
204     r += footer()
205     return r
206
207 def intentos(req, entrega_id, inscripto_id):
208     def header():
209         return '''<table>
210     <tr>
211         <th>Nro</th>
212         <th>Llegada</th>
213         <th>Compila</th>
214         <th>Pruebas</th>
215         <th>Observaciones</th>
216     <tr>
217 '''
218         pass
219     def footer():
220         r = '</table>\n<p>\n'
221         r += form(req, 'Volver', input_entrega(req, entrega_id))
222         r += '</p>\n'
223         return r
224     def row(i):
225         if i.pruebasPasadas: pruebas = 'BIEN'
226         elif not i.compila: pruebas = None
227         else: pruebas = 'MAL'
228         return '''
229     <tr>
230         <td>%d</td>
231         <td>%s</td>
232         <td>%s</td>
233         <td>%s</td>
234         <td>%s</td>
235     </tr>
236 ''' % (i.numero, i.llegada, i.compila,
237         form(req, pruebas, input_pruebas(req, i.id, inscripto_id)),
238         pre(i.observaciones))
239
240     r = '<h1>Intentos del alumno %d</h1>\n' \
241         % Inscripto.get(inscripto_id, connection=conn).padron
242     r += header()
243     for i in Intento.selectBy(entregaID=entrega_id, inscriptoID=inscripto_id,
244             connection=conn):
245         r += row(i)
246     r += footer()
247     return r
248
249 def zip(req, entrega_id):
250     def zip_path(path, base, zipfd):
251         paths = os.listdir(path)
252         for p in paths:
253             if os.path.isdir(os.path.join(path, p)):
254                 zip_path(os.path.join(path, p), os.path.join(base, p), zipfd)
255             else:
256                 zipfd.write(os.path.join(path, p), os.path.join(base, p))
257
258     from zipfile import ZipFile, ZIP_DEFLATED
259     e = Entrega.get(entrega_id, connection=conn)
260     c = e.curso
261     req.write(http_header_zip(req, 'entrega-%d.%d.%d-%d.%d.zip'
262         % (c.anio, c.cuatrimestre, c.curso, e.nroEjercicio, e.entrega)))
263     tmpfname = os.tmpnam()
264     zipfd = ZipFile(tmpfname, 'w', ZIP_DEFLATED)
265     for c in e.correcciones:
266         zip_path(os.path.join(conf.get('general', 'data_dir'), c.intento.path),
267             str(c.intento.inscripto.padron), zipfd)
268     zipfd.close()
269     req.write(file(tmpfname, 'r').read())
270     os.unlink(tmpfname)
271
272 def correcciones(req, entrega_id):
273     def header():
274         return '''<table>
275     <tr>
276         <th>Padrón</th>
277         <th>Pruebas</th>
278         <th>Intentos</th>
279     <tr>
280 '''
281         pass
282     def footer():
283         r = '</table>\n<p>\n'
284         r += form(req, 'Elegir curso', input_login(req))
285         r += form(req, 'Elegir entrega', input_curso(req, e.curso.id))
286         r += form(req, 'Bajar entrega en .zip', input_zip(req, entrega_id))
287         r += '</p>\n'
288         return r
289     def row(c):
290         if c.intento.pruebasPasadas: pruebas = 'BIEN'
291         elif not c.intento.compila: prubas = None
292         else: pruebas = 'MAL'
293         intentos = int(Intento.selectBy(inscriptoID=c.inscriptoID,
294             entregaID=c.entregaID, connection=conn).count())
295         return '''
296     <tr>
297         <td>%d</td>
298         <td>%s</td>
299         <td>%s</td>
300     </tr>
301 ''' % (c.inscripto.padron,
302         form(req, pruebas, input_pruebas(req, c.intento.id)),
303         form(req, intentos, input_intentos(req, c.entrega.id, c.inscripto.id)))
304
305     e = Entrega.get(entrega_id, connection=conn)
306     c = e.curso
307     r = '<h1>Entrega %d.%d del curso %d-%d-%d</h1>\n' \
308         % (e.nroEjercicio, e.entrega, c.anio, c.cuatrimestre, c.curso)
309     r += header()
310     correcciones = list(e.correcciones)
311     correcciones.sort(cmp_correccion_padron)
312     for c in correcciones:
313         r += row(c)
314     r += footer()
315     return r
316
317 #
318 # MAIN
319 #
320
321 req = sys.stdout
322 f = cgi.FieldStorage()
323 raw = f.has_key('zip')
324
325
326 if not raw:
327     print http_header_html(req)
328     print header(req)
329
330 path = os.getenv('PATH_INFO')
331
332 if not f.has_key('pw'):
333     print login(req)
334 elif f.has_key('pw') and f.getfirst('pw') <> PASSWD:
335     print login(req)
336     print '<p class="warn">Password Incorrecto!</p>\n'
337 elif not f.has_key('curso'):
338     print curso(req)
339 elif not f.has_key('entrega'):
340     print entrega(req, int(f.getfirst('curso')))
341 elif f.has_key('intento'):
342     inscripto_id = None
343     if f.has_key('inscripto'):
344         inscripto_id = int(f.getfirst('inscripto'))
345     print pruebas(req, int(f.getfirst('intento')), inscripto_id)
346 elif f.has_key('inscripto'):
347     print intentos(req, int(f.getfirst('entrega')), int(f.getfirst('inscripto')))
348 elif f.has_key('zip'):
349     zip(req, int(f.getfirst('entrega')))
350 else:
351     print correcciones(req, int(f.getfirst('entrega')))
352
353 if not raw:
354     print footer(req)
355