Выражение фильтра посылок позволяет задать условия, которым должны удовлетворять параметры посылок, чтобы быть показанными в списке посылок, генерируемом CGI-программами new-master и new-judge. Выражение фильтра должно иметь тип bool, а в противном случае генерируется ошибка.
При генерации страницы привилегированного пользователя в CGI-программах new-judge или new-master выражение фильтра используется следующим образом. Выражение фильтра применяется ко всем записям в базе посылок, и если на некоторой записи результат вычисления выражения равен true, то данная запись помечается как удовлетворяющая фильтру. Если при вычислении выражения фильтра хотя бы для одной посылки возникла ошибка, отображается информация об ошибке, а не результаты фильтрации. Если при вычислении выражения фильтра для всех записей завершилось успешно, из записей, удовлетворяющих выражению фильтра, отображаются записи в соответствии с заданным номером первой и номером последней записей.
Выражение фильтра посылок имеет Си-подобный синтаксис. Пробельные символы, разделяющие элементы выражения, игнорируются. В именах типов и полей регистр символов является значимым.
Выражение фильтра посылок строго типизировано. Выражение может состоять из операций над значениями следующих типов:
OK | OK |
CE | Compilation error |
RT | Run-time error |
PE | Presentation error |
WA | Wrong answer |
CF | Check failed (internal error) |
PT | Partial solution |
AC | Accepted |
IG | Ignored |
DQ | Disqualified |
PD | Pending |
ML | Memory-limit error |
SE | Security violation |
SV | Style violation |
WT | Wall time limit exceeded |
PR | Pending review |
RJ | Rejected |
RU | Running (in testing queue or being tested) |
CD | Compiled (but not yet running) |
CG | Compiling (in compile queue or being compiled) |
AV | Available for testing |
EM | Empty record |
VS | Virtual start |
VT | Virtual stop |
Выражение фильтра посылок строго типизировано, но для преобразований значений одного типа в значения другого типа могут использоваться операции преобразования типа. Операция преобразования типа записывается в стиле Си++, то есть следующим образом:
type-cast-op = type-name "(" expr ")"Здесь type-name — имя типа, одно из перечисленных выше bool, int, string, date_t, dur_t, size_t, result_t, hash_t, ip_t. Не все возможные преобразования типов допустимы. Возможные комбинации исходного типа и целевого типа показаны в таблице ниже. В строках таблицы записан исходный тип, а в столбцах таблицы — целевой тип.
bool | int | string | date_t | dur_t | size_t | result_t | hash_t | ip_t | |
---|---|---|---|---|---|---|---|---|---|
bool | + | + | + | ||||||
int | + | + | + | + | + | + | + | + | |
string | + | + | + | + | + | + | + | + | + |
date_t | + | + | + | + | |||||
dur_t | + | + | + | + | |||||
size_t | + | + | + | + | |||||
result_t | + | + | + | + | |||||
hash_t | + | + | + | + | |||||
ip_t | + | + | + | + |
Рассмотрим подробнее каждое нетривиальное преобразование типов.
YYYY/MM/DD hh:mm:ssЗдесь YYYY — год, MM — месяц (от 01 до 12), DD — день месяца (от 01 до 31), hh — час (от 00 до 23), mm — минута (от 00 до 59), ss — секунда (от 00 до 59).
#h:mm:ssЗдесь # — знак продолжительности (для положительной продолжительности знак не выводится, а для отрицательной печатается знак -), h — число полных часов, mm — число минут в последнем неполном часе (от 00 до 59), ss — число секунд в последней неполной минуте (от 00 до 59).
Y / M / D [ h [ : m [ : s ] ] ]Здесь запись [ X ], означает, что элемент X может отсутствовать, символы / и : представляют сами себя, а Y, M, D, h, m, s — это целые десятичные числа. Они могут отделяться от / и : произвольным количеством пробельных символов. Y — это год, который должен находиться в интервале от 1900 до 2100, M — порядковый номер месяца (от 1 до 12), D — порядковый номер дня в месяце (от 1 до 31), h — час суток (от 0 до 23), m — минута (от 0 до 59), s — секунда (от 0 до 59). Если часы, минуты или секунды опущены, они полагаются равными 0. Кроме того, дата должна находится в диапазоне представимых в POSIX дат (то есть примерно от 1906 до 2038 года). Если все условия выполняются, строковая запись астрономического времени конвертируется во внутреннее представление, а в противном случае генерируется ошибка.
[ # ] h [ : m [ : s ] ]Здесь запись [ X ], означает, что элемент X может отсутствовать. # — это знак + или -. h, m и s — положительные целые числа. h — количество часов, m — количество минут (от 0 до 59), s — количество секунд (от 0 до 59). Если минуты или секунды опущены, их число полагается равным 0. После перевода в секунды длительность должна находится в диапазоне целых чисел, представимых 32-битными знаковыми числами. Если все условия выполняются, то строковая запись длительностного значения конвертируется во внутреннее представление, а в противном случае генерируется ошибка.
A.B.C.DЗдесь . — это символ «точка», а A, B, C и D — целые беззнаковые числа от 0 до 255. Если эти условия выполняются строка конвертируется в соответствующее значение типа ip_t, а в противном случае генерируется ошибка.
Текущей посылкой назовём обрабатываемую при вычислении выражения фильтра посылку. На основании результата вычисления выражения фильтра определяется, может ли быть отображена текущая посылка.
Примитивы доступа к базе посылок позволяют получать значения полей как текущей посылки, так и любой другой посылки с заданным номером. Примитивы имеют следующий общий вид:
f [ ( expr ) ]Здесь в квадратных скобках [ и ] записана необязательная часть. Круглые скобки ( и ) обозначают сами себя. \V{f} — это имя примитива, а expr — это выражение целого типа. Если выражение в скобках не задано, то берётся значение поля, соответствующего имени примитива f, текущей посылки. Если выражение в скобках не является выражением целого типа, генерируется ошибка. В противном случае выражение вычисляется, и пусть при вычислении выражения ошибок не возникло, а n — результат вычисления выражения.
Если n < 0, то n задаёт номер посылки начиная от последней, то есть n' = N + n$, где N — общее количество посылок в базе посылок в данный момент. В противном случае предполагаем, что n задаёт номер посылки начиная от нулевой, то есть n' = n. Если теперь n' < 0 или n' ≥ N, то генерируется ошибка вычисления выражения фильтра. Если же n' удовлетворяет ограничениям, берётся значение поля, соответствующего имени примитива f, в посылке с номером n'.
Примитивы доступа к базе посылок перечислены в таблице.
Имя примитива | Тип значения | Описание |
---|---|---|
id или run_id | int | Номер посылки (значение поля run_id). Посылки нумеруются от 0. |
time | time_t | Астрономическое время получения посылки сервером (значение поля time) |
dur | dur_t | Длительность времени от начала турнира до получения посылки сервером (то есть разность между временем получения посылки и моментом начала турнира) |
size | size_t | Размер исходного текста программы в байтах (значение поля size). |
hash | hash_t | Хэш-код текста программы (значение поля sha1). |
uuid | string | Уникальный идентификатор посылки (значение поля run_uuid). |
ip | ip_t | IP-адрес клиента, на котором работает веб-браузер, и с которого была получена данная посылка (значение поля ip). |
uid или user_id | int | Идентификатор пользователя, от имени которого была выполнена данная посылка (значение поля user_id). Идентификатор пользователя всегда больше нуля. |
login | string | Регистрационное имя (login) пользователя, от имени которого была выполнена данная посылка. |
name | string | Имя (name) пользователя, от имени которого была выполнена данная посылка. |
group | string | Группа первого участника пользователя, от имени которого была выполнена данная посылка. |
cypher | string | Шифр пользователя, от имени которого была выполнена данная посылка. |
lang или lang_id | string | Короткое имя языка программирования, который был использован в данной посылке. Идентификатор языка программирования находится в поле lang_id записи базы посылок, а короткое имя языка программирования берётся из значения конфигурационной переменной short_name секции описания языка программирования файла конфигурации турнира serve.cfg. |
arch | string | Архитектура языка программирования |
prob или prob_id | string | Короткое имя задачи, решаемой в данной посылке. Идентификатор задачи находится в поле prob_id записи базы посылок, а короткое имя задачи берётся из значения конфигурационной переменной short_name секции описания задачи файла конфигурации турнира serve.cfg. |
result или status | result_t | Статус посылки (значение поля status). |
score | int | Балл за данную посылку без учёта штрафных баллов за посылки (значение поля score). |
test | int | Минимальный номер теста, на котором программа дала неверный результат, или количество успешно пройденных тестов в зависимости от типа турнира. |
imported | bool | Флаг импортированной посылки (значение поля is_imported). |
hidden | bool | Флаг скрытой посылки (значение поля is_hidden). |
readonly | bool | Флаг неизменяемой посылки (значение поля is_readonly). |
variant | int | Действительный вариант. Если для вариантной задачи номер варианта, хранящийся в базе посылок (значение поля variant), равен 0, используется номер варианта, установленный в файле карты вариантов, устанавливаемом глобальной конфигурационной переменной variant_map_file конфигурационного файла описания турнира serve.cfg. |
rawvariant | int | Хранимый вариант задачи в посылке (значение поля variant). |
userinvisible | bool | true, если посылка выполнена пользователем, у которого установлен статус invisible. |
userbanned | bool | true, если посылка выполнена пользователем, у которого установлен статус banned. |
userlocked | bool | true, если посылка выполнена пользователем, у которого установлен статус locked. |
userincomplete | bool | true, если посылка выполнена пользователем, у которого установлен статус incomplete. |
userdisqualified | bool | true, если посылка выполнена пользователем, у которого установлен статус disqualified. |
latest | bool | true, если посылка имеет статус OK, Partial solution или Accepted for testing и после нее нет посылок того же пользователя по той же задаче с этими статусами. Предикат может применяться в турнирах типа Olympiad для отбора посылок для полной проверки. |
afterok | bool | true, если у этого пользователя уже была посылка по этой же задаче, которая получила статус OK |
judge_id | int | Идентификационный номер запроса на тестирование (поле judge_id). Идентификационный номер изменяется в диапазоне от 1 до 65535. Число 0 означает отсутствие идентификационного номера. |
inusergroup(GRP) | bool | true, если этот пользователь принадлежит указанной группе пользователей. Название группы пользователей записывается как строка. Пример: inusergroup("Group1"). |
В выражении фильтра можно использовать примитивы для получения текущего времени, текущей продолжительности турнира и некоторые другие. Все такие примитивы рассмотрены в данном разделе. Примитивы имеют следующий общий вид:
pгде p — это имя примитива. Примитивы перечислены в таблице.
Имя примитива | Тип значения | Описание |
---|---|---|
now | time_t | Текущее астрономическое время. |
start | time_t | Астрономическое время начала турнира. |
finish | time_t | Астрономическое время завершения турнира. |
total | int | Общее количество записей в базе посылок. |
В данном разделе перечислены все операции, допустимые в выражении фильтра. Операции перечисляются в порядке убывания приоритета от наиболее приоритетных к наименее приоритетным. Приоритеты операций совпадают с приоритетами операций в языках Си, Си++, Java.
Далее рассмотрим все перечисленные операции.
Операция применима только к значению типа int. Результат операции — значение типа int, получаемое побитовым отрицанием первого значения.
Операция применима только к значению типа bool. Результат операции — значение типа bool, получаемое логическим отрицанием исходного значения.
Унарная операция смены знака применима только к значению типа int. Результат операции — значение типа int с противоположным знаком. Если результат операции не представим в типе int (то есть 32-битным знаковым числом), диагностируется ошибка переполнения.
Данная операция применима только к значению типа int и даёт результат типа int. Результирующее значение равно исходному.
Для операции умножения возможны следующие комбинации типов операндов.
Для операции целочисленного деления возможны следующие комбинации типов операндов. Если делитель равен нулю, диагностируется ошибка деления на ноль. Если результат операции не представим в типе результата, диагностируется ошибка переполнения. Например, при делении минимального значения типа int, равного −231 на −1 получается значение 231, не представимое в типе int.
Операция взятия остатка поддерживает несколько комбинаций типов аргументов. Если делитель равен нулю, диагностируется ошибка деления на ноль. Если тип делителя — какой-либо знаковый тип (например, int или dur_t), и делитель отрицателен, диагностируется ошибка неверного аргумента. Если результат операции не представим в типе результата, диагностируется ошибка переполнения. Допустимые комбинации типов операндов перечислены ниже.
Операция сложения применима ко многим комбинациям типов операндов. В любом случае, если результат операции не представим в типе результата, генерируется ошибка переполнения. Допустимые комбинации типов операндов перечислены ниже.
Операция вычитания применима ко многим комбинациям типов операндов. В любом случае, если результат операции не представим в типе результата, генерируется ошибка переполнения. Допустимые комбинации типов операндов перечислены ниже.
Операции побитового сдвига влево << и побитового сдвига вправо >> применимы только к операндам типа int. Результат операции имеет тип int. Второй аргумент операции (количество бит сдвига) должен находиться в отрезке от 0 до 32 включительно. Если это условие не выполняется, генерируется ошибка недопустимого аргумента операции. Сдвиг вправо выполняется как побитовый сдвиг, то есть на место старших разрядов числа помещаются нулевые биты. Переполнения при сдвиге влево не диагностируется.
Операции проверки на равенство или неравенство применимы ко всем типам данных. Оба аргумента должны иметь один и тот же тип. Неявных преобразований типа не производится. Результат операции имеет тип bool.
Данные операции применимы ко всем типам данных, кроме result_t, hash_t и ip_t. Оба аргумента операции должны иметь один и тот же тип данных. Результат операции имеет тип bool.
Данная операция применима к двум строкам. Первая строка проверяется на соответствие регулярному выражению, записанному во второй строке.
Побитовые операции применимы только к аргументам типа int и в результате дают значение типа int.
Показать посылки на языке gcc:
lang == "gcc"
Показать посылки по задаче A:
prob == "A"
Показать успешные посылки пользователя с логином serge:
login == "serge" && status == OK