Skip to content

Conversation

@ShashkovS
Copy link

Использование problem_dir в конфиге задачи позволяет давать разумные имена папкам с задачей. Но если мы используем варианты, скажем для контрольной, то всё ломается и портится: ведь мы должны использовать задачи, которые отличаются только суффиксом -1, -2  и т.д.
А хочется иметь возможность указать совсем разные папки. Примеры возможного конфига:

variant_num=3
problem_dir="python/assessments/loops/baz-gor"
problem_dir="python/assessments/loops/baz-rum"
problem_dir="python/assessments/loops/baz-gem"

То есть если указана переменная variant_num и её значение больше 1, то проводится проверка.
Если указан ровно один problem_dir, то пути для вариантов формируются по старой логике.
А если указана больше одного, то их число должно быть равно variant_num. И в этом случае для соответствующего варианта будет использоваться соответствующий problem_dir.

Хочется поменять логику хранения и определения директории с задачей.
Сделать полностью прозрачно и универсально.

Новая логика для problem_dir

Для каждой абстрактной задачи вычислять abstract_problem_dir.
Логика вычисления такая:

  1. Если problem_dir указан явно, и он начинается с / (абсолютный путь), то мы используем именно его
  2. Если problem_dir вообще не указан, то используется путь "путь_к_папке_с_контестами" / "номер контеста" / "problems". Например, /home/judges/000044/problems.
  3. Иначе problem_dir указан явно, но путь относительный. В этом случае итоговый abstract_problem_dir является "конкатенацией" пути "путь_к_папке_с_контестами" / "номер контеста" / "problems" и problem_dir.
    Например, если problem_dir="../baz", то получим "/home/judges/000044/problems/../baz"
    Тем самым для каждой абстрактной задачи у нас будет свой abstract_problem_dir.
    Мы будем хранить его в переменной abstract_problem_dir.

Для каждой конкретной задачи мы берём abstract_problem_dir из абстрактной задачи.
Дальше для хранения problem_dir обычной задачи мы всегда будем использовать массив (вектор) problem_dirs.
Логика его определения такая:
0. Определяем число вариантов и все указанные параметры problem_dir в задаче. Число вариантов variant_num может быть указано у конктрентной задачи, либо у её абстрактной задачи, либо используется значение по умолчанию --- variant_num=1.
0а. Если variant_num=1, то задача не вариантная. В итоговом problem_dirs всегда будет ровно один путь. В конфиге задачи может быть либо 0, либо ровно 1 problem_dir.
0б. Если variant_num указан и variant_num > 1, то задача вариантная. В итоговом problem_dirs всегда будет ровно variant_num путей. В конфиге задачи может быть либо 0, либо ровно 1 problem_dir, либо ровно variant_num параметров problem_dir.
Если число указанных problem_dir не соответствует variant_num (то есть
variant_num == 1 && len(problem_dir) > 1 || variant_num > 1 && len(problem_dir) > 1 && len(problem_dir) != variant_num), то мы возвращаем ошибку парсинга конфига "неправильное число problem_dir"

Далее. Если задача не вариантная, то есть variant_num = 1 (это дефолтное значение)
1а. Если у задачи явно указан problem_dir и этот путь абсолютный, то используем этот путь.
1б. Если у задачи явно указан problem_dir и он относительный, то используем join(abstract_problem_dir, problem_dir)
1в. Иначе если у задачи указан internal_name, то используем join(abstract_problem_dir, internal_name)
1г. Иначе используем join(abstract_problem_dir, short_name)

Если задача вариантная, то есть variant_num > 1, то нам нужно построить массив problem_dirs из variant_num элементов. Логика такая:
2а. Если у задачи явно указаны variant_num параметров problem_dir, то мы обрабатываем каждый из них по логике из 1а или 1б (явно problem_dir, если абсолютный или join(abstract_problem_dir, problem_dir) если относительный)
2бi. Если problem_dir не указан вовсе, то мы считаем, что problem_dir = internal_name, если internal_name указан, и short_name иначе. То есть тут мы заведомо получаем ровно одно значение problem_dir либо явно указанное, либо полученное из internal_name или short_name.
2бii. Если получившийся problem_dir относительный, то делаем его абсолютным при помощи join(abstract_problem_dir, problem_dir). К этому моменту мы заведомо получаем ровно один абсолютный problem_dir.
2бiii. Для каждого n от 1 до variant_num мы добавляем в problem_dirs путь вида ${problem_dir}-n.

@ShashkovS
Copy link
Author

Пример serve.cfg для тестирования:

# -*- coding: utf-8 -*-

contest_time = 0
score_system = acm
board_fog_time = 0
board_unfog_time = 0
standings_locale = "Russian"

