Скрипти автоматизації

Скрипт — це один із двох видів дії автоматизації. Коли правило спрацьовує, його скрипт виконується один раз, з інформацією про подію, що його запустила. Скрипти найкраще підходять для фіксованих, передбачуваних кроків — надати досягнення, перемістити учасника до групи, встановити медаль — які мають щоразу виконуватися однаково.

Мова

Скрипти пишуться мовою Starlark, невеликим детермінованим діалектом Python. Якщо ви трохи знаєте Python, він виглядатиме знайомо: змінні, if/elif/else, цикли for, списки, словники та виклики функцій — усе працює однаково. Повний опис мови див. у специфікації Starlark.

Starlark навмисно обмежений. Скрипт не може читати файли, робити мережеві запити чи імпортувати пакети — він може лише переглядати подію й викликати функції, перелічені на цій сторінці. Також діють кілька практичних обмежень:

  • Скрипт може виконуватися щонайбільше 10 секунд.

  • Скрипт може виконати щонайбільше 10 000 кроків.

Якщо скрипт досягає обмеження або спричиняє помилку, він зупиняється, а помилка записується до журналу правила.

Тригери

Правило має рівно один тригер — подію, що запускає його скрипт. Цей розділ описує кожен тригер, для чого він корисний, змінні, які отримує скрипт, і короткий приклад.

Кожна змінна — це об'єкт, поля якого ви читаєте через крапку (наприклад submission.verdict); перейдіть за посиланням на змінній, щоб побачити її поля. Три змінні присутні завжди, тому нижче не повторюються: space (space), event_name (короткий опис події) та trigger_name (тригер). Пов'язані об'єкти включаються, коли їх можна знайти. Функції, використані в прикладах, описано в розділі Functions.

Відправку протестовано

Спрацьовує, коли відправка проходить перевірку й отримує вердикт. Використовуйте його, щоб реагувати на окремі розв'язки — надати досягнення за першу прийняту відправку, позначити учасника, який здолав складну задачу, або вести підрахунок спроб.

Змінні: 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)

Відправку у змаганні протестовано

Спрацьовує, коли відправка, зроблена в межах змагання, проходить перевірку. Подібно до тригера Відправку протестовано, але прив'язаний до змагання — він несе змагання та учасника, а його відправка є відправкою у змаганні. Використовуйте його, щоб реагувати саме на розв'язки в змаганні.

Змінні: 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,
    )

Змагання завершено

Спрацьовує після завершення змагання. Оскільки змагання вже заморожене, використовуйте цей тригер, щоб реагувати на завершене змагання — надати досягнення за участь, запустити подальшу обробку або оголосити, що результати готові. Щоб змінити змагання або його учасників, використовуйте тригер Дія над змаганням до завершення.

Змінні: 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
        )

Бали в змаганні змінилися

Спрацьовує, коли бали учасника змінюються під час змагання. Використовуйте його, щоб реагувати в міру перебігу змагання — вручити значок у момент, коли хтось розв'язує всі задачі, або стежити за цільовими балами.

Змінні: 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,
    )

Учасника змагання зареєстровано

Спрацьовує, коли хтось реєструється як учасник змагання. Використовуйте його, щоб налаштувати нових учасників — надіслати привітання, призначити початкову групу або надати додатковий час певній когорті.

Змінні: 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)

Учасника змагання фіналізовано

Спрацьовує після фіналізації результату учасника в змаганні. Оскільки результат уже заморожений, використовуйте цей тригер, щоб реагувати на підсумкове місце — надати досягнення за високий результат, десь записати результат або сповістити учасника. Зміна учасника (призначення медалі, позначення офіційним чи неофіційним, надання додаткового часу) не вплине на фіналізований результат — робіть це до фіналізації через тригер Дія над змаганням.

Змінні: 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)

Учасника змінено

Спрацьовує, коли учасник приєднується до вашого простору або наявного учасника згодом змінено. member — поточний стан учасника; previous — його стан до зміни. previous додається лише для оновлень — його немає, коли учасник щойно приєднався, і саме так правило відрізняє нового учасника від зміненого. Використовуйте його, щоб онбордити нових учасників або реагувати на зміни профілю.

Змінні: 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>",
    )

Запитання створено або надано відповідь

