import pygame, sys
from objs import *

import thread

class BaseWidget:
    def __init__(self, pos, size, container = None, data = None):
        self.initwidget(pos, size, container, data)
    def initwidget(self, pos, size, container = None, data = None):
        self.data = data
        self.container = container
        self.pos = pos
        self.size = size
        self.image = pygame.Surface(self.size).convert()
        self.visible = True
        self.oldvisible = self.visible

        self.selected = False
        self.oldkeys = []
        self.oldmousepos = (0,0)
        self.oldmousebut = (False,False,False)
        self.oldhover = False
        self.keys = []
        self.mousepos = (0,0)
        self.mousebut = (False,False,False)
        self.hover = False
        self.disabled = False
        self.redraw = True
        self.comment = ""
        self.setup()

    def setup(self):
        pass
    def update(self, keyboard, mousepos, mousebut, hover, selected, events = [], threadcount = 0):
        self.events = events
        self.keyboard = keyboard
        self.mousepos = mousepos
        self.mousebut = mousebut
        self.hover = hover
        self.selected = selected
        if not self.disabled:
    #        if self.mousebut[0] and not self.oldmousebut[0]: self.lclick()
    #        if self.mousebut[1] and not self.oldmousebut[1]: self.mclick()
    #        if self.mousebut[2] and not self.oldmousebut[2]: self.rclick()
    #        if not self.mousebut[0] and self.oldmousebut[0]: self.lrelease()
    #        if not self.mousebut[1] and self.oldmousebut[1]: self.mrelease()
    #        if not self.mousebut[2] and self.oldmousebut[2]: self.rrelease()
            for event in self.events:
                if event.type == pygame.MOUSEBUTTONDOWN:
                    if event.button == 1: self.lclick()
                    elif event.button == 2: self.mclick()
                    elif event.button == 3: self.rclick()
                    elif event.button == 4: self.mwheelup()
                    elif event.button == 5: self.mwheeldown()
                elif event.type == pygame.MOUSEBUTTONUP:
                    if event.button == 1: self.lrelease()
                    elif event.button == 2: self.mrelease()
                    elif event.button == 3: self.rrelease()
                self.handleevent(event)
            if self.hover and not self.oldhover: self.mouseover()
            elif not self.hover and self.oldhover: self.mouseout()
            if not self.mousepos[0] == self.oldmousepos[0] or not self.mousepos[1] == self.oldmousepos[1]: self.mousemove()
            self.always()

            self.oldkeyboard = self.keyboard
            self.oldmousepos = self.mousepos
            self.oldmousebut = self.mousebut
            self.oldhover = self.hover
            self.oldvisible = self.visible
            self.oldselected = self.selected

        #threadcount -= 1

        return self.image
    def enable(self):
        self.oldkeyboard = self.keyboard
        self.oldmousepos = self.mousepos
        self.oldmousebut = self.mousebut
        self.oldhover = self.hover
        self.oldvisible = self.visible
        self.oldselected = self.selected
        self.disabled = False
        self.update(self.oldkeyboard, self.oldmousepos, self.oldmousebut, self.oldhover, self.oldselected, [])
    def handleevent(self, event):
        pass
    def lclick(self):
        pass
    def mclick(self):
        pass
    def rclick(self):
        pass
    def lrelease(self):
        pass
    def mrelease(self):
        pass
    def rrelease(self):
        pass
    def mwheelup(self):
        pass
    def mwheeldown(self):
        pass
    def mousemove(self):
        pass
    def mouseover(self):
        pass
    def mouseout(self):
        pass
    def always(self):
        pass
    def menuaction(self, selection):
        pass
    def resize(self, pos, size):
        self.pos = pos
        if size[0] < 1: size[0] = 1
        if size[1] < 1: size[1] = 1
        self.size = size
        self.image = pygame.Surface(self.size)
        self.draw()
    def draw(self):
        self.image.fill((0,0,0))

        self.redraw = True
        return self.image

class MainWindow:
    def __init__(self, data):
        self.resources = None # Insert resource object here
        self.container = None # Insert widget container here
    def setupwindow(self):
        self.menu = WindowMenu(self)

        self.comment = ["", Vector(0,0), 0] #[Comment, Position, Hover time]
        self.oldcomment = deepcopy(self.comment)
        self.commenttimestart = 1000
        self.commenttimeend = 4000

        #self.updaterects = []
        self.fullredraw = True
    def update(self, screen, keyboard, mousepos, mousebut, events = []):
        #self.updaterects = []
        menuvisible = self.menu.visible
        self.mousepos = mousepos
        if self.menu.visible:
            hover = pygame.Rect(self.menu.pos, self.menu.size).collidepoint(mousepos)
            self.menu.update(keyboard, mousepos, mousebut, hover, True, events)
            mousebut = (False,False,False)

        self.container.update(keyboard, mousepos, mousebut, not menuvisible, not menuvisible, events)
        if self.container.redraw: screen.blit(self.container.image, (0,0))

        if self.menu.visible:
            screen.blit(self.menu.image, self.menu.pos)

        if not self.comment[0] == "":
            if not self.comment[0] == self.oldcomment[0]: self.comment[2] = pygame.time.get_ticks()
            if pygame.time.get_ticks() > self.comment[2] + self.commenttimestart and pygame.time.get_ticks() < self.comment[2] + self.commenttimeend:
                #self.updaterects.append(pygame.Rect(pos-Vector(1,1), Vector(fontrender.get_size())+Vector(2,2)))
                font = pygame.font.Font(pygame.font.get_default_font(), 15)
                fontrender = font.render(self.comment[0], True, (0,0,0))
                pos = Vector(min(self.comment[1][0], self.container.size.x-fontrender.get_width()),self.comment[1][1]-fontrender.get_height())
                #pygame.draw.rect(screen, (0,0,0,100), pygame.Rect(pos+Vector(3,3), fontrender.get_size()))
                pygame.draw.rect(screen, (255,255,180), pygame.Rect(pos, fontrender.get_size()))
                pygame.draw.rect(screen, (0,0,0), pygame.Rect(pos-Vector(1,1), Vector(fontrender.get_size())+Vector(2,2)), 1)
                screen.blit(fontrender, pos)
                #self.updaterects.append(pygame.Rect(pos-Vector(1,1), Vector(fontrender.get_size())+Vector(2,2)))
        self.oldcomment = deepcopy(self.comment)

        self.fullredraw = False

class WidgetContainer(BaseWidget):
    def __init__(self, pos, size, widgets, order, mainwindow):
        self.setupcontainer(pos, size, mainwindow)
        self.widgets = widgets
        self.order = order
    def setupcontainer(self, pos, size, mainwindow, container = None, data = None):
        self.window = mainwindow
        self.widgetselected = 0
        self.initwidget(pos, size, container, data)
        self.drawbase()
    def setup(self):
        self.image = pygame.Surface(self.size)
        self.mousemask = self.image.copy()
        self.mousemask.fill((0,0,0))
        self.blank = self.mousemask
        #print "test"
    def resize(self, size, pos):
        self.size = size
        self.pos = pos
        self.setup()
        self.organise()
    def lclick(self):
        self.setSelected()
    def mclick(self):
        self.setSelected()
    def rclick(self):
        self.setSelected()
    def setSelected(self):
        self.widgetselected = 0
        mpos = Vector(self.mousepos-self.pos)
        if mpos.x > 0 and mpos.x < self.mousemask.get_width() and mpos.y > 0 and mpos.y < self.mousemask.get_height():
            self.widgetselected = (self.mousemask.get_at(mpos)[0])
    def organise(self):
        pass
    def always(self):
        if len(self.events) > 0:
            self.mousemask = self.blank.copy()

        for i in range(len(self.order)):
            if self.widgets[self.order[i]].visible: pygame.draw.rect(self.mousemask, (i+1,0,0), pygame.Rect(self.widgets[self.order[i]].pos, self.widgets[self.order[i]].size))

        threadcount = 0
        for i in range(len(self.order)):
            hover = False
            if self.mousepos[0]- self.pos[0] > 0 and self.mousepos[0]- self.pos[0] < self.mousemask.get_width() and self.mousepos[1] - self.pos[1] > 0 and self.mousepos[1] - self.pos[1] < self.mousemask.get_height():
                hover = (self.mousemask.get_at(self.mousepos-self.pos)[0] == i+1) and self.hover
                if self.mousemask.get_at(self.mousepos-self.pos)[0] == 0: self.window.comment[0] = ""

            if hover:
                self.window.comment[0] = self.widgets[self.order[i]].comment
                self.window.comment[1] = self.window.mousepos#; print self.widgets[self.order[i]].comment
            if self.mousebut[0]or self.mousebut[1] or self.mousebut[2]: self.window.comment[0] = ""

            selected = False
            if self.widgetselected == i+1:
                selected = self.selected
            self.widgets[self.order[i]].update(self.keyboard, self.mousepos-self.pos, self.mousebut, hover, selected, self.events)
            #threadcount += 1
            #thread.start_new_thread(self.widgets[self.order[i]].update, (self.keyboard, self.mousepos-self.pos, self.mousebut, hover, selected, self.events, threadcount))
            #pygame.time.wait(200)
            #print threadcount
        #while threadcount > 0: print threadcount
        self.draw()
    def draw(self):
        #self.image.fill((0,0,0))
        #self.image.blit(canvas, canvaspos)
        self.drawwidgets()

        #self.redraw = True
    def drawwidgets(self):
        if self.window.fullredraw: self.drawbase()

        for widget in self.order:
            if self.widgets[widget].visible and (self.widgets[widget].redraw or self.window.fullredraw):
                self.image.blit(self.widgets[widget].image, self.widgets[widget].pos)
                #self.window.updaterects.append(pygame.Rect(self.widgets[widget].pos, self.widgets[widget].image.get_size()))
                #self.window.updaterects.append(pygame.Rect(self.widgets[widget].pos, self.widgets[widget].image.get_size()))
                self.redraw = self.redraw or self.widgets[widget].redraw #Redraw if anything changes in any widget
                self.widgets[widget].redraw = False
    def drawbase(self):
        self.image.fill((0,0,0))

#class QuestionDialogWindow(WidgetContainer):
#    def __init__(self, question, type = "yesno", title = "Question", action = sys.exit):
#        self.question = question
#        self.action = action
#        if type == "yesno":
#            self.widgets = {'YesButton':Button}

#class QuestionDialogYesButton

class DragBar(BaseWidget):
    def setup(self):
        self.dragging = False
        self.image.fill((0,100,255))
    def lclick(self):
        if self.hover:
            self.dragging = True
            self.dragmouse = self.container.window.mousepos
            self.dragpos = self.container.pos
    def mousemove(self):
        if self.dragging:
            self.container.pos = Vector(self.dragpos + self.container.window.mousepos - self.dragmouse)
            self.container.window.fullredraw = True
    def lrelease(self):
        self.dragging = False
    def draw(self):
        pass

class Button(BaseWidget):
    def setup(self):
        self.buttonsetup()
    def buttonsetup(self, label = "Button"):
        self.label = label
        self.texbutup = self.container.window.resources['buttonup']
        self.texbutdown = self.container.window.resources['buttondown']
        self.updatefont()
        self.update([], self.oldmousepos, self.oldmousebut, self.oldhover, False)
        self.draw()
        return self
    def changelabel(self, label):
        self.label = label
        self.updatefont()
        self.draw()
    def updatefont(self):
        self.font = pygame.font.Font(pygame.font.get_default_font(), self.size[1])
        twidth = self.font.render(self.label, True, (0,0,255)).get_width()
        if twidth > self.size[0]: self.font = pygame.font.Font(pygame.font.get_default_font(), int(float(self.size[0]) / float(twidth) * float(self.size[1])))
    def lclick(self):
        self.draw()
    def lrelease(self):
        self.draw()
    def mouseover(self):
        self.draw()
    def mouseout(self):
        self.draw()
    def draw(self):
        self.drawbutton()
    def drawbutton(self):
        if self.mousebut[0] and self.hover and self.selected:
            #self.image.fill([0,0,0,0])
            self.image.blit(pygame.transform.smoothscale(self.texbutdown, (self.size[0], self.size[1])), (0,0))
        else:
            #self.image.fill([0,0,255])
            self.image.blit(pygame.transform.smoothscale(self.texbutup, (self.size[0], self.size[1])), (0,0))
        if self.hover and (not self.mousebut[0] or self.selected):
            colour = (255,0,0)
        else:
            colour = (200,0,0)
        text = self.font.render(self.label, True, colour)
        self.image.blit(text, (0,self.size[1]/2 - text.get_height()/2))

        self.redraw = True
        return self.image

