add cpp checker

This commit is contained in:
cuom1999 2020-03-17 20:41:09 -06:00
parent f74f8b6e05
commit e820697e60
6 changed files with 2859 additions and 8 deletions

File diff suppressed because it is too large Load diff

View file

@ -29,8 +29,8 @@ CHECKERS = (
('sorted', _('Unordered')), ('sorted', _('Unordered')),
('identical', _('Byte identical')), ('identical', _('Byte identical')),
('linecount', _('Line-by-line')), ('linecount', _('Line-by-line')),
('custom', _('Custom checker')), ('custom', _('Custom checker (PY)')),
('customval', _('Custom Validator')), ('customval', _('Custom validator (CPP)')),
) )

View file

@ -1,6 +1,7 @@
import json import json
import os import os
import re import re
import shutil
import yaml import yaml
from django.conf import settings from django.conf import settings
@ -9,6 +10,10 @@ from django.core.files.storage import FileSystemStorage
from django.urls import reverse from django.urls import reverse
from django.utils.translation import gettext as _ from django.utils.translation import gettext as _
VALIDATOR_TEMPLATE_PATH = 'validator_template/template.py'
if os.altsep: if os.altsep:
def split_path_first(path, repath=re.compile('[%s]' % re.escape(os.sep + os.altsep))): def split_path_first(path, repath=re.compile('[%s]' % re.escape(os.sep + os.altsep))):
return repath.split(path, 1) return repath.split(path, 1)
@ -63,17 +68,38 @@ class ProblemDataCompiler(object):
raise ProblemDataError(_('Empty batches not allowed.')) raise ProblemDataError(_('Empty batches not allowed.'))
cases.append(batch) cases.append(batch)
def make_checker_for_validator(case):
checker_name = "cppvalidator.py"
validator_path = split_path_first(case.custom_validator.name)
if len(validator_path) != 2:
raise ProblemDataError(_('How did you corrupt the custom checker path?'))
checker = os.path.join(settings.DMOJ_PROBLEM_DATA_ROOT,
validator_path[0],
checker_name)
validator_name = validator_path[1]
shutil.copy(VALIDATOR_TEMPLATE_PATH, checker)
# replace {{filecpp}} and {{problemid}} in checker file
filedata = open(checker, 'r').read()
filedata = filedata.replace('{{filecpp}}', "\'%s\'" % validator_name)
filedata = filedata.replace('{{problemid}}', "\'%s\'" % validator_path[0])
open(checker, 'w').write(filedata)
return checker_name
def make_checker(case): def make_checker(case):
if (case.checker == 'custom'): if (case.checker == 'custom'):
custom_checker_path = split_path_first(case.custom_checker.name) custom_checker_path = split_path_first(case.custom_checker.name)
if len(custom_checker_path) != 2: if len(custom_checker_path) != 2:
raise ProblemDataError(_('How did you corrupt the custom checker path?')) raise ProblemDataError(_('How did you corrupt the custom checker path?'))
return(custom_checker_path[1]) return(custom_checker_path[1])
if (case.checker == 'customval'): if (case.checker == 'customval'):
validator_path = split_path_first(case.custom_validator.name) return make_checker_for_validator(case)
if len(validator_path) != 2:
raise ProblemDataError(_('How did you corrupt the custom checker path?'))
return(validator_path[1])
if case.checker_args: if case.checker_args:
return { return {
'name': case.checker, 'name': case.checker,

View file

@ -218,8 +218,8 @@ header {
} }
#nav-shadow { #nav-shadow {
height: 1px; height: 2px;
background: linear-gradient(rgba(0, 0, 0, 0.5), transparent); background: linear-gradient($widget_black, transparent);
} }
#nav-container { #nav-container {

View file

@ -117,12 +117,18 @@
<td colspan="5"> <td colspan="5">
<div class="case-info"> <div class="case-info">
{% set curr_data = cases_data[case.case] %} {% set curr_data = cases_data[case.case] %}
{% if curr_data != null %}
<strong>{{ _('Input:') }}</strong> <strong>{{ _('Input:') }}</strong>
<pre class="case-output">{{ curr_data['input']|linebreaksbr }}</pre> <pre class="case-output">{{ curr_data['input']|linebreaksbr }}</pre>
{% endif %}
<strong>{{ _('Output:') }}</strong> <strong>{{ _('Output:') }}</strong>
<pre class="case-output">{{ case.output|linebreaksbr }}</pre> <pre class="case-output">{{ case.output|linebreaksbr }}</pre>
{% if curr_data != null %}
<strong>{{ _('Answer:') }}</strong> <strong>{{ _('Answer:') }}</strong>
<pre class="case-output">{{ curr_data['answer']|linebreaksbr }}</pre> <pre class="case-output">{{ curr_data['answer']|linebreaksbr }}</pre>
{% endif %}
{% if case.extended_feedback or case.feedback %} {% if case.extended_feedback or case.feedback %}
<strong>{{ _('Judge feedback:') }}</strong> <strong>{{ _('Judge feedback:') }}</strong>

View file

@ -0,0 +1,50 @@
import os
import subprocess
from dmoj.contrib import contrib_modules
from dmoj.error import InternalError
from dmoj.judgeenv import env, get_problem_root
from dmoj.result import CheckerResult
from dmoj.utils.helper_files import compile_with_auxiliary_files, mktemp
from dmoj.utils.unicode import utf8text
executor = None
def get_executor(files, lang, compiler_time_limit, problem_id):
global executor
if executor is None:
if not isinstance(files, list):
files = [files]
filenames = [os.path.join(get_problem_root(problem_id), f) for f in files]
executor = compile_with_auxiliary_files(filenames, lang, compiler_time_limit)
return executor
def check(process_output, judge_output, judge_input,
problem_id={{problemid}},
files={{filecpp}},
lang='CPP14',
time_limit=10,
memory_limit=1024**2,
compiler_time_limit=10,
feedback=True, type='default',
point_value=None, **kwargs) -> CheckerResult:
executor = get_executor(files, lang, compiler_time_limit, problem_id)
if type not in contrib_modules:
raise InternalError('%s is not a valid return code parser' % type)
with mktemp(judge_input) as input_file, mktemp(process_output) as output_file, mktemp(judge_output) as judge_file:
process = executor.launch(input_file.name, output_file.name, judge_file.name, stdout=subprocess.PIPE,
stderr=subprocess.PIPE, memory=memory_limit, time=time_limit)
proc_output, error = map(utf8text, process.communicate())
return contrib_modules[type].ContribModule.parse_return_code(process, executor, point_value, time_limit,
memory_limit,
feedback=utf8text(proc_output)
if feedback else None, name='checker',
stderr=error)