class CppChecker(Checker): def __init__(self, source): """ Args: source (FilePath) """ self._source = source self._compiler = CppCompiler(['-I"%s"' % source.directory()]) self._binary_path = FilePath(source.directory(), 'checker') def __call__(self, in_path, expected_path, out_path): """Run checker to evaluate outcome. Parameters correspond to convention for checker in cms. Args: in_path (FilePath) expected_path (FilePath) out_path (FilePath) """ assert in_path.exists() assert expected_path.exists() assert out_path.exists() if self._binary_path.mtime() < self._source.mtime(): if not self.build(): return (False, 0.0, "Failed to build checker") complete = subprocess.run([ str(self._binary_path), str(in_path), str(expected_path), str(out_path) ], universal_newlines=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) ret = complete.returncode st = ret == 0 if st: outcome = float(complete.stdout) msg = complete.stderr else: stderr = complete.stderr.strip('\n') outcome = 0.0 if stderr and len(stderr) < 75: msg = stderr else: if ret < 0: sig = -ret msg = 'Execution killed with signal %d' % sig if sig in SIGNALS: msg += ': %s' % SIGNALS[sig] else: msg = 'Execution ended with error (return code %d)' % ret return (st, outcome, msg) def build(self): """Build source of the checker Returns: bool: True if compilation is successful. False otherwise """ return self._compiler(self._source, self._binary_path)
def compress(self, in_ext=None, sol_ext=None): """Compress all test cases in this dataset in a single zip file. The basename of the corresponding subtask subdirectory is prepended to each file. """ in_ext = in_ext or self._in_ext sol_ext = sol_ext or self._sol_ext dst_file = FilePath(self._directory, 'data.zip') if dst_file.exists() and dst_file.mtime() >= self.mtime(): return True tmpdir = Directory.tmpdir() try: copied = 0 for subtask in self._subtasks: copied += subtask.copy_to(tmpdir) if not copied: # ui.show_message("Warning", "no files in dataset", ui.WARNING) return True cmd = 'cd %s && zip data.zip *%s *%s' % (tmpdir, in_ext, sol_ext) st = subprocess.call(cmd, stdout=subprocess.DEVNULL, shell=True) FilePath(tmpdir, 'data.zip').copy(dst_file) finally: tmpdir.rmtree() return st == 0
def compress(self, in_ext=None, sol_ext=None, random_sort=False): """Compress all test cases in this dataset in a single zip file. The basename of the corresponding subtask subdirectory is prepended to each file. """ in_ext = in_ext or self._in_ext sol_ext = sol_ext or self._sol_ext dst_file = FilePath(self._directory, 'data.zip') if dst_file.exists() and dst_file.mtime() >= self.mtime(): return True tmpdir = Directory.tmpdir() try: copied = 0 for subtask in self._subtasks: copied += subtask.copy_to(tmpdir, random_sort=random_sort) if not copied: # ui.show_message("Warning", "no files in dataset", ui.WARNING) return True cmd = 'cd %s && zip data.zip *%s *%s' % (tmpdir, in_ext, sol_ext) st = subprocess.call(cmd, stdout=subprocess.DEVNULL, shell=True) FilePath(tmpdir, 'data.zip').copy(dst_file) finally: tmpdir.rmtree() return st == 0
class CppChecker(Checker): def __init__(self, source): """ Args: source (FilePath) """ self._source = source self._compiler = CppCompiler(['-I"%s"' % source.directory()]) self._binary_path = FilePath(source.directory(), 'checker') def __call__(self, in_path, expected_path, out_path): """Run checker to evaluate outcome. Parameters correspond to convention for checker in cms. Args: in_path (FilePath) expected_path (FilePath) out_path (FilePath) """ assert in_path.exists() assert expected_path.exists() assert out_path.exists() if self._binary_path.mtime() < self._source.mtime(): if not self.build(): return (False, 0.0, "Failed to build checker") complete = subprocess.run( [str(self._binary_path), str(in_path), str(expected_path), str(out_path)], universal_newlines=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) ret = complete.returncode st = ret == 0 if st: outcome = float(complete.stdout) msg = complete.stderr else: stderr = complete.stderr.strip('\n') outcome = 0.0 if stderr and len(stderr) < 75: msg = stderr else: if ret < 0: sig = -ret msg = 'Execution killed with signal %d' % sig if sig in SIGNALS: msg += ': %s' % SIGNALS[sig] else: msg = 'Execution ended with error (return code %d)' % ret return (st, outcome, msg) def build(self): """Build source of the checker Returns: bool: True if compilation is successful. False otherwise """ return self._compiler(self._source, self._binary_path)
def build_validator(self, source): fp = FilePath(self._directory, source) if not fp.exists(): return (None, 'File does not exists.') if fp.ext == '.cpp': binary = fp.chext('.bin') if binary.mtime() < fp.mtime() and not self._cpp_compiler(fp, binary): return (None, 'Failed to build validator.') return (Runnable(binary), 'OK') if fp.ext in ['.py', '.py3']: return (Runnable('python3', [str(source)]), 'OK') if fp.ext == '.py2': return (Runnable('python2', [str(source)]), 'OK') return (None, 'Not supported source file.')
def build_validator(self, source): fp = FilePath(self._directory, source) if not fp.exists(): return (None, 'File does not exists.') if fp.ext == '.cpp': binary = fp.chext('.bin') if binary.mtime() < fp.mtime() and not self._cpp_compiler( fp, binary): return (None, 'Failed to build validator.') return (Runnable(binary), 'OK') if fp.ext in ['.py', '.py3']: return (Runnable('python3', [str(source)]), 'OK') if fp.ext == '.py2': return (Runnable('python2', [str(source)]), 'OK') return (None, 'Not supported source file.')
class Statement: """Represents a statement. A statement is formed by a latex source and a pdf file. """ def __init__(self, directory, num=None, codename=None): """ Args: directory (Directory): Directory to search for statement source file. num (int): Number of the statement in the contest starting from 0 """ assert FilePath(directory, 'statement.tex').exists() self._source = FilePath(directory, 'statement.tex') self._pdf = self._source.chext('.pdf') self._compiler = LatexCompiler() self._directory = directory self._num = num self._codename = codename @property def pdf(self): """Returns path to pdf file and compiles it if necessary. Returns: Optional[FilePath]: The file path if the binary is present or None if the pdf file cannot be generated. """ if self._pdf.mtime() < self._source.mtime(): (st, _msg) = self.build() if not st: return None return self._pdf def __str__(self): return str(self._source) @ui.work('PDF') def build(self, blank_page=False): """Compile statement latex source Args: blank_page (Optional[bool]) if true adds a blank page at the end of the problem. Returns: (bool, msg) a tuple containing status code and result message. """ if self._num is not None: os.environ['OCIMATIC_PROBLEM_NUMBER'] = chr(ord('A') + self._num) if self._codename: os.environ['OCIMATIC_CODENAME'] = self._codename if blank_page: os.environ['OCIMATIC_BLANK_PAGE'] = 'True' st = self._compiler(self._source) return (st, 'OK' if st else 'FAILED') def io_samples(self): """Find sample input data in the satement Returns: List[FilePath]: list of paths """ latex_file = self._source.open('r') samples = set() for line in latex_file: m = re.match(r'[^%]*\\sampleIO(\[[^\]]*\]){0,2}{([^}]+)}', line) if m: samples.add(m.group(2)) latex_file.close() return [FilePath(self._directory, s) for s in samples]