class Label(BaseWidget):
    def __init__(self, pos, size, label, colour = (0,0,0), container = None, data = None):
        self.colour = colour
        self.initwidget(pos, size, container, data)
        self.labelsetup(label)
    def setup(self):
        self.labelsetup()
    def labelsetup(self, label = "Button"):
        self.image = pygame.Surface(self.size).convert_alpha()
        self.label = label
        self.updatefont()
        self.draw()
    def changelabel(self, label):
        self.label = label
        self.updatefont()
        self.draw()
    def updatefont(self):
        self.font = pygame.font.Font(pygame.font.get_default_font(), self.size[1])
        twidth = self.font.render(self.label, True, (0,0,255)).get_width()
        if twidth > self.size[0]: self.font = pygame.font.Font(pygame.font.get_default_font(), int(float(self.size[0]) / float(twidth) * float(self.size[1])))
    def update(self, keyboard, mousepos, mousebut, hover, selected, events = [], threadcount=0):
        threadcount -= 1
    def draw(self):
        self.image.fill([0,0,0,0])
        text = self.font.render(self.label, True, self.colour)
        self.image.blit(text, (0,self.size[1]/2 - text.get_height()/2))

        self.redraw = True
        return self.image

class CheckBox(BaseWidget):
    def setup(self):
        self.checkboxsetup()
    def checkboxsetup(self, label = "Check Box", fontsize = 15):
        self.image = pygame.Surface(self.size).convert_alpha()
        self.label = label
        self.texchkon = self.container.window.resources['checkboxon']
        self.texchkoff = self.container.window.resources['checkboxoff']
        self.fontsize = fontsize
        self.updatefont()
        self.update([], self.oldmousepos, self.oldmousebut, self.oldhover, False)
        self.checked = False
        self.draw()
        return self
    def changelabel(self, label):
        self.label = label
        self.updatefont()
        self.draw()
    def updatefont(self):
        self.font = pygame.font.Font(pygame.font.get_default_font(), self.fontsize)
        twidth = self.font.render(self.label, True, (0,0,255)).get_width()
        if twidth > self.size[0]: self.font = pygame.font.Font(pygame.font.get_default_font(), float(self.size[0]) / float(twidth) * float(self.fontsize))
    def lclick(self):
        self.draw()
    def lrelease(self):
        if self.hover and self.selected:
            self.checked = not self.checked
            self.changed()
        self.draw()
    def mouseover(self):
        self.draw()
    def mouseout(self):
        self.draw()
    def changed(self):
        pass
    def draw(self):
        self.image.fill([0,0,0, 0])
        if self.checked:
            self.image.blit(pygame.transform.smoothscale(self.texchkon, (self.size[1], self.size[1])), (0,0))
        else:
            self.image.blit(pygame.transform.smoothscale(self.texchkoff, (self.size[1], self.size[1])), (0,0))
        if self.hover and (not self.mousebut[0] or self.selected):
            colour = (255,0,0,0)
        else:
            colour = (200,0,0,0)
        text = self.font.render(self.label, True, colour)
        self.image.blit(text, (self.size[1],self.size[1]/2 - text.get_height()/2))

        self.redraw = True
        self.container.window.fullredraw = True
        return self.image

class DropDownMenu(BaseWidget):
    def setup(self):
        self.menusetup()
    def menusetup(self, pos=(0,0), items=[("Item", "item")], fontsize = 12):
        self.items = items
        self.pos = pos
        self.fontsize = fontsize
        self.font = pygame.font.Font(pygame.font.get_default_font(), self.fontsize)
        maxwidth = 0
        for item in self.items:
            twidth = self.font.render(item[0], True, (0,0,0)).get_width()
            if twidth > maxwidth: maxwidth = twidth
        self.size = (maxwidth, self.fontsize*len(self.items))
        self.image = pygame.Surface(self.size)
    def lrelease(self):
        self.visible = False
        if self.hover and self.oldvisible:
            self.action(int(self.mousepos[1] - self.pos[1]) / self.fontsize)
    def mrelease(self):
        self.visible = False
        if self.hover and self.oldvisible:
            self.action(int(self.mousepos[1] - self.pos[1]) / self.fontsize)
    def rrelease(self):
        self.visible = False
        if self.hover and self.oldvisible:
            self.action(int(self.mousepos[1] - self.pos[1]) / self.fontsize)
    def mousemove(self):
        if self.oldvisible:
            self.draw()
    def action(self, selection):
        pass
    def draw(self):
        self.image.fill((230,230,230))
        if self.hover: pygame.draw.rect(self.image, (255,200,0), pygame.Rect((0,self.fontsize*(int(self.mousepos[1] - self.pos[1]) / self.fontsize)),(self.size[0], self.fontsize)))
        pygame.draw.rect(self.image, (0,0,0), pygame.Rect((0,0),self.size), 1)
        for i in range(len(self.items)):
            self.image.blit(self.font.render(self.items[i][0], True, (0,0,0)), (0,self.fontsize*i))

        self.redraw = True
        return self.image

class WindowMenu(DropDownMenu):
    def __init__(self, window):
        self.initwidget(Vector(0,0), Vector(1,1), None, None)
        self.visible = False
        self.oldvisible = self.visible
        self.window = window
    def showmenu(self, items, pos, caller, fontsize = 20):
        self.menusetup(Vector(pos), items, fontsize)
        if self.pos[0] + self.size[0] > self.window.container.size[0]: self.pos[0] = self.window.container.size[0] - self.size[0]
        if self.pos[1] + self.size[1] > self.window.container.size[1]: self.pos[1] = self.window.container.size[1] - self.size[1]
        self.caller = caller
        self.visible = True
        self.draw()
    def setup(self):
        pass
    def action(self, selection):
        self.caller.menuaction(self.items[selection][1])

class ScrollBar(BaseWidget):
    def scrollbarsetup(self, vertical=False, range=(0,100), value=0, griplength = 100):
        self.vertical = vertical
        self.range = range
        self.griplength = griplength
        self.texbarhori = self.container.window.resources['scrollbarhori']
        self.texbarvert = self.container.window.resources['scrollbarvert']
        self.value = value
        self.drag = False
        self.dragpos = 0
        self.updatefont()
        self.draw()
    def resize(self, pos, size):
        self.pos = pos
        if size[0] < 1: size[0] = 1
        if size[1] < 1: size[1] = 1
        self.size = size
        self.image = pygame.Surface(self.size)
        self.updatefont()
        self.draw()
    def updatefont(self):
        if self.vertical:
            self.font = pygame.font.Font(pygame.font.get_default_font(), self.size.x)
        else:
            self.font = pygame.font.Font(pygame.font.get_default_font(), self.size.y)
    def lclick(self):
        if self.hover:
            self.drag = True
            if self.vertical:
                self.dragpos = (float(self.mousepos.y) / (self.size.y - self.griplength) * self.range[1] + self.range[0])
            else:
                self.dragpos = (float(self.mousepos.x) / (self.size.x - self.griplength) * self.range[1] + self.range[0])
    def lrelease(self):
        self.drag = False
        self.draw()
    def mousemove(self):
        if self.drag:
            if self.vertical:
                off = (float(self.mousepos.y) / (self.size.y - self.griplength) * self.range[1] + self.range[0]) - self.dragpos
                self.value += off
                self.dragpos = (float(self.mousepos.y) / (self.size.y - self.griplength) * self.range[1] + self.range[0])
            else:
                off = (float(self.mousepos.x) / (self.size.x - self.griplength) * self.range[1] + self.range[0]) - self.dragpos
                self.value += off
                self.dragpos = (float(self.mousepos.x) / (self.size.x - self.griplength) * self.range[1] + self.range[0])
            if off != 0: self.scroll()
            self.draw()
    def scroll(self):
        pass
    def scrollto(self, value):
        self.value = value
        self.draw()
    def draw(self):
        self.image.fill((30,30,50))
        if self.vertical:
            sliderpos = float(self.value - self.range[0]) / (self.range[1] - self.range[0]) * (self.size.y - self.griplength)
            self.image.blit(pygame.transform.scale(self.texbarvert, (self.size[0], self.griplength)), (0, sliderpos))
            fontrender = self.font.render(str(int(self.value)), True, (255,255,255))
            fontrender = pygame.transform.rotate(fontrender, -90)
            self.image.blit(fontrender, (0, sliderpos + self.griplength / 2 - fontrender.get_height() / 2))
        else:
            sliderpos = float(self.value - self.range[0]) / (self.range[1] - self.range[0]) * (self.size.x - self.griplength)
            self.image.blit(pygame.transform.scale(self.texbarhori, (self.griplength, self.size[1])), (sliderpos, 0))
            fontrender = self.font.render(str(int(self.value)), True, (255,255,255))
            self.image.blit(fontrender, (sliderpos + self.griplength / 2 - fontrender.get_width() / 2, 0))

        self.redraw = True

class TextBox(BaseWidget):
    def setup(self):
        self.textboxsetup()
    def textboxsetup(self, text = ""):
        try:
            pygame.scrap.init()
            pygame.scrap.set_mode(pygame.SCRAP_CLIPBOARD)
        except:
            pass
        self.text = text
        self.origtext = text
        self.cursorpos = 0
        self.scroll = 0
        self.updatefont()
        self.editing = False
        self.keyrange = (32,126)
        self.draw()
    def changetext(self, text = ""):
        if not self.editing:
            self.text = text
            self.draw()
    def updatefont(self):
        self.font = pygame.font.Font(pygame.font.get_default_font(), self.size.y)
    def getcursorpos(self, x):
        if len(self.text) > 0:
            for i in range(len(self.text)+1):
                cursorpos = i
                if cursorpos < len(self.text):
                    textwidth = self.font.render(self.text[:cursorpos], True, (0,0,0)).get_width()
                    charwidth = self.font.render(self.text[cursorpos], True, (0,0,0)).get_width()
                    if textwidth + charwidth / 2 > x + self.scroll:
                        break
        else:
            cursorpos = 0
        return cursorpos
    def lclick(self):
        if self.hover:
            if not self.editing: self.origtext = self.text
            self.editing = True
            self.cursorpos = self.getcursorpos(self.mousepos.x - self.pos.x)
            self.setscroll()
        else:
            if self.editing: self.validate()
            self.editing = False
        self.draw()
    def mclick(self):
        if self.hover:
            if not self.editing: self.origtext = self.text
            self.editing = True
            self.cursorpos = self.getcursorpos(self.mousepos.x - self.pos.x)
            clip = pygame.scrap.get(pygame.SCRAP_TEXT)
            if clip: self.text = self.text[:self.cursorpos] + clip + self.text[self.cursorpos:]
            self.setscroll()
        else:
            if self.editing: self.validate()
            self.editing = False
        self.draw()
    def rclick(self):
        if self.hover:
            if not self.editing: self.origtext = self.text
            self.editing = True
            self.cursorpos = self.getcursorpos(self.mousepos.x - self.pos.x)
            self.setscroll()
        else:
            if self.editing: self.validate()
            self.editing = False
        self.draw()
    def always(self):
        # 32-126 are keyboard keys
        if self.editing:
            for event in self.events:
                if event.type == pygame.KEYDOWN:
                    if event.key >= self.keyrange[0] and event.key <= self.keyrange[1]:
                        self.text = self.text[:self.cursorpos] + event.unicode + self.text[self.cursorpos:]
                        self.cursorpos += 1
                    elif event.key == pygame.K_BACKSPACE:
                        self.text = self.text[:self.cursorpos-1] + self.text[self.cursorpos:]
                        self.cursorpos -= 1
                    elif event.key == pygame.K_DELETE:
                        self.text = self.text[:self.cursorpos] + self.text[self.cursorpos + 1:]
                    elif event.key == pygame.K_RIGHT:
                        self.cursorpos += 1
                    elif event.key == pygame.K_LEFT:
                        self.cursorpos -= 1
                    elif event.key == pygame.K_END:
                        self.cursorpos = len(self.text)
                    elif event.key == pygame.K_HOME:
                        self.cursorpos = 0
                    if self.cursorpos < 0: self.cursorpos = 0
                    if self.cursorpos > len(self.text): self.cursorpos = len(self.text)
                    self.edited()
                    self.setscroll()
                    #print self.text, self.cursorpos
                    self.draw()
    def setscroll(self):
        cursorx = self.font.render(self.text[:self.cursorpos], True, (0,0,0)).get_width()
        if self.scroll < cursorx - self.size.x:
            self.scroll = cursorx - self.size.x
        elif self.scroll > cursorx:
            self.scroll = cursorx
        if self.scroll < 0: self.scroll = 0
    def edited(self):
        pass
    def validate(self):
        pass
    def draw(self):
        self.image.fill((255,255,255))
        if self.editing:
            cursorx = self.font.render(self.text[:self.cursorpos], True, (0,0,0)).get_width()
            pygame.draw.line(self.image, (255,0,0), (cursorx-self.scroll, 0), (cursorx-self.scroll, self.size.y), 3)
        self.image.blit(self.font.render(self.text, True, (0,0,0)), (-self.scroll,0))

        self.redraw = True