compile_dir = "../../compile/var/compile"

team_enable_src_view
team_enable_ce_view
team_show_judge_report
report_error_code
disable_team_clars
ignore_compile_errors
disable_failed_test_view
disable_language
problem_navigation
notify_clar_reply


max_run_size = 3M
max_run_total = 10M

standings_file_name = "000044.html"
ignore_success_time
external_xml_update_time = 60

stand_fancy_style
stand_table_attr = " border=1 cellspacing=1 celpadding=3"
stand_place_attr = " align=\"right\""
stand_team_attr = " align=\"left\""
stand_prob_attr = " align=\"center\""
stand_solved_attr = " align=\"center\""
stand_penalty_attr = " align=\"right\""
stand_fail_attr = " align=center bgcolor=\"#ff8888\""
stand_trans_attr = " align=center bgcolor=\"#ffff88\""
stand_disq_attr = " align=center bgcolor=\"#ffaaaa\""

use_ac_not_ok
rounding_mode = floor
cr_serialization_key = 22723
show_astr_time
enable_runlog_merge
secure_run
enable_memory_limit_error
advanced_layout
ignore_bom
enable_max_stack_size
enable_l10n
team_download_time = 0
cpu_bogomips = 4527
variant_map_file = "variant.map"
clardb_plugin = "mysql"
rundb_plugin = "mysql"


[language]
id = 23
short_name = "python3"
long_name = "Python 3.11.4"
arch = "linux-shared"
src_sfx = ".py"

[problem]
abstract
short_name = "AbstractNoProblemDir"
use_stdin
input_file = "input.txt"
combined_stdin
use_stdout
output_file = "output.txt"
combined_stdout
test_dir = "%Ps"
test_sfx = ".dat"
test_pat = "%02d"
use_corr
corr_dir = "%Ps"
corr_sfx = ".ans"
corr_pat = "%02d.a"
info_dir = "%Ps"
tgz_dir = "%Ps"
time_limit = 5
real_time_limit = 5
max_stack_size = 1256M
max_rss_size = 1256M
open_tests = "1-99:brief"
acm_run_penalty = 1
check_cmd = "check"
ignore_prev_ac
ignore_compile_errors
disable_tab = 0
unrestricted_statement = 0
hide_real_time_limit
disable_ctrl_chars
enable_text_form



[problem]
abstract
short_name = "AbstractProblemDirAbsoluteShort"
problem_dir = "/home/judges/variants_problem_dir_test/by_short_name"
use_stdin
input_file = "input.txt"
combined_stdin
use_stdout
output_file = "output.txt"
combined_stdout
test_dir = "%Ps"
test_sfx = ".dat"
test_pat = "%02d"
use_corr
corr_dir = "%Ps"
corr_sfx = ".ans"
corr_pat = "%02d.a"
info_dir = "%Ps"
tgz_dir = "%Ps"
time_limit = 5
real_time_limit = 5
max_stack_size = 1256M
max_rss_size = 1256M
open_tests = "1-99:brief"
acm_run_penalty = 1
check_cmd = "check"
ignore_prev_ac
ignore_compile_errors
disable_tab = 0
unrestricted_statement = 0
hide_real_time_limit
disable_ctrl_chars
enable_text_form


[problem]
abstract
short_name = "AbstractProblemDirAbsoluteLong"
problem_dir = "/home/judges/variants_problem_dir_test/by_long_name"
use_stdin
input_file = "input.txt"
combined_stdin
use_stdout
output_file = "output.txt"
combined_stdout
test_dir = "%Ps"
test_sfx = ".dat"
test_pat = "%02d"
use_corr
corr_dir = "%Ps"
corr_sfx = ".ans"
corr_pat = "%02d.a"
info_dir = "%Ps"
tgz_dir = "%Ps"
time_limit = 5
real_time_limit = 5
max_stack_size = 1256M
max_rss_size = 1256M
open_tests = "1-99:brief"
acm_run_penalty = 1
check_cmd = "check"
ignore_prev_ac
ignore_compile_errors
disable_tab = 0
unrestricted_statement = 0
hide_real_time_limit
disable_ctrl_chars
enable_text_form


[problem]
abstract
short_name = "AbstractProblemDirAbsoluteMed"
problem_dir = "/home/judges/variants_problem_dir_test"
use_stdin
input_file = "input.txt"
combined_stdin
use_stdout
output_file = "output.txt"
combined_stdout
test_dir = "%Ps"
test_sfx = ".dat"
test_pat = "%02d"
use_corr
corr_dir = "%Ps"
corr_sfx = ".ans"
corr_pat = "%02d.a"
info_dir = "%Ps"
tgz_dir = "%Ps"
time_limit = 5
real_time_limit = 5
max_stack_size = 1256M
max_rss_size = 1256M
open_tests = "1-99:brief"
acm_run_penalty = 1
check_cmd = "check"
ignore_prev_ac
ignore_compile_errors
disable_tab = 0
unrestricted_statement = 0
hide_real_time_limit
disable_ctrl_chars
enable_text_form




