#!/usr/bin/env python
# -*- coding: utf-8 -*-

import wx
import wx.media
import time
import socket
from threading import Thread
import subprocess

cfgFile_g=".bandbreitenmonitor.settings"

FRITZBOX_IP="fritz.box"
FRITZBOX_PORT=49000
ALARM_FILE="/home/dede/daten/ding.wav"

# weitere Parameter-Kandidaten:
#   eth-X
#   Devolo-MACs
#   Pfad zur dlanlist

# ###########################################################
# Erreichbarkeit von Devolo-Dlan-Adaptern pruefen und melden.
# Der Refresh erfolgt automatisch alle 10 Sekunden per Thread.
# Die Funktion "online()" liefert die erreichbaren Adapter
# als Bitmuster (z.B. 1="Buero" oder 5=4+1="Buero und Tobi".
# Die Funktion "namen()" liefert die Kurznamen als Liste.
class devolo():
  def __init__(self):
    # MAC-Adressen der Devolo-Adapter samt Bit-Kennung
    self.macs=[ ["00:0B:3B:16:38:CD", 1],   # Buero
                ["00:0B:3B:16:38:D4", 2],   # Ferkelchen
                ["00:0B:3B:58:CA:53", 4],   # Tobi
                ["00:0B:3B:58:CA:48", 8]]   # unzugeordnet
    self.kurznamen=["B", "M", "T", "?"]

    # dlanlist von:
    # http://www.devolo.com/downloads/software/software-dlan-linux-v6-1.tar.gz
    # Der dlanlist muss mit "setcap cap_net_raw+epi" aufgemacht werden
    self.cmd=["/home/dede/bin/dlanlist", "eth0"]

    self.is_online=0

    worker=Thread(target=self.devolo_dlan)
    worker.setDaemon(True)
    worker.start()

  # ###########################################################
  # Liefert die erreichbaren Dlan-Adapter als Bitmuster (int).
  def online(self):
    return(self.is_online)

  # ###########################################################
  # Liefert die Namens-Kenner fuer die Dlan-Adapter.
  def namen(self):
    return(self.kurznamen)

  # ###########################################################
  # Sucht im Netz nach eingeschalteten dLAN-Adaptern und
  # setzt "self.is_online" entsprechend der aktiven Adapter.
  def devolo_dlan(self):
    while True:
      process=subprocess.Popen(self.cmd, shell=False, stdout=subprocess.PIPE)
      rc=process.communicate()[0]
      # Liefert sowas wie:
      # Type    MAC address        Mbps TX/RX       Version/Product
      # local   00:0B:3B:16:38:CD  ---.-- / ---.--  devolo AG dLAN HS Ethernet (MAC 1.6)
      # remote  00:0B:3B:58:CA:48   75.43 / ---.--  devolo AG dLAN HS Ethernet (MAC 1.6)
      # oder auch:
      # no devices found
      is_online=0
      for j in self.macs:
        if rc.find(j[0])>0:
          is_online+=j[1]
      self.is_online=is_online
      time.sleep(10)

# ###########################################################
# Bandbreiten-Informationen aus der Fritzbox auslesen.
class Fritzbox():
  def __init__(self, host=FRITZBOX_IP, port=FRITZBOX_PORT):
    self.host=host
    self.port=port

    self.controlURL= "upnp/control/WANCommonIFC1"
    self.serviceType="WANCommonInterfaceConfig:1"

  # ###########################################################
  # Sendet eine Anfrage an die Fritzbox und liefert den
  # Antwortstring zurueck
  def send_req_resp(self, action):
    body='<?xml version="1.0"?>\n' \
         '<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"\n' \
         ' s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">\n' \
         '  <s:Body>\n' \
         '    <u:'+action+' xmlns:u="urn:schemas-upnp-org:service:'+self.serviceType+'"/>\n' \
         '  </s:Body>\n' \
         '</s:Envelope>\n'
    pream='POST /'+self.controlURL+' HTTP/1.0\r\n' \
          'HOST: '+self.host+':'+str(self.port)+'\r\n' \
          'CONTENT-LENGTH: '+str(len(body))+'\r\n' \
          'CONTENT-TYPE: text/xml; charset="utf-8"\r\n' \
          'SOAPACTION: "urn:schemas-upnp-org:service:'+self.serviceType+'#'+action+'"\r\n\r\n'
    sock=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    sock.connect((self.host, self.port))
    sock.send(pream + body)

    resp = ""
    while True:
      data=sock.recv(1024)
      if len(data)==0:
        break
      resp+=data
    sock.close()
    return(resp)

  # ###########################################################
  # liefert aus "xml_str" den Teilstring, der zwischen
  #  <"arg"> und </"arg"> steht.
  def get_argument(self, xml_str, arg):
    v="<"+arg+">"
    p1=xml_str.find(v)
    if p1>=0:
      p2=xml_str.find("</"+arg+">", p1)
      if p2>=0:
        return(xml_str[p1+len(v):p2])
    return(None)

  # ###########################################################
  # Liefert die Maximal-Werte der Verbindung.
  def Maximalwerte(self, div=1):
    s=self.send_req_resp("GetCommonLinkProperties")
    # /9 fuer "Bit/Sek" zu "Byte/Sek"
    maxSnd=int(self.get_argument(s, "NewLayer1UpstreamMaxBitRate"))/9
    maxRec=int(self.get_argument(s, "NewLayer1DownstreamMaxBitRate"))/9
    return((maxRec/div, maxSnd/div))

  # ###########################################################
  # Liefert die aktuellen Uebertragungsraten.
  def UebertragungsRate(self, div=1):
    s=self.send_req_resp("GetAddonInfos")
    snd=int(self.get_argument(s, "NewByteSendRate"))
    rec=int(self.get_argument(s, "NewByteReceiveRate"))
    return((rec/div, snd/div))

# ###########################################################
# Bandbreiten-Informationen von ethX auslesen.
#
# pos=0     1           2         3    4    5    6     7          8           9        10      11   12   13   14    15      16
#interface: bytes       packets   errs drop fifo frame compressed multicast | bytes    packets errs drop fifo colls carrier compressed
#     eth0: 1339779969  998857    0    0    0    0     0          752         54799542 625934  0    0    0    0     1       0
#           rec_pos                                                           snd_pos
class eth_messen():
  def __init__(self, interface="eth0:", proc_net_dev="/proc/net/dev", rec_pos=1, snd_pos=9):
    self.proc_net_dev=proc_net_dev
    self.interface=interface
    self.rec_pos=rec_pos
    self.snd_pos=snd_pos
    self.letzterWert=self.DatenHolen()

  # ###########################################################
  # Liefert eine Liste mit drei Werten:
  #  [timestamp, BytesUebertragen-receive, BytesUebertragen-transmit]
  def DatenHolen(self):
    fl=open(self.proc_net_dev, "r")
    s=0
    r=0
    for ln in fl:
      ln=ln.strip()
      if ln.find(self.interface)==0:
        lnl=ln.split()
        r=long(lnl[self.rec_pos])
        s=long(lnl[self.snd_pos])
    fl.close()
    return([time.time(), r, s])

  # ###########################################################
  # Liefert die Uebertragungs-Rate anhand des letzten und des
  # aktuellen Wertes von BytesUebertragen.
  def UebertragungsRate(self, div=1):
    w=self.DatenHolen()
    d=1/float(w[0]-self.letzterWert[0])
    r=(w[1]-self.letzterWert[1])*d
    s=(w[2]-self.letzterWert[2])*d
    self.letzterWert=w
    return([round(r/div, 2), round(s/div, 2)])

