import wx
import string
import sys
import os, os.path
from animation import CAnimation
from newanimation import NewAnimationDialog
import pypoujol.animation
from pypoujol import Animation, get_parent_class
import pypoujol.animation as animation
import wx.lib.imagebrowser as ib
from os.path import realpath, normpath, normcase, exists, join
from depplatform import get_image_path

oiLineHeight = 20

class InspectorEditorControl:
    """ Interface for controls that edit values in the Inspector
        values are stored in the native type of the control       """

    def __init__(self, propEditor, value):
        self.propEditor = propEditor
        self.editorCtrl = None
        self.wID = wx.NewId()
        self.value = value

    def createControl(self):
        if self.editorCtrl: self.editorCtrl.SetFocus()

    def destroyControl(self):
        """ Close an open editor control """
        if self.editorCtrl:
            self.editorCtrl.Destroy()
            self.editorCtrl = None

    def getValue(self):
        """ Read value from editor control """
        return self.value

    def setValue(self, value):
        """ Write value to editor control """
        self.value = value

    # default sizing for controls that span the entire value width
    def setWidth(self, width):
        if self.editorCtrl:
            height = self.editorCtrl.GetSize().y
            self.editorCtrl.SetSize(wx.Size(width -1, height))

    def setIdx(self, idx):
        """ Move the to the given index """
        if self.editorCtrl:
            self.editorCtrl.SetPosition( (-2, idx*oiLineHeight -2) )

    def OnSelect(self, event):
        """ Post the value.

            Bind the event of the control that 'sets' the value to this method
        """
        event.Skip()
        self.propEditor.inspectorPost(False)

class BevelIEC(InspectorEditorControl):
    def destroyControl(self):
        if self.bevelTop:
            self.bevelTop.Destroy()
            self.bevelTop = None
            self.bevelBottom.Destroy()
        InspectorEditorControl.destroyControl(self)

    def createControl(self, parent, idx, sizeX):
        self.bevelTop = wx.Panel(parent, -1,
            (0, idx*oiLineHeight -1), (sizeX, 1))
        self.bevelTop.SetBackgroundColour(wx.BLACK)
        self.bevelBottom = wx.Panel(parent, -1,
            (0, (idx + 1)*oiLineHeight -1), (sizeX, 1))
        self.bevelBottom.SetBackgroundColour(wx.WHITE)

    def setWidth(self, width):
        if self.bevelTop:
            self.bevelTop.SetSize(wx.Size(width, 1))
            self.bevelBottom.SetSize(wx.Size(width, 1))

    def setIdx(self, idx):
        if self.bevelTop:
            self.bevelTop.SetPosition(wx.Point(-2, idx*oiLineHeight -1))
            self.bevelBottom.SetPosition(wx.Point(-2, (idx +1)*oiLineHeight -1))
#        InspectorEditorControl.setIdx(self, idx)

class BeveledLabelIEC(BevelIEC):
    def createControl(self, parent, idx, sizeX):
        BevelIEC.createControl(self, parent, idx, sizeX)
        self.editorCtrl = wx.StaticText(parent, -1, self.value,
            (2, idx*oiLineHeight+2),
            (sizeX, oiLineHeight-3))
        self.editorCtrl.SetForegroundColour(wx.Colour(24, 24, 24)) #Preferences.propValueColour)

class TextCtrlIEC(InspectorEditorControl):
    ugly_hack = True

    def createControl(self, parent, value, idx, sizeX, style=wx.TE_PROCESS_ENTER):
        value = self.propEditor.valueToIECValue()
        self.editorCtrl = wx.TextCtrl(parent, self.wID, value,
              (-2, idx*oiLineHeight -2),
              (sizeX, oiLineHeight+3), style = style)
        wx.EVT_TEXT_ENTER(parent, self.wID, self.OnSelect)
        InspectorEditorControl.createControl(self)

        if value:
            self.editorCtrl.SetSelection(0, len(value))

        # Ugly hack. It doesn't get focus the very first time
        if TextCtrlIEC.ugly_hack:
            if wx.Platform != "__WXMSW__": wx.GetApp().frame.pb.Freeze()
            wx.GetApp().frame.pb.nb.SetSelection(1)
            wx.GetApp().frame.pb.nb.SetSelection(0)
            if wx.Platform != "__WXMSW__": wx.GetApp().frame.pb.Thaw()
            TextCtrlIEC.ugly_hack = False

    def getValue(self):
        if self.editorCtrl:
            self.value = self.editorCtrl.GetValue()
        return self.value

    def setValue(self, value):
        self.value = value
        if self.editorCtrl:
            self.editorCtrl.SetValue(value)

class ChoiceIEC(InspectorEditorControl):
    def createControl(self, parent, values, idx, sizeX, iec = None):
        self.editorCtrl = wx.Choice(parent, self.wID,
         wx.Point(-2, idx*oiLineHeight -1), wx.Size(sizeX, oiLineHeight+3),
         values)
        wx.EVT_CHOICE(self.editorCtrl, self.wID, self.OnSelect)
        InspectorEditorControl.createControl(self)
        self.iec = None

    def getValue(self):
        if self.editorCtrl:
            sel = self.editorCtrl.CurrentSelection
            #if sel != -1: return self.editorCtrl.GetClientData(sel)
            return self.editorCtrl.GetStringSelection()

    def setValue(self, value):
        if self.editorCtrl:
            self.editorCtrl.SetStringSelection(value)

    def repopulate(self):
        self.editorCtrl.Clear()
        for val in self.propEditor.getValues():
            self.editorCtrl.Append(val)

    def OnSelect(self, evt):
        InspectorEditorControl.OnSelect(self, evt)

class ComboIEC(InspectorEditorControl):
    def createControl(self, parent, idx, sizeX):
        self.editorCtrl = wxComboBox(parent, self.wID, self.value,
         wxPoint(-2, idx*Preferences.oiLineHeight -1), wxSize(sizeX, Preferences.oiLineHeight+3),
         self.propEditor.getValues())
        InspectorEditorControl.createControl(self);
    def getValue(self):
        if self.editorCtrl:
            return self.editorCtrl.GetStringSelection()
    def setValue(self, value):
        if self.editorCtrl:
            self.editorCtrl.SetSelection(self.editorCtrl.FindString(value))

class ButtonIEC(BevelIEC):
    btnSize = 18
    def createControl(self, parent, idx, sizeX, editMeth):
        bmp = wx.Image(get_image_path('ellipsis.xpm'), wx.BITMAP_TYPE_XPM).ConvertToBitmap()
        self.editorCtrl = wx.BitmapButton(parent, self.wID, bmp,
          wx.Point(sizeX - self.btnSize - 3, idx*oiLineHeight +1),
          wx.Size(self.btnSize, oiLineHeight-2))
        self.propValLabel = wx.StaticText(parent, -1, str(self.getValue()),
          wx.Point(2, idx*oiLineHeight+2),
          wx.Size(sizeX - self.btnSize - 6, oiLineHeight-3),
          style=wx.ST_NO_AUTORESIZE)
        wx.EVT_BUTTON(self.editorCtrl, self.wID, editMeth)
        BevelIEC.createControl(self, parent, idx, sizeX)

    def setWidth(self, width):
        if self.editorCtrl:
            self.editorCtrl.SetDimensions(width - self.btnSize - 3,
              self.editorCtrl.GetPosition().y, self.btnSize,
              oiLineHeight-2)
            self.propValLabel.SetDimensions(2,
              self.propValLabel.GetPosition().y, width - self.btnSize - 6,
              oiLineHeight-3)

        BevelIEC.setWidth(self, width)

    def setIdx(self, idx):
        if self.editorCtrl:
            self.editorCtrl.SetDimensions(self.editorCtrl.GetPosition().x,
              idx*oiLineHeight +2, self.btnSize,
              oiLineHeight-2)
            self.propValLabel.SetDimensions(
              self.propValLabel.GetPosition().x,
              idx*oiLineHeight +1, self.propValueLabel.GetSize().x,
              oiLineHeight-3)

        BevelIEC.setIdx(self, idx)

    def setValue(self, value):
        BevelIEC.setValue(self, value)
        self.propValLabel.SetLabel(str(value))

    def destroyControl(self):
        if self.editorCtrl:
            self.propValLabel.Destroy()
            self.propValLabel = None
        BevelIEC.destroyControl(self)

class TextCtrlButtonIEC(BevelIEC):
    def createControl(self, parent, value, idx, sizeX, editMeth = None):
        bmp = wx.Bitmap('images/ellipsis.xpm')
        value = self.propEditor.valueToIECValue()
        self.wID2 = wx.NewId()
        self.editorCtrl = [
              wx.TextCtrl(parent, self.wID, value,
               (-2, idx*oiLineHeight -2),
               (sizeX - 18, oiLineHeight+3)),#, style = style),
              wx.BitmapButton(parent, self.wID2, bmp,
               (sizeX - 18 -3, idx*oiLineHeight +1),
               (18, oiLineHeight-2))]
        EVT_BUTTON(self.editorCtrl[1], self.wID2, editMeth)

        if value:
            self.editorCtrl[0].SetSelection(0, len(value))

        BevelIEC.createControl(self, parent, idx, sizeX)

    def destroyControl(self):
        """ Close an open editor control """
        if self.editorCtrl:
            #self.editorCtrl.GetParent().SetFocus()
            for ec in self.editorCtrl:
                ec.Destroy()
            self.editorCtrl = None
        if self.bevelTop:
            self.bevelTop.Destroy()
            self.bevelTop = None
            self.bevelBottom.Destroy()
            self.bevelBottom = None

    # default sizing for controls that span the entire value width
    def setWidth(self, width):
        if self.editorCtrl:
            self.editorCtrl[0].SetSize(wxSize(width -18,
                  self.editorCtrl[0].GetSize().y))
            self.editorCtrl[1].SetDimensions(width - 18 -3,
                  self.editorCtrl[1].GetPosition().y, 18,
                  Preferences.oiLineHeight-2)

        BevelIEC.setWidth(self, width)

    def setIdx(self, idx):
        """ Move the to the given index """
        if self.editorCtrl:
            for ec in self.editorCtrl:
                ec.SetPosition(ec.GetPosition().x, idx*Preferences.oiLineHeight -2)
        BevelIEC.setIdx(self, idx)

    def getValue(self):
        if self.editorCtrl:
            self.value = self.editorCtrl[0].GetValue()
        return self.value

    def setValue(self, value):
        self.value = value
        if self.editorCtrl:
            self.editorCtrl[0].SetValue(value)

class CheckBoxIEC2(InspectorEditorControl):
    def createControl(self, parent, idx, sizeX):
        self.editorCtrl = wxWindow(parent, wxNewId(),
         style = wxTAB_TRAVERSAL | wxSUNKEN_BORDER)
        self.editorCtrl.SetDimensions(-2, idx*Preferences.oiLineHeight-2,
         sizeX, Preferences.oiLineHeight+3)

        self.checkBox = wxCheckBox(self.editorCtrl, self.wID, 'False', (2, 1))
        EVT_CHECKBOX(self.editorCtrl, self.wID, self.OnSelect)
        def OnWinSize(evt, win=self.checkBox):
            win.SetSize(evt.GetSize())
        EVT_SIZE(self.editorCtrl, OnWinSize)

        InspectorEditorControl.createControl(self)

    truefalseMap = {True: 'True', False: 'False'}
    def getValue(self):
        if self.editorCtrl:
            return self.truefalseMap[self.editorCtrl.GetValue()]
    def setValue(self, value):
        if self.editorCtrl:
            self.editorCtrl.SetLabel(value)
            self.editorCtrl.SetValue(self.truefalseMap[True] == value)

    def OnSelect(self, event):
        if event.IsChecked():
            self.setValue(self.truefalseMap[event.IsChecked()])

        InspectorEditorControl.OnSelect(self, event)

