Mercurial > ~astiob > upreckon > hgweb
diff 2.00/problem.py @ 39:2b459f9743b4
Test groups are now supported
author | Oleg Oshmyan <chortos@inbox.lv> |
---|---|
date | Fri, 03 Dec 2010 02:46:06 +0000 |
parents | 5bbb68833868 |
children |
line wrap: on
line diff
--- a/2.00/problem.py Fri Dec 03 02:45:56 2010 +0000 +++ b/2.00/problem.py Fri Dec 03 02:46:06 2010 +0000 @@ -30,7 +30,7 @@ signalnames[value] = name del unixnames -__all__ = 'Problem', +__all__ = 'Problem', 'TestContext', 'test_context_end', 'TestGroup' def strerror(e): s = getattr(e, 'strerror') @@ -41,6 +41,49 @@ def __init__(self, mydict): self.__dict__ = mydict +class TestContext(object): + pass + +test_context_end = object() + +class TestGroup(TestContext): + __slots__ = 'case', 'log', 'correct', 'allcorrect', 'real', 'max', 'ntotal', 'nvalued', 'ncorrect', 'ncorrectvalued' + + def __init__(self): + self.real = self.max = self.ntotal = self.nvalued = self.ncorrect = self.ncorrectvalued = 0 + self.allcorrect = True + self.log = [] + + def case_start(self, case): + self.case = case + self.correct = False + self.ntotal += 1 + self.max += case.points + if case.points: + self.nvalued += 1 + + def case_correct(self): + self.correct = True + self.ncorrect += 1 + if self.case.points: + self.ncorrectvalued += 1 + + def case_end(self, granted): + self.log.append((self.case, self.correct, granted)) + self.real += granted + del self.case + if not self.correct: + self.allcorrect = False + + def end(self): + say('Group total: %d/%d tests; %d/%d points' % (self.ncorrect, self.ntotal, self.real if self.allcorrect else 0, self.max)) + # No real need to flush stdout, as it will anyway be flushed in a moment, + # when either the problem total or the next test case's ID is printed + if self.allcorrect: + return self.log + else: + return ((case, correct, 0) for case, correct, granted in self.log) + class Problem(object): __slots__ = 'name', 'config', 'cache', 'testcases' @@ -51,7 +94,7 @@ prob.name = name 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.cache = Cache({'padoutput': 0}) prob.testcases = testcases.load_problem(prob) # TODO @@ -61,11 +104,19 @@ def test(prob): case = None try: - real = max = ntotal = nvalued = ncorrect = ncorrectvalued = 0 + contexts = [TestGroup()] for case in prob.testcases: - ntotal += 1 - max += case.points - if case.points: nvalued += 1 + if case is test_context_end: + for case, correct, granted in contexts.pop().end(): + contexts[-1].case_start(case) + if correct: + contexts[-1].case_correct() + contexts[-1].case_end(granted) + continue + elif isinstance(case, TestContext): + contexts.append(case) + continue + contexts[-1].case_start(case) granted = 0 id = str(case.id) if case.isdummy: @@ -110,15 +161,15 @@ #except Exception: # verdict = 'unknown error [this may be a bug in test.py]%s' % strerror(sys.exc_info()[1]) else: - if hasattr(granted, '__iter__'): + try: granted, comment = granted + except TypeError: + comment = '' + else: if comment: comment = ' (%s)' % comment - else: - comment = '' if granted >= 1: - ncorrect += 1 - if case.points: ncorrectvalued += 1 + contexts[-1].case_correct() verdict = 'OK' + comment elif not granted: verdict = 'wrong answer' + comment @@ -126,12 +177,13 @@ verdict = 'partly correct' + comment granted *= case.points say('%g/%g, %s' % (granted, case.points, verdict)) - real += granted - weighted = real * prob.config.taskweight / max if max else 0 - if nvalued != ntotal: - say('Problem total: %d/%d tests (%d/%d valued); %g/%g points; weighted score: %g/%g' % (ncorrect, ntotal, ncorrectvalued, nvalued, real, max, weighted, prob.config.taskweight)) + contexts[-1].case_end(granted) + weighted = contexts[0].real * prob.config.taskweight / contexts[0].max if contexts[0].max else 0 + if contexts[0].nvalued != contexts[0].ntotal: + say('Problem total: %d/%d tests (%d/%d valued); %g/%g points; weighted score: %g/%g' % (contexts[0].ncorrect, contexts[0].ntotal, contexts[0].ncorrectvalued, contexts[0].nvalued, contexts[0].real, contexts[0].max, weighted, prob.config.taskweight)) else: - say('Problem total: %d/%d tests; %g/%g points; weighted score: %g/%g' % (ncorrect, ntotal, real, max, weighted, prob.config.taskweight)) + say('Problem total: %d/%d tests; %g/%g points; weighted score: %g/%g' % (contexts[0].ncorrect, contexts[0].ntotal, contexts[0].real, contexts[0].max, weighted, prob.config.taskweight)) + sys.stdout.flush() return weighted, prob.config.taskweight finally: if options.erase and (not prob.config.stdio or case and case.validator):