Спрацьовує, коли в змаганні ставлять запитання або надають на нього відповідь. Використовуйте його, щоб допомагати з підтримкою — позначати нові запитання, сповіщати персонал або сортувати за темою. Змінна reply присутня лише тоді, коли подія є відповіддю. (Скрипти можуть читати запитання, але не можуть відповідати на них; щоб відповідати автоматично, використовуйте дію ШІ-агента.)

Змінні: ticket, reply, contest, member

# Log newly created questions
if ticket.reply_count == 0:
    printf("new question from %s: %s", member.display_name, ticket.subject)

Дія над змаганням

Ручний тригер, який ви запускаєте за потреби над конкретним змаганням, кнопкою Запустити поруч із правилом. Це правильне місце, щоб скоригувати учасників змагання — позначити записи офіційними чи неофіційними, надати додатковий час або встановити медаль учаснику — зазвичай перед фіналізацією змагання. Він також зручний для разових завдань і для перевірки правила, перш ніж на нього покладатися.

Змінні: 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,
        )

Дія над учасником

Ручний тригер, який ви запускаєте за потреби над конкретним учасником. Використовуйте його для разових завдань з учасниками й для тестування.

Змінні: member

# Grant an achievement to the selected member
eolymp_achievements_assign(
    member_id = member.id,
    achievement_id = "<achievement-id>",
)

Functions

Викликайте функції з іменованими аргументами, наприклад eolymp_members_add_group(member_id = "...", group_id = "..."). Аргументи, позначені <optional>, можна не вказувати. Функції, що читають дані, повертають значення; функції, що змінюють дані, не повертають нічого.

Досягнення

eolymp_achievements_assign(member_id, achievement_id, qty=<optional>, inc_by=<optional>, reference=<optional>)

Надає учаснику досягнення. За замовчуванням лічильник учасника встановлюється на 1. Передайте qty, щоб встановити лічильник на точне число, або inc_by, щоб збільшити його на певну величину. reference — необов'язковий ключ: повторні запуски, що використовують той самий reference, застосовуються лише один раз для цього ключа — зручно, щоб не надати двічі за те саме.

Учасники

eolymp_members_get(id)

Отримує учасника за id. Повертає member.

eolymp_members_list(filters=<optional>, search=<optional>, size=<optional>, offset=<optional>, sort=<optional>, order=<optional>)

Перелічує учасників простору. Повертає загальну кількість і список об'єктів member — див. Listing and filters.

Поля для фільтрації: 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)

Об'єднує атрибути профілю в учасника. attributes — це словник ключів атрибутів до тексту чи чисел; ключі, які ви не вказуєте, залишаються без змін.

eolymp_members_set_preferences(member_id, locale=<optional>, timezone=<optional>, runtime=<optional>)

Оновлює налаштування учасника. Змінюються лише передані вами поля. runtime — типова мова учасника для розв'язків.

eolymp_members_add_group(member_id, group_id)

Додає учасника до групи.

eolymp_members_remove_group(member_id, group_id)

Вилучає учасника з групи.

eolymp_members_set_active(member_id, active)

Вмикає (active = True) або вимикає (active = False) учасника.

Учасники змагання

eolymp_participants_get(contest_id, participant_id)

Отримує учасника змагання. Повертає participant.

eolymp_participants_list(contest_id, filters=<optional>, search=<optional>, size=<optional>, offset=<optional>, sort=<optional>, order=<optional>)

Перелічує учасників змагання. Повертає загальну кількість і список об'єктів participant. Сортування обмежене display_name та started_at; сортування за балами чи місцем немає.

Поля для фільтрації: id, member_id, group_id, status, started_at, unofficial, disqualified, inactive, role, staff, has_violations

eolymp_participants_set_official(contest_id, participant_id, official)

Позначає учасника змагання офіційним (official = True) або неофіційним (official = False).

eolymp_participants_set_medal(contest_id, participant_id, medal)

Встановлює медаль учасника змагання. medal — одне з "gold", "silver", "bronze", "honorable_mention" або "none".

eolymp_participants_set_extra_time(contest_id, participant_id, seconds)

Надає учаснику змагання додатковий (бонусний) час, у секундах.

eolymp_participants_set_active(contest_id, participant_id, active)

Вмикає (active = True) або вимикає (active = False) учасника змагання.

eolymp_participants_disqualify(contest_id, participant_id, requalify=<optional>, reason=<optional>)

