Logo Studenta

Desarrollo-de-un-juez-en-lnea--una-herramienta-web-para-administrar-concursos-de-programacion-y-evaluar-la-efectividad-de-programas-propuestos-como-solucion-a-los-problemas-planteados

¡Este material tiene más páginas!

Vista previa del material en texto

UNIVERSIDAD NACIONAL 
AUTÓNOMA DE MÉXICO 
 
FACULTAD DE ESTUDIOS SUPERIORES 
ACATLÁN 
 
 
 
Desarrollo de un juez en línea: una herramienta web para 
administrar concursos de programación y evaluar la efectividad de 
programas propuestos como solución a los problemas planteados 
 
 
Tesina 
 
QUE PARA OBTENER EL TÍTULO DE 
 
Lic. en Matemáticas Aplicadas y Computación 
 
 
 
PRESENTA: 
 
Moroni Silverio Flores 
 
 
Asesor: Dr. Jorge Vasconcelos Santillán 
 
 
Junio 2019 
 
 
UNAM – Dirección General de Bibliotecas 
Tesis Digitales 
Restricciones de uso 
 
DERECHOS RESERVADOS © 
PROHIBIDA SU REPRODUCCIÓN TOTAL O PARCIAL 
 
Todo el material contenido en esta tesis esta protegido por la Ley Federal 
del Derecho de Autor (LFDA) de los Estados Unidos Mexicanos (México). 
El uso de imágenes, fragmentos de videos, y demás material que sea 
objeto de protección de los derechos de autor, será exclusivamente para 
fines educativos e informativos y deberá citar la fuente donde la obtuvo 
mencionando el autor o autores. Cualquier uso distinto como el lucro, 
reproducción, edición o modificación, será perseguido y sancionado por el 
respectivo titular de los Derechos de Autor. 
 
 
 
Agradecimientos 
 
 
 
 
 
 
 
 
 
 
 
 
A Saraí, 
por su apoyo en esta trayectoria. 
A mis padres, 
por apoyarme en mis estudios. 
A mi asesor, 
por su guía para llevar a cabo esta obra. 
Al Grupo de Algoritmia de la FES Acatlán, 
de quienes aprendí muchas cosas. 
Al Departamento de Servicios de Cómputo 
de la FES Acatlán, 
por los recursos facilitados para desarrollar 
este proyecto. 
Y a todos aquellos que hicieron esto posible 
que no puedo mencionar por nombre. 
 
 
 
Contenido 
Introducción ............................................................................................................................... 1 
1. La programación competitiva ........................................................................................ 3 
1.1. ¿Qué es la programación competitiva? .............................................................. 3 
1.2. Requerimientos de un juez en línea ..................................................................... 3 
1.2.1. Jueces en línea actuales ................................................................................. 4 
1.2.2. Requerimientos del Juez GUAPA ................................................................. 5 
1.2.3. Limitaciones del Juez GUAPA ....................................................................... 7 
1.3. Antecedentes históricos y beneficios ............................................................... 15 
1.3.1. Beneficios de la programación competitiva ............................................ 16 
2. Desarrollo web con Meteor .......................................................................................... 19 
2.1. ¿Qué es Meteor? ..................................................................................................... 19 
2.2. El protocolo DDP ..................................................................................................... 20 
2.2.1. Optimistic UI ..................................................................................................... 21 
2.3. Programación reactiva .......................................................................................... 25 
2.3.1. Fuentes reactivas ............................................................................................ 27 
2.3.2. Tracker ............................................................................................................... 30 
3. Almacenamiento de información con MongoDB .................................................... 32 
3.1. SQL vs NoSQL ......................................................................................................... 32 
3.2. ¿Qué es MongoDB? ............................................................................................... 34 
3.3. Colecciones del juez en línea .............................................................................. 35 
4. Desarrollo e implementación del juez ....................................................................... 53 
4.1. Desarrollo .................................................................................................................. 53 
4.2. Requerimientos para el algoritmo de evaluación........................................... 54 
4.2.1. Algoritmos eficientes de evaluación ......................................................... 55 
4.2.2. Medir el tiempo de ejecución ....................................................................... 60 
4.2.3. Proceso de instalación del juez en línea .................................................. 62 
4.3. Uso en competencias ............................................................................................ 63 
5. Discusión y trabajo a futuro ......................................................................................... 64 
5.1. Idiomas ...................................................................................................................... 65 
5.2. Nuevo contenido ..................................................................................................... 66 
5.3. Cualidades que no se deberían agregar al juez .............................................. 67 
5.4. Mejoras que se podrían incorporar al juez ...................................................... 69 
5.5. API ............................................................................................................................... 73 
Conclusiones ........................................................................................................................... 75 
Bibliografía ............................................................................................................................... 77 
Anexos ....................................................................................................................................... 81 
A. Esquema en JSON de las colecciones de la base de datos ........................ 81 
B. Configuracion de Isolate ....................................................................................... 90 
C. Código actualización scoreboard ....................................................................... 94 
D. Rutas del Juez GUAPA .......................................................................................... 96 
 
 
 
 
1 
 
Introducción 
 
 
El presente documento mostrará el proceso de creación de una herramienta Web enfocada a 
evaluar y administrar concursos de programación competitiva. 
El objetivo de esta obra es desarrollar una herramienta web, llamada “juez en línea”1, que ayude 
a organizadores de concursos de programación competitiva a evaluar las soluciones propuestas a 
los problemas planteados durante estos eventos, así como proporcionar una plataforma digital a 
los interesados en mejorar sus habilidades de programación de manera eficiente, así como 
profundizar en los algoritmos involucrados y en sus fundamentos matemáticos. 
También se desea ayudar al Grupo de Algoritmia Avanzada y Programación Competitiva 
(GUAPA), perteneciente a la Facultad de Estudios Superiores (FES) Acatlán de la Universidad 
Nacional Autónoma de México (UNAM), a tener un control del progreso de sus miembros, a 
organizar, principalmente, el concurso de programación de la semana académica de MAC y el 
concurso interno de programación; también permitirá realizar otros concursos, que, si bien no se 
realizan de manera periódica, ayudan a los miembros del grupo a prepararse para los concursos 
regionales del gran premio de México del ICPC2. 
El ser parte del grupo de algoritmiapermite ver la manera en que este ayuda a los alumnos en su 
desempeño académico y profesional, permitiendo también ver de qué cosas carece. La idea de 
tener un juez en línea en la institución fue algo que ha estado presente en la mente de varios 
miembros del grupo durante algunos años. Con esta contribución se puede ayudar a los miembros 
del grupo de algoritmia a mejorar sus habilidades de programación y de matemáticas. 
Surge también idea de esta obra para cubrir deficiencias en otras herramientas en línea existentes 
en la actualidad, no necesariamente para reemplazarlas, pero para aportar a la formación 
académica de quienes las utilizan día a día. 
 
1 Este juez en particular se llama Juez GUAPA y se puede acceder a él a través de 
https://www.juezguapa.com/ 
2 International Collegiate Programming Contest (Concurso Internacional Universitario de Programación, 
traducción libre). 
2 
 
A lo largo de cinco capítulos se describe cómo se desarrolla esta herramienta Web, los desafíos 
que se presentaron y su evolución, también se muestra el uso de distintas herramientas de 
desarrollo y lenguajes de programación que juntas hacen que este trabajo sea posible. 
En el capítulo I se hace una exposición sobre el concepto de programación competitiva, los 
principales concursos de programación en México y el mundo además de la necesidad de jueces 
en línea y automatizados. También se muestra como ha sido la participación de los alumnos de la 
FES Acatlán (principales miembros del grupo de algoritmia). Se muestra también los 
requerimientos que debe satisfacer un juez y sus limitaciones. 
En el capítulo 2 se explica que es el framework Meteor[js] y por qué se eligió para desarrollar la 
herramienta Web. También se explican algunos paradigmas de programación relacionados con el 
desarrollo Web actual. 
En el capítulo 3 se muestra que son las bases de datos no relacionales y como su uso es el adecuado 
para el desarrollo de esta herramienta. Una parte importante es el cómo se almacena la información 
y como se muestra al usuario final, se explica todo este proceso. 
El capítulo 4 muestra cómo se fue desarrollando el juez, cómo fue evolucionando, cómo instalarlo 
con sus requerimientos mínimos y se muestra al juez en acción en concursos de programación 
dentro y fuera de la FES Acatlán. 
En el último capítulo se muestra el futuro del juez en línea, con posibles líneas de investigación y 
desarrollo. También se muestran las actualizaciones que se están realizando continuamente y se 
dan detalles de algunos algoritmos, no implementados aun en el juez en línea, que se agregarán en 
un tiempo próximo para mejorar la experiencia de los usuarios, tanto concursantes como 
administradores de concursos. 
Todo el desarrollo del juez en línea fue hecho por el autor de esta obra, quien lo tomó desde cero 
con el deseo de tener una herramienta para facilitar la administración de concursos de 
programación y con el deseo de mejorar el nivel de programación de muchos entusiastas. Este 
desarrollo abarcó desde la toma de requerimientos, desarrollo backend y frontend (explicados más 
adelante), diseño de la base de datos y su producción. 
3 
 
Capítulo 1 
1. La programación competitiva 
 
 
1.1. ¿Qué es la programación competitiva? 
 
La programación competitiva es un deporte que se lleva a cabo en una red local o por internet, 
puede ser comparado con cualquier deporte de campo: Cuando se es nuevo en este quizá las cosas 
salgan mal, pero después de un tiempo y práctica se irá mejorando; se anotarán goles si se practica 
fútbol, en el caso de la programación competitiva el código que se programe será la solución de 
problemas planteados y quizá al principio sea malo o tenga muchos errores, pero con el estudio y 
la práctica se tendrán más aciertos. 
 