class NumberScrollBox(TextBox):
    def textboxsetup(self, text = ""):
        self.text = text
        self.origtext = text
        self.cursorpos = 0
        self.scroll = 0
        self.updatefont()
        self.editing = False
        self.dragging = False
        self.clickmousepos = self.mousepos
        self.keyrange = (32,126)
        self.draw()
    def lclick(self):
        if self.hover and not self.editing:
            self.clickmousepos = self.mousepos
        elif self.hover and self.editing:
            self.cursorpos = self.getcursorpos(self.mousepos.x - self.pos.x)
            self.setscroll()
        else:
            if self.editing: self.validate()
            self.editing = False
        self.draw()
    def lrelease(self):
        #print self.clickmousepos, self.mousepos, self.hover, str(self.clickmousepos) == str(self.mousepos)
        if self.hover and str(self.clickmousepos) == str(self.mousepos):
            self.editing = True
            self.cursorpos = self.getcursorpos(self.mousepos.x - self.pos.x)
            self.setscroll()
        elif not self.hover:
            #if self.editing:
            self.validate()
            self.editing = False
        self.draw()
    def scrolled(self, offset):
        self.edited()
    def validate(self):
        try:
            self.text = str(float(self.text))
        except:
            self.text = self.origtext
        self.draw()
    def mousemove(self):
        if self.mousebut[0] and self.selected and not self.editing:
            self.validate()
            self.text = str(float(self.text) + (self.oldmousepos.y - self.mousepos.y))
            self.origtext = self.text
            self.scrolled(self.oldmousepos.y - self.mousepos.y)
            self.draw()

class MenuBar(BaseWidget):
    def setup(self):
        self.menusetup([("File", [("Quit", "quit")])])
        self.texback = self.container.window.resources['textbox']
        self.draw()
    def menusetup(self, menu):
        self.menu = menu
        self.updatefont()
    def updatefont(self):
        self.font = pygame.font.Font(pygame.font.get_default_font(), self.size[1])
        twidth = ((self.size[0]/(len(self.menu)))) #self.font.render(self.list[self.selected], True, (0,0,255)).get_width()
        if twidth > self.size[0]: self.font = pygame.font.Font(pygame.font.get_default_font(), float(self.size[0]) / float(twidth) * float(self.size[1]))
    def resize(self, pos, size):
        self.pos = pos
        if size[0] < 1: size[0] = 1
        if size[1] < 1: size[1] = 1
        self.size = size
        self.image = pygame.Surface(self.size)
        self.draw()
    def lrelease(self):
        if self.hover:
            self.selected = int(float(self.mousepos.x - self.pos.x) / self.size.x * len(self.menu))
            menupos = (self.size.x / len(self.menu) * self.selected, self.size.y)
            self.container.window.menu.showmenu(self.menu[self.selected][1], menupos, self, self.size.y)
    def mouseover(self):
        self.draw()
    def mouseout(self):
        self.draw()
    def menuaction(self, selected):
        if selected == "quit": sys.exit()
    def draw(self):
        self.image.blit(pygame.transform.scale(self.texback, (self.size[0], self.size[1])), (0,0))
        if self.hover and (not self.mousebut[0] or self.selected):
            colour = (255,0,0)
        else:
            colour = (200,0,0)
        for i in range(len(self.menu)):
            text = self.font.render(self.menu[i][0], True, colour)
            self.image.blit(text, (i*((self.size[0]/(len(self.menu)))),self.size[1]/2 - text.get_height()/2))

        self.redraw = True


"""Solution to day 23 of Advent of Code"""

from collections import namedtuple, defaultdict
from enum import Enum
from get_input import get_input
from itertools import product
from queue import PriorityQueue
import os

class AmphException(Exception):
    pass

class State(Enum):
    START = "START"
    IN_HALLWAY = "IN_HALLWAY"
    DONE = "DONE"

class Species(Enum):
    AMBER = 1
    BRONZE = 10
    COPPER = 100
    DESERT = 1000

    @staticmethod
    def get_species(letter):
        if letter == 'A':
            return Species.AMBER
        if letter == 'B':
            return Species.BRONZE
        if letter == 'C':
            return Species.COPPER
        if letter == 'D':
            return Species.DESERT

    def get_letter(self):
        if self.name == 'AMBER':
            return 'A'
        if self.name == 'BRONZE':
            return 'B'
        if self.name == 'COPPER':
            return 'C'
        if self.name == 'DESERT':
            return 'D'
        raise NotImplementedError

class Amphipod(namedtuple('Amphipod',
                          ['position', 'species', 'state', 'goal_room'])):
    def __lt__(self, other):
        return (self.species, self.goal_room) < \
               (other.species, other.goal_room)

    def in_room(self):
        return self.position.real > 1 and self.position.imag == self.goal_room

def move_to_room(amp, board):
    position = amp.position
    for row in range(2, 6):
        point = complex(row, amp.goal_room)
        if point not in board.open_spaces:
            break
        if point in board.amps and not board.amps[point].in_room():
            raise AmphException("Room full")
    horiz = 1j if amp.goal_room > position.imag else -1j
    used = 0
    while position.imag != amp.goal_room:
        position += horiz
        used += amp.species.value
        if position in board.amps:
            raise AmphException("No path")
    while board.is_open(position + 1):
        position += 1
        used += amp.species.value
    if position not in board.open_spaces:
        raise NotImplementedError
    return (used, Amphipod(
        position, amp.species, State.DONE, amp.goal_room))

def move_to_hallway(amp, board):
    used, position = 0, amp.position
    # Move to hallway
    while position.real > 1:
        position -= 1
        used += amp.species.value
        if not board.is_open(position):
            # Blocked in
            return
    # move left and right
    queue = [(used, -1j, position), (used, 1j, position)]
    while queue:
        used, step, position = queue.pop()
        if not board.is_open(position):
            continue
        if board.in_hallway(position):
            yield used, Amphipod(
                position, amp.species, State.IN_HALLWAY, amp.goal_room)
        queue.append((used+amp.species.value, step, position+step))

class Board:
    def __init__(self, open_spaces):
        self.open_spaces = open_spaces
        self.room_map = defaultdict(list)
        self.hallway = set()
        for space in open_spaces:
            if space.real > 1:
                self.room_map[space.imag].append(space)
            else:
                self.hallway.add(space)
        self.hallway.difference_update(
            complex(1, rid) for rid in self.room_map.keys()
        )
        for room in self.room_map.values():
            room.sort(key=lambda p: p.real)

    def add_amps(self, amps):
        self.amps = {a.position: a for a in amps}

    def remove_amps(self):
        self.amps.clear()

    @property
    def room(self):
        rooms = {}
        for rid, room in self.room_map.items():
            rooms[rid] = []
            for depth in range(2, 5):
                if complex(depth, rid) in self.amps:
                    rooms[rid].append(self.amps[complex(depth, rid)])
        return rooms

    def is_open(self, position):
        if position not in self.open_spaces:
            return False
        return position not in self.amps

    def in_hallway(self, position):
        return position in self.hallway

    def __str__(self):
        lines = []
        for r in range(7):
            lines.append([])
            for c in range(13):
                point = complex(r, c)
                char = '#'
                if point in self.amps:
                    char = self.amps[point].species.get_letter()
                elif point in self.open_spaces:
                    char = '.'
                lines[-1].append(char)
        return '\n'.join(''.join(line) for line in lines)

def part1(lines):
    amphipods, spaces = lines[:]
    board = Board(spaces)

    room_ids = tuple(sorted(set(p.imag for p in spaces if p.real > 1)))
    assignments = dict(zip(tuple(s for s in Species), room_ids))

    state = [Amphipod(position, species, State.START, assignments[species])
             for species, position in amphipods]
    queue = PriorityQueue()
    queue.put((0, 0, tuple(state)))
    seen = set()
    while not queue.empty():
        energy, steps, state = queue.get()
        board.add_amps(state)
        if state in seen:
            continue
        seen.add(state)
        if all(amp.position.imag == amp.goal_room for amp in state):
            print(' ' * os.get_terminal_size().columns, end='\r')
            return energy
        print(energy, steps, end='\r')
        for a, amp in enumerate(state):
            if amp.state == State.DONE:
                continue
            if amp.state == State.IN_HALLWAY:
                try:
                    used, moved_amp = move_to_room(amp, board)
                except AmphException:
                    pass
                else:
                    moved_state = list(state)
                    moved_state[a] = moved_amp
                    queue.put((energy+used, steps+1, tuple(moved_state)))
            elif amp.state == State.START:
                for used, moved_amp in move_to_hallway(amp, board):
                    moved_state = list(state)
                    moved_state[a] = moved_amp
                    queue.put((energy+used, steps+1, tuple(moved_state)))
        board.remove_amps()

    raise NotImplementedError

def part2(lines):
    amphipods, spaces = lines[:]
    unfolded = list()
    for species, position in amphipods:
        if position.real > 2:
            unfolded.append((species, position+2))
        else:
            unfolded.append((species, position))
    additional = (
        (Species.DESERT, 3+3j),
        (Species.DESERT, 4+3j),
        (Species.COPPER, 3+5j),
        (Species.BRONZE, 4+5j),
        (Species.BRONZE, 3+7j),
        (Species.AMBER, 4+7j),
        (Species.AMBER, 3+9j),
        (Species.COPPER, 4+9j),
    )
    unfolded.extend(additional)
    for c, r in product((3, 5, 7, 9), (4, 5)):
        spaces.add(complex(r, c))
    return part1((unfolded, spaces))

def parse(lines):
    spaces = set()
    amphipods = []
    for r, row in enumerate(lines.splitlines()):
        for c, char in enumerate(row):
            if char == '#' or char == ' ':
                continue
            point = complex(r, c)
            spaces.add(point)
            if char in ('A', 'B', 'C', 'D'):
                amphipods.append((Species.get_species(char), point))
    return amphipods, spaces

TEST = """#############
#...........#
###B#C#B#D###
  #A#D#C#A#
  #########"""

SIMPLE = """#############
#...........#
###B#A#C#D###
  #A#B#C#D#
  #########"""

if __name__ == "__main__":
    LINES = parse(get_input(day=23, year=2021))
    test = parse(TEST)

    assert part1(parse(SIMPLE)) == 46
    assert part1(test) == 12521
    print(f"Part 1: {part1(LINES)}")

    assert part2(test) == 44169
    print(f"Part 2: {part2(LINES)}")


import vkapi
import requests
from settings import key_appid
import time

def get_weather_today(city):
    url = 'http://api.openweathermap.org/data/2.5/weather'

    try:
        data = requests.get(url, params={'lang': 'ru', 'appid': key_appid, 'q': city}).json()
    except ValueError:
        return

    result = ''

    try:
        if data['cod'] == '404':
            result = 'Город не найден.'
        else:
            weather = data['weather']
            result += weather[0]['description'].capitalize() + '\n'
            temp = data['main']
            result += 'Температура воздуха: ' + str(round(temp['temp']-273, 1)) + ' °С' + '\n'

    except KeyError:
        return

    return result

def get_weather_not_today(body):
    if len(body.split()) > 1:
        city = body.split()[0][0:-1]
        day = body.split()[1].split('.')[0]
        month = body.split()[1].split('.')[1]
        url = 'http://api.openweathermap.org/data/2.5/forecast'
    else:
        return 'Данные введены некорректно. Формат ввода: город, DD.MM'

    try:
        data = requests.get(url, params={'lang': 'ru', 'appid': key_appid, 'q': city}).json()
    except ValueError:
        return

    result = ''

    try:
        for i in data['list']:
            date = time.strptime(i['dt_txt'], "%Y-%m-%d %H:%M:%S")
            #date = i['dt_txt'].split()[0]
            i_day = date.tm_mday
            i_month = date.tm_mon

            if int(day)==i_day and int(month)==i_month:
                result += city.capitalize() + ' погода на ' + day + '.' + month + ':' + '\n'
                weather = i['weather']
                result += weather[0]['description'].capitalize() + '\n'
                temp = i['main']
                result += 'Температура воздуха: ' + str(round(temp['temp']-273, 1)) + ' °С' + '\n'
                break

            else:
                pass

        cod = data['cod']

    except KeyError:
        return

    if cod == '404':
        return 'Город не найден.'
    elif result == '':
        return 'Данные введены некорректно. Формат ввода: город, DD.MM. Прогноз погоды доступен только на 5 дней вперёд.'
    else:
        return result

