Romanes commited on
Commit
f2059f6
·
verified ·
1 Parent(s): 0a85d1f

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +200 -109
app.py CHANGED
@@ -1,123 +1,214 @@
1
-
2
  # -*- coding: utf-8 -*-
 
 
 
3
  import gradio as gr
4
  import pandas as pd
5
- import numpy as np
6
- from pathlib import Path
7
  from datetime import datetime
8
- import uuid
9
-
10
- SCHEMA = [{"criterio": "Novedad", "peso": 9.0, "opciones": []}, {"criterio": "Aplicación industrial", "peso": 10.0, "opciones": []}, {"criterio": "Nivel inventivo", "peso": 8.0, "opciones": []}, {"criterio": "Titularidad", "peso": 13.0, "opciones": []}, {"criterio": "Potencial transferencia", "peso": 14.0, "opciones": []}]
11
-
12
- TEMPLATE_HTML = Path("reporte_template.html")
13
- if not TEMPLATE_HTML.exists():
14
- TEMPLATE_HTML.write_text("""<!doctype html>
15
- <html><head><meta charset='utf-8'><title>Reporte</title>
16
- <style>
17
- body { font-family: Arial, sans-serif; margin:24px; }
18
- table { border-collapse: collapse; width:100%; }
19
- th, td { border:1px solid #ccc; padding:8px; vertical-align:top; }
20
- th { background:#f5f5f5; text-align:left; }
21
- </style>
22
- </head><body>
23
- <h1>Reporte de Evaluación de Tecnologías</h1>
24
- <p><b>Título:</b> {titulo}<br>
25
- <b>Responsable:</b> {responsable}<br>
26
- <b>Facultad:</b> {facultad}<br>
27
- <b>Fecha:</b> {fecha}<br>
28
- <b>Descripción:</b> {descripcion}</p>
29
- <table>
30
- <thead><tr><th>Criterio</th><th>Peso</th><th>Opción</th><th>Puntaje</th><th>Ponderado</th><th>Evidencia</th></tr></thead>
31
- <tbody>{filas}</tbody>
32
- <tfoot><tr><th colspan='4' style='text-align:right'>Total ponderado</th><th>{total}</th><th></th></tr></tfoot>
33
- </table>
34
- <p style='color:#777;font-size:12px'>Generado {fecha_gen}</p>
35
- </body></html>""", encoding="utf-8")
36
-
37
- OUT_DIR = Path("reportes")
38
- OUT_DIR.mkdir(parents=True, exist_ok=True)
39
-
40
- def evaluar(titulo, responsable, facultad, fecha, descripcion, *args):
41
- filas = []
42
- total = 0.0
43
- for i, item in enumerate(SCHEMA):
44
- c = item["criterio"]
45
- peso = float(item["peso"])
46
- opciones = { o["texto"]: o["puntaje"] for o in item["opciones"] }
47
- base = 3*i
48
- opcion = (args[base] or "").strip()
49
- pf = (args[base+1] or "").strip()
50
- evidencia = args[base+2] or ""
51
- usar_forzado = False
52
- try:
53
- pf_val = float(pf)
54
- usar_forzado = True
55
- except:
56
- pf_val = None
57
- if usar_forzado:
58
- puntaje = pf_val
59
- else:
60
- puntaje = opciones.get(opcion, np.nan)
61
- ppond = (puntaje if pd.notna(puntaje) else 0) * peso
62
- total += ppond
63
- filas.append({"criterio": c, "peso": peso, "opcion": opcion, "puntaje": puntaje, "puntaje_ponderado": ppond, "evidencia": evidencia})
64
-
65
- html = TEMPLATE_HTML.read_text(encoding="utf-8")
66
- filas_html = ""
67
- for f in filas:
68
- filas_html += "<tr><td>{}</td><td>{}</td><td>{}</td><td>{}</td><td>{}</td><td>{}</td></tr>\n".format(
69
- f['criterio'], f['peso'], f['opcion'], f['puntaje'], f['puntaje_ponderado'], f['evidencia']
70
- )
71
- html = (html
72
- .replace("{titulo}", str(titulo or ""))
73
- .replace("{responsable}", str(responsable or ""))
74
- .replace("{facultad}", str(facultad or ""))
75
- .replace("{fecha}", str(fecha or ""))
76
- .replace("{descripcion}", str(descripcion or ""))
77
- .replace("{filas}", filas_html)
78
- .replace("{total}", "{:.2f}".format(total))
79
- .replace("{fecha_gen}", datetime.now().strftime("%Y-%m-%d %H:%M"))
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
80
  )
 
 
 
 
 
 
 
 
 
 
 
 
