from __future__ import with_statement
from gui.toolbox import Monitor

import wx, sys
import math
import traceback
from wx import Bitmap, Rect, RectS, RectPS, GetMousePosition,  \
    MenuEvent, Point, VERTICAL, HORIZONTAL, Pen, Brush, \
    Size

from gui.skin.skinobjects import SkinColor,Margins
from gui.windowfx import fadein
from gui import skin
from util.primitives.funcs import do, Delegate
from common import pref
from gui.uberwidgets import UberWidget
from gui.textutil import GetTextWidth,default_font
from gui.windowfx import DrawSubMenuArrow, ApplySmokeAndMirrors

from logging import getLogger; log = getLogger('simplemenu')

class SMDTimer(wx.Timer):

    def __init__(self,menu):
        self.menu = menu
        wx.Timer.__init__(self)

    def Start(self,hitrect,*args,**kwargs):
        self.hitrect = hitrect
        self.args   = args
        self.kwargs = kwargs
        wx.Timer.Start(self, 500, True)

    def Notify(self):
        if not self.menu.Shown and self.hitrect.Contains(wx.GetMousePosition()):
            self.menu.Display(*self.args,**self.kwargs)

class RecapTimer(wx.Timer):
    "This timer tells the curent lowest level menu to recapture the mouse, along with it's parent tree "
    def __init__(self,target):
        wx.Timer.__init__(self)
        self.target=target
        self.Start(10)

    def Notify(self):

        target = self.target
        mp = target.Parent.ScreenToClient(wx.GetMousePosition())

        if (not target.Rect.Contains(mp) or target.ClientRect.Contains(mp)) and not wx.GetMouseState().LeftDown():
            self.Stop(target)

    def Stop(self,target):
        wx.Timer.Stop(self)
        target.Parent.CascadeCapture()
        del target.recaptimer

class SimpleMenuSpine(wx.VListBox, UberWidget):
    'This is the list handler for the menu.'

    def __init__(self, parent, skin):
        'Generic constructor'

        wx.VListBox.__init__(self,parent)
        UberWidget.__init__(self,'LISTBOX')

        self.MinSize = wx.Size(1, 1) #fix for small menus

        events = [
            (wx.EVT_PAINT,       self.OnPaint),
            (wx.EVT_MOUSEWHEEL,  self.OnMouseWheel),
            (wx.EVT_MOTION,      self.OnMouseMove),
            (wx.EVT_LEFT_UP,     self.OnLUp),
            (wx.EVT_LEFT_DOWN,   self.OnLDown),
            (wx.EVT_RIGHT_DOWN,  self.OnLDown),
            (wx.EVT_MIDDLE_DOWN, self.OnLDown),
            (wx.EVT_LEFT_DCLICK, lambda e:None),
            (wx.EVT_SCROLLWIN,   self.OnScroll),
            (wx.EVT_MOUSE_CAPTURE_LOST, self.OnMouseCaptureLost)
        ]
        do(self.Bind(event, method) for (event, method) in events)

        #TODO: soft code this
        self.itemheight = 20

        self.items = []
        self.ItemCount = len(self.items)

        self.SetSkinKey(skin,True)

    def OnMouseCaptureLost(self, e):
        self.Parent.CloseRoot()

    def UpdateSkin(self):
        key = self.skinkey

        self.native = native = not key
        if native:
            self.OpenNativeTheme()

            self.padding = wx.Point(2,2)

            self.framesize  = Margins([1,1,1,1])#[0,0,0,0] if uxthemed else

            sz = self.Parent.Sizer
            if sz:
                sz.Detach(1)
                sz.Detach(1)
                sz.Add(wx.Size(self.framesize.left,self.framesize.top),(0,0))
                sz.Add(wx.Size(self.framesize.right,self.framesize.bottom),(2,2))

            self.framebg = None
            self.menubg  = None
            self.itembg  = None
            self.selbg   = None

            self.Font    = default_font()

            self.normalfc = wx.SystemSettings_GetColour(wx.SYS_COLOUR_WINDOWTEXT)
            self.selfc    = wx.SystemSettings_GetColour(wx.SYS_COLOUR_HIGHLIGHTTEXT)

            self.MakeNativeSubmenuIcons()

            self.separator   = None

        else:

            self.CloseNativeTheme()

            s = lambda k, default: skin.get('%s.%s' % (key,k), default)

            self.padding = s('padding', wx.Point(2,2))

            self.framesize  = s('framesize',Margins([0,0,0,0]))

            sz = self.Parent.Sizer
            if sz:
                sz.Detach(1)
                sz.Detach(1)
                sz.Add(wx.Size(self.framesize.left,self.framesize.top),(0,0))
                sz.Add(wx.Size(self.framesize.right,self.framesize.bottom),(2,2))

            self.framebg = s('frame', lambda: SkinColor(wx.BLACK))
            self.menubg  = s('backgrounds.menu',  None)
            self.itembg  = s('backgrounds.item',  None)
            self.selbg   = s('backgrounds.selection', None)

            self.Font    = s('font', default_font())

            self.normalfc = s('fontcolors.normal',    lambda: wx.BLACK)
            self.selfc    = s('fontcolors.selection', lambda: wx.BLACK)

            #TODO: Default?
            submenuicon = self.submenuicon = s('submenuicon', None)
            if submenuicon is None:
                self.MakeNativeSubmenuIcons()
            else:
                self.submenuiconhot = s('submenuiconhover', submenuicon)

            #TODO: Default?
            self.separator   = s('separatorimage',None)

        for item in self.items:
            if item.menu:
                item.menu.spine.SetSkinKey(key)

    def MakeNativeSubmenuIcons(self):
        arrowmask = wx.EmptyBitmap(10,10)
        mdc = wx.MemoryDC()
        mdc.SelectObject(arrowmask)

        from gui.windowfx import controls
        arect = wx.Rect(0,0,10,10)
        DrawSubMenuArrow(mdc,arect)
        mdc.SelectObject(wx.NullBitmap)

        mdc2 = wx.MemoryDC()
        for s in xrange(2):
            acolor = self.selfc if s else self.normalfc
            arrow = wx.EmptyBitmap(10,10)
            arrow.SetMask(wx.Mask(arrowmask,wx.WHITE))
            mdc2.SelectObject(arrow)
            mdc2.Brush = wx.Brush(acolor)
            mdc2.FloodFill(0,0,wx.BLACK)
            mdc2.SelectObject(wx.NullBitmap)
            if s:
                self.submenuiconhot = arrow
            else:
                self.submenuicon = arrow#wx.Mask(arrowmask,wx.WHITE)#

    def DrawNativeBackgroundFallback(self,dc,part,state,unusedrect):

        rect = wx.RectS(self.Size)

        dc.Brush = Brush(wx.SystemSettings_GetColour(wx.SYS_COLOUR_WINDOW))
        dc.Pen   = wx.TRANSPARENT_PEN#wx.Pen(wx.SystemSettings_GetColour(wx.SYS_COLOUR_WINDOWFRAME))
        dc.DrawRectangleRect(rect)

    def OnPaint(self,event):
        'Standard paint handling.'

        dc   = wx.AutoBufferedPaintDC(self)
        rect = wx.RectS(self.ClientSize)

        if self.menubg:
            self.menubg.Draw(dc, rect)
        else:
            dc.SetClippingRect(rect)
            nrect = wx.Rect(*rect)
            nrect.Inflate(1, 1)#wx.RectPS((-self.Rect.x,-self.Rect.y),self.Size)
            self.DrawNativeLike(dc,0,0,nrect,self.DrawNativeBackgroundFallback)
            dc.DestroyClippingRegion()

#            dc.Brush = wx.RED_BRUSH
#            dc.Pen = wx.TRANSPARENT_PEN
#            dc.DrawRectangleRect(rect)

        rect.Height = self.itemheight

        i, j = self.FirstVisibleLine, self.LastVisibleLine
        if j >= 0 and j != sys.maxint*2+1:
            bg, draw, measure = self.OnDrawBackground, self.OnDrawItem, self.OnMeasureItem
            for n in xrange(i, j + 1):
                bg(dc, rect, n)
                draw(dc, rect, n)
                rect.SetY(rect.GetY() + measure(n))

#    def DrawThemelessItemBG(self,dc,part,state,rect):
#
#        if state == 2:
#            dc.Brush = wx.Brush(wx.SystemSettings_GetColour(wx.SYS_COLOUR_HIGHLIGHT))
#            dc.Pen = wx.TRANSPARENT_PEN
#            dc.DrawRectangleRect(rect)

    def OnDrawBackground(self,dc,rect,n):
        'Draws the background for each item.'

        if self.native:
            if self.GetSelection() == n:
                dc.Brush = wx.Brush(wx.SystemSettings_GetColour(wx.SYS_COLOUR_HIGHLIGHT))
                dc.Pen = wx.TRANSPARENT_PEN
                dc.DrawRectangleRect(rect)
#            s = 3 if self.GetSelection() == n else 1
#                self.DrawNativeLike(dc,5,1,rect,self.DrawThemelessItemBG)
        else:
            if self.GetSelection() == n and self.selbg:
                self.selbg.Draw(dc, rect)
            elif self.itembg:
                self.itembg.Draw(dc, rect)

    def OnDrawItem(self,dc,rect,n):
        'Draws the foreground of each item.'

        curser  = Point(rect.x, rect.y) + (self.padding.x, 0)

        if self.items[n].id==-1:
            return self.DrawSeparator(dc, rect, n)

        if self.items[n].font:
            font = self.items[n].font
        else:
            font = self.Font

        dc.Font=font
        dc.TextForeground=(self.selfc if self.Selection==n else self.normalfc)

        if self.items[n].menu:
            dc.Brush=wx.BLACK_BRUSH
            dc.Pen=wx.TRANSPARENT_PEN
            smi=self.submenuiconhot if self.Selection==n else self.submenuicon