def create_answer(data, token):
    user_id = data['user_id']

    if data['body'].split()[0][-1] != ',':
        message = get_weather_today(data['body'].lower())
    else:
        message = get_weather_not_today(data['body'].lower())

    vkapi.send_message(user_id, token, message)


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

"""
Created on 03.05.17 15:59

@author: pavel
"""
import logging

from gi.repository import Gtk

log = logging.getLogger(__name__)
from locale import gettext as _

class TextColumn(Gtk.TreeViewColumn):
    def __init__(self, column_name, tooltip_text, model_index_txt,
                 *args, **kwargs):
        super(TextColumn, self).__init__(*args, **kwargs)

        self.title = Gtk.Label(column_name)
        self.title.set_tooltip_text(tooltip_text)
        self.title.show()
        self.set_widget(self.title)

        renderer_text = Gtk.CellRendererText()
        self.cell_renderers = (renderer_text,)

        self.pack_start(renderer_text, expand=True)
        self.add_attribute(renderer_text, "text", model_index_txt)

        self.set_resizable(True)

    def set_attribute(self, name, model_column):
        for renderer in self.cell_renderers:
            self.add_attribute(renderer, name, model_column)

class FlagColumn(Gtk.TreeViewColumn):
    def __init__(self, column_name, tooltip_text, model_index_bool,
                 on_toggle, *args, on_toggle_data=None, **kwargs):
        super(FlagColumn, self).__init__(*args, **kwargs)

        self.title = Gtk.Label(column_name)
        self.title.set_tooltip_text(tooltip_text)
        self.title.show()
        self.set_widget(self.title)

        renderer_flag = Gtk.CellRendererToggle()
        renderer_flag.set_property("activatable", True)
        self.cell_renderers = (renderer_flag,)

        renderer_flag.connect("toggled", on_toggle, on_toggle_data)

        self.pack_start(renderer_flag, expand=False)
        self.add_attribute(renderer_flag, "active", model_index_bool)

        self.set_clickable(True)
        self.set_resizable(False)

        # self.set_sort_indicator(True)

    def set_attribute(self, name, model_column):
        for renderer in self.cell_renderers:
            self.add_attribute(renderer, name, model_column)

class ProfilesViewModel():
    PROF_ID_COL = 0  # int
    PROF_NAME_COL = 1 # str
    PROF_ACTIVE_COL = 2 # bool

    TOOLTIP_COL = 3 #str

    # id, name, active, tooltip
    LIST_STORE_COLUMN_TYPES = [int, str, bool, str]

    TOOLTIP_TEMPLATE = _("<b>{name}:</b> 127.0.0.1:{loc_port} <-> {serv_addr}:{serv_port}")

    def __init__(self, preferences, active_profiles):
        self.preferences = preferences
        self.active_profiles = active_profiles
        self.list_store = Gtk.ListStore(*self.LIST_STORE_COLUMN_TYPES)

        self.load()

    def get_model(self):
        return self.list_store

    def load(self):
        profiles = [(p.get("id"), p) for (k, p) in self.preferences.list_parameters("ssh_profiles")]
        for id_, profile in sorted(profiles):
            active = id_ in self.active_profiles
            name = profile.get("name")

            tooltip = self.TOOLTIP_TEMPLATE.format(name = name,
                                                    loc_port = profile.get("local_port"),
                                                    serv_addr = profile.get("server_addr"),
                                                    serv_port = profile.get("server_port")
                                                  )

            data = [id_, name, active, tooltip]
            self.list_store.append(data)

    def reload(self):
        self.list_store.clear()
        self.load()

    def set_value(self, path, column, value):
        iter_ = self.list_store.get_iter(path)
        self.list_store.set_value(iter_, column, value)

    def get_value(self, path, column):
        iter_ = self.list_store.get_iter(path)
        return self.list_store.get_value(iter_, column)

    def update_active(self):
        iter_ = self.list_store.get_iter_first()
        while iter_ is not None:
            profile_id = self.list_store.get_value(iter_, self.PROF_ID_COL)
            active = profile_id in self.active_profiles
            self.list_store.set_value(iter_, self.PROF_ACTIVE_COL, active)

            #go to next profile
            iter_ = self.list_store.iter_next(iter_)

    def switch_active(self, path):
        actual = self.get_value(path, self.PROF_ACTIVE_COL)
        log.debug(_("Force toggle %s"), path)

        self.set_value(path, self.PROF_ACTIVE_COL, not actual)

    def get_profile_id(self, path):
        return self.get_value(path, self.PROF_ID_COL)

class ProfilesView:
    def __init__(self, builder, preferences, active_profiles, sig_handler):
        self.sig_handler = sig_handler
        self.view = builder.get_object("ssh_profiles_view")
        self.selection = self.view.get_selection()

        self.model = ProfilesViewModel(preferences, active_profiles)

        self.view.set_model(self.model.get_model())
        self.view.set_tooltip_column(self.model.TOOLTIP_COL)

        active_column = FlagColumn(_("Active"), _("Is connected"),
                                   self.model.PROF_ACTIVE_COL,
                                   self.on_profile_activation)
        name_column = TextColumn(_("Profile name"), _("Profile name"),
                                 self.model.PROF_NAME_COL)
        self.view.append_column(active_column)
        self.view.append_column(name_column)

    def update(self):
        self.model.update_active()

    def reload(self):
        self.model.reload()

    def on_profile_activation(self, widget, path, *args):
        print(widget, path, args)
        profile_id = self.model.get_profile_id(path)

        # UI hack
        self.model.switch_active(path)

        self.sig_handler.on_profile_action(profile_id)
        return True

    def get_selected(self):
        if self.selection.count_selected_rows() >= 1:
            path = self.selection.get_selected_rows()[1][0]

            return self.model.get_profile_id(path)


import sys
sys.path.append('../')
import numpy as np
from torch.utils.data import DataLoader
import torch
import argparse
import os
from util.util import *
from train.eval import *
from util.scheduler import *
from clustering.domain_split import domain_split
from dataloader.dataloader import random_split_dataloader
from model.purity_predictor import *

if __name__ == '__main__':

    parser = argparse.ArgumentParser()

    parser.add_argument('--data-root', default='/home/arfeen/papers_code/dom_gen_aaai_2020/PACS/kfold/')
    parser.add_argument('--save-root', default='/home/arfeen/papers_code/dom_gen_aaai_2020/')
    parser.add_argument('--result-dir', default='default')
    parser.add_argument('--train', default='general')
    parser.add_argument('--data', default='PACS')
    parser.add_argument('--model', default='caffenet')
    parser.add_argument('--clustering', action='store_true')
    parser.add_argument('--clustering-method', default='Kmeans')
    parser.add_argument('--num-clustering', type=int, default=3)
    parser.add_argument('--clustering-step', type=int, default=1)
    parser.add_argument('--entropy', choices=['default', 'maximum_square'])

    parser.add_argument('--exp-num', type=int, default=0)
    parser.add_argument('--gpu', type=int, default=0)

    parser.add_argument('--num-epoch', type=int, default=30)
    parser.add_argument('--eval-step', type=int, default=1)
    parser.add_argument('--save-step', type=int, default=100)

    parser.add_argument('--batch-size', type=int, default=128)
    #parser.add_argument('--batch-size', type=int, default=16)

    parser.add_argument('--scheduler', default='step')
    parser.add_argument('--lr', type=float, default=0.001)
    parser.add_argument('--lr-step', type=int, default=24)
    parser.add_argument('--lr-decay-gamma', type=float, default=0.1)
    parser.add_argument('--momentum', type=float, default=0.9)

    parser.add_argument('--weight-decay', type=float, default=5e-4)
    parser.add_argument('--nesterov', action='store_true')
                        # default=True,help='use nesterov momentum')

    parser.add_argument('--fc-weight', type=float, default=1.0)
    parser.add_argument('--disc-weight', type=float, default=1.0)
    parser.add_argument('--entropy-weight', type=float, default=1.0)
    parser.add_argument('--grl-weight', type=float, default=1.0)
    parser.add_argument('--loss-disc-weight', action='store_true')

    parser.add_argument('--color-jitter', action='store_true')
    parser.add_argument('--min-scale', type=float, default=0.8)

    parser.add_argument('--instance-stat', action='store_true')
    parser.add_argument('--feature-fixed', action='store_true')
    parser.add_argument('--alpha-mixup', type=float, default=1.0,
                        help='mixup interpolation coefficient (default: 1)')

    args = parser.parse_args()

    path = args.save_root + args.result_dir
    if not os.path.isdir(path):
        os.makedirs(path)
        os.makedirs(path + '/models')

    with open(path+'/args.txt', 'w') as f:
        f.write(str(args))

    domain = get_domain(args.data)
    source_domain, target_domain = split_domain(domain, args.exp_num)

    device = torch.device("cuda:" + str(args.gpu) if torch.cuda.is_available() else "cpu")
    print('device is :', device)
    print("no of epoch:", args.num_epoch)

    get_domain_label, get_cluster = train_to_get_label(args.train, args.clustering)

    print('alpha_mixup is :', args.alpha_mixup)
    print("lr is:", args.lr)
    print("lr step is:", args.lr_step)
    # print('get_domain_label :', get_domain_label)
    # print('get_cluster :', get_cluster)

    source_lbl_train_ldr, source_unlbl_train_ldr, source_val,  target_test, source_lbl_train, source_lbl_train_eval\
        = random_split_dataloader(
        data=args.data, data_root=args.data_root, source_domain=source_domain, target_domain=target_domain,
        batch_size=args.batch_size, get_domain_label=get_domain_label, get_cluster=get_cluster, num_workers=4,
        color_jitter=args.color_jitter, min_scale=args.min_scale)

    # print('source_unlbl_train_ldr is :', list(source_unlbl_train_ldr)[0])
    # print('cls_lbl is :', cls_lbl)