1.2. Requerimientos de un juez en línea 
 
Dada la cantidad de personas que participan en un concurso de programación es evidente que no 
es tarea para humanos el revisar el código de cada concursante y emitir un veredicto. Como nota 
se puede decir que en los concursos de programación realizados dentro de la FES Acatlán se han 
realizado un promedio de dos soluciones por minuto, ahora, ¿Cuántas se realizan en un concurso 
con más de mil participantes y que dura aproximadamente cinco horas? 
En los primeros concursos de programación competitiva realizados en Estados Unidos y Canadá 
los usuarios guardaban su código en un disquete y corrían hacia los jueces (quienes estaban 
sentados en una mesa para evaluar problemas) y se formaban esperando a que su código fuente 
fuera evaluado, después empezaron a realizar sus envíos a través de la red local, sin embargo, la 
cantidad de envíos realizados siempre ha requerido la automatización del proceso de evaluación. 
Y dado que es una competencia donde el tiempo es uno de los factores importantes, se necesitan 
entregar resultados de manera rápida, los concursantes deben saber si sus envíos son correctos o 
4 
 
no lo son para pasar al siguiente problema o intentar corregir lo que les salió mal (o incluso 
abandonar el problema). 
El trabajo de los organizadores durante una competencia, en la época actual, suele limitarse a 
resolver dudas de los participantes, ya que no se cuenta con el tiempo para validar el código de 
todas las personas, eso lo debe hacer un juez automatizado. 
En los concursos clasificatorios de México donde participan alrededor de 300 equipos de distintas 
universidades suele haber hasta 2000 envíos en un periodo de cinco horas de competencia. Cada 
región es libre de utilizar el juez en línea de su preferencia para las competencias, algunos de los 
cuales son software libre y se pueden descargar para correr una copia local durante la competencia. 
 
1.2.1. Jueces en línea actuales 
 
El ICPC utiliza el DOM judge [1] para las finales mundiales, algunas regiones de Europa y Estados 
Unidos también utilizan este juez para sus competencias, para utilizarlo es necesario descargar 
una copia del juez para ejecutarlo en un servidor local durante la competencia. Este juez está 
escrito en PHP y requiere una máquina con Linux para funcionar. 
Otro juez en línea es el Kattis [2], aunque este no es software libre, a diferencia del DOM judge, 
el Kattis no tiene que descargarse para realizar concursos, el propósito de Kattis es ayudar a 
universidades con sus cursos de ciencias de la computación, ayudar a empresas a contratar 
personal y permitir a amantes de la programación practicar y ser contactados por empresas. El uso 
de Kattis para llevar a cabo concursos tiene un costo, sin embargo, tiene todo listo para que los 
administradores no tengan que preocuparse por instalar nada o verificar que el sistema de 
evaluación cumpla con requisitos que se mencionarán más adelante. 
En Latinoamérica suele utilizarse una copia del Juez Boca [3] que es utilizado principalmente en 
competencias brasileñas de programación. Para usar el juez es necesario descargarlo y correrlo en 
un servidor al que tengan acceso los concursantes. A pesar de que el juez boca cumple con el 
propósito de las competencias, los usuarios deben ser cuidadosos con los envíos que realizan ya 
que algunas veces el juez da como veredicto que la solución es muy lenta, aunque en otro juez 
hubiera pasado en tiempo, normalmente requiere métodos de lectura y escritura rápida que, en la 
5 
 
opinión de algunos participantes, van en contra del espíritu de la programación competitiva donde 
se evalúan las complejidades de las soluciones en términos de Big O. La complejidad no varía si 
se usa un printf o un cout en C++ para imprimir la respuesta, sin embargo, en este juez sí son 
importantes3. 
Otro de los problemas que enfrenta este juez es el tiempo de evaluación, en competencias ha 
habido demoras de más de 20 minutos en la evaluación de problemas, y esto afecta seriamente el 
desempeño de lacompetencia de los concursantes. 
Anteriormente su utilizaba el Caribbean Online Judge [4] (un juez en línea cubano de la 
Universidad de Ciencias Informáticas, UCI), pero se presentaban muchos problemas de 
conectividad durante las competencias, el firewall de la Universidad de Ciencias Informáticas 
bloqueaba el acceso cuando veía “demasiadas” solicitudes de la misma IP (todos los concursantes 
dentro del mismo campus muestran la misma IP) y, aunque esto se arreglaba, algunas veces el 
servidor se caía a media competencia debido al estrés que recibía por tantos concursantes, sin 
embargo sus tiempos de evaluación eran buenos (se tardaba alrededor de un minuto en emitir un 
veredicto). Actualmente sigue siendo usado para competencias del Caribe y algunos países de 
África. 
 
1.2.2. Requerimientos del Juez GUAPA 
 
¿Qué debe tener un juez en línea para administrar un concurso de programación? A simple vista 
del lado del usuario es que califique bien sus envíos, es lo que le importa a quien resuelve ejercicios 
para practicar o durante un concurso, también quiere que sea rápido. A nadie le gustan las cosas 
lentas, en especial cuando estas en una competencia donde el tiempo es un factor de desempate. 
Entonces uno quiere saber lo más rápido posible si hubo un error en su código, para que haga los 
cambios pertinentes. 
 
3 En C++ la función printf() es más rápida que cout para imprimir datos en la salida estándar, en Python 3 
se puede ver diferencias al imprimir utilizando stdout.write vs print(), siendo el primero mucho más 
rápido. Esto ha llevado a que algunos jueces acepten una solución escrita con printf y rechacen una 
escrita con cout. 
6 
 
¿Qué hay del lado de los que organizan el concurso? ¿Cuál es su juez ideal? ¿Qué requieren para 
que el juez pueda cumplir su trabajo? Un pequeño recorrido del lado de los jueces (humanos) nos 
diría que el Juez debe ser rápido. 
Al igual que los concursantes, un administrador de concurso quiere que las respuestas sean rápidas, 
no le gusta ver a la gente desesperada preguntando porque no han tenido respuesta del código que 
enviaron hace 25 minutos cuando el concurso se acaba en 15 minutos. 
El juez debe permitir una comunicación entre los administradores y los concursantes, es normal 
que haya dudas, siempre las habrá, a veces porque queda alguna ambigüedad en la redacción de 
los problemas, a veces porque los concursantes no leen bien los enunciados. Debe haber un canal 
de comunicación siempre abierto. 
Otro punto importante es la seguridad, un buen juez estará compilando y ejecutando código 
desconocido en el servidor; hay personas maliciosas, ¿Qué pasaría si alguien intenta tomar control 
del servidor? ¿O apagarlo? ¿O buscar las respuestas en alguna parte del sistema de archivos? Ese 
es un punto crucial del juez, si se planea que el servicio Web esté disponible 24/7, cuando no haya 
nadie verificando los envíos con la tranquilidad de que al despertar nadie habrá tomado control 
del servidor o ejecutado código malicioso. 
Aunque hay jueces que se montan únicamente para concursos de programación y después del 
periodo de cinco horas o menos que dura el concurso lo ponen fuera de línea. Durante un concurso 
no suele haber código malicioso, si acaso errores en el código que hacen mal uso de memoria y 
que harían que una computadora normal dejara de funcionar al ejecutar dicho código, sin embargo, 
de vez en cuando hay algún usuario que quiere hacer lo que considera una travesura enviando 
código malicioso. 
En capítulos posteriores se discutirán los requerimientos en memoria RAM y de almacenamiento 
para instalar un juez. 
 
 
 
 
7 
 
1.2.3. Limitaciones del Juez GUAPA 
 
También se debe especificar qué es lo que no hace un juez. La cosa principal que no hace es decirle 
al usuario en que está mal, esa es una tarea muy complicada que va más allá del trabajo de un juez, 
a veces los errores van desde errores en el formato de salida (se imprime un carácter de más o de 
menos), olvidan limpiar una alguna variable (se llegan a realizar operaciones correctas con 
información incorrecta), errores en la lectura de datos, etc. 
Incluso aunque pudiéramos decir, al ver el código, que la respuesta es prácticamente correcta, el 
juez no puede aceptarla, ya que ese pequeño error hace que la salida del programa enviado por el 
usuario sea diferente a la salida que se tiene como respuesta correcta. 
 
1.2.3.1. Fraude 
 
Otro asunto muy discutido entre los administradores de concursos de programación es la detección 
de plagios. Surge la pregunta: ¿Cómo se sabe que hubo un plagio, que un archivo fue copiado? Se 
podría correr un diff [5] para verificar que los archivos no sean iguales, pero esta prueba se 
pasaría al modificar un carácter del código original, entonces los archivos serían parecidos, pero 
no iguales. Entonces se podría utilizar un algoritmo para encontrar la subsecuencia común más 
grande [6], entonces, si se modificaron partes del archivo (se cambiaron nombres de las variables, 
entre otros) aun habría código en común. 
Pero ¿qué pasa si la persona que copió el código cambia el orden en que fueron declaradas las 
funciones dentro del código fuente?: La cantidad de código en común no se vería reflejado por la 
subsecuencia común más grande. 
Otra cosa que se podría hacer sería intentar verificar la estructura del árbol de sintaxis de los 
códigos fuentes. Pero ¿qué tan parecidos deben ser para considerarse fraude, incluso si los códigos 
fuente fueron escritos en distintos lenguajes de programación? Y también surge el dilema: muchos 
problemas requieren un algoritmo en específico para resolverse; entonces, dos usuarios de manera 
independiente seguramente utilizarán un Rolling Hash [7] con búsqueda binaria para encontrar el 
tamaño de la subcadena común más grande de dos cadenas de texto de 100 mil elementos cada 
8 
 