#            if isinstance(smi,wx.Mask):
#                acolor = self.selfc if self.Selection==n else self.normalfc
#                arrow = wx.EmptyBitmap(10,10)
#                arrow.SetMask(smi)
#                mdc2 = wx.MemoryDC()
#                mdc2.SelectObject(arrow)
#                mdc2.Brush = wx.Brush(acolor)
#                mdc2.FloodFill(0,0,wx.BLACK)
#                mdc2.SelectObject(wx.NullBitmap)
#                dc.DrawBitmap(arrow,rect.Width-self.padding.x-arrow.Width,rect.Y+(rect.Height/2)-arrow.Height/2,True)
#                endcap=arrow.Width+self.padding.x
#            else:
            dc.DrawBitmap(smi,rect.Width-self.padding.x-smi.Width,rect.Y+(rect.Height/2)-smi.Height/2,True)
            endcap=smi.Width+self.padding.x
        else:
            endcap=0

        padx   = self.padding.x
        txtext = dc.Font.Height
        txtext_pad = Point(txtext + padx, 0)

        for i in self.items[n].content:
            if type(i) is Bitmap:
                curser.y = rect.Y + (rect.height / 2 - i.Height / 2)
                imgpad = (self.bitmapwidth - i.Width)//2 if self.bitmapwidth else 0
                try:
                    dc.DrawBitmapPoint(i, (curser.x + imgpad, curser.y), True)
                except Exception:
                    traceback.print_exc_once()
                    try:
                        log.error("Failed drawing bitmap: %r", getattr(i, 'path', None))
                    except Exception:
                        pass
                curser += Point(max(self.bitmapwidth, i.Width) + padx, 0)
            elif isinstance(i, basestring):
                curser.y = rect.Y + (rect.height / 2 - txtext / 2)
                text_rect = RectPS(curser, Size(rect.width - curser.x - padx - endcap, txtext))
                dc.DrawTruncatedText(i, text_rect, alignment = wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL)
                curser += txtext_pad

    def DrawSeparator(self, dc, rect, n):
        sepwidth  = rect.width - self.padding.x * 2

        if self.separator:
            sepheight = self.separator.Size.height
            seppos    = (self.padding.x, rect.y + rect.height // 2 - sepheight // 2)
            self.separator.Draw(dc, RectPS(seppos, (sepwidth, sepheight)))
        else:
            dc.Pen = Pen(self.normalfc, 1)
            seppos   = Point(self.padding.x, rect.y + rect.height // 2)
            endpos   = seppos + Point(sepwidth, 0)
            dc.DrawLinePoint(seppos, endpos)

    def OnMouseWheel(self, e):
        self.ScrollLines(-math.copysign(1, e.WheelRotation))

    def OnMouseMove(self,event):
        'Mouse over event handling.'

        mp    = self.ScreenToClient(GetMousePosition())
        items = self.items

        if self.ClientRect.Contains(mp):
            n = self.HitTest(mp)
            if self.Selection != n:
                do(item.menu.Show(False) for item in self.items if item.menu and item.menu.IsShown())
                if items[n].id != -1:
                    self.SetSelection(n)
                    if items[n].menu:
                        items[n].menu.DelayedDisplay(self.GetItemRect(n), self)
                else:
                    self.SetSelection(-1)
        elif self.Rect.Contains(mp):
            self.Parent.CascadeRelease()
            self.recaptimer = RecapTimer(self)
        else:
            self.SetSelection(-1)
            gp = self.GrandParent
            if isinstance(gp, SimpleMenu) and gp.CheckParentalContact(GetMousePosition()):
                gp.spine.AddPendingEvent(event)

    def OnLUp(self,event):
        """
        Release left mouse button handling
        """
        if self.GetClientRect().Contains(event.Position):
            n = self.HitTest(event.Position)
            if self.items[n].id != -1:
                item = self.items[n]
                if not item.menu:
                    self.TriggerItem(item)

    def TriggerItem(self,item):
        'Steps to take when a item is clicked.'

        if item.method is not None:
            wx.CallAfter(item.method, item)
        elif self.Parent.callback:
            wx.CallAfter(self.Parent.callback, item)
        else:
            menuevent = MenuEvent(wx.wxEVT_COMMAND_MENU_SELECTED, item.id)
            self.Parent.AddPendingEvent(menuevent)
        self.Parent.CloseRoot()

    def OnLDown(self,event):
        """
        Mouse down handling
        """
        if not self.Rect.Contains(event.Position) and not self.Parent.CheckParentalContact(wx.GetMousePosition(),True):
            self.Parent.CloseRoot()

    def OnScroll(self,event):
        'What to do when the window is scrolled.'

        self.Refresh()
        event.Skip()

    def CalcSize(self):
        'Calculates the size of the menu.'

        self.CalcItemHeight()
        if self.Parent.staticwidth:
            width = self.Parent.width
        else:
            self.CalcItemWidth()
            width = self.calcedwidth

        if not self.Parent.maxheight or self.ItemCount<self.Parent.maxheight:
            height = self.itemheight * self.ItemCount
        else:
            height = self.itemheight * self.Parent.maxheight

        maxwidth = self.Parent.maxwidth
        if maxwidth and width > maxwidth:
            width = maxwidth

        minwidth = self.Parent.minwidth
        if minwidth and width < minwidth:
            width = minwidth

        p = self.Parent.ScreenRect[:2]
#        self.MinSize = wx.Size(self.menuwidth-self.framesize.x, height)
        self.Parent.Rect = RectPS(p, wx.Size(width, height+self.framesize.y))
        #self.Parent.Size = (self.menuwidth+self.framesize.x, height+self.framesize.y)

    def CalcItemHeight(self):
        'Calculates tallest item.'
#        print 'SimpleMenu CalcItemHeight being ran too much, this is a reminder to create a simpler version for individual changes'

        hset = list(item.font.Height for item in self.items if item.font)
        hset.append(self.Font.Height)

        if max(hset)-min(hset)>10:

            hset = sorted(hset)
            lhset = len(hset)

            def Median(set):
                lset = len(set)
                if lset % 2:
                    m1=lset//2
                    m2=m1+1
                    return set[m1] + ((set[m2] - set[m1])//2)
                else:
                    return set[lset//2+1]

            q1      = Median(hset[:lhset//2])
            q3      = Median(hset[(lhset//2)+1:])
            iqr     = q3 - q1
            hi      = q3 + 1.5*iqr

            hset = set(h for h in hset if h < hi)

        self.bitmapwidth = bitmapwidth = 0
        for item in self.items:
            if item.id == -1:
                pass
            elif item.content and isinstance(item.content[0], Bitmap):
                bitmapwidth = max(bitmapwidth, item.content[0].Width)

            for object in item.content:
                if type(object) is Bitmap:
                    hset.append(object.Height)

        # keep track of the biggest bitmap on the left to align plain text
        # items
        if bitmapwidth:
            empty_bitmap = wx.EmptyBitmap(bitmapwidth, 1)
            for item in self.items:
                if item.id == -1:
                    pass
                elif item.content and isinstance(item.content[0], basestring):
                    item.content.insert(0, empty_bitmap)
            self.bitmapwidth = bitmapwidth

        h=max(hset)

#HACK: The following section of code is a hax to remove all fonts with extreme sizes
#-------------------------------------------------------------------------------
        for item in self.items:
            if item.font and item.font.Height>h:
                self.items.remove(item)
        self.ItemCount = len(self.items)
#-------------------------------------------------------------------------------

        self.itemheight = h+2*self.padding.y

    def CalcItemWidth(self):
        if not self.items:
            self.calcedwidth=0
        else:
            wset = set(item.GetContentWidth(self.Parent) for item in self.items)#set(GetTextWidth(item.GetContentAsString(),item.font or self.Font)+len(item.content)*self.padding.x for item in self.items)
            w = max(wset)
            w += self.framesize.x

            self.calcedwidth = w

    def OnMeasureItem( self, n ):
        'Returns item height.'

        return self.itemheight

    def GetSelectionRect(self):
        return self.GetItemRect(self.Selection)

    def GetItemRect(self,n):
        pos = self.ScreenRect.Position

        x = pos.x
        width= self.Size.x
        y = pos.y + sum(self.OnMeasureItem(i) for i in xrange(n))

        height=self.OnMeasureItem(n)

        return Rect(x,y,width,height)

class SimpleMenu(wx.PopupTransientWindow, UberWidget):
    '''
    This is the class for most menus throughout the codebase
    The use of this class should be deprecated and replaced by new menus based off the menu code located in gui.prototypes
    '''

    def __init__(self, parent, skinkey = 'simplemenu', maxheight = None, width = 0, minwidth = 0, maxwidth=0, callback = None):
        """
        items - Initial items - cut - was never used
        """

        wx.PopupTransientWindow.__init__(self, parent)

        self.BeforeDisplay = Delegate()
        Bind = self.Bind
        Bind(wx.EVT_PAINT,  self.OnPaint)
        Bind(wx.EVT_SIZE,   self.OnSize)
        Bind(wx.EVT_SHOW,   self.OnClose)
        Bind(wx.EVT_MENU,   self.PassEvent)

        self.maxheight = maxheight

        self.staticwidth = bool(width)
        self.width  = width

        self.maxwidth = maxwidth
        self.minwidth = minwidth

        self.spine = SimpleMenuSpine(self,skinkey)
        self.displaytimer=SMDTimer(self)

        s = self.Sizer = wx.GridBagSizer()
        s.SetEmptyCellSize(wx.Size(0, 0))
        s.Add(self.spine,(1, 1), flag = wx.EXPAND)
        s.Add(wx.Size(self.spine.framesize.left,self.spine.framesize.top),(0,0))
        s.Add(wx.Size(self.spine.framesize.right,self.spine.framesize.bottom),(2,2))
        s.AddGrowableCol(1, 1)
        s.AddGrowableRow(1, 1)

        self.callback = callback

        self.connected=None

    def SetSkinKey(self, key):
        """shortcut to spine.updateskin"""
        self.spine.SetSkinKey(key)

    def SetWidth(self,width):
        """Set the width of the menu in pixels"""

        self.staticwidth = True

        w=width

        if self.minwidth:
            w = max(w,self.minwidth)

        if self.maxwidth:
            w = min(w,self.maxwidth)

        self.width = w
        self.Size  = wx.Size(w,-1)

    def OnSize(self, event):
        event.Skip()

#        if hasattr(self.spine,'framebg'):
        background= self.spine.framebg
        from cgui import SplitImage4
        if isinstance(background,SplitImage4):
            ApplySmokeAndMirrors(self, background.GetBitmap(self.Size))
        else:
            ApplySmokeAndMirrors(self)

        self.Layout()

    def OnPaint(self,event):
        """Draws the background of the menu"""
        dc   = wx.PaintDC(self)
        rect = wx.RectS(self.Size)

        bg = self.spine.framebg
        if bg:
            bg.Draw(dc, rect)
        elif self.spine.native:
            dc.Brush = wx.TRANSPARENT_BRUSH
            dc.Pen = wx.Pen(wx.SystemSettings_GetColour(wx.SYS_COLOUR_WINDOWFRAME))
            dc.DrawRectangleRect(rect)

            #self.DrawNativeLike(dc,0,0,rect)

    def GetIndex(self, item):
        try:
            return self.spine.items.index(item)
        except ValueError:
            return -1

    def Insert(self, index, *args, **kwargs):
        'Insert a new item into the menu.'

        self.InsertItem(index, SimpleMenuItem(*args, **kwargs))

    def Append(self, *args, **kwargs):
        'Appends a new item to the end of the menu.'

        self.AppendItem(SimpleMenuItem(*args, **kwargs))

    def InsertItem(self, index, item):
        'Insert an item to an index.'

        self.spine.items.insert(index,item)
        self.spine.ItemCount=len(self.spine.items)

    def AppendItem(self, item):
        'Adds an item to the end of the menu.'

        self.spine.items.append(item)
        self.spine.ItemCount = len(self.spine.items)

    def RemoveItem(self, item):
        'Remove the item provided from the menu.'

        sp = self.spine

        if isinstance(item, int):
            item = sp.items[item]

        sp.Selection=-1
        sp.items.remove(item)
        sp.ItemCount = len(self.spine.items)

    def RemoveAll(self):
        """
        removes all items from the menu
        """
        self.spine.items=[]
        self.spine.ItemCount=len(self.spine.items)

    def GetCount(self):
        'Returns the number of items in the menu.'

        return len(self.spine.items)

    Count = property(GetCount)

    __len__ = GetCount

    def SetSelection(self, selection): self.spine.Selection = selection
    def GetSelection(self): return self.spine.Selection

    Selection = property(GetSelection, SetSelection)

    def SetItems(self, items):
        'Set the menu to a list of items.'

        if wx.IsDestroyed(self):
            print >> sys.stderr, "WARNING: %r is destroyed" % self
            return

        with self.Frozen():

            sp = self.spine

            sp.items = items
            sp.ItemCount = len(items)

            if sp.IsShownOnScreen():
                sp.RefreshAll()

    def GetItem(self, index):
        return self.spine.items[index]

    def GetItems(self):
        return self.spine.items

    def GetItemIndex(self, item):
        return self.spine.items.index(item)

    def FindItemById(self, id):
        '''Returns a SimpleMenuItem with a matching id, or None.'''
        for item in self.spine.items:
            if item.id == id:
                return item

    def PassEvent(self,event):
        """
        A shortcut to self.Parent.AddPendingEvent(event) (Why?)
        """
        self.Parent.AddPendingEvent(event)

    def DelayedDisplay(self, rect, *args, **kwargs):
        if not self.displaytimer.IsRunning():
            self.displaytimer.Start(rect, *args, **kwargs)

    def Display(self, caller = None, funnle = True,funnlefullscreen=False):
        """
        Display the menu
        """

        self.BeforeDisplay()

        if not self.IsShown() and len(self):

            self.spine.CalcSize()

            if caller and isinstance(caller, SimpleMenuSpine):

                self.caller = None
                rect = caller.GetSelectionRect()

                position = Point(rect.x+rect.width,rect.y - self.spine.framesize.top)
                newrect  = RectPS(position, self.ScreenRect.Size)
                screenrect = Monitor.GetFromRect(newrect).Geometry

                if newrect.bottom > screenrect.bottom:
                    position.y=rect.y+rect.height-self.Size.height
                if newrect.right > screenrect.right:
                    position.x=rect.x-self.Size.width

            elif caller:
                self.caller = caller
                caller_rect = caller.ScreenRect
                position    = caller_rect.BottomLeft
                newrect     = RectPS(position, self.ScreenRect.Size)
                screenrect  = Monitor.GetFromWindow(caller).Geometry

                if newrect.bottom > screenrect.bottom:
                    position.y -= caller_rect.Height + self.spine.Size.height
                if newrect.right > screenrect.right:
                    position.x += caller_rect.Width - self.spine.Size.width

            else:
                self.caller = None
                position    = wx.GetMousePosition()
                newrect     = RectPS(position, self.ScreenRect.Size)
                screenrect  = Monitor.GetFromPoint(position).Geometry

                if newrect.bottom > screenrect.bottom:
                    position.y -= self.spine.Size.height
                if newrect.right > screenrect.right and pref('menus.shift_mode', False):
                    position.x -= self.spine.Size.width

            newrect = wx.RectPS(position,self.Size)
            screenrect = Monitor.GetFromRect(newrect).Geometry
            pos = screenrect.Clamp(newrect).Position if funnle else position
            self.SetRect(RectPS(pos, self.Size))

            self.spine.SetSelection(-1)

            fadein(self, 'xfast')
            self.spine.RefreshAll()

            if not self.spine.HasCapture():
                self.spine.CaptureMouse()

            wx.CallLater(10, self.Refresh)

            if not isinstance(caller, SimpleMenuSpine):
                self.TopConnect()

    def TopConnect(self):
        # Find the first TopLevelWindow owner of this menu
        # (popup menus are not isinstance(popup, wx.TopLevelWindow)
        t = self.Top
        while not isinstance(t, wx.TopLevelWindow):
            t = t.Parent.Top

        id = t.Id
        t.Connect(id, id, wx.wxEVT_ACTIVATE, self.OnActiveChange)
        self.connected=(t,id)

    def OnActiveChange(self,event):
        self.CloseRoot()

    def OnClose(self,event):
        """
        Handels hiding of submenus and deactivating caller if aplicable
        when the menu is closed
        """

        if not self.IsShown():
            do(item.menu.Show(False) for item in self.spine.items if item.menu and item.menu.IsShown())
            while self.spine.HasCapture():self.spine.ReleaseMouse()

            if self.caller:# and hasattr(self.caller,'Active'):
                event=wx.MenuEvent(wx.wxEVT_MENU_CLOSE,self.Id)
                self.caller.AddPendingEvent(event)
                self.caller = None

            if self.connected:
                window, id = self.connected
                window.Disconnect(id, id, wx.wxEVT_ACTIVATE)
                self.connected = None

    def CloseRoot(self):
        """
        Closes the root menu, that then handles closing of it's children
        """
        if isinstance(self.Parent,SimpleMenu):
            self.Parent.CloseRoot()
        else:
            self.Show(False)

    def __repr__(self):
        return '<SimpleMenu %r>' % self.spine.items

    def CheckParentalContact(self,pos,ignoresubmenu=False):
        """
        Checks if the mouse is inside one of the parent menus of this menu
        """
        rect = RectS(self.spine.Size)
        mp=self.spine.ScreenToClient(pos)
        if rect.Contains(mp) and (ignoresubmenu or not self.spine.items[self.spine.HitTest(mp)].menu or not self.spine.items[self.spine.HitTest(mp)].menu.IsShown()):
            return True
        if isinstance(self.Parent, SimpleMenu):
            return self.Parent.CheckParentalContact(pos, ignoresubmenu)
        return False

    def CascadeRelease(self):
        """
        All menus in hierarchy release the mouse
        """
        while self.spine.HasCapture():
            self.spine.ReleaseMouse()
        if isinstance(self.Parent,SimpleMenu):
            self.Parent.CascadeRelease()

    def CascadeCapture(self):
        """
        All menus in hierarchy capture the mouse
        """
        if isinstance(self.Parent,SimpleMenu):
            self.Parent.CascadeCapture()
        if not self.spine.HasCapture():
            self.spine.CaptureMouse()

class SimpleMenuItem(object):
    "Menu Item for the combo box"

    def __init__(self, content = '', method = None,
                 font = None, id = None, menu = None):
        """
        content - string or list of bitmaps and strings that are displayed as item lable
        method - methode exicuted when the item is slected
        id - unique ID number for the item, if left none is not generated, so
            if you need an id set it
        """

        assert isinstance(content,(basestring,list,)), 'content of type %s is not a string or list' % type(content)

        if content is not None:
            if isinstance(content, basestring):    # For strings, wrap in a list
                self.content = [content]
            elif isinstance(content,list):
                self.content = content
            else:
                raise TypeError
        else: self.content = []
        self.method = method
        self.menu   = menu
        self.font   = font

        self.id=id

    def __repr__(self):
        return '<SMItem %s>' % self.GetContentAsString()

    def __str__(self):
        return self.GetContentAsString()

    def __eq__(self, o):
        return isinstance(o, self.__class__) and self.content == o.content

    def __ne__(self, other):
        return not self.__eq__(other)

    def __hash__(self):
        return hash(id(self))

    def GetContentAsString(self):
        "Returns first string in this menu item's content, or an empty string."

        for thing in self.content:
            if isinstance(thing, basestring):
                return thing

        return ''

    def GetContentWidth(self,menu):
        if not menu:
            return None

        pad = menu.spine.padding
        font = self.font or menu.spine.Font
        cont = self.content

        count = len(cont)

        w = sum(GetTextWidth(s,font) for s in cont if isinstance(s,basestring))
        w += sum(b.Width for b in cont if type(b) is Bitmap)

        w += (count+1)*pad.x+1

        return w

    def SetLabel(self, label):
        '''Changes the first string item in self.content to the given label.'''

        for i, item in enumerate(self.content):
            if isinstance(item, basestring):
                self.content[i] = label
                return


# K-Means Clustering

# Importing the libraries
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd

# Importing the dataset
dataset = pd.read_csv('Mall_Customers.csv')
X = dataset.iloc[:, [3, 4]].values

# Using the elbow method to find the optimal number of clusters
from sklearn.cluster import KMeans
wcss = []

for i in range(1, 11):
    # Choose k from 1 to 10
    kmeans = KMeans(n_clusters = i, init = 'k-means++', max_iter = 300, random_state = 42)
    # 'k-means++' is a more powerful method than 'random'
    # max_iter: Maximum # of iterations of the k-means algorithm for a single run
    kmeans.fit(X)
    wcss.append(kmeans.inertia_)
    # .inertia_ automatically compute the WCSS

plt.plot(range(1, 11), wcss)
plt.title('The Elbow Method')
plt.xlabel('Number of clusters')
plt.ylabel('WCSS')
plt.show()
# After running this, we can choose k=5

# Fitting K-Means to the dataset
kmeans = KMeans(n_clusters = 5, init = 'k-means++', random_state = 42)
y_kmeans = kmeans.fit_predict(X)
# y_kmeans have 5 values which are 0 to 4, and it shows 5 classes of X dataset

# Visualising the clusters

# scatter(x,y,s,c,marker,cmap,norm,vmin,vmax,alpha,linewidths,verts,edgecolors,hold,data)
# x: first column, y: second column...
# s: visualize 100 points is fine in this plot. You can change the number to view.
plt.scatter(X[y_kmeans == 0, 0], X[y_kmeans == 0, 1], s = 100, c = 'red', label = 'Cluster 1')
plt.scatter(X[y_kmeans == 1, 0], X[y_kmeans == 1, 1], s = 100, c = 'blue', label = 'Cluster 2')
plt.scatter(X[y_kmeans == 2, 0], X[y_kmeans == 2, 1], s = 100, c = 'green', label = 'Cluster 3')
plt.scatter(X[y_kmeans == 3, 0], X[y_kmeans == 3, 1], s = 100, c = 'cyan', label = 'Cluster 4')
plt.scatter(X[y_kmeans == 4, 0], X[y_kmeans == 4, 1], s = 100, c = 'magenta', label = 'Cluster 5')

plt.scatter(kmeans.cluster_centers_[:, 0], kmeans.cluster_centers_[:, 1], s = 300, c = 'yellow', label = 'Centroids')

plt.title('Clusters of customers')
plt.xlabel('Annual Income (k$)')
plt.ylabel('Spending Score (1-100)')
plt.legend()
# plt.legend() creates the side window in the plot showing points corresponding with labels.
plt.show()

Machine Learning A-Z Template Folder/Part 4 - Clustering/Section 24 - K-Means Clustering/K_Means/kmeans.py


from django.urls import path
from django.views.generic import RedirectView
from rest_framework.routers import DefaultRouter

from mailing import views

app_name = 'mailing'

urlpatterns = [
    path('', RedirectView.as_view(url='/backend/docs/')),
    path(
        'admin/login/',
        views.CustomLoginView.as_view(),
        name='custom_admin_login'
    ),
]

router = DefaultRouter()
router.register('mailings', views.MailingViewSet, basename='mailings')
router.register('clients', views.ClientViewSet, basename='clients')
router.register(
    'mobile_operators', views.MobileOperatorViewSet,
    basename='mobile_operators'
)
router.register('tags', views.TagViewSet, basename='tags')

urlpatterns += router.urls


"""empty message

Revision ID: 32d423c8abbe
Revises: cfc8c12e45e3
Create Date: 2020-08-24 15:32:00.758205

"""
from alembic import op
import sqlalchemy as sa
from sqlalchemy.dialects import mysql

# revision identifiers, used by Alembic.
revision = '32d423c8abbe'
down_revision = 'cfc8c12e45e3'
branch_labels = None
depends_on = None

def upgrade():
    # ### commands auto generated by Alembic - please adjust! ###
    op.add_column('user', sa.Column('available', sa.Boolean(), nullable=True))
    op.alter_column('user_subjects', 'user_selected',
               existing_type=mysql.TINYINT(display_width=1),
               nullable=True)
    # ### end Alembic commands ###

def downgrade():
    # ### commands auto generated by Alembic - please adjust! ###
    op.alter_column('user_subjects', 'user_selected',
               existing_type=mysql.TINYINT(display_width=1),
               nullable=False)
    op.drop_column('user', 'available')
    # ### end Alembic commands ###


class SmartHomeMediator:
    def __init__(self):
        self.components = {}

    def register_component(self, component_name, component):
        self.components[component_name] = component

    def send_command(self, component_name, command):
        if component_name in self.components:
            self.components[component_name].execute_command(command)
        else:
            print(f"Component '{component_name}' not found.")

    def get_component_state(self, component_name):
        if component_name in self.components:
            return self.components[component_name].get_state()
        else:
            print(f"Component '{component_name}' not found.")
            return None

class SmartComponent:
    def __init__(self, name, mediator):
        self.name = name
        self.mediator = mediator
        self.state = "OFF"

    def execute_command(self, command):
        pass

    def get_state(self):
        return self.state

class LightComponent(SmartComponent):
    def execute_command(self, command):
        if command == "ON":
            self.state = "ON"
            print(f"Light '{self.name}' turned ON.")
        elif command == "OFF":
            self.state = "OFF"
            print(f"Light '{self.name}' turned OFF.")

class ACComponent(SmartComponent):
    def execute_command(self, command):
        if command == "ON":
            self.state = "ON"
            print(f"AC '{self.name}' turned ON.")
        elif command == "OFF":
            self.state = "OFF"
            print(f"AC '{self.name}' turned OFF.")
        elif command.startswith("SET_TEMP"):
            temperature = command.split(":")[1]    # startswith("SET_TEMP:22")
            self.state = f"ON (Temperature: {temperature})"
            print(f"AC '{self.name}' set to {temperature}°C.")

#usage
mediator = SmartHomeMediator()

light = LightComponent("Living Room Light", mediator)
ac = ACComponent("Bedroom AC", mediator)

mediator.register_component("light", light)
mediator.register_component("ac", ac)

mediator.send_command("light", "ON")
mediator.send_command("ac", "ON")
mediator.send_command("ac", "SET_TEMP:22")
mediator.send_command("light", "OFF")

print()

print(mediator.get_component_state("light"))
print(mediator.get_component_state("ac"))
print(mediator.get_component_state("fan"))

03- Behavioral DP/05- Mediator/04_exercise04_real_world_smart_home_automation_system.py


import matplotlib.pyplot as plt

# Dados de exemplo
amostra = [
    ['Módulo 1', 32, 1.66, 65],
    ['Módulo 1', 18, 1.74, 80],
    ['Módulo 1', 19, 1.76, 60],
    ['Módulo 2', 30, 1.84, 90],
    ['Módulo 2', 33, 1.81, 94],
    ['Módulo 3', 30, 1.74, 75],
    ['Módulo 4', 21, 1.83, 110],
    ['Módulo 5', 26, 1.74, 64]
]

# Separar as variáveis "altura", "peso", "módulo" e "idade"
altura = [amostra[i][3] for i in range(len(amostra))]
idades = [amostra[i][1] for i in range(len(amostra))]

# Criar o gráfico de dispersão com o eixo x representando o módulo e o eixo y representando a idade
plt.scatter(altura, idades)

# Personalizar os rótulos dos eixos x e y e adicionar um título
plt.xlabel('peso')
plt.ylabel('Idade')
plt.title('Gráfico de Dispersão para a Variável Idade em Função do Módulo')

# Exibir o gráfico
plt.show()


from torch.optim import lr_scheduler

class SchedulerManager:
    @staticmethod
    def build_scheduler(optimizer, cfg):
        """
        Return a learning rate scheduler
            For 'linear', we keep the same learning rate for the first <cfg.niter_warmup> epochs
        and linearly decay the rate to zero over the next <cfg.niter_decay> epochs.
        For other schedulers (step, plateau, and cosine), we use the default PyTorch schedulers.
        See https://pytorch.org/docs/stable/optim.html for more details.
        Args:
            optimizer (torch.optim): the optimizer of the network
            cfg: cfg.lr_decay_method is the name of the decay method of learning rate: linear | step | plateau | cosine
        return: scheduler
        """
        if cfg.lr_decay_method == "step":
            scheduler = lr_scheduler.StepLR(optimizer, step_size=cfg.lr_decay_niters, gamma=cfg.gama)
        elif cfg.lr_decay_method == "plateau":
            scheduler = lr_scheduler.ReduceLROnPlateau(optimizer, mode="min", factor=0.2, threshold=0.01, patience=5)
        elif cfg.lr_decay_method == "cosine":
            scheduler = lr_scheduler.CosineAnnealingLR(optimizer, T_max=cfg.max_iter, eta_min=0)
        else:
            raise NotImplementedError("lr_decay_method '{}' is not implemented".format(cfg.lr_decay_method))


import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from matplotlib import gridspec

import tensorflow as tf
# import tensorflow_probability as tfp

# conda install -c conda-forge bayesian-optimization
from bayes_opt import BayesianOptimization, UtilityFunction

# from IPython.display import clear_output
# import time

# Baysian Optimization : Exploitation / Exploration
def target(x):      # real_function
    return np.exp(-(x-2)**2) + np.exp(-(x-6)**2/10) + 1 / (x**2+1)

x_lp = np.linspace(-2, 10, 10000).reshape(-1,1)
y_lp = target(x_lp)

plt.plot(x_lp, y_lp)
plt.show()

# x_lp[np.argmax(y_lp)]

bayes_opt = BayesianOptimization(f=target, pbounds={'x': (-2,10)}, random_state=27)
# ?BayesianOptimization
# BayesianOptimization(f, pbounds, random_state=None, verbose=2)

bayes_opt.maximize(init_points=2, n_iter=12, acq='ucb', kappa=5)
# acq: acquisition_function('ucb...')이 내부적으로 돌아가서 최대가 되는 지점을 찾아줌
# kappa: Exploration 정도 지정      # ucb = mean + kappa * std
    # kappa ↑ → Exploration에 집중하겠다
# ?BayesianOptimization.maximize
# bayes_opt.maximize(
#     init_points=5,
#     n_iter=25,
#     acq='ucb',
#     kappa=2.576,
#     xi=0.0,
#     **gp_params,
# )

# dir(bayes_opt)
bayes_opt.max           # max_point (best_case)
bayes_opt._gp           # setting parameter
bayes_opt.res           # history
len(bayes_opt.space)    # iter횟수

x_res = np.array([res['params']['x'] for res in bayes_opt.res])
y_res = np.array([res['target'] for res in bayes_opt.res])

plt.plot(x_lp, y_lp, label='target')
plt.plot(x_res, y_res, 'r--', marker='D', alpha=0.5, label='Observations')
plt.show()

fitted = bayes_opt._gp.fit(x_res[...,np.newaxis], y_res)
fitted
bayes_opt._gp.predict(x_lp, return_std=True)

def posterior(optimizer, x_obs, y_obs, grid):
    optimizer._gp.fit(x_obs, y_obs)

    mu, sigma = optimizer._gp.predict(grid, return_std=True)
    return mu, sigma

def plot_gp(optimizer, x, y):
    fig = plt.figure(figsize=(16, 10))
    steps = len(optimizer.space)    # 현재 몇번 iteration 했는지?
    fig.suptitle(f'Gaussian Process and Utility Function After {steps} steps')

    gs = gridspec.GridSpec(2, 1, height_ratios=[3,1])
    axis = plt.subplot(gs[0])
    acq = plt.subplot(gs[1])

    # bayesian optimization으로 현재까지 관측된 x, y값
    x_obs = np.array([[res['params']['x']] for res in optimizer.res])
    y_obs = np.array([res['target'] for res in optimizer.res])

    mu, sigma = posterior(optimizer, x_obs, y_obs, x)

    # plot function
    axis.plot(x, y, linewidth=3, label='target')        # 실제 함수
    axis.plot(x_obs.flatten(), y_obs, 'D', markersize=8, label='Observations', color='r')   # 현재 관측된 값 ◆
    axis.plot(x, mu, '--', color='k', label='Prediction')
    axis.fill(np.concatenate([x, x[::-1]]),
            np.concatenate([mu - 1.9600 * sigma, (mu + 1.9600 * sigma)[::-1]]),
            alpha=0.6, fc='c', ec='None', label='95% confidence interval'
        )
    axis.set_xlim((-2, 10))
    axis.set_ylim((None, None))
    axis.set_xlabel('x', fontdict={'size':20})
    axis.set_ylabel('f(x)', fontdict={'size':20})
    axis.legend(loc=2, bbox_to_anchor=(1.01, 1), borderaxespad=0.)

    # acquition function
    util_func = UtilityFunction(kind='ucb', kappa=5, xi=0)
    utility = util_func.utility(x=x, gp=optimizer._gp, y_max=0)
    acq.plot(x, utility, color='purple', label='Utility Function')
    acq.plot(x[np.argmax(utility)], np.max(utility), '*',
        markersize=15, markerfacecolor='gold',
        markeredgecolor='k', markeredgewidth=1, label='NExt Best Gauess')
    acq.set_xlim((-2,10))
    acq.set_ylim((0, np.max(utility)+0.5))
    acq.set_xlabel('x', fontdict={'size': 20})
    acq.set_ylabel('Utility', fontdict={'size': 20})
    acq.legend(loc=2, bbox_to_anchor=(1.01, 1), borderaxespad=0.)
    plt.show()

bayes_opt = BayesianOptimization(f=target, pbounds={'x': (-2,10)}, random_state=27)
bayes_opt.maximize(init_points=0, n_iter=1, acq='ucb', kappa=5)
plot_gp(bayes_opt, x_lp, y_lp)

# Cifar10 Data에 HyperParameter Optimize
(x_trainval, y_trainval), (x_test, y_test) = tf.keras.datasets.cifar10.load_data()
print(x_trainval.shape, y_trainval.shape, x_test.shape, y_test.shape)

x_trainval = x_trainval.astype('float32')/255.0
x_test = x_test.astype('float32')/255.0

y_trainval = tf.one_hot(y_trainval.squeeze(), 10)
y_test = tf.one_hot(y_test.squeeze(), 10)
print(x_trainval.shape, y_trainval.shape, x_test.shape, y_test.shape)

x_train = x_trainval[:1000]
y_train = y_trainval[:1000]

x_valid = x_trainval[49000:]
y_valid = y_trainval[49000:]

print(x_train.shape, y_train.shape, x_valid.shape, y_valid.shape, x_test.shape, y_test.shape)

train_dataset = tf.data.Dataset.from_tensor_slices((x_train, y_train)).batch(2000)
# valid_dataset = tf.data.Dataset.from_tensor_slices((x_valid, y_valid)).batch(2000)
# test_dataset = tf.data.Dataset.from_tensor_slices((x_test, y_test)).batch(2000)

def build_network(num_layers_conv,
                num_layers_dense,
                num_channels_cnn,
                num_nodes_dense):
    model = tf.keras.Sequential()
    model.add(tf.keras.layers.Input(shape=(32,32,3)))

    # Conv_layers
    for i in range(num_layers_conv):
        model.add(tf.keras.layers.Conv2D(num_channels_cnn, kernel_size=(3,3),
                strides=1, padding='same', activation='relu'))
    model.add(tf.keras.layers.Flatten())

    # Dense_layers
    for i in range(num_layers_dense):
        model.add(tf.keras.layers.Dense(num_nodes_dense, activation='relu'))

    # output_layers
    model.add(tf.keras.layers.Dense(10))
    return model

def build_and_optimize(num_layers_conv,
                num_layers_dense,
                num_channels_cnn,
                num_nodes_dense,
                log_learning_rate):
    num_layers_conv = int(num_layers_conv)
    num_layers_dense = int(num_layers_dense)
    num_channels_cnn = int(num_channels_cnn)
    num_nodes_dense = int(num_nodes_dense)
    learning_rate = np.exp(log_learning_rate)

    # print(f'num_layers_conv: {num_layers_conv}')
    # print(f'num_layers_dense: {num_layers_dense}')
    # print(f'num_channels_cnn: {num_channels_cnn}')
    # print(f'num_nodes_dense: {num_nodes_dense}')
    # print(f'learning_rate: {learning_rate}')

    model = build_network(num_layers_conv, num_layers_dense,
                num_channels_cnn, num_nodes_dense)
    model.compile(optimizer=tf.keras.optimizers.SGD(learning_rate),
                loss=tf.keras.losses.CategoricalCrossentropy(from_logits=True),
                metrics=['accuracy'])
    model.fit(train_dataset, epochs=10, verbose=0)
    loss, accuracy = model.evaluate(x_valid, y_valid, verbose=0)
    # print(f'accuracy: {accuracy}')
    return accuracy

bound = {'num_layers_conv': (2, 5.9),
        'num_layers_dense': (2, 4.9),
        'num_channels_cnn': (32, 128.9),
        'num_nodes_dense': (32, 256.9),
        'log_learning_rate': (-5,-1)}

bayes_optimizer = BayesianOptimization(f=build_and_optimize, pbounds=bound, random_state=7)
bayes_optimizer.maximize(init_points=2, n_iter=10, kappa=5)

bayes_optimizer.max # best_case

acc_frame = pd.Series([res['target'] for res in bayes_optimizer.res], name='accuracy').to_frame()
params_frame = pd.DataFrame([res['params'] for res in bayes_optimizer.res])
bayesian_frame = pd.concat([acc_frame, params_frame], axis=1)
bayesian_frame

# models = build_network(2, 4, 3, 3)
# models.compile(optimizer=tf.keras.optimizers.SGD(0.001),
#                 loss=tf.keras.losses.CategoricalCrossentropy(from_logits=True),
#                 metrics=['accuracy'])
# models.fit(train_dataset, epochs=10, verbose=2)
# models.evaluate(x_valid, y_valid)

52_Deep_Learning/[POSTECH AI] DeepLearning (Tensorflow)/200917_p18_AutoML (Bayesian_Optimization).py


class Car:
    #     这是一个特殊的函数，使用两个下划线标记主要是为了跟其它的普通函数区分开来。 在java里这个叫构造函数
    # 里面有带了几个参数来填充属性，还可以添加默认参数，里面我添加了一个odometer_reading这个属性
    # 这里面我添加了两个方法get_descriptive_name 和 update_odometer 这里面必须传入self，这是对自身的一种引用，另外还可以在后面添加若干参数
    def __init__(self, make, model, year):
        self.make = make
        self.model = model
        self.year = year
        self.odometer_reading = 0

    def get_descriptive_name(self):
        long_name = str(self.year) + ' ' + self.make + ' ' + self.model
        return long_name.title()

    def update_odometer(self, mileage):
        if mileage >= self.odometer_reading:
            self.odometer_reading = mileage
            print('move ' + str(self.odometer_reading) + ' miles')
        else:
            print("you can't roll back an odometer!")

# 继承类
class ElectriCar(Car):
    def __init__(self, max_speed, make, model, year):
        super().__init__(make, model, year)
        self.max_speed = max_speed

    # 静态方法
    @staticmethod
    def fill_gas_tank():
        print("i hava a battery")

    # 新建方法
    def descript_batter(self):
        print("This car has a " + str(self.battery_size) + " kwh battery.")

    # 重写方法
    def get_descriptive_name(self):
        long_name = str(self.year) + ' ' + self.make + ' ' + self.model + "我是很快的特斯拉"
        return long_name.title()

# 调用类
byd = Car('byd', 'byd tang', '2017')  # 实例化Car类
str1 = byd.get_descriptive_name()  # 调用类的方法
print(str1.title())

byd.update_odometer(100)
byd.update_odometer(70)
byd.update_odometer(120)

print("=============")

ElectriCar.fill_gas_tank()
my_tesla = ElectriCar(300, "tesla", "model s", "2018")
name = my_tesla.get_descriptive_name()
print(name.title())


# Simple demo of reading the difference between channel 1 and 0 on an ADS1x15 ADC.
# Author: Tony DiCola
# License: Public Domain
import time
import math
import matplotlib.pyplot as plt
import logging

# Import the ADS1x15 module.
from ADS1x15 import ADS1115

# Create an ADS1115 ADC (16-bit) instance.
#adc = ADS1115()

# Or create an ADS1015 ADC (12-bit) instance.
adc = ADS1115()

# Note you can change the I2C address from its default (0x48), and/or the I2C
# bus by passing in these optional parameters:
#adc = ADS1015(address=0x49, busnum=1)

# Choose a gain of 1 for reading voltages from 0 to 4.09V.
# Or pick a different gain to change the range of voltages that are read:
#  - 2/3 = +/-6.144V
#  -   1 = +/-4.096V
#  -   2 = +/-2.048V
#  -   4 = +/-1.024V
#  -   8 = +/-0.512V
#  -  16 = +/-0.256V
# See table 3 in the ADS1015/ADS1115 datasheet for more info on gain.
GAIN = 16

voltList = []
stressList = []
timeList = []

logging.basicConfig(filename='data.log', filemode='w',level=logging.DEBUG)

Vex = 5
R = 350
GF = 123
E = 69 * 10 ** 9

print('Press Ctrl-C to quit...')
timeStart = time.time()
try:
    while True:
        # Read the difference between channel 0 and 1 (i.e. channel 0 minus channel 1).
        # Note you can change the differential value to the following:
        #  - 0 = Channel 0 minus channel 1
        #  - 1 = Channel 0 minus channel 3
        #  - 2 = Channel 1 minus channel 3
        #  - 3 = Channel 2 minus channel 3
        value = adc.read_adc_difference(0, gain=GAIN)
        # Note you can also pass an optional data_rate parameter above, see
        # simpletest.py and the read_adc function for more information.
        # Value will be a signed 12 or 16 bit integer value (depending on the ADC
        # precision, ADS1015 = 12-bit or ADS1115 = 16-bit).
        factor = value / 32767
        volts = factor * 4.096/GAIN
        voltList.append(volts)

        timerec = time.time()
        delta = timerec -timeStart

        timeList.append(delta)
        #print(volts)
        logging.info("volts {}".format(volts) + ", " + "time {}".format(delta))
        print('Channel 0 minus 1: {0}'.format(value))
        print('Voltage: {0}'.format(volts))

        # Pause for 0.01 seconds.
        time.sleep(0.01)

except KeyboardInterrupt:
    for volts in voltList:
        deltaR = volts / Vex * R
        strain = deltaR / (R * GF)
        stress = E * strain
        stressList.append(stress)

    plt.plot(timeList, stressList)
    plt.ylabel("Stress (N/m2)")
    plt.xlabel("Time(s)")
    plt.show()
except Exception as e:
    print(e)


import itertools

from utils import get_grid

class Cube:
    """Class representing the Cube::Bit."""

    def __init__(self):
        """Construct."""
        self.grid = get_grid()

    def display(self, colours):
        """Realign and display a 3x3 grid of colours."""
        fixed_colours = reorder(flatten(colours))
        for i in range(27):
            self.grid[i] = fixed_colours[i]

        self.grid.show()

def reorder(colours):
    """
    Reorder the colours to fit the Cube::Bit's weird space-filling curve.

    This is horribly hard-coded - if I ever get a cube that's not a 3x3x3, I'll
    do it properly
    """
    indeces = [
        0,
        3,
        6,
        7,
        4,
        1,
        2,
        5,
        8,
        17,
        16,
        15,
        12,
        13,
        14,
        11,
        10,
        9,
        18,
        21,
        24,
        25,
        22,
        19,
        20,
        23,
        26,
    ]
    reordered = []
    for i in range(27):
        reordered.append(colours[indeces[i]])
    return reordered

def flatten(colours):
    """Flatten the cubular array into one long list."""
    return list(itertools.chain.from_iterable(itertools.chain.from_iterable(colours)))


import user.connectDB as connDB

connect = connDB.connect()  # conn database
database = connect[0]  # database
cursor = connect[1]  # cursor

class Note:

    def __init__(self, user_id, title, description):
        self.user_id = user_id
        self.title = title
        self.description = description

    def store(self):
        sql = "INSERT INTO notes VALUES(NULL, %s, %s, %s, NOW())"
        note = (self.user_id, self.title, self.description)

        cursor.execute(sql, note)
        database.commit()

        return [cursor.rowcount, self]

    def readByUserId(self):
        sql = f"SELECT * FROM notes WHERE user_id = {self.user_id}"

        cursor.execute(sql);
        result = cursor.fetchall();

        return result

    def remove(self):
        sql = f"DELETE  FROM notes WHERE user_id = {self.user_id} AND title LIKE '%{self.title}%'"

        cursor.execute(sql);
        database.commit();

        return [cursor.rowcount, self]


from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker
from sqlalchemy_utils import database_exists, create_database

from logger import logger
from settings import settings

SQLALCHEMY_DATABASE_URL = f"postgresql+psycopg2://{settings.DB_USERNAME}:{settings.DB_PASSWORD}@{settings.DB_HOST}/{settings.DB_DATABASE}"

engine = create_engine(SQLALCHEMY_DATABASE_URL)
if not database_exists(engine.url):
    create_database(engine.url)

SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine, expire_on_commit=False)

Base = declarative_base()

def get_db():
    Base.metadata.create_all(bind=engine)
    db = SessionLocal()
    try:
        yield db
    except Exception:
        db.rollback()
    finally:
        db.close()


import base64
from io import BytesIO

import dash
import dash_core_components as dcc
import dash_html_components as html
import matplotlib.pyplot as plt
from pickle import load
from dash.dependencies import Output, Input

from mg_nmf.nmf import NMFGeneSetEnrichment
from mg_nmf import nmf as visualise, nmf as selection

"""
Attempt at a multipage app to
* View heatmaps summarising the model
* View a PCA-RGB map of the model
* Enrichment analysis and gene breakdown
"""

# Load some results to look at
with open('/home/hal/Dropbox/PHD/FunctionalAbundance/nmf/data/metatranscriptome_k6.enrich', 'rb') as f:
    analysis: NMFGeneSetEnrichment = load(f)

MODEL_RES = '/home/hal/Dropbox/PHD/FunctionalAbundance/nmf/data/metatranscriptome_k6.model'
res = selection.NMFModelSelectionResults.load_model(MODEL_RES)

# Methods to generate some plots
def heatmap_image(results):
    fig = visualise.heatmap_plot(res, axes=[0], return_fig=True, log=False)
    pic_bytes = BytesIO()
    plt.savefig(pic_bytes, format='png')
    pic_bytes.seek(0)
    pic_hash = base64.b64encode(pic_bytes.read()).decode("ascii").replace("\n", "")
    img = html.Img(src="data:image/png;base64,{}".format(pic_hash))
    return img

def enrichment_plot(enrichment):
    return dcc.Graph(
        id='enrichment-heatmap',
        figure=enrichment.plot_enrichment(enrichment.results(significance=0.05), group='namespace', label='name',
                                          width=None, height=None),
        style=dict(height='100%'),
        config=dict(displayModeBar=False)
    )

app = dash.Dash(__name__)

heatmap_page = html.Div([
    html.H1('Hi'),
    heatmap_image(res)
])

enrichment_page = html.Div([
        html.Div([
            enrichment_plot(enrichment=analysis),
        ], style=dict(flex=1)),
        html.Div([], id='enrichment-term-plots', style=dict(flex=1, overflowY='auto'))
    ], style=dict(display='flex', height='100%'))

navigation_buttons = html.Div([
        html.Button('Model Heatmap', id='button-heatmap'),
        html.Button('Enrichment', id='button-enrichment'),
        html.Button('Map', id='button-map')
    ], style=dict(display='flex'),
)

layout_index = html.Div([
    navigation_buttons,
    html.Div([], id='content-div', style=dict(height='90vh'))
])

app.layout = layout_index

# Button callbacks
@app.callback(
    Output('content-div', 'children'),
    Input('button-heatmap', 'n_clicks'),
    Input('button-enrichment', 'n_clicks'),
    Input('button-map', 'n_clicks')
)
def button_event(btn1, btn2, btn3):
    ctx = dash.callback_context
    if ctx is None:
        return heatmap_image(res)
    # Find which button triggered the callback
    btn_trigger = ctx.triggered[0]['prop_id'].split('.')[0]
    if btn_trigger == 'button-heatmap':
        return heatmap_image(res)
    if btn_trigger == 'button-enrichment':
        return enrichment_page
    return []

# Heatmap page callbacks

# Enrichment page callbacks
@app.callback(
    Output('enrichment-term-plots', 'children'),
    Input('enrichment-heatmap', 'clickData'))
def display_click_data(clickData):
    # Extract the GO Term from this
    if clickData is None:
        return html.Div()
    go = clickData['points'][0]['y'].split("GO:")[1][:-1]
    go = 'GO:' + go
    component = clickData['points'][0]['x']
    return dcc.Graph(
        id='enrichment-correlation',
        figure=analysis.plot_geneset_correlation(component=component, gene_set_id=go, cols=3, vspace=0.03)
    )

if __name__ == '__main__':
    app.run_server(debug=True)


import random
import sys

from line_profiler import LineProfiler
class SingleNode(object):
    """单链表的结点"""
    def __init__(self,item):
        self.item = item
        self.next = None

class SingleLinkList(object):
    """单链表"""
    def __init__(self):
        self._head = None

    def is_empty(self):
        return self._head == None

    def length(self):
        """链表长度"""
        cur = self._head
        count = 0
        while cur != None:
            count += 1
            cur = cur.next
        return count

    def travel(self):
        """遍历链表"""
        cur = self._head
        while cur != None:
            print(cur.item , end=" ")
            cur = cur.next
        print("\n")

    def add(self, item):
        """头部添加元素"""
        node = SingleNode(item)
        node.next = self._head
        self._head = node

    def append(self, item):
        """尾部添加元素"""
        node = SingleNode(item)
        if self.is_empty():
            self._head = node
        else:
            cur = self._head
            while cur.next != None:
                cur = cur.next
            cur.next = node

    def get(self, pos):
        """获取指定位置的元素"""
        if pos <= 0:
            return self._head
        cur = self._head
        count = 0
        while count < pos:
            count += 1
            cur = cur.next
        return cur

    def insert(self, pos, item):
        """指定位置添加元素"""
        if pos <= 0:
            self.add(item)
        elif pos > (self.length() - 1):
            self.append(item)
        else:
            node = SingleNode(item)
            cur = self.get(pos - 1)
            node.next = cur.next
            cur.next = node

    def remove(self, pos):
        """删除节点"""
        if pos <= 0:
            self._head = self._head.next
        elif pos > (self.length() - 1):
            pass
        else:
            cur = self.get(pos - 1)
            cur.next = cur.next.next

    def search(self, item):
        """查找节点是否存在"""
        cur = self._head
        while cur != None:
            if cur.item == item:
                return True
            cur = cur.next
        return False
    '''
    单链表反转有两种办法
    1. 递归
    2. 非递归
    '''
    def reverse2(self):
        """反转链表 非递归"""
        cur = self._head
        pre = None
        while cur != None:
            next = cur.next
            cur.next = pre
            pre = cur
            cur = next
        self._head = pre

    def reverse1(self):
        """反转链表 递归"""
        self._reverse(self._head)

    def _reverse(self, head):
        """反转链表 递归"""
        if head==None or head.next == None :
            return head
        else:
            new_head = self._reverse(head.next)
            head.next.next = head
            head.next = None
            return new_head

    def sort(self):
        """排序"""
        if self.is_empty():
            return
        self._sort(self._head)

    def _sort(self, head):
        pass
        """排序
        if head==None or head.next == None:
            return head
        else:
            cur = head
            while cur.next != None:
                if cur.item > cur.next.item:
                    cur.item, cur.next.item = cur.next.item, cur.item
                cur = cur.next
            self._sort(head)
        """

if __name__ == "__main__":
    ll = SingleLinkList()
    lp = LineProfiler()
    #lp_wrapper = lp(ll.add)
    #lp_wrapper(1)
    #lp.print_stats()
    #ll.add(1)
    for i in range(10):
        ll.add(random.randint(0,1000))
    #ll.travel()
    ll.sort()
    ll.travel()

'''
    lp.add_function(ll.reverse2)
    lp.add_function(ll.reverse1)
    lp.enable()
    ll.reverse1()
    ll.reverse2()
    lp.disable()
    lp.print_stats(sys.stdout)

   '''

   # print ll.search(3)
   # print ll.search(5)
   # ll.remove(1)
   # print "length:",ll.length()
   # ll.travel()


import torch
import torch.nn as nn

device = torch.device("cuda" if torch.cuda.is_available() else "cpu")

def vog_calc(trainloader, model,dataset_name):
    vog = {}
    for idx, batch in enumerate(trainloader):
        if idx >= 10:
            print(idx)
            break
        X,y = batch
        X, y = X.to(device), y.to(device)
        grad_X = X
        grad_Y = y
        grad_X.requires_grad = True
        logits = model(grad_X)
        celoss = nn.CrossEntropyLoss()
        loss = celoss(logits, grad_Y)
        loss.backward()
        sumMatrix = torch.sum(grad_X.grad, dim=0)

    sumMatrix /= grad_X.grad.shape[0] * len(trainloader)
    covMatrix = [torch.pow(covMatric - sumMatrix, 2) for covMatric in grad_X]
    covMatrix = sum(covMatrix)
    covMatrix /= len(trainloader)
    meanMatrix = torch.mean(covMatrix)
    print("Dataset_ {}: {}".format(dataset_name, meanMatrix.item()))

    # print(covGrad)

import torch.nn as nn
import torchvision
class MyResNet(nn.Module):

    def __init__(self, in_channels=1):
        super(MyResNet, self).__init__()

        # bring resnet
        self.model = torchvision.models.resnet18(pretrained=True)

        # original definition of the first layer on the renset class
        # self.conv1 = nn.Conv2d(3, 64, kernel_size=7, stride=2, padding=3, bias=False)

        # your case
        self.model.conv1 = nn.Conv2d(in_channels, 64, kernel_size=7, stride=2, padding=3, bias=False)

    def forward(self, x):
        return self.model(x)

model = MyResNet()
model_rgb = torchvision.models.resnet18(pretrained=True)
import torch

from torchvision import transforms, datasets
transform = transforms.Compose(
    [transforms.ToTensor(),
     transforms.Normalize((0.5), (0.5))])

trainset = datasets.MNIST(root='./data', train=True,
                                        download=True, transform=transform)
trainloader = torch.utils.data.DataLoader(trainset, batch_size=64,
                                          shuffle=True, num_workers=2)

testset = datasets.MNIST(root='./data', train=False,
                                       download=True, transform=transform)
testloader = torch.utils.data.DataLoader(testset, batch_size=64,
                                         shuffle=False, num_workers=2)

model.to(device)
model = nn.DataParallel(model)
model.eval()

model_rgb.to(device)
model_rgb = nn.DataParallel(model_rgb)
model_rgb.eval()

vog = vog_calc(trainloader, model, "MNIST")

from torchvision import transforms, datasets
transform = transforms.Compose(
    [transforms.ToTensor(),
     transforms.Normalize((0.5), (0.5))])

trainset = datasets.KMNIST(root='./data2', download=True, transform=transform)
trainloader = torch.utils.data.DataLoader(trainset, batch_size=64,
                                          shuffle=True, num_workers=2)
'''
testset = datasets.SEMEION(root='./data2', train=False,
                                       download=True, transform=transform)
testloader = torch.utils.data.DataLoader(testset, batch_size=64,
                                         shuffle=False, num_workers=2)

'''
vog = vog_calc(trainloader, model, "KMNIST")

from torchvision import transforms, datasets
transform = transforms.Compose(
    [transforms.ToTensor(),
     transforms.Normalize((0.5), (0.5))])

trainset = datasets.FashionMNIST(root='./data2', download=True, transform=transform)
trainloader = torch.utils.data.DataLoader(trainset, batch_size=64,
                                          shuffle=True, num_workers=2)
'''
testset = datasets.SEMEION(root='./data2', train=False,
                                       download=True, transform=transform)
testloader = torch.utils.data.DataLoader(testset, batch_size=64,
                                         shuffle=False, num_workers=2)

'''
vog = vog_calc(trainloader, model, "FashionMNIST")
print(vog)

from torchvision import transforms, datasets
transform = transforms.Compose(
    [transforms.ToTensor(),
     transforms.Normalize((0.5), (0.5))])

trainset = datasets.CIFAR10(root='./data2', download=True, transform=transform)
trainloader = torch.utils.data.DataLoader(trainset, batch_size=64,
                                          shuffle=True, num_workers=2)
'''
testset = datasets.SEMEION(root='./data2', train=False,
                                       download=True, transform=transform)
testloader = torch.utils.data.DataLoader(testset, batch_size=64,
                                         shuffle=False, num_workers=2)

'''
vog = vog_calc(trainloader, model_rgb, "CIFAR10")
print(vog)


import numpy as np
from scipy.integrate import solve_ivp
import matplotlib.pyplot as plt

# Parameters
w = 1
mu = 1
a = 1

x_base = 1
y_base = 1
r_base = np.sqrt(x_base ** 2 + y_base ** 2)

e = 0

# Initial conditions
x0 = 0
y0 = 2 * a

# Potential function
def get_numeric_potential(t, x1, x3, r_base):
    # Calculate potential using provided equation
    potential = mu / r_base ** 3 - w ** 2 + e * np.sin(f * t)
    return potential

# ODE system
# x1 = x
# x2 = x_dot
# x3 = y
# x4 = y_dot
def odes(t, z):
    # Unpack state
    x1, x2, x3, x4 = z

    # Get potential
    U = get_numeric_potential(t, x1, x3, r_base)

    # Calculate derivatives
    dxdt = [
        x2,
        2 * w * x4 - U * x1,
        x4,
        -2 * w * x2 - U * x3
    ]

    return dxdt

# Initial state
omega1 = -w - np.sqrt(mu / r_base ** 3)
x_dot0 = -2 * a * omega1
y_dot0 = 0
omega3 = -w + np.sqrt(mu / r_base ** 3)
f = omega3
z0 = [x0, x_dot0, y0, y_dot0]

# Specify time points
t = np.linspace(0, 10, 1000)

# Solve
sol = solve_ivp(odes, [0, 10], z0, t_eval=t)

# Plot
plt.plot(sol.t, sol.y[0], label='x(t)')
plt.plot(sol.t, sol.y[2], label='y(t)')
plt.xlabel('t')
plt.legend()
plt.show()

# Get x and y solution vectors
x = sol.y[0]
y = sol.y[2]

# Plot
plt.plot(x, y)
plt.xlabel('x')
plt.ylabel('y')
plt.title('x vs y')
plt.show()


"""Basis functionality that should always be present."""
import re
import pytest
import requests
from playwright.sync_api import expect

FOOTER_TEXT_EN = "Internet.nl is an initiative of the Internet community and the Dutch"
FOOTER_TEXT_NL = "Internet.nl is een initiatief van de internetgemeenschap en de Nederlandse"

SECURITY_TXT_TEXT = "Policy: https://internet.nl/disclosure/"

ROBOTS_TXT_TEXT = "Disallow: /site/"

def test_index_http_ok(page, app_url_subdomain):
    response = page.request.get(app_url_subdomain)
    expect(response).to_be_ok()

@pytest.mark.parametrize(
    ("app_url", "footer_text"),
    [("https://en.internet.test", FOOTER_TEXT_EN), ("https://nl.internet.test", FOOTER_TEXT_NL)],
)
def test_index_footer_text_present(page, app_url, footer_text):
    page.goto(app_url)
    footer = page.locator("#footer")

    assert footer_text in footer.text_content()

def test_security_txt(page, app_url_subdomain):
    page.goto(app_url_subdomain + "/.well-known/security.txt")

    assert SECURITY_TXT_TEXT in page.content()

def test_robots_txt(page, app_url_subdomain):
    page.goto(app_url_subdomain + "/robots.txt")

    assert ROBOTS_TXT_TEXT in page.content()

def test_favicon_ico(page, app_url_subdomain):
    response = page.request.get(app_url_subdomain + "/favicon.ico")
    expect(response).to_be_ok()

def test_static_files(page, app_url_subdomain):
    response = requests.get(app_url_subdomain + "/static/logo_en.png", verify=False)
    response.raise_for_status()

def test_generated_css_static_files(page, app_url_subdomain):
    response = requests.get(app_url_subdomain + "/static/css/style-min.css", verify=False)
    response.raise_for_status()
    assert "@font-face" in response.text
    assert "expires" in response.headers

def test_generated_js_static_files(page, app_url_subdomain):
    response = requests.get(app_url_subdomain + "/static/js/menu-min.js", verify=False)
    response.raise_for_status()
    assert "hideMenuButton" in response.text
    assert "expires" in response.headers

@pytest.mark.parametrize(
    "path",
    ["/grafana", "/prometheus", "/prometheus/targets"],
)
def test_monitoring_auth(page, app_url, path):
    """Monitoring endpoints must be behind basic auth."""

    response = requests.get(app_url + path, verify=False)
    assert response.status_code == 401

    # MONITORING_AUTH provided in docker/test.env
    auth = ("test", "test")

    response = requests.get(app_url + path, auth=auth, verify=False)
    response.raise_for_status()

def test_monitoring_auth_raw(page, app_url):
    """Monitoring endpoints must be behind basic auth."""
    path = "/grafana"

    response = requests.get(app_url + path, verify=False)
    assert response.status_code == 401

    # MONITORING_AUTH_RAW provided in docker/test.env
    auth = ("test_raw", "test_raw")

    response = requests.get(app_url + path, auth=auth, verify=False)
    response.raise_for_status()

def test_no_server_banner(page, app_url_subdomain):
    response = requests.get(app_url_subdomain, verify=False)
    assert response.headers["server"] == "nginx"

def test_http_redirect_https(page, app_url_subdomain):
    response = requests.get(app_url_subdomain.replace("https", "http"), allow_redirects=False)
    assert response.status_code == 301
    assert re.match(app_url_subdomain, response.headers["location"])

def test_nowww_class_b(page, app_domain, app_url):
    response = requests.get(f"https://www.{app_domain}", allow_redirects=False, verify=False)
    assert response.status_code == 301
    assert response.headers["location"] == f"{app_url}/"

def test_additional_redirect_domains(page, app_url):
    """Additional configured redirect subdomains should redirect to the frontpage."""
    response = requests.get("https://platforminternet.test", allow_redirects=False, verify=False)
    assert response.status_code == 301
    assert response.headers["location"] == f"{app_url}/"

def test_default_sni_none(app_domain):
    """Default vhost should 404 on any non explicitly configured domain. #894"""

    not_configured_domain = "telefax.test"

    # make a https request to the webserver's adres but request a vhost that is not configured
    response = requests.get(
        f"https://{app_domain}", headers={"Host": not_configured_domain}, verify=False, allow_redirects=False
    )
    assert response.status_code == 404

def test_conn_over_https_no_hsts(app_domain):
    """Serving conn. over HTTPS should disable HSTS and downgrade to HTTP. #894"""

    # make a https request to the webserver's adres but request a vhost that is not configured
    response = requests.get(f"https://conn.{app_domain}", verify=False, allow_redirects=False)
    assert response.status_code == 301
    assert response.headers["Strict-Transport-Security"] == "max-age=0;"
    assert response.headers["location"] == f"http://conn.{app_domain}"

@pytest.mark.parametrize(
    ("from_language", "to_language", "footer_text"),
    [("nl", "en", FOOTER_TEXT_EN), ("en", "nl", FOOTER_TEXT_NL)],
)
def test_change_language(page, app_domain, from_language, to_language, footer_text):
    """Test clicking the language change button."""

    page.goto(f"https://{from_language}.{app_domain}")
    page.locator("#language-switch-header-container button:not(:disabled)").click()
    page.wait_for_url(f"https://{to_language}.internet.test/")

    footer = page.locator("#footer")
    assert footer_text in footer.text_content()

@pytest.mark.parametrize(
    ("language", "footer_text"),
    [("en", FOOTER_TEXT_EN), ("nl", FOOTER_TEXT_NL)],
)
def test_accept_language_header(page, app_domain, language, footer_text):
    """Browser preferred language should be respected."""

    page.set_extra_http_headers({"Accept-Language": language})
    page.goto(f"https://{app_domain}")

    footer = page.locator("#footer")
    assert footer_text in footer.text_content()


#
#   44 - DSA nonce recovery from repeated nonce
#

from cryptopals.asymmetric import DSA
from cryptopals.hash import SHA1
from cryptopals.utils import Math
from random import randint

def test_c44() -> None:
    # DSA Oracle
    dsa = DSA()

    # Messages
    message1 = b"First message."
    message2 = b"Second message."

    # Broken DSA Implementation Uses The Same 'k' Everytime
    k = randint(1, dsa.parameters.q - 1)

    # Known First And Second Signing Component
    (r1, s1) = dsa.sign(message=message1, k=k)
    (r2, s2) = dsa.sign(message=message2, k=k)

    # The Leftmost min(N, outlen) Bits Of Hash(M)
    digest1 = int.from_bytes(SHA1.digest(m=message1), "big")
    digest_len1 = digest1.bit_length()
    z1 = digest1 >> (digest_len1 - Math.gcd(dsa.parameters.q.bit_length(), digest_len1))

    digest2 = int.from_bytes(SHA1.digest(m=message2), "big")
    digest_len2 = digest2.bit_length()
    z2 = digest2 >> (digest_len2 - Math.gcd(dsa.parameters.q.bit_length(), digest_len2))

    # Modular Inverse Of The First And Second Signing Component 'r' And 's'
    r2_inv = Math.mod_inv(a=r2, m=dsa.parameters.q)
    s1_inv = Math.mod_inv(a=s1, m=dsa.parameters.q)

    # Calculate The Subkey 'k'
    numerator = s1_inv * (z1 - z2 * r2_inv * r1) % dsa.parameters.q
    denominator = (1 - s1_inv * s2 * r2_inv * r1) % dsa.parameters.q
    k = numerator * Math.mod_inv(a=denominator, m=dsa.parameters.q) % dsa.parameters.q

    # Calculate The Private Key 'x'
    x = (s2 * k - z2) * r2_inv % dsa.parameters.q

    assert  x == dsa.parameters.x


from manga_py.provider import Provider
from .helpers.std import Std

class PlusComicoJp(Provider, Std):

    def get_chapter_index(self) -> str:
        return self.re.search('/manga/\d+/(\d+)', self.chapter).group(1)

    def get_content(self):
        content = self._storage.get('main_content', None)
        if content:
            return content
        idx = self.re.search('/manga/(\d+)', self.get_url())
        url = '{}/manga/{}/'.format(self.domain, idx.group(1))
        return self.http_get(url)

    def get_manga_name(self) -> str:
        return self.text_content_full(self.content, '.stage__body h1')

    def get_chapters(self):
        idx = self.re.search(r'/manga/(\d+)', self.get_url()).group(1)
        with self.http().post('{}/api/getArticleList.nhn'.format(
            self.domain
        ), data={
            'titleNo': idx
        }) as resp:
            json = resp.json()
        items = []
        for i in json.get('result', {}).get('list', {}):
            if i.get('freeFlg', 'N') == 'Y':
                items.append(i.get('articleDetailUrl'))
        return items[::-1]

    def get_files(self):
        content = self.http_get(self.chapter)
        images = [i.get('src') for i in self.document_fromstring(content, '.comic-image > img')]
        images += self.re.findall(r'\'(http://comicimg.comico.jp/onetimecontents/.+)\'', content)
        return images

    def get_cover(self) -> str:
        item = self.document_fromstring(self.content, '.stage div[class^="article-hero"]')
        if item:
            return self.parse_background(item[0])

    def save_file(self, idx=None, callback=None, url=None, in_arc_name=None):
        if in_arc_name is None:
            in_arc_name = '{}_image.jpg'.format(idx)
        super().save_file(idx, callback, url, in_arc_name)

main = PlusComicoJp


from functools import reduce
from operator import add
from flask import Flask, render_template, url_for, request, redirect
from flask_sqlalchemy import SQLAlchemy
from datetime import datetime
from wtforms import Form, BooleanField, StringField, validators, IntegerField
from wtforms.fields.core import Field, FieldList, FormField, SelectField
from wtforms.ext.sqlalchemy.fields import QuerySelectField

app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///test.db'
db = SQLAlchemy(app)

class Elo(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    score = db.Column(db.Integer)
    name = db.Column(db.String(200), nullable=False)

    def __repr__(self):
        return self.name

class EloAddForm(Form):
    name = StringField('Name')
    score = IntegerField('Score')

class PlayerAddForm(Form):
    elos = Elo.query.order_by(-(Elo.score)).all()
    player = QuerySelectField(query_factory=lambda: Elo.query)

added_players = []

class PlaceForm(Form):
    place = SelectField('Place', coerce=int)

@app.route('/', methods=['POST', 'GET'])
def index():
    eloaddform = EloAddForm(request.form)
    playeraddform = PlayerAddForm()
    placeform = PlaceForm()
    placeform.place.choices = list(range(1, len(added_players)+1))

    if(request.method == 'POST'):
        elo_name = eloaddform.name.data
        elo_score = eloaddform.score.data
        new_elo = Elo(score = elo_score, name = elo_name )

        try:
            db.session.add(new_elo)
            db.session.commit()
            return redirect('/')
        except:
            return 'There was a problem adding your elo'

    else:
        all_elos = Elo.query.order_by(-(Elo.score)).all()
        return render_template('index.html', elos = all_elos, eloaddform = eloaddform, playeraddform = playeraddform, players = added_players, placeform = placeform)

@app.route('/delete/<int:id>')
def delete(id):
    elo_to_delete = Elo.query.get_or_404(id)

    try:
        db.session.delete(elo_to_delete)
        db.session.commit()
        return redirect('/')
    except:
        return 'There was a problem deleting this elo'

@app.route('/add_player/', methods=['POST', 'GET'])
def add_player():
    playeraddform = PlayerAddForm(request.form)

    if(request.method == 'POST'):
        added_players.append(playeraddform.player.data)
        return redirect('/')

@app.route('/calc_elo/', methods=['POST', 'GET'])
def calc_elo():
    placeform = PlaceForm(request.form)
    game_size = len(added_players)
    places = []
    if(request.method == 'POST'):
        places = list(map(int, request.form.getlist('place')))

        for i in range(game_size):
            elo_sum = 0
            for j in range(game_size):
                isWin = 0
                if j != i:
                    if places[i] < places[j]:
                        isWin = 1
                    expected = 1/(1 + pow(10, (added_players[j].score-added_players[i].score)/400))
                    elo_sum += added_players[i].score+32*(isWin - expected)

            Elo.query.filter_by(name=added_players[i].name).first().score = int(elo_sum/(game_size-1))

        db.session.commit()
        added_players.clear()

    return redirect('/')

if __name__ == "__main__":
    app.run(debug=True)


# -*- coding: utf-8 -*-
"""
Created on Tue Dec  7 09:40:41 2021

@author: b.sereeter
"""

Numbers = [ int(i) for i in open('Inputs/Day7T.txt', 'r').read().split(',')]

# %% Part1 and Part2
def ComputeSumUntilN(n):
    return int(n*(n+1)/2)

def FindTotalFuelCost(numbers, part):
    maxN = max(numbers)
    dicForSum = {}
    listOfSum = []
    for i in range(0,maxN):
        if part == 1:
            totalCost = sum([abs(j-i) for j in Numbers])
        if part ==2:
            totalCost = sum([ComputeSumUntilN(abs(j-i)) for j in Numbers])
        dicForSum[totalCost] = i
        listOfSum.append(totalCost)
    minCost = min(listOfSum)
    return minCost, dicForSum[minCost]

print("Part-1: total fuel cost is :", FindTotalFuelCost(Numbers.copy(),1))
print("Part-2: total fuel cost is :", FindTotalFuelCost(Numbers.copy(),2))


#!/usr/bin/env python
"""Load OBP chapter metadata into Thoth"""

import re
import logging

from bookloader import BookLoader
from chapterloader import ChapterLoader

class ObpChapterLoader(ChapterLoader):
    """OBP specific logic to ingest chapter metadata from CSV into Thoth"""
    publisher_name = "Open Book Publishers"
    contributors_limit = 1  # lookup not needed in this workflow
    institutions_limit = 1

    def run(self):
        """Process CSV and call Thoth to insert its data"""
        book_doi = self.data.at[0, 'doi'].strip().lower()[:-3]  # OBP chapter DOIs are book's + ".00"
        book_id = self.get_work_by_doi(book_doi)['workId']

        relation_ordinal = 1
        for row in self.data.index:
            work = self.get_work(row, self.imprint_id)
            logging.info(work)
            work_id = self.thoth.create_work(work)
            logging.info('Created chapter %s: %s (%s)' % (relation_ordinal, work['fullTitle'], work_id))
            self.create_languages(row, work_id)
            self.create_contributors(row, work_id)
            self.create_chapter_relation(book_id, work_id, relation_ordinal)
            relation_ordinal += 1

    def get_work(self, row, imprint_id):
        """Returns a dictionary with all attributes of a 'work'

        row: current row number

        imprint_id: previously obtained ID of this work's imprint
        """
        title = self.data.at[row, 'title']
        subtitle = self.data.at[row, 'subtitle']
        title = self.sanitise_title(title, subtitle)
        doi = self.data.at[row, 'doi'].strip().lower()

        cc_license = "https://creativecommons.org/licenses/{}/4.0/".format(self.data.at[row, 'license'].lower())

        # Produce landing page based on OBP's convention
        chapter_doi = doi.replace("https://doi.org/", "")
        book_doi = chapter_doi[:-3]
        landing_page = f"https://www.openbookpublishers.com/books/{book_doi}/chapters/{chapter_doi}"

        page_count = int(self.data.at[row, "page_count"]) \
            if self.data.at[row, "page_count"] else None
        first_page = str(self.data.at[row, "first_page"]) \
            if self.data.at[row, "first_page"] else None
        last_page = str(self.data.at[row, "last_page"]) \
            if self.data.at[row, "last_page"] else None
        page_interval = None
        if first_page and last_page:
            page_interval = "{}–{}".format(first_page, last_page)
        abstract = self.data.at[row, "long_abstract"].strip() \
            if self.data.at[row, "long_abstract"] else None

        work = {
            "workType": "BOOK_CHAPTER",
            "workStatus": "FORTHCOMING",
            "fullTitle": title["fullTitle"],
            "title": title["title"],
            "subtitle": title["subtitle"],
            "reference": None,
            "edition": None,
            "imprintId": imprint_id,
            "doi": doi,
            "publicationDate": None,
            "place": "Cambridge, UK",
            "width": None,
            "height": None,
            "pageCount": page_count,
            "pageBreakdown": None,
            "imageCount": None,
            "tableCount": None,
            "audioCount": None,
            "videoCount": None,
            "license": cc_license,
            "copyrightHolder": self.data.at[row, "copyright_holder"],
            "landingPage": landing_page,
            "lccn": None,
            "oclc": None,
            "shortAbstract": None,
            "longAbstract": abstract,
            "generalNote": None,
            "bibliographyNote": None,
            "toc": None,
            "coverUrl": None,
            "coverCaption": None,
            "firstPage": first_page,
            "lastPage": last_page,
            "pageInterval": page_interval
        }
        return work

    def create_languages(self, row, work_id):
        """Creates all languages associated with the current work

        row: current row number

        work_id: previously obtained ID of the current work
        """
        for index in range(1, 4):
            try:
                language = {
                    "workId": work_id,
                    "languageCode": self.data.at[row, f"language_code_{index}"],
                    "languageRelation": self.data.at[row, f"language_relation_{index}"].upper(),
                    "mainLanguage": "true" if self.data.at[row, f"main_language_{index}"] == "Yes" else "false",
                }
                language_id = self.thoth.create_language(language)
                logging.info(f"Language: {language_id}")
            except AttributeError:
                continue

    def create_contributors(self, row, work_id):
        """Creates all contributions associated with the current work

        row: current row number

        work_id: previously obtained ID of the current work
        """
        for index in range(1, 8):
            contributor_id = self.data.at[row, f"contributor_id_{index}"]
            if not contributor_id:
                continue
            contributor_id = contributor_id.strip()
            contribution_type = BookLoader.contribution_types[self.data.at[row, f"contribution_type_{index}"].strip()]
            main_contribution = "true" if self.data.at[row, f"main_contribution_{index}"].strip() == "Yes" else "false"
            biography = self.data.at[row, f"biography_{index}"].strip() if self.data.at[row, f"biography_{index}"] else None

            contributor = self.thoth.contributor(contributor_id)

            contribution = {
                "workId": work_id,
                "contributorId": contributor_id,
                "contributionType": contribution_type,
                "mainContribution": main_contribution,
                "biography": biography,
                "institution": None,
                "firstName": contributor['firstName'],
                "lastName": contributor['lastName'],
                "fullName": contributor['fullName'],
                "contributionOrdinal": index
            }
            contribution_id = self.thoth.create_contribution(contribution)
            logging.info(f"Contribution: {contribution_id}")

            # now create affiliations
            for affiliation_ordinal in range(1, 4):
                institution_id = self.data.at[row, f"institution_id_{index}_{affiliation_ordinal}"]
                if not institution_id:
                    continue
                institution_id = institution_id.strip()
                position = self.data.at[row, f"position_{index}_{affiliation_ordinal}"].strip()

                affiliation = {
                    "contributionId": contribution_id,
                    "institutionId": institution_id,
                    "position": position,
                    "affiliationOrdinal": affiliation_ordinal
                }
                affiliation_id = self.thoth.create_affiliation(affiliation)
                logging.info(f"Affiliation {affiliation_id}")


#!/usr/bin/env python3
import sys

from headwind.spec import CollectorResult, Run, Metric

import pandas as pd

assert len(sys.argv) == 2
input_file = sys.argv[1]

metrics = []
metric_names = []

df = pd.read_csv(input_file)
df = df.drop_duplicates(subset=["file"])
df.max_rss = df.max_rss / 1024 / 1024 / 1024  # GB

limit = 20

mdf = df.sort_values(by="max_rss", ascending=False)
for row in mdf.itertuples():
    name = "max_rss_" + row.file
    metrics.append(
        Metric(name=name, value=row.max_rss, unit="GB", group="compile_max_rss")
    )
    if name in metric_names:
        print("Duplicate:", name)
    metric_names.append(name)

tdf = df.sort_values(by="time", ascending=False)
for row in tdf.itertuples():
    name = "time_" + row.file
    metrics.append(
        Metric(name=name, value=row.time, unit="seconds", group="compile_time")
    )
    if name in metric_names:
        print("Duplicate:", name)
    metric_names.append(name)

sys.stdout.write(CollectorResult(metrics=metrics).json(indent=2))


import numpy as np
import scipy.stats
import scikit_posthocs as sp
import matplotlib.pyplot as plt

cmap = ['1', '#fb6a4a', 'mediumseagreen', 'limegreen', 'palegreen']
heatmap_args = {'cmap':cmap, 'linewidths': 0.5, 'linecolor': '0.3', 'clip_on': False, 'square': True, 'cbar_ax_bbox': [0.80, 0.35, 0.04, 0.3]}

# Verification of statistical tests with known distributions
# x = np.array([np.random.normal(loc=00.0, scale=1.0, size=30),
              # np.random.normal(loc=19.5, scale=1.0, size=30),
              # np.random.normal(loc=20.0, scale=1.0, size=30)])
# print(np.shape(x))
# fr_test = scipy.stats.friedmanchisquare(*x)
# print(fr_test)
# nm_posthoc = sp.posthoc_nemenyi_friedman(x.T)
# print(nm_posthoc)
# sp.sign_plot(nm_posthoc, **heatmap_args)
# exit()

function_evals = [i * 100 for i in range(1,101)] + [11000 + i * 1000 for i in range(90)]
function_evals_of_interest = [1e3, 1e4, 1e5]
evals_mask = [eval in function_evals_of_interest for eval in function_evals]

for system_order in ['finite', 'infinite']:
    print(system_order.upper())

    for eval in range(len(function_evals_of_interest)):
        algorithms_at_fes = []
        for algorithm in ['sa', 'acfsa', 'pso', 'aiwpso', 'acor', 'baacor']:
            print(algorithm)
            # Load test costs of a given metaheuristic for a given system, considering some number of objective function evaluations
            base_filename   = './results/' + algorithm + '_' + system_order
            test_costs_mat  = np.load(base_filename + '_test_costs.npy')
            test_costs_of_interest = test_costs_mat[:, evals_mask]
            costs_fe = test_costs_of_interest[:, eval]

            algorithms_at_fes.append(list(costs_fe))
            print(str(function_evals_of_interest[eval]) + ':  \t' + str(np.mean(costs_fe)))

        algorithms_at_fes = np.array(algorithms_at_fes)
        print('\n Statistical significance')
        print(np.shape(algorithms_at_fes))
        print('Friedman p-val = ' + str(scipy.stats.friedmanchisquare(*algorithms_at_fes)[1]) + '\n\n')
        nm_posthoc = sp.posthoc_nemenyi_friedman(algorithms_at_fes.T)
        plt.figure()
        sp.sign_plot(nm_posthoc, **heatmap_args)
        plt.show()
        print('\n')


from recipe_engine.recipe_api import Property

DEPS = [
  'depot_tools/bot_update',
  'depot_tools/cipd',
  'depot_tools/gclient',
  'recipe_engine/path',
  'recipe_engine/properties',
]

PROPERTIES = {
  'mastername': Property(default=''),
  'buildername': Property(default=''),
  'buildnumber': Property(default=-1, kind=int),
}

def RunSteps(api, mastername, buildername, buildnumber):
  api.cipd.set_service_account_credentials(
      api.cipd.default_bot_service_account_credentials)

  api.gclient.set_config('recipes_py_bare')
  bot_update_step = api.bot_update.ensure_checkout()

  tags = {
    'buildbot_build' : (
      '%s/%s/%s' % (mastername, buildername, buildnumber)
    ).encode('utf-8'),
    'git_repository' : api.gclient.c.solutions[0].url,
    'git_revision' : bot_update_step.presentation.properties['got_revision'],
  }

  api.cipd.create_from_yaml(
      api.path['checkout'].join('infra', 'cipd', 'recipes-py.yaml'),
      refs=['latest'],
      tags=tags)

def GenTests(api):
  yield api.test('basic') + api.properties(path_config='kitchen')


import unittest
import logging
import os
import sys
import tempfile
import shutil
from importlib import import_module

from google.protobuf import text_format

from acts.libs.proto.proto_utils import compile_proto
from acts.libs.proto.proto_utils import compile_import_proto

TEST_PROTO_NAME = "acts_proto_utils_test.proto"
TEST_PROTO_GENERATED_NAME = "acts_proto_utils_test_pb2"
TEST_PROTO_DATA_NAME = "acts_proto_utils_test_data.txt"
TEST_NAME = "test_name"
TEST_ID = 42

class BtMetricsUtilsTest(unittest.TestCase):
    """This test class has unit tests for the implementation of everything
    under acts.controllers.android_device.
    """

    def setUp(self):
        # Set log_path to logging since acts logger setup is not called.
        if not hasattr(logging, "log_path"):
            setattr(logging, "log_path", "/tmp/logs")
        # Creates a temp dir to be used by tests in this test class.
        self.tmp_dir = tempfile.mkdtemp()

    def tearDown(self):
        """Removes the temp dir.
        """
        shutil.rmtree(self.tmp_dir)

    def getResource(self, relative_path_to_test):
        return os.path.join(
            os.path.dirname(os.path.realpath(__file__)), relative_path_to_test)

    def compare_test_entry(self, entry, name, id, nested):
        self.assertEqual(entry.name, name)
        self.assertEqual(entry.id, id)
        self.assertEqual(len(entry.nested), len(nested))
        for i in range(len(entry.nested)):
            self.assertEqual(entry.nested[i].name, nested[i][0])
            self.assertEqual(entry.nested[i].type, nested[i][1])

    def test_compile_proto(self):
        proto_path = self.getResource(TEST_PROTO_NAME)
        output_module_name = compile_proto(proto_path, self.tmp_dir)
        self.assertIsNotNone(output_module_name)
        self.assertEqual(output_module_name, TEST_PROTO_GENERATED_NAME)
        self.assertTrue(
            os.path.exists(
                os.path.join(self.tmp_dir, output_module_name) + ".py"))
        sys.path.append(self.tmp_dir)
        bt_metrics_utils_test_pb2 = None
        try:
            bt_metrics_utils_test_pb2 = import_module(output_module_name)
        except ImportError:
            self.fail("Cannot import generated py-proto %s" %
                      (output_module_name))
        test_proto = bt_metrics_utils_test_pb2.TestProto()
        test_proto_entry = test_proto.entries.add()
        test_proto_entry.id = TEST_ID
        test_proto_entry.name = TEST_NAME
        self.assertEqual(test_proto.entries[0].id, TEST_ID)
        self.assertEqual(test_proto.entries[0].name, TEST_NAME)

    def test_parse_proto(self):
        proto_path = self.getResource(TEST_PROTO_NAME)
        output_module = compile_import_proto(self.tmp_dir, proto_path)
        self.assertIsNotNone(output_module)
        AAA = output_module.TestProtoEntry.NestedType.AAA
        BBB = output_module.TestProtoEntry.NestedType.BBB
        test_proto = output_module.TestProto()
        proto_data_path = self.getResource(TEST_PROTO_DATA_NAME)
        self.assertTrue(os.path.exists(proto_data_path))
        self.assertTrue(os.path.isfile(proto_data_path))
        with open(proto_data_path) as f:
            text_format.Merge(f.read(), test_proto)
        self.assertEqual(len(test_proto.entries), 2)
        entry1 = test_proto.entries[0]
        self.compare_test_entry(entry1, "TestName1", 42,
                                [("NestedA", AAA), ("NestedB", BBB),
                                 ("NestedA", AAA)])
        entry2 = test_proto.entries[1]
        self.compare_test_entry(entry2, "TestName2", 43,
                                [("NestedB", BBB), ("NestedA", AAA),
                                 ("NestedB", BBB)])


#!/usr/bin/python3
"""Program that solves the N queens problem."""

from sys import argv, exit

def solution(n):
    """Solution"""
    res = []

    def boardPosition(row, left, right, m, arr):
        """ Check Board Positions"""
        if row == n:
            res.append(arr)
        else:
            left = left[1:] + [0]
            right = [0] + right[:-1]
            for col in range(n):
                if m[col] == left[col] == right[col] == 0:
                    left[col] = right[col] = m[col] = 1
                    pair = [] + arr
                    pair.append([row, col])
                    boardPosition(row + 1, left, right, m, pair)
                    left[col] = right[col] = m[col] = 0

    boardPosition(0, [0] * n, [0] * n, [0] * n, [])

    for positions in res:
        print(positions)

if __name__ == "__main__":
    if len(argv) is not 2:
        print("Usage: nqueens N")
        exit(1)
    elif argv[1].isdigit() is not True:
        print("N must be a number")
        exit(1)
    elif int(argv[1]) < 4:
        print("N must be at least 4")
        exit(1)

    solution(int(argv[1]))


#!/usr/bin/env python3

# Script Name:                  ops401d8-day37
# Author:                       Jonathan McMullin
# Date of latest revision:      08/29/2023
# Purpose:                      Cookie Capture Tool

# Credit: Utilized syntax from Code Fellows Demo and ChatGPT to develop this script

# Note: You will need to have Firefox and the Geckodriver

import requests
from bs4 import BeautifulSoup
from selenium import webdriver
from selenium.webdriver.firefox.options import Options

targetsite = input("Enter target site url: ")
response = requests.get(targetsite)
cookie = response.cookies

def bringforthcookiemonster(): # Because why not!
    print('''

              .---. .---.
             :     : o   :    me want cookie!
         _..-:   o :     :-.._    /
     .-''  '  `---' `---' "   ``-.
   .'   "   '  "  .    "  . '  "  `.
  :   '.---.,,.,...,.,.,.,..---.  ' ;
  `. " `.                     .' " .'
   `.  '`.                   .' ' .'
    `.    `-._           _.-' "  .'  .----.
      `. "    '"--...--"'  . ' .'  .'  o   `.

        ''')

def save_html_response(response_text):
    with open('response.html', 'w', encoding='utf-8') as f:
        f.write(response_text)

def open_html_with_firefox():
    options = Options()
    options.headless = True  # Set to False if you want to run Firefox in GUI mode
    driver = webdriver.Firefox(options=options)
    driver.get('file://' + 'response.html')

bringforthcookiemonster()
print("Target site is " + targetsite)
print(cookie)

# Send the cookie back to the site and receive an HTTP response
response_with_cookie = requests.get(targetsite, cookies=cookie)

# Generate a .html file to capture the contents of the HTTP response
save_html_response(response_with_cookie.text)

# Open it with Firefox
open_html_with_firefox()

# End


#简单的gui界面，搭配按钮点击
import tkinter as tk

window = tk.Tk()
window.title("购买阿里云服务器")   #窗体的标题
window.geometry("500x750")  #宽X长

var = tk.StringVar()
l=tk.Label(window,textvariable=var,bg='green',font=('Arial',12),width=15,height=2)    #配置label
l.pack()    #place方法就是具体放置，需要指明坐标

on_hit = False
def hit_me():
    #print("olalalala")  #如果这么写就是在后台打印
    global on_hit
    if on_hit == False:
        on_hit = True
        var.set("你点到我了！")   #将label里的var赋值
    else:
        on_hit = False
        var.set("")

b = tk.Button(window,text="点我啊！",width=15,height=2,command=hit_me)  #这个button是在window这个载体上运行的，点击之后会执行hit_me这个函数

b.pack()
window.mainloop()   #不断的循环刷新

制作一个简单的按钮.py

制作一个简单的按钮.py