class CheckBoxIEC(BevelIEC):
    def createControl(self, parent, idx, sizeX):
        self.editorCtrl = wx.CheckBox(parent, self.wID, 'False',
            (2, idx*oiLineHeight+1),
            (sizeX, oiLineHeight-2) )
        wx.EVT_CHECKBOX(self.editorCtrl, self.wID, self.OnSelect)

        BevelIEC.createControl(self, parent, idx, sizeX)

    truefalseMap = {True: 'True', False: 'False'}
    def getValue(self):
        if self.editorCtrl:
            return self.truefalseMap[self.editorCtrl.GetValue()]
        else:
            return self.value
    def setValue(self, value):
        if self.editorCtrl:
            self.editorCtrl.SetLabel(value)
            self.editorCtrl.SetValue(
                string.lower(self.truefalseMap[True]) == string.lower(value))

    def setIdx(self, idx):
        if self.editorCtrl:
            self.editorCtrl.SetDimensions(2, idx*Preferences.oiLineHeight +1,
            self.editorCtrl.GetSize().x, Preferences.oiLineHeight-2)
        BevelIEC.setIdx(self, idx)
        # InspectorEditorControl.setIdx(self, idx)

    def OnSelect(self, event):
        self.setValue(self.truefalseMap[event.IsChecked()])

        BevelIEC.OnSelect(self, event)

import  wx.lib.popupctl as  pop
import  wx.calendar     as  cal

thumbnail_size = 64

class AnimationPanel(wx.Panel):
    class ThumbnailCache:
        def __init__(self):
            self.cache = {}

        def get_thumbnail(self, filename):
            filename = join(wx.GetApp().frame.project.project_path, filename)
            if not exists(filename):
                return None
            if self.cache.has_key(filename):
                return self.cache[filename]
            img = wx.Image(filename)
            w, h = img.GetWidth(), img.GetHeight()
            if w > h:
                h *= thumbnail_size / float(w)
                w = thumbnail_size
            else:
                w *= thumbnail_size / float(h)
                h = thumbnail_size

            img.Rescale(w, h)
            bmp = wx.BitmapFromImage(img)
            self.cache[filename] = bmp
            return bmp

    cache = ThumbnailCache()

    def __init__(self, parent, iec, poz):
        wx.Panel.__init__(self, parent, pos = poz)
        self.parent = parent
        self.iec = iec

        n = len(pypoujol.animation.anim_classes.values()) + 2
        self.SetSize((thumbnail_size * 4 + 40, (n / 4) * thumbnail_size + 104))
        parent.SetSize((thumbnail_size * 4 + 40, (n / 4) * thumbnail_size + 104))

    def create_buttons(self):
        def is_derived_from(c, b):
            try:
                for i in c.__bases__:
                    if b == i: return True
                    if is_derived_from(i, b): return True
                return None
            except: pass # Not a class ?

        if sys.platform == "darwin": pos = (20, 20)
        else: pos = (20, 20)
        cancel = wx.Button(self, 30, "Cancel\n", pos = pos, size = (thumbnail_size, thumbnail_size))
        cancel.Bind(wx.EVT_BUTTON, self.on_cancel_button)
        n = 1
        pos = ((n % 4) * thumbnail_size + 20, (n / 4) * thumbnail_size + 20)
        nonebutton = wx.Button(self, -1, "None\n", pos = pos, size = (thumbnail_size, thumbnail_size))
        nonebutton.Bind(wx.EVT_BUTTON, self.on_none_button)
        n += 1
        newanimbutton = wx.Button(self, -1, "From file\n",
            pos = ((n % 4) * thumbnail_size + 20,
                   (n / 4) * thumbnail_size + 20),
            size = (thumbnail_size, thumbnail_size))
        newanimbutton.Bind(wx.EVT_BUTTON, self.on_new_anim_button)
        n += 1
        self.buttons = []

        for i, filename, j in pypoujol.animation.anim_classes.values():
            if (not filename) or (not filename[0]): continue
            filename = filename[0]
            bmp = self.cache.get_thumbnail(filename)
            if not bmp: continue
            b = wx.BitmapButton(self, 30 + n, bmp, ((n % 4) * thumbnail_size + 20, (n / 4) * thumbnail_size + 20), (thumbnail_size, thumbnail_size))
            self.buttons.append(b)
            try:
                parent_class = get_parent_class(j)
                b.image = parent_class
                b.Bind(wx.EVT_BUTTON, self.on_button)
                n = n + 1
            except: pass

    def on_cancel_button(self, evt):
        self.iec.editorCtrl.PopDown()

    def on_none_button(self, evt):
        self.iec.editorCtrl.SetValue("None")
        self.iec.editorCtrl.PopDown()

    def on_new_anim_button(self, evt):
        self.iec.editorCtrl.PopDown()

        newanimdlg = NewAnimationDialog(wx.GetApp().frame, -1, size = (500, 400),
                                        style = wx.DEFAULT_DIALOG_STYLE)
        newanimdlg.CenterOnScreen()
        newanimdlg.name.SetValue(self.iec.resource.__class__.__name__ + "_anim")
        val = newanimdlg.ShowModal()

        if val == wx.ID_OK:
            project = wx.GetApp().frame.project
            res = wx.GetApp().frame.pb.active_resource
            res.sync()
            name = newanimdlg.name.GetValue()
            filename = project.ask_to_import(newanimdlg.filename.GetValue())

            if filename.endswith('.psd'):
                import PIL.Image
                img = PIL.Image.open(str(filename))
                base = str(filename[:-4]) + '.png'
                import tempfile
                import exceptions
                import shutil

                tempdir = tempfile.gettempdir()
                tempdir = tempdir + '/psd_outputs'
                shutil.rmtree(tempdir, ignore_errors=True)

                try: os.mkdir(tempdir)
                except: pass

                for index, layer in enumerate(img.layers):
	                img.seek(index)
	                img.save(join(tempdir, os.path.basename(base) + "_" + layer[0].decode('utf-8') + ".png"))

                dlg = ib.ImageDialog(self, tempdir)
                dlg.Centre()

                if dlg.ShowModal() == wx.ID_OK:
                    filename = wx.GetApp().frame.project.project_path + '/' + os.path.basename(dlg.GetFile())
                    shutil.copyfile(dlg.GetFile(), filename)

                else:
                    self.iec.editorCtrl.PopDown()
                    newanimdlg.Destroy()
                    return

                shutil.rmtree(tempdir, ignore_errors=True)

            nom = get_parent_class(self.iec.resource.__class__)
            classe = res.get_class(nom)
            c = classe.add_class(name, ["Animation"], [
                           "filenames = [" + repr(filename) + "]\n"])
            res.ast_has_changed = True
            res.topy()
            wx.GetApp().gns.run(res.listing)
            wx.GetApp().artub_frame.update_treeitem(res)
            self.iec.editorCtrl.SetValue(nom + '.' + name)
            if os.name != "posix": # Hack
                self.iec.editorCtrl.PopDown()
            self.iec.propEditor.inspectorPost(False)

        newanimdlg.Destroy()

    def on_button(self, evt):
        self.iec.editorCtrl.SetValue(evt.GetEventObject().image)
        self.iec.editorCtrl.PopDown()
        self.iec.propEditor.inspectorPost(False)
        evt.Skip()

from    wx.lib import masked
import  wx.lib.colourselect as  csel

class FloatCtrlIEC(InspectorEditorControl):
    def createControl(self, parent, value, idx, sizeX, constraints):
        self.editorCtrl = masked.NumCtrl(
                                parent, pos=(-2, idx*oiLineHeight-2),
                                size=(sizeX, oiLineHeight+3), value=value,
                                integerWidth=constraints[0],
                                fractionWidth=constraints[1], allowNegative=constraints[2],
                                min=constraints[3], max=constraints[4],
                                limited=constraints[5], autoSize=constraints[6])

    def getValue(self):
        self.value = self.editorCtrl.GetValue()
        return self.value

class ColorIEC(InspectorEditorControl):
    def createControl(self, parent, value, idx, sizeX, style=wx.TE_PROCESS_ENTER):
        # r = value[0] * 255
        # g = value[1] * 255
        # b = value[2] * 255
        r = value[0]
        g = value[1]
        b = value[2]
        self.parent = parent
        self.sizeX = sizeX
        self.idx = idx
        s = "(%d, %d, %d)" % (r, g, b)
        self.editorCtrl = csel.ColourSelect(parent, 2000, s, wx.Color(r, g, b),
                                            size=(sizeX, oiLineHeight+3),
                                            pos=(-2, idx*oiLineHeight-2))
        self.editorCtrl.Bind(csel.EVT_COLOURSELECT, self.on_select_color, id=2000)

    def getValue(self):
        self.value = self.editorCtrl.GetValue()
        self.value = (self.value.Red(), self.value.Green(), self.value.Blue())
        # self.value = (self.value.Red() / 255., self.value.Green() / 255., self.value.Blue() / 255.)
        return self.value

    def on_select_color(self, evt):
        value = evt.GetValue()
        self.editorCtrl.Destroy()
        s = "(%d, %d, %d)" % (value[0], value[1], value[2])
        self.editorCtrl = csel.ColourSelect(self.parent, 2000, s, wx.Color(value[0], value[1], value[2]),
                                            size=(self.sizeX, oiLineHeight+3),
                                            pos=(-2, self.idx*oiLineHeight-2))
        self.editorCtrl.Refresh()
        self.propEditor.inspectorPost(False)

class AnimationIEC(InspectorEditorControl):
    def createControl(self, parent, value, idx, sizeX, style=wx.TE_PROCESS_ENTER):
        self.editorCtrl = pop.PopupControl(parent, -1, pos = (0,0), size = (sizeX,oiLineHeight))
        self.win = wx.Window(self.editorCtrl, wx.NewId(),
         style = wx.TAB_TRAVERSAL | wx.SUNKEN_BORDER, size = (-1, -1)) # (200,200))
        self.win.Show(False)
        self.editorCtrl.SetDimensions(-2, idx*oiLineHeight-2,
         sizeX, oiLineHeight+3)

        self.cal = AnimationPanel(self.win, self, (0,0))
        self.cal.resource = self.resource

        self.editorCtrl.SetValue(value)
        self.editorCtrl.SetPopupContent(self.win)
        InspectorEditorControl.createControl(self)
        self.cal.create_buttons()

        wx.EVT_KILL_FOCUS(self.cal, self.on_left_button_down)

    def on_left_button_down(self, evt):
        # self.editorCtrl.PopDown()
        evt.Skip()

    def getValue(self):
        if self.editorCtrl:
            return self.editorCtrl.GetValue()

    def setValue(self, value):
        if self.editorCtrl:
            self.editorCtrl.SetLabel(value)
            self.editorCtrl.SetValue(self.truefalseMap[True] == value)

    def OnSelect(self, event):
        if event.IsChecked():
            self.setValue(self.truefalseMap[event.IsChecked()])

        InspectorEditorControl.OnSelect(self, event)


import datetime
import unittest
import logging
from asciiserialcom.message import ASC_Message
from asciiserialcom.host import Host
from asciiserialcom.errors import *
from asciiserialcom.utilities import Tracer
from asciiserialcom.tty_utils import setup_tty
import trio
import termios
import time