una. Otra manera de solucionarlo es con un suffiex trie, quizá haya más soluciones, pero es seguro 
que los concursantes se apegarán a esas soluciones. 
Se utilizará de ejemplo el algoritmo de Euclides (el cual sirve para encontrar el máximo común 
divisor de dos números a y b) como ejemplo para crear un árbol de sintaxis, el código en Python 
es el siguiente: 
 
 
 
Ilustración 1-1 Árbol de sintaxis del algoritmo de Euclides 
Secuencia de 
enunciados
Mientras
Comparar !=
Variable b
Constante 0
Si
Comparar >
Variable a
Variable b
Cumple
Asignar
Variable a Operacion -
Variable a
Variable b
No se 
cumple
Asignar
Variable b Operacion -
Variable b
Variable a
Regresar
Variable a
while b != 0: 
 if a > b: 
 a = a − b 
 else 
 b = b − a 
return a 
9 
 
El árbol de sintaxis es libre del lenguaje de programación, entonces, si alguien programara el 
algoritmo de Euclides utilizando otro lenguaje de programación sus códigos pasarían la prueba de 
comparación de texto como subsecuencia común más grande porque la manera de escribir es 
distinta, sin embargo, sus árboles de sintaxis serían el mismo (la ilustración 1-1 muestra este árbol 
de sintaxis), pero esto no nos dice nada en cuanto al fraude. Solo nos dice que programaron lo 
mismo, pero nada más. El hecho de que dos personas hayan sacado diez en su tarea no significa 
que se hayan copiado. 
Regresando al problema de la subcadena común más grande, si hay más de dos personas que 
resolvieron el problema, por el principio de Dirichlet podemos decir que hay al menos dos 
concursantes con la misma solución. Su árbol de sintaxis será muy parecido, incluso su código. 
¿Por qué? Porque muchos equipos usan plantillas para resolver problemas bien conocidos para 
ahorrarse tiempo en concurso. 
Y, qué pasa si ambos equipos tuvieron el mismo maestro y ambos programan la solución de un 
problema que les pide contar el número de permutaciones de un arreglo de tamaño 𝑛 dónde los 
primeros𝑘 elementos no están en su lugar. Seguramente sus soluciones serán casi idénticas, 
inclusive con el nombre de las variables; ambos aprendieron el principio de inclusión exclusión y 
no hay fraude ni malicia en ellos, sin embargo, sus códigos son muy parecidos. ¿Es plagio porque 
ambos equipos de la misma institución supieron resolver el mismo problema de la misma manera 
porque de esa manera aprendieron a resolverlo? ¿O, aunque sean de escuelas distintas? 
La solución4 es: 
 
∑(−1)𝑖 (
𝑘
𝑖
) (n − i)!
𝑘
𝑖=0
 
 
 
 
4 Este es un problema de desarreglos (derangements) y puede resolverse con el principio de inclusión-
exclusión, sin embargo, la demostración, aunque hermosa, va más allá de esta obra, pero en un buen 
libro de matemáticas discretas se puede encontrar la explicación. 
10 
 
A continuación, se comparará el código fuente que soluciona el problema hecho por dos personas 
que lo programaron de manera independiente: 
Solución 1: 
#include <iostream> 
#include <cmath> 
using namespace std; 
#define mod 1000000007 
typedef long long ll; 
#define N 1000003 
ll facto[N+3]; 
ll revfacto[N+3]; 
ll fast_pow(ll x,ll n) 
{ 
 ll res = 1; 
 while(n) 
 { 
 if(n & 1) 
 res = res * x % mod; 
 x = x * x % mod; 
 n >>= 1; 
 } 
 return res; 
} 
void llena() 
{ 
 facto[0] = 1; 
 for(int I = 1; I <= N; i++) 
 facto[i]=(facto[I - 1] * i) % mod; 
 revfacto[N - 1] = fast_pow( facto[N],mod - 2) * N % mod; 
 for(int i =N - 2; I >= 0; i--) 
 revfacto[i] = revfacto[I + 1] * (i + 1) % mod; 
} 
ll combi(int n,int k) 
{ 
 if(k == 0 or n == k) 
 return 1; 
 return (facto[n] * revfacto[n - k] % mod * revfacto[k]) % mod; 
} 
 
11 
 
 
 
Solución 2: 
 
int main() 
{ 
 llena(); 
 int n, k; 
 cin>>n>>k; 
 ll resto = 0; 
 for(int i = 1; i <= k; i++) 
 { 
 ll pro = combi(k, i) * facto[n - i] % mod; 
 i & 1 ? resto += pro : resto -= pro; 
 resto = (resto + mod) % mod; 
 } 
 cout<<(facto[n] – resto + mod) % mod<<endl; 
 return 0; 
} 
#include <bits/stdc++.h> 
using namespace std; 
typedef long long ll; 
#define mod 1000000007 
#define tam 1000003 
 
ll fastpow( ll a, ll n ) 
{ 
 ll res=1; 
 while ( n ) 
 { 
 if ( n&1 ) 
 res=res*a%mod; 
 a = a*a%mod; 
 n >>=1; 
 } 
 return res; 
} 
 
ll fact[tam + 5], factreverso[tam + 5]; 
12 
 
 
No es un problema trivial, entonces quien lo resolvió o conoce del tema o realizó fraude, en este 
caso en particular conozco la fuente de ambas soluciones y no hubo fraude, sin embargo se parecen 
bastante, podríamos pensar que se cambió el nombre de la función combi(int n,int k) a 
n_en_k(int n,int k). También que la función llena() se metió dentro del main y se cambió 
el nombre de tam por N. Considerando esos cambios podríamos decir que la solución dos es una 
ligera modificación de la solución 1, pero no es así. 
ll n_en_k(int n, int k) 
{ 
 if (n < k) return 0LL; 
 ll res = fact[n]; 
 res = res * factreverso[k] % mod; 
 res = res * factreverso[n-k] % mod; 
 return res; 
} 
 
int main() 
{ 
 fact[0] = 1; 
 for (int I = 1; I <= tam; ++i) 
 fact[i] = fact[i - 1] * i % mod; 
 
 factreverso[tam] = fastpow(fact[tam], mod - 2); 
 
 for (int i = tam-1; i >= 0; --i) 
 factreverso[i] = factreverso[i + 1] * ( i + 1) % mod; 
 
 int n, k; 
 cin>>n>>k; 
 
 ll res = 0LL; 
 for (int i = 0; i <= k; ++i) 
 { 
 int signo = (i % 2 == 0) ? 1:-1; 
 res = (res + fact[n - i] * n_en_k(k, i) * 
 signo % mod + mod) % mod; 
 } 
 cout<<res<<"\n"; 
 return 0; 
} 
13 
 
Por eso mismo no es posible, para un juez en línea, identificar un fraude en un concurso, lo que se 
exhorta a hacer es realizar técnicas y reglamentos que disuadan a los concursantes a realizar algún 
tipo de trampa. 
 
1.2.3.2. Prevención de Fraude 
 
¿Cómo evitamos el plagio en un concurso de programación competitiva? ¿Cómo se evita el plagio 
en el salón de clases? Si un profesor utiliza un juez en línea para evaluar a sus alumnos podría 
pensar que hubo plagio porque incluso los comentarios son los mismos, o los códigos tienen los 
mismos errores, o el código está en una lengua extranjera (buscaron el código en internet). En un 
concurso de programación hay otras técnicas que se utilizan para evitar el fraude, aunque no son 
100% efectivas son lo que se utiliza en la actualidad en la región de México y Centroamérica. 
Si bien los concursos clasificatorios no son tan estrictos con los concursantes, en la final regional 
de México y Centroamérica, donde se disputan los lugares para asistir a las Finales Mundiales, se 
aplican las siguientes reglas: 
Restricción de acceso a internet 
Únicamente se puede acceder a las paginas permitidas durante el concurso, que son la IP del 
servidor donde está el juez en línea y la documentación de los lenguajes oficiales, aunque estas 
últimas suelen estar ya descargadas, por lo que únicamente se tiene acceso por internet al juez en 
línea, se bloquean las conexiones a otros puertos para las computadoras no tengan comunicación 
vía ssh con otros equipos de cómputo. 
Modo superusuario 
Los concursantes inician sesión en la computadora que se les asigna con un usuario que no tiene 
permisos (privilegios) de hacer prácticamente nada, esto impide que el usuario llegue a burlar la 
restricción de acceso a internet o a la red local para comunicarse con otros equipos durante la 
competencia. 
 
 
14 
 
No equipos electrónicos 
Antes de entrar a la sala donde será el concurso todos los aparatos electrónicos son recogidos a 
los concursantes, si se llegase a detectar alguno durante la competencia, esto sería motivo de 
descalificación. 
Aunque en la final mundial las reglas son aún más estrictas no las abarcaremos en esta obra ya 
que incluso la región de México no cuenta con la infraestructura para cumplirlas, mucho menos 
un organizador de un concurso local. 
 
1.2.3.3. Error humano 
 
