Scripts de automatización

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.

El lenguaje

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.

Disparadores

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.

Envío completado

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)

Envío de concurso completado

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,
    )

Concurso finalizado

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
        )

Puntuación del concurso modificada

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,
    )

Participante registrado

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)

Participante finalizado

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)

Miembro modificado

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.

Variables: member, previous

# 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>",
    )

Pregunta creada o respondida

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)

Acción de concurso

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,
        )

Acción de miembro

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>",
)

Functions

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.

Logros

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.

Miembros

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.

Participantes

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.

Concursos

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

Problemas

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

Envíos

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

Grupos

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

Páginas

eolymp_pages_get(id)

Obtiene una página de contenido por id. Devuelve una page.

Tiempo

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.

Registro

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.

Listing and filters

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

eq

igual (también el valor predeterminado)

ne / neq

distinto

gt, ge / gte

mayor que, mayor o igual

lt, le / lte

menor que, menor o igual

contains

contiene subcadena

starts / prefix

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".

Ejecución de prueba

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.

Objetos

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.

submission

Campo

Tipo

id

texto

problem_id

texto

user_id

texto

member_id

texto

lang

texto (idioma corto, p. ej. cpp)

runtime

texto (id de runtime completo)

status

texto

verdict

texto

score

número

cost

número

percentage

número

submitted_at

marca de tiempo

judged_at

marca de tiempo

contest submission

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

id

texto

contest_id

texto

problem_id

texto

participant_id

texto

lang

texto (idioma corto, p. ej. cpp)

runtime

texto (id de runtime completo)

status

texto

verdict

texto

score

número

cost

número

percentage

número

deleted

booleano

submitted_at

marca de tiempo

member

Campo

Tipo

id

texto

external_ref

texto

display_name

texto

rank

texto

rating

número

level

número

inactive

booleano

attributes

objeto (clave de atributo → texto o número)

user_name

texto

user_nickname

texto

user_email

texto

user_email_verified

booleano

user_picture

texto

user_city

texto

user_country

texto

contest

Campo

Tipo

id

texto

key

texto

slug

texto

name

texto

url

texto

image_url

texto

format

texto

series

texto

status

texto

visibility

texto

participation_mode

texto

duration

número (segundos)

starts_at

marca de tiempo

ends_at

marca de tiempo

problem_count

número

participant_count

número

allow_upsolve

booleano

require_admission

booleano

participant

Campo

Tipo

id

texto

member_id

texto

display_name

texto

role

texto

status

texto

unofficial

booleano

ghost

booleano

inactive

booleano

disqualified

booleano

finalized

booleano

started_at

marca de tiempo

end_at

marca de tiempo

result

Campo

Tipo

participant_id

texto

member_id

texto

contest_id

texto

name

texto

unofficial

booleano

disqualified

booleano

ghost

booleano

medal

texto

rank

número

rank_lower

número

score

número

penalty

número

solved

número

score

Campo

Tipo

score

número

penalty

número

solved

número

upsolve

booleano

breakdown

lista de objetos (ver abajo)

Cada elemento de breakdown tiene:

Campo

Tipo

problem_id

texto

solved

booleano

score

número

percentage

número

attempts

número

ticket

Campo

Tipo

id

texto

contest_id

texto

member_id

texto

participant_id

texto

subject

texto

message

texto

status

texto

reply_count

número

created_at

marca de tiempo

updated_at

marca de tiempo

last_reply_at

marca de tiempo

reply

Campo

Tipo

id

texto

ticket_id

texto

author

texto (participant o jury)

member_id

texto

user_id

texto

message

texto

created_at

marca de tiempo

problem

Campo

Tipo

id

texto

url

texto

type

texto

number

número

title

texto

language

texto

languages

lista de textos

topics

lista de textos

difficulty

número

score

número

acceptance_rate

número

submissions_count

número

submissions_accepted

número

author

texto

source

texto

origin

texto

visible

booleano

group

Campo

Tipo

id

texto

name

texto

description

texto

external_ref

texto

icon

texto

badge

texto

color

texto

space

Campo

Tipo

id

texto

key

texto

name

texto

url

texto

status

texto

page

Campo

Tipo

id

texto

path

texto

locale

texto

title

texto

draft

booleano

labels

lista de textos