Скрипт — це один із двох видів дії автоматизації. Коли правило спрацьовує, його скрипт виконується один раз, з інформацією про подію, що його запустила. Скрипти найкраще підходять для фіксованих, передбачуваних кроків — надати досягнення, перемістити учасника до групи, встановити медаль — які мають щоразу виконуватися однаково.
Скрипти пишуться мовою 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 додається лише для оновлень — його немає, коли учасник щойно приєднався, і саме так правило відрізняє нового учасника від зміненого. Використовуйте його, щоб онбордити нових учасників або реагувати на зміни профілю.
# 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>",
)Викликайте функції з іменованими аргументами, наприклад 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)
Додає просте повідомлення до журналу.
Кожна функція ..._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)Доступні оператори:
Оператор | Значення |
|---|---|
| дорівнює (також за замовчуванням) |
| не дорівнює |
| більше, більше або дорівнює |
| менше, менше або дорівнює |
| містить підрядок |
| починається з |
Значення можуть бути текстом, цілими числами, True/False або рядком часової позначки RFC 3339, як-от "2026-01-01T00:00:00Z".
Коли правило виконується як пробний запуск, функції лише для читання (..._get, ..._list) працюють як зазвичай, але перша функція, що змінила б дані, записується до журналу без виконання, і скрипт після цього зупиняється. Використовуйте пробний запуск, щоб перевірити, що скрипт зробив би, перш ніж дозволити йому діяти по-справжньому.
Поля кожного об'єкта, що повертається функцією або передається як змінна тригера. Читайте поле через крапку, напр. submission.verdict.
Поле | Тип |
|---|---|
| текст |
| текст |
| текст |
| текст |
| текст (коротка мова, напр. |
| текст (повний id runtime) |
| текст |
| текст |
| число |
| число |
| число |
| часова позначка |
| часова позначка |
Відправка, зроблена в межах змагання, яку повертають eolymp_contests_get_submission та eolymp_contests_list_submissions. Її problem_id — це задача змагання (а не задача архіву), і вона також несе змагання та учасника.
Поле | Тип |
|---|---|
| текст |
| текст |
| текст |
| текст |
| текст (коротка мова, напр. |
| текст (повний id runtime) |
| текст |
| текст |
| число |
| число |
| число |
| булеве |
| часова позначка |
Поле | Тип |
|---|---|
| текст |
| текст |
| текст |
| текст |
| число |
| число |
| булеве |
| об'єкт (ключ атрибута → текст або число) |
| текст |
| текст |
| текст |
| булеве |
| текст |
| текст |
| текст |
Поле | Тип |
|---|---|
| текст |
| текст |
| текст |
| текст |
| текст |
| текст |
| текст |
| текст |
| текст |
| текст |
| текст |
| число (секунди) |
| часова позначка |
| часова позначка |
| число |
| число |
| булеве |
| булеве |
Поле | Тип |
|---|---|
| текст |
| текст |
| текст |
| текст |
| текст |
| булеве |
| булеве |
| булеве |
| булеве |
| булеве |
| часова позначка |
| часова позначка |
Поле | Тип |
|---|---|
| текст |
| текст |
| текст |
| текст |
| булеве |
| булеве |
| булеве |
| текст |
| число |
| число |
| число |
| число |
| число |
Поле | Тип |
|---|---|
| число |
| число |
| число |
| булеве |
| список об'єктів (див. нижче) |
У кожному елементі breakdown:
Поле | Тип |
|---|---|
| текст |
| булеве |
| число |
| число |
| число |
Поле | Тип |
|---|---|
| текст |
| текст |
| текст |
| текст |
| текст |
| текст |
| текст |
| число |
| часова позначка |
| часова позначка |
| часова позначка |
Поле | Тип |
|---|---|
| текст |
| текст |
| текст ( |
| текст |
| текст |
| текст |
| часова позначка |
Поле | Тип |
|---|---|
| текст |
| текст |
| текст |
| число |
| текст |
| текст |
| список текстів |
| список текстів |
| число |
| число |
| число |
| число |
| число |
| текст |
| текст |
| текст |
| булеве |
Поле | Тип |
|---|---|
| текст |
| текст |
| текст |
| текст |
| текст |
| текст |
| текст |
Поле | Тип |
|---|---|
| текст |
| текст |
| текст |
| текст |
| текст |
Поле | Тип |
|---|---|
| текст |
| текст |
| текст |
| текст |
| булеве |
| список текстів |