Ankündigung

Einklappen
Keine Ankündigung bisher.

Item mit Zeitberechnung bspw für Verbrauchsauswertung als Systemitems bereitstellen

Einklappen
X
 
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

    #46
    Hallo,

    Mitten in der Überarbeitung des struct kam der Jahreswechsel und damit die Erkenntnis, dass die bisherige Berechnung für den Vormonat etc nicht immer richtig war.
    Bislang habe ich den Wert für den Vormonat so ermittelt:
    Code:
    eval: round((sh...db('max', str(shtime.time_since(shtime.beginning_of_month(shtime.current_month()), 'im')) + 'i', str(shtime.time_since(shtime.beginning_of_month(shtime.current_month()), 'im')) + 'i') - sh...db('max', str(shtime.time_since(shtime.beginning_of_month(shtime.current_month() - 1), 'im')) + 'i', str(shtime.time_since(shtime.beginning_of_month(shtime.current_month() - 1), 'im')) + 'i')), 2)
    Da nun aber der aktuelle Monat Januar und damit shtime.current_month() = 1 ist, ergibt shtime.current_month() - 1) = 0 und ist damit für die weitere Berechnung ungültig.
    Gibt es eine Möglichkeit mit Boardmitteln im eval den Vormonat zu ermitteln?

    Das Python Modul dateutil bzw. das darin enthaltene "relativedelta" kann das, nur wir kann man das im eval nutzen?
    Hat jemand eine Idee?

    Kommentar


      #47
      Hallo,

      nachdem Onkelandy die Funktionen der shtime erweitert hat und somit auch die relative Zeitpunkt-Ermittlung einfach möglich ist (wird wahrscheinlich im Release 1.8 kommen) hier mal ein Update der evals für die Ermittlung von historischen Verbrauchswerten.

      Ich habe ein struct für die Berechnung der historischen Verbrauchswerte und den passenden evals angelegt. Dabei wird auch geprüft, ob zum Abfragezeitpunkt auch Daten in der DB vorhanden sind. Nur dann werden auch die Berechnungen durchgeführt, ansonsten wird der Wert 0 gesetzt.

      struct.yaml im Ordern \etc
      Code:
      wertehistorie_total:
          # Aktualisierung erfolgt über Logik, die täglich um Mitternacht getriggert wird.
          name: Struct für Wertehistorie total
          heute:
              type: num
              visu_acl: ro
              eval: round((sh...() - sh...db('max', str(shtime.time_since(shtime.today(), 'im')) + 'i', str(shtime.time_since(shtime.today(), 'im')) + 'i')), 2)
              eval_trigger:
                - ..
              cache: yes
      
          woche:
              type: num
              visu_acl: ro
              eval: round((sh...() - sh...db('max', str(shtime.time_since(shtime.beginning_of_week(), 'im')) + 'i', str(shtime.time_since(shtime.beginning_of_week(), 'im')) + 'i')), 2)
              eval_trigger:
                - ..
              cache: yes
      
          monat:
              type: num
              visu_acl: ro
              eval: round((sh...() - sh...db('max', str(shtime.time_since(shtime.beginning_of_month(), 'im')) + 'i', str(shtime.time_since(shtime.beginning_of_month(), 'im')) + 'i')), 2) if sh...db('max', str(shtime.time_since(shtime.beginning_of_month(), 'im')) + 'i', str(shtime.time_since(shtime.beginning_of_month(), 'im')) + 'i') is not None else 0
              eval_trigger:
                - ..
              cache: yes
      
          jahr:
              type: num
              visu_acl: ro
              eval: round((sh...() - sh...db('max', str(shtime.time_since(shtime.beginning_of_year(), 'im')) + 'i', str(shtime.time_since(shtime.beginning_of_year(), 'im')) + 'i')), 2) if sh...db('max', str(shtime.time_since(shtime.beginning_of_year(), 'im')) + 'i', str(shtime.time_since(shtime.beginning_of_year(), 'im')) + 'i') is not None else 0
              eval_trigger:
                - ..
              cache: yes
      
          gestern:
              type: num
              visu_acl: ro
              eval: round((sh...db('max', str(shtime.time_since(shtime.today(), 'im')) + 'i', str(shtime.time_since(shtime.today(), 'im')) + 'i') - sh...db('max', str(shtime.time_since(shtime.today(-1), 'im')) + 'i', str(shtime.time_since(shtime.today(-1), 'im')) + 'i')), 2) if sh...db('max', str(shtime.time_since(shtime.today(-1), 'im')) + 'i', str(shtime.time_since(shtime.today(-1), 'im')) + 'i') is not None else 0
              enforce_updates: yes
      
          gestern_minus1:
              type: num
              visu_acl: ro
              eval: round((sh...db('max', str(shtime.time_since(shtime.today(-1), 'im')) + 'i', str(shtime.time_since(shtime.today(-1), 'im')) + 'i') - sh...db('max', str(shtime.time_since(shtime.today(-2), 'im')) + 'i', str(shtime.time_since(shtime.today(-2), 'im')) + 'i')), 2) if sh...db('max', str(shtime.time_since(shtime.today(-2), 'im')) + 'i', str(shtime.time_since(shtime.today(-2), 'im')) + 'i') is not None else 0
              cache: yes
              enforce_updates: yes
          
          gestern_minus2:
              type: num
              visu_acl: ro
              eval: round((sh...db('max', str(shtime.time_since(shtime.today(-2), 'im')) + 'i', str(shtime.time_since(shtime.today(-2), 'im')) + 'i') - sh...db('max', str(shtime.time_since(shtime.today(-3), 'im')) + 'i', str(shtime.time_since(shtime.today(-3), 'im')) + 'i')), 2) if sh...db('max', str(shtime.time_since(shtime.today(-3), 'im')) + 'i', str(shtime.time_since(shtime.today(-3), 'im')) + 'i') is not None else 0
              cache: yes
              enforce_updates: yes
              
          gestern_minus3:
              type: num
              visu_acl: ro
              eval: round((sh...db('max', str(shtime.time_since(shtime.today(-3), 'im')) + 'i', str(shtime.time_since(shtime.today(-3), 'im')) + 'i') - sh...db('max', str(shtime.time_since(shtime.today(-4), 'im')) + 'i', str(shtime.time_since(shtime.today(-4), 'im')) + 'i')), 2) if sh...db('max', str(shtime.time_since(shtime.today(-4), 'im')) + 'i', str(shtime.time_since(shtime.today(-4), 'im')) + 'i') is not None else 0
              cache: yes
              enforce_updates: yes
              
          gestern_minus4:
              type: num
              visu_acl: ro
              eval: round((sh...db('max', str(shtime.time_since(shtime.today(-4), 'im')) + 'i', str(shtime.time_since(shtime.today(-4), 'im')) + 'i') - sh...db('max', str(shtime.time_since(shtime.today(-5), 'im')) + 'i', str(shtime.time_since(shtime.today(-5), 'im')) + 'i')), 2) if sh...db('max', str(shtime.time_since(shtime.today(-5), 'im')) + 'i', str(shtime.time_since(shtime.today(-5), 'im')) + 'i') is not None else 0
              cache: yes
              enforce_updates: yes
      
          gestern_minus5:
              type: num
              visu_acl: ro
              eval: round((sh...db('max', str(shtime.time_since(shtime.today(-5), 'im')) + 'i', str(shtime.time_since(shtime.today(-5), 'im')) + 'i') - sh...db('max', str(shtime.time_since(shtime.today(-6), 'im')) + 'i', str(shtime.time_since(shtime.today(-6), 'im')) + 'i')), 2) if sh...db('max', str(shtime.time_since(shtime.today(-6), 'im')) + 'i', str(shtime.time_since(shtime.today(-6), 'im')) + 'i') is not None else 0
              cache: yes
              enforce_updates: yes        
              
          vorwoche:
              type: num
              visu_acl: ro
              eval: round((sh...db('max', str(shtime.time_since(shtime.beginning_of_week(), 'im')) + 'i', str(shtime.time_since(shtime.beginning_of_week(), 'im')) + 'i') - sh...db('max', str(shtime.time_since(shtime.beginning_of_week(shtime.calendar_week(), None, - 1), 'im')) + 'i', str(shtime.time_since(shtime.beginning_of_week(shtime.calendar_week(), None, - 1), 'im')) + 'i')), 2) if sh...db('max', str(shtime.time_since(shtime.beginning_of_week(shtime.calendar_week(), None, - 1), 'im')) + 'i', str(shtime.time_since(shtime.beginning_of_week(shtime.calendar_week(), None, - 1), 'im')) + 'i') is not None else 0
              database: init
              enforce_updates: yes
      
          vorwoche_minus1:
              type: num
              visu_acl: ro
              eval: round((sh...db('max', str(shtime.time_since(shtime.beginning_of_week(shtime.calendar_week(), None, -1), 'im')) + 'i', str(shtime.time_since(shtime.beginning_of_week(shtime.calendar_week(), None, -1), 'im')) + 'i') - sh...db('max', str(shtime.time_since(shtime.beginning_of_week(shtime.calendar_week(), None, -2), 'im')) + 'i', str(shtime.time_since(shtime.beginning_of_week(shtime.calendar_week(), None, -2), 'im')) + 'i')), 2) if sh...db('max', str(shtime.time_since(shtime.beginning_of_week(shtime.calendar_week(), None, -2), 'im')) + 'i', str(shtime.time_since(shtime.beginning_of_week(shtime.calendar_week(), None, -2), 'im')) + 'i') is not None else 0
              cache: yes
              enforce_updates: yes
              
          vorwoche_minus2:
              type: num
              visu_acl: ro
              eval: round((sh...db('max', str(shtime.time_since(shtime.beginning_of_week(shtime.calendar_week(), None, -2), 'im')) + 'i', str(shtime.time_since(shtime.beginning_of_week(shtime.calendar_week(), None, -2), 'im')) + 'i') - sh...db('max', str(shtime.time_since(shtime.beginning_of_week(shtime.calendar_week(), None, -3), 'im')) + 'i', str(shtime.time_since(shtime.beginning_of_week(shtime.calendar_week(), None, -3), 'im')) + 'i')), 2) if sh...db('max', str(shtime.time_since(shtime.beginning_of_week(shtime.calendar_week(), None, -3), 'im')) + 'i', str(shtime.time_since(shtime.beginning_of_week(shtime.calendar_week(), None, -3), 'im')) + 'i') is not None else 0
              cache: yes
              enforce_updates: yes
              
          vorwoche_minus3:
              type: num
              visu_acl: ro
              eval: round((sh...db('max', str(shtime.time_since(shtime.beginning_of_week(shtime.calendar_week(), None, -3), 'im')) + 'i', str(shtime.time_since(shtime.beginning_of_week(shtime.calendar_week(), None, -3), 'im')) + 'i') - sh...db('max', str(shtime.time_since(shtime.beginning_of_week(shtime.calendar_week(), None, -4), 'im')) + 'i', str(shtime.time_since(shtime.beginning_of_week(shtime.calendar_week(), None, -4), 'im')) + 'i')), 2) if sh...db('max', str(shtime.time_since(shtime.beginning_of_week(shtime.calendar_week(), None, -4), 'im')) + 'i', str(shtime.time_since(shtime.beginning_of_week(shtime.calendar_week(), None, -4), 'im')) + 'i') is not None else 0
              cache: yes
              enforce_updates: yes
              
          vormonat:
              type: num
              visu_acl: ro
              eval: round((sh...db('max', str(shtime.time_since(shtime.beginning_of_month(None, None, 0), 'im')) + 'i', str(shtime.time_since(shtime.beginning_of_month(None, None, 0), 'im')) + 'i') - sh...db('max', str(shtime.time_since(shtime.beginning_of_month(None, None, -1), 'im')) + 'i', str(shtime.time_since(shtime.beginning_of_month(None, None, -1), 'im')) + 'i')), 2) if sh...db('max', str(shtime.time_since(shtime.beginning_of_month(None, None, -1), 'im')) + 'i', str(shtime.time_since(shtime.beginning_of_month(None, None, -1), 'im')) + 'i') is not None else 0
              database: init
              enforce_updates: yes
              
          vormonat_minus1:
              type: num
              visu_acl: ro
              eval: round((sh...db('max', str(shtime.time_since(shtime.beginning_of_month(None, None, -1), 'im')) + 'i', str(shtime.time_since(shtime.beginning_of_month(None, None, -1), 'im')) + 'i') - sh...db('max', str(shtime.time_since(shtime.beginning_of_month(None, None, -2), 'im')) + 'i', str(shtime.time_since(shtime.beginning_of_month(None, None, -2), 'im')) + 'i')), 2) if sh...db('max', str(shtime.time_since(shtime.beginning_of_month(None, None, -2), 'im')) + 'i', str(shtime.time_since(shtime.beginning_of_month(None, None, -2), 'im')) + 'i') is not None else 0
              cache: yes
              enforce_updates: yes
              
          vormonat_minus2:
              type: num
              visu_acl: ro
              eval: round((sh...db('max', str(shtime.time_since(shtime.beginning_of_month(None, None, -2), 'im')) + 'i', str(shtime.time_since(shtime.beginning_of_month(None, None, -2), 'im')) + 'i') - sh...db('max', str(shtime.time_since(shtime.beginning_of_month(None, None, -3), 'im')) + 'i', str(shtime.time_since(shtime.beginning_of_month(None, None, -3), 'im')) + 'i')), 2) if sh...db('max', str(shtime.time_since(shtime.beginning_of_month(None, None, -3), 'im')) + 'i', str(shtime.time_since(shtime.beginning_of_month(None, None, -3), 'im')) + 'i') is not None else 0
              cache: yes
              enforce_updates: yes
      
          vormonat_zaehlerstand:
              type: num
              visu_acl: ro
              eval: round(sh...db('max', str(shtime.time_since(shtime.beginning_of_month(None, None, 0), 'im')) + 'i', str(shtime.time_since(shtime.beginning_of_month(None, None, 0), 'im')) + 'i'), 2) if sh...db('max', str(shtime.time_since(shtime.beginning_of_month(None, None, 0), 'im')) + 'i', str(shtime.time_since(shtime.beginning_of_month(None, None, 0), 'im')) + 'i') is not None else 0
              database: init
              enforce_updates: yes
              
          vormonat_minus1_zaehlerstand:
              type: num
              visu_acl: ro
              eval: round(sh...db('max', str(shtime.time_since(shtime.beginning_of_month(None, None, -1), 'im')) + 'i', str(shtime.time_since(shtime.beginning_of_month(None, None, -1), 'im')) + 'i'), 2) if sh...db('max', str(shtime.time_since(shtime.beginning_of_month(None, None, -1), 'im')) + 'i', str(shtime.time_since(shtime.beginning_of_month(None, None, -1), 'im')) + 'i') is not None else 0
              cache: yes
              enforce_updates: yes
          
          vormonat_minus2_zaehlerstand:
              type: num
              visu_acl: ro
              eval: round(sh...db('max', str(shtime.time_since(shtime.beginning_of_month(None, None, -2), 'im')) + 'i', str(shtime.time_since(shtime.beginning_of_month(None, None, -2), 'im')) + 'i'), 2) if sh...db('max', str(shtime.time_since(shtime.beginning_of_month(None, None, -2), 'im')) + 'i', str(shtime.time_since(shtime.beginning_of_month(None, None, -2), 'im')) + 'i') is not None else 0
              cache: yes
              enforce_updates: yes
      Im Item sieht es dann so aus:
      item.yaml:
      Code:
      heizung:
          brenner:
              name: Brennerstatus Heizung
              type: bool
              betriebsstunden_knx:
                  name: Betriebsstundenzähler Brenner in Stunden
                  type: num
                  database: init
                  struct: wertehistorie_total
      Die Aktualisierung der Items mit historischen Verbrauchswerten erfolgt über eine Logik, die per crontab jeweils um Mitternacht und kurz nach Start von shNG ausgeführt wird. Dabei werden beim ersten Start der Logik alle Items die "gestern", "vorwoche" oder "vormonat" im Pfad haben in eine persistente Variable geschrieben. Danach wird die Berechnung (Ausführen des Evals) der Items durch das Zuweisen von "1" ausgelöst, sobald die zeitlichen Bedingungen dafür erfüllt sind.
      Eine manuelle Berechnung kann durch das "manuelle" Auslösen der Logik erreicht werden.

      berechnung_wertehistorie.py
      Code:
      #!/usr/bin/env python3
      # berechnung_wertehistorie.py
      
      # Die Logik stößt die Neuberechnung der Wertehistorie gemäß struct an.
      # Alle Item werden nach gestern, vorwoche und vormonat durchsucht und entsprechende Aktionen ausgeführt
      
      logger.info("Logik 'Berechnung Wertehistorie' durch: {} und {}".format(trigger['by'], trigger['source'] ))
      
      from lib.item import Items
      items = Items.get_instance()
      
      if not hasattr(logic, 'all_historical_items_gestern'):
          logic.all_historical_items_gestern = items.match_items('*gestern*')
          logger.info("Logik 'Berechnung Wertehistorie' hat folgende Items für GESTERN gefunden: {}".format(logic.all_historical_items_gestern))
          
      if not hasattr(logic, 'all_historical_items_vorwoche'):
          logic.all_historical_items_vorwoche = items.match_items('*vorwoche*')
          logger.info("Logik 'Berechnung Wertehistorie' hat folgende Items für VORWOCHE gefunden: {}".format(logic.all_historical_items_vorwoche))
          
      if not hasattr(logic, 'all_historical_items_vormonat'):
          logic.all_historical_items_vormonat = items.match_items('*vormonat*')
          logger.info("Logik 'Berechnung Wertehistorie' hat folgende Items für VORMONAT gefunden: {}".format(logic.all_historical_items_vormonat))
          
      if trigger['by'] == 'Scheduler':
          if sh.now().hour == 0 and sh.now().minute == 0:
              logger.info("Logik 'Berechnung Wertehistorie' hat Aktualisierung der Item GESTERN durchgeführt")
              for item in logic.all_historical_items_gestern:
                  item(1)
          else:
              logger.debug("Logik 'Berechnung Wertehistorie' hat Aktualisierung der Item GESTERN nicht durchgeführt")
      
          if sh.now().hour == 0 and sh.now().minute == 0 and shtime.weekday(shtime.today()) == 1:
              logger.info("Logik 'Berechnung Wertehistorie' hat Aktualisierung der Item VORWOCHE durchgeführt")
              for item in logic.all_historical_items_vorwoche:
                  item(1)
          else:
              logger.debug("Logik 'Berechnung Wertehistorie' hat Aktualisierung der Item VORWOCHE nicht durchgeführt")
          
          if sh.now().hour == 0 and sh.now().minute == 0 and sh.now().day == 1:
              logger.info("Logik 'Berechnung Wertehistorie' hat Aktualisierung der Item VORMONAT durchgeführt")
              for item in logic.all_historical_items_vormonat:
                  item(1)
          else:
              logger.debug("Logik 'Berechnung Wertehistorie' hat Aktualisierung der Item VORMONAT nicht durchgeführt")
              
      elif trigger['by'] == 'Admin':
          logger.info("Logik 'Berechnung Wertehistorie' manuell ausgelöst und Aktualisierung aller Items durchgeführt")
          for item in logic.all_historical_items_gestern:
              item(1)
          for item in logic.all_historical_items_vorwoche:
              item(1)
          for item in logic.all_historical_items_vormonat:
              item(1)
      Vielleicht kann es einer nutzen.
      Beste Grüße

      Kommentar


        #48
        Update ist vermutlich zu umfangreich für das kommende Release Man müsste sich also die shtime.py aus dem PR hier selbst ziehen:
        https://github.com/smarthomeNG/smarthome/pull/375

        In der Logik sollten übrigens sh.now() durch shtime.now() ersetzt werden. Danke sonst schon mal für die evals und Logiken, ich teste die Tage mal.

        Kommentar


          #49
          Zitat von Onkelandy Beitrag anzeigen
          Man müsste sich also die shtime.py aus dem PR hier selbst ziehen:
          Ich habe mir die shtime.py aus Deinem Github gezogen. Damit geht es. Msinn hatte auch schon eine Korrektur an der shtime.py bzgl. der beginning_since_week vorgenommen, die auch in den den Rechenfehler zum Jahreswechsel hatte.

          Kommentar


            #50
            Moin,
            ich guck gerade wie ich meine PV Anlage, Verbrauch und E-Auto Visualisiere.

            Dies scheint wohl die "latest and greates" Lösung zu sein. Es sind aber vermutlich noch nicht alle Anpassungen im Release? Cool fände ich eine kleine Anwenderdoku. Verstanden habe ich es nähmlich noch nicht zu 100%. Habt ihr da was geplant?

            Zapft ihr Narren der König hat Durst

            Kommentar


              #51
              Welche Anpassungen meinst Du, die nicht im Release sein sollten?
              Viele Grüße
              Martin

              There is no cloud. It's only someone else's computer.

              Kommentar


                #52
                Zitat von Hochpass Beitrag anzeigen
                Cool fände ich eine kleine Anwenderdoku.
                Sowas? https://www.smarthomeng.de/user/

                Kommentar


                  #53
                  Zitat von Msinn Beitrag anzeigen
                  Welche Anpassungen meinst Du, die nicht im Release sein sollten?
                  Ich denke, er meint den PR von Onkelandy aus dem Beitrag #48.
                  So wie ich das sehe, ist diese Änderung für V1.9 vorgemerkt.

                  Kommentar


                    #54
                    Ja ist natürlich bekannt aber das Thema ist dann wohl veraltet.

                    Das Beispiel würde man anders lösen
                    https://www.smarthomeng.de/user/beis...zeitdaten.html
                    Zapft ihr Narren der König hat Durst

                    Kommentar


                      #55
                      Mein PR ist noch offen und muss getestet werden bzw. wollte Msinn das Ganze etwas anders lösen. Ich nutze bei mir die Logik von #47 und den Code für shtime.py von meinem PR. Das läuft soweit prima - ansonsten müsste man sich noch etwas gedulden.

                      Kommentar


                        #56
                        Zitat von Onkelandy Beitrag anzeigen
                        Ich nutze bei mir die Logik von #47 und den Code für shtime.py von meinem PR. Das läuft soweit prima
                        Genau so mache ich das auch. Funktioniert prima.

                        Kommentar


                          #57
                          Zitat von Onkelandy Beitrag anzeigen
                          Das läuft soweit prima
                          O.k. ein langes Wochenende mit schlechtem Wetter steht vor der Tür. Ich guck mal ob ich das zum laufen kriege.

                          Danke!
                          Zapft ihr Narren der König hat Durst

                          Kommentar


                            #58
                            Hätte jemand ne Idee wie man das Problem beim Berechnen der Wertehistorie abfangen kann, wenn zu besagtem Abfragezeitpunkt keine Daten in der Datenbank sind?
                            Also ganz konkret.. Ich hab seit Mai 2021 ein neues Item am Start und möchte den max Wert vom Jahr 2021 ermitteln. Hier kommt ein "None" zurück, da zu Beginn des Jahres noch keine Daten vorhanden sind. Es sollte also statt beginning_of_year der Zeitpunkt des ersten db Eintrags für das Item herangezogen werden.

                            Selbes Spiel dann halt auch für den Monat. Wenn man ein Item erst am 10. des Monats angelegt hat, man aber am 30. des Verbrauch im laufenden Monat abfragen will.
                            Das würde die obigen Abfragen noch ein Stück robuster und wertvoller machen Sisamiwe
                            Vielen Dank!

                            Kommentar


                              #59
                              Zitat von Onkelandy Beitrag anzeigen
                              Hätte jemand ne Idee wie man das Problem beim Berechnen der Wertehistorie abfangen kann, wenn zu besagtem Abfragezeitpunkt keine Daten in der Datenbank sind?
                              Ich bin ein Stück weitergekommen. Im Database Plugin ist eine Funktion integriert, die den Timestamp des ältesten Eintrags zu einer Item-ID zurückgibt. Ich habe das mal in eine Testlogik gegossen:

                              Code:
                              #!/usr/bin/env python3
                              # db_test.py
                              
                              plugin = sh.plugins.return_plugin('database')
                              id = plugin.id(sh.raumtemp.aussen.nord)
                              
                              readOldestLog = plugin.readOldestLog(id)
                              readOldestLog = datetime.datetime.fromtimestamp(readOldestLog/1000, datetime.timezone.utc).astimezone().strftime('%Y-%m-%d %H:%M:%S %Z%z')  
                              
                              logger.info(readOldestLog)
                              Ausgabe ist:
                              Code:
                              2021-10-10  17:31:48 INFO     logics.db_test                           2017-08-12 21:04:30 CEST+0200
                              Also ist der älteste Eintrag für dieses Item vom 12. Aug 2017.

                              Jetzt muss man das nur noch sinnvoll einbauen

                              Kommentar


                                #60
                                Oha, das ist schon mal cool. Der Eval-String dürfte da aber ziemlich ekelhaft werden hehe.. müsste man mal schauen, ob man das irgendwie sinnvoll mit der Logik kombinieren kann.

                                Kommentar

                                Lädt...
                                X