#     num_epoch = int(args.num_iteration / len(source_train))
#     lr_step = int(args.lr_step / min([len(domain) for domain in source_train]))
#     print(num_epoch)
    num_epoch = args.num_epoch
    lr_step = args.lr_step

    disc_dim = get_disc_dim(args.train, args.clustering, len(source_domain), args.num_clustering)

    # print('no of class :',source_lbl_train_ldr.dataset.num_class)
    # model = get_model(args.model, args.train)(
        # num_classes=source_lbl_train.dataset.dataset.num_class, num_domains=disc_dim, pretrained=True)
    model = get_model(args.model, args.train)(
        num_classes=source_lbl_train_ldr.dataset.num_class, num_domains=disc_dim, pretrained=True)

    model = model.to(device)
    reg_model = Purity()
    reg_model = reg_model.to(device)
    #print('model is :', model)
    model_lr = get_model_lr(args.model, args.train, model, reg_model,  fc_weight=args.fc_weight, disc_weight=args.disc_weight)
    #print("model lr:", model_lr)
    optimizers = [get_optimizer( model_part, args.lr * alpha, args.momentum, args.weight_decay,
                                args.feature_fixed, args.nesterov, per_layer=False) for model_part, alpha in model_lr]
    #print("optimizers:", optimizers)
    reg_optimizers = reg_optimizer(reg_model, reg_lr=0.001, momentum=args.momentum, weight_decay=args.weight_decay, nesterov=args.nesterov)
    # "Regression model optimizer"

    if args.scheduler == 'inv':
        schedulers = [get_scheduler(args.scheduler)(optimizer=opt, alpha=10, beta=0.75, total_epoch=num_epoch)
                     for opt in optimizers]
    elif args.scheduler == 'step':
        schedulers = [get_scheduler(args.scheduler)(optimizer=opt, step_size=lr_step, gamma=args.lr_decay_gamma)
                     for opt in optimizers]
        reg_scheduler = get_scheduler('multistep')(optimizer=reg_optimizers, milestones=[10, 40, 80, 150, 200],
                                                   gamma=0.1)
    elif args.scheduler == 'multistep':
        schedulers = [get_scheduler(args.scheduler)(optimizer=opt, milestones =[20, 40, 100, 200], gamma=args.lr_decay_gamma)
                     for opt in optimizers]
        reg_scheduler = get_scheduler('multistep')(optimizer=reg_optimizers, milestones=[10, 40, 80, 150, 200], gamma=0.1)
        print('multistep scheduler is used')
    else:
        raise ValueError('Name of scheduler unknown %s' %args.scheduler)

    best_acc = 0.0
    test_acc = 0.0
    best_epoch = 0
    best_reg_acc = 0

    # if args.alpha_mixup > 0:
    #     lam = np.random.beta(args.alpha_mixup, args.alpha_mixup)
    # else:
    #     lam = 1
    #
    # index = torch.randperm(args.batch_size)

    for epoch in range(num_epoch):

        print('Epoch: {}/{}, Lr: {:.6f}'.format(epoch, num_epoch-1, optimizers[0].param_groups[0]['lr']))
        print('Temporary Best Accuracy is {:.4f} ({:.4f} at Epoch {})'.format(test_acc, best_acc, best_epoch))

        unlbl_dataset = source_unlbl_train_ldr.dataset.dataset
        lbl_dataset = source_lbl_train_ldr.dataset
        if args.clustering:
            if epoch % args.clustering_step == 0:
                pseudo_lbl_domain_label = domain_split(lbl_dataset, model, device=device,
                                                       cluster_before=lbl_dataset.clusters,
                                                       filename=path + '/nmi.txt', epoch=epoch,
                                                       nmb_cluster=args.num_clustering, method=args.clustering_method,
                                                       pca_dim=256, whitening=False, L2norm=False,
                                                       instance_stat=args.instance_stat)
                lbl_dataset.set_cluster(np.array(pseudo_lbl_domain_label))

                pseudo_unlbl_domain_label = domain_split(unlbl_dataset, model, device=device,
                                                         cluster_before=unlbl_dataset.clusters,
                                                         filename=path + '/nmi.txt', epoch=epoch,
                                                         nmb_cluster=args.num_clustering, method=args.clustering_method,
                                                         pca_dim=256, whitening=False, L2norm=False,
                                                         instance_stat=args.instance_stat)
                unlbl_dataset.set_cluster(np.array(pseudo_unlbl_domain_label))

        if args.loss_disc_weight:
            if args.clustering:
                lbl_hist = lbl_dataset.clusters
                unlbl_hist = unlbl_dataset.clusters

            else:
                lbl_hist = lbl_dataset.domains
                unlbl_hist = unlbl_dataset.domains

            lbl_weight = 1. / np.histogram(lbl_hist, bins=model.num_domains)[0]
            lbl_weight = lbl_weight / lbl_weight.sum() * model.num_domains
            lbl_weight = torch.from_numpy(lbl_weight).float().to(device)
            unlbl_weight = 1. / np.histogram(unlbl_hist, bins=model.num_domains)[0]
            unlbl_weight = unlbl_weight / unlbl_weight.sum() * model.num_domains
            unlbl_weight = torch.from_numpy(unlbl_weight).float().to(device)
            weight = (lbl_weight + unlbl_weight)/2

        else:
            weight = None

        # print('weight :', weight)
        # print('unlbl_weight :', unlbl_weight)
        model, optimizers = get_train(args.train)(
            model=model,reg_model = reg_model, reg_optimizers=reg_optimizers, source_lbl_train_ldr=source_lbl_train_ldr, source_unlbl_train_ldr=source_unlbl_train_ldr,
            source_lbl_train=source_lbl_train, optimizers=optimizers, device=device, epoch=epoch, num_epoch=num_epoch,
            filename=path+'/source_train.txt', entropy=args.entropy, alpha_mixup=args.alpha_mixup, disc_weight=weight, entropy_weight=args.entropy_weight,
            grl_weight=args.grl_weight)

        if epoch % args.eval_step == 0:
            acc, reg_acc = eval_model(model, reg_model, source_val, source_lbl_train_eval, device, epoch, path+'/source_eval.txt')
            acc_, reg_acc_ = eval_model(model, reg_model, target_test, source_lbl_train_eval, device, epoch, path+'/target_test.txt')

        if epoch % args.save_step == 0:
            torch.save(model.state_dict(), os.path.join(
                path, 'models',
                "model_{}.pt".format(epoch)))

        if acc >= best_acc:
            best_acc = acc
            test_acc = acc_
            best_epoch = epoch
            torch.save(model.state_dict(), os.path.join(
                path, 'models',
                "model_best.pt"))

        # if reg_acc>=best_reg_acc:
        #     best_reg_acc=reg_acc

        curr_reg_lr = get_reg_lr(reg_optimizers)
        print("Current reg model lr :", curr_reg_lr)
        for scheduler in schedulers:
            scheduler.step()
        reg_scheduler.step()

    best_model = get_model(args.model, args.train)(num_classes=source_lbl_train_ldr.dataset.num_class, num_domains=disc_dim, pretrained=False)
    best_model.load_state_dict(torch.load(os.path.join(
                path, 'models',
                "model_best.pt"), map_location=device))
    best_model = best_model.to(device)
    test_acc = eval_model(best_model, reg_model, target_test, source_lbl_train_eval, device, best_epoch, path+'/target_best.txt')
    print('Test Accuracy by the best model on the source domain is {} (at Epoch {})'.format(test_acc, best_epoch))


import math
import os
import pickle
from tqdm import tqdm
import random
import copy

import torch
import torch.nn as nn
import gensim
import faiss
import time
from modules import Encoder, LayerNorm

class KMeans(object):
    def __init__(self, num_cluster, seed, hidden_size, gpu_id=0, device="cpu"):
        """
        Args:
            k: number of clusters
        """
        self.seed = seed
        self.num_cluster = num_cluster
        self.max_points_per_centroid = 4096
        self.min_points_per_centroid = 0
        self.gpu_id = 0
        self.device = device
        self.first_batch = True
        self.hidden_size = hidden_size
        self.clus, self.index = self.__init_cluster(self.hidden_size)
        self.centroids = []

    def __init_cluster(
        self, hidden_size, verbose=False, niter=20, nredo=5, max_points_per_centroid=4096, min_points_per_centroid=0
    ):
        print(" cluster train iterations:", niter)
        clus = faiss.Clustering(hidden_size, self.num_cluster)
        clus.verbose = verbose
        clus.niter = niter
        clus.nredo = nredo
        clus.seed = self.seed
        clus.max_points_per_centroid = max_points_per_centroid
        clus.min_points_per_centroid = min_points_per_centroid

        res = faiss.StandardGpuResources()
        res.noTempMemory()
        cfg = faiss.GpuIndexFlatConfig()
        cfg.useFloat16 = False
        cfg.device = self.gpu_id
        index = faiss.GpuIndexFlatL2(res, hidden_size, cfg)
        return clus, index

    def train(self, x):
        # train to get centroids
        if x.shape[0] > self.num_cluster:
            self.clus.train(x, self.index)
        # get cluster centroids
        centroids = faiss.vector_to_array(self.clus.centroids).reshape(self.num_cluster, self.hidden_size)
        # convert to cuda Tensors for broadcast
        centroids = torch.Tensor(centroids).to(self.device)
        self.centroids = nn.functional.normalize(centroids, p=2, dim=1)

    def query(self, x):
        # self.index.add(x)
        D, I = self.index.search(x, 1)  # for each sample, find cluster distance and assignments
        seq2cluster = [int(n[0]) for n in I]
        # print("cluster number:", self.num_cluster,"cluster in batch:", len(set(seq2cluster)))
        seq2cluster = torch.LongTensor(seq2cluster).to(self.device)
        return seq2cluster, self.centroids[seq2cluster]

class SASRecModel(nn.Module):
    def __init__(self, args):
        super(SASRecModel, self).__init__()
        self.item_embeddings = nn.Embedding(args.item_size, args.hidden_size, padding_idx=0)
        self.position_embeddings = nn.Embedding(args.max_seq_length, args.hidden_size)
        self.item_encoder = Encoder(args)
        self.LayerNorm = LayerNorm(args.hidden_size, eps=1e-12)
        self.dropout = nn.Dropout(args.hidden_dropout_prob)
        self.args = args

        self.criterion = nn.BCELoss(reduction="none")
        self.apply(self.init_weights)

    # Positional Embedding
    def add_position_embedding(self, sequence):

        seq_length = sequence.size(1)
        position_ids = torch.arange(seq_length, dtype=torch.long, device=sequence.device)
        position_ids = position_ids.unsqueeze(0).expand_as(sequence)

        item_embeddings = self.item_embeddings(sequence)
        position_embeddings = self.position_embeddings(position_ids)
        sequence_emb = item_embeddings + position_embeddings
        sequence_emb = self.LayerNorm(sequence_emb)
        sequence_emb = self.dropout(sequence_emb)

        return sequence_emb

    # model same as SASRec
    def forward(self, input_ids):

        attention_mask = (input_ids > 0).long()
        extended_attention_mask = attention_mask.unsqueeze(1).unsqueeze(2)  # torch.int64
        max_len = attention_mask.size(-1)
        attn_shape = (1, max_len, max_len)
        subsequent_mask = torch.triu(torch.ones(attn_shape), diagonal=1)  # torch.uint8
        subsequent_mask = (subsequent_mask == 0).unsqueeze(1)
        subsequent_mask = subsequent_mask.long()

        if self.args.cuda_condition:
            subsequent_mask = subsequent_mask.cuda()

        extended_attention_mask = extended_attention_mask * subsequent_mask
        extended_attention_mask = extended_attention_mask.to(dtype=next(self.parameters()).dtype)  # fp16 compatibility
        extended_attention_mask = (1.0 - extended_attention_mask) * -10000.0

        sequence_emb = self.add_position_embedding(input_ids)

        item_encoded_layers = self.item_encoder(sequence_emb, extended_attention_mask, output_all_encoded_layers=True)

        sequence_output = item_encoded_layers[-1]
        return sequence_output

    def init_weights(self, module):
        """ Initialize the weights.
        """
        if isinstance(module, (nn.Linear, nn.Embedding)):
            # Slightly different from the TF version which uses truncated_normal for initialization
            # cf https://github.com/pytorch/pytorch/pull/5617
            module.weight.data.normal_(mean=0.0, std=self.args.initializer_range)
        elif isinstance(module, LayerNorm):
            module.bias.data.zero_()
            module.weight.data.fill_(1.0)
        if isinstance(module, nn.Linear) and module.bias is not None:
            module.bias.data.zero_()

# GRU Encoder
class GRUEncoder(nn.Module):
    r"""GRU4Rec is a model that incorporate RNN for recommendation.

    Note:

        Regarding the innovation of this article,we can only achieve the data augmentation mentioned
        in the paper and directly output the embedding of the item,
        in order that the generation method we used is common to other sequential models.
    """

    def __init__(self, args):
        super(GRUEncoder, self).__init__()

        # load parameters info
        self.item_embeddings = nn.Embedding(args.item_size, args.hidden_size, padding_idx=0)
        self.args = args
        self.embedding_size = args.hidden_size #64
        self.hidden_size = args.hidden_size*2  #128
        self.num_layers = args.num_hidden_layers-1 #1
        self.dropout_prob =args.hidden_dropout_prob #0.3

        # define layers and loss
        self.emb_dropout = nn.Dropout(args.hidden_dropout_prob)
        self.gru_layers = nn.GRU(
            input_size=self.embedding_size,
            hidden_size=self.hidden_size,
            num_layers=self.num_layers,
            bias=False,
            batch_first=True,
        )
        self.dense = nn.Linear(self.hidden_size, self.embedding_size)

    def forward(self, item_seq):
        item_seq_emb = self.item_embeddings(item_seq)
        item_seq_emb_dropout = self.emb_dropout(item_seq_emb)
        gru_output, _ = self.gru_layers(item_seq_emb_dropout)
        gru_output = self.dense(gru_output)
        # the embedding of the predicted item, shape of (batch_size, embedding_size)
        # seq_output = self.gather_indexes(gru_output, item_seq_len - 1)
        seq_output=gru_output
        return seq_output


# -*- coding: utf-8 -*-

#sonstige Utility imports
from __future__ import print_function
import time
import logging
import sys
sys.path.append("/home/pi/.local/lib/python2.7/site-packages")  #path muss hinzugefügt werden damit PyOta librarys gefunden werden können