Дискваліфікує учасника змагання; передайте requalify = True, щоб скасувати це. reason — необов'язковий пояснювальний текст.

Ці функції змінюють учасників змагання, і їх найкраще запускати з правила Дія над змаганням до фіналізації змагання.

Змагання

eolymp_contests_get(id)

Отримує змагання за id. Повертає contest.

eolymp_contests_list(filters=<optional>, search=<optional>, size=<optional>, offset=<optional>)

Перелічує змагання простору. Повертає загальну кількість і список об'єктів contest.

Поля для фільтрації: 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)

Отримує відправку, зроблену в межах змагання. Повертає відправку змагання.

eolymp_contests_list_submissions(contest_id, filters=<optional>, after=<optional>, size=<optional>, offset=<optional>)

Перелічує відправки змагання. Повертає загальну кількість і список об'єктів відправка змагання.

Поля для фільтрації: id, participant_id, problem_id, status, runtime, score, percentage, submitted_at, signature, verdict

Задачі

eolymp_problems_get(id)

Отримує задачу за id. Повертає problem.

eolymp_problems_list(filters=<optional>, search=<optional>, size=<optional>, offset=<optional>, sort=<optional>, order=<optional>)

Перелічує задачі простору. Повертає загальну кількість і список об'єктів problem.

Поля для фільтрації: id, topic_id, is_visible, is_private, number, difficulty, status, score, is_bookmarked

Відправки

eolymp_submissions_get(id)

Отримує відправку за id. Повертає submission.

eolymp_submissions_list(filters=<optional>, after=<optional>, size=<optional>, offset=<optional>)

Перелічує відправки простору. Повертає загальну кількість і список об'єктів submission.

Поля для фільтрації: 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>)

Зводить відправки у групи. group_by — один або кілька вимірів для групування — "SUBMITTED_AT", "VERDICT", "STATUS" (передайте список для кількох). metric — те, що обчислюється для кожної групи; наразі лише "COUNT" (за замовчуванням). range_start та range_end — часові позначки RFC 3339, що обмежують враховувані відправки; якщо їх опущено, рахуються лише останні 30 днів. Повертає список груп, кожна з яких — об'єкт із dimensions (значення групування для цієї групи) та count.

Поля для фільтрації: problem_id, member_id, user_id, verdict, runtime, status, score, percentage

Групи

eolymp_groups_get(id)

Отримує групу за id. Повертає group.

eolymp_groups_list(filters=<optional>, size=<optional>, offset=<optional>)

Перелічує групи простору. Повертає загальну кількість і список об'єктів group.

Поля для фільтрації: id, external_ref, name, query

Сторінки

eolymp_pages_get(id)

Отримує сторінку контенту за id. Повертає page.

Час

Часові позначки в корисному навантаженні — це рядки RFC 3339, а Starlark не має типу годинника чи тривалості — ці помічники дають правилу змогу міркувати про час (наприклад, "протягом п'яти хвилин до дедлайну").

time_diff(a, b)

Повертає a − b у секундах (ціле число), від'ємне, коли a раніше за b. Обидва аргументи — рядки часових позначок RFC 3339.

time_shift(timestamp, seconds)