A pesar de las muchas cosas que puede hacer un juez en línea, este no puede detectar errores de 
los administradores de los concursos, sin embargo, un buen juez debe ayudarlos a corregirlos 
cuando estos los detectan. En la práctica se ha visto que cuando ocurre un error por parte de los 
administradores del concurso, son los concursantes quienes se dan cuenta que ocurre un error, o 
en la mayoría de los casos sospechan que hay un error y preguntan a los organizadores, quienes 
podrán verificar y darse cuenta si hubo un error o no. 
Se han recopilado algunos ejemplos de errores que han ocurrido en competencias y que se hace 
para solucionarlos: 
Durante el concurso se dan cuenta que el enunciado de un problema esta mal, lo que se suele 
hacer es responder en la sección de clarificaciones cual debería ser el enunciado correcto, esta 
sección es utilizada como canal de comunicación para que los concursantes puedan resolver dudas 
y se aclaren ambigüedades en los enunciados del problema. 
Durante el concurso se dan cuenta que los archivos de entrada o salida, que sirven para evaluar 
las soluciones de los concursantes, están mal, Lo que se debe hacer es en ese momento corregir 
los archivos de entrada o salida y reevaluar el problema. Esto seguramente afectara el marcador, 
quizá algunos concursantes pierdan puntos (en caso de que se les haya aceptado una solución 
incorrecta) o ganen puntos (su solución, aunque correcta había sido rechazada porque los archivos 
con los que el juez en línea verifico la solución estaban mal). Esto quizá retrase el concurso por 
15 
 
unos minutos, pero es lo mejor que se puede hacer. Esto ha pasado en concursos de clasificación 
del Gran Premio de México y Centroamérica.Pero ¿qué sucede si este error es detectado una vez que el concurso ha finalizado? También ha 
ocurrido y para bien o para mal, si algún usuario recibió puntos con una respuesta incorrecta, no 
se le pueden quitar esos puntos, la corrección hecha después de acabado el concurso solo puede 
subir los puntos de los participantes o dejarlos igual, pero no se les quitan los puntos bajo la 
premisa de que fue error de los jueces no de los usuarios, y no se sabe si hubieran llegado a la 
respuesta correcta después de haber sido notificados que su solución estaba mal, por lo tanto se 
les dejan los puntos. Y a los usuarios que tenían la solución correcta se les aumentan los puntos. 
Estos son los errores más comunes que llegan a pasar en las competencias, aunque no ocurren en 
cada concurso, se debe estar preparado para ello. 
Mas adelante se hablará sobre el uso de esas presentaciones en el juez en línea que hacen posible 
la solución de errores. 
 
1.3. Antecedentes históricos y beneficios 
 
Todo comenzó en 1970 cuando la UPE Computer Science Honor Society (Upsilon Pi Epsilon: 
Sociedad de Honor para las Ciencias de la Computación) llevó a cabo la primera competencia de 
programación [8]. La iniciativa se extendió rápidamente por Estados Unidos y Canadá con la idea 
de incrementar la ambición, habilidad de resolución de problemas y para dar oportunidades a 
estudiantes en el campo de la computación. 
Actualmente cada año, aproximadamente en abril, se llevan a cabo las finales mundiales de 
programación competitiva (ICPC World Finals). El ICPC (International Collegiate Programming 
Contest) se lleva en diferentes etapas alrededor del mundo: concursos locales, regionales y finales 
mundiales. En las finales mundiales participan alrededor de 120 universidades de distintas 
regiones del mundo, las cuales obtuvieron su pase en sus respectivas regiones al ganar los 
concursos regionales, (la Facultad de Estudios Superiores Acatlán pertenece a la región México y 
Centroamérica). Actualmente hay más de 50 mil estudiantes registrados participando en el ICPC 
de aproximadamente tres mil universidades [8]. El concurso se realiza en inglés, y aunque cada 
16 
 
región decide el idioma de la competencia la mayoría opta por este, aunque no sea la lengua 
materna de ningún concursante de la región. 
 
1.3.1. Beneficios de la programación competitiva 
 
En estos días el ICPC no es el único concurso que se lleva a cabo a nivel mundial, la mayoría de 
estos se realizan por grandes compañías con el fin de reclutar talento, aunque también hay 
concursos con el único fin de preparar a estudiantes para el ICPC. Todos los concursos de 
programación siguen un estilo similar al del ICPC debido a que los creadores de los concursos son 
en su mayoría personas que se formaron y obtuvieron sus empleos gracias a la programación 
competitiva. Se mencionan algunos concursos internacionales de programación en los cuales 
participa el grupo de Algoritmia: 
• Facebook Hackercup: No es un concurso para hackear cuentas de Facebook, es un concurso 
en cinco etapas: Ronda de Clasificación, Ronda 1, Ronda 2, Ronda 3 y Ronda Final. En cada 
ronda se presentan de tres a cuatro problemas de distinta dificultad, excepto en la Ronda Final 
donde se presentan seis problemas. Es un concurso individual donde el primer lugar se lleva 
$10,000 USD. Fuera de los primeros 25 lugares el premio es una playera para los primeros 
500 lugares, que, a pesar de no ser un premio ostentoso, se ve muy bien poner el lugar obtenido 
en un Curriculum Vitae. Participan anualmente cerca de 7000 personas alrededor del mundo. 
En este concurso cualquier lenguaje de programación es permitido. Para la evaluación de los 
problemas los concursantes, después de que han programado su solución, reciben un archivo 
de entrada y cuentan con cinco minutos para ejecutar su código con el archivo de entrada que 
descargaron para posteriormente subir un archivo con la solución del problema que depende 
del archivo de entrada y el cual fue generado por su solución. Este modo de evaluación puede 
considerarse arcaico si se compara con el grueso de los concursos de programación de hoy en 
día. Cada concursante cuenta con una oportunidad para subir su solución de cada problema 
durante el tiempo del concurso, por lo que, si no sube su archivo de salida a tiempo después 
de haber solicitado el archivo de entrada, se considera que su solución fue incorrecta. Uno 
debe estar seguro de lo que ya tiene la solución para no perder su oportunidad además de una 
buena conexión a internet. 
17 
 
• Google Code Jam: Este concurso, obviamente organizado por Google, cuenta con cinco 
rondas al igual que el Facebook Hacker Cup (incluso se llaman igual), con pequeñas 
diferencias: Una es que la Ronda 1 está dividida en tres fechas(A, B y C) y no importa en cuál 
de las tres se participe, solo se necesita quedar dentro de los primeros mil lugares en cualquiera 
de ellas para asegurar un lugar para clasificar a la siguiente ronda, se hace esto con el fin de 
facilitar a personas de distintas partes del mundo el participar ya que suele haber conflictos 
con los husos horarios. Participan poco más de 25000 personas alrededor del mundo. El 
premio es de igual manera de $10000 USD para el primer lugar. El modo de evaluación es 
distinto al del Facebook Hacker Cup, los usuarios envían su código con su solución en el 
lenguaje de programación de su elección (limitado a doce lenguajes de programación 
permitidos [9]). Entonces en los servidores de Google el código es compilado y ejecutado para 
verificar si imprime la misma solución que tienen ellos del problema dado. En el año 2018 
tuvieron dificultades porque había demasiados usuarios intentando subir sus soluciones 
provocando que el servicio de evaluación estuviera sin funcionar por algunas horas. 
• Snack Down: Realizado por CodeChef con sede en la India, en la edición anterior participaron 
alrededor de 28 mil personas de distintas partes del mundo. El premio es de $10000 USD. La 
fase final se realiza en la India y busca incluir a estudiantes y profesionales en la competencia. 
En todos estos concursos los temas a tratar van desde matemáticas discretas a geometría 
computacional, es un “temario” muy completo, también se abordan paradigmas para la resolución 
de problemas de programación, estructuras de datos y procesamiento de texto. 
A excepción del ICPC los demás concursos hacen públicos los códigos fuentes de los envíos 
realizados por los concursantes una vez finalizadas las rondas. Esto ha contribuido a que 
concursantes con menos experiencia se fortalezcan aprendiendo de las soluciones de otras 
personas, en muchos casos desconocidas. 
La Facultad de Estudios Superiores Acatlán inició su participación en las competencias de 
programación competitiva en el año 2011 con dos equipos, el grupo de Algoritmia Avanzada y 
Programación Competitiva fue fundado por un alumno de la Facultad que había participado en la 
olimpiada mexicana de informática (OMI) y obtuvo medalla de plata en dicha competencia. Esta 
primera participación por parte de la Facultad se realizó en la región México, Centroamérica y el 
Caribe, donde un equipo obtuvo el lugar número 11 de la competencia. El siguiente año se obtuvo 
el lugar 20 en la competencia regional. Aunque la final regional del ICPC no ha sido la única 
18 
 
competencia en la que se ha participado por parte del grupo de algoritmia, es la más importante y 
la que más auge ha tenido en México en los últimos años, aumentando su nivel de dificultad 
considerablemente (ha pasado de tener 150 equipos concursando a 400 en cinco años). 
Para el año 2013 ya eran cuatro equipos participando en la Final Regional de México y el Caribe 
de la FES Acatlán, el mejor de estos obtuvo el lugar 10 de la competencia, los miembros de la 
Facultad participaron desde Querétaro en dicha competencia. 
El siguiente año se logró obtenerel sexto lugar de la competencia que tuvo como sede a la 
Universidad Jesuita de Guadalajara (ITESO), Guadalajara, a partir de este año la final regional 
empezó a llevarse en un mismo sitio. Anteriormente la final se llevaba en al menos cinco sedes a 
lo largo de la República, sin embargo, solía haber problemas de conexión y desfaces en los 
horarios (una sede, la de Querétaro en 2013, comenzó media hora después que el resto de las 
sedes). Cada sede tenía su propia copia local del juez, entonces para saber el resultado final era 
esperar al resto de las sedes y juntar los resultados. La ventaja de esto es que podían participar 
muchos alumnos en la final regional (aproximadamente 170 equipos), actualmente solo se permite 
la participación de 50 equipos en la final con un máximo de dos equipos por universidad. 
El 2015 fue el año en que el grupo de Algoritmia ha estado más cerca de clasificar a las Finales 
Mundiales del ICPC y en el que se empezaron a notar más los frutos de los miembros del grupo. 
El equipo UNAM1 tuvo el primer lugar en las 4 rondas clasificatorias del gran premio de México 
y Centroamérica, clasificando a la Final Regional como el equipo favorito para ganar la 
competencia y obtener su pase a las Finales Mundiales, sin embargo, la fortuna no siempre le 
sonríe a todos y el equipo quedó en cuarto lugar de la competencia. Uno de los miembros de ese 
equipo se encuentra actualmente trabajando en Microsoft en el estado de Washington, EUA, otro 
de los miembros del equipo se encuentra laborando en Guadalajara. 
Otros exalumnos de la FES Acatlán que fueron miembros del grupo de algoritmia se encuentran 
trabajando en empresas como Oracle, Wizeline (ambas en Guadalajara) y GoCater (Francia). 
El verano pasado uno de los miembros de Algoritmia se fue “intern”5 al campus de Microsoft en 
Redmond, y más miembros actuales del grupo han aplicado para participar de interns en la misma 
empresa, así como de Facebook. 
 
5 La traducción más cercana es pasantía, un “intern” suele trabajar en verano en una compañía durante 
12 semanas con el requisito de que sea un estudiante universitario. 
19 
 
Capítulo 2 
2. Desarrollo web con Meteor 
 
 
2.1. ¿Qué es Meteor? 
 
Meteor es una plataforma de software libre de desarrollo de aplicaciones Web y móviles (Android 
y iOS), es una plataforma Full Stack (base de datos, backend y frontend). Esta plataforma 
isomórfica utiliza el protocolo DDP (siguiendo un patrón de suscribirse-publicar) para la 
comunicación entre cliente y servidor, está escrita sobre Nodejs y utiliza MongoDB para 
almacenar la información. Quizá sean demasiados conceptos en un solo párrafo, a continuación, 
se desglosan: 
Backend o server side 
Es el cómo el sitio funciona y actualiza la información, se puede decir que es todo lo que el usuario 
no ve en el explorador Web, es donde se mantiene la lógica de la aplicación, es donde se trabaja 
con la seguridad, estructura y administración de la información. Cuando un usuario se conecta al 
servicio Web, solicita información al servidor. Del lado del servidor se decide qué información 
mostrar o actualizar después de ser solicitada por el cliente. 
Frontend 
Es todo lo que el usuario puede ver, es con lo que interactúa, el diseño. El usuario recibe la 
información y del lado del frontend se maneja el diseño para mostrar la información de una manera 
amigable a este, es lo que tiene que ver con la experiencia del usuario (UX). 
Full Stack: 
Se dice que una plataforma es considerada Full Stack si tiene herramientas para manejar la base 
de datos, el frontend y el backend de manera que convivan sin que haya fricciones entre ellas. La 
más conocida es LAMP la cual usa Linux como Sistema Operativo, Apache como servidor Web, 
20 
 
MySQL como el sistema administrador de base de datos y PHP como lenguaje de scripts para 
manejar el backend; podría decirse que es de las más antiguas y por donde muchos desarrolladores 
Web empiezan su camino. 
De las plataformas Full Stack más recientes se encuentra MEAN la cual utiliza MongoDB para 
administrar las bases de datos (es un sistema NoSQL), Express, Angular que permite el desarrollo 
del frontend en Javascript (fue desarrollado por Google) y Nodejs el cual permite utilizar 
Javascript (JS) del lado del servidor (backend). 
Isomórfica 
Podemos llamar a Meteor una plataforma isomórfica porque permite usar el mismo código en el 
lado del servidor y del cliente (backend y frontend respectivamente). Meteor está escrito en JS y 
ejecuta el mismo código en el cliente y en el servidor a menos que explícitamente se diga de qué 
lado se debe ejecutar el código. Esto es una gran ventaja porque no se tiene que aprender un nuevo 
lenguaje de programación para trabajar entre el cliente y el servidor. 
 
2.2. El protocolo DDP 
 
Desarrollado originalmente por el MDG (Meteor Developer Group), permite llamadas remotas a 
procedimientos del cliente al servidor y también otorga al cliente la facilidad de suscribirse a un 
conjunto de documentos con la premisa de que el cliente siempre estará actualizado y será 
notificado cuando estos documentos hayan sido modificados en tiempo real. Resuelve muchas de 
las dificultades que desarrolladores Web enfrentan hoy en día, ya que muchas veces para saber si 
hubo algún cambio en algún documento tienen que volver a solicitar toda la información al 
servidor, aumentando la carga sobre este. El protocolo DDP [10] fue la gran noticia cuando se 
creó Meteor y una de las razones por la cual utilizar Meteor para desarrollar el juez. 
El Juez Boca, que se mencionó anteriormente, funciona bajo el esquema de entregar páginas Web 
estáticas que se actualizan cada cierto periodo de tiempo; incluso el DOM Judge, utilizado en la 
final mundial, trabaja bajo este mismo formato. 
21 
 
Lo anterior lo hacen para mantener al usuario siempre actualizado sin que tenga que recargar la 
página para solicitar la información más reciente al servidor, como el scoreboard, por ejemplo. 
Sin embargo, esto ha llegado a ser un problema en competencias regionales en México ya que 
provoca que se aumente la carga al servidor ya que el cliente sigue refrescando el contenido y 
solicitando, aunque el usuario no esté prestando atención al juez en ese momento, información al 
servidor, llegando a provocar incluso que debido a la carga de trabajo el servidor no pudiera 
atender solicitudes en verdad importantes como el envío de soluciones de los problemas del 
concurso. 
Incluso estas actualizaciones forzadas no solicitadas llegan a ser molestas cuando alguien está 
viendo el scoreboard (usualmente una lista con más de 300 equipos) y antes de que el usuario 
termine de revisar la información la página se refresca regresando al inicio y provocando que el 
usuario tenga que volver a empezar su búsqueda y resultando en una pérdida de tiempo. El 
protocolo DDP de Meteor resuelve este inconveniente de manera natural sin complicaciones o la 
necesidad de escribir código adicional para poder lograrlo. 
 
2.2.1. Optimistic UI 
 
La manera en que trabaja Meteor para modificar información o guardar información que viene del 
cliente es con Methods (métodos) [11] [12]. Si alguien ha trabajado con solicitudes HTTP tipo 
POST los encontrará similares, sin embargo, los métodos tienen algunos beneficios que las 
solicitudes HTTP no tienen, por ejemplo, gracias a Optimistic-ui [13], se puede simular el 
comportamiento del servidor del lado del cliente haciendo parecer al sitio Web más rápido de lo 
que realmente es. 
Cuando un administrador de concurso desea crear un nuevo concurso, un nuevo problema, 
modificar la fecha de inicio de un concurso, modificar el enunciado de un problema; lo normal es 
mandar la solicitud al servidor, el servidor autoriza la modificación o creación del documento y 
después manda su respuesta al cliente, posiblemente tambiénenvíe los datos del documento que 
modificó. 
22 
 
Con los métodos de Meteor, el cliente corre una simulación donde se crea el nuevo documento, se 
elimina o se modifica, entonces el cliente no tiene por qué esperar a que el servidor reciba la 
solicitud y devuelva una respuesta para seguir trabajando. Aunque esto en realidad sí pasa (se hace 
una predicción), si está bien programado el cliente no notara la diferencia, la ilustración 2-1 
muestra cómo se lleva a cabo este proceso el cual es explicado en los siguientes párrafos. 
 
Se mostrará cómo funciona el protocolo DDP usando como ejemplo el envío de una solución por 
parte de un usuario en un concurso. 
Suponiendo que nuestro usuario ya ha realizado cierta cantidad de envíos previamente de distintos 
problemas durante un concurso, el usuario tiene acceso a una tabla que muestra los envíos que ha 
realizado junto con sus veredictos y se ve en la tabla 2-1: 
 
Ilustración 2-1 Funcionamiento de Optimistic UI, obtenido desde [13] 
23 
 
Tabla 2-1Envíos de un usuario durante un concurso 
Problema Veredicto Puntos Lenguaje Fecha 
Encriptación 
Alienígena 
Incorrecto 0 C++ 27/09/2018 
04:59:25 pm 
Barbacoa Parcialmente 
Aceptado 
70 C++11 27/09/2018 
04:37:09 pm 
Fuera de la 
cama 
Aceptado 100 Java8 27/09/2018 
01:29:22 pm 
La fuente de información de la herramienta Web es la base de datos, con la cual el servidor obtiene 
toda la información. Sin embargo, para el cliente, toda la información viene de una mini base de 
datos llamada minimongo (se explicará sobre Mongo en el siguiente capítulo), la cual ha obtenido 
toda su información de la base de datos. 
Entonces cuando un usuario manda un nuevo envío para ser evaluado, lo hace con la siguiente 
información en un objeto tipo JSON: 
 
Y cuando se invoca a un método de Meteor de la siguiente manera: 
 
