From ebb379390c640b73c6c21df7264a8bd727fece8d Mon Sep 17 00:00:00 2001
From: Rolfes <alois.rolfes@hs-hannover.de>
Date: Wed, 12 Jan 2022 14:07:00 +0100
Subject: [PATCH] load_sim_libs

---
 .env                                          |    1 +
 .../requirements-checkpoint.txt               |    2 +
 Balance_Binary.ipynb                          |  123 +-
 README.md                                     |    3 +-
 __pycache__/nowo1_base.cpython-39.pyc         |  Bin 0 -> 43593 bytes
 __pycache__/nowo1_gui_base.cpython-39.pyc     |  Bin 0 -> 1791 bytes
 __pycache__/nowo1_log_base.cpython-39.pyc     |  Bin 0 -> 3377 bytes
 __pycache__/nowo1_sim_binary.cpython-39.pyc   |  Bin 0 -> 9603 bytes
 __pycache__/sim_base.cpython-39.pyc           |  Bin 0 -> 308 bytes
 nowo1_base.py                                 | 1527 +++++++++++++++++
 nowo1_gui_base.py                             |   47 +
 nowo1_log_base.py                             |   85 +
 nowo1_sim_binary.py                           |  406 +++++
 requirements.txt                              |    1 +
 sim_base.py                                   |   11 +
 15 files changed, 2184 insertions(+), 22 deletions(-)
 create mode 100644 .env
 create mode 100644 .ipynb_checkpoints/requirements-checkpoint.txt
 create mode 100644 __pycache__/nowo1_base.cpython-39.pyc
 create mode 100644 __pycache__/nowo1_gui_base.cpython-39.pyc
 create mode 100644 __pycache__/nowo1_log_base.cpython-39.pyc
 create mode 100644 __pycache__/nowo1_sim_binary.cpython-39.pyc
 create mode 100644 __pycache__/sim_base.cpython-39.pyc
 create mode 100644 nowo1_base.py
 create mode 100644 nowo1_gui_base.py
 create mode 100644 nowo1_log_base.py
 create mode 100644 nowo1_sim_binary.py
 create mode 100644 sim_base.py

diff --git a/.env b/.env
new file mode 100644
index 0000000..3479d91
--- /dev/null
+++ b/.env
@@ -0,0 +1 @@
+PYTHONPATH="/libs"
\ No newline at end of file
diff --git a/.ipynb_checkpoints/requirements-checkpoint.txt b/.ipynb_checkpoints/requirements-checkpoint.txt
new file mode 100644
index 0000000..e76e091
--- /dev/null
+++ b/.ipynb_checkpoints/requirements-checkpoint.txt
@@ -0,0 +1,2 @@
+voila
+voila-gridstack
diff --git a/Balance_Binary.ipynb b/Balance_Binary.ipynb
index 4c87cd9..9b71568 100644
--- a/Balance_Binary.ipynb
+++ b/Balance_Binary.ipynb
@@ -132,7 +132,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": null,
+   "execution_count": 1,
    "id": "ab70ee95-ce3c-4c4c-a7bc-2658a1a5d41a",
    "metadata": {
     "extensions": {
@@ -152,15 +152,15 @@
    },
    "outputs": [],
    "source": [
-    "import nowo_base_1 as no_ba\n",
-    "import nowo_sim_binary as no_bi\n",
-    "import nowo_gui_base as no_gui\n",
-    "import nowo_log_base as no_log"
+    "import nowo1_base as no_ba\n",
+    "import nowo1_sim_binary as no_bi\n",
+    "import nowo1_gui_base as no_gui\n",
+    "import nowo1_log_base as no_log"
    ]
   },
   {
    "cell_type": "code",
-   "execution_count": null,
+   "execution_count": 4,
    "id": "eec838fd-a5a9-49c8-a873-07c0e3653622",
    "metadata": {
     "extensions": {
@@ -180,15 +180,15 @@
    },
    "outputs": [],
    "source": [
-    "test_obj = no_bi.binaer_node('test_obj') # Umgebungs\n",
-    "step_1 = no_ba.step_single('step_1')\n",
+    "bilanz_1 = no_bi.binary_node('bilanz_1') # Umgebungs\n",
+    "step = no_ba.step_single('step')\n",
     "gui_data = no_gui.gui_ipysheet('gui_data')\n",
-    "log_1 = no_log.log_sheet('log_1')"
+    "log = no_log.log_sheet('log')"
    ]
   },
   {
    "cell_type": "code",
-   "execution_count": null,
+   "execution_count": 5,
    "id": "5e7dc37c-8fe1-4569-a233-e3e45f450ae2",
    "metadata": {
     "extensions": {
@@ -208,13 +208,13 @@
    },
    "outputs": [],
    "source": [
-    "step_1.Init(work_objs=[test_obj.Calc_A_B])\n",
-    "log_1.Init(Values=[test_obj.log_all], Gui_For_Data = gui_data)"
+    "step.Init(work_objs=[bilanz_1.Calc_A_B])\n",
+    "log.Init(Values=[bilanz_1.log_all], Gui_For_Data = gui_data)"
    ]
   },
   {
    "cell_type": "code",
-   "execution_count": null,
+   "execution_count": 6,
    "id": "9a853d13-b21f-475a-8262-b9616bad6a60",
    "metadata": {
     "extensions": {
@@ -233,14 +233,29 @@
     },
     "tags": []
    },
-   "outputs": [],
+   "outputs": [
+    {
+     "data": {
+      "application/vnd.jupyter.widget-view+json": {
+       "model_id": "3b61942308af4a80ae7925cd8d0f83e0",
+       "version_major": 2,
+       "version_minor": 0
+      },
+      "text/plain": [
+       "VBox(children=(Sheet(cells=(Cell(column_end=0, column_start=0, row_end=7, row_start=0, squeeze_row=False, type…"
+      ]
+     },
+     "metadata": {},
+     "output_type": "display_data"
+    }
+   ],
    "source": [
     "gui_data.Show_GUI()"
    ]
   },
   {
    "cell_type": "code",
-   "execution_count": null,
+   "execution_count": 8,
    "id": "155a052c-b1b6-4098-8614-19388211296a",
    "metadata": {
     "extensions": {
@@ -258,14 +273,29 @@
      }
     }
    },
-   "outputs": [],
+   "outputs": [
+    {
+     "data": {
+      "application/vnd.jupyter.widget-view+json": {
+       "model_id": "6be30af1c3954d52ba1a8a26b2a93196",
+       "version_major": 2,
+       "version_minor": 0
+      },
+      "text/plain": [
+       "VBox(children=(VBox(children=(Label(value='extensive Größe:'), HBox(children=(Dropdown(layout=Layout(width='10…"
+      ]
+     },
+     "metadata": {},
+     "output_type": "display_data"
+    }
+   ],
    "source": [
-    "test_obj.Show_GUI()"
+    "bilanz_1.Show_GUI()"
    ]
   },
   {
    "cell_type": "code",
-   "execution_count": null,
+   "execution_count": 9,
    "id": "aa1fe3ad-55bb-491d-a677-ea20354ba5c1",
    "metadata": {
     "extensions": {
@@ -283,10 +313,63 @@
      }
     }
    },
-   "outputs": [],
+   "outputs": [
+    {
+     "data": {
+      "application/vnd.jupyter.widget-view+json": {
+       "model_id": "a7b9403b09c842cd849ebe6827a4801b",
+       "version_major": 2,
+       "version_minor": 0
+      },
+      "text/plain": [
+       "VBox(children=(Button(description='Calc', style=ButtonStyle()),))"
+      ]
+     },
+     "metadata": {},
+     "output_type": "display_data"
+    },
+    {
+     "data": {
+      "application/vnd.jupyter.widget-view+json": {
+       "model_id": "ed555c63520a4dd7a0a83be748fcfb44",
+       "version_major": 2,
+       "version_minor": 0
+      },
+      "text/plain": [
+       "Output()"
+      ]
+     },
+     "metadata": {},
+     "output_type": "display_data"
+    }
+   ],
    "source": [
-    "step_1.Show_GUI()"
+    "step.Show_GUI()"
    ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "e725524f-503a-4133-8445-2702b729abcf",
+   "metadata": {
+    "extensions": {
+     "jupyter_dashboards": {
+      "activeView": "grid_default",
+      "views": {
+       "grid_default": {
+        "col": null,
+        "height": 2,
+        "hidden": true,
+        "row": null,
+        "width": 2
+       }
+      }
+     }
+    },
+    "tags": []
+   },
+   "outputs": [],
+   "source": []
   }
  ],
  "metadata": {
diff --git a/README.md b/README.md
index 476b50c..22af31a 100644
--- a/README.md
+++ b/README.md
@@ -5,5 +5,4 @@
 
 
 
-[![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/was-ist-immer/Binary_Balance/HEAD?urlpath=voila/render/Balance_Binary.ipynb)
-
+[![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/was-ist-immer/Binary_Balance/HEAD?urlpath=voila%2Frender%2FBalance_Binary.ipynb)
diff --git a/__pycache__/nowo1_base.cpython-39.pyc b/__pycache__/nowo1_base.cpython-39.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..4a2d8537bfdba8749adffb5c8d4fb534ecbee302
GIT binary patch
literal 43593
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

literal 0
HcmV?d00001

diff --git a/__pycache__/nowo1_gui_base.cpython-39.pyc b/__pycache__/nowo1_gui_base.cpython-39.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..eedef653f6714a41958a39925eccf904fb940d62
GIT binary patch
literal 1791
zcmYe~<>g{vU|?8$@m}H;HU@^rAPzESVPIfzU|?V<PGewTNMT4}%wdRP1k+4W%wU=&
ziWN+=MX`fvjwntr%@xHBrg@@xQW#R0a(Hriqj(uXW-#aQ<?=`IGcvd{q_Cv0wlJiy
zrZQ&<G&4sDrZ5IGXtKQoxxi18@fKfNQGRZGN@7W3T2W$dswU$t_LR)xf}F(4WRMbM
z%nIccJ25aYq=Fq8#gxLG%ACrQ!Ze4eogs}eg*k<#g*S>dg*An(g&~S9g*}C%g&~R^
zEXSF`)xr_Q(ayla5XBkHpviNKC%rT?KC_^*I3qQ+#7&dw7E4}YZt5*&_fXGdW~gl-
z3KT>j%nb@A3kC*;5{71mEXEqf8m2U+OokffC5(NHAdlBD#51Kc)G)*|gGrVY5StZD
zvZXKtGpuCv(`3KJT3lL?T6BveK0Y%qvm`$L7Ax2RxA?$Rd~$vc$Qi{jeo=logwF+$
z2L)CXFNg#OS$uwJi6+Y}mg3Z$v?5R#6|pfeFx+CxE>A2<FJ8%bi!(kxIVZ8WI6i(Q
z!!K1&s~E4+g36NABA>*hn2`MZoZ^_g{PKLmcu-&@B^IaZ6;u{+GB7akgM7;a@;{>(
zBO4S}iGq~D!b}h5g=8j>Iw%IQLBZz?GC+rcfuV-6h9RDzgt3Mpi(vuNLWX7#pBci>
zVp+fn6#)lP5jz6|gC=_sFUS)tIhn;Jw^%Y#6H|&nfq#oNGcP5z;uc#;K1ikr<T_2J
zB0i8>PI!nE2{AA*KnP)wjG$*;W=VWfB_f$gfLsO&CI&_}MghhuITTM}C{JdD`V2&Y
zd<RMlVBe{Le8-T*kj0qAw19abLoH(oOBQPlV+x}rLkd$0b1xGpSp+j^viKE&40#D6
zG#R6KlJj#)bMxYhOA?DpG}$1&Wh+a}DNQZD#TZf~4stgKESRIXl2dbX;)@dV(o<pH
zWlJheOG_<+coXbluwQwLQWH}u<J0ns;#2cd<UsxeIhKKukFiP$#g`}wQG5uBJ5WLb
z(ZyNd<etS?!c@bM#oP>`S(+JB7{wV<n9@OU$|BB?!raST!w}C{!jQ$9!U9qW%J;p@
zwTvZf3)pKIvKZ4D7c$m@%-~qSnZgDV$z)u}$jDH_)y%Mfdm#fOLk&|fgC@IQkrdeP
zWr;<ZiAg!Bn#{LYit@{gZ?QvytT>7f!iWc@iqxWFaJXtR-r_9EFNcI@5vah^<SCK`
zB?A!q7IRK&9yqZ;QV|=(gj?+8nJMY1CB?T`!kqFeZt=#uhkC|mmZau_64x!Z(t?!4
zlGGv&kbAh}lZ#RlOHx6(M3Whu;-Wyt6vrFh;w;H8Nz92)%C9IA09gr-jUp`u1_n?P
zDFz8KF!3<*FmnClU=d>CV-#ZKVyu!ti4kNg7~M3vKqUky=f}t2;);*Y%}*)KNsW)c
z#S<T2SeghfBjV$4F&CE<-C{|~&(8s8+9FAi3*<or$nsmf(991`K=DYa1?*B#k|_eE
z4^R#&26>c&QH+y=je`v=sws4fqc}4+9#ksaVg<3%Z*f5i3$PFih<%F#6iOwTxv969
zQc7;I6(r`RBo^OdDoDA-npc`zP<e|fuizF}W<e!1w2Rb0t^-F7C@<aO_Y9~k$;i*s
xgBJWnpmcYO0~9nMTfi<sayTd`i$D&)#bE;p6FX3*0tYb%BNQ@$XdXr$762eizjy!u

literal 0
HcmV?d00001

diff --git a/__pycache__/nowo1_log_base.cpython-39.pyc b/__pycache__/nowo1_log_base.cpython-39.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..5a454f371b8823692aa4b1f24492237b7ff8d62d
GIT binary patch
literal 3377
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
a-r}%<w14bC#eXrVG0VXSg-k+%LRtW`J-tZ)

