formatting of execises
This commit is contained in:
@ -1,6 +1,6 @@
|
||||
import functools
|
||||
import multiprocessing
|
||||
from typing import Callable, Iterator
|
||||
from typing import Callable, Iterable, Iterator
|
||||
|
||||
|
||||
class TimeoutException(Exception):
|
||||
@ -43,7 +43,7 @@ def run_tests_for_task(task: type) -> None:
|
||||
run_tests_for_task(task)
|
||||
|
||||
|
||||
def points_to_detuct(e: type | Callable) -> int:
|
||||
def points_to_deduct(e: type | Callable) -> int:
|
||||
match e:
|
||||
case type() if hasattr(e, 'is_task'):
|
||||
to_detuct = 0
|
||||
@ -51,7 +51,7 @@ def points_to_detuct(e: type | Callable) -> int:
|
||||
if hasattr(test, 'is_test'):
|
||||
to_detuct += test.to_deduct()
|
||||
for task in e.tasks:
|
||||
to_detuct += points_to_detuct(task)
|
||||
to_detuct += points_to_deduct(task)
|
||||
return e.max_points if to_detuct > e.max_points else to_detuct
|
||||
case Callable(test):
|
||||
return test.to_detuct()
|
||||
@ -76,6 +76,23 @@ class Exercise(object):
|
||||
self.run_tests()
|
||||
self.deduct_points()
|
||||
|
||||
@property
|
||||
def id(self) -> str:
|
||||
return self.__id
|
||||
|
||||
@property
|
||||
def max_points(self) -> float:
|
||||
return self.__max_points
|
||||
|
||||
@property
|
||||
def points(self) -> float:
|
||||
return self.__points
|
||||
|
||||
@property
|
||||
def tasks(self) -> Iterable[object]:
|
||||
return self.__tasks
|
||||
|
||||
|
||||
|
||||
def run_tests(self):
|
||||
for task in self.__tasks:
|
||||
@ -83,7 +100,7 @@ class Exercise(object):
|
||||
|
||||
def deduct_points(self):
|
||||
for task in self.__tasks:
|
||||
to_detuct = points_to_detuct(task)
|
||||
to_detuct = points_to_deduct(task)
|
||||
task.points = 0 if to_detuct > task.max_points else task.max_points - to_detuct
|
||||
self.__points = functools.reduce(
|
||||
lambda a, b: a + b, map(lambda t: t.points, self.__tasks), 0.0)
|
||||
|
@ -1,5 +1,5 @@
|
||||
def is_prime(n: int) -> bool:
|
||||
if n < 2:
|
||||
if n <= 2:
|
||||
return False
|
||||
|
||||
for i in range(2, n // 2 + 1):
|
||||
|
@ -1,4 +1,4 @@
|
||||
from utils import has_annotation_callable
|
||||
from utils import has_annotation_callable, format
|
||||
from testing import eip_task, eip_test, Exercise
|
||||
|
||||
PRIMES = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37,
|
||||
@ -11,7 +11,7 @@ MAX = 100
|
||||
primes_exercise = Exercise("primes")
|
||||
|
||||
|
||||
@eip_task("`is_prime`", 4, primes_exercise)
|
||||
@eip_task("a) `is_prime`", 4, primes_exercise)
|
||||
class IsPrime:
|
||||
|
||||
@eip_test("`is_prime` nicht implementiert", 4)
|
||||
@ -36,7 +36,7 @@ class IsPrime:
|
||||
has_annotation_callable(is_prime, [int], bool)
|
||||
|
||||
|
||||
@eip_task("`next_prime`", 6, primes_exercise)
|
||||
@eip_task("b) `next_prime`", 6, primes_exercise)
|
||||
class NextPrime:
|
||||
|
||||
@eip_test("`next_prime` nicht implementiert", 6)
|
||||
@ -100,4 +100,4 @@ class PrimeFactorize:
|
||||
|
||||
if __name__ == "__main__":
|
||||
primes_exercise.run()
|
||||
print(f"# exercise ({primes_exercise.get_points():.2g} / {primes_exercise.get_max_points()})")
|
||||
print("\n".join(format(primes_exercise)))
|
||||
|
31
src/utils.py
31
src/utils.py
@ -1,5 +1,9 @@
|
||||
from typing import Any, Callable, TypeAliasType
|
||||
|
||||
from more_itertools import flatten
|
||||
|
||||
from testing import Exercise, points_to_deduct
|
||||
|
||||
def has_annotation_callable(f: Callable, param_types: list[type], return_type: object = None) -> bool:
|
||||
a = f.__annotations__
|
||||
ret = a['return'] if 'return' in a else None
|
||||
@ -32,4 +36,29 @@ def format_callable(f: Callable[..., Any]) -> str:
|
||||
|
||||
|
||||
def assert_annotation_callable(f: Callable[..., Any], param_types: list[type], return_type: object = None):
|
||||
assert has_annotation_callable(f, param_types, return_type), f"{f.__name__}({", ".join(format_type(p) for p in param_types)}) -> {format_type(return_type)} != {format_callable(f)}"
|
||||
assert has_annotation_callable(f, param_types, return_type), f"{f.__name__}({", ".join(format_type(p) for p in param_types)}) -> {format_type(return_type)} != {format_callable(f)}"
|
||||
|
||||
def format(ob: Exercise | object | Callable[..., Any]) -> list[str]:
|
||||
match ob:
|
||||
case Exercise():
|
||||
out = [f"# {ob.id} ({ob.points:.2g} / {ob.max_points:.2g})"]
|
||||
return out + list(flatten(map(format, ob.tasks)))
|
||||
case object() if hasattr(ob, 'is_task'):
|
||||
return format_task("##", ob)
|
||||
case Callable() if hasattr(ob, 'is_test'):
|
||||
return format_test(ob)
|
||||
case _:
|
||||
return []
|
||||
|
||||
def format_test(test: Callable[..., Any]) -> list[str]:
|
||||
if not test.has_failed:
|
||||
return []
|
||||
return [f"- {test.msg} [`-{test.to_deduct():.2g}p`]"]
|
||||
|
||||
def format_task(prefix: str, task: object) -> list[str]:
|
||||
out = [f"{prefix} {task.header} - ({(task.max_points - points_to_deduct(task)):.2g} / {task.max_points:.2g})"]
|
||||
for t in task.tasks:
|
||||
out += format_task(prefix + "#", t)
|
||||
for t in task.tests:
|
||||
out += format_test(t)
|
||||
return out
|
Reference in New Issue
Block a user