from iota import Iota, ProposedTransaction, ProposedBundle, Address, Tag, TryteString       #importe Iota-Bibliothek um die API anzusprechen
from iota.crypto.addresses import AddressGenerator

# Reciever Seed: GCUKFZRLCTBGBDKQCQY9SMJPDPLFBDJJFTXZANHDJUTCZKIQQEUHSAVOYWKPTDDNEWRGBFWDMWYYRLRUR
# returned Address at index 0 for Security Level 2
reciever_address = "LOZMZOKJWWVASYYWT999JPLDBMUSFZKMLZW9IXHTOAUOQKZMRLRAZCWECAFONWKT9HSHKHLMKAWSQFFXX"

seed = "DSPOAXMVSC99IUIVJXTIBZFATVFKTCLLJYOLAGSMFJGFXAWEB9GNTQWEDVRYHKIOQF9T9IZY9IVPKTSZK"
url = "https://potato.iotasalad.org:14265" #fullnode url
api = Iota(url, seed) #erstelle Iota API
logging.basicConfig(format='%(levelname)s:%(message)s', level=logging.DEBUG)
logger = logging.getLogger(__name__)
api.adapter.set_logger(logger)

proposedTrx = ProposedTransaction(
    address = Address(reciever_address),
    value = 0,
    tag = Tag("BACHELORTEST"),
    message = TryteString.from_string("This is a test transaction")
)

proposedBundle = ProposedBundle([proposedTrx])
preparedBundle = api.prepare_transfer(proposedBundle)
publishedBundle = api.send_transfer(depth = 3, transfers = proposedBundle)

SmartRefueling/Raspberry Pi - Python/transfer-test.py


from typing import Optional, Tuple
import IPython

from reward_machine import RewardMachine

class Builder:
    def __init__(self, appears: frozenset[str]):
        self.appears = appears
        self.transitions: dict[int,
                               dict[frozenset[str], Tuple[int, int]]] = dict()
        self.terminal_states: set[int] = set()

    def build(self) -> RewardMachine:
        return RewardMachine(self.transitions, frozenset(self.appears), frozenset(self.terminal_states))

    def terminal(self, state: int) -> 'Builder':
        self.terminal_states.add(state)
        return self

    def t(self, from_state: int, to_state: int, input_symbol: frozenset[str], output: int) -> 'Builder':
        if from_state in self.terminal_states:
            raise ValueError(
                f'terminal states can\'t have outgoing connections')
        if from_state not in self.transitions:
            self.transitions[from_state] = dict()
        if input_symbol in self.transitions[from_state]:
            raise ValueError(
                f'{input_symbol} already in state {from_state} ({(from_state, to_state, input_symbol, output)})')
        self.transitions[from_state][input_symbol] = (to_state, output)
        return self


from typing import List  # noqa: F401

from libqtile import bar, layout, widget, extension
from libqtile.config import Click, Drag, Group, Key, Match, Screen
from libqtile.lazy import lazy
from libqtile.utils import guess_terminal
import sys
import os

config_dir = os.path.dirname(__file__)
print("Amy's debug: The config dir is : " + config_dir)
from colour import Colour

logo = "mod4"
alt="mod1"

terminal = guess_terminal()
launcher = "amys-launcher"
keyHelp = "key-help " + config_dir

print("Amy's debug: keyHelp=" + keyHelp)

keys = [
    # A list of available commands that can be bound to keys can be found
    # at https://docs.qtile.org/en/latest/manual/config/lazy.html

    Key([logo], "menu", lazy.spawn(keyHelp), desc="Show key help"),
    Key([], "pause", lazy.spawn(swaylock), desc="Lock screen"),

    # Switch between windows
    Key([logo], "Left", lazy.layout.left(), desc="Move focus to left"),
    Key([logo], "Right", lazy.layout.right(), desc="Move focus to right"),
    Key([logo], "Down", lazy.layout.down(), desc="Move focus down"),
    Key([logo], "Up", lazy.layout.up(), desc="Move focus up"),
    Key([alt], "Tab", lazy.group.next_window(), desc="Move focus to next window"),
    Key([alt, "shift"], "Tab", lazy.group.next_window(), desc="Move focus to next window"),
    # Key([alt], ".", lazy.next_screen(), desc='Next monitor')
    Key([logo], "Tab", lazy.next_screen(), desc="Next monitor"),

    # Move windows between left/right columns or move up/down in current stack.
    # Moving out of range in Columns layout will create new column.
    Key([logo, "shift"], "Left", lazy.layout.shuffle_left(), desc="Move window to the left"),
    Key([logo, "shift"], "Right", lazy.layout.shuffle_right(), desc="Move window to the right"),
    Key([logo, "shift"], "Down", lazy.layout.shuffle_down(), desc="Move window down"),
    Key([logo, "shift"], "Up", lazy.layout.shuffle_up(), desc="Move window up"),

    # Grow windows. If current window is on the edge of screen and direction
    # will be to screen edge - window would shrink.
    Key([logo, "control"], "Left", lazy.layout.grow_left(), desc="Grow window to the left"),
    Key([logo, "control"], "Right", lazy.layout.grow_right(), desc="Grow window to the right"),
    Key([logo, "control"], "Down", lazy.layout.grow_down(), desc="Grow window down"),
    Key([logo, "control"], "Up", lazy.layout.grow_up(), desc="Grow window up"),
    Key([logo], "n", lazy.layout.normalize(), desc="Reset all window sizes"),

    Key([logo, alt], "d", lazy.screen.next_group(), desc="Go to next screen"),

    # Swap??? windows between left/right columns or up/down in current stack.
    Key([logo, alt], "Left", lazy.layout.flip_left(), desc="Move window to the left"),
    Key([logo, alt], "Right", lazy.layout.flip_right(), desc="Move window to the right"),
    Key([logo, alt], "Down", lazy.layout.flip_down(), desc="Move window down"),
    Key([logo, alt], "Up", lazy.layout.flip_up(), desc="Move window up"),

    # Key([logo, "control"], 'Return', lazy.run_extension(extension.WindowList(
    #     dmenu_prompt=">"
    # ))),

    # Toggle between split and unsplit sides of stack.
    # Split = all windows displayed
    # Unsplit = 1 window displayed, like Max layout, but still with
    # multiple stack panes
    # Key([logo, "shift"], "Return", lazy.layout.toggle_split(),
    #     desc="Toggle between split and unsplit sides of stack"),
    Key([logo], "Return", lazy.spawn(launcher), desc="Show launch menu"),
    Key([logo, "shift"], "Return", lazy.spawn(terminal), desc="Launch terminal"),

    # Toggle between different layouts as defined below
    Key([logo, "control"], "l", lazy.next_layout(), desc="Toggle between layouts"),

    Key([logo], "Delete", lazy.window.kill(), desc="Kill focused window"),

    Key([logo, "control"], "r", lazy.reload_config(), desc="Reload the config"),
    Key([logo, "control"], "q", lazy.shutdown(), desc="Shutdown Qtile"),
    # Key([logo], "r", lazy.spawncmd(),
    #     desc="Spawn a command using a prompt widget"),

    Key([logo, "control"], "f", lazy.window.toggle_floating(), desc="Toggle floating"),
    Key([logo, "control", "shift"], "f", lazy.window.toggle_fullscreen(), desc="Toggle fullscreen"),

    Key([alt, "control"], "F1", lazy.core.change_vt(1), desc="Go to virtual console 1"),
    Key([alt, "control"], "F2", lazy.core.change_vt(2), desc="Go to virtual console 2"),
    Key([alt, "control"], "F3", lazy.core.change_vt(3), desc="Go to virtual console 3"),
    Key([alt, "control"], "F4", lazy.core.change_vt(4), desc="Go to virtual console 4"),
    Key([alt, "control"], "F5", lazy.core.change_vt(5), desc="Go to virtual console 5"),
    Key([alt, "control"], "F6", lazy.core.change_vt(6), desc="Go to virtual console 6"),
    Key([alt, "control"], "F7", lazy.core.change_vt(7), desc="Go to virtual console 7"),
    Key([alt, "control"], "F8", lazy.core.change_vt(8), desc="Go to virtual console 8"),
    Key([alt, "control"], "F9", lazy.core.change_vt(9), desc="Go to virtual console 9"),
]

# What other window managers often call "workspaces".
groups = [Group(i) for i in ["1", "2", "3", "4", "5", "6", "7", "8", "9",
                             "nixos", "vmware", "maths", "haskell", "qtile"]]

for g in groups:
    shortcut_key=g.name[0];
    # print(f"DEBUG g={g}, shortcut_key={shortcut_key}")
    keys.extend([
        # mod1 + letter of group = switch to group
        Key([logo], shortcut_key, lazy.group[g.name].toscreen(), desc="Switch to group {}".format(g.name)),

        # mod1 + shift + letter of group = move focused window to group
        Key([logo, "shift"], shortcut_key, lazy.window.togroup(g.name), desc="move focused window to group {}".format(g.name)),
    ])

layouts = [
#    layout.Columns(border_focus_stack=['#d75f5f', '#8f3d3d'], border_width=4),
    layout.Bsp(
        # Border colour(s) for the focused window.
        border_focus=Colour.base0D,
        # Border colour(s) for un-focused windows.
        border_normal=Colour.base04,
	# Border width.
        border_width=6,
        # New clients are inserted in the shortest branch.
	#fair=True,      jupyterlab      jupyterlab

        # Amount by which to grow a window/column.
	#grow_amount=10,
        # New client occupies lower or right subspace.
	#lower_right=True,
	# Margin of the layout (int or list of ints [N E S W]).
        #margin=0,
        # Width/height ratio that defines the partition direction.
        #ratio=1.6
    ),
    layout.Tile(
        # Border colour(s) for the focused window.
        border_focus=Colour.base0D,
        # Border colour(s) for un-focused windows.
        border_normal=Colour.base04,
    )
]

widget_defaults = dict(
    font='sans',
    fontsize=12,
    padding=3,
)
extension_defaults = widget_defaults.copy()

status_bar_widgets = [
    widget.CurrentLayout(),
    widget.CurrentLayoutIcon(),
    widget.CurrentScreen(active_color=Colour.base0A, inactive_colour=Colour.base0D),
    widget.GroupBox(),
    widget.Prompt(),
    # widget.Wlan(
    #         format='{essid} {quality}/70',
    #         update_interval=5
    #     ),
    widget.WindowName(),
    widget.Spacer(length=10),
    widget.Net(
        format='  {interface}: {down} ↓↑ {up}',
        update_interval=10
    ),
    widget.Spacer(length=10),
    widget.Chord(
        chords_colors={
            'launch': ("#ff0000", "#ffffff"),
        },
        name_transform=lambda name: name.upper(),
    ),
    widget.Spacer(length=10),
    widget.ThermalSensor(),
    widget.Spacer(length=10),
    widget.Memory(
        format=' {MemUsed: .0f}{mm}/{MemTotal: .0f}{mm}',
        update_interval=10
    ),
    widget.Spacer(length=10),
    widget.CPU(
        format=' {freq_current}GHz {load_percent}%',
        update_interval=10
    ),
    widget.Spacer(length=10),
    widget.Clock(
        foreground=Colour.base00,
        background=Colour.base0D,
        format='%A, %d %B %Y %H:%M'
    ),
]