class TestRxCounterFromDevice(unittest.TestCase):
    """
    Requires firmware:

        openocd -f /usr/share/openocd/scripts/board/st_nucleo_f0.cfg -c "program build/cortex-m0_gcc_debug/stm32f091nucleo64_write_pattern_to_serial.elf verify reset exit"

    """

    def setUp(self):
        self.baud = 9600
        self.dev_path = "/dev/ttyACM0"
        # self.dev_path = "/dev/ttyACM1"

        logging.basicConfig(
            # filename="test_asciiSerialCom.log",
            # level=logging.INFO,
            # level=logging.DEBUG,
            level=logging.WARNING,
            # format="%(asctime)s %(levelname)s L%(lineno)d %(funcName)s: %(message)s"
            format="%(message)s",
        )
        setup_tty(self.dev_path, self.baud)

    def test_just_device(self):
        async def receiver(chan, f):
            while True:
                data = await f.read(1)
                if len(data) == 0:
                    continue
                await chan.send(data)

        async def data_checker(self, chan, data_checker_finished):
            last = None
            logging.debug("Starting data_checker")
            for i in range(400):
                await chan.receive()
            for i in range(2000):
                data = await chan.receive()
                num = int(data)
                logging.debug(f"{i:5} {num:2}")
                if last == 9:
                    self.assertEqual(num, 0)
                elif last:
                    self.assertEqual(num, last + 1)
                last = num
            data_checker_finished.set()

        async def run_test(self):
            logging.info("Starting run_test")
            send_chan, recv_chan = trio.open_memory_channel(100)
            data_checker_finished = trio.Event()
            got_to_cancel = False
            with trio.move_on_after(10):
                logging.info("About to open file...")
                async with await trio.open_file(self.dev_path, "br") as portr:
                    termios.tcflush(portr.wrapped, termios.TCIFLUSH)
                    logging.debug("flushed input buffer")
                    await portr.read(400)
                    async with trio.open_nursery() as nursery:
                        nursery.start_soon(receiver, send_chan, portr)
                        nursery.start_soon(
                            data_checker, self, recv_chan, data_checker_finished
                        )
                        await data_checker_finished.wait()
                        nursery.cancel_scope.cancel()
            self.assertTrue(data_checker_finished.is_set())

        trio.run(run_test, self)

class TestRxASCCounterFromDevice(unittest.TestCase):
    """
    Requires firmware:

        openocd -f /usr/share/openocd/scripts/board/st_nucleo_f0.cfg -c "program build/cortex-m0_gcc_debug/stm32f091nucleo64_adc_streaming.elf verify reset exit"

    """

    def setUp(self):
        self.baud = 9600
        # self.baud = 19200
        self.dev_path = "/dev/ttyACM0"
        # self.dev_path = "/dev/ttyACM1"

        logging.basicConfig(
            # filename="test_asciiSerialCom.log",
            # level=logging.INFO,
            # level=logging.DEBUG,
            level=logging.WARNING,
            format="%(levelname)s L%(lineno)d %(funcName)s: %(message)s",
        )
        setup_tty(self.dev_path, self.baud)
        self.max32bits = 2 ** 32 - 1

    def test_host_device(self):
        nRegisterBits = 32

        async def data_checker(self, chan, data_checker_finished):
            logging.debug("Starting data_checker",)
            last = None
            starttime = time.time()
            nMessages = 200
            messageLen = 0
            for iMessage in range(nMessages):
                nMissed, data = await chan.receive()
                logging.info(f"message received: {nMissed} {data}")
                num = int(data.decode()[0], 16)
                if last == self.max32bits:
                    self.assertEqual(num, 0)
                elif last:
                    self.assertEqual(num, last + 1)
                last = num
                if iMessage == 0:
                    messageLen = len(data) + 10
            endtime = time.time()
            deltat = endtime - starttime
            tpermessage = deltat / nMessages
            tperbyte = tpermessage / messageLen
            bitpers = 1 / tperbyte * 8
            logging.warning(
                f"Time spent per message: {tpermessage} s, per byte: {tperbyte}, per bit: {1./bitpers}"
            )
            logging.warning(
                f"Message per second {1./tpermessage}, byte per second: {1./tperbyte}, bit per second: {bitpers}"
            )
            data_checker_finished.set()

        async def run_test(self):
            logging.info("Starting run_test")
            send_chan, recv_chan = trio.open_memory_channel(100)
            data_checker_finished = trio.Event()
            with trio.move_on_after(10) as cancel_scope:
                logging.info("About to open file...")
                async with await trio.open_file(self.dev_path, "br") as portr:
                    async with await trio.open_file(self.dev_path, "bw") as portw:
                        logging.debug("files opened")
                        async with trio.open_nursery() as nursery:
                            logging.debug("About to startup host")
                            host = Host(nursery, portr, portw, nRegisterBits)
                            logging.debug("Host started")
                            host.forward_received_s_messages_to(send_chan)
                            logging.debug("messages now forwarded to send_chan")
                            nursery.start_soon(
                                data_checker, self, recv_chan, data_checker_finished
                            )
                            await host.write_register(2, 1)  # set to counter mode
                            await host.start_streaming()
                            logging.debug(
                                "data_checker starting soon, waiting for it to finish"
                            )
                            await data_checker_finished.wait()
                            logging.debug("data_checker_finished")
                            await host.stop_streaming()
                            await host.write_register(
                                2, 0
                            )  # set back to default ADC mode
                            nursery.cancel_scope.cancel()
            self.assertTrue(data_checker_finished.is_set())

        trio.run(run_test, self)


import pandas as pd
import matplotlib.pyplot as plt
import datetime
# A. Load data for a specific time period
def load_data(start_date, end_date):
    # Read the CSV file
    df = pd.read_csv('data.csv')

    # Convert date_created column to datetime format
    df['date_created'] = pd.to_datetime(df['date_created'], utc=True)

    # Filter the data for the specified time period
    mask = (df['date_created'].dt.date >= start_date) & (df['date_created'].dt.date <= end_date)
    filtered_df = df[mask]

    return filtered_df

# B. Calculate statistics for the selected dates
def calculate_statistics(df):
    # Calculate minimum, maximum, mean, standard deviation, and variance
    min_poso = df['poso'].min()
    max_poso = df['poso'].max()
    mean_poso = df['poso'].mean()
    std_poso = df['poso'].std()
    var_poso = std_poso ** 2

    return min_poso, max_poso, mean_poso, std_poso, var_poso

# C. Calculate total outstanding bills per apartment building
def calculate_debts_per_building(df):
    # Group the data by buildingID and sum the outstanding amounts
    debts_per_building = df.groupby('buildingID')['poso'].sum()

    return debts_per_building

# D. Generate required graphs
def generate_graphs(data):
    # Total debts per apartment building
    debts_per_building = data.groupby('buildingID')['poso'].sum()
    plt.figure(figsize=(10, 5))
    plt.bar(debts_per_building.index, debts_per_building.values)
    plt.xlabel('buildingID')
    plt.ylabel('Total Debts')
    plt.title('Total Debts per Apartment Building')
    plt.show()

    # Debts per month/year
    data['date_created'] = pd.to_datetime(data['date_created'])
    debts_per_month_year = data.groupby(data['date_created'].dt.to_period('M'))['poso'].sum()
    plt.figure(figsize=(10, 5))
    plt.plot(debts_per_month_year.index.astype(str), debts_per_month_year.values)
    plt.xlabel('Month/Year')
    plt.ylabel('Total Debts')
    plt.title('Debts per Month/Year')
    plt.xticks(rotation=45)
    plt.show()

    # Number of expenses per apartment building
    expenses_per_building = data.groupby('buildingID').size()
    plt.figure(figsize=(10, 5))
    plt.bar(expenses_per_building.index, expenses_per_building.values)
    plt.xlabel('buildingID')
    plt.ylabel('Number of Expenses')
    plt.title('Number of Expenses per Apartment Building')
    plt.show()

    # Total debts per apartment building per month
    debts_per_building_month = data.groupby(['buildingID', data['date_created'].dt.to_period('M')])['poso'].sum()
    debts_per_building_month.unstack(level=0).plot(kind='bar', figsize=(10, 5))
    plt.xlabel('Month')
    plt.ylabel('Total Debts')
    plt.title('Total Debts per Apartment Building per Month')
    plt.legend(title='buildingID')
    plt.show()

def get_time_period():
    while True:
        try:
            start_date_str = input("Enter the start date (YYYY-MM-DD): ")
            start_date = datetime.datetime.strptime(start_date_str, "%Y-%m-%d").date()

            end_date_str = input("Enter the end date (YYYY-MM-DD): ")
            end_date = datetime.datetime.strptime(end_date_str, "%Y-%m-%d").date()

            if start_date > end_date:
                print("Start date cannot be greater than end date. Please try again.")
                continue

            return start_date, end_date

        except ValueError:
            print("Invalid date format. Please enter the date in the format YYYY-MM-DD.")

def print_stats(data):
    min_poso, max_poso, mean_poso, std_poso, var_poso = calculate_statistics(data)
    print('Statistics for the selected dates:')
    print('Minimum Poso:', min_poso)
    print('Maximum Poso:', max_poso)
    print('Mean Poso:', mean_poso)
    print('Standard Deviation:', std_poso)
    print('Variance:', var_poso)
# Usage example:
start_date, end_date = get_time_period()

data = load_data(start_date, end_date)
print_stats(data)
# Generate the required graphs
generate_graphs(data)


def emptyCallBack(pram1, pram2):
    return;

import cv2
import numpy as np

cap = cv2.VideoCapture(0)
# create trackbars for color change
#cv2.createTrackbar('HMin','image',0,255,nothing)
cv2.namedWindow('image')
cv2.createTrackbar('HMin','image',0,255,emptyCallBack)
cv2.createTrackbar('HMax','image',0,255,emptyCallBack)
cv2.createTrackbar('SMin','image',0,255,emptyCallBack)
cv2.createTrackbar('SMax','image',0,255,emptyCallBack)
cv2.createTrackbar('VMin','image',0,255,emptyCallBack)
cv2.createTrackbar('VMax','image',0,255,emptyCallBack)

while(1):

    # Take each frame
    _, frame = cap.read()

    # Convert BGR to HSV
    hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
# get current positions of four trackbars
    hMin = cv2.getTrackbarPos('HMin','image')
    hMax = cv2.getTrackbarPos('HMax','image')
    sMin = cv2.getTrackbarPos('SMin','image')
    sMax = cv2.getTrackbarPos('SMax','image')
    vMin = cv2.getTrackbarPos('VMin','image')
    vMax = cv2.getTrackbarPos('VMax','image')

    # define range of blue color in HSV
    lower_blue = np.array([110,50,50])
    upper_blue = np.array([130,255,255])
    lower_green = np.array([hMin,sMin,vMin])
    upper_green = np.array([hMax,sMax,vMax])

    # Threshold the HSV image to get only blue colors
    mask = cv2.inRange(hsv, lower_green, upper_green)

    # Bitwise-AND mask and original image
    res = cv2.bitwise_and(frame,frame, mask= mask)

    cv2.imshow('frame',frame)
    cv2.imshow('mask',mask)
    cv2.imshow('res',res)
    cv2.imwrite('filteredImage.png',mask)
    k = cv2.waitKey(5) & 0xFF
    if k == 27:
        break

cv2.destroyAllWindows()


import random

# Q = []

# for i in range(20):
#     Q.append(random.randint(1,100))

# if Q:
#     max_value, max_position = max(Q), Q.index(max(Q)) + 1
#     min_value, min_position = min(Q), Q.index(min(Q)) + 1

#     print(f'O maior elemento é {max_value} na posição {max_position}')
#     print(f'O menor elemento é {min_value} na posição {min_position}')
# else:
#     print('Não foram fornecidos números positivos')

lista = []
resultado_da_soma = 0

for n in range(10):
    lista.append(random.randint(1,10))

