Mercurial > ~astiob > upreckon > hgweb
diff 2.00/problem.py @ 21:ec6f1a132109
A pretty usable version
Test groups and testconfs in non-ZIP archives or ZIP archives with comments are not yet supported.
author | Oleg Oshmyan <chortos@inbox.lv> |
---|---|
date | Fri, 06 Aug 2010 15:39:29 +0000 |
parents | f2279b7602d3 |
children | f07b7a431ea6 |
line wrap: on
line diff
--- a/2.00/problem.py Mon Jun 14 21:02:06 2010 +0000 +++ b/2.00/problem.py Fri Aug 06 15:39:29 2010 +0000 @@ -1,14 +1,44 @@ -#!/usr/bin/python +#! /usr/bin/env python # Copyright (c) 2010 Chortos-2 <chortos@inbox.lv> +from __future__ import division, with_statement + +try: + from compat import * + import config, testcases +except ImportError: + import __main__ + __main__.import_error(sys.exc_info()[1]) +else: + from __main__ import clock + +import sys, re + try: - import config as _config, testcases as _testcases -except ImportError as e: - import __main__ - __main__.import_error(e) + import signal +except ImportError: + signalnames = () +else: + # Construct a cache of all signal names available on the current + # platform. Prefer names from the UNIX standards over other versions. + unixnames = frozenset(('HUP', 'INT', 'QUIT', 'ILL', 'ABRT', 'FPE', 'KILL', 'SEGV', 'PIPE', 'ALRM', 'TERM', 'USR1', 'USR2', 'CHLD', 'CONT', 'STOP', 'TSTP', 'TTIN', 'TTOU', 'BUS', 'POLL', 'PROF', 'SYS', 'TRAP', 'URG', 'VTALRM', 'XCPU', 'XFSZ')) + signalnames = {} + for name in dir(signal): + if re.match('SIG[A-Z]+$', name): + value = signal.__dict__[name] + if isinstance(value, int) and (value not in signalnames or signalnames[value][3:] not in unixnames): + signalnames[value] = name + del unixnames +__all__ = 'Problem', + +# This should no more be needed; pass all work on to the TestCase inheritance tree # LIBRARY and STDIO refer to interactive aka reactive problems -BATCH, OUTONLY, LIBRARY, STDIO, BESTOUT = xrange(5) +#BATCH, OUTONLY, LIBRARY, STDIO, BESTOUT = xrange(5) + +class Cache(object): + def __init__(self, mydict): + self.__dict__ = mydict class Problem(object): __slots__ = 'name', 'config', 'cache', 'testcases' @@ -16,16 +46,111 @@ def __init__(prob, name): if not isinstance(name, basestring): # This shouldn't happen, of course - raise TypeError, "Problem() argument 1 must be string, not " + str(type(name)).split('\'')[1] + raise TypeError('Problem() argument 1 must be string, not ' + type(name).__name__) prob.name = name - prob.config = _config.load_problem(name) - prob.cache = type('Cache', (object,), {'padoutputtolength': 0})() - prob.testcases = _testcases.load_problem(prob) + prob.config = config.load_problem(name) + if not getattr(prob.config, 'kind', None): prob.config.kind = 'batch' + prob.cache = Cache({'padoutput': 0, 'usegroups': False}) + prob.testcases = testcases.load_problem(prob) + + # TODO + def build(prob): + raise NotImplementedError def test(prob): - real = max = 0 + real = max = ntotal = nvalued = ncorrect = ncorrectvalued = 0 for case in prob.testcases: - r, m = case() - real += r - max += m - return real, max \ No newline at end of file + ntotal += 1 + max += case.points + if case.points: nvalued += 1 + granted = 0 + id = str(case.id) + if case.isdummy: + id = 'sample ' + id + say('%*s: ' % (prob.cache.padoutput, id), end='') + sys.stdout.flush() + try: + granted = case() + except KeyboardInterrupt: + if not hasattr(case, 'time_stopped'): + # Too quick! The testing has not even started! + raise + verdict = 'canceled by the user' + except testcases.TimeLimitExceeded: + verdict = 'time limit exceeded' + except testcases.WrongAnswer: + e = sys.exc_info()[1] + if e.comment: + verdict = 'wrong answer (%s)' % e.comment + else: + verdict = 'wrong answer' + except testcases.NonZeroExitCode: + e = sys.exc_info()[1] + if e.exitcode < 0: + if sys.platform == 'win32': + verdict = 'terminated with error 0x%X' % (e.exitcode + 0x100000000) + elif -e.exitcode in signalnames: + verdict = 'terminated by signal %d (%s)' % (-e.exitcode, signalnames[-e.exitcode]) + else: + verdict = 'terminated by signal %d' % -e.exitcode + else: + verdict = 'non-zero return code %d' % e.exitcode + except testcases.CannotStartTestee: + e = sys.exc_info()[1] + if e.upstream.strerror: + verdict = 'cannot launch the program to test (%s)' % e.upstream.strerror.lower() + else: + verdict = 'cannot launch the program to test' + except testcases.CannotStartValidator: + e = sys.exc_info()[1] + if e.upstream.strerror: + verdict = 'cannot launch the validator (%s)' % e.upstream.strerror.lower() + else: + verdict = 'cannot launch the validator' + except testcases.CannotReadOutputFile: + e = sys.exc_info()[1] + if e.upstream.strerror: + verdict = 'cannot read the output file (%s)' % e.upstream.strerror.lower() + else: + verdict = 'cannot read the output file' + except testcases.CannotReadInputFile: + e = sys.exc_info()[1] + if e.upstream.strerror: + verdict = 'cannot read the input file (%s)' % e.upstream.strerror.lower() + else: + verdict = 'cannot read the input file' + except testcases.CannotReadAnswerFile: + e = sys.exc_info()[1] + if e.upstream.strerror: + verdict = 'cannot read the reference output file (%s)' % e.upstream.strerror.lower() + else: + verdict = 'cannot read the reference output file' + except testcases.TestCaseNotPassed: + e = sys.exc_info()[1] + verdict = 'unspecified reason [this may be a bug in test.py] (%s)' % e + #except Exception: + # e = sys.exc_info()[1] + # verdict = 'unknown error [this may be a bug in test.py] (%s)' % e + else: + if hasattr(granted, '__iter__'): + granted, comment = granted + if comment: + comment = ' (%s)' % comment + else: + comment = '' + if granted == case.points: + ncorrect += 1 + if granted: ncorrectvalued += 1 + verdict = 'OK' + comment + elif not granted: + verdict = 'wrong answer' + comment + else: + verdict = 'partly correct' + comment + say('%.3f%s s, %g/%g, %s' % (case.time_stopped - case.time_started, case.time_limit_string, granted, case.points, verdict)) + real += granted + weighted = real * prob.config.taskweight / max if max else 0 + if nvalued != ntotal: + say('Grand total: %d/%d tests (%d/%d valued); %g/%g points; weighted score: %g/%g' % (ncorrect, ntotal, ncorrectvalued, nvalued, real, max, weighted, prob.config.taskweight)) + else: + say('Grand total: %d/%d tests; %g/%g points; weighted score: %g/%g' % (ncorrect, ntotal, real, max, weighted, prob.config.taskweight)) + return weighted, prob.config.taskweight