81
 
82
- rid = uuid.uuid4().hex[:8]
83
- out_html = OUT_DIR / f"reporte_{rid}.html"
84
- out_csv = OUT_DIR / f"detalle_{rid}.csv"
85
- pd.DataFrame(filas).to_csv(out_csv, index=False)
86
- out_html.write_text(html, encoding="utf-8")
87
 
88
- return pd.DataFrame(filas), float(total), str(out_html), str(out_csv)
89
 
90
- with gr.Blocks(title="Evaluación de Tecnologías (Autocontenida)") as demo:
91
- gr.Markdown("# Evaluación de Tecnologías (Autocontenida)")
92
- gr.Markdown("Diligencie la información. No requiere subir Excel.")
 
 
 
 
93
 
 
 
 
 
 
94
  with gr.Row():
95
- titulo = gr.Textbox(label="Título de la tecnología")
96
- responsable = gr.Textbox(label="Responsable / Autor")
 
 
 
 
 
 
 
 
97
  with gr.Row():
98
- facultad = gr.Textbox(label="Facultad / Dependencia")
99
- fecha = gr.Textbox(label="Fecha (YYYY-MM-DD)")
100
- descripcion = gr.Textbox(label="Descripción breve", lines=3)
101
-
102
- inputs = [titulo, responsable, facultad, fecha, descripcion]
103
- gr.Markdown("## Criterios")
104
- for item in SCHEMA:
105
- c = item["criterio"]; peso = item["peso"]
106
- opciones = [o["texto"] for o in item["opciones"]]
107
- with gr.Group():
108
- gr.Markdown("### {} — Peso: **{}**".format(c, peso))
109
- dd = gr.Dropdown(choices=opciones, label="Opción")
110
- pf = gr.Textbox(label="Puntaje forzado (opcional)")
111
- ev = gr.Textbox(label="Evidencia / comentarios", lines=2)
112
- inputs += [dd, pf, ev]
113
-
114
- btn = gr.Button("Evaluar y generar reporte")
115
- tabla = gr.Dataframe(headers=["criterio","peso","opcion","puntaje","puntaje_ponderado","evidencia"], label="Detalle")
116
- total = gr.Number(label="Total ponderado")
117
- out_html = gr.File(label="Descargar reporte HTML")
118
- out_csv = gr.File(label="Descargar detalle CSV")
119
-
120
- btn.click(evaluar, inputs=inputs, outputs=[tabla, total, out_html, out_csv])
121
 
122
  if __name__ == "__main__":
123
  demo.launch()
 
 
1
  # -*- coding: utf-8 -*-
2
+ # App: Información general de la tecnología (versión inicial, sin descargas)
3
+ # Requisitos: pip install gradio pandas
4
+
5
  import gradio as gr
6
  import pandas as pd
 
 
7
  from datetime import datetime
8
+
9
+ # --- Listas de opciones -------------------------------------------------------
10
+ FACULTADES = [
11
+ "Facultad de Ciencias Agropecuarias",
12
+ "Facultad de Ciencias",
13
+ "Facultad de Ciencias de la Educación",
14
+ "Facultad de Ciencias Económicas y Administrativas",
15
+ "Facultad de Ciencias de la Salud",
16
+ "Facultad de Derecho",
17
+ "Facultad de Ingeniería",
18
+ "Facultad de Estudios a Distancia",
19
+ "Facultad Chiquinquirá",
20
+ "Facultad Duitama",
21
+ "Facultad Sogamoso",
22
+ ]
23
+
24
+ NIVELES_FORMACION = [
25
+ "Estudiante de pregrado",
26
+ "Profesional",
27
+ "Especialización",
28
+ "Maestria",
29
+ "Doctorado",
30
+ ]
31
+
32
+ TIPOS_VINCULACION = [
33
+ "Estudiante de pregrado",
34
+ "Estudiante de posgrado",
35
+ "Joven investigador",
36
+ "Docente catedratico",
37
+ "Docente ocasional medio tiempo",
38
+ "Docente ocasional tiempo completo",
39
+ "Docente de planta",
40
+ "Contrato de Prestación de Servicios",
41
+ "Externo (aliado)",
42
+ ]
43
+
44
+ TIPOS_DOCUMENTO = ["CC", "TI", "CE"]
45
+
46
+ # --- Defaults sugeridos por Facultad (de tu tabla) ----------------------------
47
+ DEFAULTS = {
48
+ "Facultad de Ciencias Agropecuarias": {
49
+ "nivel": "Estudiante de pregrado",
50
+ "vinc": "Estudiante de pregrado",
51
+ },
52
+ "Facultad de Ciencias": {
53
+ "nivel": "Profesional",
54
+ "vinc": "Estudiante de posgrado",
55
+ },
56
+ "Facultad de Ciencias de la Educación": {
57
+ "nivel": "Especialización",
58
+ "vinc": "Joven investigador",
59
+ },
60
+ "Facultad de Ciencias Económicas y Administrativas": {
61
+ "nivel": "Maestria",
62
+ "vinc": "Docente catedratico",
63
+ },
64
+ "Facultad de Ciencias de la Salud": {
65
+ "nivel": "Doctorado",
66
+ "vinc": "Docente ocasional medio tiempo",
67
+ },
68
+ "Facultad de Derecho": {
69
+ "nivel": None,
70
+ "vinc": "Docente ocasional tiempo completo",
71
+ },
72
+ "Facultad de Ingeniería": {
73
+ "nivel": None,
74
+ "vinc": "Docente de planta",
75
+ },
76
+ "Facultad de Estudios a Distancia": {
77
+ "nivel": None,
78
+ "vinc": "Contrato de Prestación de Servicios",
79
+ },
80
+ # Estas tres filas también fijan Tipo de documento:
81
+ "Facultad Chiquinquirá": {
82
+ "nivel": None, # en tu tabla aparece "TI" aquí, pero eso es tipo de documento; se fija abajo
83
+ "vinc": "Externo (aliado)",
84
+ "tdoc": "TI",
85
+ },
86
+ "Facultad Duitama": {
87
+ "nivel": None,
88
+ "vinc": None,
89
+ "tdoc": "CC",
90
+ },
91
+ "Facultad Sogamoso": {
92
+ "nivel": None,
93
+ "vinc": None,
94
+ "tdoc": "CE",
95
+ },
96
+ }
97
+
98
+ def aplicar_defaults_facultad(facultad):
99
+ """Devuelve updates para nivel, vinculación y tipo de documento al cambiar la facultad."""
100
+ cfg = DEFAULTS.get(facultad, {})
101
+ upd_nivel = gr.update() # sin cambio por defecto
102
+ upd_vinc = gr.update()
103
+ upd_tdoc = gr.update()
104
+ if cfg.get("nivel") in NIVELES_FORMACION:
105
+ upd_nivel = gr.update(value=cfg["nivel"])
106
+ if cfg.get("vinc") in TIPOS_VINCULACION:
107
+ upd_vinc = gr.update(value=cfg["vinc"])
108
+ if cfg.get("tdoc") in TIPOS_DOCUMENTO:
109
+ upd_tdoc = gr.update(value=cfg["tdoc"])
110
+ return upd_nivel, upd_vinc, upd_tdoc
111
+
112
+ def generar_ficha(
113
+ codigo, fecha, facultad, grupo, nombre,
114
+ pn, sn, pa, sa,
115
+ tdoc, ndoc, profesion, nivel, vinculacion,
116
+ correo, direccion, telefono
117
+ ):
118
+ """Devuelve una vista previa tipo tabla (sin archivos)."""
119
+ fila = {
120
+ "Código": codigo,
121
+ "Fecha de ingreso": fecha,
122
+ "Facultad": facultad,
123
+ "Grupo de investigación": grupo,
124
+ "Nombre de la tecnología": nombre,
125
+ "Primer nombre": pn,
126
+ "Segundo nombre": sn,
127
+ "Primer apellido": pa,
128
+ "Segundo apellido": sa,
129
+ "Tipo de documento": tdoc,
130
+ "Número de documento": ndoc,
131
+ "Profesión": profesion,
132
+ "Nivel de formación": nivel,
133
+ "Tipo de vinculación": vinculacion,
134
+ "Correo electrónico": correo,
135
+ "Dirección": direccion,
136
+ "Número de teléfono": telefono,
137
+ "Generado": datetime.now().strftime("%Y-%m-%d %H:%M"),
138
+ }
139
+ df = pd.DataFrame([fila])
140
+ resumen = (
141
+ f"**{nombre or 'Tecnología'}** — {facultad or 'Sin facultad'}\n\n"
142
+ f"Inventor/a: {pn} {sn} {pa} {sa}\n"
143
+ f"Documento: {tdoc or ''} {ndoc or ''} | Nivel: {nivel or '-'} | Vinculación: {vinculacion or '-'}"
144
  )
145
+ return df, resumen
146
+
147
+ with gr.Blocks(title="Información general de la tecnología") as demo:
148
+ gr.Markdown("# Información general de la tecnología (versión inicial)")
149
+ gr.Markdown(
150
+ "Capture la ficha base. Los campos **Facultad**, **Nivel de formación** y **Tipo de vinculación** "
151
+ "tienen listas de opciones; al cambiar *Facultad* se sugieren valores por defecto según su tabla."
152
+ )
153
+
154
+ with gr.Row():
155
+ codigo = gr.Textbox(label="Código", value="P2024/")
156
+ fecha = gr.Textbox(label="Fecha de ingreso", placeholder="YYYY-MM-DD")
157
 
158
+ with gr.Row():
159
+ facultad = gr.Dropdown(choices=FACULTADES, label="Facultad")
160
+ grupo = gr.Textbox(label="Grupo de investigación")
 
 
161
 
162
+ nombre = gr.Textbox(label="Nombre de la tecnología")
163
 
164
+ gr.Markdown("## Inventores (principal)")
165
+ with gr.Row():
166
+ pn = gr.Textbox(label="Primer nombre")
167
+ sn = gr.Textbox(label="Segundo nombre")
168
+ with gr.Row():
169
+ pa = gr.Textbox(label="Primer apellido")
170
+ sa = gr.Textbox(label="Segundo apellido")
171
 
172
+ gr.Markdown("## Datos de contacto")
173
+ with gr.Row():
174
+ tdoc = gr.Dropdown(choices=TIPOS_DOCUMENTO, label="Tipo de documento")
175
+ ndoc = gr.Textbox(label="Número de documento")
176
+ profesion = gr.Textbox(label="Profesión")
177
  with gr.Row():
178
+ nivel = gr.Dropdown(choices=NIVELES_FORMACION, label="Nivel de formación")
179
+ vinculacion = gr.Dropdown(choices=TIPOS_VINCULACION, label="Tipo de vinculación")
180
+ with gr.Row():
181
+ correo = gr.Textbox(label="Correo electrónico")
182
+ direccion = gr.Textbox(label="Dirección")
183
+ telefono = gr.Textbox(label="Número de teléfono")
184
+
185
+ # Sugerir defaults al cambiar la Facultad
186
+ facultad.change(aplicar_defaults_facultad, inputs=[facultad], outputs=[nivel, vinculacion, tdoc])
187
+
188
  with gr.Row():
189
+ btn_generar = gr.Button("Generar ficha (vista previa)")
190
+ btn_limpiar = gr.Button("Limpiar")
191
+
192
+ tabla = gr.Dataframe(label="Vista previa", wrap=True)
193
+ resumen_md = gr.Markdown()
194
+
195
+ btn_generar.click(
196
+ generar_ficha,
197
+ inputs=[codigo, fecha, facultad, grupo, nombre, pn, sn, pa, sa, tdoc, ndoc, profesion, nivel, vinculacion, correo, direccion, telefono],
198
+ outputs=[tabla, resumen_md],
199
+ )
200
+
201
+ def _limpiar():
202
+ return (
203
+ "P2024/", "", None, "", "", "", "", "", "", None, "", "",
204
+ None, None, "", "", ""
205
+ )
206
+
207
+ btn_limpiar.click(
208
+ _limpiar,
209
+ inputs=None,
210
+ outputs=[codigo, fecha, facultad, grupo, nombre, pn, sn, pa, sa, tdoc, ndoc, profesion, nivel, vinculacion, correo, direccion, telefono],
211
+ )
212
 
213
  if __name__ == "__main__":
214
  demo.launch()