for i in lista:
    if(i % 2) == 0:
        resultado_da_soma = resultado_da_soma + i

print(f'O resultado da soma é: {resultado_da_soma}')
print(lista)


from abc import ABC, abstractmethod
import json
from os import stat
import traceback

from django.conf import settings
from api.models.campaign.campaign import Campaign
from api.models.facebook.facebook_page import FacebookPage
from api.models.youtube.youtube_channel import YoutubeChannel
from api.models.instagram.instagram_profile import InstagramProfile
from api.models.user.user_subscription import UserSubscription
from api.models.user.static_assets import StaticAssets

from api.models.order.order import Order
from api.models.order.pre_order import PreOrder
from api.models.order.order_product import OrderProduct
from api.models.cart.cart import Cart

from lib.error_handle.error.api_error import ApiVerifyError
import service
from business_policy.subscription_plan import SubscriptionPlan
import hashlib
from api import models
from bson.objectid import ObjectId
import database

platform_dict = {'facebook': FacebookPage, 'youtube': YoutubeChannel, 'instagram': InstagramProfile}

class VerifyRequestFromWhome(ABC):

    @staticmethod
    @abstractmethod
    def verify(request, pk=None):
        ...

class Verify():

    @staticmethod
    def is_platform_admin(api_user, platform_name, platform):
        try:
            if platform_name == 'facebook':
                status_code, response = service.facebook.user.get_me_accounts(
                    api_user.facebook_info['token'])

                for item in response['data']:
                    if item['id'] == platform.page_id:
                        return True
                return False
            elif platform_name == 'youtube':
                # return api_user.youtube_info[''] == platform.xxx
                return True
            elif platform_name == 'instagram':
                # api_user.instagram_info['']

                return True
        except Exception as e:
            return False
        return False

    @staticmethod
    def language_supported(language):
        if language not in settings.SUPPORTED_LANGUAGES:
            raise ApiVerifyError('util.language_not_supported')

    @staticmethod
    def check_is_admin_by_token(token, platform_name, platform):
        try:
            if platform_name == 'facebook':
                status_code, response = service.facebook.user.get_me_accounts(
                    token)
                for item in response['data']:
                    if item['id'] == platform.page_id:
                        return True
                return False
            elif platform_name == 'youtube':
                # return api_user.youtube_info[''] == platform.xxx
                return True
            elif platform_name == 'instagram':
                # api_user.instagram_info['']

                return True
        except Exception as e:
            return False
        return False

    @staticmethod
    def get_customer_user(request):
        if not request.user.api_users.filter(type='customer').exists():
            raise ApiVerifyError('util.no_api_user_found')
        return request.user.api_users.get(type='customer')

    @staticmethod
    def get_seller_user(request):
        if not request.user.api_users.filter(type='user').exists():
            raise ApiVerifyError('util.no_api_user_found')
        api_user = request.user.api_users.get(type='user')
        if api_user.status != "valid":
            raise ApiVerifyError("util.not_activated_user")
        return api_user

    @staticmethod
    def get_seller_user_from_scope(scope):
        auth_user = scope.get('user')
        if not auth_user:
            raise ApiVerifyError('util.no_api_user_found')
        if not auth_user.api_users.filter(type='user').exists():
            raise ApiVerifyError('util.no_api_user_found')
        api_user = auth_user.api_users.get(type='user')
        if api_user.status != "valid":
            raise ApiVerifyError("util.not_activated_user")
        return api_user

    @staticmethod
    def verify_user(api_user):
        if not api_user:
            raise ApiVerifyError("util.no_api_user_found")
        elif api_user.status != "valid":
            raise ApiVerifyError("util.not_activated_user")

    @classmethod
    def get_platform(cls, api_user, platform_name, platform_id):
        if platform_name not in platform_dict:
            raise ApiVerifyError("util.no_platform_name_found")
        if not platform_dict[platform_name].objects.filter(id=platform_id).exists():
            raise ApiVerifyError("util.no_platform_found")
        platform = platform_dict[platform_name].objects.get(
            id=platform_id)
        # if not cls.is_platform_admin(api_user, platform_name, platform):
        #     raise ApiVerifyError("user is not platform admin")
        return platform

    @classmethod
    def get_platform_from_user_subscription(cls, user_subscription, platform_name, platform_id):
        if platform_name not in models.user.user_subscription.PLATFORM_ATTR:
            raise ApiVerifyError('util.not_support_platform')

        if not getattr(user_subscription, models.user.user_subscription.PLATFORM_ATTR[platform_name]['attr']).filter(id=platform_id).exists():
            raise ApiVerifyError('util.no_platform_found')

        return getattr(user_subscription, models.user.user_subscription.PLATFORM_ATTR[platform_name]['attr']).get(id=platform_id)

    @classmethod
    def get_platform_verify_with_token(cls, token, platform_name, platform_id):
        if platform_name not in platform_dict:
            raise ApiVerifyError("util.no_platform_name_found")
        if not platform_dict[platform_name].objects.filter(id=platform_id).exists():
            raise ApiVerifyError("util.no_platform_found")
        platform = platform_dict[platform_name].objects.get(
            id=platform_id)
        if not cls.check_is_admin_by_token(token, platform_name, platform):
            raise ApiVerifyError("util.user_is_not_platform_admin")
        return platform

    @staticmethod
    def get_support_stock_user_subscriptions_from_user_subscription(support_stock_user_subscription_id,self_user_subscription_subscription):
        support_stock_user_subscriptions = json.loads(json.dumps(self_user_subscription_subscription.meta_store.get("support_stock_user_subscriptions", [])))
        print(support_stock_user_subscriptions)
        for i in support_stock_user_subscriptions:
            try:
                if i.get("user_subscription_id","") == int(support_stock_user_subscription_id):
                    return models.user.user_subscription.UserSubscription.objects.get(id=support_stock_user_subscription_id)
            except:
                print(traceback.format_exc())
        raise ApiVerifyError("util.no_support_stock_user_subscription_found")
    @staticmethod
    def get_cart(cart_id):
        if not Cart.objects.filter(id=cart_id).exists():
            raise ApiVerifyError('util.no_cart_found')
        return Cart.objects.get(id=cart_id)

    @staticmethod
    def get_cart_from_user_subscription(user_subscription, cart_id):
        if not user_subscription.carts.filter(id=cart_id).exists():
            raise ApiVerifyError('util.no_cart_found')
        return user_subscription.carts.get(id=cart_id)

    @staticmethod
    def get_cart_with_oid(oid):
        try:
            _id=ObjectId(oid)
        except Exception:
            raise ApiVerifyError('util.no_cart_found')

        cart = database.lss.cart.Cart.get(_id=_id)
        if not cart:
            raise ApiVerifyError('util.no_cart_found')
        return Cart.objects.get(id=cart['id'])

    @staticmethod
    def get_user_register_with_oid(oid):
        try:
            _id=ObjectId(oid)
        except Exception:
            raise ApiVerifyError('no registeration found')

        user_register = database.lss.user_register.UserRegister.get(_id=_id)
        if not user_register:
            raise ApiVerifyError('no registeration found')
        return models.user.user_register.UserRegister.objects.get(id=user_register['id'])

    @staticmethod
    def get_pre_order(pre_order_id):
        if not PreOrder.objects.filter(id=pre_order_id).exists():
            raise ApiVerifyError('util.no_pre_order_found')
        return PreOrder.objects.get(id=pre_order_id)

    @staticmethod
    def get_pre_order_with_oid(oid):
        try:
            _id=ObjectId(oid)
        except Exception:
            raise ApiVerifyError('util.no_pre_order_found')

        pre_order = database.lss.pre_order.PreOrder.get(_id=_id)
        # pre_order=db.api_pre_order.find_one({"_id":_id})
        if not pre_order:
            raise ApiVerifyError('util.no_pre_order_found')
        return PreOrder.objects.get(id=pre_order['id'])

    @staticmethod
    def get_order_product(order_product_id):
        if not OrderProduct.objects.filter(id=order_product_id).exists():
            raise ApiVerifyError('util.no_order_product_found')
        return OrderProduct.objects.get(id=order_product_id)

    @staticmethod
    def get_order(order_id):
        if not Order.objects.filter(id=order_id).exists():
            raise ApiVerifyError('util.no_order_found')
        return Order.objects.get(id=order_id)

    @staticmethod
    def get_order_from_user_subscription(user_subscription, order_id):
        if not user_subscription.orders.filter(id=order_id).exists():
            raise ApiVerifyError('util.no_order_found')
        return user_subscription.orders.get(id=order_id)

    @staticmethod
    def get_order_with_oid(oid):
        try:
            _id=ObjectId(oid)
        except Exception:
            raise ApiVerifyError('util.no_order_found')
        # order=db.api_order.find_one({"_id":_id})
        order = database.lss.order.Order.get(_id=_id)
        if not order:
            raise ApiVerifyError('util.no_order_found')
        return Order.objects.get(id=order['id'])

    @staticmethod
    def get_order_by_api_user(api_user, order_id):
        if not api_user.orders.filter(id=order_id).exists():
            raise ApiVerifyError('util.no_order_found')
        return api_user.orders.get(id=order_id)

    @staticmethod
    def get_user_subscription(user_subscription_id):
        if not UserSubscription.objects.filter(id=user_subscription_id).exists():
            raise ApiVerifyError("util.user_subscription_not_found")
        return UserSubscription.objects.get(id=user_subscription_id)

    @staticmethod
    def get_user_subscription_from_platform(platform):
        user_subscriptions = platform.user_subscriptions.all()
        if not user_subscriptions:
            raise ApiVerifyError("util.platform_not_in_any_user_subscription")
        user_subscription = user_subscriptions[0]
        return user_subscription

    @staticmethod
    def get_customer_from_user_subscription(user_subscription, customer_id):
        if not user_subscription.customers.filter(id=customer_id).exists():
            raise ApiVerifyError("customer_not_found")
        return user_subscription.customers.get(id=customer_id)

    @staticmethod
    def get_user_subscription_from_api_user(api_user):
        user_subscription = api_user.user_subscription
        if not user_subscription:
            raise ApiVerifyError("util.user_subscription_not_found")
        return user_subscription

    @staticmethod
    def get_assets_from_user_subscription(user_subscription, id):
        if not user_subscription.assets.filter(id=id).exists():
            raise ApiVerifyError("util.static_assets_not_found")
        return user_subscription.assets.get(id=id)

    @staticmethod
    def get_dealer_user_subscription_from_api_user(api_user):
        user_subscription = api_user.user_subscription
        if not user_subscription:
            raise ApiVerifyError("util.user_subscription_not_found")
        if user_subscription.type != "dealer":
            raise ApiVerifyError("util.not_dealer")
        return user_subscription

    def get_user_subscription_from_dealer_user_subscription(dealer_user_subscription, user_subscription_id):
        if not dealer_user_subscription.subscribers.filter(id=user_subscription_id).exists():
            raise ApiVerifyError("util.user_subscription_not_found")
        return dealer_user_subscription.subscribers.get(id=user_subscription_id)

    @staticmethod
    def get_facebook_page_from_user_subscription(user_subscription, facebook_page_id):
        if not user_subscription.facebook_pages.filter(id=facebook_page_id).exists():
            raise ApiVerifyError("util.facebook_page_not_bound_to_user_subscription")
        return user_subscription.facebook_pages.get(id=facebook_page_id)

    @staticmethod
    def get_youtube_channel_from_user_subscription(user_subscription, youtube_channel_id):
        if not user_subscription.youtube_channels.filter(id=youtube_channel_id).exists():
            raise ApiVerifyError("util.youtube_channel_not_bound_to_user_subscription")
        return user_subscription.youtube_channels.get(id=youtube_channel_id)

    @staticmethod
    def get_instagram_profile_from_user_subscription(user_subscription, instagram_profile_id):
        if not user_subscription.instagram_profiles.filter(id=instagram_profile_id).exists():
            raise ApiVerifyError("util.instagram_profile_not_bound_to_user_subscription")
        return user_subscription.instagram_profiles.get(id=instagram_profile_id)

    @staticmethod
    def get_twitch_channel_from_user_subscription(user_subscription, twitch_channel_id):
        if not user_subscription.twitch_channels.filter(id=twitch_channel_id).exists():
            raise ApiVerifyError("util.twitch_channels_not_bound_to_user_subscription")
        return user_subscription.twitch_channels.get(id=twitch_channel_id)

    @staticmethod
    def get_tiktok_channel_from_user_subscription(user_subscription, tiktok_account_id):
        if not user_subscription.tiktok_accounts.filter(id=tiktok_account_id).exists():
            raise ApiVerifyError("util.tiktok_accounts_not_bound_to_user_subscription")
        return user_subscription.tiktok_accounts.get(id=tiktok_account_id)

    @staticmethod
    def get_campaign(campaign_id):
        if not Campaign.objects.filter(id=campaign_id).exists():
            raise ApiVerifyError("util.no_campaign_found")
        campaign = Campaign.objects.get(id=campaign_id)
        return campaign

    @staticmethod
    def get_campaign_from_order(order):
        if not order.campaign:
            raise ApiVerifyError("util.no_campaign_found")
        return order.campaign

    @staticmethod
    def get_campaign_from_pre_order(pre_order):
        if not pre_order.campaign:
            raise ApiVerifyError("util.no_campaign_found")
        return pre_order.campaign

    @staticmethod
    def get_campaign_from_cart(cart):
        if not cart.campaign:
            raise ApiVerifyError("util.no_campaign_found")
        return cart.campaign

    @staticmethod
    def get_campaign_product(campaign_product_id):
        if not models.campaign.campaign_product.CampaignProduct.objects.filter(id=campaign_product_id).exists():
            raise ApiVerifyError("util.no_campaign_product_found")
        return models.campaign.campaign_product.CampaignProduct.objects.get(id=campaign_product_id)

    @staticmethod
    def get_campaign_from_platform(platform, campaign_id):
        if not platform.campaigns.filter(id=campaign_id).exists():
            raise ApiVerifyError("util.no_campaign_found")
        campaign = platform.campaigns.get(id=campaign_id)
        return campaign

    @staticmethod
    def get_campaign_from_user_subscription(user_subscription, campaign_id):
        if not user_subscription.campaigns.filter(id=campaign_id).exists():
            raise ApiVerifyError("util.no_campaign_found")
        campaign = user_subscription.campaigns.get(id=campaign_id)
        return campaign

    @staticmethod
    def get_product_from_user_subscription(user_subscription, product_id):
        if not user_subscription.products.filter(id=product_id).exists():
            raise ApiVerifyError("util.no_product_found")
        return user_subscription.products.get(id=product_id)

    @staticmethod
    def get_product_category_from_user_subscription(user_subscription, product_category_id):
        if not user_subscription.product_categories.filter(id=product_category_id).exists():
            raise ApiVerifyError("util.no_product_category_found")
        return user_subscription.product_categories.get(id=product_category_id)

    @staticmethod
    def get_campaign_product_from_campaign(campaign, campaign_product_id):
        if not campaign.products.filter(id=campaign_product_id).exists():
            raise ApiVerifyError('util.no_campaign_product_found')
        campaign_product = campaign.products.get(id=campaign_product_id)
        return campaign_product

    @staticmethod
    def get_pre_order_from_campaign(campaign, pre_order_id):
        if not campaign.pre_orders.filter(id=pre_order_id).exists():
            raise ApiVerifyError('util.no_pre_order_found')
        return campaign.pre_orders.get(id=pre_order_id)

    @staticmethod
    def get_order_product_from_pre_order(pre_order, order_product_id):
        if not pre_order.order_products.filter(id=order_product_id).exists():
            raise ApiVerifyError("util.no_order_product_found")
        return pre_order.order_products.get(id=order_product_id)

    @staticmethod
    def get_campaign_product_from_pre_order(pre_order, campaign_product_id):
        if not pre_order.campaign.products.filter(id=campaign_product_id).exists():
            raise ApiVerifyError("util.no_campaign_product_found")
        return pre_order.campaign.products.get(id=campaign_product_id)

    @staticmethod
    def is_valid_country_code_for_user_plan(country_code):
        support_country_code = [cls_attribute.__name__  for cls_attribute in SubscriptionPlan.__dict__.values() if type(cls_attribute)==type] #TODO find a better way to do this
        if country_code not in support_country_code:
            raise ApiVerifyError("util.country_code_not_valid")

    @staticmethod
    def is_valid_country_code(country_code):
        if country_code not in ["SG", "PH", "IN", "ID", "MY", "TW", "CN"]:
            raise ApiVerifyError("util.country_code_not_valid")

    @staticmethod
    def get_discount_code_from_user_subscription(user_subscription, discount_code_id):

        if not user_subscription.discount_codes.filter(id=discount_code_id).exists():
            raise ApiVerifyError("util.no_discount_code_found")
        return user_subscription.discount_codes.get(id=discount_code_id)

    @staticmethod
    def get_auto_response_from_user_subscription(user_subscription, auto_response_id):

        if not user_subscription.auto_responses.filter(id=auto_response_id).exists():
            raise ApiVerifyError("util.no_auto_reply_found")
        return user_subscription.auto_responses.get(id=auto_response_id)

    @staticmethod
    def user_match_pre_order(api_user, pre_order):
        pass
        # platform_id = pre_order.get('platform_id')
        # platform_name = pre_order.get('platform')

        # if platform_name == 'facebook':
        #     pass
        #     if pre_order.get('customer_id') != api_user.get('facebook_info',{}).get("id"):
        #         raise ApiVerifyError('error!')
        # elif platform_name == 'youtube':
        #     if pre_order.get('customer_id') != api_user.get('google_info',{}).get("id"):
        #         raise ApiVerifyError('error!')
        #     pass
        # else:
        #     pass

    @staticmethod
    def user_match_order(api_user, order):
        pass
        # platform_name = order.get('platform')

        # if platform_name == 'facebook':
        #     pass
        #     if order.get('customer_id') != api_user.get('facebook_info',{}).get("id"):
        #         raise ApiVerifyError('error!')
        # elif platform_name == 'youtube':
        #     if order.get('customer_id') != api_user.get('google_info',{}).get("id"):
        #         raise ApiVerifyError('error!')
        #     pass
        # else:
        #     pass

    @staticmethod
    def is_hubspot_signature_valid(request):

        request_body = request.body.decode('utf-8')
        http_method = request.method
        http_uri = settings.GCP_API_LOADBALANCER_URL+request.get_full_path()
        source_string = settings.HUBSPOT_CLIENT_SECRET + http_method + http_uri + request_body

        print(http_method,http_uri)
        if request.META.get('HTTP_X_HUBSPOT_SIGNATURE') != hashlib.sha256(source_string.encode('utf-8')).hexdigest():
            raise ApiVerifyError('util.signature_error')

    @staticmethod
    def check_is_page_token_valid(platform_name, officiall_page_token, officiall_page_id=None):
        try:
            if platform_name == 'facebook':
                status_code, response = service.facebook.page.get_page_posts(page_token=officiall_page_token, page_id=officiall_page_id, limit=1)
                if status_code == 200:
                    return True
                return False
            elif platform_name == 'youtube':
                status_code, response = service.youtube.channel.get_list_channel_by_token(access_token=officiall_page_token)
                # print("response", response)
                if status_code == 200:
                    return True
                return False
            elif platform_name == 'instagram':
                status_code, response = service.instagram.profile.get_profile_live_media(page_token=officiall_page_token, profile_id=officiall_page_id, limit=1)
                if status_code == 200:
                    return True
                return False
            elif platform_name == 'twitch':
                status_code, response = service.twitch.twitch.api_twitch_validate_token(access_token=officiall_page_token)
                if status_code == 200:
                    return True
        except Exception as e:
            return False
        return False

    @staticmethod
    def get_lucky_draw(lucky_draw_id):
        if not models.campaign.campaign_lucky_draw.CampaignLuckyDraw.objects.filter(id=lucky_draw_id).exists():
            raise ApiVerifyError('util.lucky_draw_not_found')
        return models.campaign.campaign_lucky_draw.CampaignLuckyDraw.objects.get(id=lucky_draw_id)

    @staticmethod
    def get_quiz_game(quiz_game_id):
        if not models.campaign.campaign_quiz_game.CampaignQuizGame.objects.filter(id=quiz_game_id).exists():
            raise ApiVerifyError('util.quiz_game_not_found')
        return models.campaign.campaign_quiz_game.CampaignQuizGame.objects.get(id=quiz_game_id)

    @staticmethod
    def get_quiz_game_bundle(quiz_game_bundle_id):
        if not models.campaign.campaign_quiz_game_bundle.CampaignQuizGameBundle.objects.filter(id=quiz_game_bundle_id).exists():
            raise ApiVerifyError('util.quiz_game_not_found')
        return models.campaign.campaign_quiz_game_bundle.CampaignQuizGameBundle.objects.get(id=quiz_game_bundle_id)

    @staticmethod
    def get_user_register_by_email(user_register_email):
        if not models.user.user_register.UserRegister.objects.filter(email=user_register_email).exists():
            raise ApiVerifyError(f'user register not found by {user_register_email}')
        return models.user.user_register.UserRegister.objects.filter(email=user_register_email).order_by('-created_at')[0]

    @staticmethod
    def get_product_by_id(product_id):
        if not models.product.product.Product.objects.filter(id=product_id).exists():
            raise ApiVerifyError(f'product not found by {product_id}')
        return models.product.product.Product.objects.get(id=product_id)


