From 6bf15f936ea4aba04f1a8e85a5a72369e34d18c7 Mon Sep 17 00:00:00 2001 From: raj_mathe Date: Fri, 5 Nov 2021 08:50:44 +0100 Subject: [PATCH] master > master: code py - vereinheitlicht mit go projekt --- code/python/src/algorithms/methods.py | 11 +- code/python/src/algorithms/search/binary.py | 2 +- code/python/src/algorithms/search/interpol.py | 2 +- .../src/algorithms/search/ith_smallest.py | 4 +- code/python/src/algorithms/search/jump.py | 4 +- code/python/src/algorithms/search/poison.py | 4 +- .../src/algorithms/search/sequential.py | 2 +- code/python/src/algorithms/sum/maxsubsum.py | 4 +- code/python/src/core/log.py | 16 ++- code/python/src/core/utils.py | 40 +++++++ code/python/src/endpoints/__init__.py | 0 code/python/src/endpoints/exports.py | 11 ++ code/python/src/endpoints/print.py | 29 +++++ code/python/src/endpoints/run.py | 69 ++++++++++++ code/python/src/main.py | 103 ++++++++---------- code/python/src/setup/appconfig.py | 66 +++++++++++ code/python/src/setup/cli.py | 30 ++++- 17 files changed, 313 insertions(+), 84 deletions(-) create mode 100644 code/python/src/core/utils.py create mode 100644 code/python/src/endpoints/__init__.py create mode 100644 code/python/src/endpoints/exports.py create mode 100644 code/python/src/endpoints/print.py create mode 100644 code/python/src/endpoints/run.py create mode 100644 code/python/src/setup/appconfig.py diff --git a/code/python/src/algorithms/methods.py b/code/python/src/algorithms/methods.py index 79c4a0f..1f51e6e 100644 --- a/code/python/src/algorithms/methods.py +++ b/code/python/src/algorithms/methods.py @@ -5,9 +5,10 @@ # IMPORTS # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -import functools; +import functools from src.core.log import *; +from src.setup import appconfig; from src.core.metrics import *; from src.setup.display import *; @@ -38,8 +39,6 @@ nonnestedAlgorithms = OneShot(); def algorithmInfos( name: str, - checks: bool = True, - metrics: bool = None, outputnames: List[str] = ['result'], preChecks: Any = None, postChecks: Any = None @@ -67,7 +66,7 @@ def algorithmInfos( # Initialisierung DisplayStartOfAlgorithm(name, **inputs); # Prechecks - if checks and callable(preChecks): + if appconfig.AppConfigPerformChecks() and callable(preChecks): preChecks(**inputs); # Metriken initialisieren + starten ResetMetrics(); @@ -85,11 +84,11 @@ def algorithmInfos( outputs_ = outputs if isinstance(outputs, tuple) else tuple([outputs]); outputsNamed = { outputnames[k]: value for k, value in enumerate(outputs_) }; # Letzte Messages - if metrics: + if appconfig.AppConfigShowMetrics(): DisplayMetrics(); DisplayEndOfAlgorithm(**outputsNamed); # Postchecks - if checks and callable(postChecks): + if appconfig.AppConfigPerformChecks() and callable(postChecks): postChecks(**inputs, **outputsNamed); except Exception as e: nonnestedAlgorithms.state = state1; diff --git a/code/python/src/algorithms/search/binary.py b/code/python/src/algorithms/search/binary.py index e39534b..25709cd 100644 --- a/code/python/src/algorithms/search/binary.py +++ b/code/python/src/algorithms/search/binary.py @@ -37,7 +37,7 @@ def postChecks(L: List[int], x: int, index: int, **_): # ALGORITHM binary search # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -@algorithmInfos(name='Binärsuchalgorithmus', outputnames=['index'], checks=True, metrics=True, preChecks=preChecks, postChecks=postChecks) +@algorithmInfos(name='Binärsuchalgorithmus', outputnames=['index'], preChecks=preChecks, postChecks=postChecks) def BinarySearch(L: List[int], x: int) -> int: ''' Inputs: L = Liste von Zahlen, x = Zahl. diff --git a/code/python/src/algorithms/search/interpol.py b/code/python/src/algorithms/search/interpol.py index 407ab30..f193586 100644 --- a/code/python/src/algorithms/search/interpol.py +++ b/code/python/src/algorithms/search/interpol.py @@ -37,7 +37,7 @@ def postChecks(L: List[int], x: int, index: int, **_): # ALGORITHM interpolation # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -@algorithmInfos(name='Interpolationssuchalgorithmus', outputnames=['index'], checks=True, metrics=True, preChecks=preChecks, postChecks=postChecks) +@algorithmInfos(name='Interpolationssuchalgorithmus', outputnames=['index'], preChecks=preChecks, postChecks=postChecks) def InterpolationSearch(L: List[int], x: int, u: int, v: int) -> int: ''' Inputs: L = Liste von Zahlen, x = Zahl, [u, v] = Suchinterval. diff --git a/code/python/src/algorithms/search/ith_smallest.py b/code/python/src/algorithms/search/ith_smallest.py index 52da2ce..f58c878 100644 --- a/code/python/src/algorithms/search/ith_smallest.py +++ b/code/python/src/algorithms/search/ith_smallest.py @@ -36,7 +36,7 @@ def postChecks(L: List[int], i: int, value: int, **_): # ALGORITHM find ith smallest element # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -@algorithmInfos(name='Auswahlproblem (i. kleinstes Element)', outputnames=['value'], checks=True, metrics=True, preChecks=preChecks, postChecks=postChecks) +@algorithmInfos(name='Auswahlproblem (i. kleinstes Element)', outputnames=['value'], preChecks=preChecks, postChecks=postChecks) def FindIthSmallest(L: List[int], i: int) -> int: ''' Inputs: L = Liste von Zahlen, i = Ordinalzahl @@ -68,7 +68,7 @@ def FindIthSmallest(L: List[int], i: int) -> int: # ALGORITHM find ith smallest element (D & C) # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -@algorithmInfos(name='Auswahlproblem (i. kleinstes Element, D & C)', outputnames=['value'], checks=True, metrics=True, preChecks=preChecks, postChecks=postChecks) +@algorithmInfos(name='Auswahlproblem (i. kleinstes Element, D & C)', outputnames=['value'], preChecks=preChecks, postChecks=postChecks) def FindIthSmallestDC(L: List[int], i: int) -> int: ''' Inputs: L = Liste von Zahlen, i = Ordinalzahl diff --git a/code/python/src/algorithms/search/jump.py b/code/python/src/algorithms/search/jump.py index 37b7b47..c361a11 100644 --- a/code/python/src/algorithms/search/jump.py +++ b/code/python/src/algorithms/search/jump.py @@ -39,7 +39,7 @@ def postChecks(L: List[int], x: int, index: int, **_): # ALGORITHM jump search # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -@algorithmInfos(name='Sprungsuche', outputnames=['index'], checks=True, metrics=True, preChecks=preChecks, postChecks=postChecks) +@algorithmInfos(name='Sprungsuche', outputnames=['index'], preChecks=preChecks, postChecks=postChecks) def JumpSearchLinear(L: List[int], x: int, m: int) -> int: ''' Inputs: L = Liste von Zahlen, x = Zahl, m = lineare Sprunggröße. @@ -71,7 +71,7 @@ def JumpSearchLinear(L: List[int], x: int, m: int) -> int: # ALGORITHM jump search - exponentiell # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -@algorithmInfos(name='Sprungsuche (exponentiell)', outputnames=['index'], checks=True, metrics=True, preChecks=preChecks, postChecks=postChecks) +@algorithmInfos(name='Sprungsuche (exponentiell)', outputnames=['index'], preChecks=preChecks, postChecks=postChecks) def JumpSearchExponentiell(L: List[int], x: int) -> int: ''' Inputs: L = Liste von Zahlen, x = Zahl. diff --git a/code/python/src/algorithms/search/poison.py b/code/python/src/algorithms/search/poison.py index 6bff089..ff71b0d 100644 --- a/code/python/src/algorithms/search/poison.py +++ b/code/python/src/algorithms/search/poison.py @@ -36,7 +36,7 @@ def postChecks(L: List[int], index: int, **_): # ALGORITHM find poison # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -@algorithmInfos(name='Giftsuche (O(n) Vorkoster)', outputnames=['index'], checks=True, metrics=True, preChecks=preChecks, postChecks=postChecks) +@algorithmInfos(name='Giftsuche (O(n) Vorkoster)', outputnames=['index'], preChecks=preChecks, postChecks=postChecks) def FindPoison(L: List[int]) -> int: ''' Inputs: L = Liste von Getränken: durch 0-1 Werte wird dargestellt, ob ein Getränk vergiftet ist. @@ -64,7 +64,7 @@ def FindPoison(L: List[int]) -> int: # ALGORITHM find poison fast # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -@algorithmInfos(name='Giftsuche (O(log(n)) Vorkoster)', outputnames=['index'], checks=True, metrics=True, preChecks=preChecks, postChecks=postChecks) +@algorithmInfos(name='Giftsuche (O(log(n)) Vorkoster)', outputnames=['index'], preChecks=preChecks, postChecks=postChecks) def FindPoisonFast(L: List[int]) -> int: ''' Inputs: L = Liste von Getränken: durch 0-1 Werte wird dargestellt, ob ein Getränk vergiftet ist. diff --git a/code/python/src/algorithms/search/sequential.py b/code/python/src/algorithms/search/sequential.py index 3b5ab2a..8995061 100644 --- a/code/python/src/algorithms/search/sequential.py +++ b/code/python/src/algorithms/search/sequential.py @@ -37,7 +37,7 @@ def postChecks(L: List[int], x: int, index: int, **_): # ALGORITHM sequential search # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -@algorithmInfos(name='Sequenziellsuchalgorithmus', outputnames=['index'], checks=True, metrics=True, preChecks=preChecks, postChecks=postChecks) +@algorithmInfos(name='Sequenziellsuchalgorithmus', outputnames=['index'], preChecks=preChecks, postChecks=postChecks) def SequentialSearch(L: List[int], x: int) -> int: ''' Inputs: L = Liste von Zahlen, x = Zahl. diff --git a/code/python/src/algorithms/sum/maxsubsum.py b/code/python/src/algorithms/sum/maxsubsum.py index 14a47e5..ce964c9 100644 --- a/code/python/src/algorithms/sum/maxsubsum.py +++ b/code/python/src/algorithms/sum/maxsubsum.py @@ -33,7 +33,7 @@ def postChecks(L: List[int], **_): # ALGORITHM max sub sum # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -@algorithmInfos(name='MaxSubSum (Maximale Teilsumme)', outputnames=['maxSum', 'index_from', 'index_to'], checks=True, metrics=True, preChecks=preChecks, postChecks=postChecks) +@algorithmInfos(name='MaxSubSum (Maximale Teilsumme)', outputnames=['maxSum', 'index_from', 'index_to'], preChecks=preChecks, postChecks=postChecks) def MaxSubSum(L: List[float]) -> Tuple[float, int, int]: ''' Inputs: L = Liste von Zahlen @@ -58,7 +58,7 @@ def MaxSubSum(L: List[float]) -> Tuple[float, int, int]: # ALGORITHM max sub sum (D & C) # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -@algorithmInfos(name='MaxSubSum (Maximale Teilsumme mit D & C)', outputnames=['maxSum', 'index_from', 'index_to'], checks=True, metrics=True, preChecks=preChecks, postChecks=postChecks) +@algorithmInfos(name='MaxSubSum (Maximale Teilsumme mit D & C)', outputnames=['maxSum', 'index_from', 'index_to'], preChecks=preChecks, postChecks=postChecks) def MaxSubSumDC(L: List[float]) -> Tuple[float, int, int]: ''' Inputs: L = Liste von Zahlen diff --git a/code/python/src/core/log.py b/code/python/src/core/log.py index 45ecad7..cd1c899 100644 --- a/code/python/src/core/log.py +++ b/code/python/src/core/log.py @@ -10,6 +10,8 @@ from src.local.misc import *; from src.local.system import *; from src.local.typing import *; +from src.core.utils import StripAnsi; + # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # GLOBAL VARIABLES # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -17,6 +19,7 @@ from src.local.typing import *; _logging_prefix: str = ''; _quietmode: bool = False; _debugmode: bool = False; +_ansimode: bool = False; # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # METHOD get/set quiet mode, logging depth, timer @@ -38,6 +41,14 @@ def SetDebugMode(mode: bool): _debugmode = mode; return; +def GetAnsiMode() -> bool: + return _ansimode; + +def SetAnsiMode(mode: bool): + global _ansimode; + _ansimode = mode; + return; + # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # Logging # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -48,7 +59,10 @@ def logGeneric(tag: str, *lines: Any, file: io.TextIOWrapper, force: bool = Fals tag = '' if tag == '' else tag + ' '; file = file or sys.stdout; for line in lines: - print('{}{}{}'.format('', tag, line), file=file); + line = '{}{}{}'.format('', tag, line); + if not _ansimode: + line = StripAnsi(line); + print(line, file=file); if not tag_all: tag = ''; return; diff --git a/code/python/src/core/utils.py b/code/python/src/core/utils.py new file mode 100644 index 0000000..6f98a44 --- /dev/null +++ b/code/python/src/core/utils.py @@ -0,0 +1,40 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# IMPORTS +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +import re; +from textwrap import dedent; + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# METHODS ansi +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +def StripAnsi(text: str) -> str: + return re.sub(r'\x1b[^m]*m', '', text); + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# METHODS strings +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +def DedentIgnoreFirstLast(text: str) -> str: + text = '\n'.join(re.split(r'\n', text)[1:][:-1]) + return dedent(text); + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# METHODS strings -> bool +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +def IsTrue(text: str) -> bool: + text = text.strip(); + if re.match(r'^(true|t|yes|y|1|\+|\+1)$', text, re.IGNORECASE): + return True; + return False; + +def IsFalse(text: str) -> bool: + text = text.strip(); + if re.match(r'^(false|f|no|n|0|-|-1)$', text, re.IGNORECASE): + return True; + return False; diff --git a/code/python/src/endpoints/__init__.py b/code/python/src/endpoints/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/code/python/src/endpoints/exports.py b/code/python/src/endpoints/exports.py new file mode 100644 index 0000000..2932f89 --- /dev/null +++ b/code/python/src/endpoints/exports.py @@ -0,0 +1,11 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# EXPORTS +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +from src.endpoints.print import version as endpoint_version; +from src.endpoints.print import help as endpoint_help; +from src.endpoints.run import runInteractive as endpoint_runInteractive; +from src.endpoints.run import runNonInteractive as endpoint_runNonInteractive; diff --git a/code/python/src/endpoints/print.py b/code/python/src/endpoints/print.py new file mode 100644 index 0000000..42a9c8d --- /dev/null +++ b/code/python/src/endpoints/print.py @@ -0,0 +1,29 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# IMPORTS +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +from src.core.log import *; +from src.setup.cli import GetArgumentsFromCli; +from src.setup.cli import GetArgumentParser; + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# ENDPOINT version +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +def version(): + with open('assets/VERSION', 'r') as fp: + version = ('\n'.join(fp.readlines())).strip(); + logPlain(version); + return; + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# ENDPOINT help +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +def help(): + parser = GetArgumentParser(); + parser.print_help(); + return; diff --git a/code/python/src/endpoints/run.py b/code/python/src/endpoints/run.py new file mode 100644 index 0000000..158cddd --- /dev/null +++ b/code/python/src/endpoints/run.py @@ -0,0 +1,69 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# IMPORTS +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +from src.core.log import *; +from src.core.config import *; +from src.setup.display import *; +from src.algorithms.exports import *; + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# ENDPOINT run interactive modus +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +def runInteractive(): + ''' + Startet Programm im interaktiven Modus (Konsole). + ''' + logWarn('Interaktiver Modus noch nicht implementiert.'); + return; + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# ENDPOINT run non-interactive +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +def runNonInteractive(path: str): + ''' + Liest Fälle aus Configdatei aus und führt Algorithmen darauf aus. + ''' + config = ReadConfigFile(path); + cases = GetAttribute(config, 'parts', 'cases', expectedtype=list, default=[]); + for caseindex, case in enumerate(cases): + command = GetAttribute(case, 'command', expectedtype=str, default=''); + descr = GetAttribute(case, 'description', expectedtype=str, default=''); + inputs = GetAttribute(case, 'inputs', expectedtype=dict, default={}); + + DisplayStartOfCase(caseindex, descr); + + try: + if command == 'algorithm-sum-maxsub': + MaxSubSum(L=inputs['L']); + elif command == 'algorithm-sum-maxsub-dc': + MaxSubSumDC(L=inputs['L']); + elif command == 'algorithm-search-sequential': + SequentialSearch(L=inputs['L'], x=inputs['x']); + elif command == 'algorithm-search-binary': + BinarySearch(L=inputs['L'], x=inputs['x']); + elif command == 'algorithm-search-interpolation': + InterpolationSearch(L=inputs['L'], x=inputs['x'], u=0, v=len(inputs['L'])-1); + elif command == 'algorithm-search-jump': + JumpSearchLinear(L=inputs['L'], x=inputs['x'], m=inputs['m']); + elif command == 'algorithm-search-jump-exp': + JumpSearchExponentiell(L=inputs['L'], x=inputs['x']); + elif command == 'algorithm-search-ith-element': + FindIthSmallest(L=inputs['L'], i=inputs['i']); + elif command == 'algorithm-search-ith-element-dc': + FindIthSmallestDC(L=inputs['L'], i=inputs['i']); + elif command == 'algorithm-search-poison': + FindPoison(L=inputs['L']); + elif command == 'algorithm-search-poison-fast': + FindPoisonFast(L=inputs['L']); + else: + raise ValueError('Command \033[1m{}\033[0m nicht erkannt'.format(command)); + except Exception as e: + logError(e); + DisplayEndOfCase(); + return; diff --git a/code/python/src/main.py b/code/python/src/main.py index ec2565c..aec251d 100644 --- a/code/python/src/main.py +++ b/code/python/src/main.py @@ -8,80 +8,54 @@ import os; import sys; -sys.path.insert(0, os.path.abspath(os.path.join(os.path.abspath(__file__), '..', '..'))); -os.chdir(os.path.abspath(os.path.join(os.path.abspath(__file__), '..', '..', '..', '..'))); +_path_to_python_project = os.path.abspath(os.path.join(os.path.abspath(__file__), '..', '..')); +sys.path.insert(0, _path_to_python_project); +os.chdir(_path_to_python_project); from src.core.log import *; -from src.core.config import *; -from src.setup.display import *; +from src.core.utils import IsTrue; +from src.core.utils import IsFalse; from src.setup.cli import *; -from src.algorithms.exports import *; +from src.setup import appconfig; +from src.endpoints.exports import *; # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # GLOBAL VARIABLES/CONSTANTS # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -PATH_TO_CONFIG: str = 'code/config.yml'; +PATH_TO_CONFIG: str = '../config.yml'; # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # MAIN PROCESS # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -def enter(quiet: bool, debug: bool, mode: str, path: Any, **_): +def enter( + mode: str, + it: bool, + quiet: bool, + debug: bool, + checks: bool, + colour: bool, + config: Any, **_ +): SetQuietMode(quiet); SetDebugMode(debug); - configpath = path if isinstance(path, str) else PATH_TO_CONFIG; - if mode in 'run': - LoopThroughCases(path=configpath); - else: - DisplayHelpMessage(); - return; + SetAnsiMode(colour); + appconfig.SetAppConfigPerformChecks(checks); -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# SECONDARY PROCESSES -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + config = config if isinstance(config, str) else PATH_TO_CONFIG; -def LoopThroughCases(path: str): - ''' - Durchlauf aller Testfälle. - ''' - config = ReadConfigFile(path); - cases = GetAttribute(config, 'parts', 'cases', expectedtype=list, default=[]); - for caseindex, case in enumerate(cases): - command = GetAttribute(case, 'command', expectedtype=str, default=''); - descr = GetAttribute(case, 'description', expectedtype=str, default=''); - inputs = GetAttribute(case, 'inputs', expectedtype=dict, default={}); - - DisplayStartOfCase(caseindex, descr); - - try: - if command == 'algorithm-sum-maxsub': - MaxSubSum(L=inputs['L']); - elif command == 'algorithm-sum-maxsub-dc': - MaxSubSumDC(L=inputs['L']); - elif command == 'algorithm-search-sequential': - SequentialSearch(L=inputs['L'], x=inputs['x']); - elif command == 'algorithm-search-binary': - BinarySearch(L=inputs['L'], x=inputs['x']); - elif command == 'algorithm-search-interpolation': - InterpolationSearch(L=inputs['L'], x=inputs['x'], u=0, v=len(inputs['L'])-1); - elif command == 'algorithm-search-jump': - JumpSearchLinear(L=inputs['L'], x=inputs['x'], m=inputs['m']); - elif command == 'algorithm-search-jump-exp': - JumpSearchExponentiell(L=inputs['L'], x=inputs['x']); - elif command == 'algorithm-search-ith-element': - FindIthSmallest(L=inputs['L'], i=inputs['i']); - elif command == 'algorithm-search-ith-element-dc': - FindIthSmallestDC(L=inputs['L'], i=inputs['i']); - elif command == 'algorithm-search-poison': - FindPoison(L=inputs['L']); - elif command == 'algorithm-search-poison-fast': - FindPoisonFast(L=inputs['L']); - else: - raise ValueError('Command \033[1m{}\033[0m nicht erkannt'.format(command)); - except Exception as e: - logError(e); - DisplayEndOfCase(); + if mode == 'version': + endpoint_version(); + return; + elif mode == 'run': + if it: + endpoint_runInteractive(); + else: + endpoint_runNonInteractive(path=config); + else: # elif mode + endpoint_help(); + return; return; # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -91,7 +65,16 @@ def LoopThroughCases(path: str): if __name__ == '__main__': sys.tracebacklimit = 0; try: - args = GetArgumentsFromCli(sys.argv[1:]); - except: + args = GetArgumentsFromCli(*sys.argv[1:]); + except Exception as e: + endpoint_help(); exit(1); - enter(quiet=args.quiet, debug=args.debug, mode=args.mode[0], path=args.path); + enter( + mode=args.mode[0], + it=args.it, + quiet=args.quiet, + debug=args.debug, + checks=IsTrue(args.checks[0]), + colour=IsTrue(args.colour[0]), + config=args.config, + ); diff --git a/code/python/src/setup/appconfig.py b/code/python/src/setup/appconfig.py new file mode 100644 index 0000000..029f6c9 --- /dev/null +++ b/code/python/src/setup/appconfig.py @@ -0,0 +1,66 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# IMPORTS +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +from src.local.io import *; +from src.local.misc import *; +from src.local.system import *; +from src.local.typing import *; + +from src.core.config import *; + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# GLOBAL VARIABLES +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +_config: Dict[str, bool] = dict( + display = True, + metrics = True, + checks = False, +); + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# METHOD getters +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +def AppConfigInitialise(): + ''' + Extrahiert Inhalte einer YAML Config und parset dies als Struktur + ''' + global _config; + config = ReadConfigFile('assets/config.yml'); + _config['display'] = GetAttribute(config, 'options', 'display', expectedtype=bool, default=True); + _config['metrics'] = GetAttribute(config, 'options', 'metrics', expectedtype=bool, default=True); + _config['checks'] = GetAttribute(config, 'options', 'checks', expectedtype=bool, default=True); + return; + +def AppConfigFancyMode() -> bool: + return _config['display']; + +def AppConfigShowMetrics() -> bool: + return _config['metrics']; + +def AppConfigPerformChecks() -> bool: + return _config['checks']; + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# METHOD setters +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +def SetAppConfigFancyMode(mode: bool): + global _config; + _config['display'] = mode; + return; + +def SetAppConfigShowMetrics(mode: bool): + global _config; + _config['metrics'] = mode; + return; + +def SetAppConfigPerformChecks(mode: bool): + global _config; + _config['checks'] = mode; + return; diff --git a/code/python/src/setup/cli.py b/code/python/src/setup/cli.py index 2812928..2bfa381 100644 --- a/code/python/src/setup/cli.py +++ b/code/python/src/setup/cli.py @@ -5,9 +5,11 @@ # IMPORTS # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +from argparse import ArgumentError from src.local.typing import *; from src.core.log import *; +from src.core.utils import DedentIgnoreFirstLast; # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # GLOBAL VARIABLES @@ -24,18 +26,34 @@ def GetArgumentParser() -> argparse.ArgumentParser: if not isinstance(parser, argparse.ArgumentParser): parser = argparse.ArgumentParser( prog='code/main.py', - description=dedent(''' + description=DedentIgnoreFirstLast(''' \033[93;1mBeschreibung:\033[0m \033[93;2mEin Programm, das verschiedene Algorithmen aus dem Kurs AlgoDat I testet.\033[0m '''), formatter_class=argparse.RawTextHelpFormatter, ); - parser.add_argument('mode', nargs=1, choices=['run'], help='run = Führt alle Testfälle in der config.yml Datei durch.'); - parser.add_argument('--path', nargs=1, type=str, help='Pfad zur alternativen Configdatei.'); - parser.add_argument('--debug', action='store_true', help='Debugging Messages stummschalten.') - parser.add_argument('-q', '--quiet', action='store_true', help='Alle console-messages bis auf Errors stummschalten.') + parser.add_argument('mode', + nargs=1, + choices=['version', 'help', 'run'], + help=DedentIgnoreFirstLast(''' + help = Hilfsanleitung anzeigen. + version = Version anzeigen. + run = Algorithmen ausführen. + '''), + ); + parser.add_argument('--it', action='store_true', help='Startet die App im interaktiven Modus.') + parser.add_argument('-q', '--quiet', action='store_true', help='Blendet alle Konsole-Messages aus.') + parser.add_argument('--debug', action='store_true', help='Blendet die Debugging-Befehle ein.') + parser.add_argument('--checks', nargs=1, type=str, default=['False'], + help=DedentIgnoreFirstLast(''' + (bool) Ob vor und nach Ausführung von Algorithmen Checks + auf Inputs/Outputs ausgeführt werden sollen. + '''), + ), + parser.add_argument('--colour', nargs=1, type=str, default=['False'], help='(bool) Ob Logging färblich angezeigt wird.') + parser.add_argument('--config', nargs=1, type=str, help='(string) Pfad zur Configdatei (nur für run Endpunkt).'); return parser; -def GetArgumentsFromCli(cli_args: List[str]) -> argparse.Namespace: +def GetArgumentsFromCli(*cli_args: str) -> argparse.Namespace: parser = GetArgumentParser(); return parser.parse_args(cli_args);