[problem]
abstract
short_name = "AbstractProblemDirRelativeShort"
problem_dir = "../../variants_problem_dir_test/by_short_name"
use_stdin
input_file = "input.txt"
combined_stdin
use_stdout
output_file = "output.txt"
combined_stdout
test_dir = "%Ps"
test_sfx = ".dat"
test_pat = "%02d"
use_corr
corr_dir = "%Ps"
corr_sfx = ".ans"
corr_pat = "%02d.a"
info_dir = "%Ps"
tgz_dir = "%Ps"
time_limit = 5
real_time_limit = 5
max_stack_size = 1256M
max_rss_size = 1256M
open_tests = "1-99:brief"
acm_run_penalty = 1
check_cmd = "check"
ignore_prev_ac
ignore_compile_errors
disable_tab = 0
unrestricted_statement = 0
hide_real_time_limit
disable_ctrl_chars
enable_text_form


[problem]
abstract
short_name = "AbstractProblemDirRelativeLong"
problem_dir = "../../variants_problem_dir_test/by_long_name"
use_stdin
input_file = "input.txt"
combined_stdin
use_stdout
output_file = "output.txt"
combined_stdout
test_dir = "%Ps"
test_sfx = ".dat"
test_pat = "%02d"
use_corr
corr_dir = "%Ps"
corr_sfx = ".ans"
corr_pat = "%02d.a"
info_dir = "%Ps"
tgz_dir = "%Ps"
time_limit = 5
real_time_limit = 5
max_stack_size = 1256M
max_rss_size = 1256M
open_tests = "1-99:brief"
acm_run_penalty = 1
check_cmd = "check"
ignore_prev_ac
ignore_compile_errors
disable_tab = 0
unrestricted_statement = 0
hide_real_time_limit
disable_ctrl_chars
enable_text_form



# Без вариантов

[problem]
id = 1010
super = "AbstractNoProblemDir"
short_name = "A-1"
long_name = "1010 AbstractNoProblemDir, A-1"
type = "standard"
xml_file = "statement.xml"
standard_checker = "cmp_file"
# должна смотреть на
# /home/judges/000044/problems/A-1

[problem]
id = 1020
super = "AbstractNoProblemDir"
short_name = "B"
long_name = "1020 AbstractNoProblemDir, B"
type = "standard"
xml_file = "statement.xml"
standard_checker = "cmp_file"
# должна смотреть на
# /home/judges/000044/problems/B

[problem]
id = 1030
super = "AbstractProblemDirAbsoluteShort"
# abstract_problem_dir = "/home/judges/variants_problem_dir_test/by_short_name"
short_name = "A-1"
long_name = "1030 AbstractProblemDirAbsoluteShort, A-1"
type = "standard"
xml_file = "statement.xml"
standard_checker = "cmp_file"
# должна смотреть на
# /home/judges/variants_problem_dir_test/by_short_name/A-1

[problem]
id = 1040
super = "AbstractProblemDirAbsoluteShort"
# abstract_problem_dir = "/home/judges/variants_problem_dir_test/by_short_name"
short_name = "B"
long_name = "1040 AbstractProblemDirAbsoluteShort, B"
type = "standard"
xml_file = "statement.xml"
standard_checker = "cmp_file"
# должна смотреть на
# /home/judges/variants_problem_dir_test/by_short_name/B

[problem]
id = 1050
super = "AbstractProblemDirRelativeShort"
# abstract_problem_dir = "../../variants_problem_dir_test/by_short_name"
short_name = "A-1"
long_name = "1050 AbstractProblemDirRelativeShort, A-1"
type = "standard"
xml_file = "statement.xml"
standard_checker = "cmp_file"
# должна смотреть на
# /home/judges/000044/problems/../../variants_problem_dir_test/by_short_name/A-1

[problem]
id = 1060
super = "AbstractProblemDirRelativeShort"
# abstract_problem_dir = "../../variants_problem_dir_test/by_short_name"
short_name = "B"
long_name = "1060 AbstractProblemDirRelativeShort, B"
type = "standard"
xml_file = "statement.xml"
standard_checker = "cmp_file"
# должна смотреть на
# /home/judges/000044/problems/../../variants_problem_dir_test/by_short_name/B