"""
    @Difficulty : M 2
    @Status     : AC
    @Time       : 2021/1/24 10:29
    @Author     : Chen Runwen
"""
from typing import List

class Solution:
    def kthLargestValue(self, matrix: List[List[int]], k: int) -> int:
        nums = []
        m, n = len(matrix), len(matrix[0])
        for j in range(1, n):
            for i in range(m):
                matrix[i][j] ^= matrix[i][j-1]
        nums += matrix[0]
        for i in range(1, m):
            for j in range(n):
                matrix[i][j] ^= matrix[i-1][j]
            nums += matrix[i]
        nums.sort(reverse=True)
        return nums[k-1]

if __name__ == '__main__':
    matrix = [[5, 2], [1, 6]]
    k = 4
    print(Solution())

contests/20210124/5663. 找出第 K 大的异或坐标值.py

5663. 找出第 K 大的异或坐标值.py


# Y1 KESA 2019
# Ohjelma, joka pelaa laivanupotus luokan kayttamalla luokkaa laivanupotus.
# Kirjoittanut Ville Piiparinen
# Muokannut Joel Lahenius 2019

from laivanupotus import Laivanupotus

# Funktio huolehtii pelin yhden vuoron pelaamisesta. Funktio saa
# parametrina vuorossa olevaa kenttaa kuvaavan Laivanupotus-olion.