screens = [
    Screen(
        bottom=bar.Bar([
            widget.CurrentLayout(),
            widget.CurrentLayoutIcon(),
            widget.CurrentScreen(active_color=Colour.base0A, inactive_colour=Colour.base0D),
            widget.GroupBox(),
            widget.Prompt(),
            # widget.Wlan(
            #         format='{essid} {quality}/70',
            #         update_interval=5
            #     ),
            widget.WindowName(),
            widget.Spacer(length=10),
            widget.Net(
                format='  {interface}: {down} ↓↑ {up}',
                update_interval=10
            ),
            widget.Spacer(length=10),
            widget.Chord(
                chords_colors={
                    'launch': ("#ff0000", "#ffffff"),
                },
                name_transform=lambda name: name.upper(),
            ),
            widget.Spacer(length=10),
            widget.ThermalSensor(),
            widget.Spacer(length=10),
            widget.Memory(
                format=' {MemUsed: .0f}{mm}/{MemTotal: .0f}{mm}',
                update_interval=10
            ),
            widget.Spacer(length=10),
            widget.CPU(
                format=' {freq_current}GHz {load_percent}%',
                update_interval=10
            ),
            widget.Spacer(length=10),
            widget.Clock(
                foreground=Colour.base00,
                background=Colour.base0D,
                format='%A, %d %B %Y %H:%M'
            ),
        ],
        24)),
    Screen(
        bottom=bar.Bar([
            widget.CurrentLayout(),
            widget.CurrentLayoutIcon(),
            widget.CurrentScreen(active_color=Colour.base0A, inactive_colour=Colour.base0D),
            widget.GroupBox(),
            widget.Prompt(),
            # widget.Wlan(
            #         format='{essid} {quality}/70',
            #         update_interval=5
            #     ),
            widget.WindowName(),
            widget.Spacer(length=10),
            widget.Net(
                format='  {interface}: {down} ↓↑ {up}',
                update_interval=10
            ),
            widget.Spacer(length=10),
            widget.Chord(
                chords_colors={
                    'launch': ("#ff0000", "#ffffff"),
                },
                name_transform=lambda name: name.upper(),
            ),
            widget.Spacer(length=10),
            widget.ThermalSensor(),
            widget.Spacer(length=10),
            widget.Memory(
                format=' {MemUsed: .0f}{mm}/{MemTotal: .0f}{mm}',
                update_interval=10
            ),
            widget.Spacer(length=10),
            widget.CPU(
                format=' {freq_current}GHz {load_percent}%',
                update_interval=10
            ),
            widget.Spacer(length=10),
            widget.Clock(
                foreground=Colour.base00,
                background=Colour.base0D,
                format='%A, %d %B %Y %H:%M'
            ),
        ],
        24))
]

# Drag floating layouts.
mouse = [
    Drag([logo], "Button1", lazy.window.set_position_floating(),
         start=lazy.window.get_position()),
    Drag([logo], "Button3", lazy.window.set_size_floating(),
         start=lazy.window.get_size()),
    Click([logo], "Button2", lazy.window.bring_to_front())
]

dgroups_key_binder = None
dgroups_app_rules = []  # type: List
follow_mouse_focus = False
bring_front_click = False
cursor_warp = False
# floating_layout = layout.Floating(float_rules=[
#     # Run the utility of `xprop` to see the wm class and name of an X client.
#     *layout.Floating.default_float_rules,
#     Match(wm_class='confirmreset'),  # gitk
#     Match(wm_class='makebranch'),  # gitk
#     Match(wm_class='maketag'),  # gitk
#     Match(wm_class='ssh-askpass'),  # ssh-askpass
#     Match(title='branchdialog'),  # gitk
#     Match(title='pinentry'),  # GPG key password entry
# ])
auto_fullscreen = True
focus_on_window_activation = "smart"
reconfigure_screens = True

# If things like steam games want to auto-minimize themselves when losing
# focus, should we respect this or not?
auto_minimize = True

# XXX: Gasp! We're lying here. In fact, nobody really uses or cares about this
# string besides java UI toolkits; you can see several discussions on the
# mailing lists, GitHub issues, and other WM documentation that suggest setting
# this string if your java app doesn't work correctly. We may as well just lie
# and say that we're a working one by default.
#
# We choose LG3D to maximize irony: it is a 3D non-reparenting WM written in
# java that happens to be on java's whitelist.
wmname = "LG3D"


import os, subprocess, glob, argparse
parser = argparse.ArgumentParser()
parser.add_argument("chrom", help="chromosome to analyze, in format 'chr1'")
parser.add_argument("tissue", help="tissue being analyzed")
parser.add_argument("data_source", help="origin of expression data (e.g. GTEx, CMC")
parser.add_argument("out", help="Output directory")
parser.add_argument("sumstats", help="GWAS summary stats")
parser.add_argument("LD", help="chromosome to analyze, in format 'chr1'")
args = parser.parse_args()

##############Run TWAS#################
#This script takes weights in a chromosome-specific WEIGHTS_* directory and runs TWAS on them.
#######################################

chromnum = args.chrom.split('r')[-1:][0]

#Move all chromosome-specific WEIGHTS_* dir contents to WEIGHTS
if not os.path.isdir("%s/WEIGHTS"%(args.tissue)):
	os.mkdir("%s/WEIGHTS"%(args.tissue))
cmd = "mv %s/WEIGHTS_%s/* %s/WEIGHTS && rm -r %s/WEIGHTS_%s" % (args.tissue,chromnum,args.tissue,args.tissue,chromnum)
os.system(cmd)

#make WEIGHTS*.pos file listing all *RDat files and corresponding gene coordinates
posfile="%s/WEIGHTS/%s.%s.pos" % (args.tissue,args.data_source,chromnum)
pos = open(posfile,'w')
pos.write("WGT\tID\tCHR\tP0\tP1\n")

weights=glob.glob("%s/WEIGHTS/*RDat"%(args.tissue))
for ln in weights:
	line = ln.strip().split('/')[2]
	clust = ln.strip().split('.wgt.RDat')[0].split('/')[2]
	clustID,c,s,e = clust.split('-')
	if c == chromnum:
		posline=("%s\t%s\t%s\t%s\t%s\n") % (line, clust, chromnum, s, e)
		pos.write(posline)
pos.close()

#Run TWAS
cmd = """Rscript /project2/nobrega/grace/splicing/scripts/fusion_twas-master/FUSION.assoc_test.R \
--sumstats %s \
--weights ./%s/WEIGHTS/%s.%s.pos \
--weights_dir ./%s/WEIGHTS/ \
--ref_ld_chr %s \
--chr %s \
--out %s%s.%s.dat""" % (args.sumstats, args.tissue, args.data_source, chromnum, args.tissue, args.LD, chromnum, args.out, args.data_source, chromnum)
os.system(cmd)


import json
import simplekml

def iterateData(data):
    for point in data:
        ts = int(point["timestampMs"])
        lat = int(point["latitudeE7"]) / 10000000
        long = int(point["longitudeE7"]) / 10000000
        yield(ts, (lat, long))

print("Parsing...")

data = json.load(open("Location History.json", "r"))

data = data['locations']

print("There are %d data points" % len(data))

fCount = 0
i = 0

kml = None
pieces = []

for timestamp, (lat, long) in iterateData(data):
      if i % 190000 == 0 and i != 0 and False:
            kml = simplekml.Kml()
            kml.newlinestring(name="line", coords=pieces)
            kml.save(f"output{fCount}.kml")
            pieces = []
            fCount += 1
      pieces.append((long,lat))
      i += 1

if len(pieces) > 0:
        kml = simplekml.Kml()
        kml.newlinestring(name="line", coords=pieces)
        kml.save(f"output{fCount}.kml")


import argparse
import sys
from pydantic import BaseSettings
import requests
from http.client import HTTPConnection
import json

PUSHOVER_BASE_URL = "https://api.pushover.net/1/messages.json"

class Settings(BaseSettings):
    pushover_token: str
    pushover_user: str

    class Config:
        env_file = ".env"

def parse_args():
    parser = argparse.ArgumentParser(description="DESCRIPTION")
    parser.add_argument(
        "-v",
        "--verbose",
        help="Enable verbose logging",
        action="store_true",
        default=False,
    )
    parser.add_argument(
        "-m", "--message", help="notification", action="store", required=True
    )
    parser.add_argument("-t", "--title", help="notification title", action="store")
    parser.add_argument(
        "-p",
        "--priority",
        help="notification priority",
        action="store",
        choices=[-2, -1, 0, 1, 2],
        default=0,
    )

    return parser.parse_args()

def notify(**kwargs):
    r = requests.post(PUSHOVER_BASE_URL, **kwargs)
    r_json = r.json()

    if r.status_code == 200:
        sys.exit(0)
    if r.status_code == 400:
        print(json.dumps(r_json, indent=2))
        sys.exit(1)

if __name__ == "__main__":
    settings = Settings()
    args = parse_args()
    if args.verbose:
        HTTPConnection.debuglevel = 1

    # Build payload
    payload = {"token": settings.pushover_token, "user": settings.pushover_user}

    payload["message"] = args.message
    payload["title"] = args.title if args.title is not None else None
    payload["priority"] = args.priority if args.priority is not None else None

    # send notification
    notify(data=payload, headers={})


import numpy as np
import os
from mpEntropy import mpSystem
import matplotlib as mpl
from matplotlib.pyplot import cm
import matplotlib.pyplot as plt
from scipy.signal import savgol_filter
# This is a workaround until scipy fixes the issue
import warnings

warnings.filterwarnings(action="ignore", module="scipy", message="^internal gelsd")

# Load sysVar
sysVar = mpSystem("../interact_0.ini", plotOnly=True)

# Create plot folder
pltfolder = "./epsplots/"
if not os.path.exists(pltfolder):
    os.mkdir(pltfolder)

print("Plotting", end='')
mpl.use('Agg')
# minimum and maximum times to plot
min_time = 0
max_time = 30
inlay_min_time = 10
inlay_max_time = 100
inlay_log_min_time = 0
inlay_log_max_time = 20
# styles and stuff
avgstyle = 'dashed'
avgsize = 0.6
expectstyle = 'solid'
expectsize = 1
legend_size = 10
font_size = 10
# https://scipy.github.io/old-wiki/pages/Cookbook/Matplotlib/LaTeX_Examples.html
fig_width_pt = 246.0  # Get this from LaTeX using \showthe\columnwidth
inches_per_pt = 1.0 / 72.27  # Convert pt to inches
golden_mean = (np.sqrt(5) - 1.0) / 2.0  # Aesthetic ratio
fig_width = fig_width_pt * inches_per_pt  # width in inches
fig_height = fig_width * golden_mean  # height in inches
fig_size = [fig_width, fig_height]
# padding in units of fontsize
padding = 0.32

params = {
    'axes.labelsize': 10,
    'font.size': 10,
    'legend.fontsize': 10,
    'xtick.labelsize': 8,
    'ytick.labelsize': 8,
    'lines.linewidth': 0.7,
    'figure.figsize': fig_size,
    'legend.frameon': False,
    'legend.loc': 'best',
    'mathtext.default': 'rm'  # see http://matplotlib.org/users/customizing.html
}
plt.rcParams['agg.path.chunksize'] = 0
plt.rcParams.update(params)
plt.rc('text', usetex=True)
plt.rc('font', **{'family': 'sans-serif', 'sans-serif': ['Arial']})

loavgpercent = sysVar.plotLoAvgPerc  # percentage of time evolution to start averaging
loavgind = int(loavgpercent * sysVar.dataPoints)  # index to start at when calculating average and stddev
loavgtime = np.round(loavgpercent * (sysVar.deltaT * sysVar.steps * sysVar.plotTimeScale), 2)

if sysVar.boolPlotAverages:
    print(' with averaging from Jt=%.2f' % loavgtime, end='')

fwidth = sysVar.plotSavgolFrame
ford = sysVar.plotSavgolOrder

occ_array = np.loadtxt('../data/occupation.txt')
# multiply step array with time scale
step_array = occ_array[:, 0] * sysVar.plotTimeScale
min_index = int(min_time / step_array[-1] * len(step_array))
max_index = int(max_time / step_array[-1] * len(step_array))
inlay_min_index = int(inlay_min_time / step_array[-1] * len(step_array))
inlay_max_index = int(inlay_max_time / step_array[-1] * len(step_array))
inlay_log_min_index = int(inlay_log_min_time / step_array[-1] * len(step_array))
inlay_log_max_index = int(inlay_log_max_time / step_array[-1] * len(step_array))

### Single-level occupation numbers

for i in range(0, sysVar.m):
    plt.plot(step_array[min_index:max_index], occ_array[min_index:max_index, i + 1], label=r'$n_' + str(i) + '$')
    if sysVar.boolPlotAverages:
        tavg = savgol_filter(occ_array[:, i + 1], fwidth, ford)
        plt.plot(step_array[loavgind:], tavg[loavgind:], linestyle=avgstyle, color='black')

plt.ylabel(r'$\langle n \rangle$')
plt.xlabel(r'$J\,t$')
plt.legend(loc='upper right')
plt.tight_layout(padding)
plt.savefig(pltfolder + 'occupation_single.eps', format='eps', dpi=1000)
plt.clf()

### Single-level occupation number difference to mean

for i in range(0, sysVar.m):
    plt.semilogy(step_array[min_index:max_index], np.abs(occ_array[min_index:max_index, i + 1] - np.average(occ_array[loavgind:, i + 1]))*np.exp(-i*2.1))

plt.ylabel(r'$| \bar{\langle n \rangle} - \langle n \rangle|$')
plt.xlabel(r'$J\,t$')
plt.ylim(ymin=1e-6, ymax=5e0)
plt.yticks([])
plt.tight_layout(padding)
plt.savefig(pltfolder + 'occupation_single_difftomean.eps', format='eps', dpi=1000)
plt.clf()