Зсуває timestamp на задану кількість секунд (від'ємну, щоб піти назад) і повертає результат як рядок RFC 3339.

Журналювання

Журналювання дає змогу відстежувати, що зробив скрипт; вивід з'являється в журналах правила.

printf(format, *args)

Форматує повідомлення й додає його до журналу. Використовуйте %s для тексту, %d для цілих чисел і %v для будь-якого значення.

print(*args)

Додає просте повідомлення до журналу.

Listing and filters

Кожна функція ..._list повертає два значення: загальну кількість відповідних елементів і список елементів на поточній сторінці. Розпакуйте їх разом:

total, members = eolymp_members_list(size = 5)
printf("space has %d members", total)
for m in members:
    printf("- %s", m.display_name)

size та offset керують посторінковим виведенням. search, sort та order ("asc" або "desc") доступні там, де підтримуються.

Фільтри передаються як словник із ключами за назвою поля. Кожне поле зіставляється з оператором і значенням; окреме значення — це скорочення для рівності. Наведені нижче назви полів є ілюстративними; власні поля для фільтрації кожного списку зазначено разом з його функцією вище.

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

Доступні оператори:

Оператор

Значення

eq

дорівнює (також за замовчуванням)

ne / neq

не дорівнює

gt, ge / gte

більше, більше або дорівнює

lt, le / lte

менше, менше або дорівнює

contains

містить підрядок

starts / prefix

починається з

Значення можуть бути текстом, цілими числами, True/False або рядком часової позначки RFC 3339, як-от "2026-01-01T00:00:00Z".

Пробний запуск

Коли правило виконується як пробний запуск, функції лише для читання (..._get, ..._list) працюють як зазвичай, але перша функція, що змінила б дані, записується до журналу без виконання, і скрипт після цього зупиняється. Використовуйте пробний запуск, щоб перевірити, що скрипт зробив би, перш ніж дозволити йому діяти по-справжньому.

Об'єкти

Поля кожного об'єкта, що повертається функцією або передається як змінна тригера. Читайте поле через крапку, напр. submission.verdict.

submission

Поле

Тип

id

текст

problem_id

текст

user_id

текст

member_id

текст

lang

текст (коротка мова, напр. cpp)

runtime

текст (повний id runtime)

status

текст

verdict

текст

score

число

cost

число

percentage

число

submitted_at

часова позначка

judged_at

часова позначка

contest submission

Відправка, зроблена в межах змагання, яку повертають eolymp_contests_get_submission та eolymp_contests_list_submissions. Її problem_id — це задача змагання (а не задача архіву), і вона також несе змагання та учасника.

Поле

Тип

id

текст

contest_id

текст

problem_id

текст

participant_id

текст

lang

текст (коротка мова, напр. cpp)

runtime

текст (повний id runtime)

status

текст

verdict

текст

score

число

cost

число

percentage

число

deleted

булеве

submitted_at

часова позначка

member

Поле

Тип

id

текст

external_ref

текст

display_name

текст

rank

текст

rating

число

level

число

inactive

булеве

attributes

об'єкт (ключ атрибута → текст або число)

user_name

текст

user_nickname

текст

user_email

текст

user_email_verified

булеве

user_picture

текст

user_city

текст

user_country

текст

contest

Поле

Тип

id

текст

key

текст

slug

текст

name

текст

url

текст

image_url

текст

format

текст

series

текст

status

текст

visibility

текст

participation_mode

текст

duration

число (секунди)

starts_at

часова позначка

ends_at

часова позначка

problem_count

число

participant_count

число

allow_upsolve

булеве

require_admission

булеве

participant

Поле

Тип

id

текст

member_id

текст

display_name

текст

role

текст

status

текст

unofficial

булеве

ghost

булеве

inactive

булеве

disqualified

булеве

finalized

булеве

started_at

часова позначка

end_at

часова позначка

result

Поле

Тип

participant_id

текст

member_id

текст

contest_id

текст

name

текст

unofficial

булеве

disqualified

булеве

ghost

булеве

medal

текст

rank

число

rank_lower

число

score

число

penalty

число

solved

число

score

Поле

Тип

score

число

penalty

число

solved

число

upsolve

булеве

breakdown

список об'єктів (див. нижче)

У кожному елементі breakdown:

Поле

Тип

problem_id

текст

solved

булеве

score

число

percentage

число

attempts

число

ticket

Поле

Тип

id

текст

contest_id

текст

member_id

текст

participant_id

текст

subject

текст

message

текст

status

текст

reply_count

число

created_at

часова позначка

updated_at

часова позначка

last_reply_at

часова позначка

reply

Поле

Тип

id

текст

ticket_id

текст

author

текст (participant або jury)

member_id

текст

user_id

текст

message

текст

created_at

часова позначка

problem

Поле

Тип

id

текст

url

текст

type

текст

number

число

title

текст

language

текст

languages

список текстів

topics

список текстів

difficulty

число

score

число

acceptance_rate

число

submissions_count

число

submissions_accepted

число

author

текст

source

текст

origin

текст

visible

булеве

group

Поле

Тип

id

текст

name

текст

description

текст

external_ref

текст

icon

текст

badge

текст

color

текст

space

Поле

Тип

id

текст

key

текст

name

текст

url

текст

status

текст

page

Поле

Тип

id

текст

path

текст

locale

текст

title

текст

draft

булеве

labels

список текстів