[problem]
id = 1070
super = "AbstractProblemDirAbsoluteLong"
# abstract_problem_dir = "/home/judges/variants_problem_dir_test/by_long_name"
short_name = "1070-L1"
internal_name = "long_one"
long_name = "1070 AbstractProblemDirAbsoluteLong, long_one"
type = "standard"
xml_file = "statement.xml"
standard_checker = "cmp_file"
# должна смотреть на
# /home/judges/variants_problem_dir_test/by_long_name/long_one

[problem]
id = 1080
super = "AbstractProblemDirAbsoluteLong"
# abstract_problem_dir = "/home/judges/variants_problem_dir_test/by_long_name"
short_name = "long_two"
long_name = "1080 AbstractProblemDirAbsoluteLong, long_two"
type = "standard"
xml_file = "statement.xml"
standard_checker = "cmp_file"
# должна смотреть на
# /home/judges/variants_problem_dir_test/by_long_name/long_two


[problem]
id = 1090
super = "AbstractProblemDirRelativeLong"
# abstract_problem_dir = "../../variants_problem_dir_test/by_long_name"
short_name = "1090-L1"
internal_name = "long_one"
long_name = "1090 AbstractProblemDirRelativeLong, long_one"
type = "standard"
xml_file = "statement.xml"
standard_checker = "cmp_file"
# должна смотреть на
# /home/judges/000044/problems/../../variants_problem_dir_test/by_long_name/long_one

[problem]
id = 1100
super = "AbstractProblemDirRelativeLong"
# abstract_problem_dir = "../../variants_problem_dir_test/by_long_name"
short_name = "long_two"
long_name = "1100 AbstractProblemDirRelativeLong, long_two"
type = "standard"
xml_file = "statement.xml"
standard_checker = "cmp_file"
# должна смотреть на
# /home/judges/000044/problems/../../variants_problem_dir_test/by_long_name/long_two


[problem]
id = 1110
super = "AbstractNoProblemDir"
short_name = "1110-A-1"
problem_dir = "../../variants_problem_dir_test/by_short_name/A-1"
long_name = "1110 AbstractNoProblemDir, problem_dir, A-1"
type = "standard"
xml_file = "statement.xml"
standard_checker = "cmp_file"
# должна смотреть на
# /home/judges/000044/problems/../../variants_problem_dir_test/by_short_name/A-1


[problem]
id = 1120
super = "AbstractProblemDirAbsoluteShort"
# abstract_problem_dir = "/home/judges/variants_problem_dir_test/by_short_name"
short_name = "1120-A-1"
problem_dir = "A-1"
long_name = "1120 AbstractProblemDirAbsoluteShort, problem_dir, A-1"
type = "standard"
xml_file = "statement.xml"
standard_checker = "cmp_file"
# должна смотреть на
# /home/judges/variants_problem_dir_test/by_short_name/A-1

[problem]
id = 1130
super = "AbstractProblemDirRelativeShort"
# abstract_problem_dir = "../../variants_problem_dir_test/by_short_name"
short_name = "1130-B"
problem_dir = "B"
long_name = "1130 AbstractProblemDirRelativeShort, problem_dir, B"
type = "standard"
xml_file = "statement.xml"
standard_checker = "cmp_file"
# должна смотреть на
# /home/judges/000044/problems/../../variants_problem_dir_test/by_short_name/B

[problem]
id = 1140
super = "AbstractProblemDirAbsoluteLong"
# abstract_problem_dir = "/home/judges/variants_problem_dir_test/by_long_name"
short_name = "1140-L4"
problem_dir = "long_four"
long_name = "1140 AbstractProblemDirAbsoluteLong, problem_dir, long_four"
type = "standard"
xml_file = "statement.xml"
standard_checker = "cmp_file"
# должна смотреть на
# /home/judges/variants_problem_dir_test/by_long_name/long_four

[problem]
id = 1150
super = "AbstractProblemDirRelativeLong"
# abstract_problem_dir = "../../variants_problem_dir_test/by_long_name"
short_name = "1150-L3"
problem_dir = "long_three"
long_name = "1150 AbstractProblemDirRelativeLong, problem_dir, long_three"
type = "standard"
xml_file = "statement.xml"
standard_checker = "cmp_file"
# должна смотреть на
# /home/judges/000044/problems/../../variants_problem_dir_test/by_long_name/long_three


[problem]
id = 1160
super = "AbstractNoProblemDir"
short_name = "1160-A-1"
problem_dir = "/home/judges/variants_problem_dir_test/by_short_name/A-1"
long_name = "1160 AbstractNoProblemDir, problem_dir, A-1"
type = "standard"
xml_file = "statement.xml"
standard_checker = "cmp_file"
# должна смотреть на
# /home/judges/variants_problem_dir_test/by_short_name/A-1



# C вариантами, но без указания конкретных папок вариантов

