На сайте http://moodle153.edu.ru/ установлена и работает система дистанционного обучения moodle, к которой прикручен плагин автопроверки написанного кода. Т.е. написанные учениками программы проверяются автоматически.
В рамках подготовки к ЕГЭ есть потребность создавать задачи, решение к которым можно бы было сдавать на разных языках программирования. Для этого в плагине есть возможность использовать multilanguage question, в котором изначально предусмотрено 4 языка: c, cpp, java и python3. Поскольку самым популярным для сдачи ЕГЭ языком продолжает оставаться Паскаль, его туда необходимо добавить.
Следует отметить, что в coderunner есть тип вопроса с Паскалем, и он работает. Но для добавления еще одного языка программирования в вопрос multilanguage необходимо добавить программный код, который это делает.
Единственное упоминание в сети нашел тут https://coderunner.org.nz/mod/forum/discuss.php?d=196
У человека до конца не получилось, разработчик ему ответил что можно попробовать сделать и все. Тишина.
Поскольку на сервер проверки установлен Debian, компилятор там fpc. Проблема в том, что он выдает много лишней информации. Пример вывода
Free Pascal Compiler version 3.0.0+dfsg-11+deb9u1 [2017/06/10] for x86_64
Copyright (c) 1993-2015 by Florian Klaempfl and others
Target OS: Linux for x86-64
Compiling p.pas
Linking p
/usr/bin/ld.bfd: warning: link.res contains output sections; did you forget -T?
6 lines compiled, 0.2 sec
Из-за строки /usr/bin/ld.bfd: warning: link.res contains output sections; did you forget -T? и не выходит правильно компиляция. На сайте fpc говорят, что избавились от этой проблемы в версии 3.1.1. Но на сайте есть только 3.0.4. Из репозиториев вообще стоит 3.0.0 В общем, как обойти эту проблему в fpc я не нашел.
Второй кандидат – PascalABC.
Установил по автоматическому способу вот отсюда http://pascalabc.net/wiki/index.php?title=Какинсталлировать_PascalABC.NETпод_Linux
Получаем компилятор pabcnetcclear, который тоже выдает лишнюю информацию. Это фраза “ОК”. Но с этим можно бороться.
При создании нового вопроса multilanguage надо поставить галочку customize и изменить код
"""The template for a "write a program" question type that accepts answers in C, C++, PascalABC, Java or Python3 according to the value in the language select dropdown menu. """ import subprocess import re student_answer = """{{ STUDENT_ANSWER | e('py') }}""" language = """{{ ANSWER_LANGUAGE | e('py') }}""".lower() language_extension_map = {'c':'c', 'cpp':'cpp', 'pascal':'pas', 'java':'java', 'python3':'py'} if language not in language_extension_map.keys(): raise Exception('Error in question. Unknown/unexpected language ({})'.format(language)) if language == 'java': # Need to determine public class name in order to name output file. Sigh. # The best I can be bothered to do is to use a regular expression match. match = re.search(r'public\s+class\s+([_a-zA-Z][_a-zA-Z0-9]*)', student_answer, re.DOTALL | re.MULTILINE) if match is None: raise Exception("Unable to determine class name. Does the file include 'public class name'?") classname = match.group(1) filename = classname + '.java' else: filename = 'tester.' + language_extension_map[language] Write the student code to a file with open(filename, "w") as src: print(student_answer, file=src) Compile C, C++ and Java if language == 'c': cflags = "-std=c99 -Wall -Werror" return_code = subprocess.call("gcc {0} -o tester tester.c".format(cflags).split()) if return_code != 0: raise Exception("** Compilation failed. Testing aborted ") exec_command = ["./tester"] elif language == 'cpp': cppflags = "-Wall -Werror" return_code = subprocess.call("g++ {0} -o tester tester.cpp".format(cppflags).split()) if return_code != 0: raise Exception(" Compilation failed. Testing aborted ") exec_command = ["./tester"] elif language == 'pascal': return_code = subprocess.check_output("pabcnetcclear tester.pas".split()) if return_code != b'OK\n': raise Exception(" Compilation failed. Testing aborted ") exec_command = ["mono", "./tester.exe"] elif language == 'java': return_code = subprocess.call(['javac', "-J-Xss64m", "-J-Xmx4g", filename]) if return_code != 0: raise Exception(" Compilation failed. Testing aborted **") exec_command = ["java", "-Xss16m", "-Xmx500m", classname] else: # Python doesn't need a compile phase exec_command = ["python3", "./tester.py"] Now run the code. Since this is a per-test template, stdin is already set up for the stdin text specified in the test case, so we can run the compiled program directly. try: output = subprocess.check_output(exec_command, universal_newlines=True) print(output) except subprocess.CalledProcessError as e: if e.returncode > 0: # Ignore non-zero positive return codes if e.output: print(e.output) else: # But negative return codes are signals - abort if e.output: print(e.output, file=sys.stderr) if e.returncode < 0: print("Task failed with signal", -e.returncode, file=sys.stderr) print("** Further testing aborted **", file=sys.stderr)
Добавлен фрагмент
elif language == 'pascal':
return_code = subprocess.check_output("pabcnetcclear tester.pas".split())
if return_code != b'OK\n':
raise Exception(" Compilation failed. Testing aborted ") exec_command = ["mono", "./tester.exe"]
Вместо subprocess.call используем subprocess.check_output – это совет разработчика. И сверяем результат со строкой “ОК”. Из минусов – теперь ошибки компиляции не будут показаны. Будет просто одна общая ошибка на все.
Чтобы в выпадающем меню появился пункт про паскаль, в настройках вопроса в разделе Advanced customisation в Ace language вписать c,cpp,pascal,java,python3
Чтобы не делать это каждый раз для новых заданий, я поменял прототип задания multilanguage.
Хотелось бы еще понять как заставить работать fpc, ведь если делать обычное задание конкретно на Паскаль, там все работает.
День добрый!
Андрей, как Вы реализовали проверку задач с рандомными числами и задачи на файловый ввод-вывод?
Созданием собственных прототипов. Реализовано с помощью python. Тут в двух словах не объяснишь.
Уже вышел fpc 3.2 и на сайте есть скачивание. Установить и настроить не пробовали?
Действительно, вышел пару месяцев назад. Спасибо за информацию.
Установить не пытался, пока работает на устраивающем меня уровне.