def pelaa_vuoro(vuorossa):
    print("Seuraavan pelaajan ruudukko talla hetkella:")
    print(vuorossa)
    print("Vuorossa on pelaaja", vuorossa.kerro_pelaaja())
    vuoro_pelattu = False
    while not vuoro_pelattu:
        try:
            ruutu = int(input("Mihin ruutuun ammutaan?\n"))
            ampuminen = vuorossa.ammu(ruutu)
            if ampuminen == Laivanupotus.OSUMA:
                print("Osuma!")
                vuoro_pelattu = True
            elif ampuminen == Laivanupotus.OHI:
                print("Ohi!")
                vuoro_pelattu = True
            elif ampuminen == Laivanupotus.ULKONA:
                print("Antamaasi ruutuun ei voi ampua.")
            else:
                print("[Luokkasi palautti vaaran arvon]")
        except ValueError:
            print("Laivan sijainnin pitaa olla kokonaisluku.")

class LaivaError(Exception):
    """Luokka, joka kuvaa virheellisesta laivasta syntyvaa poikkeusta"""

# Apufunktio joka tutkii onko laiva oikean pituinen, yhtenainen ja vaaka- tai pystysuuntainen.
# Funktio palauttaa listan, joka sisaltaa laivan koordinaatit kokonaislukuina.
# Tai virhetapauksessa nostaa LaivaError-virheen
def tarkista_ja_muuta_koordinaateiksi(laiva_merkkijonona):
    try:
        koordinaatit = [int(x) for x in laiva_merkkijonona.strip().split(" ")]
    except ValueError:
        raise LaivaError("Laivojen koordinaattien tulee olla kokonaislukuja!")
    pituus = len(koordinaatit)
    if not 2 <= pituus <= 5:
        raise LaivaError("Laivan tulee olla 2-5 merkkia pitka!")
    for koord in koordinaatit:
        if not 1 <= koord <= 100:
            raise LaivaError("Kaikkien koordinaattien tulee olla valilta 1-100!")
    diff = koordinaatit[-1] - koordinaatit[-2]
    if diff not in (1, 10, -1, -10):
        raise LaivaError("Laivan tulee olla pysty- tai vaakasuorassa!")
    for i in range(pituus-1, 0, -1):
        if koordinaatit[i] - koordinaatit[i-1] != diff:
            raise LaivaError("Laivan tulee olla pysty- tai vaakasuorassa!")
        if sorted([koordinaatit[i] % 10, koordinaatit[i-1] % 10]) == [0,1]:
            raise LaivaError("Laivan tulee olla yhtenainen!")

    return koordinaatit

# Funktio tarkistaa, onko listoissa samoja arvoja
def leikkaavat(lst1, lst2):
    for item in lst1:
        if item in lst2:
            return True
    return False

# Funktio kysyy ja palauttaa laivojen koordinaatit yhdessa listassa
def pyyda_laivat():
    laiva_annettu = False
    while not laiva_annettu:
        laivat = []
        print("Anna 2-5 merkin pituisia laivoja pilkulla eroteltuna, laivaruudut valilyonnilla eroteltuna.")
        print("Esimerkiksi: 13 23, 54 64 74 84 94, 25 26 27")
        tiedot = input().split(",")
        try:
            for i in range(len(tiedot)):
                laiva = tarkista_ja_muuta_koordinaateiksi(tiedot[i])
                if not leikkaavat(laiva, laivat):
                    laivat += laiva
                else:
                    raise LaivaError("Laivat eivat saa olla paallekkain!")
        except LaivaError as e:
            print(e)
        else:
            laiva_annettu = True

    return laivat

def main():
    print("Laivanupotusta! Ruutujen koordinaatit ovat 1-100 alkaen")
    print("vasemmasta ylakulmasta, kasvaen aina vasemmalta oikealle.")

    eka_nimi = input("Anna ensin ensimmaisen pelaajan nimi.\n")
    print("Sijoita laivat. Toinen pelaaja katsoo muualle!")
    laivat1 = pyyda_laivat()

    toka_nimi = input("Anna toisen pelaajan nimi.\n")
    print("Sijoita laivat. Ensimmainen pelaaja katsoo muualle!")
    laivat2 = pyyda_laivat()

    peli1 = Laivanupotus(eka_nimi, laivat2)
    peli2 = Laivanupotus(toka_nimi, laivat1)

    vuorossa = peli1
    paattynyt = False
    while not paattynyt:
        pelaa_vuoro(vuorossa)
        paattynyt = vuorossa.peli_paattynyt()
        vuorossa = peli1 if vuorossa == peli2 else peli2

    if vuorossa == peli1:
        voittajan_nimi = peli2.kerro_pelaaja()
    else:
        voittajan_nimi = peli1.kerro_pelaaja()
    print("Peli ohi! Pelin voitti {:s}!".format(voittajan_nimi))

main()


import numpy as np
import pandas as pd
from datasets import Dataset
from transformers import AutoTokenizer
from transformers import AutoModelForMultipleChoice
import torch
from torch.utils.data import DataLoader
from torch.nn.functional import softmax

from wikipeida_processor import add_context

from utils import *

model_dir = "./models/deberta-v3-large"
tokenizer = AutoTokenizer.from_pretrained(model_dir)
model = AutoModelForMultipleChoice.from_pretrained(model_dir).cuda()
model.eval()

def preprocess(example):
    # The AutoModelForMultipleChoice class expects a set of question/answer pairs
    # so we'll copy our question 5 times before tokenizing
    first_sentence = [example['prompt']] * 5
    second_sentence = []
    for option in options:
        second_sentence.append(example[option])
    # Our tokenizer will turn our text into token IDs BERT can understand
    tokenized_example = tokenizer(first_sentence, second_sentence, truncation=True)
    tokenized_example['label'] = option_to_index[example['answer']]
    return tokenized_example

def infer(query: pd):
    mask = [-999 if (query[i] == "")[0] else 0 for i in ["A", "B", "C", "D", "E"]]
    query = add_context(query)
    query.index = list(range(len(query)))
    query["id"] = list(range(len(query)))
    query["prompt"] = query["context"].apply(lambda x: x[:1750]) + " #### " + query["question"]
    query["answer"] = "A"

    tokenized_test_dataset = Dataset.from_pandas(query[['prompt', 'A', 'B', 'C', 'D', 'E', 'answer']]).map(preprocess, remove_columns=['prompt', 'A', 'B', 'C', 'D', 'E', 'answer'])
    tokenized_test_dataset = tokenized_test_dataset.remove_columns(["__index_level_0__"])
    data_collator = DataCollatorForMultipleChoice(tokenizer=tokenizer)
    test_dataloader = DataLoader(tokenized_test_dataset, batch_size=1, shuffle=False, collate_fn=data_collator)

    test_predictions = []
    for batch in test_dataloader:
        for k in batch.keys():
            batch[k] = batch[k].cuda()
        with torch.no_grad():
            outputs = model(**batch)
        test_predictions.append(outputs.logits.cpu().detach())
    test_predictions[0] = test_predictions[0] + torch.FloatTensor(mask)
    prob = softmax(test_predictions[0])
    prob = float(torch.max(prob))
    test_predictions = torch.cat(test_predictions)
    test_predictions = test_predictions.numpy()
    predictions_as_ids = np.argsort(-test_predictions, 1)
    predictions_as_answer_letters = np.array(list('ABCDE'))[predictions_as_ids]
    predictions_as_string = query['prediction'] = [
    ' '.join(row) for row in predictions_as_answer_letters[:, :3]
    ]
    return predictions_as_string[0][0], prob


import functools
import warnings
import numpy as np
from .base import Decomposition, svd
from ...core.structures import Tensor, TensorCPD, residual_tensor
from ...core.operations import khatri_rao, hadamard

# TODO: Need to add option of sorting vectors in the factor matrices and making them sign invariant
class BaseCPD(Decomposition):

    def __init__(self, init, max_iter, epsilon, tol, random_state, verbose):
        super(BaseCPD, self).__init__()
        self.init = init
        self.max_iter = max_iter
        self.epsilon = epsilon
        self.tol = tol
        self.random_state = random_state
        self.verbose = verbose

    def copy(self):
        """ Copy of the Decomposition as a new object """
        new_object = super(BaseCPD, self).copy()
        return new_object

    @property
    def name(self):
        """ Name of the decomposition

        Returns
        -------
        decomposition_name : str
        """
        decomposition_name = super(BaseCPD, self).name
        return decomposition_name

    def decompose(self, tensor, rank, keep_meta):
        raise NotImplementedError('Not implemented in base (BaseCPD) class')

    @property
    def converged(self):
        """ Checks convergence

        Returns
        -------
        is_converged : bool
        """
        try:  # This insures that the cost has been computed at least twice without checking number of iterations
            is_converged = abs(self.cost[-2] - self.cost[-1]) <= self.tol
        except IndexError:
            is_converged = False
        return is_converged

    def _init_fmat(self, tensor, rank):
        """ Initialisation of factor matrices

        Parameters
        ----------
        tensor : Tensor
            Multidimensional data to be decomposed
        rank : tuple
            Should be of shape (R,1), where R is the desired tensor rank. It should be passed as tuple for consistency.

        Returns
        -------
        fmat : list[np.ndarray]
            List of factor matrices
        """
        self.cost = []  # Reset cost every time when method decompose is called
        t_rank = rank[0]
        fmat = [np.array([])] * tensor.order
        # Check if all dimensions are greater then kryskal rank
        dim_check = (np.array(tensor.shape) >= t_rank).sum() == tensor.order
        if dim_check:
            if self.init is 'svd':
                for mode in range(tensor.order):
                    # TODO: don't really like this implementation
                    fmat[mode], _, _ = svd(tensor.unfold(mode, inplace=False).data, t_rank)
            elif self.init is 'random':
                fmat = [np.random.randn(mode_size, t_rank) for mode_size in tensor.shape]
            else:
                raise NotImplementedError('The given initialization is not available')
        else:
            fmat = [np.random.randn(mode_size, t_rank) for mode_size in tensor.shape]
            if self.verbose and self.init != 'random':
                warnings.warn(
                    "Specified rank value is greater then one of the dimensions of a tensor ({} > {}).\n"
                    "Factor matrices have been initialized randomly.".format(t_rank, tensor.shape), RuntimeWarning
                )
        return fmat

    def plot(self):
        raise NotImplementedError('Not implemented in base (BaseCPD) class')