literal 0
HcmV?d00001

diff --git a/__pycache__/nowo1_sim_binary.cpython-39.pyc b/__pycache__/nowo1_sim_binary.cpython-39.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..bcc80afd87a78bb2f2485fba89fdead4adb99d0c
GIT binary patch
literal 9603
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
MK|KrPAtWAV0FuztPyhe`

literal 0
HcmV?d00001

diff --git a/__pycache__/sim_base.cpython-39.pyc b/__pycache__/sim_base.cpython-39.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..e0a283222cd5cdad6d62aca686191908ea88c219
GIT binary patch
literal 308
zcmYe~<>g{vU|<NmcrTHek%8ech=Yuo7#J8F7#J9e%@`OMQW#Pga~Pr^G-DKFDq|K?
z3X>#56mu#|GeZiqBtsM{NGz3Ak|ByMg(ZqTg)x{xll3LYM88`c@$tEdnR)T?AXZ*t
zZfbmdm7r>*u4=BXYKnrYhn1?Ym1?ji$1V1P#FC7h%%oe)#g)ak*mLt!N^??+Z*lp8
zbo+vMx7gEj@{<yCif{1+r{<)^g9SlG-r_>=Z*iAo=B5@TmXxFx<*j5W;$dKb5WnO-
ztzx`N3o1)ei+mE3VnXusbBbe%GjrpU5{pyy3My}L*g!0`V+8pf6hs`19L!vdT#Q^S
E0RAph9{>OV

literal 0
HcmV?d00001

diff --git a/nowo1_base.py b/nowo1_base.py
new file mode 100644
index 0000000..3fdac91
--- /dev/null
+++ b/nowo1_base.py
@@ -0,0 +1,1527 @@
+import sys
+import sim_base as sim_g
+import pandas as pd
+import datetime as dt
+from dateutil.relativedelta import relativedelta
+from typing import Any, Callable, List, Type
+import math
+import numpy as np
+import ipywidgets as widgets
+from IPython.display import display
+
+
+
+Main_Modul = sys.modules['__main__']
+Self_Modulname = globals()['__name__']
+Self_Modul = sys.modules[Self_Modulname]
+
+
+def get_attr_rek(names, start_obj=Main_Modul):
+    """get attr / obj by list or str.
+
+Keyword arguments:
+names -- as str or list (example: 'obj.attr1.attr2'  or ['obj', 'attr1', 'attr2'])
+start_obj -- obj where to search
+"""
+    if isinstance(names, str):
+        name_list = names.split('.')
+    elif isinstance(names, list):
+        name_list = names
+    else:
+        return None
+
+    obj = start_obj
+    for name in name_list:
+        if hasattr(obj, name):
+            obj = getattr(obj, name)
+        else:
+            return None
+    return obj
+
+
+def analyse_func_old(func_to_analyse, sim_obj):
+    if isinstance(func_to_analyse, str):
+        func_name = func_to_analyse
+        func = get_attr_rek(func_to_analyse)
+        if not func: return None
+        sim_obj = func.__self__
+
+    elif callable(func_to_analyse):
+        func = func_to_analyse
+        func_name = func.__name__
+        if hasattr(func, '__self__'):
+            sim_obj = func.__self__ 
+            func_name = sim_obj.name + '.' + func_name
+        else:
+            setattr(sim_obj, func_name, func)
+        func_name = sim_obj.name + '.' + func_name
+    else: return None
+
+    return [sim_obj, func, func_name]
+
+
+def analyse_func(func):
+    if isinstance(func, str):
+        func_name = func
+        func = get_attr_rek(func)
+        if not func: return None
+
+    if callable(func):
+        func_name = func.__name__
+        sim_obj = None
+        if hasattr(func, '__self__'):
+            sim_obj = func.__self__ 
+            func_name = sim_obj.name + '.' + func_name
+        
+    else: return None
+
+    return [sim_obj, func, func_name]
+
+
+
+class sim_value():
+    def __init__(self, name: str, parent, value_type ):
+        self.name = name
+        self._parent = parent
+        self._simparent =  getattr(self._parent, 'sim_parent', self._parent)
+        if not self._simparent: self._simparent = self._parent
+        value_type_list = list(value_type)
+        value_type_list.append(type(None))
+        self.value_type = tuple(value_type_list)
+        self._value = None
+        self._default_value = None
+        self.unit = ''
+
+        self.set = self._set # Überschreibbar durch callback funktion
+        self.call_extern = None
+        self.call_intern = None
+        self._fullname = self._get_fullname()
+        self._loggerlist : set = set()
+        
+
+    def _get_fullname(self):
+        namelist = []
+        if not self._simparent == self._parent:
+            namelist.append(self._simparent.name)
+        namelist.append(self._parent.name)
+        namelist.append(self.name)
+        return '.'.join(namelist)
+
+    #TODO typen überprüfen
+    def _set(self,  value):
+        if not isinstance(value, self.value_type): raise Exception('ungültiger typ')
+        self._value = value
+        return self._value
+
+    # Wird geändert über value erfolgt kein callback zugriff es wird nur
+    #_value geändert oder zurückgegeben
+    @property
+    def value(self):
+        return self._value
+
+
+    @value.setter
+    def value(self, value):
+        if not isinstance(value, self.value_type): raise Exception('ungültiger typ')
+        self._value = value   
+    
+
+    @property
+    def default_value(self):
+        return self._default_value
+
+
+    @default_value.setter
+    def default_value(self, value):
+        self._default_value = value
+        self._value = self._default_value 
+
+
+    def get_set(self, stepper=None, value=None):
+        if self.call_extern:
+            self._value = self.call_extern(self, value, stepper) 
+        elif self.call_intern:
+            self._value = self.call_intern(value, stepper) 
+        return self._value
+
+
+   
+    #TODO Warum Any würde hier nicht auch ein None genügen?
+    def Init(self, value = Any, default = Any, unit = ''):
+        #self._loggerlist : set = set()
+        self.unit = unit
+        self._default_value = default
+        if isinstance(value, str): 
+            value = get_attr_rek(value)
+        if isinstance(value, Callable):
+            if hasattr(value, '__self__') and (value.__self__ == self._simparent):
+                self.call_intern = value
+            else: self.call_extern = value
+            self._value = self._default_value
+            return
+        elif isinstance(value, type(None)):
+            self._value = value
+            self.set = self._set
+        elif isinstance(value, self.value_type):
+            self._value = self.value_type[0](value)
+            self.set = self._set
+        return 
+
+    
+    def _add_logger(self, logger):
+        self._simparent._add_logger(logger)
+        self._loggerlist.add(logger)
+        return self._fullname
+
+
+    def _del_logger(self, logger):
+        self._simparent._del_logger(logger)
+
+
+    def _node_success(self, stepper):
+        for logger in self._loggerlist:
+            logger._add_value(self._fullname, self._value)
+
+
+#-------------------------------------------------------------------
+class gate_base:
+    def __init__(self, name, sim_parent):
+        self.name = name
+        self.sim_parent = sim_parent
+        self._success_flag : bool = True
+       
+    def set(self, value: Any, value_name: str = ''):pass
+        
+    def get(self, value_name: str = ''):pass
+        
+    def Init(self, values):pass
+        
+    def _reset(self): 
+        self._success_flag : bool = True
+
+    def _node_success(self, stepper): pass
+
+    def log_all(self, logger):
+        name_list = []
+        for key, value in self.__dict__.items():
+            if issubclass(type(value), sim_value):
+                name_list.append(value._add_logger(logger))
+        return name_list
+         
+
+#-------------------------------------------------------------------
+class gate_time(gate_base):
+    def __init__(self, name,  sim_parent):
+        super().__init__(name,  sim_parent)
+        self.time = sim_value('time', self, (dt.datetime,))
+
+    def _node_success(self, timer):
+        self.time._node_success(timer)  
+
+    def _reset(self):
+        super()._reset()
+        self.time.set(dt.datetime(1, 1, 1, 0, 0, 0))
+
+    def set(self, value):
+        if isinstance(value, dt.datetime):
+            self.time.value = value
+
+    def get(self, value_name: str = ''):
+        if not value_name:
+            return self.time.value
+        elif value_name == 'time':
+            return self.time.value
+
+
+#-------------------------------------------------------------------
+class gate_general(gate_base):
+    def __init__(self, name, sim_parent):
+        super().__init__(name, sim_parent)
+        self.general = sim_value('general', self, (float, int,))
+        
+       # self.time_factor = 0.0
+        
+       
+    def _reset(self):
+        super()._reset()
+        #self.general.set(np.nan)
+       
+
+    def set(self, value):
+        if isinstance(value, (float, int)):
+            self.general.set(float(value))
+        elif isinstance(value, type(self)):
+            self.general.set(value.general.value)
+
+
+    def get(self, value_name: str = ''):
+        if not value_name:
+            return self.general.value
+        elif value_name == 'general':
+            return self.general.value
+    
+
+    def _node_success(self, stepper): 
+        if not self._success_flag: return
+        self.general._node_success(stepper)
+        self._success_flag = False
+
+
+#-------------------------------------------------------------------
+class gate_dynamic(gate_base):
+    def __init__(self, name, sim_parent):
+        super().__init__(name, sim_parent)
+        self.Dyn_Values : dict = dict()
+        
+
+    def Init(self, values):
+        super().Init(values)
+        if not isinstance(values, dict): raise Exception('das ist kein Dictionary')
+        for key, value in values.items():
+            base_val = sim_value(key, self, value['type'])
+            base_val.Init(value['value'], value['default'], value['unit'])
+            self.Dyn_Values.update({key : base_val})
+            setattr(self,key,base_val)
+
+
+    def _reset(self):
+        super()._reset()
+        for val in self.Dyn_Values.values():
+            val._value = val._default_value
+       
+      
+    def set(self, value, value_name):
+        if not isinstance(value_name, str): 
+            raise Exception('Name nich korrekt')
+        if not value_name in self.Dyn_Values.keys():
+            raise Exception('Name nich korrekt')
+        
+        val = self.Dyn_Values[value_name]
+
+        if not isinstance(value, val.value_type):
+            raise Exception('Falscher typ')
+        val.set(value)
+        
+
+
+    def get(self, value_name: str = ''):
+        if not isinstance(value_name, str): 
+            raise Exception('Name nich korrekt')
+        if not value_name in self.Dyn_Values.keys():
+            raise Exception('Name nich korrekt')
+        
+        return self.Dyn_Values[value_name]._value
+
+
+    def _node_success(self, timer): 
+        if not self._success_flag: return
+        for val in self.Dyn_Values.values():
+            val._value = val._node_success(timer)
+        self._success_flag = False
+
+
+    def _actual_values(self, timer):
+        for val in self.Dyn_Values.values():
+            val.get_set(timer)
+
+
+class gate_dataframe(gate_base):
+    def __init__(self, name, sim_parent):
+        super().__init__(name, sim_parent)
+        self.dataframe = sim_value('dataframe', self, (pd.DataFrame,))
+    
+       
+    def _reset(self):
+        super()._reset()
+        #self.dataframe.set(0.0)
+
+
+    def _add_logger(self, logger):
+        super()._add_logger(logger)  
+
+
+    def set(self, value):
+        if isinstance(value, (float, int)):
+            self.dataframe.set(float(value))
+        elif isinstance(value, type(self)):
+            self.dataframe.set(value.dataframe.value)
+
+
+    def get(self, value_name: str = ''):
+        if not value_name:
+            return self.dataframe.value
+        elif value_name == 'dataframe':
+            return self.dataframe.value
+    
+
+    def _node_success(self, stepper): 
+        if not self._success_flag: return
+        self.dataframe._node_success(stepper)
+        self._success_flag = False
+
+
+
+#*****************************************************************
+class step_base():
+    def __init__(self, name : str,  GUI : bool = False):
+        self.name = name
+        self.step_nr: int = 0
+        self.total_steps: int = 0
+        self.work_objs = [ ] # Diese Objekte sind mit dem Timer verknüpft
+        self.sim_funcs : dict = {}# Ersetzt self.work_objs und self.work_funcs
+        self._loggerlist : set = set() 
+        
+        self._GUI_visible = GUI
+        self._GUI_itemlist : dict = dict()
+        self.GUI_Item =  self._create_gui()
+        self._GUI_is_visible = False
+
+        self.info = widgets.Output()
+
+
+
+    def on_start_clicked(self, args):
+        parent = args.parent
+        parent.reset()
+        #with self.info:
+          #  print('Hier')
+       
+        # for obj in parent.work_objs:
+        #     if obj._GUI_is_visible:
+        #         obj.Init_Over_GUI()
+        parent.work()
+      
+
+    def Show_GUI(self):
+        for obj in self.work_objs:
+            if obj._GUI_visible:
+                obj.Show_GUI()
+        if self.GUI_Item:
+            self._GUI_is_visible = True
+            display(self.GUI_Item, self.info)
+            #with self.info:
+            #    print('Na dann wollen wir mal')    
+
+
+    def _create_gui(self):
+        for widget in self._GUI_itemlist.values():
+            setattr(widget, 'parent', self)
+        return None
+     
+
+    def reset(self):
+        self.step_nr = 0
+        
+
+
+    def Init(self, work_objs : list = []):
+        self.step_nr = 0
+        if not work_objs: raise Exception(f'obj : {self.name} |wenigstens eine start Methode muss angeben werden!')
+        self.work_objs = [] # Diese Objekte sind mit dem Timer verknüpft
+        
+        for func_to_analyse in work_objs:
+            func_info = analyse_func(func_to_analyse)
+            if not func_info:raise Exception(f'obj : {self.name} Startfunktion nicht korrekt')
+            if not isinstance(func_info[0], work_base):raise Exception(f'obj : {self.name} |node ist kein Type von work_base')
+            self.work_objs.append(func_info[0])
+            if not callable(func_info[1]): raise Exception(f'obj : {self.name} |node hat keine func_work methode')
+            gate = func_info[0].ch_type('Timer_Summe', self)
+            gate.set(0.0)
+            self.sim_funcs.update(
+                {func_info[1] : {
+                    'obj' : func_info[0],
+                    'gate' : gate}})
+ 
+
+    def work(self):
+        for obj in self.work_objs:
+            if obj._GUI_is_visible:
+                obj.Init_Over_GUI()
+
+        for obj in self.work_objs:
+            obj.ready_for_start(self)
+        for logger in self._loggerlist:
+            logger.ready_for_start(self)
+
+        if self._GUI_visible: pass 
+        while self.step() == 1:
+            self._node_success()
+            
+        for obj in self.work_objs:
+            obj.ready_for_end()
+
+        for logger in self._loggerlist:
+            logger.ready_for_end()
+         
+
+    def step(self):
+        for obj in self.work_objs:
+                obj._reset() #Todo ist das immer erforderlich?
+           
+        for func, values in self.sim_funcs.items():
+            func(stepper = self, Gate_In = values['gate'])
+            values['obj']._node_success(stepper = self)
+
+        self.step_nr = self.step_nr + 1
+
+
+    def _add_logger(self, logger):
+        if isinstance(logger, set):
+            self._loggerlist.update(logger)
+        elif isinstance(logger, port_base):
+            self._loggerlist.add(logger)
+
+
+    def _del_logger(self, logger):
+        self._loggerlist.remove(logger)
+
+
+    def _node_success(self): pass 
+
+
+class step_range(step_base):
+    def __init__(self, name : str,  GUI : bool = False):
+        super().__init__(name, GUI)
+        self.total_steps = sim_value('total_steps', self, (float, int,)) 
+        self.Gate_Step: gate_general = gate_general( 'Gate_Step', self)
+
+
+    def Init(self, 
+            work_objs : list = [],
+            total_steps  = 1
+            ):
+
+        super().Init(work_objs=work_objs)
+        self.total_steps.Init(total_steps, 1)
+        self.step_nr = 0
+       
+
+    def _create_gui(self):
+        
+        start_button = widgets.Button(description='Calc')  
+        start_button.on_click(self.on_start_clicked)
+        total_box = widgets.VBox([start_button])
+
+        self._GUI_itemlist.update({
+            'start_button' : start_button
+        })
+        super()._create_gui()# Attention! --must-- because the widget get a parent attr.
+        return  total_box
+     
+
+
+
+    # ergebnis 1 ein step
+    # 0 kein step 
+    def step(self):
+        if self.step_nr <= self.total_steps.get_set(self):
+            self.Gate_Step.set(self.step_nr)
+            super().step()
+            return 1
+        else: return 0
+        
+
+    def _node_success(self): 
+        super()._node_success()
+        self.Gate_Step._node_success(self)
+
+
+
+class step_single(step_base):
+    def __init__(self, name : str,  GUI : bool = False):
+        super().__init__(name, GUI)
+        
+        
+    def Init(self,  work_objs : list = []):
+        super().Init(work_objs=work_objs)
+        self.step_nr = 0
+
+
+    # Später im Parent
+    def _create_gui(self):
+        start_button = widgets.Button(description='Calc')  
+        start_button.on_click(self.on_start_clicked)
+        total_box = widgets.VBox([start_button])
+
+        self._GUI_itemlist.update({
+            'start_button' : start_button
+        })
+      
+        super()._create_gui()# Attention! --must-- because the widget get a parent attr.
+        return  total_box
+     
+
+    def step(self):
+        if self.step_nr < 1:
+            super().step()
+            return 1
+        else: return 0
+        
+
+# ------------------------------------------------------------------
+class step_timer(step_base):
+    def __init__(self, name : str,  GUI : bool = False):
+        super().__init__(name, GUI)
+
+        self.abs_start = dt.datetime(1, 1, 1, 0, 0, 0)
+        self.start: dt.datetime = dt.datetime(1, 1, 1, 0, 0, 0)
+        self.ende: dt.datetime = dt.datetime(1, 1, 1, 1, 0, 0)
+        self.actual: dt.datetime = self.start
+        self.step_width: str = 's'
+        self.step_count: int = 0
+        self.total_sec: int = 0
+        self._max_sec: int = 0 
+        self._step_sec : int = 0
+        self.step_props = dict(s=1, m=60, h=3600, d=86400, m15=900)
+
+        self.Gate_Time: gate_time = gate_time( 'Gate_Time', self)
+           
+        self.factor : float = self.step_props[self.step_width] / 3600.0 
+       
+              
+    def Init(self, 
+            work_objs : list = [],
+            start = '0001-01-01 00:00:00',
+            ende = '0001-01-01 01:00:00',
+            stepwidth = 's'
+            ):
+        
+        super().Init(work_objs=work_objs)
+ 
+        self.start = dt.datetime.strptime(start, sim_g.timepattern)
+        self.ende = dt.datetime.strptime(ende, sim_g.timepattern)
+        if not self.start < self.ende: raise Exception('ende vor start')
+        
+        self.step_width = stepwidth
+        if not self.step_width in self.step_props.keys():raise Exception('step_width nicht bekannt (s,m,h,d, m15)')    
+
+        self.actual = self.start
+        self._step_sec = self.step_props[self.step_width]
+        self.Gate_Time.set(self.actual) 
+        self.total_sec = 0
+        self._max_sec = int((self.start - self.abs_start).total_seconds())
+    
+        self.total_steps = int(self._max_sec /self.step_props[self.step_width])
+        self.factor : float = self.step_props[self.step_width] / 3600.0 
+
+    # ergebnis 1 ein step
+    # 0 kein step act_time < self.start
+    # -1 kein step act_time > self.ende
+    def step(self):
+        relation_time = self.actual
+        if relation_time < self.start: return 0
+        
+        if (relation_time >= self.start) and (relation_time < self.ende):
+            # Mache einen step
+            self.total_sec = self.total_sec + self.step_props[self.step_width]
+            self.actual = self.actual + \
+                dt.timedelta(seconds=self.step_props[self.step_width])
+            self.Gate_Time.time.set(self.actual)
+            super().step()
+            return 1
+
+        if self.actual >= self.ende: return -1
+            
+
+
+    def _node_success(self):
+        super()._node_success()
+        self.Gate_Time._node_success(self)
+    
+
+
+#*****************************************************************
+class work_base():
+    def __init__(self, name: str, GUI : bool = False, **kwargs):
+        
+        self.name = name
+        self._ctrl_ok : bool = False
+        
+        self._GUI_visible = GUI
+        self._GUI_itemlist : dict = dict()
+        self.GUI_Item =  None
+        self._GUI_is_visible = False
+
+        self.info = widgets.Output()
+   
+    def Init(self): pass
+       
+    def ready_for_start(self, timer: step_timer): pass
+       
+    def ready_for_end(self):pass
+
+
+    def _create_gui(self):
+        for widget in self._GUI_itemlist.values():
+            setattr(self, 'parent', widget)
+        return None
+     
+
+    def Show_GUI(self):
+        #display(self.info)
+        if not self.GUI_Item:
+            self.GUI_Item =  self._create_gui()
+        self._GUI_is_visible = True
+        display(self.GUI_Item)
+
+
+class gui_base(work_base):
+    def __init__(self, name: str, GUI : bool = False,  **kwargs):
+        super().__init__(name, GUI, **kwargs)
+       
+
+    def ready_for_start(self, stepper: step_base):pass
+    
+    def ready_for_end(self):pass
+        
+    def Init(self): super().Init()
+       
+    def Init_by_dataframe(self, dataframe): pass
+
+
+
+# ------------------------------------------------------------------
+class port_base(work_base):
+    def __init__(self, name: str, GUI : bool = False,  **kwargs):
+        super().__init__(name, GUI, **kwargs)
+        self.buffer_data: dict = dict()
+        self.col_name : list = list()
+        self.Gui_For_Data : gui_base = None
+
+
+    def clear_buffer(self):
+        for key in self.buffer_data.keys():
+            self.buffer_data[key] = []
+
+
+    def ready_for_start(self, stepper: step_base):
+        self.clear_buffer()
+
+
+    def ready_for_end(self):pass
+        
+        #with self.info:
+        #    print('ready_for_end')
+
+
+    def reset_ports(self, port_parentname: str):
+        if port_parentname in self.ports.keys():
+            self.ports[port_parentname] = dict()
+
+
+    def Init(self,  
+            Values = [],
+            Gui_For_Data  = None,
+        ):
+        super().Init()
+        self.Gui_For_Data = Gui_For_Data
+        self.buffer_data: dict = dict()
+        for value in Values:
+            if isinstance(value, sim_value):
+                name = value._add_logger(self)
+                self.buffer_data.update({name: []})
+            elif isinstance(value, Callable):
+                for item in value(self):
+                    self.buffer_data.update({item: []})
+        self.col_name = list(self.buffer_data.keys())     
+
+
+    def _add_value(self, name, value):
+        if name in self.buffer_data.keys():
+            self.buffer_data[name].append(value)
+
+
+# -------------------------------------------------------------------
+class sim_base(work_base):
+
+    def __init__(self, name: str, GUI : bool = False,  **kwargs):
+        super().__init__(name, GUI, **kwargs)
+        self.time_factor: float = 0.0
+        self.ch_type: gate_base = None
+        
+        if 'ch_type' in kwargs.keys():
+            self.ch_type = kwargs['ch_type']
+            if isinstance(self.ch_type, str):
+                self.ch_type = Main_Modul.sim_obj_factory.get_classtype_by_name(
+                    self.ch_type)
+
+            if not issubclass(self.ch_type, gate_base): raise Exception('ist nicht vom Type gate_base abgeleitet')
+           
+        self._loggerlist : set = set()
+        self._funcgate : dict = {}
+
+       
+        
+    def _getgate_func(self, func : Callable):
+        if func in self._funcgate.keys():
+            return self._funcgate[func]
+        return None
+  
+    def _node_success(self, timer: step_timer):pass
+      
+
+    def _reset(self):pass
+
+
+    def _add_logger(self, logger):
+        self._loggerlist.add(logger)
+
+
+    def _del_logger(self, logger):
+        self._loggerlist.remove(logger)
+
+
+    def ready_for_start(self, stepper: step_base):
+        super().ready_for_start(stepper)
+        self._reset()
+        if isinstance(stepper, step_timer):
+            self.time_factor = stepper.factor
+        stepper._add_logger(self._loggerlist)
+
+
+    def log_all(self, logger):
+        name_list = []
+        for key, value in self.__dict__.items(): 
+            if issubclass(type(value), sim_value):   
+                name_list.append(value._add_logger(logger))
+            elif issubclass(type(value), gate_base):
+                name_list = name_list + value.log_all(logger)
+        return name_list
+
+
+        
+    def Init_Over_GUI(self): pass
+       
+       
+      
+
+class ctrl_base():
+    def __init__(self, name : str, gate_type : gate_base):
+        super().__init__()
+        self._parent = None
+        self.name = name
+        self.Gate_Ctrl = gate_type('Gate_Ctrl', self)
+       
+
+    def Do(self,  timer: step_timer, Summe: gate_general):
+        pass
+
+    def _init(self, parent):
+        self._parent = parent
+        return self.Do
+
+    def ready_for_start(self, timer: step_timer): pass
+       
+    def ready_for_end(self):pass
+    
+    def _reset(self):
+        self.Gate_Ctrl.reset() 
+
+#*****************************************************************#--------------------------------------------------------------------
+class ctrl_general_factor(ctrl_base):
+    def __init__(self, name : str = 'ctrl_general_factor', gate_type : gate_base = gate_general, Factor = 1.0):
+        super().__init__(name, gate_type)
+        self.Factor = sim_value('Factor', self, (float, int,))
+        self.Factor.Init(Factor)
+
+
+    def Do(self,  timer: step_timer, Gate_In: gate_general):
+        self.Gate_Ctrl.general._value = Gate_In.general._value * self.Factor.get_set(stepper=timer)
+        return self.Gate_Ctrl
+
+
+class ctrl_general_rest(ctrl_base):
+    def __init__(self, name : str = 'ctrl_general_rest', gate_type : gate_base = gate_general):
+        super().__init__(name, gate_type)
+        
+      
+    def Do(self,  timer: step_timer, Gate_In: gate_general):
+        sum = self._parent.Gate_In.general._value
+        for gate  in self._parent._sequence_work[self._parent.Sequence_Key]['gates']:
+            sum = sum + gate.general._value
+        self.Gate_Ctrl.set(sum)
+        #self._parent.Gate_Node.set(sum)
+        return self.Gate_Ctrl
+
+
+class ctrl_general_set(ctrl_base):
+    def __init__(self, name : str = 'ctrl_general_rest', gate_type : gate_base = gate_general, Value = 0.0):
+        super().__init__(name, gate_type)
+        self.Value = sim_value('Factor', self, (float, int,))
+        self.Value.Init(Value)
+      
+
+    def Do(self,  timer: step_timer, Gate_In: gate_general):
+        self.Gate_Ctrl.general._value = self.Value.get_set(timer)
+        return self.Gate_Ctrl  
+       
+
+class ctrl_general_zero(ctrl_general_rest):
+    def __init__(self, name : str = 'ctrl_general_zero', gate_type : gate_base = gate_general):
+        super().__init__(name, gate_type)
+      
+
+    def Do(self,  timer: step_timer, Gate_In: gate_general):
+        super().Do(timer = timer, Gate_In = Gate_In)
+        if (abs(self.Gate_Ctrl.general._value) < 0.0000001): 
+            self._parent._ctrl_ok = True 
+        return self.Gate_Ctrl
+
+
+class ctrl_general_step(ctrl_base): 
+    def __init__(self, name : str = 'ctrl_general_step', gate_type : gate_base = gate_general):
+        super().__init__(name, gate_type)
+        self.Gate_In = gate_general('Gate_In', self)
+        self._Gate_Step = gate_general('_Gate_Step', self)
+        self._sequence_work : dict = None
+        self.Sequence_Key : str = ''
+
+
+    def _init(self, parent):
+        super()._init(parent)
+        self._sequence_work = parent._sequence_work
+        self.Sequence_Key = parent.Sequence_Key
+
+    def Do(self, timer: step_timer, Gate_In: gate_general):
+            self._ctrl_ok = False
+            self.Gate_In.general._value = Gate_In.general._value
+            self._Gate_Step.general._value = Gate_In.general._value
+            for gate_func in self._sequence_work[self.Sequence_Key]['funcs']:
+                gate = gate_func(timer, self.Summe)
+                self._Gate_Step.general._value = gate.general._value
+                if self._ctrl_ok: 
+                    self.Gate_Ctrl.set(0.0)
+                    return self.Gate_Ctrl
+                
+            sum = 0
+            for gate  in self._sequence_work[self.Sequence_Key]['gates']:
+                sum = sum + gate.general._value
+            self.Gate_Ctrl.set(sum)
+            return self.Gate_Ctrl
+
+
+#*****************************************************************
+class sim_dynamic(sim_base):
+    def __init__(self, name: str, GUI : bool = False,  **kwargs):
+        kwargs.update({'ch_type' : gate_general}) 
+        super().__init__(name, GUI, **kwargs)
+        
+        self.Gate_Dynamic = gate_dynamic('Gate_Dynamic', self)
+        self.Feature : dict = None
+        self._funcgate.update({
+                self.Do : self.Gate_Dynamic})
+        
+        
+    def _reset(self):
+        self.Gate_Dynamic._reset()
+        super()._reset()
+
+
+    def _node_success(self, timer: step_timer):
+        self.Gate_Dynamic._node_success(timer)
+
+
+    def Init(self, Feature : None):
+        super().Init()  
+        self.Feature = Feature
+        self.Gate_Dynamic.Init(self.Feature)
+
+
+    def Do(self,  timer: step_timer, Gate_In: gate_general):
+        self.Gate_Dynamic._actual_values(timer)
+        return self.Gate_Dynamic
+
+
+#--------------------------------------------------------------------  
+class sim_general_node(sim_base):
+    def __init__(self, name: str, GUI : bool = False,  **kwargs):
+        kwargs.update({'ch_type' : gate_general}) 
+        super().__init__(name, GUI, **kwargs)   
+        
+        self._iterat_counter : int = 0
+        self.Max_Iterat = sim_value('Max_Iterat', self, (int,)) 
+        self.Gate_Node = gate_general('Gate_Node', self)
+        self.Summe = gate_general('Summe', self)
+        self.Gate_In = gate_general('Gate_In', self)
+
+        #Controll Strukturen
+        self._ctrl_nodeok : bool = False
+        
+        self.Sequence: dict = dict() # beinhaltet den vollen Namen und die Instance
+        self.Sequence_Key: str = ''
+
+        self._sequence_work : dict = dict() # beinhaltet verschiedene Informationen für verschiedene Aufgaben wird gebildet
+        self._sequence_sims : set = set() # speichert alle verlinken sims
+        self._sims_gates : dict = dict()
+        self.Joker : sim_general_joker = None
+
+        self._funcgate.update({
+                self.Step : self.Gate_Node,
+                self.StepRec : self.Gate_Node,
+                self.SumEqual : self.Gate_Node})
+
+
+    def Init(self, 
+                Sequence = None,
+                Sequence_Key = '',
+                Joker = False,
+                Max_Iterat = -1
+                ):
+
+        super().Init()
+        self.Max_Iterat.Init(Max_Iterat)
+
+        if Joker:  self.Joker = sim_general_joker(self.name + '.joker')
+           
+        if not isinstance(Sequence, dict): 
+            raise Exception(f'Sequence ist kein dict')
+        self.Sequence = Sequence
+       
+
+        for sequence_name, sequence_list in self.Sequence.items():
+            self._sequence_work.update({sequence_name : {
+                'func_names' : [],
+                'funcs' : [],
+                'sims' : set(),
+                'gates' : set()
+            }})
+         
+            for seq_item in sequence_list:
+                if isinstance(seq_item, ctrl_base):
+                    seq_item = seq_item._init(self)
+
+                func_info = analyse_func(seq_item)
+                if not func_info:
+                    raise Exception(f'obj : {self.name} Startfunktion nicht korrekt')
+                if not isinstance(func_info[0], (work_base, ctrl_base,)):
+
+                    raise Exception(f'obj : {self.name} | {func_info[0].name}|node ist kein Type von work_base')
+                if not callable(func_info[1]): 
+                    raise Exception(f'obj : {self.name} |node hat keine func_work methode')
+                     
+                self._sequence_work[sequence_name]['func_names'].append(func_info[2])
+                self._sequence_work[sequence_name]['funcs'].append(func_info[1])
+                if isinstance(func_info[0], work_base):
+                    self._sequence_work[sequence_name]['sims'].add(func_info[0])
+                self._sequence_sims.add(func_info[0])
+                
+        if not Sequence_Key :  
+            self.Sequence_Key = next(iter(self._sequence_work)) # Der erste wird gewählt
+        elif Sequence_Key in self._sequence_str.keys():
+            self.Sequence_Key = Sequence_Key
+        else: raise Exception(f'Sequence_Key {Sequence_Key} nicht vorhanden!')
+         
+
+    def ready_for_start(self, timer: step_timer):
+        super().ready_for_start(timer)
+        for sim_obj in self._sequence_sims:
+            if sim_obj == self: 
+                continue
+            sim_obj.ready_for_start(timer)
+        
+        for func in self._sequence_work[self.Sequence_Key]['funcs']:
+            for sim_obj in self._sequence_work[self.Sequence_Key]['sims']:
+                gate = sim_obj._getgate_func(func)
+                if isinstance(gate, gate_base):
+                    self._sequence_work[self.Sequence_Key]['gates'].add(gate)
+                    break
+            
+            #raise Exception('gate to Funktion not found')      
+   
+   
+    #----------------------- Simulations Steps ---------------------------------
+    def _reset(self):
+        super()._reset()
+        self.Gate_Node._reset()
+        self.Gate_In._reset()
+        self.Summe._reset()
+        self._iterat_counter = 0
+        for sim_obj in self._sequence_work[self.Sequence_Key]['sims']:
+            if sim_obj == self: 
+                continue
+            sim_obj._reset()
+        if not self.Joker == None:
+            self.Joker._reset()
+
+
+    def _calc_node(self):
+        sum = 0.0
+        for gate  in self._sequence_work[self.Sequence_Key]['gates']:
+            sum = sum + gate.get()
+          
+        sum = sum - self.Gate_Node.get()
+        self.Summe.set(sum)
+        if (abs(sum) < 0.0000001):
+            return True
+        return False
+
+
+    def _node_success(self, timer: step_timer):
+        for sim_obj in self._sequence_work[self.Sequence_Key]['sims']:
+            if sim_obj == self: continue
+            sim_obj._node_success(timer)
+        
+        if not self.Joker == None:
+            self.Joker._node_success(timer)
+
+        super()._node_success(timer)
+        self.Gate_Node._node_success(timer)
+        self.Gate_In._node_success(timer)
+
+
+
+    def sum_master(self, timer: step_timer, Summe: gate_base = None):
+        master_gate : gate_general =  gate_general('master_gate', self)
+        master_sum : gate_general = gate_general('master_sum', self)
+        
+        if isinstance(Summe, self.ch_type):
+            self.Summe.set(Summe)
+            self.Gate_Node.set(Summe)
+        else:
+            self.Summe.set(0.0)
+        
+        old_master = 0.0
+        new_master = 0.0
+        master_sum.set(old_master)
+        while True:
+            master_func = self._sequence_work[self.Sequence_Key]['funcs'][0]
+            value = master_func(timer,  master_sum).general.value
+            master_gate.set(-value)
+            for gate_func in self._sequence_work[self.Sequence_Key]['funcs'][1:]:
+                gate_func(timer, master_gate)
+                   
+            if self._calc_node():
+                self._node_success(timer)
+                return self.Gate_Node
+            
+            new_master = master_gate.general.value + self.Summe.general.value
+            master_sum.general.value = new_master
+            if abs(new_master - old_master) < 0.0000001:
+                break
+           
+            old_master = new_master
+        
+        if self.Joker:
+            self.Joker.Var(timer, self.Summe)
+            #if self._calc_node():
+            self._node_success(timer)
+        return self.Gate_Node
+        
+
+    def SumEqual(self, timer: step_timer, Summe: gate_base = None):
+        self.Summe.general.value = Summe.general.value
+        # Hier eine Zählschleife um weitere Informationen über den Ablauf zu erhalten
+        
+        for gate_func in self._sequence_work[self.Sequence_Key]['funcs']:
+            gate_func(timer, self.Summe)
+            if self._ctrl_nodeok:
+               return self._ctrl_nodeok
+           
+
+        if self.Joker:
+            self.Joker.Var(timer, self.Summe)
+        return self.Gate_Node
+
+
+   
+    def Step(self, timer: step_timer, Gate_In: gate_base = None):
+        self._ctrl_ok = False
+        self.Gate_In.general._value = Gate_In.general._value
+        self.Summe.general._value = Gate_In.general._value
+        for gate_func in self._sequence_work[self.Sequence_Key]['funcs']:
+            if gate_func == self.Step: # Verhindern von  rekursiven Aufrufs
+                continue
+            gate = gate_func(timer, self.Summe)
+            self.Summe.general._value = gate.general._value
+            if self._ctrl_ok: 
+                self.Gate_Node.set(0.0)
+                return self.Gate_Node
+               
+        #sum = self.In.general._value
+        sum = 0
+        for gate  in self._sequence_work[self.Sequence_Key]['gates']:
+            sum = sum + gate.general._value
+        self.Gate_Node.set(sum)
+        return self.Gate_Node
+  
+      
+    #Rekursiver aktiver Chanal von Step
+    # ruft sich selber auf wenn kein 0 erreicht ist am Ende 
+    def StepRec(self, timer: step_timer, Gate_In: gate_base = None, counter : int = 0):
+        max_iterat = self.Max_Iterat.get_set(timer)
+        
+        self._ctrl_ok = False
+        self.Gate_In.general._value = Gate_In.general._value
+        self.Summe.general._value = Gate_In.general._value
+        for gate_func in self._sequence_work[self.Sequence_Key]['funcs']:
+            gate = gate_func(timer, self.Summe)
+            if gate_func == self.Step: # Verhindern von  rekursiven Aufrufs
+                continue
+                
+            self.Summe.general._value = gate.general._value
+            if self._ctrl_ok: # rekursion beenden
+                self.Gate_Node.set(0.0)
+                return self.Gate_Node
+       
+        counter = counter + 1
+        if (max_iterat >= 0) and (counter < max_iterat):
+            for sim_obj in self._sequence_work[self.Sequence_Key]['sims']:
+                if sim_obj == self: continue
+                sim_obj._reset()
+            self.StepRec(timer=timer, Gate_In=Gate_In, counter = counter)     
+            
+
+        sum = 0
+        for gate  in self._sequence_work[self.Sequence_Key]['gates']:
+            sum = sum + gate.general._value
+        self.Gate_Node.set(sum)
+        return self.Gate_Node
+
+
+
+    def ready_for_end(self):
+        super().ready_for_end()
+        for sim_obj in self._sequence_sims:
+            if sim_obj == self:continue 
+            sim_obj.ready_for_end()
+
+
+class sim_general_chanal(sim_base):
+    def __init__(self, name: str, GUI : bool = False,  **kwargs):
+        kwargs.update({'ch_type' : gate_general}) 
+        super().__init__(name, GUI, **kwargs)
+        
+        self.Gate_Set = gate_general('Gate_Set', self)
+        self.Gate_Get = gate_general('Gate_Get', self)
+        self.Gate_Chanal = gate_general('Gate_Chanal', self)
+        
+        self._funcgate.update({
+                self.Set : self.Gate_Set,
+                self.Get : self.Gate_Get})
+
+
+    def Init(self, Gate_Set = None, Gate_Get = None):
+        super().Init()
+        self.Gate_Set.Init(Gate_Set)
+        self.Gate_Get.Init(Gate_Get)
+        self.Gate_Chanal.Init(None)
+
+        
+
+    def Set(self,  timer: step_timer, Gate_In: gate_general):
+        self.Gate_Set.general._value = -Gate_In.general._value
+        self.Gate_Chanal.general._value = Gate_In.general._value
+        self.Gate_Get.general._value = 0
+        return self.Gate_Set
+
+
+    def Get(self,  timer: step_timer, Gate_In: gate_general):
+        self.Gate_Get.general._value = -self.Gate_Set.general._value
+        self.Gate_Set.general._value = 0
+        return self.Gate_Get
+
+    
+    def _reset(self):
+        self.Gate_Set._reset()
+        self.Gate_Get._reset()
+        self.Gate_Chanal._reset()
+        super()._reset()
+
+
+    def _node_success(self, timer: step_timer):
+        self.Gate_Set._node_success(timer)
+        self.Gate_Get._node_success(timer)
+        self.Gate_Chanal._node_success(timer)
+
+
+
+class sim_general_user(sim_base):
+    def __init__(self, name: str, **kwargs):
+        
+        kwargs.update({'ch_type' : gate_general})   
+        super().__init__(name, **kwargs)
+        self.Gate_User = gate_general('Gate_User', self)
+        self.User_Func = sim_value('UserFunc', self, (float, int,)) 
+        self._funcgate.update({
+                self.User : self.Gate_User})
+        
+       
+    def Init(self,  
+            User_Func = None,
+            Gate_User = None
+        ):
+
+        super().Init()
+        self.Gate_User.Init(Gate_User)
+        self.User_Func.Init(User_Func)
+      
+
+    def User(self,  timer: step_timer, Gate_In: gate_general):
+        gate = self.User_Func.get_set(stepper = timer, value = Gate_In)
+        self.Gate_User.general._value = gate.general._value
+        return self.Gate_User
+
+    
+    def _reset(self):
+        self.Gate_User._reset()
+        super()._reset()
+
+
+    def _node_success(self, timer: step_timer):
+        self.Gate_User._node_success(timer)
+
+
+
+#TODO ergänzen um pulswidth von 0..1 
+#TODO absolute zeit bezogen auf s einführen
+#TODO verschiedene Formen auswählen
+class sim_general_signal(sim_base):
+    def __init__(self, name: str, GUI : bool = False,  **kwargs):
+        kwargs.update({'ch_type' : gate_general}) 
+        super().__init__(name, GUI, **kwargs)
+        
+        self.Gate_Signal = gate_general('Gate_Signal', self)
+        
+        self.Frequency = sim_value('Frequency', self, (float, int,)) 
+        self.Amplitude = sim_value('Amplitude', self, (float, int,)) 
+        self.Offset = sim_value('Offset', self, (float, int,)) 
+        
+        self._max_val: float = 0
+        self._min_val: float = 0
+        self._funcgate.update({
+                self.Fix : self.Gate_Signal})
+        
+       
+    def Init(self,  
+            Amplitude = None,
+            Frequency = None,
+            Offset = None,
+            Gate_Signal = None
+        ):
+
+        super().Init()
+        self.Gate_Signal.Init(Gate_Signal)
+        self.Amplitude.Init(Amplitude)
+        self.Frequency.Init(Frequency)
+        self.Offset.Init(Offset)
+
+        self._max_val = self.Amplitude.value - self.Offset.value
+        self._min_val = self.Offset.value
+
+
+    def Fix(self,  timer: step_timer, Gate_In: gate_general):
+        value = int(timer.step_nr / self.Frequency.value)
+        if value % 2:  # ungrade
+            self.Gate_Signal.set(self._min_val)
+        else:  # grade
+            self.Gate_Signal.set(self._max_val)
+        return self.Gate_Signal
+
+    
+    def _reset(self):
+        self.Gate_Signal._reset()
+        super()._reset()
+
+
+    def _node_success(self, stepper: step_base):
+        self.Gate_Signal._node_success(stepper)
+
+
+#--------------------------------------------------------------------
+class sim_general_joker(sim_base):
+    def __init__(self, name: str, GUI : bool = False,  **kwargs):
+        kwargs.update({'ch_type' : gate_general}) 
+        super().__init__(name, GUI, **kwargs)
+      
+
+    def Init(self,
+        Gate = None):
+        super().Init()
+        self.Gate.Init(Gate)
+
+
+    def _reset(self):
+        self.Gate._reset()
+        super()._reset()
+
+
+    def _node_success(self, timer: step_timer):
+        self.Gate._node_success(timer)
+
+
+    def Var(self,  timer: step_timer, Summe: gate_general):
+        self.Gate.general.set(-Summe.general.value)
+        return self.Gate
+
+#TODO ch_type raus
+#--------------------------------------------------------------------
+class sim_general_store(sim_base):
+    def __init__(self, name: str, GUI : bool = False,  **kwargs):
+        kwargs.update({'ch_type' : gate_general}) 
+        super().__init__(name, GUI, **kwargs)
+        
+        self.Gate_Store = gate_general('Gate_Store', self)
+        self.Gate_Leak = gate_general('Gate_Leak', self)
+        self.Capacity_Actual = sim_value('Capacity_Actual', self, (float, int,))
+        self.Leak_Capacity_Actual = sim_value('Leak_Capacity_Actual', self, (float, int,))
+
+        self.Capacity_Max = sim_value('Capacity_Max', self, (float, int,))  # Wenn None dann unendlich +
+        self.Capacity_Min = sim_value('Capacity_Min', self, (float, int,))  # Wenn None dann unendlich -
+        self.Load_Max = sim_value('Load_Max', self, (float, int,))  # Wenn None dann unendlich schnelles beladen
+        self.Unload_Max = sim_value('Unload_Max', self, (float, int,))  # Wenn None dann unendlich schnelles entladen
+        self.Leak_Rate = sim_value('Leak_Rate', self, (float, int,))
+        self.Factor = sim_value('Factor', self, (float, int,))
+        self.Invert = sim_value('invert', self, (bool,))
+
+        self.func_leak : dict = {'leak_rate' : 0.0}
+
+        self._funcgate.update({self.Var : self.Gate_Store})
+       
+
+
+    def Init(self, 
+                Capacity_Max = None,
+                Capacity_Min = None,
+                Load_Max = None,
+                Unload_Max = None,
+                Leak_Rate = 0.0,
+                Gate_Store = 0.0, 
+                Gate_Leak = 0.0,
+                Capacity_Actual = 0.0,
+                Factor = 1.0,
+                Invert = False              
+                ):
+        """ Initialisiert den Speicher 
+
+        Keyword Arguments:
+            Capacity_Max {float oder funktion} -- maximale Kapazität des Speichers (default: {None})
+                Kein Wert (None) Speichergröße im positiven Bereich unbegrenzt
+            Capacity_Min {[type]} -- [description] (default: {None})
+            Load_Max {[type]} -- [description] (default: {None})
+            Unload_Max {[type]} -- [description] (default: {None})
+            Gate_Store {[type]} -- [description] (default: {None})
+            Gate_Leak {[type]} -- [description] (default: {None})
+            Capacity_Actual {[type]} -- [description] (default: {None})
+            Factor{[float, int]} Bereich üblicherweise zwischen 0.0 und 1.0
+        """        
+               
+        super().Init()
+
+        self.Gate_Store.Init(Gate_Store)
+        self.Capacity_Actual.Init(Capacity_Actual, default = 0.0)
+        self.Gate_Leak.Init(Gate_Leak)
+        self.Capacity_Max.Init(Capacity_Max)
+        self.Capacity_Min.Init(Capacity_Min)
+        self.Load_Max.Init(Load_Max)
+        self.Unload_Max.Init(Unload_Max)
+        
+        self.Factor.Init(Factor, default = 1.0)
+        self.Invert.Init(Invert, default = False)
+        if isinstance(Leak_Rate, (float, int,)):
+            self.func_leak['leak_rate'] = Leak_Rate 
+            Leak_Rate = self._leak
+        self.Leak_Rate.Init(Leak_Rate, default = 0.0)
+        
+      
+
+    def _reset(self):
+        self.Gate_Store._reset()
+        super()._reset()
+
+    # Es wird die Differenz berechnet
+    def _leak(self, value = None, timer : step_timer = None):
+        rate = self.func_leak['leak_rate']
+        akt_cap = self.Capacity_Actual.value
+        if rate == 0.0:
+            return 0.0
+        new_cap = akt_cap * math.exp(-rate * timer.total_sec)
+        return akt_cap - new_cap
+      
+
+
+    def calc_loadcapacity(self, value: float):
+        if not isinstance(self.Capacity_Max._value, (float, int,)):
+            return value
+        full_diff = (self.Capacity_Max._value -
+                           self.Capacity_Actual._value) / self.time_factor
+        if full_diff > value:
+            return value
+        elif full_diff == 0.0:
+            return 0.0
+        else:
+            return full_diff
+
+
+
+    def calc_unloadcapacity(self, value: float):
+        if not isinstance(self.Capacity_Min._value, float):
+            return value
+        empty_diff = -(self.Capacity_Min._value -
+                             self.Capacity_Actual._value) / self.time_factor
+        if empty_diff >= -value:
+            return value
+        elif empty_diff == 0:
+            return 0.0
+        else:
+            return -empty_diff
+
+    #TODO es sollte noch eine variante zu Var geben, um z.B. einfach Verluste Widerstände zu simulieren
+    def Var(self, timer: step_timer, Gate_In: gate_general):
+        aim_value = -Gate_In.general.value * self.Factor.get_set(timer)
+        if self.Invert.value : aim_value = -aim_value
+        if aim_value >= 0:  # Beladen
+            max_value = self.Load_Max.get_set(stepper=timer)
+            if max_value == None: # Keine Begrenzung
+                real_value = aim_value 
+            elif max_value >= 0 and max_value > aim_value:
+                real_value = aim_value 
+            elif max_value >= 0 and max_value <= aim_value:
+                real_value =  max_value  
+            elif max_value < 0:
+                real_value =  max_value
+        else:
+            max_value = self.Unload_Max.get_set(stepper=timer)
+            if max_value == None: # Keine Begrenzung
+                real_value = aim_value 
+            elif max_value <= 0 and max_value < aim_value:
+                real_value = aim_value 
+            elif max_value <= 0 and max_value >= aim_value:
+                real_value =  max_value  
+            elif max_value > 0:
+                real_value =  max_value
+
+        if real_value >= 0:  # Beladen
+            real_value = self.calc_loadcapacity(real_value)
+        else:  # Entladen
+            real_value = self.calc_unloadcapacity(real_value)
+        
+        self.Gate_Store.set(real_value) #Todo Set verbessern damit auch ein Callback erfolgt
+        return self.Gate_Store
+
+
+    # Immer den gleichen Wert speichern
+    def Fix_Load(self,  timer: step_timer, Summe: gate_general):
+        self.Gate_Store.set(self.Load_Max)
+        return self.Gate_Store, True
+
+
+    # Immer den gleichen Wert entladen
+    def Fix_Unload(self,  timer: step_timer, Summe: gate_general):
+        self.Gate_Store.set(self.Unload_Max)
+        return self.Gate_Store, True
+
+
+    def _node_success(self, timer: step_timer):
+        super()._node_success(timer)
+        
+        corr_value = self.Gate_Store.get() * self.time_factor
+        value = self.Capacity_Actual._value + corr_value
+        self.Capacity_Actual._value = value 
+
+        diff = self.Leak_Rate.get_set(stepper=timer) 
+        self.Capacity_Actual._value = self.Capacity_Actual._value - diff
+        #self.Leak_Capacity_Actual._value = self.Leak_Capacity_Actual._value + diff
+
+        self.Gate_Store._node_success(timer)
+        self.Capacity_Actual._node_success(timer)
+        self.Gate_Leak._node_success(timer)
diff --git a/nowo1_gui_base.py b/nowo1_gui_base.py
new file mode 100644
index 0000000..5cb8310
--- /dev/null
+++ b/nowo1_gui_base.py
@@ -0,0 +1,47 @@
+import sim_base as sim_g
+import nowo1_base as nowo
+import datetime as dt
+import pandas as pd
+import numpy as np
+
+import ipywidgets as widgets
+import ipysheet
+from ipysheet import from_dataframe
+from IPython.display import display
+
+
+
+class gui_ipysheet(nowo.gui_base):
+    def __init__(self, name: str, GUI : bool = False,  **kwargs):
+        super().__init__(name, GUI, **kwargs)
+        self.sheet : ipysheet.sheet = None 
+        self.sheet_colnames : list = []
+        self.sheet_rownames : list = []
+        self.sheet_data: pd.DataFrame = None  
+        self.dataframe_out: pd.DataFrame = None 
+
+
+    def Init_by_dataframe(self, dataframe):
+        self.sheet_data = dataframe
+        self.sheet_colnames = list(self.sheet_data.head())
+        self.sheet_rownames = list(self.sheet_data.index.tolist())
+
+
+    def ready_for_end(self):
+        buffer = self.sheet_data.values.T.tolist()
+        ipysheet.cell_range(buffer[0], column_start=1)
+       # self.dataframe_out = ipysheet.to_dataframe(self.sheet)
+        #self.sheet_data.to_clipboard()
+               
+    def _create_gui(self):
+       # sheet = ipysheet.sheet(rows = len(self.sheet_rownames) + 1, columns= len(self.sheet_colnames) + 1) 
+        self.sheet = ipysheet.sheet(rows = len(self.sheet_rownames),  
+                columns= len(self.sheet_colnames) + 1, 
+                column_headers = ['variable'] + self.sheet_colnames)
+     
+        cols_1 = ipysheet.column(0, self.sheet_rownames, row_start = 0)
+       
+        total_box = widgets.VBox([self.sheet])
+        self._GUI_itemlist.update({'sheet' : self.sheet})
+        super()._create_gui()# Attention! --must-- because the widget get a parent attr.
+        return  total_box
\ No newline at end of file
diff --git a/nowo1_log_base.py b/nowo1_log_base.py
new file mode 100644
index 0000000..c65b4f7
--- /dev/null
+++ b/nowo1_log_base.py
@@ -0,0 +1,85 @@
+import sim_base as sim_g
+import nowo1_base as nowo
+import datetime as dt
+import pandas as pd
+import numpy as np
+
+class logger(nowo.port_base):
+    def __init__(self, name: str, GUI : bool = False,  **kwargs):
+        super().__init__(name, GUI, **kwargs)
+        self.log_data: pd.DataFrame = pd.DataFrame()
+
+    def clear_buffer(self):
+        super().clear_buffer()
+        self.log_data = pd.DataFrame()
+
+    def ready_for_end(self):
+        super().ready_for_end()
+        self.log_data = pd.DataFrame(dict([ (k,pd.Series(v)) for k,v in self.buffer_data.items() ]))
+        
+
+
+# Nimmt nur den ersten Wert und bildet eine Tabelle
+# wird verwendet bei gleichen sim_obj die nur einmal berechnet wurden
+class log_sheet(nowo.port_base):
+    def __init__(self, name: str, GUI : bool = False,  **kwargs):
+        self.log_data: pd.DataFrame = pd.DataFrame()
+        super().__init__(name, GUI, **kwargs)
+        self.sheet_colnames : list = []
+        self.sheet_rownames : list = []
+        self.sheet_data: pd.DataFrame = None
+         
+    
+    def clear_buffer(self):
+        super().clear_buffer()
+        self.log_data = pd.DataFrame()
+
+
+    def Init(self,  Values = [], Gui_For_Data  = None, ):
+        super().Init(Values, Gui_For_Data)
+        for name in self.buffer_data.keys():
+            split_name = name.split('.', 1)
+            if not split_name[0] in self.sheet_colnames:
+                self.sheet_colnames.append(split_name[0])
+            if not split_name[1] in self.sheet_rownames:    
+                self.sheet_rownames.append(split_name[1])
+        self.sheet_data = pd.DataFrame(columns = self.sheet_colnames, index = self.sheet_rownames)
+        if self.Gui_For_Data:
+            self.Gui_For_Data.Init_by_dataframe(self.sheet_data)
+
+
+    def ready_for_end(self):
+        super().ready_for_end()
+        # self.log_data = pd.DataFrame(dict([ (k,pd.Series(v)) for k,v in self.buffer_data.items() ]))
+       
+        for col_name in self.sheet_colnames:
+            for row_name in self.sheet_rownames:
+                key_name = col_name + '.' + row_name
+                value = self.buffer_data[key_name]
+                self.sheet_data.at[row_name, col_name] = value
+        self.sheet_data.to_clipboard()
+        if self.Gui_For_Data:
+            self.Gui_For_Data.ready_for_end()
+
+
+
+class log_dataframe(nowo.port_base):
+    def __init__(self, name: str, GUI : bool = False,  **kwargs):
+        super().__init__(name, GUI, **kwargs)
+        self.log_data: pd.DataFrame = pd.DataFrame()
+
+    def clear_buffer(self):
+        super().clear_buffer()
+        self.log_data = pd.DataFrame()
+
+
+    def ready_for_end(self):
+        super().ready_for_end()
+        new = pd.DataFrame()
+        for name, valuelist in self.buffer_data.items():
+            for value in valuelist:
+                if isinstance(value, pd.DataFrame):
+                    new = pd.concat([new,value], ignore_index=True)
+
+        self.log_data = new
+        self.col_name = self.log_data.columns.tolist()
\ No newline at end of file
diff --git a/nowo1_sim_binary.py b/nowo1_sim_binary.py
new file mode 100644
index 0000000..953e140
--- /dev/null
+++ b/nowo1_sim_binary.py
@@ -0,0 +1,406 @@
+
+import sim_base as sim_g
+import nowo1_base as nowo
+import datetime as dt
+import pandas as pd
+import numpy as np
+import ipywidgets as widgets
+from IPython.display import display
+
+
+class binary_node(nowo.sim_base):
+    def __init__(self, name: str, **kwargs):
+        kwargs.update({'ch_type' : nowo.gate_general})   
+        super().__init__(name, **kwargs)
+        self.Gate_A = nowo.gate_general('Gate_A', self)
+        self.Gate_B = nowo.gate_general('Gate_B', self)
+        self.Gate_A_B = nowo.gate_general('Gate_A_B', self)
+
+        self.A_ratio = nowo.sim_value('A_ratio', self, (float, int,)) 
+        self.B_ratio = nowo.sim_value('B_ratio', self, (float, int,)) 
+        self.A_portion = nowo.sim_value('A_portion', self, (float, int,)) 
+        self.B_portion = nowo.sim_value('B_portion', self, (float, int,)) 
+        
+        self.Info = nowo.sim_value('Info', self, (str,)) 
+
+        self.calcflag : bool = True
+        self._value_key : np.byte = 0b00000000
+        
+    
+        self._checkstruct : dict = dict(
+            {'one_val' : [0,1,2,4,8,16,32,64]}
+        )
+
+        self._value_keys : dict = {
+            'A' :       0b01000000,
+            'B' :       0b00100000,
+            'A_B':      0b00010000,
+            'A_ratio':  0b00001000,
+            'B_ratio':  0b00000100,
+            'A_portion':0b00000010,
+            'B_portion':0b00000001
+        }
+
+        self._funcgate.update({
+                self.Calc_A : self.Gate_A,
+                self.Calc_B : self.Gate_B,
+                self.Calc_A_B : self.Gate_A_B
+                })
+
+
+    def _create_gui(self):
+        options =[('Strom A', 'A'), 
+             ('Strom B', 'B'), 
+             ('Summe A und B', 'A_B'),
+             ('Verhältnis A', 'A_ratio'), 
+             ('Verhältnis B', 'B_ratio'), 
+             ('Anteil A', 'A_portion'),
+             ('Anteil B', 'B_portion')
+            ]
+
+        layout_select = widgets.Layout(width='100%')
+        layout_valbox = widgets.Layout(padding = '1em 0  0  0', background_color='red')
+        
+        val_label_1 = widgets.Label(value='extensive Größe:')
+        val_select_1 = widgets.Dropdown(options = options[:3], 
+            value='A',  
+            #description='Extensive Größe:',
+            layout = layout_select
+        )
+        value_1 = widgets.FloatText(value = 0.0, layout=widgets.Layout(width='15%'))
+
+        val_label_2 = widgets.Label(value='extensive oder intensive Größe')
+        val_select_2 = widgets.Dropdown(options = options, 
+            value='B',  
+            #description='extensive oder intensive Größe:',
+            layout = layout_select) 
+        value_2 = widgets.FloatText(value = 0.0, layout=widgets.Layout(width='15%'))    
+        
+        val1_box = widgets.VBox([val_label_1, widgets.HBox([val_select_1, value_1])],
+                background_color='red')
+        val2_box = widgets.VBox([val_label_2, widgets.HBox([val_select_2, value_2])], layout = layout_valbox)
+      
+        
+        total_box = widgets.VBox([val1_box, val2_box], background_color='red')
+
+        self._GUI_itemlist.update({
+            'val_select_1' : val_select_1,
+            'value_1' : value_1,
+            'val_select_2' : val_select_2,
+            'value_2' : value_2,
+        })
+        super()._create_gui()# Attention! --must-- because the widget get a parent attr.
+        return  total_box
+     
+
+    def  Init_Over_GUI(self):
+        para = {
+           self._GUI_itemlist['val_select_1'].value :  self._GUI_itemlist['value_1'].value,
+           self._GUI_itemlist['val_select_2'].value :  self._GUI_itemlist['value_2'].value
+        }
+        self.Init(**para)
+        
+    
+    def Init(self, 
+            A = np.nan,
+            B = np.nan,
+            A_B = np.nan,
+            A_ratio = np.nan,
+            B_ratio = np.nan,
+            A_portion = np.nan,
+            B_portion = np.nan,
+        ):
+
+        super().Init()
+        self._value_key  = 0b00000000
+        self.Gate_A.general.Init(A)
+        self.Gate_B.general.Init(B)
+        self.Gate_A_B.general.Init(A_B)
+        self.A_ratio.Init(A_ratio)
+        self.B_ratio.Init(B_ratio)
+        self.A_portion.Init(A_portion)
+        self.B_portion.Init(B_portion)
+        self.Info.Init('kein Kommentar')
+        self.Info._value = 'Oh mann'
+
+
+    def _set_values(self):
+       if not self._korr_key & 0b01000000: self.A = np.nan
+       if not self._korr_key & 0b00100000: self.B = np.nan
+       if not self._korr_key & 0b00010000: self.A_B = np.nan
+       if not self._korr_key & 0b00001000: self.A_ratio = np.nan
+       if not self._korr_key & 0b00000100: self.B_ratio = np.nan
+       if not self._korr_key & 0b00000010: self.A_portion = np.nan
+       if not self._korr_key & 0b00000001: self.B_portion = np.nan
+
+
+    # es muss mindestens ein  A oder B oder A_B vorhanden sein aber nicht mehr wie zwei
+    def _check_values(self, stepper : nowo.step_base):
+        # Build zahl bei values 
+        count : int = 0
+        if not np.isnan(self.Gate_A.general.get_set(stepper)): 
+            self._value_key = self._value_key   |self._value_keys['A']
+            count = count + 1
+        if not np.isnan(self.Gate_B.general.get_set(stepper)): 
+            self._value_key = self._value_key   |self._value_keys['B']
+            count = count + 1
+        if not np.isnan(self.Gate_A_B.general.get_set(stepper)): 
+            self._value_key = self._value_key   |self._value_keys['A_B']
+            count = count + 1
+        if not np.isnan(self.A_ratio.get_set(stepper)): 
+            self._value_key = self._value_key   |self._value_keys['A_ratio']
+            count = count + 1
+        if not np.isnan(self.B_ratio.get_set(stepper)):
+             self._value_key = self._value_key  |self._value_keys['B_ratio']
+             count = count + 1
+        if not np.isnan(self.A_portion.get_set(stepper)): 
+            self._value_key = self._value_key   |self._value_keys['A_portion']
+            count = count + 1
+        if not np.isnan(self.B_portion.get_set(stepper)): 
+            self._value_key = self._value_key   |self._value_keys['B_portion']
+            count = count + 1
+
+        if count < 2: 
+            self.Info._value = 'Es müssen mind. 2 unterschiedliche Werte angeben werden'
+            return False
+        elif count > 2:
+            self.Info._value = 'Es dürfen nicht mehr als 2 unterschiedliche Werte angeben werden'
+            return False
+         
+        # Abfrage ob wenigstens eine Masse vorhanden ist
+        if self._value_key < 16:
+            self.Info._value = 'Es muss min. ein Strom (A, B oder A_B) angegeben werden'
+            return False
+        
+        return True
+
+
+    def Calc_A(self,  stepper : nowo.step_base, Gate_In: nowo.gate_general):
+        self._calc(stepper, Gate_In)
+        return self.Gate_A
+
+
+    def Calc_B(self,  stepper : nowo.step_base, Gate_In: nowo.gate_general):
+        self._calc(stepper, Gate_In)
+        return self.Gate_B
+
+
+    def Calc_A_B(self,  stepper : nowo.step_base, Gate_In: nowo.gate_general):
+        self._calc(stepper, Gate_In)
+        return self.Gate_A_B
+
+
+    def _calc(self,  stepper : nowo.step_base, Gate_In: nowo.gate_general):
+        if not self._check_values(stepper): return
+        self.calcflag =  True
+        while self.calcflag:
+            self.calcflag = False
+            self._calc_A_ratio()
+            self._calc_B_ratio()
+            self._calc_A_portion()
+            self._calc_B_portion()
+            self._calc_A()
+            self._calc_B()  
+            self._calc_A_B()        
+          
+
+    def _set_calcflag(self, flag):
+        if not self.calcflag:
+            self.calcflag = flag
+
+
+
+    def _calc_A_ratio(self):
+        if self._value_keys['A_ratio'] & self._value_key:
+            self._set_calcflag(False)
+            return
+        
+        try:
+            if self._value_keys['A_portion'] & self._value_key:
+                self.A_ratio._value = 1/(1/self.A_portion._value -1)  
+
+            elif self._value_keys['B_ratio'] & self._value_key:
+                self.A_ratio._value = 1/self.B_ratio._value  
+
+            elif  self._value_keys['A'] & self._value_key and self._value_keys['B'] & self._value_key:     
+                self.A_ratio._value = self.Gate_A.general._value / self.Gate_B.general._value  
+            
+            elif  self._value_keys['A_B'] & self._value_key and self._value_keys['A'] & self._value_key:
+                self.A_ratio._value = self.Gate_A.general._value / (self.Gate_A_B.general._value - self.Gate_A.general._value)
+            
+            elif  self._value_keys['A_B'] & self._value_key and  self._value_keys['B'] & self._value_key:
+                self.A_ratio._value = (self.Gate_A_B.general._value - self.Gate_B.general._value) / self.B
+            
+            else: 
+                self._set_calcflag(False)
+                return  
+            self._set_calcflag(True)
+            self._value_key = self._value_key |  self._value_keys['A_ratio'] 
+        except ZeroDivisionError as error:
+            pass
+        except Exception as exception:
+            pass
+
+
+
+    def _calc_A_portion(self):
+        if self._value_keys['A_portion'] & self._value_key: 
+            self._set_calcflag(False)
+            return
+        try:
+            if self._value_keys['A_ratio'] & self._value_key:
+                self.A_portion._value = 1/(1/self.A_ratio._value +1)
+            else: 
+                self._set_calcflag(False)  
+                return  
+            self._set_calcflag(True)
+            self._value_key = self._value_key |  self._value_keys['A_portion']   
+        
+        except ZeroDivisionError as error:
+            pass
+        except Exception as exception:
+            pass
+
+
+
+    def _calc_B_portion(self):
+        if self._value_keys['B_portion'] & self._value_key: 
+            self._set_calcflag(False)
+            return
+        
+        try:
+            if self._value_keys['B_ratio'] & self._value_key:
+                self.B_portion._value = 1/(1/self.B_ratio._value +1)
+                
+            else: 
+                self._set_calcflag(False)
+                return    
+            self._set_calcflag(True)
+            self._value_key = self._value_key |  self._value_keys['B_portion'] 
+
+        except ZeroDivisionError as error:
+            pass
+        except Exception as exception:
+            pass
+        
+    
+
+    def _calc_B_ratio(self):
+        if self._value_keys['B_ratio'] & self._value_key:
+            self._set_calcflag(False)
+            return
+        try:
+            if self._value_keys['A_ratio'] & self._value_key:
+                self.B_ratio._value = 1/self.A_ratio._value  
+                
+            elif self._value_keys['B_portion'] & self._value_key:
+                self.B_ratio._value = 1/(1/self.B_portion._value -1)
+                
+            elif self._value_keys['A'] & self._value_key and self._value_keys['B'] & self._value_key:
+                self.B_ratio._value = self.Gate_B.general._value / self.Gate_A.general._value
+                
+            elif self._value_keys['A_B'] & self._value_key and self._value_keys['B'] & self._value_key:
+                self.B_ratio._value = self.Gate_B.general._value / (self.Gate_A_B.general._value - self.Gate_B.general._value)
+                
+            elif self._value_keys['A_B'] & self._value_key and self._value_keys['A'] & self._value_key:
+                self.B_ratio._value = (self.Gate_A_B.general._value - self.Gate_A.general._value) / self.Gate_A.general._value
+            else: 
+                self._set_calcflag(False)
+                return   
+            self._set_calcflag(True)
+            self._value_key = self._value_key |  self._value_keys['B_ratio'] 
+
+        except ZeroDivisionError as error:
+            pass
+        except Exception as exception:
+            pass
+
+
+
+    def _calc_A(self):
+        if self._value_keys['A'] & self._value_key: 
+            self._set_calcflag(False)
+            return
+
+        try:
+            if self._value_keys['A_B'] & self._value_key and self._value_keys['B'] & self._value_key:
+                self.Gate_A.general._value = (self.Gate_A_B.general._value - self.B)
+                
+            elif self._value_keys['A_B'] & self._value_key and self._value_keys['A_portion'] & self._value_key:
+                self.Gate_A.general._value = (self.Gate_A_B.general._value * self.A_portion._value)
+                
+            elif self._value_keys['A_B'] & self._value_key and self._value_keys['A_ratio'] & self._value_key:
+                self.Gate_A.general._value = (self.Gate_A_B.general._value * self.A_portion._value)
+                
+            elif self._value_keys['B'] & self._value_key and self._value_keys['A_ratio'] & self._value_key:
+                self.Gate_A.general._value = (self.Gate_B.general._value * self.A_ratio._value)
+                
+            else: 
+                self._set_calcflag(False)
+                return    
+            self._set_calcflag(True)
+            self._value_key = self._value_key |  self._value_keys['A'] 
+
+        except ZeroDivisionError as error:
+            pass
+        except Exception as exception:
+            pass
+
+        
+                                
+    def _calc_B(self):
+        if self._value_keys['B'] & self._value_key:#
+            self._set_calcflag(False)
+            return
+        
+        try:
+            if self._value_keys['A_B'] & self._value_key and self._value_keys['A'] & self._value_key:
+                self.Gate_B.general._value = (self.Gate_A_B.general._value - self.Gate_A.general._value)  
+            elif self._value_keys['A_B'] & self._value_key and self._value_keys['B_portion'] & self._value_key:
+                self.Gate_B.general._value = (self.Gate_A_B.general._value * self.B_portion._value)
+            elif self._value_keys['A'] & self._value_key and self._value_keys['B_ratio'] & self._value_key:
+                self.Gate_B.general._value = (self.Gate_A.general._value * self.B_ratio._value)
+                
+            else: 
+                self._set_calcflag(False)
+                return   
+            self._set_calcflag(True)
+            self._value_key = self._value_key |  self._value_keys['B'] 
+
+        except ZeroDivisionError as error:
+            pass
+        except Exception as exception:
+            pass
+
+    
+
+        
+    def _calc_A_B(self):
+        if self._value_keys['A_B'] & self._value_key:
+            self._set_calcflag(False)
+            return
+        
+        if self._value_keys['A'] & self._value_key and self._value_keys['B'] & self._value_key:
+            self.Gate_A_B.general._value = (self.Gate_A.general._value + self.Gate_B.general._value)
+            self._set_calcflag(True)
+            self._value_key = self._value_key |  self._value_keys['A_B'] 
+            return
+        self._set_calcflag(False)    
+    
+
+    def _reset(self):
+        self.Gate_A._reset()
+        self.Gate_B._reset()
+        self.Gate_A_B._reset()
+        super()._reset()
+
+    
+    def _node_success(self, stepper: nowo.step_base):
+        self.Gate_A._node_success(stepper)
+        self.Gate_B._node_success(stepper)
+        self.Gate_A_B._node_success(stepper)
+        self.A_ratio._node_success(stepper)
+        self.B_ratio._node_success(stepper)
+        self.A_portion._node_success(stepper)
+        self.B_portion._node_success(stepper)
+        self.Info._node_success(stepper)
\ No newline at end of file
diff --git a/requirements.txt b/requirements.txt
index e76e091..a02b580 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,2 +1,3 @@
 voila
 voila-gridstack
+ipysheet
diff --git a/sim_base.py b/sim_base.py
new file mode 100644
index 0000000..865172d
--- /dev/null
+++ b/sim_base.py
@@ -0,0 +1,11 @@
+import pathlib
+import sys
+
+# Globale Festlegungen
+Main_Modul = sys.modules['__main__']
+Self_Modulname = globals()['__name__']
+Self_Modul = sys.modules[Self_Modulname]
+
+#sim_obj_factory = Main_Modul.sim_obj_factory
+
+timepattern = '%Y-%m-%d %H:%M:%S' 
\ No newline at end of file
-- 
GitLab