Нужно было по быстрому поднять виртуальную машину для оффлайн-олимпиады по программированию в локальной сети. Решал раньше эту задачу с помощью Moodle c Coderunner и Jobe, но со сторонними дистрибутивами. Сейчас с костылями поднял все это на альте. Все вроде есть в репозитарии, но без бубна не заработало. Вот минусовка, может кому пригодится, хотя-бы для приведения в порядок этих пакетов в дистрибутиве:
Jobe и Сoderunner в moodle на Alt 10 (последний starterkit XFCE)
Jobe не работает: runguard использует cgroupsV1, а в альте cgroupsV2.
Выход - перекомпилировать вариант без cgroups, поправить в коде Jobe способ вызова runguard с учетом отката на старые параметры
Jobe не работает: попытка запуска sudo блокируется, ибо оно в альте доступно только для группы wheel.
Выход - дать возможность запуска sudo остальным. Или искать другие пути, без понижения уровня безопасности, но меня и этот устроил
Coderunner не работает, ибо настройки безопасности мудла по умолчанию не дают доступа к локалхост ни в каком виде, а jobe у меня крутится на той-же машине.
Выход - в разделе "Безопасность/Безопасность HTTP" почистить все запреты на URL и добавить разрешенные порты, для jobe - 8089
Coderunner не имеет мультиязыкового шаблона для паскаля и php, что есть нисусветный пердимонокль.
Выход: берем из банка вопросов шаблон multilanguage от coderunner, делаем копию и там правим:
language_extension_map = {'c':'c', 'cpp':'cpp', 'java':'java', 'python3':'py'}
заменяем на
language_extension_map = {'c':'c', 'cpp':'cpp', 'php':'php', 'python3':'py', 'pascal':'pas'}
java мне особо не нужна, заменяю ее на точно существующий php. Ну а pascal просто добавляем. На машине устанавливаем все языки из списка.
Затем удаляем все шаблоне, связанное с java. Добавляем поддержку php и pascal:
...
elif language == 'pascal':
pasflags = " -vew -Se"
return_code = subprocess.call("fpc {0} __tester__.pas".format(pasflags).split())
if return_code != 0:
raise Exception("** Compilation failed. Testing aborted **")
exec_command = ["./__tester__"]
elif language == 'php':
exec_command = ["php", "./__tester__.php"]
...
Затем в расширенной настройке "Язык Ace" указываем список наших языков
c,cpp,pascal*,php,python3
И в ответе вписываем кусок кода:
{$mode objfpc}
begin
end.
Если другой язык делать дефолтным, то два последних действия исправляем.
Теперь по удобству представления результатов. Поле "got" не годится для олимпиад, оно возвращает результат вывода программы. А ушлые олимпиадники этим пользуются. Забирают ввод и отправляют его на вывод, тем самым получая все тестовые задания. Затем - подгоняют решение под тест и вуа-ля, прям юные хакеры. Но без этого поля тоже плохо, ибо при ошибке компиляции или выполнения там возвращаются подробности, а отдельного поля для ошибок в coderunner нет.
Выход: сделать свое поле.
Правка /moodle/question/type/coderunner/classes/grader.php
public function grade(&$output, &$testcase, $isbad = false) {
if ($isbad) {
$testcase->resultinfo = $output;
$outcome = new qtype_coderunner_test_result($testcase, false, 0.0, $output);
} else {
$outcome = $this->grade_known_good($output, $testcase);
}
return $outcome;
}
Правка /moodle/question/type/coderunner/classes/test_result.php
class qtype_coderunner_test_result {
public function __construct($testcase, $iscorrect, $awardedmark, $got) {
if (!property_exists($testcase,"resultinfo")){
if ($iscorrect) $testcase->resultinfo=get_string('correct','question');
else $testcase->resultinfo=get_string('incorrect','question');
}
Теперь можно использовать поле resultinfo, которое будет либо говорить "верно", либо "неверно", либо вываливать портянку с ошибками при их возникновении.