diff --git a/code/algorithms/methods.py b/code/algorithms/methods.py new file mode 100644 index 0000000..eb7a5ce --- /dev/null +++ b/code/algorithms/methods.py @@ -0,0 +1,90 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# IMPORTS +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +import functools; + +from code.core.log import *; +from code.display.display import *; + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# CLASSES +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +class OneShot(object): + state: bool; + def __init__(self): + self.state = True; + + def reload(self): + self.state = True; + + def trigger(self): + self.state = False; + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# DECORATORS +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +## Trigger, der das fancy Zeug bei verschachtelten Algorithmen verhindert +nonnestedAlgorithms = OneShot(); + +def algorithmInfos( + name: str, + checks: bool = True, + metrics: bool = None, + outputnames: Union[str, Tuple[str]] = 'result', + preChecks: Any = None, + postChecks: Any = None +): + ''' + Decorator für Algorthmen, der Folgendes macht: + + - Zeigt vorm Start Console-Messages mit Namen des Algorithmus + Inputs. + - Zeit am Ende optional Metriken (bspw. Zeitkosten). + - Zeigt am Ende Console-Messages von Output/s. + - Prüft optional vor und nach Ausführung des Algorithmus, dass die Inputs/Outputs stimmen. + + Bei rekursiven Definitionen werden die o. s. Punkte nur bei dem äußersten Aufruf gemacht. + ''' + def func_decorator(func): + ## Trigger, der das fancy Zeug bei verschachtelten Aufrufen verhindert + nonnestedRecursion = OneShot(); + @functools.wraps(func) + def func_wrapper(**inputs): + try: + state = nonnestedRecursion.state and nonnestedAlgorithms.state; + if state: + # Initialisierung + DisplayStartOfAlgorithm(name.title(), **inputs); + RestartCounter(); + # Prechecks + if checks and callable(preChecks): + preChecks(**inputs); + # Ausführung des Algorithmus: + nonnestedRecursion.trigger(); + nonnestedAlgorithms.trigger(); + outputs = func(*[], **inputs); + nonnestedAlgorithms.reload(); + nonnestedRecursion.reload(); + if state: + # benenne Outputs: + outputs_ = outputs if isinstance(outputs, tuple) else tuple([outputs]); + outputnames_ = outputnames if isinstance(outputnames, tuple) else tuple([outputnames]); + outputsNamed = { outputnames_[k]: value for k, value in enumerate(outputs_) }; + # Postchecks + if checks and callable(postChecks): + postChecks(**inputs, **outputsNamed); + # Letzte Messages + if metrics: + DisplayMetrics(); + DisplayEndOfAlgorithm(**outputsNamed); + except Exception as e: + _switch.reload(); + raise e; + return outputs; + return func_wrapper; + return func_decorator;