class CPD(BaseCPD):
    """ Canonical Polyadic Decomposition.

    Computed via alternating least squares (ALS)

    Parameters
    ----------
    init : str
        Type of factor matrix initialisation. Available options are `svd` and `random`
    max_iter : int
        Maximum number of iteration
    epsilon : float
        Threshold for the relative error of approximation.
    tol : float
        Threshold for convergence of factor matrices
    random_state : int
    verbose : bool
        If True, enable verbose output

    Attributes
    ----------
    cost : list
        A list of relative approximation errors at each iteration of the algorithm.
    """

    def __init__(self, init='svd', max_iter=50, epsilon=10e-3, tol=10e-5,
                 random_state=None, verbose=False) -> None:
        super(CPD, self).__init__(init=init,
                                  max_iter=max_iter,
                                  epsilon=epsilon,
                                  tol=tol,
                                  random_state=random_state,
                                  verbose=verbose)
        self.cost = []

    def copy(self):
        """ Copy of the CPD algorithm as a new object """
        new_object = super(CPD, self).copy()
        new_object.cost = []
        return new_object

    @property
    def name(self):
        """ Name of the decomposition

        Returns
        -------
        decomposition_name : str
        """
        decomposition_name = super(CPD, self).name
        return decomposition_name

    def decompose(self, tensor, rank, keep_meta=0, kr_reverse=False):
        """ Performs CPD-ALS on the `tensor` with respect to the specified `rank`

        Parameters
        ----------
        tensor : Tensor
            Multidimensional data to be decomposed
        rank : tuple
            Desired Kryskal rank for the given `tensor`. Should contain only one value.
            If it is greater then any of dimensions then random initialisation is used
        keep_meta : int
            Keep meta information about modes of the given `tensor`.
            0 - the output will have default values for the meta data
            1 - keep only mode names
            2 - keep mode names and indices
        kr_reverse : bool

        Returns
        -------
        tensor_cpd : TensorCPD
            CP representation of the `tensor`

        Notes
        -----
        khatri-rao product should be of matrices in reversed order. But this will duplicate original data (e.g. images)
        Probably this has something to do with data ordering in Python and how it relates to kr product
        """
        if not isinstance(tensor, Tensor):
            raise TypeError("Parameter `tensor` should be an object of `Tensor` class!")
        if not isinstance(rank, tuple):
            raise TypeError("Parameter `rank` should be passed as a tuple!")
        if len(rank) != 1:
            raise ValueError("Parameter `rank` should be tuple with only one value!")

        tensor_cpd = None
        fmat = self._init_fmat(tensor, rank)
        core_values = np.repeat(np.array([1]), rank)
        norm = tensor.frob_norm
        for n_iter in range(self.max_iter):

            # Update factor matrices
            for mode in range(tensor.order):
                kr_result = khatri_rao(fmat, skip_matrix=mode, reverse=kr_reverse)
                hadamard_result = hadamard([np.dot(mat.T, mat) for i, mat in enumerate(fmat) if i != mode])
                # Do consecutive multiplication of np.ndarray
                update = functools.reduce(np.dot, [tensor.unfold(mode, inplace=False).data,
                                                   kr_result,
                                                   np.linalg.pinv(hadamard_result)])
                fmat[mode] = update

            # Update cost
            tensor_cpd = TensorCPD(fmat=fmat, core_values=core_values)
            residual = residual_tensor(tensor, tensor_cpd)
            self.cost.append(abs(residual.frob_norm / norm))
            if self.verbose:
                print('Iter {}: relative error of approximation = {}'.format(n_iter, self.cost[-1]))

            # Check termination conditions
            if self.cost[-1] <= self.epsilon:
                if self.verbose:
                    print('Relative error of approximation has reached the acceptable level: {}'.format(self.cost[-1]))
                break
            if self.converged:
                if self.verbose:
                    print('Converged in {} iteration(s)'.format(len(self.cost)))
                break
        if self.verbose and not self.converged and self.cost[-1] > self.epsilon:
            print('Maximum number of iterations ({}) has been reached. '
                  'Variation = {}'.format(self.max_iter, abs(self.cost[-2] - self.cost[-1])))

        if keep_meta == 1:
            mode_names = {i: mode.name for i, mode in enumerate(tensor.modes)}
            tensor_cpd.set_mode_names(mode_names=mode_names)
        elif keep_meta == 2:
            tensor_cpd.copy_modes(tensor)
        else:
            pass
        return tensor_cpd

    @property
    def converged(self):
        """ Checks convergence of the CPD-ALS algorithm.

        Returns
        -------
        bool
        """
        is_converged = super(CPD, self).converged
        return is_converged

    def _init_fmat(self, tensor, rank):
        fmat = super(CPD, self)._init_fmat(tensor=tensor,
                                           rank=rank)
        return fmat

    def plot(self):
        print('At the moment, `plot()` is not implemented for the {}'.format(self.name))


"""
SwiftFormer
"""
import os
import copy
import torch
import torch.nn as nn
from timm.data import IMAGENET_DEFAULT_MEAN, IMAGENET_DEFAULT_STD
from timm.models.layers import DropPath, trunc_normal_
from timm.models.registry import register_model
from timm.models.layers.helpers import to_2tuple
import einops

SwiftFormer_width = {
    'XS': [48, 56, 112, 220],
    'S': [48, 64, 168, 224],
    'l1': [48, 96, 192, 384],
    'l3': [64, 128, 320, 512],
}

SwiftFormer_depth = {
    'XS': [3, 3, 6, 4],
    'S': [3, 3, 9, 6],
    'l1': [4, 3, 10, 5],
    'l3': [4, 4, 12, 6],
}

