def get_graders(task: IOITask): """ Get the paths of all the graders/stubs according to the task type. """ if task.task_type == TaskType.Communication: return list_files(["sol/stub.*"]) else: return list_files(["sol/grader.*"])
def check_att_folder(task: IOITask, solutions: List[Solution], interface: IOIUIInterface): """ Check if the following files are present: - grader.* for all the languages which have a solution - task_name.* for all the languages above - task_name.inputX.txt / task_name.outputX.txt / inputX.txt / outputX.txt making sure that they are symlinks """ languages = _get_languages(solutions) _check_graders("att/", languages, solutions, interface) if _has_grader(solutions): for language in languages: if not os.path.exists("att/{}{}".format( task.name, language.source_extension)): interface.add_warning("Missing {}{} in att/ folder".format( task.name, language.source_extension)) sample_files = list_files([ "att/input*.txt", "att/output*.txt", "att/{}.input*.txt".format(task.name), "att/{}.output*.txt".format(task.name) ]) for sample in sample_files: if not os.path.islink(sample): interface.add_warning( "Sample file {} is not a symlink".format(sample)) if len(sample_files): interface.add_warning("No sample files provided")
def get_official_solution() -> Optional[str]: """ Get the first solution that matches sol/solution.* or sol/soluzione.* If no solution is found None is returned. """ for sol in list_files(["sol/solution.*", "sol/soluzione.*"]): return sol return None
def get_validator() -> Optional[str]: """ Get the first validator that matches gen/validator.* or gen/valida.* If no validator is found None is returned. """ for validator in list_files(["gen/validator.*", "gen/valida.*"]): return validator return None
def get_generator() -> Optional[str]: """ Get the first generator that matches gen/generator.* or gen/generatore.* If no generator is found None is returned. """ for generator in list_files(["gen/generator.*", "gen/generatore.*"]): return generator return None
def get_manager() -> Optional[str]: """ Get the first manager that matches check/manager.* or cor/manager.* If no manager is found None is returned. """ managers = list_files(["check/manager.*", "cor/manager.*"]) if not managers: manager = None elif len(managers) == 1: manager = managers[0] else: raise ValueError("Too many managers in check/cor folder") return manager
def get_checker() -> Optional[str]: """ Get the first checker that matches check/checker.* or cor/correttore.* If no checker is found None is returned. """ checkers = list_files(["check/checker.*", "cor/correttore.*"]) if not checkers: checker = None elif len(checkers) == 1: checker = checkers[0] else: raise ValueError("Too many checkers in check/cor folder") return checker
def check_sol_folder(solutions: List[Solution], interface: IOIUIInterface): """ Check if the following files are present: - grader.* for all the languages which have a solution - solution.* / soluzione.cpp is a symlink """ languages = _get_languages(solutions) _check_graders("sol/", languages, solutions, interface) sols = list_files(["sol/solution.*", "sol/soluzione.*"]) if len(sols) > 1: interface.add_warning("More than one official solution found") for sol in sols: if not os.path.islink(sol): interface.add_warning( "Official solution {} is not a symlink".format(sol))
def compile_statements(pool: ExecutionPool, task: IOITask, interface: IOIUIInterface): """ Create the statement compilation part of the DAG """ tex_files = list_files(["statement/*.tex", "testo/*.tex"], valid_extensions=[".tex"]) for tex_file in tex_files: pdf_file = tex_file.replace(".tex", ".pdf") language = os.path.split(os.path.splitext(tex_file)[0])[1] statement = OIITexStatement(task, os.path.abspath(tex_file)) statement.compile(pool, language) if not pool.config.dry_run: statement.pdf_file.getContentsToFile(pdf_file, True, True) interface.add_statement(statement)
def make_booklet(frontend: Frontend, config: Config, tasks: List[Tuple[str, IOITask]]) -> int: statements = dict() # type: Dict[str, List[OIITexStatement]] for path, task in tasks: config.task_dir = path os.chdir(path) tex_files = list_files(["statement/*.tex", "testo/*.tex"], valid_extensions=[".tex"]) for tex_file in tex_files: lang = os.path.basename(tex_file)[:-4] statement = OIITexStatement(task, os.path.abspath(tex_file)) if lang not in statements: statements[lang] = list() statements[lang].append(statement) if config.ui == UIS.PRINT: printer = StdoutPrinter() else: printer = Printer() ui_printer = UIPrinter(printer, config.ui == UIS.JSON) pool = ExecutionPool(config, frontend, ui_printer) successful_compilations = 0 for lang, texts in statements.items(): file_name = "booklet_%s.pdf" % lang target_file = os.path.join(config.contest_dir, file_name) compilation, pdf_file, deps = OIITexStatement.compile_booklet( pool, texts, lang) if not pool.config.dry_run: pdf_file.getContentsToFile(target_file) def on_done(res: Result): nonlocal successful_compilations if res.status == ResultStatus.SUCCESS or \ res.status == ResultStatus.RETURN_CODE: successful_compilations += 1 compilation.bind(on_done) pool.start() return len(statements) - successful_compilations
def get_manager(manager: str, target_arch: Arch, optional: bool = False) -> Optional[SourceFile]: """ Search for a manager and create the relative SourceFile. `manager` is the base name without the extension (eg. "checker"). If `optional` is set to true and no managers are found, None is returned, otherwise an exception is raised. """ managers = list_files(["managers/%s.*" % manager], exclude=["managers/%s.*.*" % manager]) if len(managers) == 0: if not optional: raise FileNotFoundError("Missing manager: %s" % manager) return None if len(managers) != 1: raise ValueError("Ambiguous manager: " + ", ".join(managers)) return SourceFile.from_file( managers[0], manager, True, "managers/%s%s" % (manager, get_extension(target_arch)), target_arch, {})
def _get_statement_tex(): return list_files(["statement/*.tex", "testo/*.tex"], valid_extensions=[".tex"])
def check_sample_cases(task: IOITask, pool: ExecutionPool, interface: IOIUIInterface): """ Check if the sample cases in the statement are valid and the output is correct """ # Communication tasks does not have output files if task.task_type != TaskType.Batch: return # without official solution we cannot solve the input files if not task.official_solution: return inputs = list_files([ "statement/input*.txt", "statement/{}.input*.txt".format(task.name), "testo/input*.txt", "testo/{}.input*.txt".format(task.name) ], valid_extensions=[".txt"]) outputs = list_files([ "statement/output*.txt", "statement/{}.output*.txt".format(task.name), "testo/output*.txt", "testo/{}.output*.txt".format(task.name) ], valid_extensions=[".txt"]) num_to_input = dict() # type: Dict[int, str] num_to_output = dict() # type: Dict[int, str] num_to_input_file = dict() # type: Dict[int, File] num_to_output_file = dict() # type: Dict[int, File] num_to_sol_output_file = dict() # type: Dict[int, File] num_to_validation = dict() # type: Dict[int, File] for infile in inputs: match = re.match(r".*input(\d+).txt", infile) # invalid sample file format, skip it if not match: continue sample_num = int(match.group(1)) num_to_input[sample_num] = infile num_to_input_file[sample_num] = pool.frontend.provideFile( infile, "Sample input {}".format(infile), False) # skip the validation if there is no default validator if not task.default_val: continue in_files = {VALIDATION_INPUT_NAME: num_to_input_file[sample_num]} validation = Execution("Validation of sample input {}".format(infile), pool, task.default_val.source_file, [VALIDATION_INPUT_NAME, "0"], "sanity-check-validation", {"sample_testcase": sample_num}, inputs=in_files) num_to_validation[sample_num] = validation.stdout _setup_execution_callback( interface, validation, "Validation of sample input {} failed".format(infile)) # if the output files were not yet generated (e.g. when they are just # copied), the solution is not prepared if not task.official_solution.prepared: task.official_solution.prepare(pool) for outfile in outputs: match = re.match(r".*output(\d+).txt", outfile) if not match: continue sample_num = int(match.group(1)) # skip the output if there is no corresponding input if sample_num not in num_to_input: continue num_to_output[sample_num] = outfile num_to_output_file[sample_num] = pool.frontend.provideFile( outfile, "Sample output {}".format(outfile), False) in_files = dict() # if the validator is not present we don't wait for it if sample_num in num_to_validation: in_files["wait_for_validation"] = num_to_validation[sample_num] if task.input_file: in_files[task.input_file] = num_to_input_file[sample_num] stdin = None else: stdin = num_to_input_file[sample_num] out_files = [] if task.output_file: out_files.append(task.output_file) solving = Execution("Solving sample output {}".format(outfile), pool, task.official_solution, [], "sanity-check-solution", {"sample_testcase": sample_num}, inputs=in_files, stdin=stdin, outputs=out_files) if task.output_file: num_to_sol_output_file[sample_num] = solving.output( task.output_file) else: num_to_sol_output_file[sample_num] = solving.stdout _setup_execution_callback( interface, solving, "Solution of sample input {} failed".format( num_to_input[sample_num])) check = get_checker_execution( pool, task, "", -1, sample_num, task.checker, num_to_input_file[sample_num], num_to_output_file[sample_num], num_to_sol_output_file[sample_num], "Checking sample output {}".format(outfile), {"sanity_check": True}) _setup_checker_callback( interface, check, "Checking sample output {} failed".format(outfile), task.checker is not None)