[problem]
id = 3010
super = "AbstractNoProblemDir"
short_name = "A"
long_name = "3010 AbstractNoProblemDir, A-*"
type = "standard"
xml_file = "statement.xml"
standard_checker = "cmp_file"
variant_num = 3
autoassign_variants
# должна смотреть на
# /home/judges/000044/problems/A-1
# /home/judges/000044/problems/A-2
# /home/judges/000044/problems/A-3

[problem]
id = 3030
super = "AbstractProblemDirAbsoluteShort"
# abstract_problem_dir = "/home/judges/variants_problem_dir_test/by_short_name"
short_name = "A"
long_name = "3030 AbstractProblemDirAbsoluteShort, A-*"
type = "standard"
xml_file = "statement.xml"
standard_checker = "cmp_file"
variant_num = 2
autoassign_variants
# должна смотреть на
# /home/judges/variants_problem_dir_test/by_short_name/A-1
# /home/judges/variants_problem_dir_test/by_short_name/A-2

[problem]
id = 3050
super = "AbstractProblemDirRelativeShort"
# abstract_problem_dir = "../../variants_problem_dir_test/by_short_name"
short_name = "A"
long_name = "3050 AbstractProblemDirRelativeShort, A-*"
type = "standard"
xml_file = "statement.xml"
standard_checker = "cmp_file"
variant_num = 4
autoassign_variants
# должна смотреть на
# /home/judges/000044/problems/../../variants_problem_dir_test/by_short_name/A-1
# /home/judges/000044/problems/../../variants_problem_dir_test/by_short_name/A-2
# /home/judges/000044/problems/../../variants_problem_dir_test/by_short_name/A-3
# /home/judges/000044/problems/../../variants_problem_dir_test/by_short_name/A-4


[problem]
id = 3110
super = "AbstractNoProblemDir"
short_name = "3110-A"
problem_dir = "../../variants_problem_dir_test/by_short_name/A"
long_name = "3110 AbstractNoProblemDir, problem_dir, A-*"
type = "standard"
xml_file = "statement.xml"
standard_checker = "cmp_file"
variant_num = 3
autoassign_variants
# должна смотреть на
# /home/judges/000044/problems/../../variants_problem_dir_test/by_short_name/A-1
# /home/judges/000044/problems/../../variants_problem_dir_test/by_short_name/A-2
# /home/judges/000044/problems/../../variants_problem_dir_test/by_short_name/A-3

[problem]
id = 3120
super = "AbstractProblemDirAbsoluteShort"
# abstract_problem_dir = "/home/judges/variants_problem_dir_test/by_short_name"
short_name = "3120-A"
problem_dir = "A"
long_name = "3120 AbstractProblemDirAbsoluteShort, problem_dir, A-*"
type = "standard"
xml_file = "statement.xml"
standard_checker = "cmp_file"
variant_num = 2
autoassign_variants
# должна смотреть на
# /home/judges/variants_problem_dir_test/by_short_name/A-1
# /home/judges/variants_problem_dir_test/by_short_name/A-2



# C вариантами, С указанием конкретных папок вариантов

[problem]
id = 5010
super = "AbstractNoProblemDir"
short_name = "5010-A"
long_name = "5010 AbstractNoProblemDir, A-*"
type = "standard"
xml_file = "statement.xml"
standard_checker = "cmp_file"
variant_num = 3
autoassign_variants
problem_dir = "A-1"
problem_dir = "A-2"
problem_dir = "A-3"
# должна смотреть на
# /home/judges/000044/problems/A-1
# /home/judges/000044/problems/A-2
# /home/judges/000044/problems/A-3

[problem]
id = 5030
super = "AbstractProblemDirAbsoluteShort"
# abstract_problem_dir = "/home/judges/variants_problem_dir_test/by_short_name"
short_name = "5030-A"
long_name = "5030 AbstractProblemDirAbsoluteShort, A-*"
type = "standard"
xml_file = "statement.xml"
standard_checker = "cmp_file"
variant_num = 2
autoassign_variants
problem_dir = "A-1"
problem_dir = "A-2"
# должна смотреть на
# /home/judges/variants_problem_dir_test/by_short_name/A-1
# /home/judges/variants_problem_dir_test/by_short_name/A-2