def stem(in_chs, out_chs):
    """
    Stem Layer that is implemented by two layers of conv.
    Output: sequence of layers with final shape of [B, C, H/4, W/4]
    """
    return nn.Sequential(
        nn.Conv2d(in_chs, out_chs // 2, kernel_size=3, stride=2, padding=1),
        nn.BatchNorm2d(out_chs // 2),
        nn.ReLU(),
        nn.Conv2d(out_chs // 2, out_chs, kernel_size=3, stride=2, padding=1),
        nn.BatchNorm2d(out_chs),
        nn.ReLU(), )

class Embedding(nn.Module):
    """
    Patch Embedding that is implemented by a layer of conv.
    Input: tensor in shape [B, C, H, W]
    Output: tensor in shape [B, C, H/stride, W/stride]
    """

    def __init__(self, patch_size=16, stride=16, padding=0,
                 in_chans=3, embed_dim=768, norm_layer=nn.BatchNorm2d):
        super().__init__()
        patch_size = to_2tuple(patch_size)
        stride = to_2tuple(stride)
        padding = to_2tuple(padding)
        self.proj = nn.Conv2d(in_chans, embed_dim, kernel_size=patch_size,
                              stride=stride, padding=padding)
        self.norm = norm_layer(embed_dim) if norm_layer else nn.Identity()

    def forward(self, x):
        x = self.proj(x)
        x = self.norm(x)
        return x

class ConvEncoder(nn.Module):
    """
    Implementation of ConvEncoder with 3*3 and 1*1 convolutions.
    Input: tensor with shape [B, C, H, W]
    Output: tensor with shape [B, C, H, W]
    """

    def __init__(self, dim, hidden_dim=64, kernel_size=3, drop_path=0., use_layer_scale=True):
        super().__init__()
        self.dwconv = nn.Conv2d(dim, dim, kernel_size=kernel_size, padding=kernel_size // 2, groups=dim)
        self.norm = nn.BatchNorm2d(dim)
        self.pwconv1 = nn.Conv2d(dim, hidden_dim, kernel_size=1)
        self.act = nn.GELU()
        self.pwconv2 = nn.Conv2d(hidden_dim, dim, kernel_size=1)
        self.drop_path = DropPath(drop_path) if drop_path > 0. \
            else nn.Identity()
        self.use_layer_scale = use_layer_scale
        if use_layer_scale:
            self.layer_scale = nn.Parameter(torch.ones(dim).unsqueeze(-1).unsqueeze(-1), requires_grad=True)
        self.apply(self._init_weights)

    def _init_weights(self, m):
        if isinstance(m, nn.Conv2d):
            trunc_normal_(m.weight, std=.02)
            if m.bias is not None:
                nn.init.constant_(m.bias, 0)

    def forward(self, x):
        input = x
        x = self.dwconv(x)
        x = self.norm(x)
        x = self.pwconv1(x)
        x = self.act(x)
        x = self.pwconv2(x)
        if self.use_layer_scale:
            x = input + self.drop_path(self.layer_scale * x)
        else:
            x = input + self.drop_path(x)
        return x

class Mlp(nn.Module):
    """
    Implementation of MLP layer with 1*1 convolutions.
    Input: tensor with shape [B, C, H, W]
    Output: tensor with shape [B, C, H, W]
    """

    def __init__(self, in_features, hidden_features=None,
                 out_features=None, act_layer=nn.GELU, drop=0.):
        super().__init__()
        out_features = out_features or in_features
        hidden_features = hidden_features or in_features
        self.norm1 = nn.BatchNorm2d(in_features)
        self.fc1 = nn.Conv2d(in_features, hidden_features, 1)
        self.act = act_layer()
        self.fc2 = nn.Conv2d(hidden_features, out_features, 1)
        self.drop = nn.Dropout(drop)
        self.apply(self._init_weights)

    def _init_weights(self, m):
        if isinstance(m, nn.Conv2d):
            trunc_normal_(m.weight, std=.02)
            if m.bias is not None:
                nn.init.constant_(m.bias, 0)

    def forward(self, x):
        x = self.norm1(x)
        x = self.fc1(x)
        x = self.act(x)
        x = self.drop(x)
        x = self.fc2(x)
        x = self.drop(x)
        return x

class EfficientAdditiveAttnetion(nn.Module):
    """
    Efficient Additive Attention module for SwiftFormer.
    Input: tensor in shape [B, N, D]
    Output: tensor in shape [B, N, D]
    """

    def __init__(self, in_dims=512, token_dim=256, num_heads=2):
        super().__init__()

        self.to_query = nn.Linear(in_dims, token_dim * num_heads)
        self.to_key = nn.Linear(in_dims, token_dim * num_heads)

        self.w_g = nn.Parameter(torch.randn(token_dim * num_heads, 1))
        self.scale_factor = token_dim ** -0.5
        self.Proj = nn.Linear(token_dim * num_heads, token_dim * num_heads)
        self.final = nn.Linear(token_dim * num_heads, token_dim)

    def forward(self, x):
        query = self.to_query(x)
        key = self.to_key(x)

        query = torch.nn.functional.normalize(query, dim=-1) #BxNxD
        key = torch.nn.functional.normalize(key, dim=-1) #BxNxD

        query_weight = query @ self.w_g # BxNx1 (BxNxD @ Dx1)
        A = query_weight * self.scale_factor # BxNx1

        A = torch.nn.functional.normalize(A, dim=1) # BxNx1

        G = torch.sum(A * query, dim=1) # BxD

        G = einops.repeat(
            G, "b d -> b repeat d", repeat=key.shape[1]
        ) # BxNxD

        out = self.Proj(G * key) + query #BxNxD

        out = self.final(out) # BxNxD

        return out

class SwiftFormerLocalRepresentation(nn.Module):
    """
    Local Representation module for SwiftFormer that is implemented by 3*3 depth-wise and point-wise convolutions.
    Input: tensor in shape [B, C, H, W]
    Output: tensor in shape [B, C, H, W]
    """

    def __init__(self, dim, kernel_size=3, drop_path=0., use_layer_scale=True):
        super().__init__()
        self.dwconv = nn.Conv2d(dim, dim, kernel_size=kernel_size, padding=kernel_size // 2, groups=dim)
        self.norm = nn.BatchNorm2d(dim)
        self.pwconv1 = nn.Conv2d(dim, dim, kernel_size=1)
        self.act = nn.GELU()
        self.pwconv2 = nn.Conv2d(dim, dim, kernel_size=1)
        self.drop_path = DropPath(drop_path) if drop_path > 0. \
            else nn.Identity()
        self.use_layer_scale = use_layer_scale
        if use_layer_scale:
            self.layer_scale = nn.Parameter(torch.ones(dim).unsqueeze(-1).unsqueeze(-1), requires_grad=True)
        self.apply(self._init_weights)

    def _init_weights(self, m):
        if isinstance(m, nn.Conv2d):
            trunc_normal_(m.weight, std=.02)
            if m.bias is not None:
                nn.init.constant_(m.bias, 0)

    def forward(self, x):
        input = x
        x = self.dwconv(x)
        x = self.norm(x)
        x = self.pwconv1(x)
        x = self.act(x)
        x = self.pwconv2(x)
        if self.use_layer_scale:
            x = input + self.drop_path(self.layer_scale * x)
        else:
            x = input + self.drop_path(x)
        return x

class SwiftFormerEncoder(nn.Module):
    """
    SwiftFormer Encoder Block for SwiftFormer. It consists of (1) Local representation module, (2) EfficientAdditiveAttention, and (3) MLP block.
    Input: tensor in shape [B, C, H, W]
    Output: tensor in shape [B, C, H, W]
    """

    def __init__(self, dim, mlp_ratio=4.,
                 act_layer=nn.GELU,
                 drop=0., drop_path=0.,
                 use_layer_scale=True, layer_scale_init_value=1e-5):

        super().__init__()

        self.local_representation = SwiftFormerLocalRepresentation(dim=dim, kernel_size=3, drop_path=0.,
                                                                   use_layer_scale=True)
        self.attn = EfficientAdditiveAttnetion(in_dims=dim, token_dim=dim, num_heads=1)
        self.linear = Mlp(in_features=dim, hidden_features=int(dim * mlp_ratio), act_layer=act_layer, drop=drop)
        self.drop_path = DropPath(drop_path) if drop_path > 0. \
            else nn.Identity()
        self.use_layer_scale = use_layer_scale
        if use_layer_scale:
            self.layer_scale_1 = nn.Parameter(
                layer_scale_init_value * torch.ones(dim).unsqueeze(-1).unsqueeze(-1), requires_grad=True)
            self.layer_scale_2 = nn.Parameter(
                layer_scale_init_value * torch.ones(dim).unsqueeze(-1).unsqueeze(-1), requires_grad=True)

    def forward(self, x):
        x = self.local_representation(x)
        B, C, H, W = x.shape
        if self.use_layer_scale:
            x = x + self.drop_path(
                self.layer_scale_1 * self.attn(x.permute(0, 2, 3, 1).reshape(B, H * W, C)).reshape(B, H, W, C).permute(
                    0, 3, 1, 2))
            x = x + self.drop_path(self.layer_scale_2 * self.linear(x))

        else:
            x = x + self.drop_path(
                self.attn(x.permute(0, 2, 3, 1).reshape(B, H * W, C)).reshape(B, H, W, C).permute(0, 3, 1, 2))
            x = x + self.drop_path(self.linear(x))
        return x

def Stage(dim, index, layers, mlp_ratio=4.,
          act_layer=nn.GELU,
          drop_rate=.0, drop_path_rate=0.,
          use_layer_scale=True, layer_scale_init_value=1e-5, vit_num=1):
    """
    Implementation of each SwiftFormer stages. Here, SwiftFormerEncoder used as the last block in all stages, while ConvEncoder used in the rest of the blocks.
    Input: tensor in shape [B, C, H, W]
    Output: tensor in shape [B, C, H, W]
    """
    blocks = []

    for block_idx in range(layers[index]):
        block_dpr = drop_path_rate * (block_idx + sum(layers[:index])) / (sum(layers) - 1)

        if layers[index] - block_idx <= vit_num:
            blocks.append(SwiftFormerEncoder(
                dim, mlp_ratio=mlp_ratio,
                act_layer=act_layer, drop_path=block_dpr,
                use_layer_scale=use_layer_scale,
                layer_scale_init_value=layer_scale_init_value))

        else:
            blocks.append(ConvEncoder(dim=dim, hidden_dim=int(mlp_ratio * dim), kernel_size=3))

    blocks = nn.Sequential(*blocks)
    return blocks

class SwiftFormer(nn.Module):

    def __init__(self, layers, embed_dims=None,
                 mlp_ratios=4, downsamples=None,
                 act_layer=nn.GELU,
                 num_classes=1000,
                 down_patch_size=3, down_stride=2, down_pad=1,
                 drop_rate=0., drop_path_rate=0.,
                 use_layer_scale=True, layer_scale_init_value=1e-5,
                 fork_feat=False,
                 init_cfg=None,
                 pretrained=None,
                 vit_num=1,
                 distillation=True,
                 **kwargs):
        super().__init__()

        if not fork_feat:
            self.num_classes = num_classes
        self.fork_feat = fork_feat

        self.patch_embed = stem(3, embed_dims[0])

        network = []
        for i in range(len(layers)):
            stage = Stage(embed_dims[i], i, layers, mlp_ratio=mlp_ratios,
                          act_layer=act_layer,
                          drop_rate=drop_rate,
                          drop_path_rate=drop_path_rate,
                          use_layer_scale=use_layer_scale,
                          layer_scale_init_value=layer_scale_init_value,
                          vit_num=vit_num)
            network.append(stage)
            if i >= len(layers) - 1:
                break
            if downsamples[i] or embed_dims[i] != embed_dims[i + 1]:
                # downsampling between two stages
                network.append(
                    Embedding(
                        patch_size=down_patch_size, stride=down_stride,
                        padding=down_pad,
                        in_chans=embed_dims[i], embed_dim=embed_dims[i + 1]
                    )
                )

        self.network = nn.ModuleList(network)

        if self.fork_feat:
            # add a norm layer for each output
            self.out_indices = [0, 2, 4, 6]
            for i_emb, i_layer in enumerate(self.out_indices):
                if i_emb == 0 and os.environ.get('FORK_LAST3', None):
                    layer = nn.Identity()
                else:
                    layer = nn.BatchNorm2d(embed_dims[i_emb])
                layer_name = f'norm{i_layer}'
                self.add_module(layer_name, layer)
        else:
            # Classifier head
            self.norm = nn.BatchNorm2d(embed_dims[-1])
            self.head = nn.Linear(
                embed_dims[-1], num_classes) if num_classes > 0 \
                else nn.Identity()
            self.dist = distillation
            if self.dist:
                self.dist_head = nn.Linear(
                    embed_dims[-1], num_classes) if num_classes > 0 \
                    else nn.Identity()

        # self.apply(self.cls_init_weights)
        self.apply(self._init_weights)

        self.init_cfg = copy.deepcopy(init_cfg)
        # load pre-trained model
        if self.fork_feat and (
                self.init_cfg is not None or pretrained is not None):
            self.init_weights()

    # init for mmdetection or mmsegmentation by loading
    # imagenet pre-trained weights
    def init_weights(self, pretrained=None):
        logger = get_root_logger()
        if self.init_cfg is None and pretrained is None:
            logger.warn(f'No pre-trained weights for '
                        f'{self.__class__.__name__}, '
                        f'training start from scratch')
            pass
        else:
            assert 'checkpoint' in self.init_cfg, f'Only support ' \
                                                  f'specify `Pretrained` in ' \
                                                  f'`init_cfg` in ' \
                                                  f'{self.__class__.__name__} '
            if self.init_cfg is not None:
                ckpt_path = self.init_cfg['checkpoint']
            elif pretrained is not None:
                ckpt_path = pretrained

            ckpt = _load_checkpoint(
                ckpt_path, logger=logger, map_location='cpu')
            if 'state_dict' in ckpt:
                _state_dict = ckpt['state_dict']
            elif 'model' in ckpt:
                _state_dict = ckpt['model']
            else:
                _state_dict = ckpt

            state_dict = _state_dict
            missing_keys, unexpected_keys = \
                self.load_state_dict(state_dict, False)

    def _init_weights(self, m):
        if isinstance(m, (nn.Conv2d, nn.Linear)):
            trunc_normal_(m.weight, std=.02)
            if m.bias is not None:
                nn.init.constant_(m.bias, 0)
        elif isinstance(m, (nn.LayerNorm)):
            nn.init.constant_(m.bias, 0)
            nn.init.constant_(m.weight, 1.0)

    def forward_tokens(self, x):
        outs = []
        for idx, block in enumerate(self.network):
            x = block(x)
            if self.fork_feat and idx in self.out_indices:
                norm_layer = getattr(self, f'norm{idx}')
                x_out = norm_layer(x)
                outs.append(x_out)
        if self.fork_feat:
            return outs
        return x

    def forward(self, x):
        x = self.patch_embed(x)
        x = self.forward_tokens(x)
        if self.fork_feat:
            # Output features of four stages for dense prediction
            return x

        x = self.norm(x)
        if self.dist:
            cls_out = self.head(x.flatten(2).mean(-1)), self.dist_head(x.flatten(2).mean(-1))
            if not self.training:
                cls_out = (cls_out[0] + cls_out[1]) / 2
        else:
            cls_out = self.head(x.mean(-2))
        # For image classification
        return cls_out

def _cfg(url='', **kwargs):
    return {
        'url': url,
        'num_classes': 1000, 'input_size': (3, 224, 224), 'pool_size': None,
        'crop_pct': .95, 'interpolation': 'bicubic',
        'mean': IMAGENET_DEFAULT_MEAN, 'std': IMAGENET_DEFAULT_STD,
        'classifier': 'head',
        **kwargs
    }

@register_model
def SwiftFormer_XS(pretrained=False, **kwargs):
    model = SwiftFormer(
        layers=SwiftFormer_depth['XS'],
        embed_dims=SwiftFormer_width['XS'],
        downsamples=[True, True, True, True],
        vit_num=1,
        **kwargs)
    model.default_cfg = _cfg(crop_pct=0.9)
    return model

@register_model
def SwiftFormer_S(pretrained=False, **kwargs):
    model = SwiftFormer(
        layers=SwiftFormer_depth['S'],
        embed_dims=SwiftFormer_width['S'],
        downsamples=[True, True, True, True],
        vit_num=1,
        **kwargs)
    model.default_cfg = _cfg(crop_pct=0.9)
    return model

@register_model
def SwiftFormer_L1(pretrained=False, **kwargs):
    model = SwiftFormer(
        layers=SwiftFormer_depth['l1'],
        embed_dims=SwiftFormer_width['l1'],
        downsamples=[True, True, True, True],
        vit_num=1,
        **kwargs)
    model.default_cfg = _cfg(crop_pct=0.9)
    return model

@register_model
def SwiftFormer_L3(pretrained=False, **kwargs):
    model = SwiftFormer(
        layers=SwiftFormer_depth['l3'],
        embed_dims=SwiftFormer_width['l3'],
        downsamples=[True, True, True, True],
        vit_num=1,
        **kwargs)
    model.default_cfg = _cfg(crop_pct=0.9)
    return model


import datetime
import os

class bcolors:
    HEADER = '\033[95m'
    OKBLUE = '\033[94m'
    OKGREEN = '\033[92m'
    WARNING = '\033[93m'
    FAIL = '\033[91m'
    ENDC = '\033[0m'
    BOLD = '\033[1m'
    UNDERLINE = '\033[4m'

#log level warning.
loglevel = 2 # 0 Info 1 Warning 2 Error 3 Important 4 Critical

def error(message):
    print(f"{bcolors.FAIL}[-]   {message}{bcolors.ENDC}")
    if loglevel <= 2:
        log(message, 2)

def important(message):
    print(f"{bcolors.UNDERLINE}[!]  {message}{bcolors.ENDC}")
    if loglevel <= 3:
        log(message, 3)

def warning(message):
    print(f"{bcolors.WARNING}[*]    {message}{bcolors.ENDC}")
    if loglevel <= 1:
        log(message, 1)

def success(message):
    print(f"{bcolors.OKGREEN}[+]    {message}{bcolors.ENDC}")
    if loglevel <= 0:
        log(message, 0)

def header(message):
    print(f"{bcolors.OKBLUE}{message}{bcolors.ENDC}")

def intrusionDetected(message):
    print(f"{bcolors.UNDERLINE}{bcolors.FAIL}[INTRUSION ALERT]  {message}{bcolors.ENDC}")
    log(message, 4)

def log(message, severity):

    try:
        os.mkdir('/var/log/IDS')
    except OSError:
        pass

    with open('/var/log/IDS/alert.log', 'a') as file:
        file.write('[{0}] Severity: {1}, {2}\n'.format(datetime.datetime.now(), severity, message))


# see edabit for question breakdown
# takes number and returns number of boxes

# optimal solution:
def stack_boxes(n):
	return n ** 2

# my solution (works):
def stack_boxes(n):
	if n == 0:
		return 0
	elif n == 1:
		return 1
	else:
		box_count = 1
		row_size = 1
		for item in range(n-1):
			row_size += 2
			box_count += row_size
		return box_count

# had to add -1 to the range, forgot about 0 index