{ 
 "usuario": "Nombre de usuario", 
 "idproblema": "_id", 
 "idconcurso": "_id", 
 "codigo": "#include ...", 
 "lenguaje": "C++11" 
} 
Meteor.call ('subir_envio', 
 datos, 
 (error, respuesta) => { 
 if (error) { swal( `Error ${error.error}`, error.reason ... 
 toastr['success'](`Felicidades ${Meteor.user().username ... 
 if ( Session.get('slugconcurso') ) 
 Router.go(`/concursos/${Session.get('slugconcurso ... 
 else Router.go('/problemas/veredictos'); 
 } 
); 
24 
 
Esta solicitud es enviada al servidor, y al mismo tiempo se corre una simulación del método del 
lado del cliente, y aunque el cliente no cuenta con toda la información con la que cuenta el servidor 
al poder acceder a la base de datos, la simulación hace un buen trabajo. 
Dado que Meteor es isomórfico, se utiliza el mismo código para la simulación del lado del cliente 
que para la llamada del lado del servidor, el cliente obtiene primero la respuesta de la simulación 
y aun antes de que el servidor termine de procesar la solicitud obtiene una versión actualizada de 
su tabla con información de la base de datos de minimongo, mostrando casi instantáneamente la 
nueva tabla con los envíos (ver tabla 2-2). 
Tabla 2-2Envíos después de subir una solución 
Problema Veredicto Puntos Lenguaje Fecha 
Encriptación 
Alienígena 
Pendiente -- C++ 27/09/2018 
05:04:25 pm 
Encriptación 
Alienígena 
Incorrecto 0 C++ 27/09/2018 
04:59:25 pm 
Barbacoa Parcialmente 
Aceptado 
70 C++11 27/09/2018 
04:37:09 pm 
Fuera de la 
cama 
Aceptado 100 Java8 27/09/2018 
01:29:22 pm 
 
Y aunque el último registro de la tabla (el que tiene veredicto pendiente) aún no existe en la base 
de datos, el usuario puede ver la información de su ultimo envío como si ya existiera; 
posteriormente el servidor devolverá la respuesta de la solicitud con la misma información de la 
predicción que hizo Optimistic UI, pero sin mostrar un cambio aparente para el usuario. Lo que 
se hizo fue hacerle creer que la herramienta es más rápida de lo que en verdad es. 
Si alguno es descuidado con las simulaciones podría darse el caso que la simulación agregue un 
nuevo registro a la base de datos de minimongo y por ende mostrarlo en la tabla de envíos, pero 
el servidor podría llegar a rechazar la solicitud evitando que se agregue un nuevo documento a la 
base de datos, eso provocaría que cuando se obtenga la respuesta del servidor el documento se 
elimine de minimongo y el registro desaparezca de la tabla instantes después de haber aparecido. 
Afortunadamente este no es el caso. 
25 
 
Para poder separar el código que debe ejecutarse únicamente en el cliente o en el servidor debe 
hacer de la siguiente manera: 
 
Y surge la pregunta: ¿cómo es que la tabla de envíos se actualiza automáticamente modificando 
la información de los envíos (agregando el veredicto una vez que ha sido evaluado o agregando 
nuevos envíos) sin que el usuario actualice la página Web? 
 
2.3. Programación reactiva 
 
Se puede utilizar el cuerpo humano para explicar que es la programación reactiva y cómo funciona: 
En un día normal a cualquier ser humano le dará hambre, estará lleno, tendrá sed, sueño, ganas de 
ir al baño, entre otros; el cuerpo, inteligentemente, avisa cuando se requiere o ya no se requiere 
algo. Una persona no pasa su día preguntándose ¿tengo hambre?, ¿tengo ganas de ir al baño? El 
cuerpo simplemente avisa y entonces uno toma acciones. 
Algo similar ocurre con la programación reactiva, la cual es un paradigma de programación 
relacionada con el flujo de información y propagación del cambio que esta sufre; en el ejemplo 
del cuerpo humano cuando alguien está lleno, no significa que nunca más volverá a tener hambre, 
Meteor.methods ({ 
 ... 
 'subir_envio'(datos) { 
 
 if (this.isSimulation) { 
 /* Código que corre únicamente del lado del cliente */ 
 } 
 
 if (!this.isSimulation) { 
 /* Código que corre únicamente del lado del servidor */ 
 } 
 
 /* Código que corre en ambos lados */ 
 } 
 ... 
}); 
26 
 
cuando el contenido en el estómago cambie el cuerpo eventualmente volverá a tener hambre sin 
necesidad de que la persona haga algo en especial para saber si tiene hambre o para saber cómo 
se encuentra su estómago [14]. 
Para que la programación reactiva suceda se necesita una fuente de información reactiva, la cual 
nos avisa cuando algo dentro de ella cambia: El estómago nos avisa cuando el contenido, por así 
decirlo, dentro de él cambia. 
Por ejemplo, adentrándonos a la herramienta Web, podemos tener una variable llamada puntos, 
que nos indica cuántos puntos ha acumulado un usuario durante un concurso, el valor de esta 
variable cambia con el tiempo a medida que se resuelvan más problemas. Pero de nada nos sirve 
que nuestra variable nos avise que cambió de valor si nadie la escucha. 
¿Para qué nos sirve saber cuántos puntos lleva un usuario? Para saber su posición en el scoreboard. 
Entonces si su puntaje cambia (porque se resolvió un problema no resuelto anteriormente), 
cambiará también el color que tiene en el marcador dependiendo cual fue el nuevo problema que 
resolvió e incluso la asignación de una imagen de trofeo junto a su nombre. Entonces, todas estas 
cosas deben de actualizarse cuando sus puntos cambian. 
En la ilustración 2-2 se muestran los cambios generados a partir del nuevo valor del puntaje al 
resolver un problema (el 100 dentro de un rectángulo): el usuario Jiren subió su posición en el 
Ilustración 2-2 Scoreboard y actualizaciones 
27 
 
scoreboard del sexto lugar al tercero, su puntaje general aumentó a 200 puntos, en lugar de 
aparecer un numero indicando su lugar aparece un trofeo y el problema que resolvió (L) ahora se 
ve sombreado (verde). 
Estos cambios inherentes al nuevo valor del puntaje se generan a través de lo que se conoce como 
computaciones reactivas, que básicamente es un segmento de código dentro de unafunción (no 
necesariamente la función completa) que será reevaluado cuando la fuente reactiva dentro de esa 
sección de código cambie. 
 
2.3.1. Fuentes reactivas 
 
Meteor tiene, desde su concepción, la programación reactiva como parte de él [15], y tiene tres 
principales fuentes reactivas: 
Minimongo 
Es la principal fuente reactiva de información [16], las consultas a la base de datos son la fuente 
reactiva, entonces si una colección cambia porque se modificó, agrego o elimino un documento 
de la colección en minimongo cualquier sección de código, en el cliente, que obtenga o manipulé 
información obtenida por la consulta en la colección volverá a ejecutarse. 
Por ejemplo: 
 
Cuando se modifica algún documento en la colección Noficicaciones, únicamente se ejecuta 
la última línea de código (la que tiene el enunciado return), las primeras líneas de código en 
notificaciones() no se ven afectadas si cambia algún valor en la colección de 
Template.navbar.helpers ({ 
 ... 
 notificaciones() { 
 let username = Meteor.user(); 
 if (username) username = username.username; 
 return Notificaciones.find({username:username}, 
 {sort:{hora:-1}}); 
 } 
}); 
28 
 
Notificaciones, por eso no se vuelven a ejecutar. En cambio, si el usuario cambia (cierra 
sesión, inicia sesión otro usuario) las primeras líneas de código en notificaciones() se 
vuelven a ejecutar porque obtienen información de Meteor.user(), provocando además que la 
consulta también se vuelva a ejecutar. 
Pero ¿cómo sabe el cliente que hubo algún cambio en la colección de notificaciones o en alguna 
otra colección para volver a ejecutar las consultas correspondientes? Esto se hace mediante el 
modelo de subscripciones-publicaciones. 
Normalmente el cliente se suscribe a cierta información al entrar a una nueva ruta dentro del sitio 
Web, al observar algún cambio en alguna colección o al ocurrir un evento. 
Una vez que el cliente se suscribe, el servidor verifica los privilegios que el usuario tiene y que 
datos pude ver, entonces publica la información que le es permitida en forma de cursores [17], la 
cual es recibida por minimongo y eso activa el computo reactivo. La ilustración 2-3 muestra cómo 
funcionan las publicaciones subscriciones. 
 
 
Ilustración 2-3 Suscripciones y Publicaciones en Meteor 
29 
 
El siguiente extracto de código muestra cómo se publica la información cuando un usuario quiere 
ver los problemas de un concurso: 
 
 
 
/* Cliente */ 
Router.route('/concursos/:slugconcurso/problemas', { 
 waitOn: function () { 
 return [Meteor.subscribe('problemas_concurso', 
 this.params.slugconcurso)]; 
 }, 
 ... 
}); 
 
/* Servidor */ 
Meteor.publish ('problemas_concurso', 
 function(slugconcurso) { 
 /*slugconcurso: es un identificador de concurso*/ 
 
 /* Verificaciones */ 
 //evitar inyecciones de codigo 
 check(slugconcurso, NonEmptyString); 
 
 //verificar que el concurso exista 
 let c = Concursos.findOne({slug:slugconcurso}, 
 {fields:{slug:1, inicio:1}}); 
 if (!c) return []; 
 //si aun no empieza no puede ver los problemas 
 const idconcurso = c._id; 
 const d = new Date(); 
 if (c.inicio > d) 
 return []; 
 
 //Se publica la información del concurso 
 //y los problemas del mismo 
 return [Problemas_concurso.find({idconcurso:idconcurso}), 
 Concursos.find({_id:idconcurso},{fields:{slug:1}})]; 
 } 
); 
30 
 
Variables de sesión 
Las variables de sesión son otra fuente de información reactiva, sirven para guardar información 
en pares del tipo llave-valor. En la herramienta en línea que se desarrolló se utilizó para guardar 
información para identificar problemas, concursos y ayudar a saber el estado de algunas 
operaciones (como subir un archivo de entrada de 10 mb). Podrían ser comparadas con variables 
globales. 
También son utilizadas para guardar resultados obtenidos en consultas a la base de datos cuya 
información ya no está disponible para el cliente. Tienen tres funciones básicas: set(), get(), 
equals(), que sirven para asignarles un valor, obtener su valor y realizar comparaciones, todas 
de manera inteligente. 
Variables reactivas 
Meteor permite crear variables reactivas propias, normalmente para reducir el alcance de las 
mismas (las variables de sesión son globales) ya que se requieren para casos muy particulares. El 
juez en línea no las utiliza ya que la herramienta se ha bastado con las variables de sesión y 
minimongo. 
 
2.3.2. Tracker 
 
Hasta el momento la programación reactiva ha sido magia [14], las fuentes reactivas avisan que 
hay cambios y entonces estos se propagan; pero la magia tiene su explicación. 
Tracker es la herramienta que utiliza Meteor para rastrear las dependencias de las fuentes reactivas 
de información, el programador no tiene que preocuparse por declarar o guardar en alguna parte 
todas las secciones de su código que utilizan fuentes reactivas [18]. 
Cuando se ejecutan funciones con fuentes reactivas, se guarda un objeto de computo, el cual es 
invalidado cuando una fuente reactiva actualiza su valor y entonces se vuelve a ejecutar ese objeto 
de computo. 
Esto se conoce como computo reactivo, que son las secciones de código re-ejecutadas cada vez 
que una fuente reactiva cambia su valor. 
31 
 
La manera en que Tracker mantiene todo esto es por medio de teoría de gráficas, guardando 
dependencias como aristas y las fuentes reactivas como nodos, de esta manera los cambios se 
propagan haciendo algo similar a una búsqueda en una gráfica dirigida. 
 
La ilustración 2-4 muestra cómo se comporta Meteor al notificar a los clientes suscritos a cierta 
información de la base de datos cuando hay cambios en ella. Todo esto genera una reacción en 
cadena que termina mostrando al usuario la información más reciente sin que este tenga que hacer 
o presionar algún botón, todo llega de manera automática y natural. Es importante recalcar que en 
un concurso donde el tiempo es un factor decisivo en desempates es necesario contar con la 
información más reciente sin contratiempos. 
Esta es una de las razones principales por las que Meteor fue escogido como el framework para 
programar el juez en línea, se requiere entregar velocidad, o al menos hacer creer que hay 
velocidad. 
 
Ilustración 2-4 Computo reactivo en clientes suscritos 
32 
 
Capítulo 3 
3. Almacenamiento de información con 
MongoDB 
 
 
3.1. SQL vs NoSQL 
 
Cuando se habla de NoSQL (bases de datos no relacionales, a veces también referido como Not 
Only SQL) se hace mención de distintas tecnologías de bases de datos desarrolladas en los últimos 
años con características que las bases de datos relacionales (SQL) no tienen. 
Una manera de decidirse por cual camino tomar es estudiando ambos paradigmas, y decidir cual 
es el mejor para el momento, aunque sin la ayuda adecuada [19] las voces del mundo dirán que se 
debe usar MongoDB porque es lo de hoy. Se escogió MongoDB pero no por esas razones, en este 
capitulo se da el por qué. 
Actualmente cuando se busca desarrollar y entregar un producto, la información se guarda de 
manera estructurada, semi estructurada, no estructurada y de manera polimórfica; los tipos de dato 
cambian frecuentemente conforme se van agregando características al producto. 
El juez en línea no es la excepción, las bases de datos relacionales son muy estrictas en cuanto al 
esquema en que se guardará la información, pero cuando se está en desarrollo las ideas van y 
vienen y lo que fue un modelo aceptado para almacenar la información puede ser modificado 
completamente al día siguiente, incluso el mismo día. Entonces, ¿Qué se hace cuando ya se pobló 
coninformación la base de datos, pero se desea cambiar el esquema? 
Cambiar el esquema en una base de datos ya poblada suele ser un dolor de cabeza en las bases de 
datos tipo SQL, pero no en las bases de datos no relacionales, cuando se cambia el esquema 
únicamente se agregan los nuevos “registros” sin hacer ningún alboroto, pueden vivir en la misma 
“tabla” registros con diferentes “columnas”, incluso aunque no tengan nada en común. 
33 
 
Quizá alguien piense que esto lleva al desorden y al caos, pero esta flexibilidad permite hacer 
mejoras continuas. Por ejemplo, al desarrollar el juez, se planteó el modelo de cómo se 
almacenaría la información de los marcadores (scoreboard) en los concursos. La idea inicial fue 
la siguiente: 
 
Con este modelo habría únicamente un “registro” (documento) por concurso; sin embargo, esto 
causaría problemas debido a la alta actualización del scoreboard en un concurso; si se espera que 
haya más de mil cambios en un corto periodo de tiempo, es necesario reducir la carga de trabajo 
del servidor, ya que cada vez que hubiera un cambio, gracias al protocolo DDP [10], todos los 
concursantes y espectadores recibirían de nuevo todo el documento. 
El esquema de cómo se vería el scoreboard cambio varias veces hasta llegar a la versión actual. 
Lo que se hizo con MongoDB fue seguir poblando las colecciones con documentos sin borrar la 
información anterior para seguir haciendo pruebas, algo que no hubiera sido posible con una base 
de datos relacional. 
Scoreboard: { 
 "_id": Mongo id, 
 "idconcurso": Mongo id, 
 "info": { 
 <idusuario>: { 
 "puntos": entero, 
 "penalizacion": entero, 
 "problemas": { 
 <idproblema> : { 
 "puntos": entero, 
 "intentos": entero, 
 "primero_en_resolver": booleano 
 }, 
 ... 
 <idproblema>: { 
 ... 
 } 
 } 
 }, 
 ... 
 <idusuario> : {} 
 } 
} 
34 
 
 
3.2. ¿Qué es MongoDB? 
 
MongoDB es un administrador de base de datos de software libre basado en documentos que 
almacena la información en documentos tipo JSON cuya estructura y campos pueden variar entre 
documento y documento [20]. Esta es una de las razones principales por las que se decidió trabajar 
con Mongo, por la continua variación de la estructura de la información en el juez en línea. 
En [21] se discuten fuertemente los modelos de bases de datos relacionales y los no relacionales, 
la intención no es que un modelo sustituya al otro, sino que uno se de cuenta que no todos los 
modelos son para todos los proyectos. 
A continuación, se dan algunas definiciones antes de seguir el esquema de la base de datos que 
utiliza el juez en línea. 
Document (documento) 
Es un registro en una colección de MongoDB análogo a un objeto JSON, en el sistema SQL su 
homologo sería un registro en una tabla. 
JSON (Javascript Object Notation) 
Es un formato de intercambio de información fácil de leer para humanos y computadoras [22], 
aunque está basado en Javascript usa convenciones usadas por muchos lenguajes de programación 
logrando que estos pueden leer este tipo de documentos. Son similares a lo que en otros lenguajes 
se conocería como objeto, registro, estructura, tabla hash, diccionario, etc. Si bien los objetos 
JSON no son parte del estándar de algunos lenguajes de programación es muy fácil encontrar 
librerías para poder utilizarlos o incluso escribir una librería que pueda utilizarlos, la ilustración 
3-1 muestra cómo es un objeto JSON. 
 
Ilustración 3-1 Representación de una gráfica dirigía de la expresión regular de un JSON, obtenida de [22] 
35 
 
Collection (Colección) 
Es una agrupación de documentos de Mongo, similar a una tabla en SQL. Las colecciones no 
fuerzan a que se cumpla un esquema en particular (como es el caso en SQL), aunque mucha gente 
tiende a forzarlo al momento de guardar documentos en las colecciones para mantener cierta 
consistencia entre todos sus documentos, esto se hace al revisar el formato de los documentos, por 
fuera de MongoDB, antes de insertarlos en la colección. Los documentos dentro de la misma 
colección suelen tener campos similares (pero no necesariamente los mismos) [23], lo cual es 
notorio en la evolución del proyecto cuando se ha ido cambiando el “esquema” del mismo o 
porque arbitrariamente así se han decido almacenar (el juez en línea explota esta característica de 
Mongo). 
Aunque algunas personas usan MongoDB solo porque es algo relativamente nuevo, se debe pensar 
dos veces antes de utilizarlo, y considerar los pros y los contras de hacerlo. Al mostrar las 
especificaciones de la base de datos se hará evidente la necesidad de usar MongoBD, aunque otros 
proyectos quizá requieran otro tipo de base de datos. 
Se consideró seriamente [24] para decidir si se debía utilizar MongoDB o algún otro manejador 
de base de datos relacional o no relacional. Como suele decirse en otros campos: MongoDB no es 
para todos. En [25] se discute claramente porque MongoDB no debió utilizarse en una red social 
llamada Diaspora* [26] y el vía crucis que se vivió desde que se empezó a utilizar MongoDB hasta 
que se cambió por una base de datos relacional. Quizá sea importante resaltar que MongoDB no 
ha sido un dolor de cabeza en el desarrollo del juez en línea, sino algo sencillo y necesario. 
 
3.3. Colecciones del juez en línea 
 
Una buena guía para diseñar bases de datos orientadas a objetos (MongoDB) se encuentra en [27]. 
Algunas personas han llegado a pensar que estos modelos son recientes sin embargo llevan años 
implementándose, solo que no habían adquirido popularidad. En [27] se encuentran instrucciones 
para hacer consultas a este tipo de bases de datos de manera eficiente y ha sido de gran utilidad al 
diseñar las consultas y colecciones del juez en línea. 
36 
 
Si bien no todas las colecciones que utiliza el juez en línea se comportan como no relacionales, al 
describir cada una se hará aún más evidente la necesidad de MongoDB para almacenar la 
información del juez. La descripción de las colecciones que usa el juez en línea se da a 
continuación en orden alfabético según sus nombres: 
Aclaraciones 
Esta colección registra las dudas que van saliendo durante cada concurso por los participantes, es 
la vía de comunicación de estos con los organizadores. 
• _id6: Es la llave primaria del documento [28]. 
• Idconcurso: Toda aclaración va ligada a un concurso, este id indica en que concurso se 
hizo la pregunta. Fuera de un concurso no se hacen aclaraciones debido a que no se 
asegura que haya un humano resolviendo las dudas sobre problemas del juez, sin embargo, 
hay comentarios que se pueden dejar en cada problema. 
• Idproblema: También van ligadas a un problema en particular, cuando hay un concurso 
puede que un participante no tenga claro el enunciado de un problema, entonces hace la 
pregunta correspondiente, el ligar la pregunta a un problema hace más fácil a los 
organizadores de un concurso saber de qué está hablando el participante. 
• Autor: Es el usuario de la persona que hizo la pregunta, este únicamente es visible para 
los organizadores de un concurso (los demás concursantes no saben quién hizo la 
pregunta) y ayuda a dar seguimiento a las dudas o para evitar que se abuse del sistema. 
• Pregunta: Es la duda que el participante del concurso tiene. Se permite a cada usuario 
hacer una pregunta cada 30 segundos. Las preguntas no son visibles para el público a 
menos que hayan sido contestadas por algún administrador del concurso. 
• Respuesta: Es la respuesta que dan los organizadores de concurso a la pregunta en 
particular, estos pueden decidir no contestar la pregunta en caso de que lo consideren 
necesario.6 El campo _id está reservado para usarse como llave primaria; su valor debe ser único en la colección, es 
inmutable y puede ser de cualquier tipo (a excepción de un arreglo) 
El _id utilizado por MongoDB es una cadena de 12 caracteres que se genera de la siguiente forma: 
• Cuatro caracteres representando el tiempo transcurrido desde el Unix epoch. 
• Cinco caracteres creados al azar. 
• Tres caracteres de un contador inicializado en un valor al azar. 
Se omite el _id en la en la descripción de futuras colecciones debido a que no cambia la información 
respecto a este. 
37 
 
• Creado_en: Sirve para ordenar las preguntas en orden en que fueron hechas, ayuda a 
responder en orden para no hacer esperar a concursantes y para llevar una comunicación 
más amena con los concursantes. 
Blogposts 
Mantiene un historial con las noticias más recientes relacionadas con la programación competitiva 
y el Grupo de Algoritmia de la FES Acatlán. 
• Título: Es el título del post que será creado. 
• Imagen: Cada blogpost requiere al menos una imagen, no se permite que sea únicamente 
texto, esta aparece en la portada del post. Dada la reducida capacidad de almacenamiento 
con la que dispone el juez en línea se recomienda que se almacene en otra parte la imagen 
y únicamente se provea con una URL para poder acceder a ella7. 
• Resumen: Cuando se accede al sitio Web del juez en línea lo primero que se ve es la lista 
de blogs publicados, el resumen es la parte del texto que se muestra como vista previa del 
blog para invitar a los visitantes a leerlo. 
• Texto: Es el texto con el que está compuesto el blogspot, puede estar en markdown, html 
o una combinación de ambos para hacerlo más atractivo, el juez en línea no tiene un editor 
de markdown o html dado que este no es su propósito o razón por la que fue creado; sin 
embargo, es fácil encontrar en internet un editor para estos y pegar el texto en markdown 
o html en el juez. 
• Tag: Indica el tema a tratar en el blogpost, sirve para buscar posts por tema y para que el 
usuario pueda saber de qué va a tratar lo que va a leer, si bien aún no está implementada 
una búsqueda de blogposts por tag, es algo que se hará a futuro y se menciona en el 
capítulo cinco de esta obra. 
• Publicado: Indica si el blogpost está disponible al público o no, si aún está en edición 
únicamente quienes tienen permitido modificarlo pueden verlo. 
• Idautor: Liga al blogpost con su autor, únicamente usuarios que tienen rol de blog pueden 
escribir nuevos blogs o recibir invitación a editarlos 
 
7 Actualmente todas las imágenes a las que tienen acceso el juez, ya sea por blogposts, problemas o 
concursos son almacenadas en una carpeta publica en Dropbox. 
38 
 
• Autor: Esta redundancia con el campo anterior ahorra tiempo de computo al evitar una 
consulta en la base de datos para averiguar quién es el autor del blogpost. Este tipo de 
redundancias podrá observarse en otras colecciones de la base de datos. 
• Creado: Permite ordenar, con fines de visualización, los blogposts para tener acceso a los 
más recientes primero. 
Casos 
Todo problema tiene un conjunto de entradas y salidas secretas con los cuales se califican los 
envíos hechos por los usuarios dentro y fuera de un concurso. En el modelo original de la colección 
de Problemas, esta colección [Casos] estaba contenida dentro de la primera; esto se quitó debido 
a que MongoDB tiene un límite de 16 MB por documento y cada archivo de entrada llega a pesar 
hasta 10 mb8 (cuando la entrada es muy corta llega a ser de unkb), por lo que cada par de archivo 
de entrada y salida se almacena como un solo documento. 
La cantidad de casos que un problema tiene es de aproximadamente cuarenta. 
• Idproblema: Similar a una llave foránea, indica a que problema pertenece esta entrada y 
salida. 
• Entrada: Es la entrada secreta recibe una posible solución del problema al que pertenece. 
• Salida: Es la salida que debe generar la solución enviada por el usuario, si las salidas son 
distintas se considera como incorrecta su solución. 
• Caso: Para mejor manejo de las entradas y salidas, estas se han dividido en tres casos: 
pequeño, mediano y grande; estos van aumentando en dificultad y normalmente también 
en tamaño, esto se ha hecho para evaluar distintas soluciones y sus complejidades en un 
mismo problema. 
• Creado: Esta fecha ayuda a mantener un orden por caso al momento de evaluarlos y 
extraerlos de la colección. 
 
 
 
 
8 Si bien no hay un estándar de cuanto debe pesar un archivo de entrada o de salida, el limite de 
MongoDB ha permitido almacenar el 99.99% de los archivos de entrada. 
39 
 
Concursos 
La colección almacena los detalles del concurso para ser mostrados al público, así como la 
información necesaria para que cada concurso pueda ser editado y compartido con los 
organizadores del evento. 
• Nombre: Es el nombre que llevará el concurso. 
• Nombre corto: Este campo únicamente es utilizado para generar una ruta corta que pueda 
ser compartida a través de redes sociales u otro medio electrónico, es similar a un url 
shortener dentro del juez en línea. 
• Inicio: Es la fecha9 en que el concurso iniciará, a partir de esta fecha las personas inscritas 
en el concurso podrán hacer preguntas, subir soluciones y se bloquea la opción de 
desinscribirse del concurso, también esta fecha permite ver el scoreboard con todos los 
problemas y puntaje. Antes de esta fecha las acciones anteriores no son permitidas. 
• Fin: Es la fecha en la que finaliza el concurso; una vez que este ha finalizado ya no es 
posible hacer más envíos al concurso para intentar subir puntos (es posible resolver los 
problemas fuera del concurso, pero sin ningún efecto en el scoreboard), tampoco se 
permite hacer más preguntas y/o aclaraciones. 
• Descripción: Sirve para dar información adicional sobre el concurso realizado, suele ser 
la razón por la que se celebra el evento: algún aniversario, tradición anual/semestral o la 
razón que los organizadores crean conveniente. 
• Premios: Normalmente los concursos de entrenamiento no llevan ningún premio ya que 
la mayoría de los participantes no lo hacen desde alguna universidad o sede, si no desde 
sus casas. Algunos concursos son patrocinados y se entregan premios a los participantes 
dentro de la sede y un premio especial al mejor concursante que no estuvo presente en una 
sede. 
• Reglas: Aunque normalmente todos los concursos de programación competitiva siguen 
las reglas del ICPC descritas en [29], cada evento tiene la libertad de crear sus propias 
reglas que suelen referirse a cuestiones administrativas y logística; como hora de acceso, 
límite de concursantes, lenguajes de programación permitidos (algunos concursos son más 
 
9 Si bien todas las fechas almacenadas en Mongo están en tiempo epoch, en ellas se guarda la 
información con precisión de día, mes, año, hora, minutos y segundos. 
40 
 
flexibles en cuando a los lenguajes de programación permitidos para concursar), costos 
administrativos, etc. 
• Bases: En este campo se agregan especificaciones del evento que no vienen en la 
descripción ni en las reglas, como el sistema operativo a utilizar, software instalado en los 
equipos de cómputo, etc. Las bases, premios y reglas se pueden escribir en formato html 
para mayor claridad. 
• Congelar_en: Cuando se alcanza esta fecha el scoreboard se deja de actualizar 
parcialmente para los participantes del evento (los organizadores del concurso siempre 
tienen acceso al scoreboard actualizado en todo momento). Los concursantes desconocen, 
al llegar a esta fecha, el puntaje actualizado de los demás, se les permite saber de cuales 
problemas han hecho nuevos envíos, pero no el veredicto de estos, únicamente de sus 
propios envíos.

Continuar navegando