[problem]
id = 5050
super = "AbstractProblemDirRelativeShort"
# abstract_problem_dir = "../../variants_problem_dir_test/by_short_name"
short_name = "5050-A"
long_name = "5050 AbstractProblemDirRelativeShort, A-*"
type = "standard"
xml_file = "statement.xml"
standard_checker = "cmp_file"
variant_num = 4
autoassign_variants
problem_dir = "A-1"
problem_dir = "A-2"
problem_dir = "A-3"
problem_dir = "A-4"
# должна смотреть на
# /home/judges/000044/problems/../../variants_problem_dir_test/by_short_name/A-1
# /home/judges/000044/problems/../../variants_problem_dir_test/by_short_name/A-2
# /home/judges/000044/problems/../../variants_problem_dir_test/by_short_name/A-3
# /home/judges/000044/problems/../../variants_problem_dir_test/by_short_name/A-4


[problem]
id = 5070
super = "AbstractProblemDirAbsoluteLong"
# abstract_problem_dir = "/home/judges/variants_problem_dir_test/by_long_name"
short_name = "5070-L123"
internal_name = "long_one"
long_name = "5070 AbstractProblemDirAbsoluteLong, long_*"
type = "standard"
xml_file = "statement.xml"
standard_checker = "cmp_file"
variant_num = 3
autoassign_variants
problem_dir = "long_one"
problem_dir = "long_two"
problem_dir = "long_three"
# должна смотреть на
# /home/judges/variants_problem_dir_test/by_long_name/long_one
# /home/judges/variants_problem_dir_test/by_long_name/long_two
# /home/judges/variants_problem_dir_test/by_long_name/long_three


[problem]
id = 5090
super = "AbstractProblemDirRelativeLong"
# abstract_problem_dir = "../../variants_problem_dir_test/by_long_name"
short_name = "5090-L1234"
internal_name = "long_one"
long_name = "5090 AbstractProblemDirRelativeLong, long_*"
type = "standard"
xml_file = "statement.xml"
standard_checker = "cmp_file"
variant_num = 4
autoassign_variants
problem_dir = "long_one"
problem_dir = "long_two"
problem_dir = "long_three"
problem_dir = "long_four"
# должна смотреть на
# /home/judges/000044/problems/../../variants_problem_dir_test/by_long_name/long_one
# /home/judges/000044/problems/../../variants_problem_dir_test/by_long_name/long_two
# /home/judges/000044/problems/../../variants_problem_dir_test/by_long_name/long_three
# /home/judges/000044/problems/../../variants_problem_dir_test/by_long_name/long_four

[problem]
id = 5110
super = "AbstractNoProblemDir"
short_name = "5110-A123"
long_name = "5110 AbstractNoProblemDir, problem_dir, A-*"
type = "standard"
xml_file = "statement.xml"
standard_checker = "cmp_file"
variant_num = 3
autoassign_variants
problem_dir = "../../variants_problem_dir_test/by_short_name/A-1"
problem_dir = "../../variants_problem_dir_test/by_short_name/A-2"
problem_dir = "../../variants_problem_dir_test/by_short_name/A-3"
# должна смотреть на
# /home/judges/000044/problems/../../variants_problem_dir_test/by_short_name/A-1
# /home/judges/000044/problems/../../variants_problem_dir_test/by_short_name/A-2
# /home/judges/000044/problems/../../variants_problem_dir_test/by_short_name/A-3


[problem]
id = 5120
super = "AbstractProblemDirAbsoluteShort"
# abstract_problem_dir = "/home/judges/variants_problem_dir_test/by_short_name"
short_name = "5120-A12"
long_name = "5120 AbstractProblemDirAbsoluteShort, problem_dir, A-*"
type = "standard"
xml_file = "statement.xml"
standard_checker = "cmp_file"
variant_num = 2
autoassign_variants
problem_dir = "A-1"
problem_dir = "A-2"
# должна смотреть на
# /home/judges/variants_problem_dir_test/by_short_name/A-1
# /home/judges/variants_problem_dir_test/by_short_name/A-2

[problem]
id = 5130
super = "AbstractProblemDirRelativeShort"
# abstract_problem_dir = "../../variants_problem_dir_test/by_short_name"
short_name = "5130-BCD"
long_name = "5130 AbstractProblemDirRelativeShort, problem_dir, B"
type = "standard"
xml_file = "statement.xml"
standard_checker = "cmp_file"
variant_num = 3
autoassign_variants
problem_dir = "B"
problem_dir = "C"
problem_dir = "D"
# должна смотреть на
# /home/judges/000044/problems/../../variants_problem_dir_test/by_short_name/B
# /home/judges/000044/problems/../../variants_problem_dir_test/by_short_name/C
# /home/judges/000044/problems/../../variants_problem_dir_test/by_short_name/D