# with inlay
f = plt.figure(1)
a1 = plt.subplot(1, 1, 1)
for i in range(0, sysVar.m):
    a1.plot(step_array[min_index:max_index], occ_array[min_index:max_index, i + 1], label=r'$n_' + str(i) + '$')
    if sysVar.boolPlotAverages:
        tavg = savgol_filter(occ_array[:, i + 1], fwidth, ford)
        plt.plot(step_array[loavgind:], tavg[loavgind:], linestyle=avgstyle, color='black')
    a2 = plt.axes([.3, .575, .4, .35])
    a2.plot(step_array[inlay_min_index:inlay_max_index], occ_array[inlay_min_index:inlay_max_index, i + 1],
            linewidth=0.2)
    a2.yaxis.tick_right()

tmp_ticks = list(a2.get_xticks())
tmp_ticks.pop(0)
tmp_ticks.pop(0)
tmp_ticks.pop(1)
if tmp_ticks[-1] >= inlay_max_time:
    tmp_ticks.pop(-1)
    if tmp_ticks[-1] < inlay_max_time or len(tmp_ticks) == 0:
        tmp_ticks = tmp_ticks + [inlay_max_time]
a2.set_xticks(tmp_ticks + [inlay_min_time])
a1.set_ylabel(r'$\langle n \rangle$')
a1.set_xlabel(r'$J\,t$')
a1.legend(loc='upper right')
f.savefig(pltfolder + 'occupation_single_inlay.eps', format='eps', dpi=1000)
f.clf()
print('.', end='', flush=True)

### Traced out (bath) occupation numbers
for i in sysVar.kRed:
    plt.plot(step_array[min_index:max_index], occ_array[min_index:max_index, i + 1], label=r'$n_' + str(i) + '$',
             color='C%i' % i)
    if sysVar.boolPlotAverages:
        tavg = savgol_filter(occ_array[:, i + 1], fwidth, ford)
        plt.plot(step_array[loavgind:], tavg[loavgind:], linestyle=avgstyle, color='black')

plt.ylabel(r'$\langle n \rangle$')
plt.xlabel(r'$J\,t$')
plt.legend(loc='upper right')
plt.tight_layout(padding)
plt.savefig(pltfolder + 'occupation_bath.eps', format='eps', dpi=1000)
plt.clf()

# with inlay
f = plt.figure(1)
a1 = plt.subplot(1, 1, 1)
a1.set_ylabel(r'$\langle n \rangle$')
a1.set_xlabel(r'$J\,t$')
plt.tight_layout(padding)
for i in sysVar.kRed:
    a1.plot(step_array[min_index:max_index], occ_array[min_index:max_index, i + 1], label=r'$n_' + str(i) + '$',
            color='C%i' % i)
    if sysVar.boolPlotAverages:
        tavg = savgol_filter(occ_array[:, i + 1], fwidth, ford)
        plt.plot(step_array[loavgind:], tavg[loavgind:], linestyle=avgstyle, color='black')
    a2 = plt.axes([.27, .575, .4, .35])
    a2.plot(step_array[inlay_min_index:inlay_max_index], occ_array[inlay_min_index:inlay_max_index, i + 1],
            linewidth=0.2, color='C%i' % i)
    a2.yaxis.tick_right()

tmp_ticks = list(a2.get_xticks())
tmp_ticks.pop(0)
tmp_ticks.pop(0)
tmp_ticks.pop(1)
if tmp_ticks[-1] >= inlay_max_time:
    tmp_ticks.pop(-1)
    if tmp_ticks[-1] < inlay_max_time or len(tmp_ticks) == 0:
        tmp_ticks = tmp_ticks + [inlay_max_time]
a2.set_xticks(tmp_ticks + [inlay_min_time])
a1.legend(loc='upper right')
f.savefig(pltfolder + 'occupation_bath_inlay.eps', format='eps', dpi=1000)
f.clf()
print('.', end='', flush=True)

### Leftover (system) occupation numbers

for i in np.arange(sysVar.m)[sysVar.mask]:
    plt.plot(step_array[min_index:max_index], occ_array[min_index:max_index, i + 1], label=r'$n_' + str(i) + '$',
             color='C%i' % i)
    if sysVar.boolPlotAverages:
        tavg = savgol_filter(occ_array[:, i + 1], fwidth, ford)
        plt.plot(step_array[loavgind:], tavg[loavgind:], linestyle=avgstyle, color='black')

plt.ylabel(r'$\langle n \rangle$')
plt.xlabel(r'$J\,t$')
plt.legend(loc='lower right')
plt.tight_layout(padding+0.4)
plt.savefig(pltfolder + 'occupation_system.eps', format='eps', dpi=1000)
plt.clf()

# with inlay
f = plt.figure(1)
a1 = plt.subplot(1, 1, 1)
for i in np.arange(sysVar.m)[sysVar.mask]:
    a1.plot(step_array[min_index:max_index], occ_array[min_index:max_index, i + 1], label=r'$n_' + str(i) + '$',
            color='C%i' % i)
    if sysVar.boolPlotAverages:
        tavg = savgol_filter(occ_array[:, i + 1], fwidth, ford)
        plt.plot(step_array[loavgind:], tavg[loavgind:], linestyle=avgstyle, color='black')
    a2 = plt.axes([.3, .275, .4, .35])
    a2.plot(step_array[inlay_min_index:inlay_max_index], occ_array[inlay_min_index:inlay_max_index, i + 1],
            linewidth=0.2, color='C%i' % i)
    a2.yaxis.tick_right()

tmp_ticks = list(a2.get_xticks())
tmp_ticks.pop(0)
tmp_ticks.pop(0)
tmp_ticks.pop(1)
if tmp_ticks[-1] >= inlay_max_time:
    tmp_ticks.pop(-1)
    if tmp_ticks[-1] < inlay_max_time or len(tmp_ticks) == 0:
        tmp_ticks = tmp_ticks + [inlay_max_time]
a2.set_xticks(tmp_ticks + [inlay_min_time])
a1.set_ylabel(r'$\langle n \rangle$')
a1.set_xlabel(r'$J\,t$')
a1.legend(loc='lower right')
f.savefig(pltfolder + 'occupation_system_inlay.eps', format='eps', dpi=1000)
f.clf()
print('.', end='', flush=True)

### Subsystems occupation numbers
# store fluctuations in a data
fldat = open(pltfolder + 'occ_fluctuation_N' + str(sysVar.N) + '.txt', 'w')
fldat.write('N_tot: %i\n' % sysVar.N)
tmp = np.zeros(len(step_array))
for i in sysVar.kRed:
    tmp += occ_array[:, i + 1]
plt.plot(step_array[min_index:max_index], tmp[min_index:max_index], label="bath", color='magenta')

if sysVar.boolPlotAverages:
    tavg = savgol_filter(tmp, fwidth, ford)
    plt.plot(step_array[loavgind:], tavg[loavgind:], linestyle=avgstyle, color='black')

avg = np.mean(tmp[loavgind:], dtype=np.float64)
stddev = np.std(tmp[loavgind:], dtype=np.float64)
fldat.write('bath_average: %.16e\n' % avg)
fldat.write('bath_stddev: %.16e\n' % stddev)
fldat.write('bath_rel._fluctuation: %.16e\n' % (stddev / avg))

tmp.fill(0)
for i in np.arange(sysVar.m)[sysVar.mask]:
    tmp += occ_array[:, i + 1]
plt.plot(step_array[min_index:max_index], tmp[min_index:max_index], label="system", color='darkgreen')

if sysVar.boolPlotAverages:
    tavg = savgol_filter(tmp, fwidth, ford)
    plt.plot(step_array[loavgind:], tavg[loavgind:], linestyle=avgstyle, color='black')

avg = np.mean(tmp[loavgind:], dtype=np.float64)
stddev = np.std(tmp[loavgind:], dtype=np.float64)
fldat.write('system_average: %.16e\n' % avg)
fldat.write('system_stddev: %.16e\n' % stddev)
fldat.write('system_rel._fluctuation: %.16e\n' % (stddev / avg))

for i in range(sysVar.m):
    avg = np.mean(occ_array[loavgind:, i + 1], dtype=np.float64)
    stddev = np.std(occ_array[loavgind:, i + 1], dtype=np.float64)
    fldat.write('n%i_average: %.16e\n' % (i, avg))
    fldat.write('n%i_stddev: %.16e\n' % (i, stddev))
    fldat.write('n%i_rel._fluctuation: %.16e\n' % (i, (stddev / avg)))
fldat.close()

plt.ylabel(r'$\langle n \rangle$')
plt.xlabel(r'$J\,t$')
plt.legend(loc='upper right')
plt.tight_layout(padding)
plt.savefig(pltfolder + 'occupation_systems.eps', format='eps', dpi=1000)
plt.clf()
print('.', end='', flush=True)

### occupation number in levels against level index

occavg = np.loadtxt(pltfolder + 'occ_fluctuation_N' + str(sysVar.N) + '.txt', usecols=(1,))
plt.xlim(-0.1, sysVar.m - 0.9)
for l in range(0, sysVar.m):
    plt.errorbar(l, occavg[int(7 + 3 * l)] / sysVar.N, xerr=None, yerr=occavg[int(8 + 3 * l)] / sysVar.N,
                 marker='o', color=cm.Set1(0))
plt.ylabel(r'Relative level occupation')
plt.xlabel(r'Level index')
plt.tight_layout(padding)
plt.savefig(pltfolder + 'occupation_distribution.eps', format='eps', dpi=1000)
plt.clf()

plt.xlim(np.min(np.arange(sysVar.m)[sysVar.mask]) - 0.1, np.max(np.arange(sysVar.m)[sysVar.mask]) + 0.1)
for l in np.arange(sysVar.m)[sysVar.mask]:
    plt.errorbar(l, occavg[int(7 + 3 * l)] / sysVar.N, xerr=None, yerr=occavg[int(8 + 3 * l)] / sysVar.N,
                 marker='o', color=cm.Set1(0))
plt.ylabel(r'Relative level occupation')
plt.xlabel(r'Level index')
plt.tight_layout(padding)
plt.savefig(pltfolder + 'occupation_distribution_sys.eps', format='eps', dpi=1000)
plt.clf()

plt.xlim(np.min(sysVar.kRed) - 0.1, np.max(sysVar.kRed) + 0.1)
for l in sysVar.kRed:
    plt.errorbar(l, occavg[int(7 + 3 * l)] / sysVar.N, xerr=None, yerr=occavg[int(8 + 3 * l)] / sysVar.N,
                 marker='o', color=cm.Set1(0))
plt.ylabel(r'Relative level occupation')
plt.xlabel(r'Level index')
plt.tight_layout(padding)
plt.savefig(pltfolder + 'occupation_distribution_bath.eps', format='eps', dpi=1000)
plt.clf()

print(" done!")


import cv2
from lib.crypto.encoder import encode_bytes, decode_bytes

Q = 8

def encode_data(image: cv2.Mat, data: bytes) -> cv2.Mat:
    """Encodes data into given cv2 image using QIM steganography method.

    Args:
        image (cv2.Mat): cv2 image to encode data in
        data (bytes): data to encode

    Returns:
        cv2.Mat: cv2 image with encoded data
    """
    height, width, _ = image.shape
    data = encode_bytes(data)

    assert height * width >= len(data) + 1, "[ERROR]: Can't encode data: image is too small."

    for i in range(height):
        for j in range(width):
            if i * width + j < len(data):
                image[i, j][2] = (image[i, j][2] // Q) * Q + Q//2 * int(data[i * width + j])
            elif i * width + j == len(data):
                image[i, j][2] = (image[i, j][2] // Q) * Q + Q//2
            else:
                image[i, j][2] = (image[i, j][2] // Q) * Q

    return image

def decode_data(image: cv2.Mat) -> bytes:
    """Decodes data from given cv2 image using QIM steganography method.

    Args:
        image (cv2.Mat): image to decode data from

    Returns:
        bytes: decoded data
    """
    height, width, _ = image.shape
    data = ""

    for i in range(height):
        for j in range(width):
            pxl0 = (image[i, j][2] // Q) * Q
            pxl1 = (image[i, j][2] // Q) * Q + Q//2
            if abs(pxl0 - image[i, j][2]) < abs(pxl1 - image[i, j][2]):
                data += "0"
            else:
                data += "1"

    return decode_bytes(data[:data.rfind("1")])