# ###########################################################
# Verwaltet eine Liste von "breite" Werten, die von links
# nach rechts mit "WertAufnehmen()" gefuellt wird. In die
# komplett gefuellte Liste werden die neuen Werte von rechts
# reingeschoben, der aelteste Wert ganz links wird geloescht.
# Der Inhalt der Liste wird ueber "ListeLiefern()" abgerufen.
# Geliefert wird eine Liste aus Koordinaten, die bei
# ("pos_x", "pos_y") ihren Null-Punkt haben und bei
# ("pos_x"+"breite", "pos_y"+"hoehe") enden.
class Kurve():
  def __init__(self, pos_x, pos_y, breite, hoehe, name=""):
    self.pos_x =pos_x   # X-Koordinate der linken unteren Ecke
    self.pos_y =pos_y   # Y-Koordinate der linken unteren Ecke
    self.breite=breite  # Anzahl Pixel in der Horizontalen
    self.hoehe =hoehe   # Anzahl Pixel in der Vertikalen
    self.name  =name    # der Name der Kurve

    self.aktPos=0       # aktuelle Einfuegeposition
    self.Ywerte=[]      # die Liste der Y-Werte
    self.maximal=1      # Maximal-Wert in "Ywerte"
    self.maximalAufgerundet=(1, "1 B")
    self.konstant=0     # Zaehler fuer "Werte am Minimum"
    for x in range(breite):
      self.Ywerte.append(0) # init

  # ###########################################################
  # Liefert Position und Abmessungen der Kurve.
  def xywh(self):
    return([self.pos_x, self.pos_y, self.breite, self.hoehe])

  # ###########################################################
  # X- und Y-Koordinate der Kurve [neu] setzen.
  def PositionEinstellen(self, pos_x, pos_y):
    self.pos_x =pos_x   # X-Koordinate der linken unteren Ecke
    self.pos_y =pos_y   # Y-Koordinate der linken unteren Ecke

  # ###########################################################
  # Die Hoehe der Kurve [neu] setzen.
  def HoeheEinstellen(self, hoehe):
    self.hoehe=hoehe

  # ###########################################################
  # Die Breite der Kurve [neu] setzen.
  def BreiteEinstellen(self, breite):
    if self.breite>breite:
      d=self.breite-breite  # Kurve um "d" kleiner machen
      for i in range(d):
        self.Ywerte.pop(0)
      self.aktPos=max(self.aktPos-d, 0)
    elif self.breite<breite:
      d=breite-self.breite  # Kurve um "d" groesser machen
      for i in range(d):
        self.Ywerte.append(0)
    else:
      return  # Breite hat sich nicht veraendert

    self.maximal=max(self.Ywerte)
    self.maximalAufgerundet=self.Aufrunden(self.maximal)
    self.breite=breite

  # ###########################################################
  # Einen Y-Wert ("wert") von rechts in die Liste reinschieben.
  # Ueber "glaetten_stufe" wird bestimmt, an wie viele der
  # alten Werte der aufzunehmende Wert angeglichen werden soll.
  # Mit "alarm" ==True wird bestimmt, ob die Funktion melden
  # soll, wenn die Werte 5x hintereinander unterhalb von 1%
  # des Maximums lagen.
  def WertAufnehmen(self, wert, glaetten_stufe=0, alarm=False):
    rc=0
    if self.aktPos<self.breite:     # wenn Liste noch nicht ganz voll ist
      if glaetten_stufe>0:          # ...per Index aufnehmen
        wert=self.glaetten(self.aktPos-1, wert, glaetten_stufe)
      self.Ywerte[self.aktPos]=wert
      self.aktPos+=1
    else:                           # ...sonst reinschieben
      w=self.Ywerte.pop(0)
      if w==self.maximal:             # wenn derzeitiger Maximal-Wert rausgeschoben wurde
        self.maximal=max(self.Ywerte) # ...dann neuen Maximal-Wert suchen
        self.maximalAufgerundet=self.Aufrunden(self.maximal)
      if glaetten_stufe>0:
        wert=self.glaetten(self.aktPos-2, wert, glaetten_stufe)
      self.Ywerte.append(wert)

    if alarm==True and self.aktPos>1:
      proz_max=100.0/self.maximal*(self.Ywerte[self.aktPos-1] + self.Ywerte[self.aktPos-2])/2
      if proz_max<1.0:            # wenn Bandbreite unterhalb 1% des Maximums...
        self.konstant+=1
        if self.konstant>4:       # ...und das 5x hintereinander so ist...
          rc=1                    # ...dann Kenner fuer "Sound spielen" zurueckliefern
      else:
        self.konstant=0

    if wert>self.maximal:
      self.maximal=wert
      self.maximalAufgerundet=self.Aufrunden(self.maximal)
    return(rc)

  # ###########################################################
  # Liefert den geglaetteten Wert von "wert", indem er als
  # Mittelwert der letzten "stufe" Werte zurueckgegeben wird.
  # Der juengste alte Wert befindet sich am Index "maxidx".
  def glaetten(self, maxidx, wert, stufe):
    anz=max(0, min(maxidx, stufe))
    w=0
    for i in range(anz):
      w+=self.Ywerte[maxidx-i]
    w+=wert
    return(w/(anz+1))

  # ###########################################################
  # Den Inhalt der Liste um X-Werte erweitern und als
  # Koordinaten-Liste zurueckgeben.
  # Die Y-Werte werden so skaliert, dass der groesste Y-Wert
  # der Liste unterhalb von "max_y" landet.
  # Die Koordinaten-Liste liegt immer zwischen den Eckpunkten
  # der Null-Linie - so dass sie als gefuelltes Polygon
  # dargestellt werden kann.
  def ListeLiefern(self, max_y):
    l=[(self.pos_x, self.pos_y)]                      # links unten
    for x in range(self.breite):
      l.append((x+self.pos_x, self.pos_y-max(min(self.Ywerte[x]*self.hoehe/max_y, self.hoehe), 0)))
    l.append((self.breite-1+self.pos_x, self.pos_y))  # rechts unten
    return(l)

  # ###########################################################
  # Liefert den groessten Wert aus der Liste als Liste mit drei
  # Elementen:
  #  [Maximal-Wert, aufgerundeter Maximal-Wert, aufgerundeter Maximal-Wert mit Faktor (B/KB/MB/GB)]
  def MaximalwertLiefern(self):
    return((self.maximal, self.maximalAufgerundet[0], self.maximalAufgerundet[1]))

  # ###########################################################
  # Liefert ein Raster fuer die Kurve als Input fuer DrawLineList.
  def RasterLiefern(self):
    r=[]
    for i in [0.25, 0.5, 0.75, 1]:
      r.append([self.pos_x, self.pos_y-(self.hoehe*i), self.pos_x+self.breite, self.pos_y-(self.hoehe*i)])
    for i in range(self.pos_x+self.breite, self.pos_x, -60):
      r.append([i, self.pos_y+5, i, self.pos_y-self.hoehe])
    return(r)

  # ###########################################################
  # Liefert den Namen der Kurve
  def NameLiefern(self):
    return(self.name)

  # ###########################################################
  # Liefert den aufgerundeten Betrag von "z" als Liste mit
  # zwei Werten. Der erste Wert entaelt den Betrag als Zahl,
  # der zweite als String mit Groessen-Faktor (B/KB/MB/GB).
  def Aufrunden(self, z):
    k=z
    f=0
    while k>1024:
      k/=1024
      f+=1
    fd=[100, 5, 1, 1]
    fe=["B", "KB", "MB", "GB"]
    e=((k//fd[f])+1)*fd[f]
    r=e
    for i in range(f):
      r*=1024
    return([int(r), str(e) + " " + fe[f]])

# ###########################################################
# Liefert "num" in der passendsten Groessenangabe
def prettySize(num):
  for x in ['','KB','MB','GB', 'TB']:
    if num<1024.0:
      return("{0:3.0f} {1:s}".format(num, x))
    num/=1024.0

ABSTAND_X=10
ABSTAND_Y=20
RAND_UNTEN=5
INFO_BEREICH=25

# ###########################################################
# Das Fenster.
class MyPanel(wx.Window):
  def __init__(self, parent):
    wx.Window.__init__(self, parent)

    try:
      self.mc = wx.media.MediaCtrl(self)
    except NotImplementedError:
      self.Destroy()
      raise
    self.mc.Load(ALARM_FILE)
    #self.mc.SetVolume(0.2)
    self.alarm=False

    self.parent=parent
    self.SetBackgroundStyle(wx.BG_STYLE_CUSTOM)
    self.Bind(wx.EVT_PAINT, self.on_paint)

    self.MenueErstellen()
    self.Bind(wx.EVT_CONTEXT_MENU, self.OnContextMenu)

    self.KonfigEinlesen()

    self.Bind(wx.EVT_TIMER, self.on_timer)
    self.timer=wx.Timer(self)
    self.timer.Start(self.updateIntervall)

    self.basis_x=ABSTAND_X
    self.basis_y=ABSTAND_Y+self.hoehe

    self.eth0=eth_messen("eth0:")
    self.k1=Kurve(self.basis_x+self.breite+ABSTAND_X, self.basis_y, self.breite, self.hoehe, "eth0")
    if self.kurven_uebereinander==True:
      self.k2=Kurve(self.basis_x+self.breite+ABSTAND_X, self.basis_y                     , self.breite, self.hoehe)
    else:
      self.k2=Kurve(self.basis_x+self.breite+ABSTAND_X, self.basis_y+self.hoehe+ABSTAND_Y, self.breite, self.hoehe)

    self.fb=Fritzbox()
    r, s=self.fb.Maximalwerte()
    self.k3=Kurve(self.basis_x, self.basis_y, self.breite, self.hoehe, \
                  "Fritzbox (" + prettySize(r) + " / " + prettySize(s) + ")")
    if self.kurven_uebereinander==True:
      self.k4=Kurve(self.basis_x, self.basis_y                     , self.breite, self.hoehe)
    else:
      self.k4=Kurve(self.basis_x, self.basis_y+self.hoehe+ABSTAND_Y, self.breite, self.hoehe)

    if self.dlan_anzeigen==True:
      self.devolo=devolo()
      self.devolo_online=0

    wx.CallLater(100, self.FensterPositionAnpassen)

  # ###########################################################
  # Konfig-File einlesen und Werte entsprechend einstellen.
  def KonfigEinlesen(self):
    fc=wx.FileConfig(localFilename=cfgFile_g)
    self.kurven_uebereinander=fc.ReadInt("KurvenUebereinander", 1)
    self.updateIntervall=     fc.ReadInt("UpdateIntervall", 1000)
    self.hoehe=               fc.ReadInt("KurvenHoehe", 60)
    self.breite=              fc.ReadInt("KurvenBreite", 300)
    self.glaettung=           fc.ReadInt("Glaettung", 0)
    self.dlan_anzeigen=       fc.ReadInt("dlanAnzeigen", 0)
    self.eth0_anzeigen=       fc.ReadInt("eth0Anzeigen", 1)
    self.farbeEmpfangsKurve=  fc.Read("farbeEmpfangsKurve", "#0000FF")
    self.farbeSendeKurve=     fc.Read("farbeSendeKurve"   , "#FFFF00")
    self.farbeHintergrund=    fc.Read("farbeHintergrund"  , "#CCCCCC")
    self.farbeRaster=         fc.Read("farbeRaster"       , "#FFFFFF")
    self.farbeSchrift=        fc.Read("farbeSchrift"      , "#000000")

  # ###########################################################
  # Stellt das Kontext-Menue dar.
  def OnContextMenu(self, event):
    self.PopupMenu(self.menue)

  # ###########################################################
  # Legt das Kontext-Menue an.
  def MenueErstellen(self):
    self.menue=wx.Menu()
    self.menue.Append(100, 'Einstellungen ändern')
    self.menue.Append(101, 'Einstellungen speichern')
    self.menue.AppendSeparator()
    self.menue.Append(102, 'Alarm', '', True)
    #self.menue.Append(109, 'debug')
    self.menue.AppendSeparator()
    self.menue.Append(108, 'Über das Programm')

    self.menue.Check(102, self.alarm)

    self.Bind(wx.EVT_MENU, self.KonfigAendern, id=100)
    self.Bind(wx.EVT_MENU, self.KonfigSchreiben, id=101)
    self.Bind(wx.EVT_MENU, self.Alarm, id=102)
    #self.Bind(wx.EVT_MENU, self.debug, id=109)
    self.Bind(wx.EVT_MENU, self.UeberGewaehlt, id=108)

  # ###########################################################
  #
  def debug(self, event):
    pass

  # ###########################################################
  # Setzt "self.alarm" gemaess Menue-Auswahl und spielt den
  # Sound einmal ab, wenn der Alarm eingeschaltet wurde.
  def Alarm(self, event):
    self.alarm=self.menue.IsChecked(102)
    if self.alarm==True:
      self.mc.Play()

  # ###########################################################
  # Fenster-Position/Groesse den geaenderten Anzeige-Elementen
  # anpassen.
  def FensterPositionAnpassen(self):
    ax, ay=self.parent.GetScreenPositionTuple()
    aw, ah=self.parent.GetSizeTuple()

    ib=0
    if self.dlan_anzeigen==True:          ib=INFO_BEREICH
    if self.eth0_anzeigen==True:          w=self.basis_x + 2*self.breite + 2*ABSTAND_X + ib
    else:                                 w=self.basis_x +   self.breite +   ABSTAND_X + ib
    if self.kurven_uebereinander==True:   h=self.basis_y + RAND_UNTEN
    else:                                 h=self.basis_y + RAND_UNTEN + ABSTAND_Y + self.hoehe
    self.parent.SetSize((w, h))

    dx=aw-w # Ausdehung des Fensters entsprechend der Bildschirm-Ecke, in der sich das Fenster befindet
    dy=ah-h
    links, oben, rechts, unten=wx.Display().GetGeometry()

    if ax==0 and ay==0:                               self.parent.Move((ax, ay))        # links oben
    if ax==0 and (ay+ah)>(unten-100):                 self.parent.Move((ax, ay+dy))     # links unten
    if (ax+aw)>(rechts-100) and ay==0:                self.parent.Move((ax+dx, ay))     # rechts oben
    if (ax+aw)>(rechts-100) and (ay+ah)>(unten-100):  self.parent.Move((ax+dx, ay+dy))  # rechts unten

  # ###########################################################
  # Oeffnet den Einstellungs-Dialog und verarbeitet danach ggf.
  # die Aenderungen an den Konfigurations-Parametern.
  def KonfigAendern(self, event):
    d=EinstellungsDialog( self, self.updateIntervall, self.hoehe, self.breite, \
                          self.glaettung, self.dlan_anzeigen, self.eth0_anzeigen, \
                          self.kurven_uebereinander, self.farbeEmpfangsKurve, self.farbeSendeKurve, \
                          self.farbeHintergrund, self.farbeRaster, self.farbeSchrift)
    if d.ShowModal()==wx.ID_OK:
      r=d.GetValues()
      hoehe_oder_breite_geaendert=0
      if self.updateIntervall!=r[0]:
        self.updateIntervall=r[0]               # updateIntervall
        self.timer.Stop()
        self.timer.Start(self.updateIntervall)

      if self.hoehe!=r[1]:
        self.hoehe=r[1]                         # kurvenHoehe
        self.k1.HoeheEinstellen(self.hoehe)
        self.k2.HoeheEinstellen(self.hoehe)
        self.k3.HoeheEinstellen(self.hoehe)
        self.k4.HoeheEinstellen(self.hoehe)
        hoehe_oder_breite_geaendert=1

      if self.breite!=r[2]:
        self.breite=r[2]                        # kurvenBreite
        self.k1.BreiteEinstellen(self.breite)
        self.k2.BreiteEinstellen(self.breite)
        self.k3.BreiteEinstellen(self.breite)
        self.k4.BreiteEinstellen(self.breite)
        hoehe_oder_breite_geaendert=1

      if hoehe_oder_breite_geaendert==1:
        self.basis_y=ABSTAND_Y+self.hoehe
        self.k1.PositionEinstellen(self.basis_x+self.breite+ABSTAND_X, self.basis_y)
        self.k3.PositionEinstellen(self.basis_x, self.basis_y)

      self.glaettung=           r[3]            # glaettung

      if self.dlan_anzeigen!=r[4]:
        self.dlan_anzeigen=r[4]                 # dlan_anzeigen
        if self.dlan_anzeigen==True:
          self.devolo=devolo()
          self.devolo_online=0
        else:
          del self.devolo

      self.eth0_anzeigen=       r[5]            # eth0_anzeigen
      self.kurven_uebereinander=r[6]            # kurven_uebereinander
      self.farbeEmpfangsKurve=  r[7]            # farbeEmpfangsKurve
      self.farbeSendeKurve=     r[8]            # farbeSendeKurve
      self.farbeHintergrund=    r[9]
      self.farbeRaster=         r[10]
      self.farbeSchrift=        r[11]

      if self.kurven_uebereinander==True:
        self.k2.PositionEinstellen(self.basis_x+self.breite+ABSTAND_X, self.basis_y)
        self.k4.PositionEinstellen(self.basis_x, self.basis_y)
      else:
        self.k2.PositionEinstellen(self.basis_x+self.breite+ABSTAND_X, self.basis_y+self.hoehe+ABSTAND_Y)
        self.k4.PositionEinstellen(self.basis_x, self.basis_y+self.hoehe+ABSTAND_Y)
    d.Destroy()
    self.FensterPositionAnpassen()

  # ###########################################################
  # Speichert die Groesse und Position des Fensters im
  # Konfig-File.
  def KonfigSchreiben(self, event):
    fc=wx.FileConfig(localFilename=cfgFile_g)
    sp=self.GetScreenPosition()
    ss=self.GetSizeTuple()
    fc.WriteInt("pos_x",  sp[0])
    fc.WriteInt("pos_y",  sp[1])
    fc.WriteInt("size_x", ss[0])
    fc.WriteInt("size_y", ss[1])
    fc.WriteInt("KurvenUebereinander",  self.kurven_uebereinander)
    fc.WriteInt("UpdateIntervall",      self.updateIntervall)
    fc.WriteInt("KurvenHoehe",          self.hoehe)
    fc.WriteInt("KurvenBreite",         self.breite)
    fc.WriteInt("Glaettung",            self.glaettung)
    fc.WriteInt("dlanAnzeigen",         self.dlan_anzeigen)
    fc.WriteInt("eth0Anzeigen",         self.eth0_anzeigen)
    fc.Write("farbeEmpfangsKurve",      str(self.farbeEmpfangsKurve))
    fc.Write("farbeSendeKurve",         str(self.farbeSendeKurve))
    fc.Write("farbeHintergrund",        str(self.farbeHintergrund))
    fc.Write("farbeRaster",             str(self.farbeRaster))
    fc.Write("farbeSchrift",            str(self.farbeSchrift))
    fc.Flush()

  # ###########################################################
  # Menue: Ueber
  def UeberGewaehlt(self, event):
    info=wx.AboutDialogInfo()
    info.SetName("Bandbreiten-Monitor")
    info.SetVersion("2.0")
    info.SetCopyright("D.A.  (05.2012)")
    info.SetDescription("Ein kleines Programm zur Anzeige der Bandbreiten-Nutzung von eth0 und FritzBox.")
    info.SetLicence("Dieses Programm ist freie Software gemaess GNU General Public License")
    info.AddDeveloper("Detlev Ahlgrimm")
    wx.AboutBox(info)

  # ###########################################################
  # Ruft einmal pro Update-Intervall die Anzeige-Update-Funktion
  # auf.
  def on_timer(self, event):
    self.update_drawing()

  # ###########################################################
  # Aktualisiert die internen Listen im Sekunden-Takt, um
  # danach einen Fenster-Refresh einzuleiten.
  def update_drawing(self):
    r, s=self.eth0.UebertragungsRate()
    self.k1.WertAufnehmen(r, self.glaettung)
    self.k2.WertAufnehmen(s, self.glaettung)

    r, s=self.fb.UebertragungsRate()
    alarm=self.k3.WertAufnehmen(r, self.glaettung, self.alarm)
    self.k4.WertAufnehmen(s, self.glaettung)
    self.Refresh(False)

    if self.dlan_anzeigen==True:
      self.devolo_online=self.devolo.online()

    if alarm>0:
      self.mc.Play()
      self.alarm=False
      self.menue.Check(102, self.alarm)

  # ###########################################################
  # Aktualisiert das Fenster.
  def on_paint(self, event):
    dc=wx.AutoBufferedPaintDC(self)
    dc.SetBackground(wx.Brush(self.farbeHintergrund))
    dc.Clear()

    # -----------------------------------------------------------
    # Raster zeichnen
    dc.SetPen(wx.Pen(self.farbeRaster))
    l=[]
    if self.eth0_anzeigen==True:
      l+=self.k1.RasterLiefern()    # Raster fuer eth0-Empfangen
    l+=self.k3.RasterLiefern()      # Raster fuer Fritzbox-Empfangen

    if self.kurven_uebereinander==False:
      if self.eth0_anzeigen==True:
        l+=self.k2.RasterLiefern()  # Raster fuer eth0-Senden
      l+=self.k4.RasterLiefern()    # Raster fuer Fritzbox-Senden
    dc.DrawLineList(l)

    # -----------------------------------------------------------
    # Kurven zeichnen
    dc.SetPen(wx.Pen(self.farbeEmpfangsKurve))
    dc.SetBrush(wx.Brush(self.farbeEmpfangsKurve))

    if self.eth0_anzeigen==True:
      if self.kurven_uebereinander==True:  # Kurven ueberlagert darstellen
        if self.k1.MaximalwertLiefern()[1]>self.k2.MaximalwertLiefern()[1]:
          m1=self.k1.MaximalwertLiefern()
        else:
          m1=self.k2.MaximalwertLiefern()
      else:
        m1=self.k1.MaximalwertLiefern()
      # m1 enthaelt jetzt den Maximal-Kurvenhoehe fuer k1 und ggf. k2 (eth0)
      l=self.k1.ListeLiefern(m1[1])
      dc.DrawPolygon(l)

    if self.kurven_uebereinander==True:  # Kurven ueberlagert darstellen
      if self.k3.MaximalwertLiefern()[1]>self.k4.MaximalwertLiefern()[1]:
        m3=self.k3.MaximalwertLiefern()
      else:
        m3=self.k4.MaximalwertLiefern()
    else:
      m3=self.k3.MaximalwertLiefern()
    # m3 enthaelt jetzt den Maximal-Kurvenhoehe fuer k3 und ggf. k4 (Fritzbox)
    l=self.k3.ListeLiefern(m3[1])
    dc.DrawPolygon(l)

    dc.SetPen(wx.Pen(self.farbeSendeKurve))
    dc.SetBrush(wx.Brush(self.farbeSendeKurve))

    if self.eth0_anzeigen==True:
      if self.kurven_uebereinander==True:  # Kurven ueberlagert darstellen
        m=m1  # Kurvenhoehe von k1
      else:
        m=self.k2.MaximalwertLiefern()
      l=self.k2.ListeLiefern(m[1])
      dc.DrawPolygon(l)

    if self.kurven_uebereinander==True:  # Kurven ueberlagert darstellen
      m=m3  # Kurvenhoehe von k3
    else:
      m=self.k4.MaximalwertLiefern()
    l=self.k4.ListeLiefern(m[1])
    dc.DrawPolygon(l)

    # -----------------------------------------------------------
    # Texte zeichen
    dc.SetTextForeground(self.farbeSchrift)
    if self.eth0_anzeigen==True:
      w, h=dc.GetTextExtent(self.k1.NameLiefern())
      y=self.k1.xywh()[1]-self.k1.xywh()[3]-h
      dc.DrawText(self.k1.NameLiefern(), self.k1.xywh()[0]+self.k1.xywh()[2]-w, y)
      dc.DrawText(m1[2], self.k1.xywh()[0], y)

    w, h=dc.GetTextExtent(self.k3.NameLiefern())
    y=self.k3.xywh()[1]-self.k3.xywh()[3]-h
    dc.DrawText(self.k3.NameLiefern(), self.k3.xywh()[0]+self.k3.xywh()[2]-w, y)
    dc.DrawText(m3[2], self.k3.xywh()[0], y)

    if self.kurven_uebereinander==False:  # Kurven einzeln darstellen
      if self.eth0_anzeigen==True:
        dc.DrawText(self.k2.MaximalwertLiefern()[2], self.k2.xywh()[0], self.k2.xywh()[1]-self.k2.xywh()[3]-h)
      dc.DrawText(self.k4.MaximalwertLiefern()[2], self.k4.xywh()[0], self.k4.xywh()[1]-self.k4.xywh()[3]-h)

    # -----------------------------------------------------------
    # Dlan-Info-Bereich
    if self.dlan_anzeigen==True:
      if self.eth0_anzeigen==True:          w=self.basis_x + 2*self.breite + 2*ABSTAND_X
      else:                                 w=self.basis_x +   self.breite +   ABSTAND_X
      if self.kurven_uebereinander==True:   h=self.basis_y + RAND_UNTEN
      else:                                 h=self.basis_y + RAND_UNTEN + ABSTAND_Y + self.hoehe

      bw, bh=dc.GetTextExtent("B")  # es geht nur um die Hoehe
      dc.SetPen(wx.Pen("BLACK"))
      for i in range(4):
        b=1<<i
        if self.devolo_online&b==b: dc.SetBrush(wx.Brush("YELLOW"))
        else:                       dc.SetBrush(wx.Brush(self.farbeHintergrund))
        dc.DrawCirclePoint((w, self.basis_y-(5+20*i)), 5)
        dc.DrawText(self.devolo.namen()[i], w+10, self.basis_y-(5+20*i)-bh/2)

# ###########################################################
# Ein Dialog zum Aendern von Einstellungen
class EinstellungsDialog(wx.Dialog):
  def __init__( self, parent, updateIntervall, kurvenHoehe, kurvenBreite, glaettung, \
                dlan_anzeigen, eth0_anzeigen, kurven_uebereinander, farbeEmpfangsKurve, farbeSendeKurve, \
                farbeHintergrund, farbeRaster, farbeSchrift):
    super(EinstellungsDialog, self).__init__(parent=parent, title="Einstellungen")

    st11=wx.StaticText(self, label="Update-Intervall [ms]:")
    self.updateIntervall=wx.SpinCtrl(self, wx.ID_ANY, "1000", size=(90, -1), min=500, max=10000)
    self.updateIntervall.SetValue(updateIntervall)
    self.updateIntervall.SetToolTip(wx.ToolTip('500 - 10.000'))

    st12=wx.StaticText(self, label="Kurven-Höhe [Pixel]:")
    self.kurvenHoehe=wx.SpinCtrl(self, wx.ID_ANY, "70", size=(70, -1), min=10, max=200)
    self.kurvenHoehe.SetValue(kurvenHoehe)
    self.kurvenHoehe.SetToolTip(wx.ToolTip('10 - 200'))

    st13=wx.StaticText(self, label="Kurven-Breite [Pixel]:")
    self.kurvenBreite=wx.SpinCtrl(self, wx.ID_ANY, "300", size=(70, -1), min=200, max=500)
    self.kurvenBreite.SetValue(kurvenBreite)
    self.kurvenBreite.SetToolTip(wx.ToolTip('200 - 500'))

    st14=wx.StaticText(self, label="Glättungswert [Werte]:")
    self.glaettung=wx.SpinCtrl(self, wx.ID_ANY, "0", size=(40, -1), min=0, max=5)
    self.glaettung.SetValue(glaettung)
    self.glaettung.SetToolTip(wx.ToolTip('0 - 5'))

    self.dlan_anzeigen=wx.CheckBox(self, label="Dlan-Monitor")
    self.dlan_anzeigen.SetValue(dlan_anzeigen)

    self.eth0_anzeigen=wx.CheckBox(self, label="eth0 anzeigen")
    self.eth0_anzeigen.SetValue(eth0_anzeigen)

    self.kurven_uebereinander=wx.CheckBox(self, label="Kurven übereinander")
    self.kurven_uebereinander.SetValue(kurven_uebereinander)

    st15=wx.StaticText(self, label="Farbe Empfangs-Kurve:")
    self.farbeEmpfangsKurve=wx.ColourPickerCtrl(self, wx.ID_ANY)
    self.farbeEmpfangsKurve.SetColour(farbeEmpfangsKurve)

    st16=wx.StaticText(self, label="Farbe Sende-Kurve:")
    self.farbeSendeKurve=wx.ColourPickerCtrl(self, wx.ID_ANY)
    self.farbeSendeKurve.SetColour(farbeSendeKurve)

    st17=wx.StaticText(self, label="Hintergrund-Farbe:")
    self.farbeHintergrund=wx.ColourPickerCtrl(self, wx.ID_ANY)
    self.farbeHintergrund.SetColour(farbeHintergrund)

    st18=wx.StaticText(self, label="Raster-Farbe:")
    self.farbeRaster=wx.ColourPickerCtrl(self, wx.ID_ANY)
    self.farbeRaster.SetColour(farbeRaster)

    st19=wx.StaticText(self, label="Schrift-Farbe:")
    self.farbeSchrift=wx.ColourPickerCtrl(self, wx.ID_ANY)
    self.farbeSchrift.SetColour(farbeSchrift)

    ok=     wx.Button(self, wx.ID_OK,     "Ok")
    abbruch=wx.Button(self, wx.ID_CANCEL, "Abbruch")

    sizer=wx.GridBagSizer()

    flag=wx.ALIGN_CENTER_VERTICAL|wx.ALL
    border=5
    # size(x, y)    pos(y, x)    span(y, x)
    sizer.Add(st11,                       pos=(0, 0), flag=flag, border=border)
    sizer.Add(self.updateIntervall,       pos=(0, 1), flag=flag, border=border)
    sizer.Add(st12,                       pos=(1, 0), flag=flag, border=border)
    sizer.Add(self.kurvenHoehe,           pos=(1, 1), flag=flag, border=border)
    sizer.Add(st13,                       pos=(2, 0), flag=flag, border=border)
    sizer.Add(self.kurvenBreite,          pos=(2, 1), flag=flag, border=border)
    sizer.Add(st14,                       pos=(3, 0), flag=flag, border=border)
    sizer.Add(self.glaettung,             pos=(3, 1), flag=flag, border=border)
    sizer.Add(self.dlan_anzeigen,         pos=(4, 1), flag=flag, border=border)
    sizer.Add(self.eth0_anzeigen,         pos=(5, 1), flag=flag, border=border)
    sizer.Add(self.kurven_uebereinander,  pos=(6, 1), flag=flag, border=border)
    sizer.Add(st15,                       pos=(7, 0), flag=flag, border=border)
    sizer.Add(self.farbeEmpfangsKurve,    pos=(7, 1), flag=flag, border=border)
    sizer.Add(st16,                       pos=(8, 0), flag=flag, border=border)
    sizer.Add(self.farbeSendeKurve,       pos=(8, 1), flag=flag, border=border)

    sizer.Add(st17,                       pos=(9, 0), flag=flag, border=border)
    sizer.Add(self.farbeHintergrund,      pos=(9, 1), flag=flag, border=border)
    sizer.Add(st18,                       pos=(10, 0), flag=flag, border=border)
    sizer.Add(self.farbeRaster,           pos=(10, 1), flag=flag, border=border)
    sizer.Add(st19,                       pos=(11, 0), flag=flag, border=border)
    sizer.Add(self.farbeSchrift,          pos=(11, 1), flag=flag, border=border)

    sizer.Add(wx.StaticLine(self),        pos=(12, 0), span=(1, 2), flag=wx.ALL|wx.GROW, border=5)
    sizer.Add(ok,                         pos=(13, 0), flag=flag, border=border)
    sizer.Add(abbruch,                    pos=(13, 1), flag=flag, border=border)

    self.SetSizerAndFit(sizer)
    self.Center()
    abbruch.SetFocus()

  def GetValues(self):
    ek=self.farbeEmpfangsKurve.GetColour()
    sk=self.farbeSendeKurve.GetColour()
    hf=self.farbeHintergrund.GetColour()
    rf=self.farbeRaster.GetColour()
    sf=self.farbeSchrift.GetColour()
    return([self.updateIntervall.GetValue(),      \
            self.kurvenHoehe.GetValue(),          \
            self.kurvenBreite.GetValue(),         \
            self.glaettung.GetValue(),            \
            self.dlan_anzeigen.GetValue(),        \
            self.eth0_anzeigen.GetValue(),        \
            self.kurven_uebereinander.GetValue(), \
            ek.GetAsString(wx.C2S_HTML_SYNTAX),   \
            sk.GetAsString(wx.C2S_HTML_SYNTAX),   \
            hf.GetAsString(wx.C2S_HTML_SYNTAX),   \
            rf.GetAsString(wx.C2S_HTML_SYNTAX),   \
            sf.GetAsString(wx.C2S_HTML_SYNTAX) ])

# ###########################################################
# Der Fenster-Rahmen.
class MyFrame(wx.Frame):
  def __init__(self, parent, pos=wx.DefaultPosition, size=wx.DefaultSize):
    wx.Frame.__init__(self, None, wx.ID_ANY, "Bandbreitenmonitor v2.0", pos=pos, size=size)
    self.panel=MyPanel(self)

# ###########################################################
# Der Starter
if __name__=='__main__':
  fc=wx.FileConfig(localFilename=cfgFile_g)
  spx=fc.ReadInt("pos_x", -1)
  spy=fc.ReadInt("pos_y", -1)
  ssx=fc.ReadInt("size_x", -1)
  ssy=fc.ReadInt("size_y", -1)

  sp=(spx, spy) # (-1, -1) entspricht wx.DefaultPosition
  ss=(ssx, ssy) # (-1, -1) entspricht wx.DefaultSize

  app=wx.App(False)
  frame=MyFrame(None, pos=sp, size=ss)
  frame.Show(True)
  app.MainLoop()


import pytest
from com_hrbot_logger.log import *
from com_hrbot_constant.hrbot_config_mapper import *
from com_htbot_utility.utility import *
from com_htbot_utility.excel_reader import *
from analytics_module.conftest import *
import allure
from allure_commons.types import AttachmentType

logger = Log.get_logger()

@pytest.mark.usefixtures('setup')
class Test26:

    def test26_Verify_users_data_after_clicking_on_user_setting(self):
        driver  = self.driver
        try:
            logger.info('enter user\'s credentials to login page')
            element = self.driver.find_element_by_xpath(HrBot_Config_mapper.hrbot_locators.get("login_user_box"))
            element.send_keys(HrBot_Config_mapper.hrbot_config.get("username"))

            time.sleep(2)
            element = self.driver.find_element_by_xpath(HrBot_Config_mapper.hrbot_locators.get("login_pass_box"))
            element.send_keys(HrBot_Config_mapper.hrbot_config.get("password"))
            logger.info('User has successfully entered credentials')

            self.driver.find_element_by_xpath(HrBot_Config_mapper.hrbot_locators.get("login_button")).click()
            logger.info('User has successfully clicked on login button')

            logger.info('Waiting for the element')
            Utility.explicit_Wait1(HrBot_Config_mapper.hrbot_locators.get('conversation_reports'), 'visibility',  driver)

            url = self.driver.current_url
            if url:
                assert url == ExcelReader.read_excel().get("hrbot_homepage_url")
                logger.info('User has been navigated successfully to home page')
            else:
                logger.info('User is not navigated to home page')

            self.driver.find_element_by_xpath(HrBot_Config_mapper.hrbot_locators.get('users_management')).click()
            logger.info('User has successfully clicked on user\'s  module')

            url = self.driver.current_url
            url1 = ExcelReader.read_excel().get('hrbot_users_url')
            if url:
                assert url == url1.replace('\n', '')
                logger.info('User has been navigated successfully to user\'s page')
            else:
                logger.info('User is not navigated to user\'s page')

            Utility.explicit_Wait1(HrBot_Config_mapper.hrbot_locators.get('user_management'), 'visibility', driver)

            self.driver.find_element_by_xpath(HrBot_Config_mapper.hrbot_locators.get('total_users')).click()
            logger.info('User has clicked on total users tab successfully')

            time.sleep(2)
            try:
                users_number = self.driver.find_element_by_xpath(HrBot_Config_mapper.hrbot_locators.get('total_users_num')).text
                logger.info('Total users number has been fetched successfully how many users exist currently')
                print(users_number)
            except Exception as e:
                print('-----amjad-----', e)

            ls = ['user_name', 'email', 'role', 'region', 'active', 'created']
            dct = {}
            for i in range(1, 11):
                for j in range(1, 7):
                    print(str([j]))
                    time.sleep(1)
                    xpath = "//*[@class='row grid-odd no-gutters']"+ str([i]) +"/div[@class='pr-3 undefined']" +str([j])+ "/span"
                    print(xpath)
                    try:
                        data = self.driver.find_element_by_xpath("//*[@class='row grid-odd no-gutters']"+ str([i]) +"/div[@class='pr-3 undefined']" +str([j])+ "/span").text
                        dct[ls[j-1]] = data
                    except  Exception as e:
                        print('--------3-------', e)
                    print(dct)
                    logger.info('data has been displayed correctly as expected')

        except Exception as e:
            allure.attach(driver.get_screenshot_as_png(), 'screenshots', AttachmentType.PNG)
            logger.error('An Exception occurred in test case verify users data respectively 26')
            print(e)
            pytest.fail(e, pytrace=True)


# Write a program to convert speed of a vehicle given in km/hour to miles/hour.
# entering the kilometers through keybord
kilometers=float(input("enter the kilometrs value"))

# the converting  factor is

conv_fac= 0.621371

# converting the  km/hour to miles/hour
miles= kilometers *conv_fac

# printing the miles...
print(f"miles of {kilometers},{conv_fac} of {miles}")


import cv2
import numpy as np

# original = cv2.imread("14.jpg")
# duplicate = cv2.imread("862.jpg")

original = cv2.imread("1929.jpg")
duplicate = cv2.imread("1437.jpg")

original = cv2.cvtColor(original, cv2.COLOR_BGR2GRAY)
duplicate = cv2.cvtColor(duplicate, cv2.COLOR_BGR2GRAY)

height1, width1= original.shape
height2, width2 = duplicate.shape

# print(width1)
# print(width2)

# original = cv2.normalize(original, 0, 255, norm_type=cv2.NORM_MINMAX)
# duplicate = cv2.normalize(duplicate, 0, 255, norm_type=cv2.NORM_MINMAX)

# original = cv2.Sobel(original, cv2.CV_8U, 1, 0, ksize=3)
# duplicate = cv2.Sobel(duplicate, cv2.CV_8U, 1, 0, ksize=3)

retval, original = cv2.threshold(original, 150, 255, cv2.THRESH_BINARY)
retval, duplicate = cv2.threshold(duplicate, 150, 255, cv2.THRESH_BINARY)

# print(cv2.countNonZero(original))
# print(cv2.countNonZero(duplicate))

cv2.imshow("img1", original)
cv2.imshow("img2", duplicate)
# cv2.imshow("img4", original_1)

# Initiate SIFT detector
sift = cv2.xfeatures2d.SIFT_create()

# find the keypoints and descriptors with SIFT
kp1, des1 = sift.detectAndCompute(original, None)
kp2, des2 = sift.detectAndCompute(duplicate, None)

# FLANN parameters
FLANN_INDEX_KDTREE = 0
index_params = dict(algorithm=FLANN_INDEX_KDTREE, trees=5)
search_params = dict()

flann = cv2.FlannBasedMatcher(index_params, search_params)

matches = flann.knnMatch(des1, des2, k=2)

print(len(kp1))
print(len(kp2))
print(len(matches))

good_points = []

# ratio test
for match1, match2 in matches:
    if match1.distance < 0.2 * match2.distance:
        good_points.append(match1)

print(len(good_points))
flann_matches = cv2.drawMatches(original, kp1, duplicate, kp2, good_points, None)

cv2.imshow("img3", flann_matches)

cv2.waitKey(0)
cv2.destroyAllWindows()

Find similarities between two images/2/project.py


import sys

# 입력값을 받기
input = sys.stdin.readline
n, m = map(int, input().split())
# 초기값을 담을 리스트
lancable = []
# 랜선의 크기를 받고
for _ in range(n):
    lan = int(input())
    lancable.append(lan)

# 시작점 초기값 0으로 시작했다가 zerodivisionError가 발생
min_lan = 1
# 끝점
max_lan = max(lancable)

# while문을 돌면서
while min_lan <= max_lan:
    total = 0
    # 중간값
    mid = (min_lan + max_lan) // 2
    # 이미 가지고 있는 랜선의 개수만큼 돌면서
    for x in range(n):
        # 중간값으로 나눈 값들을 계속 더해주고
        total += lancable[x] // mid
    # 개수가 필요한 개수 이상이면 오른쪽 부분을 탐색하고
    if total >= m:
        min_lan = mid + 1
    # 개수가 필요한 개수 이하이면 왼쪽 부분을 탐색한다.
    else:
        max_lan = mid - 1
print(max_lan)


import sys
import time
import copy
import pickle
from socket import *

# define the format of the packet
class Packet:
    '''
    type should be either 0, 1, or 2
    seqnum is an integer
    length is the length of data, which is between 0 and 500
    data's length should not exceed 500
    '''
    def __init__(self, Type, Seqnum, Data):
        self.type = Type
        self.seqnum = Seqnum
        self.data = Data
        self.length = len(Data)

    def getType(self):
        '''
        get the type of the packet
        '''
        return self.type

    def getSeqnum(self):
        '''
        get the sequence number of the packet
        '''
        return self.seqnum

    def getLength(self):
        '''
        get the length of the data in the packet
        '''
        return self.length

    def getData(self):
        '''
        get the data content of the packet
        '''
        return self.data

# get the network emulator address, the emulator port number, the port number used to
#   receive ACKs from the emulator and the timeout interval in ms from command line input
Emu_address = sys.argv[1]
e_port = int(sys.argv[2])
ACK_port = int(sys.argv[3])
TOI = int(sys.argv[4]) / 1000  # from millisecond to second
TfileName = sys.argv[5]

# build empty log files
seqlogFile = open('seqnum.log', 'w')
acklogFile = open('ack.log', 'w')

# get the content of the file that will be transmitted
Tfile = open(TfileName, 'r')
TfileContent = Tfile.read()
content = copy.deepcopy(TfileContent)  # get a copy of the content to manipulate
Tfile.close()

N = 30  # set the window size to be 30 packets

# devide the data into packets
P = {}  # stores all the packets
seq = 0  # let the order of a packet be the sequence number of the packet
dataLength = len(content) // 30 + 1
seq = 0
while seq < N:  # check if content is all pipelined
    dataPiece = copy.deepcopy(content[: dataLength])  # get the data of the packet
    P[seq] = Packet(1, seq, dataPiece)  # append the new packet to P
    content = copy.deepcopy(content[dataLength: ])  # cut the packed part of content

    seq += 1  # increment the sequence number

# implement RDT

senderSocket = socket(AF_INET, SOCK_DGRAM)  # create a socket
senderSocket.bind(('', ACK_port))

# send data until every packets are sent and ACKed
while P != {}:
    # transmit every packet in P
    for sqnb in P:
        senderSocket.sendto(pickle.dumps(P[sqnb]), (Emu_address, e_port))  # send the packet
        seqlogFile.write(str(P[sqnb].getSeqnum()) + '\n')  # record the sent packet's sequence number

    # receive the ACKs before timeout
    try:
        senderSocket.settimeout(TOI)
        while True:
            ACK_packet, emulator_addr = senderSocket.recvfrom(40960)
            ACK_packet = pickle.loads(ACK_packet)  # decode the pickled class received

            # record the ACKed sequence number
            acklogFile.write(str(ACK_packet.getSeqnum()) + '\n')

            # get the sequence number of the packet
            ACK_seqnum = ACK_packet.getSeqnum()

            if ACK_seqnum in P:
                P.pop(ACK_seqnum)  # pop out the ACKed element in P since it has already been received

    except Exception:
        if P == {}:
            break
        else:
            continue

# every packet has been received by the receiver, send EOT
EOT = Packet(2, 9999, '')
senderSocket.sendto(pickle.dumps(EOT), (Emu_address, e_port))

# record the sending
seqlogFile.write(str(EOT.getSeqnum()) + '\n')

# get the ACKed EOT
senderSocket.settimeout(1000)
ACK_packet, emulator_addr = senderSocket.recvfrom(40960)
ACK_packet = pickle.loads(ACK_packet)

# record the ACKed sequence number
acklogFile.write(str(ACK_packet.getSeqnum()) + '\n')

if ACK_packet.getType() == 2:
# close everything and quit
    senderSocket.close()
    seqlogFile.close()
    acklogFile.close()
    exit(0)


import tensorflow as tf
import numpy as np
from PIL import Image
import scipy.misc
import utils
import model
import segmentizer
import net

#test_path = 'learning/00001.jpg'
#test_path = 'learning2/57.jpg'
#test_path = 'input.jpg'
#learning_list = utils.get_files('resized_img/learning')
learning_list = utils.get_files('input_dev')

#input0 = utils.get_img(test_path,img_size=[48,48])
#input0 = np.array(Image.fromarray(input0.astype(np.uint8)))#.convert('L'))

#input_org = input0
#input1 = np.reshape(input0, [-1, input0.shape[0], input0.shape[1], 3])
#input = input_#np.zeros([1,  48, 48,3])
#input = np.zeros([1,  48, 48,3])

def imsave(path, img):
    #img = np.clip(img, 0, 255).astype(np.uint8)
    #print('out img data', img)
    Image.fromarray(img).save(path, quality=100)

device_ = '/cpu:0'

x =tf.placeholder(tf.float32, shape=[1,48,48,3],name="input")

#y = tf.placeholder(tf.float32, shape = [None,48*48],name="output_placeholder")
#

#segNet = net.SegNet()
#mask_pred = segNet(x)
# Simple SegNet

weight_kener_size = 5

conv1_weight_shape = [weight_kener_size, weight_kener_size, 3, 64]
conv2_weight_shape = [weight_kener_size, weight_kener_size, 64, 64]
conv3_weight_shape = [3, 3, 64, 64]

fc4_weight_shape = [12 * 12 * 64, 100]
fc5_weight_shape = [100, 400]
fc6_weight_shape = [400, 48 * 48]

print('process')
conv1_weight = model.weights_variables(conv1_weight_shape, "conv1_weight")
conv1_bias = model.bias_variables([64], "conv1_bias")
conv2_weight = model.weights_variables(conv2_weight_shape, "conv2_weight")
conv2_bias = model.bias_variables([64], "conv2_bias")
conv3_weight = model.weights_variables(conv3_weight_shape, "conv3_weight")
conv3_bias = model.bias_variables([64], "conv3_bias")
fc4_weight = model.weights_variables(fc4_weight_shape, "fc4_weight")
fc4_bias = model.bias_variables([100], "fc4_bias")
fc5_weight = model.weights_variables(fc5_weight_shape, "fc5_weight")
fc5_bias = model.bias_variables([400], "fc5_bias")
fc6_weight = model.weights_variables(fc6_weight_shape, "fc6_weight")
fc6_bias = model.bias_variables([48 * 48], "fc6_bias")

conv1 = tf.nn.conv2d(x, conv1_weight, strides=[1, 1, 1, 1], padding='SAME', name='conv')
pool1 = tf.nn.relu(conv1+conv1_bias)
pool1 = tf.nn.max_pool(pool1, ksize=(1, 3, 3, 1), strides=(1, 2, 2, 1), padding='SAME')

kenel2 = conv2_weight# + conv2_bias
conv2 = tf.nn.conv2d(pool1, conv2_weight, strides=[1, 1, 1, 1], padding='SAME', name='conv2')
pool2 = tf.nn.relu(conv2+conv2_bias)
pool2 = tf.nn.max_pool(pool2, ksize=(1, 3, 3, 1), strides=(1, 2, 2, 1), padding='SAME')

conv3 = tf.nn.conv2d(pool2, conv3_weight, strides=[1, 1, 1, 1], padding='SAME', name='conv2')
conv3 = tf.nn.relu(conv3+conv3_bias)

h_flat = tf.reshape(conv3, [-1, 12 * 12 * 64])  # -1은 batch size를 유지하는 것.
fc4 = (tf.matmul(h_flat, fc4_weight) + fc4_bias)
fc4 = tf.nn.sigmoid(fc4)
print('fc4', fc4)

fc5 = (tf.matmul(fc4, fc5_weight) + fc5_bias)
fc5 = tf.nn.sigmoid(fc5)
print('fc5', fc5)

# h_flat = tf.reshape(fc5, [-1, 12 * 12 * 64])  # -1은 batch size를 유지하는 것.
h = tf.matmul(fc5, fc6_weight) + fc6_bias
# fc6 = tf.nn.sigmoid(h, name="fc6")
output_node = tf.nn.sigmoid(h, name="output")
# mask_pred = segmentizer.inference(x)

model_directory = './weights/'

saver = tf.train.Saver()

init = tf.global_variables_initializer()

with tf.Session() as sess:
#
    sess.run(init)

    print('evaluate...')

    #saver = tf.train.import_meta_graph('model/model.ckpt.meta')
    saver.restore(sess,"model_test2/model.ckpt")
    #saver.restore(sess,tf.train.latest_checkpoint('model'))

    with open(model_directory + "conv1_W.bin", 'wb') as f:
        W_conv1_p = tf.transpose(conv1_weight, perm=[3, 0, 1, 2])
        f.write(sess.run(W_conv1_p).tobytes())
    with open(model_directory + "conv2_W.bin", 'wb') as f:
        W_conv2_p = tf.transpose(conv2_weight, perm=[3, 0, 1, 2])
        f.write(sess.run(W_conv2_p).tobytes())
    with open(model_directory + "conv3_W.bin", 'wb') as f:
        W_conv3_p = tf.transpose(conv3_weight, perm=[3, 0, 1, 2])
        f.write(sess.run(W_conv3_p).tobytes())

    with open(model_directory + "conv1_b.bin", 'wb') as f:
        f.write(sess.run(conv1_bias).tobytes())
    with open(model_directory + "conv2_b.bin", 'wb') as f:
        f.write(sess.run(conv2_bias).tobytes())
    with open(model_directory + "conv3_b.bin", 'wb') as f:
        f.write(sess.run(conv3_bias).tobytes())

    with open(model_directory + "fc4_W.bin", 'wb') as f:
        W_fc4_shp = tf.reshape(fc4_weight, [12, 12, 64, 100])
        W_fc4_p = tf.transpose(W_fc4_shp, perm=[3, 0, 1, 2])
        f.write(sess.run(W_fc4_p).tobytes())
    with open(model_directory + "fc5_W.bin", 'wb') as f:
        W_fc5_shp = tf.reshape(fc5_weight, [1, 1, 100, 400])
        W_fc5_p = tf.transpose(W_fc5_shp, perm=[3, 0, 1, 2])
        f.write(sess.run(W_fc5_p).tobytes())
    with open(model_directory + "fc6_W.bin", 'wb') as f:
        W_fc6_shp = tf.reshape(fc6_weight, [1, 1, 400, 48 * 48])
        W_fc6_p = tf.transpose(W_fc6_shp, perm=[3, 0, 1, 2])
        f.write(sess.run(W_fc6_p).tobytes())

    with open(model_directory + "fc4_b.bin", 'wb') as f:
        f.write(sess.run(fc4_bias).tobytes())
    with open(model_directory + "fc5_b.bin", 'wb') as f:
        f.write(sess.run(fc5_bias).tobytes())
    with open(model_directory + "fc6_b.bin", 'wb') as f:
        f.write(sess.run(fc6_bias).tobytes())

    len  = len(learning_list)
    for i in range(len):
        test_path = 'learning2/'+str(i+1)+".jpg"
        #test_path = 'input.jpg'
        image_q = utils.get_img(learning_list[i], img_size=[48, 48])
        # img = scipy.misc.imread("learning2/"+str(i+1)+".jpg", mode='RGB')
        # image_q = scipy.misc.imresize(img, [48,48],interp="lanczos")
        image_q = np.array(Image.fromarray(image_q.astype(np.uint8)))#.convert('L'))

        #image_q = np.array(Image.fromarray(image_q.astype(np.uint8)))

        image_q = np.reshape(image_q, [-1, 48, 48, 3])

        output = sess.run(output_node,feed_dict={x:image_q})

        output = np.reshape(output, [48, 48])
        array1 = np.array(output)
        array = 255 * array1

        image2 = Image.fromarray(array.astype(np.uint8))  # Image.fromarray(convert.astype(np.uint8))
        original_yuv = np.array(image2)  # .convert('YCbCr'))
        #imsave('eval/restore'+str(i)+".jpg", original_yuv)
        imsave('eval/'+learning_list[i], original_yuv)

        #image2 =np.array(Image.fromarray(input0.astype(np.uint8)))
        #original_yuv = np.array(image2)  # .convert('YCbCr'))
        #imsave('org_developing.jpg', original_yuv)

#print('input',input)


import pygame
from threading import Timer

from components.config import CONFIG, CONST, debug

from components.text import Text
from components.text.text_collection import TextCollection
from components.text.mutual_text import MutualText

from characters.player import Player

class TextEvent(object):
    """인게임 내에서 처리될 공통 텍스트 이벤트"""

    dialog_delayed = True
    """대화창의 텍스트 출력이 지연되어야 하는가? (REFRESH 이슈 & 텍스트 미리 출력 대응)"""

    dialog_paused = True
    """대화창의 텍스트 출력이 완성되었는가?"""

    dialog_closed = True
    """대화창 텍스트가 닫혀있는가?"""

    dialog: TextCollection = None
    """대화창 (Text 배열)"""

    NPC: Player = None
    """대화하는 NPC"""

    @classmethod
    def process_next_event(cls):
        # 다음 대화창 이벤트 구현

        if cls.dialog_paused:  # 대화창의 텍스트 출력이 완성되었을 때
            if cls.dialog.index == 0 and cls.dialog_closed:  # 대화창이 처음으로 출력될 때
                cls.dialog_closed = False  # 대화창 열림
                cls.dialog_paused = False  # 텍스트 출력 미완성

            else:
                if cls.dialog.jump_to_next():  # 대화창을 넘길 때
                    cls.dialog_paused = False  # 텍스트 출력 미완성

                else:  # 대화창의 텍스트가 더이상 없을 때
                    cls.dialog = None  # 대화창 초기화
                    cls.dialog_closed = True  # 대화창 닫힘
                    cls.dialog_paused = True  # 텍스트 출력 완성

                cls.dialog_delayed = True  # 텍스트 출력 지연

        else:
            cls.dialog_delayed = False  # 텍스트 미리 모두 출력
            cls.dialog_paused = True  # 텍스트 출력 완성

    @classmethod
    def process_animation_event(cls, surface: pygame.Surface = None):
        """
        한번에 애니메이션 이벤트 구현 (V2)
        :param surface: 렌더링할 화면 (기본: CONFIG.surface)
        """

        mutual_index = 0  # MutualText 클래스 index
        mutual_text_index = 0  # MutualText 클래스의 텍스트 index
        ch_x = cls.dialog.position[0]  # 대화창 시작 X좌표
        ch_y = cls.dialog.position[1]  # 대화창 시작 Y좌표

        def write_each():
            """각 문자 렌더링 (출력)"""
            nonlocal mutual_index, mutual_text_index, ch_x, ch_y

            if cls.dialog is None:  # 대화를 너무 빨리 넘긴 경우
                return  # 출력할 대화가 없으므로 종료

            if mutual_index + 1 > len(cls.dialog.current.texts):  # MutualText 배열의 범위를 벗어난 경우
                cls.dialog_paused = True  # 텍스트 출력 완성
                cls.dialog_delayed = True  # 텍스트 지연

                return  # 함수를 재귀할 때 무한 루프를 돌면 안되므로 반환

            mutual = cls.dialog.current.texts[mutual_index]  # MutualText 클래스 가져오기
            new_ch_pos = cls.dialog.current.write(
                mutual, mutual_text_index, cls.dialog.position, (ch_x, ch_y), surface
            )  # 텍스트 렌더링 후 좌표 갱신

            if new_ch_pos is None:  # 대화를 너무 빨리 넘긴 경우
                return  # 출력할 대화가 없으므로 종료

            ch_x = new_ch_pos[0]
            ch_y = new_ch_pos[1]

            mutual_text_index += 1

            if mutual_text_index + 1 > len(mutual.text):  # MutualText 클래스의 문자열 범위를 벗어난 경우
                mutual_index += 1  # 새로운 MutualText 클래스 가져오기 위해 index를 1씩 추가
                mutual_text_index = 0  # 새로운 MutualText 클래스를 가져오므로 index 초기화

            if mutual.delay > 0 and cls.dialog_delayed:  # 지연 시간이 있는 경우
                delay_per_second = mutual.delay / 1000.0  # 이 때 threading.Timer 클래스의 시간 변수는 단위가 초이므로 단위를 ms에서 초로 변환
                Timer(delay_per_second, write_each).start()  # threading.Timer 클래스로 특정 시간 후 비동기적으로 함수 재귀
            else:
                write_each()  # 특정 시간 없이 함수 재귀

        if surface is None: # 사용자 지정한 화면이 없다면
            surface = CONFIG.surface # 렌더링할 화면을 기본 지정한 화면으로 지정

        if not cls.dialog_paused:  # 텍스트 출력이 미완성인 경우
            write_each()  # 텍스트를 처음부터 출력


#### EXCEPTIONS ####

class MatrixIndexError(Exception):
    ''' An attempt has been made to access an invalid index in this matrix '''
    pass

class MatrixInvalidOperation(Exception):
    '''An attempt was made to perform an operation on this matrix which is
    not valid given its type'''
    pass

#### HELPER FUNCTIONS ####

def dot_product(first_list, second_list):
    ''' (list of float, list of float) -> float
    Given two lists of floats, determines the dot product
    The dot product is the sum of the product of each component of two vectors
    REQ: the length of both lists must be the same
    '''
    result = 0
    for i in range(0, len(first_list)):
        result += first_list[i] * second_list[i]

    return result

#### MATRIX ####

class Matrix():
    ''' A class to represent a mathematical matrix '''

    def __init__(self, m, n, default=0):
        ''' (Matrix, int, int, float) -> NoneType
        Creates a new (m x n) matrix with the given default value (0 if no value is given)
        '''
        self._rows = m
        self._cols = n
        self._matrix = []

        for i in range(0, self._rows):
            self._matrix.append([default] * (self._cols))

    def __str__(self):
        ''' (Matrix) -> str
        Returns a string representation of this Matrix
        '''
        result = ""

        for row in self._matrix:
            result += str(row) + "\n"

        return result

    def add(self, other):
        ''' (Matrix, Matrix) -> Matrix
        Adds two matrices together based on the mathematical definition of matrix addition
        REQ: both matrices must be the same size (same length rows and columns)
        '''
        if ((self._rows != other.get_rows()) or (self._cols != other.get_cols())):
            raise MatrixInvalidOperation("cannot add two matrices of different sizes")

        new_matrix = Matrix(self._rows, self._cols)
        for i in range(0, self._rows):
            for j in range(0, self._cols):
                new_matrix.set_element(i, j, self.get_element(i, j) + other.get_element(i, j))

        return new_matrix

    def subtract(self, other):
        ''' (Matrix, Matrix) -> Matrix
        Subtracts two matrices together based on the mathematical definition of matrix subtraction
        REQ: both matrices must be the same size (same length rows and columns)
        '''
        if ((self._rows != other.get_rows()) or (self._cols != other.get_cols())):
            raise MatrixInvalidOperation("cannot subtract two matrices of different sizes")

        new_matrix = Matrix(self._rows, self._cols)
        for i in range(0, self._rows):
            for j in range(0, self._cols):
                new_matrix.set_element(i, j, self.get_element(i, j) - other.get_element(i, j))

        return new_matrix

    def transpose(self):
        ''' (Matrix) -> Matrix
        Transposes the matrix based on the mathematical definition of matrix transposition
        (changes the rows to columns and the columns to rows; rotates the matrix by 45 degrees)
        '''
        new_rows = []
        for i in range(0, self._cols):
            new_rows.append(self.get_col(i))

        matrix = Matrix(self._cols, self._rows)
        for i in range(0, matrix.get_rows()):
            matrix.set_row(i, new_rows[i])

        return matrix

    def multiply_scalar(self, scalar):
        ''' (Matrix, float) -> Matrix
        Multiplies the matrix by a scalar value based on the mathematical definition of scalar multiplication
        '''
        matrix = Matrix(self._cols, self._rows)
        for i in range(0, self._rows):
            for j in range(0, self._cols):
                matrix.set_element(i, j, self.get_element(i, j) * scalar)

        return matrix

    def multiply(self, other):
        ''' (Matrix, Matrix) -> Matrix
        Multiplies two matrices together based on the mathematical definition of matrix multiplication
        REQ: the number of columns of the first matrix must be equal to the number of rows of the second matrix
        '''
        if (self._cols != other.get_rows()):
            raise MatrixInvalidOperation("cannot multiply matrices of these dimensions")

        matrix = Matrix(self._rows, other.get_cols())
        for i in range(0, matrix.get_rows()):
            for j in range(0, matrix.get_cols()):

                matrix.set_element(i, j, dot_product(self.get_row(i), other.get_col(j)))

        return matrix

    def get_element(self, row, col):
        ''' (Matrix, int, int) -> float
        Returns the element at the given index
        '''
        return self._matrix[row][col]

    def get_rows(self):
        ''' (Matrix) -> int
        Returns the number of rows in this Matrix
        '''
        return self._rows

    def get_cols(self):
        ''' (Matrix) -> int
        Returns the number of columns in this Matrix
        '''
        return self._cols

    def get_row(self, index):
        ''' (Matrix, int) -> list of float
        Returns the entire row given the index
        '''
        if ((index > self._rows) or (index < 0)):
            raise MatrixIndexError("the given index is out of bounds")

        return self._matrix[index]

    def get_col(self, index):
        ''' (Matrix, int) -> list of float
        Returns the entire column given the index
        '''
        if ((index > self._cols) or (index < 0)):
            raise MatrixIndexError("the given index is out of bounds")

        cols = []
        for row in self._matrix:
            cols.append(row[index])

        return cols

    def set_element(self, row, col, new_element):
        ''' (Matrix, int, int, float) -> NoneType
        Sets the given index to the value of new_element
        '''
        self._matrix[row][col] = new_element

    def set_row(self, index, new_row):
        ''' (Matrix, int, list of float)
        Sets the given row to the value of new_row
        REQ: new_row must be the same length as the original row
        '''
        if (len(new_row) != self._cols):
            raise MatrixIndexError("the new row is longer/shorter than the original row")
        if ((index > self._rows) or (index < 0)):
            raise MatrixIndexError("the given index is out of bounds")

        self._matrix[index] = new_row

    def set_col(self, index, new_col):
        ''' (Matrix, int, list of float)
        Sets the given column to the value of new_col
        REQ: new_col must be the same length as the original column
        '''
        if (len(new_col) != self._rows):
            raise MatrixIndexError("the new column is longer/shorter than the original column")
        if ((index > self._cols) or (index < 0)):
            raise MatrixIndexError("the given index is out of bounds")

        for i in range(0, len(self._matrix)):
            self._matrix[i][index] = new_col[i]


import numpy as np

def create_batch_from_file(label, samples, rate, starts):
    starts = np.asarray(starts)
    if len(samples.shape) > 1:
        raise "samples be of shape (n,) where 'n' is the number of samples"

    split_locations = (starts * rate).astype(int)
    batches = np.split(samples, split_locations)
    labels = list([label for _ in batches])

    return labels, batches


from collections import deque
from typing import Any, Deque, Dict, List, Optional, Sequence
from langchain.chains.llm import LLMChain
from pydantic import BaseModel, Field

from babyagi.task_creation_chain import TaskCreationChain
from babyagi.task_prioritization_chain import TaskPrioritizationChain
import babyagi.vectorstore as babyagi_vectorstore
from langchain.agents.agent import AgentExecutor

from langchain.vectorstores.base import VectorStore

from langchain.chains.base import Chain

from langchain.llms.base import BaseLLM

from langchain.tools.base import BaseTool

from langchain.agents.mrkl.base import ZeroShotAgent
from babyagi.tools import babyagi_tools

PREFIX = """You are an AI who performs one task based on the following objective: {objective}. Take into account these previously completed tasks: {context}."""
SUFFIX = """Question: {task}
{agent_scratchpad}"""

class BabyAGI(Chain, BaseModel):
    """Controller model for the BabyAGI agent."""

    task_list: Deque = Field(default_factory=deque)
    task_creation_chain: TaskCreationChain = Field(...)
    task_prioritization_chain: TaskPrioritizationChain = Field(...)
    execution_chain: AgentExecutor = Field(...)
    task_id_counter: int = Field(1)
    vectorstore: VectorStore = Field(init=False)
    max_iterations: Optional[int] = None
    class Config:
        """Configuration for this pydantic object."""

        arbitrary_types_allowed = True

    def add_task(self, task: Dict):
        self.task_list.append(task)

    def print_task_list(self):
        print("\033[95m\033[1m" + "\n*****TASK LIST*****\n" + "\033[0m\033[0m")
        for t in self.task_list:
            print(str(t["task_id"]) + ": " + t["task_name"])

    def print_next_task(self, task: Dict):
        print("\033[92m\033[1m" + "\n*****NEXT TASK*****\n" + "\033[0m\033[0m")
        print(str(task["task_id"]) + ": " + task["task_name"])

    def print_task_result(self, result: str):
        print("\033[93m\033[1m" + "\n*****TASK RESULT*****\n" + "\033[0m\033[0m")
        print(result)

    @property
    def input_keys(self) -> List[str]:
        return ["objective"]

    @property
    def output_keys(self) -> List[str]:
        return []

    def get_next_task(
      self,
      task_creation_chain: LLMChain,
      result: Dict,
      task_description: str,
      task_list: List[str],
      objective: str,
  ) -> List[Dict]:
      """Get the next task."""
      incomplete_tasks = ", ".join(task_list)
      response = task_creation_chain.run(
          result=result,
          task_description=task_description,
          incomplete_tasks=incomplete_tasks,
          objective=objective,
      )
      new_tasks = response.split("\n")
      return [{"task_name": task_name} for task_name in new_tasks if task_name.strip()]

    def prioritize_tasks(
            self,
        task_prioritization_chain: LLMChain,
        this_task_id: int,
        task_list: List[Dict],
        objective: str,
    ) -> List[Dict]:
        """Prioritize tasks."""
        task_names = [t["task_name"] for t in task_list]
        next_task_id = int(this_task_id) + 1
        response = task_prioritization_chain.run(
            task_names=task_names, next_task_id=next_task_id, objective=objective
        )
        new_tasks = response.split("\n")
        prioritized_task_list = []
        for task_string in new_tasks:
            if not task_string.strip():
                continue
            task_parts = task_string.strip().split(".", 1)
            if len(task_parts) == 2:
                task_id = task_parts[0].strip()
                task_name = task_parts[1].strip()
                prioritized_task_list.append({"task_id": task_id, "task_name": task_name})
        return prioritized_task_list

    def _get_top_tasks(self, vectorstore, query: str, k: int) -> List[str]:
        """Get the top k tasks based on the query."""
        results = vectorstore.similarity_search_with_score(query, k=k)
        if not results:
            return []
        sorted_results, _ = zip(*sorted(results, key=lambda x: x[1], reverse=True))
        return [str(item.metadata["task"]) for item in sorted_results]

    def execute_task(
        self, vectorstore, execution_chain: LLMChain, objective: str, task: str, k: int = 5
    ) -> str:
        """Execute a task."""
        context = self._get_top_tasks(vectorstore, query=objective, k=k)
        return execution_chain.run(objective=objective, context=context, task=task)

    def _call(self, inputs: Dict[str, Any]) -> Dict[str, Any]:
        """Run the agent."""
        objective = inputs["objective"]
        first_task = inputs.get("first_task", "Make a task list")
        self.add_task({"task_id": 1, "task_name": first_task})
        num_iters = 0
        while True:
            if self.task_list:
                self.print_task_list()

                # Step 1: Pull the first task
                task = self.task_list.popleft()
                self.print_next_task(task)

                # Step 2: Execute the task
                result = self.execute_task(
                    self.vectorstore, self.execution_chain, objective, task["task_name"]
                )
                this_task_id = int(task["task_id"])
                self.print_task_result(result)

                # Step 3: Store the result in Pinecone
                result_id = f"result_{task['task_id']}"
                self.vectorstore.add_texts(
                    texts=[result],
                    metadatas=[{"task": task["task_name"]}],
                    ids=[result_id],
                )

                # Step 4: Create new tasks and reprioritize task list
                new_tasks = self.get_next_task(
                    self.task_creation_chain,
                    result,
                    task["task_name"],
                    [t["task_name"] for t in self.task_list],
                    objective,
                )
                for new_task in new_tasks:
                    self.task_id_counter += 1
                    new_task.update({"task_id": self.task_id_counter})
                    self.add_task(new_task)
                self.task_list = deque(
                    self.prioritize_tasks(
                        self.task_prioritization_chain,
                        this_task_id,
                        list(self.task_list),
                        objective,
                    )
                )
            num_iters += 1
            if self.max_iterations is not None and num_iters == self.max_iterations:
                print(
                    "\033[91m\033[1m" + "\n*****TASK ENDING*****\n" + "\033[0m\033[0m"
                )
                break
        return {}

    @classmethod
    def create_prompt(
        cls,
        tools: Sequence[BaseTool],
        prefix: str = PREFIX,
        suffix: str = SUFFIX,
    ):
        prompt = ZeroShotAgent.create_prompt(
            tools,
            prefix=prefix,
            suffix=suffix,
            input_variables=["objective", "task", "context", "agent_scratchpad"],
        )
        return prompt

    @classmethod
    def from_llm(
        cls,
        llm: BaseLLM,
        tools: Sequence[BaseTool] = babyagi_tools,
        verbose: bool = False,
        **kwargs
    ) -> "BabyAGI":
        """Initialize the BabyAGI Controller."""
        vectorstore = kwargs.get('vectorstore', babyagi_vectorstore.vectorstore)
        task_creation_chain = TaskCreationChain.from_llm(llm, verbose=verbose)
        task_prioritization_chain = TaskPrioritizationChain.from_llm(
            llm, verbose=verbose
        )
        prompt = cls.create_prompt(tools)
        llm_chain = LLMChain(llm=llm, prompt=prompt)
        tool_names = [tool.name for tool in tools]
        agent = ZeroShotAgent(llm_chain=llm_chain, allowed_tools=tool_names)
        agent_executor = AgentExecutor.from_agent_and_tools(
            agent=agent, tools=tools, verbose=False
        )
        return cls(
            task_creation_chain=task_creation_chain,
            task_prioritization_chain=task_prioritization_chain,
            execution_chain=agent_executor,
            vectorstore=vectorstore,
            **kwargs,
        )


from __future__ import with_statement
import os
import shutil
from code import InteractiveInterpreter
from ConfigParser import RawConfigParser
from django.core.management.base import BaseCommand, CommandError
from . import CONFIG_DIR_NAME, DEFAULT_CONFIG_NAME, CommonMixin

CODE = """
from ConfigParser import RawConfigParser
import os
import getpass

def get_config():
    root = os.path.dirname(__file__)
    username = getpass.getuser() or 'nouser'
    path = os.path.join(root, 'configs',"%s_%s.cfg" % (os.uname()[1], username))
    if not os.path.exists(path):
        path = os.path.join(root, 'configs',"default.cfg")
    config = RawConfigParser()
    config.read(path)
    return config
config = get_config()

DEBUG = config.get('debug','DEBUG')
TEMPLATE_DEBUG = config.get('debug','TEMPLATE_DEBUG')
db_attrs = ['ENGINE', 'NAME', 'USER', 'PASSWORD', 'HOST', 'PORT']

DATABASES = {
    'default' : dict([(x, config.get('database', x))
                      for x in db_attrs])
}
"""

class Command(BaseCommand, CommonMixin):

    def _check_configs(self):
        if (os.path.exists(self.configs_path) and
            os.path.exists(self.default_config_path)):
            raise CommandError("Looks like this project is already using local configs, aborting")

    def handle(self, *args, **options):
        self._initialize_paths()
        self._check_settings()
        self._check_configs()
        settings = open(self.settings_path, 'r')
        db_braces = 0
        db_lines = []
        other_lines = []
        debug_line, template_debug_line = None, None
        for line in settings:
            if line.startswith('DEBUG'):
                debug_line = line
            elif line.startswith('TEMPLATE_DEBUG'):
                template_debug_line = line
            elif line.startswith('DATABASES') and '{' in line:
                db_braces = 1
                db_lines.append(line)
            elif db_braces:
                db_lines.append(line)
                if '{' in line:
                    db_braces += 1
                elif '}' in line:
                    db_braces -= 1
            else:
                other_lines.append(line)
        new_settings_path = os.path.join(self.base,
                                         'new_settings.py')
        with open(new_settings_path, 'w') as new_settings:
            new_settings.write(CODE)
            new_settings.write(''.join(other_lines))
        context = InteractiveInterpreter()
        context.runcode(''.join(db_lines))
        if debug_line: context.runcode(debug_line)
        if template_debug_line: context.runcode(template_debug_line)
        if not os.path.exists(self.configs_path):
            os.mkdir(self.configs_path)
        config = RawConfigParser()
        config.add_section('debug')
        config.set('debug', 'DEBUG', context.locals['DEBUG'])
        config.set('debug', 'TEMPLATE_DEBUG', context.locals['TEMPLATE_DEBUG'])
        db_attrs = ['ENGINE', 'NAME', 'USER', 'PASSWORD', 'HOST', 'PORT']
        config.add_section('database')
        for x in db_attrs:
            config.set('database', x, context.locals['DATABASES']['default'][x])
        with open(self.default_config_path, 'w') as config_file:
            config.write(config_file)
        #and now switch the configs
        shutil.move(self.settings_path,
                    os.path.join(self.base, 'old_settings.py'))
        shutil.move(new_settings_path,
                    self.settings_path)


#!/usr/bin/python3
from graphviz import Digraph, nohtml

if __name__ == "__main__":
    dot = Digraph(
        name='tree',
        comment='Tree',
        node_attr={
            'shape': 'record',
            'style': 'filled',
            'color': 'black',
            'fontcolor': 'white'
        })
    dot.node('9', nohtml('<f0> |<f1> 9|<f2>'))
    dot.node('5', nohtml('<f0> |<f1> 5|<f2>'))
    dot.edge('9:f0:sw', '5:f1')
    dot.node('18', nohtml('<f0> |<f1> 18|<f2>'), color='red')
    dot.edge('9:f2:se', '18:f1')
    print(dot.source)
    dot.render(
        filename=None, directory=None, view=False, cleanup=False, format='png')
    # dot.view()


import json
import utils
import config_reader as config
from googleapiclient.discovery import build
from googleapiclient.http import MediaIoBaseUpload
from google.oauth2 import service_account
from io import BytesIO

COINS_COLLECTION = "COINS"
SCOPES = ['https://www.googleapis.com/auth/drive.file']
SERVICE_ACCOUNT_FILE = 'models/drv/service.json'
SNAPSHOT_FOLDER_ID = utils.get_env("SNAPSHOT_FOLDER_ID") or config.get('DB', 'SNAPSHOT_FOLDER_ID', fallback=None)

class Aldriver:

    def __init__(self, date):
        self.json_snapshot = json.loads('{}')
        self.drive_service = None
        self.creds = service_account.Credentials.from_service_account_file(
        SERVICE_ACCOUNT_FILE, scopes=SCOPES)
        self.drive = build('drive', 'v3', credentials = self.creds)
        self.date = date.strftime("%Y%m%d")

    def insert_coins(self, coins_dict):
        coins = [c.__dict__ for c in coins_dict.values()]
        coins_jarr = json.dumps(coins)
        self.json_snapshot[COINS_COLLECTION] = coins_jarr

    def set_id_date(self, id):
        self.json_snapshot["ID"] = id
        self.json_snapshot["DATE"] = self.date

    def store(self):
        txt_fd = BytesIO(json.dumps(self.json_snapshot).encode())
        file_metadata = {'name': f'{self.date}.json', 'parents': [SNAPSHOT_FOLDER_ID]}
        media = MediaIoBaseUpload(txt_fd, mimetype='application/json',
            chunksize=1024*1024, resumable=True)
        file = self.drive.files().create(body=file_metadata,
                                        media_body=media,
                                        fields='id').execute()
        print('Uploaded File with ID: %s' % file.get('id'))
        txt_fd.close()


# Given a list of numbers and a number k,
#return whether any two numbers from the list add up to k.

# For example, given [10, 15, 3, 7]
#and k of 17, return true since 10 + 7 is 17.

def solution(num, k):
	## Naive solution:
	## check all combinations:
	val = False
	for i in range(len(num)-1):
		for j in range(1, len(num)):
			if num[i]+num[j] == k:
				val = True
				break
		if val == True:
			break

	## Improvement version 1:
	## sort the numbers, have two pointers running in
			## from both sides based on the difference

	return val

print (solution([10,15,3,7], 13))


from util.parse import *
from util.tile_map import TileMap

parse_input = compose(
	map_func(lambda line: [int(c) for c in line]),
	TileMap,
)

Coords = tuple[int, int]
TreeGrid = TileMap[int]
TreeMap = list[list[int]]

def transpose(tree_map: TreeMap) -> TreeGrid:
	return [
		[
			tree_map.get_at(x, y)
			for y in range(tree_map.get_height())
		]
		for x in range(tree_map.get_width())
	]

def get_trees_visible_from(tree_map: TreeMap, direction: str) -> list[Coords]:
	delta: int
	is_transposed = False
	tree_grid: TreeGrid
	if direction in ("north", "south"):
		tree_grid = transpose(tree_map)
		is_transposed = True
		delta = 1 if direction == "north" else -1

	elif direction in ("west", "east"):
		tree_grid = tree_map.state
		delta = 1 if direction == "west" else -1

	else:
		raise Exception(f"Bad direction: {direction}")

	visible_trees = []
	for y, row in enumerate(tree_grid):
		row_indices = range(0, len(row))
		if delta == -1:
			row_indices = reversed(row_indices)

		tallest_tree_seen = -float("inf")
		for x in row_indices:
			tree_height = tree_grid[y][x]
			if tree_height > tallest_tree_seen:
				tallest_tree_seen = tree_height

				visible_trees.append(
					(y, x) if is_transposed else (x, y)
				)

	return visible_trees

def add_coords(c1: Coords, c2: Coords) -> Coords:
	return (c1[0] + c2[0], c1[1] + c2[1])

def get_sightline_from(
	tree_map: TreeMap,
	x: int,
	y: int,
	direction: str,
) -> int:
	delta = {
		"north": (0, -1),
		"south": (0, 1),
		"west": (-1, 0),
		"east": (1, 0),
	}[direction]

	sightline = 0
	to_check = (x, y)
	while True:
		to_check = add_coords(to_check, delta)
		if not tree_map.contains_coordinates(*to_check):
			break

		sightline += 1
		if tree_map.get_at(*to_check) >= tree_map.get_at(x, y):
			break

	return sightline

def get_scenic_score(tree_map: TreeMap, x: int, y: int) -> int:
	return (
		get_sightline_from(tree_map, x, y, "north")
		* get_sightline_from(tree_map, x, y, "south")
		* get_sightline_from(tree_map, x, y, "west")
		* get_sightline_from(tree_map, x, y, "east")
	)

def part1(tree_map: TreeMap) -> int:
	return len(
		set(
			get_trees_visible_from(tree_map, "north")
		).union(
			get_trees_visible_from(tree_map, "south")
		).union(
			get_trees_visible_from(tree_map, "west")
		).union(
			get_trees_visible_from(tree_map, "east")
		)
	)

def part2(tree_map: TreeGrid) -> int:
	return max(
		get_scenic_score(tree_map, x, y)
		for _tree_height, x, y in tree_map.walk()
	)


#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# @Time    : 2017/4/1 18:32
# @Author  : Carl
# @Site    :
# @File    : 136-GIL&&muitlthreading.py
# @Software: PyCharm Community Edition
#
#
#====================Import Modules==================
import threading
import time

#====================================================
def addNum():
    global num  # 在每个线程中都获取这个全局变量
    print('--get num:', num)
    time.sleep(1)
    lock.acquire()
    num -= 1  # 对此公共变量进行-1操作
    lock.release()
    print("%s"%num)

lock=threading.Lock()
num = 100  # 设定一个共享变量
thread_list = []
for i in range(100):
    t = threading.Thread(target=addNum)
    t.start()
    thread_list.append(t)

for t in thread_list:  # 等待所有线程执行完毕
    t.join()

print('final num:', num)


from __future__ import division
from socket import socket, AF_INET, SOCK_STREAM
from time import time
from select import select

from struct import pack, unpack

from threading import Lock

RQT_GET = 0x00
RQT_ASSIGN = 0x01
RQT_DELETE = 0x02

def REQ_to_bytes(request, tablespace, key, value):
    return pack('!BBLL', request, tablespace, len(key), len(value)) + key + value

def GET_to_bytes(tablespace, key):
    return REQ_to_bytes(RQT_GET, tablespace, key, '')

def ASSIGN_to_bytes(tablespace, key, value):
    return REQ_to_bytes(RQT_ASSIGN, tablespace, key, value)

def DELETE_to_bytes(tablespace, key):
    return REQ_to_bytes(RQT_DELETE, tablespace, key, '')

def scan_frame(frame):
    """
    Scans a Vanad server reply frame, and asserts if this could be a frame.

    If this cannot be a valid frame, it will raise an exception of
    undefined type and arguments.

    Will return values if this is a valid frame
    @return: tuple (int resultcode, bytearray data)
    """
        # Unzip the header. Will throw if not sufficient bytes there
    resultcode, data_len = unpack('!BL', str(frame[:5]))

        # Check if frame is OK with length, if not - throw Exception
    if len(frame) != 5 + data_len: raise Exception

        # Extract data and rest of the data
    data = frame[5:5+data_len]

    return resultcode, data

class VanadConnection(object):
    """
    Class that represents a connection to a Vanad database

    Will autoreconnect upon detecting socket lossage and repeat the query, as needed
    Will behave smoothly even if user orders a query in the middle of database's
    restart.

    Will connect only if there'a need to do so.

    If database is reliably down for longer periods of time, this WILL HANG!
    """

    def __init__(self, address, connect_timeout=4, txrx_timeout=4, eo_timeout=8):
        """
        Connect to a remote database.

        @type address: tuple of (str address, int port)
        @param address: SOCK_STREAM-compatible address of target database

        @type connect_timeout: int
        @param connect_timeout: timeout in seconds that will be used during
                                connecting to database

        @type txrx_timeout: int
        @param txrx_timeout: timeout for send/recv operations

        @type eo_timeout: dont-care
        @param eo_timeout: supported for legacy applications. dont-care.
        """
        self.lock = Lock()
        self.connect_timeout = connect_timeout
        self.txrx_timeout = txrx_timeout

        self.remote_address = address
        self.connected = False
        self.last_activity = 0   # an int with time() of last activity
        self.socket = None      # a socket.socket object will be here

        self.default_tablespace = 0        # default tablespace

    def __shut_sock(self):
        try:
            self.socket.close()
        except:
            pass
        self.socket = None
        self.connected = False

    def __ensure_connected(self, force_reconnect=False):
        """PRIVATE METHOD.
        Ensured that connection to database is on.
        If it isn't, it will make it so.
        If it can't be done, it will hang."""

        if time() - self.last_activity > 3:     # Connection down
            self.__shut_sock()

        while (not self.connected) or force_reconnect:    # Assure that you are connected
            # we don't close our sockets here, because closing a socket might take a while
            # we just plainly discard it. Mail me if you got a better idea.
            self.socket = socket(AF_INET, SOCK_STREAM)
            self.socket.settimeout(self.connect_timeout)
            try:
                self.socket.connect(self.remote_address)
            except:     # timeout or active denial
                try:
                    self.socket.close()
                except:
                    pass
                self.socket = None
            else:
                self.connected = True
                self.last_activity = time()
                self.socket.settimeout(self.txrx_timeout)

    def set_default_tablespace(self, id):
        """
        Sets a new tablespace as default one

        @type id: int in (0..255)
        @param id: number of new default tablespace
        """
        self.default_tablespace = id

    def __transact(self, to_send):
        """
        Transacts with the database. Will return value that got returned.
        Will raise exception if it could not be completed, and should be retried.
        """

        # Send now
        self.socket.sendall(to_send)

        # Now, wait for reception
        recvdata = bytearray()
        while True:
            k = self.socket.recv(1024)
            if len(k) == 0: raise Exception     # server closed connection
            recvdata.extend(k)
            try:
                result, value = scan_frame(recvdata)
            except:     # Frame not ready yet
                pass
            else:       # Frame completed
                break
        self.last_activity = time()     # Note the activity
        if result == 0x01: return None  # Not found for GET's
        if len(value) == 0: return None # None and empty string have same meaning
        return value

    def get(self, key, tablespace=None):
        """
        Fetches a record from database.

        @type key: str
        @param key: Key to fetch with

        @type tablespace: int in (0..255), or None
        @param tablespace: number of tablespace to fetch from. If None,
                           default tablespace will be used
        """

        self.lock.acquire()

        if tablespace == None: tablespace = self.default_tablespace

        self.__ensure_connected()
        while True:
            try:
                f = self.__transact(GET_to_bytes(tablespace, key))
                self.lock.release()
                return f
            except:
                self.__ensure_connected(force_reconnect=True)

    def assign(self, key, value, tablespace=None):
        """
        Writes a record to database

        @type key: str
        @param key: Key to write

        @type value: str
        @param value: Value to write

        @type tablespace: int in (0..255), or None
        @param tablespace: number of tablespace to write to. If None,
                           default tablespace will be used
        """
        self.lock.acquire()
        if tablespace == None: tablespace = self.default_tablespace

        self.__ensure_connected()
        while True:
            try:
                self.__transact(ASSIGN_to_bytes(tablespace, key, value))
                self.lock.release()
                return
            except:
                self.__ensure_connected(force_reconnect=True)

    def delete(self, key, tablespace=None):
        """
        Deletes a record from database

        @type key: str
        @param key: Key to delete

        @type tablespace: int in (0..255), or None
        @param tablespace: number of tablespace to write to. If None,
                           default tablespace will be used
        """
        self.lock.acquire()
        if tablespace == None: tablespace = self.default_tablespace

        self.__ensure_connected()
        while True:
            try:
                self.__transact(DELETE_to_bytes(tablespace, key))
                self.lock.release()
                return
            except:
                self.__ensure_connected(force_reconnect=True)


#!/usr/bin/python3
if __name__ == "__main__":
    from sys import argv
    length = len(argv) - 1
    a = ':'
    if length == 0:
        a = 's.'
    if length > 1:
        a = 's:'
    print("{} argument{}".format(length, a))
    for i in range(1, length + 1):
        print("{}: {}".format(i, argv[i]))