[problem]
id = 5140
super = "AbstractProblemDirAbsoluteLong"
# abstract_problem_dir = "/home/judges/variants_problem_dir_test/by_long_name"
short_name = "5140-L145"
long_name = "5140 AbstractProblemDirAbsoluteLong, problem_dir, long_*"
type = "standard"
xml_file = "statement.xml"
standard_checker = "cmp_file"
variant_num = 3
autoassign_variants
problem_dir = "long_one"
problem_dir = "long_four"
problem_dir = "long_five"
# должна смотреть на
# /home/judges/variants_problem_dir_test/by_long_name/long_one
# /home/judges/variants_problem_dir_test/by_long_name/long_four
# /home/judges/variants_problem_dir_test/by_long_name/long_five

[problem]
id = 5150
super = "AbstractProblemDirRelativeLong"
# abstract_problem_dir = "../../variants_problem_dir_test/by_long_name"
short_name = "5150-L1245"
long_name = "5150 AbstractProblemDirRelativeLong, problem_dir, long_*"
type = "standard"
xml_file = "statement.xml"
standard_checker = "cmp_file"
variant_num = 4
autoassign_variants
problem_dir = "long_one"
problem_dir = "long_two"
problem_dir = "long_four"
problem_dir = "long_five"
# должна смотреть на
# /home/judges/000044/problems/../../variants_problem_dir_test/by_long_name/long_one
# /home/judges/000044/problems/../../variants_problem_dir_test/by_long_name/long_two
# /home/judges/000044/problems/../../variants_problem_dir_test/by_long_name/long_four
# /home/judges/000044/problems/../../variants_problem_dir_test/by_long_name/long_five

[problem]
id = 5160
super = "AbstractNoProblemDir"
short_name = "5160-A123"
long_name = "5160 AbstractNoProblemDir, problem_dir, A-*"
type = "standard"
xml_file = "statement.xml"
standard_checker = "cmp_file"
variant_num = 3
autoassign_variants
problem_dir = "/home/judges/variants_problem_dir_test/by_short_name/A-1"
problem_dir = "/home/judges/variants_problem_dir_test/by_short_name/A-2"
problem_dir = "/home/judges/variants_problem_dir_test/by_short_name/A-3"
# должна смотреть на
# /home/judges/variants_problem_dir_test/by_short_name/A-1
# /home/judges/variants_problem_dir_test/by_short_name/A-2
# /home/judges/variants_problem_dir_test/by_short_name/A-3


[problem]
id = 5170
super = "AbstractNoProblemDir"
short_name = "5170-L12"
long_name = "5170 AbstractNoProblemDir, problem_dir, long-*"
type = "standard"
xml_file = "statement.xml"
standard_checker = "cmp_file"
variant_num = 2
autoassign_variants
problem_dir = "/home/judges/variants_problem_dir_test/by_long_name/long_one"
problem_dir = "/home/judges/variants_problem_dir_test/by_long_name/long_two"
# должна смотреть на
# /home/judges/variants_problem_dir_test/by_long_name/long_one
# /home/judges/variants_problem_dir_test/by_long_name/long_two


[problem]
id = 5180
super = "AbstractProblemDirAbsoluteMed"
# abstract_problem_dir = "/home/judges/variants_problem_dir_test"
short_name = "5180-L12"
long_name = "5180 AbstractProblemDirAbsoluteMed, problem_dir, long-*"
type = "standard"
xml_file = "statement.xml"
standard_checker = "cmp_file"
variant_num = 2
autoassign_variants
problem_dir = "by_long_name/long_one"
problem_dir = "by_long_name/long_two"
# должна смотреть на
# /home/judges/variants_problem_dir_test/by_long_name/long_one
# /home/judges/variants_problem_dir_test/by_long_name/long_two




[tester]
name = Linux-shared
arch = "linux-shared"
abstract
no_core_dump
enable_memory_limit_error
kill_signal = KILL
memory_limit_type = "default"
secure_exec_type = "dll"
clear_env
start_env = "PATH=/usr/local/bin:/usr/bin:/bin:/web/ejudge/cargo/bin"
start_env = "CARGO_HOME=/web/ejudge/cargo"
start_env = "RUSTUP_HOME=/web/ejudge/cargo"
start_env = "RUSTDIR=/web/ejudge/cargo/bin"
start_env = "HOME"
check_dir = "/var/run/ejudge/work-disk/work"

[tester]
any
super = Linux-shared
arch = linux-shared

@ShashkovS
Copy link
Author

serve.txt

@ShashkovS
Copy link
Author

variants_problem_dir_test.zip

Набор задач для тестирования. Положить в /home/judges.
Кроме того из контеста для тестирования повесить сим-линку
problems -> /home/judges/variants_problem_dir_test/by_short_name/

@ShashkovS
Copy link
Author

text_runs.xml

Архив посылок для тестирования

@ShashkovS
Copy link
Author

ShashkovS commented Jan 7, 2026

Теперь problem_dir отображается в интерфейсе и может быть изменён в интерфейсе:

image image image image image image

Также все пути отображаются после Commit изменений:

image image

В админ-интерфейсе сабмита задачи при выборе варианта отображается актуальный путь:

image

@ShashkovS
Copy link
Author

Страница документации:
https://ejudge.ru/wiki/index.php/Serve.cfg:problem:problem_dir

Предложение для обновления документации:

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

Базовая логика (abstract_problem_dir)

Для каждой абстрактной задачи вычисляется abstract_problem_dir — базовый путь, относительно которого разрешаются пути задач.

Алгоритм:

  1. Если problem_dir указан и является абсолютным путём (начинается с /), то abstract_problem_dir = problem_dir.
  2. Если problem_dir не указан, то abstract_problem_dir равен ${root_dir}/${contest_id}/problems.
  3. Если problem_dir указан, но путь относительный, то abstract_problem_dir = ${root_dir}/${contest_id}/problems + problem_dir (простая конкатенация пути).

Пример:

[problem]
abstract
short_name = "Generic"
problem_dir = "../000010/problems"

Для этой абстрактной задачи:
abstract_problem_dir = /home/judges/000044/problems/../000010/problems

Поддерживается начиная с версии 3.5.2.

Конкретная задача: правила problem_dir

Для конкретной задачи всегда вычисляется список путей problem_dirs (массив). Он содержит:

  • один элемент для невариантной задачи,
  • variant_num элементов для вариантной задачи.

Определение количества вариантов

Используется значение variant_num (с наследованием от абстрактной задачи).

  • Если variant_num не задан или равен 0, задача считается не вариантной.
  • Если variant_num равен 1, задача тоже считается не вариантной (суффиксы -1 не добавляются).
  • Если variant_num > 1, задача вариантная.

Проверка числа problem_dir

Пусть k — количество указанных problem_dir в описании конкретной задачи:

  • Если задача не вариантная, то допустимо k = 0 или k = 1.
  • Если задача вариантная, допустимо k = 0, k = 1 или k = variant_num.
  • Любое другое значение — ошибка парсинга: «неправильное число problem_dir».

Невариантная задача (variant_num = 0 или 1)

Итоговый problem_dirs состоит из одного пути и строится так:

  1. Если problem_dir указан и путь абсолютный — используется он.
  2. Если problem_dir указан и путь относительный — используется join(abstract_problem_dir, problem_dir).
  3. Если problem_dir не указан, но задан internal_name — используется join(abstract_problem_dir, internal_name).
  4. Иначе используется join(abstract_problem_dir, short_name).

Вариантная задача (variant_num > 1)

Случай A: указано ровно variant_num значений problem_dir

Каждый путь обрабатывается независимо по правилам:

  • абсолютный путь оставляется без изменений,
  • относительный преобразуется в join(abstract_problem_dir, problem_dir).

Случай B: problem_dir не указан или указан ровно один раз

  1. Если problem_dir не задан, то берётся базовое имя:
    • internal_name, если задан;
    • иначе short_name.
  2. Если получившийся путь относительный, он преобразуется в абсолютный:
    problem_dir = join(abstract_problem_dir, problem_dir).
  3. Итоговые пути строятся добавлением суффикса варианта:
    ${problem_dir}-1, ${problem_dir}-2, …, ${problem_dir}-variant_num.

Примеры

Простая относительная директория

problem_dir = "./other_name"

Каталог задачи будет расположен в problems/./other_name.

Абсолютная директория

problem_dir = "/home/judges/git-repo/2016/A"

Каталог задачи — /home/judges/git-repo/2016/A.

Абстрактная база + относительный путь конкретной задачи

[problem]
abstract
short_name = "Generic"
problem_dir = "/home/judges/git-repo/2016"

[problem]
short_name = "A"
super = "Generic"
problem_dir = "A"

Итоговый путь: /home/judges/git-repo/2016/A.

Вариантная задача с индивидуальными директориями

[problem]
abstract
short_name = "Generic"
problem_dir = "/home/judges/problems"

[problem]
id = 7010
super = "Generic"
short_name = "A"
long_name = "Максимум цветов"
variant_num = 3
problem_dir = "python/ege07/07-A1-max-colors-32x32"
problem_dir = "python/ege07/07-A2-max-colors-1024x1024"
problem_dir = "python/ege07/07-A3-max-colors-128x320"

В результате будут использованы пути:

  • /home/judges/problems/python/ege07/07-A1-max-colors-32x32
  • /home/judges/problems/python/ege07/07-A2-max-colors-1024x1024
  • /home/judges/problems/python/ege07/07-A3-max-colors-128x320

Поддержка нескольких problem_dir для вариантной задачи — начиная с версии [3.13.1].

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant