Un script es uno de los dos tipos de acción de automatización. Cuando una regla se dispara, su script se ejecuta una vez, con información sobre el evento que lo activó. Los scripts son ideales para pasos fijos y predecibles —otorgar un logro, mover a un miembro a un grupo, asignar una medalla— que deben ejecutarse igual cada vez.
Los scripts se escriben en Starlark, un dialecto pequeño y determinista de Python. Si conoces un poco de Python, te resultará familiar: las variables, if/elif/else, los bucles for, las listas, los diccionarios y las llamadas a funciones funcionan todos de la misma manera. Para conocer el lenguaje completo, consulta la especificación de Starlark.
Starlark es intencionadamente limitado. Un script no puede leer archivos, hacer solicitudes de red ni importar paquetes: solo puede examinar el evento y llamar a las funciones que se enumeran en esta página. También se aplican un par de límites prácticos:
Un script puede ejecutarse durante un máximo de 10 segundos.
Un script puede ejecutar como máximo 10 000 pasos.
Si un script alcanza un límite o produce un error, se detiene y el error se escribe en el registro de la regla.
Una regla tiene exactamente un disparador: el evento que ejecuta su script. Esta sección describe cada disparador, para qué es útil, las variables que recibe el script y un breve ejemplo.
Cada variable es un objeto cuyos campos lees con un punto (por ejemplo submission.verdict); sigue el enlace de una variable para ver sus campos. Tres variables están siempre presentes, por lo que no se repiten a continuación: space (el space), event_name (una breve descripción del evento) y trigger_name (el disparador). Los objetos relacionados se incluyen cuando pueden buscarse. Las funciones utilizadas en los ejemplos se describen en Funciones.
Se dispara cuando un envío termina de evaluarse y recibe un veredicto. Úsalo para reaccionar a soluciones individuales: otorgar un logro por un primer envío aceptado, marcar a un miembro que resolvió un problema difícil o llevar la cuenta de los intentos.
Variables: submission
# Grant an achievement for an accepted submission, once per problem
if submission.verdict == "ACCEPTED":
eolymp_achievements_assign(
member_id = submission.member_id,
achievement_id = "<achievement-id>",
reference = submission.problem_id,
)
printf("achievement granted to %s", submission.member_id)Se dispara cuando un envío realizado dentro de un concurso termina de evaluarse. Como Envío completado, pero limitado a un concurso: incluye el concurso y el participante, y su envío es un envío de concurso. Úsalo para reaccionar específicamente a las soluciones de concurso.
Variables: submission, contest, participant, member
# Grant an achievement when a contest submission is accepted
if submission.verdict == "ACCEPTED":
eolymp_achievements_assign(
member_id = member.id,
achievement_id = "<achievement-id>",
reference = submission.problem_id,
)Se dispara después de que un concurso se finaliza. Como el concurso ya está congelado, usa este disparador para reaccionar al concurso terminado: otorgar logros de participación, iniciar un posprocesamiento o anunciar que los resultados están listos. Para cambiar el concurso o sus participantes, usa el disparador Acción de concurso antes de finalizar.
Variables: contest
# Grant a participation achievement to everyone in the contest
total, participants = eolymp_participants_list(contest_id = contest.id, size = 500)
for p in participants:
if not p.ghost:
eolymp_achievements_assign(
member_id = p.member_id,
achievement_id = "<participation-achievement-id>",
reference = contest.id, # once per contest
)Se dispara cuando la puntuación de un participante cambia durante un concurso. Úsalo para reaccionar a medida que un concurso se desarrolla: otorgar una insignia en el momento en que alguien resuelve todos los problemas o vigilar una puntuación objetivo.
Variables: score, contest, participant, member
# Award a badge when a participant solves every problem
if contest.problem_count > 0 and score.solved == contest.problem_count:
eolymp_achievements_assign(
member_id = member.id,
achievement_id = "<all-solved-achievement-id>",
reference = contest.id,
)Se dispara cuando alguien se registra como participante en un concurso. Úsalo para preparar a los nuevos inscritos: enviar una bienvenida, asignar un grupo inicial u otorgar tiempo extra a una cohorte concreta.
Variables: participant, contest, member
# Add every new entrant to a group
eolymp_members_add_group(
member_id = member.id,
group_id = "<contestants-group-id>",
)
printf("%s registered for %s", participant.display_name, contest.name)Se dispara después de que el resultado de un participante en un concurso se finaliza. Como el resultado ya está congelado, usa este disparador para reaccionar a la clasificación final: otorgar un logro por un buen puesto, registrar el resultado en algún lugar o notificar al participante. Cambiar al participante (asignar una medalla, marcarlo como oficial o no oficial, otorgar tiempo extra) no afectará a un resultado finalizado; hazlo antes de finalizar con el disparador Acción de concurso en su lugar.
Variables: participant, result, contest, member
# Grant an achievement for a top-three finish
if result.rank <= 3 and not result.unofficial:
eolymp_achievements_assign(
member_id = result.member_id,
achievement_id = "<achievement-id>",
)
printf("top-3 achievement granted to %s", result.name)Se dispara cuando un miembro se une a tu espacio o cuando un miembro existente se modifica después. member es el estado actual del miembro; previous es su estado antes del cambio. previous se incluye solo en las modificaciones: no se proporciona cuando un miembro acaba de unirse, que es como una regla distingue a un miembro nuevo de uno modificado. Úsalo para incorporar nuevos miembros o para reaccionar a cambios de perfil.
# Route new members into a group based on their grade attribute
if member.attributes.grade > 9:
eolymp_members_add_group(
member_id = member.id,
group_id = "<senior-group-id>",
)
else:
eolymp_members_add_group(
member_id = member.id,
group_id = "<junior-group-id>",
)Se dispara cuando se hace o se responde una pregunta en un concurso. Úsalo para ayudar con el soporte: marcar preguntas nuevas, notificar al personal o clasificarlas por tema. La variable reply está presente solo cuando el evento es una respuesta. (Los scripts pueden leer preguntas pero no pueden responderlas; para responder automáticamente, usa una acción de agente de IA).
Variables: ticket, reply, contest, member
# Log newly created questions
if ticket.reply_count == 0:
printf("new question from %s: %s", member.display_name, ticket.subject)Un disparador manual que ejecutas bajo demanda sobre un concurso específico, con el botón Disparar junto a la regla. Este es el lugar adecuado para ajustar los participantes de un concurso: marcar entradas como oficiales o no oficiales, otorgar tiempo extra o asignar una medalla a un participante, normalmente antes de finalizar el concurso. También es útil para tareas puntuales y para probar una regla antes de confiar en ella.
Variables: contest
# Make every unofficial entry official, before finalizing the contest
total, participants = eolymp_participants_list(contest_id = contest.id, size = 500)
for p in participants:
if p.unofficial:
eolymp_participants_set_official(
contest_id = contest.id,
participant_id = p.id,
official = True,
)Un disparador manual que ejecutas bajo demanda sobre un miembro específico. Úsalo para tareas puntuales de miembros y para pruebas.
Variables: member
# Grant an achievement to the selected member
eolymp_achievements_assign(
member_id = member.id,
achievement_id = "<achievement-id>",
)Llama a las funciones con argumentos con nombre, por ejemplo eolymp_members_add_group(member_id = "...", group_id = "..."). Los argumentos marcados como <optional> pueden omitirse. Las funciones que leen datos devuelven un valor; las funciones que cambian datos no devuelven nada.
eolymp_achievements_assign(member_id, achievement_id, qty=<optional>, inc_by=<optional>, reference=<optional>)
Otorga un logro a un miembro. De forma predeterminada, el recuento del miembro se establece en 1. Pasa qty para fijar el recuento en un número exacto, o inc_by para aumentarlo en una cantidad. reference es una clave opcional: las ejecuciones repetidas que usan la misma referencia se aplican solo una vez para esa clave, útil para evitar otorgar dos veces por lo mismo.
eolymp_members_get(id)
Obtiene un miembro por id. Devuelve un member.
eolymp_members_list(filters=<optional>, search=<optional>, size=<optional>, offset=<optional>, sort=<optional>, order=<optional>)
Lista los miembros del espacio. Devuelve el recuento total y una lista de objetos member; consulta Listing and filters.
Campos filtrables: id, external_ref, type, display_name, inactive, incomplete, unofficial, seated, team_id, group_id, user_issuer, user_subject, user_email, user_name, user_nickname, birthday, country, score, attribute
eolymp_members_set_attributes(member_id, attributes)
Fusiona atributos de perfil en un miembro. attributes es un diccionario de claves de atributo a texto o números; las claves que no incluyas quedan sin cambios.
eolymp_members_set_preferences(member_id, locale=<optional>, timezone=<optional>, runtime=<optional>)
Actualiza las preferencias de un miembro. Solo se cambian los campos que pases. runtime es el lenguaje predeterminado del miembro para las soluciones.
eolymp_members_add_group(member_id, group_id)
Añade un miembro a un grupo.
eolymp_members_remove_group(member_id, group_id)
Quita un miembro de un grupo.
eolymp_members_set_active(member_id, active)
Habilita (active = True) o deshabilita (active = False) a un miembro.
eolymp_participants_get(contest_id, participant_id)
Obtiene un participante de un concurso. Devuelve un participant.
eolymp_participants_list(contest_id, filters=<optional>, search=<optional>, size=<optional>, offset=<optional>, sort=<optional>, order=<optional>)
Lista los participantes de un concurso. Devuelve el recuento total y una lista de objetos participant. La ordenación se limita a display_name y started_at; no hay ordenación por puntuación ni por rango.
Campos filtrables: id, member_id, group_id, status, started_at, unofficial, disqualified, inactive, role, staff, has_violations
eolymp_participants_set_official(contest_id, participant_id, official)
Marca a un participante como oficial (official = True) o no oficial (official = False).
eolymp_participants_set_medal(contest_id, participant_id, medal)
Establece la medalla de un participante. medal es uno de "gold", "silver", "bronze", "honorable_mention" o "none".
eolymp_participants_set_extra_time(contest_id, participant_id, seconds)
Otorga tiempo extra (adicional) a un participante, en segundos.
eolymp_participants_set_active(contest_id, participant_id, active)
Habilita (active = True) o deshabilita (active = False) a un participante.
eolymp_participants_disqualify(contest_id, participant_id, requalify=<optional>, reason=<optional>)
Descalifica a un participante; pasa requalify = True para revertirlo. reason es un texto explicativo opcional.
Estas funciones cambian los participantes de un concurso y es mejor ejecutarlas desde una regla de Acción de concurso antes de que el concurso se finalice.
eolymp_contests_get(id)
Obtiene un concurso por id. Devuelve un contest.
eolymp_contests_list(filters=<optional>, search=<optional>, size=<optional>, offset=<optional>)
Lista los concursos del espacio. Devuelve el recuento total y una lista de objetos contest.
Campos filtrables: id, name, starts_at, ends_at, public, visibility, format, status, featured, year, scale, series, difficulty, country, region, city, member_id
eolymp_contests_get_submission(contest_id, id)
Obtiene un envío realizado dentro de un concurso. Devuelve un envío de concurso.
eolymp_contests_list_submissions(contest_id, filters=<optional>, after=<optional>, size=<optional>, offset=<optional>)
Lista los envíos de un concurso. Devuelve el recuento total y una lista de objetos envío de concurso.
Campos filtrables: id, participant_id, problem_id, status, runtime, score, percentage, submitted_at, signature, verdict
eolymp_problems_get(id)
Obtiene un problema por id. Devuelve un problem.
eolymp_problems_list(filters=<optional>, search=<optional>, size=<optional>, offset=<optional>, sort=<optional>, order=<optional>)
Lista los problemas del espacio. Devuelve el recuento total y una lista de objetos problem.
Campos filtrables: id, topic_id, is_visible, is_private, number, difficulty, status, score, is_bookmarked
eolymp_submissions_get(id)
Obtiene un envío por id. Devuelve un submission.
eolymp_submissions_list(filters=<optional>, after=<optional>, size=<optional>, offset=<optional>)
Lista los envíos del espacio. Devuelve el recuento total y una lista de objetos submission.
Campos filtrables: id, problem_id, user_id, member_id, submitted_at, runtime, status, verdict, score, percentage
eolymp_submissions_aggregate(group_by=<optional>, filters=<optional>, metric=<optional>, range_start=<optional>, range_end=<optional>)
Resume los envíos en grupos. group_by es una o más dimensiones por las que agrupar: "SUBMITTED_AT", "VERDICT", "STATUS" (pasa una lista para varias). metric es lo que se calcula por grupo; actualmente solo "COUNT" (el valor predeterminado). range_start y range_end son marcas de tiempo RFC 3339 que delimitan los envíos considerados; si se omiten, solo se cuentan los últimos 30 días. Devuelve una lista de grupos, cada uno un objeto con dimensions (los valores de agrupación de ese grupo) y count.
Campos filtrables: problem_id, member_id, user_id, verdict, runtime, status, score, percentage
eolymp_groups_get(id)
Obtiene un grupo por id. Devuelve un group.
eolymp_groups_list(filters=<optional>, size=<optional>, offset=<optional>)
Lista los grupos del espacio. Devuelve el recuento total y una lista de objetos group.
Campos filtrables: id, external_ref, name, query
eolymp_pages_get(id)
Obtiene una página de contenido por id. Devuelve una page.
Las marcas de tiempo en una carga útil son cadenas RFC 3339, y Starlark no tiene un tipo de reloj ni de duración: estas utilidades permiten que una regla razone sobre el tiempo (por ejemplo, "dentro de los cinco minutos posteriores a la fecha límite").
time_diff(a, b)
Devuelve a − b en segundos (un número entero), negativo cuando a es anterior a b. Ambos argumentos son cadenas de marca de tiempo RFC 3339.
time_shift(timestamp, seconds)
Desplaza timestamp el número de segundos indicado (negativo para retroceder) y devuelve el resultado como una cadena RFC 3339.
El registro te permite rastrear lo que hizo un script; la salida aparece en los registros de la regla.
printf(format, *args)
Formatea un mensaje y lo añade al registro. Usa %s para texto, %d para números enteros y %v para cualquier valor.
print(*args)
Añade un mensaje simple al registro.
Cada función ..._list devuelve dos valores: el número total de elementos coincidentes y una lista de los elementos de la página actual. Desempáquetalos juntos:
total, members = eolymp_members_list(size = 5)
printf("space has %d members", total)
for m in members:
printf("- %s", m.display_name)size y offset controlan la paginación. search, sort y order ("asc" o "desc") están disponibles donde se admiten.
Los filtros se pasan como un diccionario indexado por nombre de campo. Cada campo se asigna a un operador y un valor; un valor por sí solo es la abreviatura de igualdad. Los nombres de campo a continuación son ilustrativos; los campos filtrables propios de cada lista se indican junto a su función más arriba.
{"verdict": "ACCEPTED"} # equals
{"level": {"gte": 5}} # greater than or equal
{"display_name": {"contains": "team"}} # substring match
{"created_at": {"gt": "2026-01-01T00:00:00Z"}} # after a date (RFC 3339)Operadores disponibles:
Operador | Significado |
|---|---|
| igual (también el valor predeterminado) |
| distinto |
| mayor que, mayor o igual |
| menor que, menor o igual |
| contiene subcadena |
| empieza por |
Los valores pueden ser texto, números enteros, True/False o una cadena de marca de tiempo RFC 3339 como "2026-01-01T00:00:00Z".
Cuando una regla se ejecuta como ejecución de prueba, las funciones de solo lectura (..._get, ..._list) funcionan como de costumbre, pero la primera función que cambiaría datos se registra en el log sin realizarse, y el script se detiene entonces. Usa una ejecución de prueba para comprobar lo que un script haría antes de dejar que actúe de verdad.
Los campos de cada objeto devuelto por una función o pasado como variable de disparador. Lee un campo con un punto, p. ej. submission.verdict.
Campo | Tipo |
|---|---|
| texto |
| texto |
| texto |
| texto |
| texto (idioma corto, p. ej. |
| texto (id de runtime completo) |
| texto |
| texto |
| número |
| número |
| número |
| marca de tiempo |
| marca de tiempo |
Un envío realizado dentro de un concurso, devuelto por eolymp_contests_get_submission y eolymp_contests_list_submissions. Su problem_id es el problema del concurso (no el problema del archivo), y también incluye el concurso y el participante.
Campo | Tipo |
|---|---|
| texto |
| texto |
| texto |
| texto |
| texto (idioma corto, p. ej. |
| texto (id de runtime completo) |
| texto |
| texto |
| número |
| número |
| número |
| booleano |
| marca de tiempo |
Campo | Tipo |
|---|---|
| texto |
| texto |
| texto |
| texto |
| número |
| número |
| booleano |
| objeto (clave de atributo → texto o número) |
| texto |
| texto |
| texto |
| booleano |
| texto |
| texto |
| texto |
Campo | Tipo |
|---|---|
| texto |
| texto |
| texto |
| texto |
| texto |
| texto |
| texto |
| texto |
| texto |
| texto |
| texto |
| número (segundos) |
| marca de tiempo |
| marca de tiempo |
| número |
| número |
| booleano |
| booleano |
Campo | Tipo |
|---|---|
| texto |
| texto |
| texto |
| texto |
| texto |
| booleano |
| booleano |
| booleano |
| booleano |
| booleano |
| marca de tiempo |
| marca de tiempo |
Campo | Tipo |
|---|---|
| texto |
| texto |
| texto |
| texto |
| booleano |
| booleano |
| booleano |
| texto |
| número |
| número |
| número |
| número |
| número |
Campo | Tipo |
|---|---|
| número |
| número |
| número |
| booleano |
| lista de objetos (ver abajo) |
Cada elemento de breakdown tiene:
Campo | Tipo |
|---|---|
| texto |
| booleano |
| número |
| número |
| número |
Campo | Tipo |
|---|---|
| texto |
| texto |
| texto |
| texto |
| texto |
| texto |
| texto |
| número |
| marca de tiempo |
| marca de tiempo |
| marca de tiempo |
Campo | Tipo |
|---|---|
| texto |
| texto |
| texto ( |
| texto |
| texto |
| texto |
| marca de tiempo |
Campo | Tipo |
|---|---|
| texto |
| texto |
| texto |
| número |
| texto |
| texto |
| lista de textos |
| lista de textos |
| número |
| número |
| número |
| número |
| número |
| texto |
| texto |
| texto |
| booleano |
Campo | Tipo |
|---|---|
| texto |
| texto |
| texto |
| texto |
| texto |
| texto |
| texto |
Campo | Tipo |
|---|---|
| texto |
| texto |
| texto |
| texto |
| texto |
Campo | Tipo |
|---|---|
| texto |
| texto |
| texto |
| texto |
| booleano |
| lista de textos |