from __future__ import absolute_import
from __future__ import division
import re
from functools import reduce

import wx
import wx.stc
from six.moves import xrange

from graphics.GraphicCommons import ERROR_HIGHLIGHT, SEARCH_RESULT_HIGHLIGHT, REFRESH_HIGHLIGHT_PERIOD
from plcopen.structures import ST_BLOCK_START_KEYWORDS, IEC_BLOCK_START_KEYWORDS, LOCATIONDATATYPES
from editors.EditorPanel import EditorPanel
from controls.CustomStyledTextCtrl import CustomStyledTextCtrl, faces, GetCursorPos

# -------------------------------------------------------------------------------
#                         Textual programs Viewer class
# -------------------------------------------------------------------------------

NEWLINE = "\n"
NUMBERS = [str(i) for i in xrange(10)]
LETTERS = ['_']
for i in xrange(26):
    LETTERS.append(chr(ord('a') + i))
    LETTERS.append(chr(ord('A') + i))

[STC_PLC_WORD, STC_PLC_COMMENT, STC_PLC_NUMBER, STC_PLC_STRING,
 STC_PLC_VARIABLE, STC_PLC_PARAMETER, STC_PLC_FUNCTION, STC_PLC_JUMP,
 STC_PLC_ERROR, STC_PLC_SEARCH_RESULT,
 STC_PLC_EMPTY] = range(11)
[SPACE, WORD, NUMBER, STRING, WSTRING, COMMENT, PRAGMA, DPRAGMA] = range(8)

re_texts = {}
re_texts["letter"] = "[A-Za-z]"
re_texts["digit"] = "[0-9]"
re_texts["identifier"] = "((?:%(letter)s|(?:_(?:%(letter)s|%(digit)s)))(?:_?(?:%(letter)s|%(digit)s))*)" % re_texts
IDENTIFIER_MODEL = re.compile(re_texts["identifier"])
LABEL_MODEL = re.compile("[ \t\n]%(identifier)s:[ \t\n]" % re_texts)
EXTENSIBLE_PARAMETER = re.compile("IN[1-9][0-9]*$")

HIGHLIGHT_TYPES = {
    ERROR_HIGHLIGHT: STC_PLC_ERROR,
    SEARCH_RESULT_HIGHLIGHT: STC_PLC_SEARCH_RESULT,
}

def LineStartswith(line, symbols):
    return reduce(lambda x, y: x or y, map(line.startswith, symbols), False)

class TextViewer(EditorPanel):

    def _init_Editor(self, prnt):
        self.Editor = CustomStyledTextCtrl(parent=prnt, name="TextViewer", size=wx.Size(0, 0), style=0)
        self.Editor.ParentWindow = self

        self.Editor.CmdKeyAssign(ord('+'), wx.stc.STC_SCMOD_CTRL, wx.stc.STC_CMD_ZOOMIN)
        self.Editor.CmdKeyAssign(ord('-'), wx.stc.STC_SCMOD_CTRL, wx.stc.STC_CMD_ZOOMOUT)

        self.Editor.SetViewWhiteSpace(False)

        self.Editor.SetLexer(wx.stc.STC_LEX_CONTAINER)

        # Global default styles for all languages
        self.Editor.StyleSetSpec(wx.stc.STC_STYLE_DEFAULT, "face:%(mono)s,size:%(size)d" % faces)
        self.Editor.StyleClearAll()  # Reset all to be like the default

        self.Editor.StyleSetSpec(wx.stc.STC_STYLE_LINENUMBER,  "back:#C0C0C0,size:%(size)d" % faces)
        self.Editor.SetSelBackground(1, "#E0E0E0")

        # Highlighting styles
        self.Editor.StyleSetSpec(STC_PLC_WORD, "fore:#00007F,bold,size:%(size)d" % faces)
        self.Editor.StyleSetSpec(STC_PLC_VARIABLE, "fore:#7F0000,size:%(size)d" % faces)
        self.Editor.StyleSetSpec(STC_PLC_PARAMETER, "fore:#7F007F,size:%(size)d" % faces)
        self.Editor.StyleSetSpec(STC_PLC_FUNCTION, "fore:#7F7F00,size:%(size)d" % faces)
        self.Editor.StyleSetSpec(STC_PLC_COMMENT, "fore:#7F7F7F,size:%(size)d" % faces)
        self.Editor.StyleSetSpec(STC_PLC_NUMBER, "fore:#007F7F,size:%(size)d" % faces)
        self.Editor.StyleSetSpec(STC_PLC_STRING, "fore:#007F00,size:%(size)d" % faces)
        self.Editor.StyleSetSpec(STC_PLC_JUMP, "fore:#FF7FFF,size:%(size)d" % faces)
        self.Editor.StyleSetSpec(STC_PLC_ERROR, "fore:#FF0000,back:#FFFF00,size:%(size)d" % faces)
        self.Editor.StyleSetSpec(STC_PLC_SEARCH_RESULT, "fore:#FFFFFF,back:#FFA500,size:%(size)d" % faces)

        # Indicators styles
        self.Editor.IndicatorSetStyle(0, wx.stc.STC_INDIC_SQUIGGLE)
        if self.ParentWindow is not None and self.Controler is not None:
            self.Editor.IndicatorSetForeground(0, wx.RED)
        else:
            self.Editor.IndicatorSetForeground(0, wx.WHITE)

        # Line numbers in the margin
        self.Editor.SetMarginType(1, wx.stc.STC_MARGIN_NUMBER)
        self.Editor.SetMarginWidth(1, 50)

        # Folding
        self.Editor.MarkerDefine(wx.stc.STC_MARKNUM_FOLDEROPEN,    wx.stc.STC_MARK_BOXMINUS,          "white", "#808080")
        self.Editor.MarkerDefine(wx.stc.STC_MARKNUM_FOLDER,        wx.stc.STC_MARK_BOXPLUS,           "white", "#808080")
        self.Editor.MarkerDefine(wx.stc.STC_MARKNUM_FOLDERSUB,     wx.stc.STC_MARK_VLINE,             "white", "#808080")
        self.Editor.MarkerDefine(wx.stc.STC_MARKNUM_FOLDERTAIL,    wx.stc.STC_MARK_LCORNER,           "white", "#808080")
        self.Editor.MarkerDefine(wx.stc.STC_MARKNUM_FOLDEREND,     wx.stc.STC_MARK_BOXPLUSCONNECTED,  "white", "#808080")
        self.Editor.MarkerDefine(wx.stc.STC_MARKNUM_FOLDEROPENMID, wx.stc.STC_MARK_BOXMINUSCONNECTED, "white", "#808080")
        self.Editor.MarkerDefine(wx.stc.STC_MARKNUM_FOLDERMIDTAIL, wx.stc.STC_MARK_TCORNER,           "white", "#808080")

        # Indentation size
        self.Editor.SetTabWidth(2)
        self.Editor.SetUseTabs(0)

        self.Editor.SetModEventMask(wx.stc.STC_MOD_BEFOREINSERT |
                                    wx.stc.STC_MOD_BEFOREDELETE |
                                    wx.stc.STC_PERFORMED_USER)

        self.Bind(wx.stc.EVT_STC_STYLENEEDED, self.OnStyleNeeded, self.Editor)
        self.Editor.Bind(wx.stc.EVT_STC_MARGINCLICK, self.OnMarginClick)
        self.Editor.Bind(wx.stc.EVT_STC_UPDATEUI, self.OnUpdateUI)
        self.Editor.Bind(wx.EVT_KEY_DOWN, self.OnKeyDown)
        if self.Controler is not None:
            self.Editor.Bind(wx.EVT_KILL_FOCUS, self.OnKillFocus)
            self.Bind(wx.stc.EVT_STC_DO_DROP, self.OnDoDrop, self.Editor)
            self.Bind(wx.stc.EVT_STC_MODIFIED, self.OnModification, self.Editor)

    def __init__(self, parent, tagname, window, controler, debug=False, instancepath=""):
        if tagname != "" and controler is not None:
            self.VARIABLE_PANEL_TYPE = controler.GetPouType(tagname.split("::")[1])

        EditorPanel.__init__(self, parent, tagname, window, controler, debug)

        self.Keywords = []
        self.Variables = {}
        self.Functions = {}
        self.TypeNames = []
        self.Jumps = []
        self.EnumeratedValues = []
        self.DisableEvents = True
        self.TextSyntax = None
        self.CurrentAction = None

        self.InstancePath = instancepath
        self.ContextStack = []
        self.CallStack = []

        self.ResetSearchResults()

        self.RefreshHighlightsTimer = wx.Timer(self, -1)
        self.Bind(wx.EVT_TIMER, self.OnRefreshHighlightsTimer, self.RefreshHighlightsTimer)

    def __del__(self):
        self.RefreshHighlightsTimer.Stop()

    def GetTitle(self):
        if self.Debug or self.TagName == "":
            if len(self.InstancePath) > 15:
                return "..." + self.InstancePath[-12:]
            return self.InstancePath
        return EditorPanel.GetTitle(self)

    def GetInstancePath(self):
        return self.InstancePath

    def IsViewing(self, tagname):
        if self.Debug or self.TagName == "":
            return self.InstancePath == tagname
        else:
            return self.TagName == tagname

    def GetText(self):
        return self.Editor.GetText()

    def SetText(self, text):
        self.Editor.SetText(text)

    def SelectAll(self):
        self.Editor.SelectAll()

    def Colourise(self, start, end):
        self.Editor.Colourise(start, end)

    def StartStyling(self, pos, mask):
        self.Editor.StartStyling(pos, mask)

    def SetStyling(self, length, style):
        self.Editor.SetStyling(length, style)

    def GetCurrentPos(self):
        return self.Editor.GetCurrentPos()

    def ResetSearchResults(self):
        self.Highlights = []
        self.SearchParams = None
        self.SearchResults = None
        self.CurrentFindHighlight = None

    def OnModification(self, event):
        if not self.DisableEvents:
            mod_type = event.GetModificationType()
            if mod_type & wx.stc.STC_MOD_BEFOREINSERT:
                if self.CurrentAction is None:
                    self.StartBuffering()
                elif self.CurrentAction[0] != "Add" or self.CurrentAction[1] != event.GetPosition() - 1:
                    self.Controler.EndBuffering()
                    self.StartBuffering()
                self.CurrentAction = ("Add", event.GetPosition())
                wx.CallAfter(self.RefreshModel)
            elif mod_type & wx.stc.STC_MOD_BEFOREDELETE:
                if self.CurrentAction is None:
                    self.StartBuffering()
                elif self.CurrentAction[0] != "Delete" or self.CurrentAction[1] != event.GetPosition() + 1:
                    self.Controler.EndBuffering()
                    self.StartBuffering()
                self.CurrentAction = ("Delete", event.GetPosition())
                wx.CallAfter(self.RefreshModel)
        event.Skip()

    def OnDoDrop(self, event):
        try:
            values = eval(event.GetDragText())
        except Exception:
            values = event.GetDragText()
        if isinstance(values, tuple):
            message = None
            if values[1] in ["program", "debug"]:
                event.SetDragText("")
            elif values[1] in ["functionBlock", "function"]:
                blocktype = values[0]
                blockname = values[2]
                if len(values) > 3:
                    blockinputs = values[3]
                else:
                    blockinputs = None
                if values[1] != "function":
                    if blockname == "":
                        dialog = wx.TextEntryDialog(self.ParentWindow, _("Block name"), _("Please enter a block name"), "", wx.OK | wx.CANCEL | wx.CENTRE)
                        if dialog.ShowModal() == wx.ID_OK:
                            blockname = dialog.GetValue()
                        else:
                            event.SetDragText("")
                            return
                        dialog.Destroy()
                    if blockname.upper() in [name.upper() for name in self.Controler.GetProjectPouNames(self.Debug)]:
                        message = _("\"%s\" pou already exists!") % blockname
                    elif blockname.upper() in [name.upper() for name in self.Controler.GetEditedElementVariables(self.TagName, self.Debug)]:
                        message = _("\"%s\" element for this pou already exists!") % blockname
                    else:
                        self.Controler.AddEditedElementPouVar(self.TagName, values[0], blockname)
                        self.RefreshVariablePanel()
                        self.RefreshVariableTree()
                blockinfo = self.Controler.GetBlockType(blocktype, blockinputs, self.Debug)
                hint = ',\n    '.join(
                    [" " + fctdecl[0]+" := (*"+fctdecl[1]+"*)" for fctdecl in blockinfo["inputs"]] +
                    [" " + fctdecl[0]+" => (*"+fctdecl[1]+"*)" for fctdecl in blockinfo["outputs"]])
                if values[1] == "function":
                    event.SetDragText(blocktype+"(\n    "+hint+")")
                else:
                    event.SetDragText(blockname+"(\n    "+hint+")")
            elif values[1] == "location":
                _pou_name, pou_type = self.Controler.GetEditedElementType(self.TagName, self.Debug)
                if len(values) > 2 and pou_type == "program":
                    var_name = values[3]
                    dlg = wx.TextEntryDialog(
                        self.ParentWindow,
                        _("Confirm or change variable name"),
                        _('Variable Drop'), var_name)
                    dlg.SetValue(var_name)
                    var_name = dlg.GetValue() if dlg.ShowModal() == wx.ID_OK else None
                    dlg.Destroy()
                    if var_name is None:
                        return
                    elif var_name.upper() in [name.upper() for name in self.Controler.GetProjectPouNames(self.Debug)]:
                        message = _("\"%s\" pou already exists!") % var_name
                    elif var_name.upper() in [name.upper() for name in self.Controler.GetEditedElementVariables(self.TagName, self.Debug)]:
                        message = _("\"%s\" element for this pou already exists!") % var_name
                    else:
                        location = values[0]
                        if not location.startswith("%"):
                            dialog = wx.SingleChoiceDialog(
                                self.ParentWindow,
                                _("Select a variable class:"),
                                _("Variable class"),
                                [_("Input"), _("Output"), _("Memory")],
                                wx.DEFAULT_DIALOG_STYLE | wx.OK | wx.CANCEL)
                            if dialog.ShowModal() == wx.ID_OK:
                                selected = dialog.GetSelection()
                            else:
                                selected = None
                            dialog.Destroy()
                            if selected is None:
                                event.SetDragText("")
                                return
                            if selected == 0:
                                location = "%I" + location
                            elif selected == 1:
                                location = "%Q" + location
                            else:
                                location = "%M" + location
                        if values[2] is not None:
                            var_type = values[2]
                        else:
                            var_type = LOCATIONDATATYPES.get(location[2], ["BOOL"])[0]
                        self.Controler.AddEditedElementPouVar(
                            self.TagName,
                            var_type, var_name,
                            location=location, description=values[4])
                        self.RefreshVariablePanel()
                        self.RefreshVariableTree()
                        event.SetDragText(var_name)
                else:
                    event.SetDragText("")
            elif values[1] == "NamedConstant":
                _pou_name, pou_type = self.Controler.GetEditedElementType(self.TagName, self.Debug)
                if pou_type == "program":
                    initval = values[0]
                    var_name = values[3]
                    dlg = wx.TextEntryDialog(
                        self.ParentWindow,
                        _("Confirm or change variable name"),
                        _('Variable Drop'), var_name)
                    dlg.SetValue(var_name)
                    var_name = dlg.GetValue() if dlg.ShowModal() == wx.ID_OK else None
                    dlg.Destroy()
                    if var_name is None:
                        return
                    elif var_name.upper() in [name.upper() for name in self.Controler.GetProjectPouNames(self.Debug)]:
                        message = _("\"%s\" pou already exists!") % var_name
                    else:
                        var_type = values[2]
                        if not var_name.upper() in [name.upper() for name in self.Controler.GetEditedElementVariables(self.TagName, self.Debug)]:
                            self.Controler.AddEditedElementPouVar(self.TagName,
                                                                  var_type,
                                                                  var_name,
                                                                  description=values[4], initval=initval)
                            self.RefreshVariablePanel()
                            self.RefreshVariableTree()
                        event.SetDragText(var_name)
            elif values[1] == "Global":
                var_name = values[0]
                dlg = wx.TextEntryDialog(
                    self.ParentWindow,
                    _("Confirm or change variable name"),
                    _('Variable Drop'), var_name)
                dlg.SetValue(var_name)
                var_name = dlg.GetValue() if dlg.ShowModal() == wx.ID_OK else None
                dlg.Destroy()
                if var_name is None:
                    return
                elif var_name.upper() in [name.upper() for name in self.Controler.GetProjectPouNames(self.Debug)]:
                    message = _("\"%s\" pou already exists!") % var_name
                else:
                    if not var_name.upper() in [name.upper() for name in self.Controler.GetEditedElementVariables(self.TagName, self.Debug)]:
                        kwargs = dict(description=values[4]) if len(values)>4 else {}
                        self.Controler.AddEditedElementPouExternalVar(self.TagName, values[2], var_name, **kwargs)
                        self.RefreshVariablePanel()
                        self.RefreshVariableTree()
                    event.SetDragText(var_name)
            elif values[1] == "Constant":
                event.SetDragText(values[0])
            elif values[3] == self.TagName:
                self.ResetBuffer()
                event.SetDragText(values[0])
                wx.CallAfter(self.RefreshModel)
            else:
                message = _("Variable don't belong to this POU!")
            if message is not None:
                dialog = wx.MessageDialog(self, message, _("Error"), wx.OK | wx.ICON_ERROR)
                dialog.ShowModal()
                dialog.Destroy()
                event.SetDragText("")
        event.Skip()

    def SetTextSyntax(self, syntax):
        self.TextSyntax = syntax
        if syntax in ["ST", "ALL"]:
            self.Editor.SetMarginType(2, wx.stc.STC_MARGIN_SYMBOL)
            self.Editor.SetMarginMask(2, wx.stc.STC_MASK_FOLDERS)
            self.Editor.SetMarginSensitive(2, 1)
            self.Editor.SetMarginWidth(2, 12)
            if syntax == "ST":
                self.BlockStartKeywords = ST_BLOCK_START_KEYWORDS
                self.BlockEndKeywords = ST_BLOCK_START_KEYWORDS
            else:
                self.BlockStartKeywords = IEC_BLOCK_START_KEYWORDS
                self.BlockEndKeywords = IEC_BLOCK_START_KEYWORDS
        else:
            self.BlockStartKeywords = []
            self.BlockEndKeywords = []

    def SetKeywords(self, keywords):
        self.Keywords = [keyword.upper() for keyword in keywords]
        self.Colourise(0, -1)

    def RefreshJumpList(self):
        if self.TextSyntax == "IL":
            self.Jumps = [jump.upper() for jump in LABEL_MODEL.findall(self.GetText())]

    # Buffer the last model state
    def RefreshBuffer(self):
        self.Controler.BufferProject()
        if self.ParentWindow:
            self.ParentWindow.RefreshTitle()
            self.ParentWindow.RefreshFileMenu()
            self.ParentWindow.RefreshEditMenu()

    def StartBuffering(self):
        self.Controler.StartBuffering()
        if self.ParentWindow:
            self.ParentWindow.RefreshTitle()
            self.ParentWindow.RefreshFileMenu()
            self.ParentWindow.RefreshEditMenu()

    def ResetBuffer(self):
        if self.CurrentAction is not None:
            self.Controler.EndBuffering()
            self.CurrentAction = None

    def GetBufferState(self):
        if not self.Debug and self.TextSyntax != "ALL":
            return self.Controler.GetBufferState()
        return False, False

    def Undo(self):
        if not self.Debug and self.TextSyntax != "ALL":
            self.Controler.LoadPrevious()
            self.ParentWindow.CloseTabsWithoutModel()

    def Redo(self):
        if not self.Debug and self.TextSyntax != "ALL":
            self.Controler.LoadNext()
            self.ParentWindow.CloseTabsWithoutModel()

    def HasNoModel(self):
        if not self.Debug and self.TextSyntax != "ALL":
            return self.Controler.GetEditedElement(self.TagName) is None
        return False

    def RefreshView(self, variablepanel=True):
        EditorPanel.RefreshView(self, variablepanel)

        if self.Controler is not None:
            self.ResetBuffer()
            self.DisableEvents = True
            old_cursor_pos = self.GetCurrentPos()
            line = self.Editor.GetFirstVisibleLine()
            column = self.Editor.GetXOffset()
            old_text = self.GetText()
            new_text = self.Controler.GetEditedElementText(self.TagName, self.Debug)
            if old_text != new_text:
                self.SetText(new_text)
                new_cursor_pos = GetCursorPos(old_text, new_text)
                self.Editor.LineScroll(column, line)
                if new_cursor_pos is not None:
                    self.Editor.GotoPos(new_cursor_pos)
                else:
                    self.Editor.GotoPos(old_cursor_pos)
                self.RefreshJumpList()
                self.Editor.EmptyUndoBuffer()
            self.DisableEvents = False

            self.RefreshVariableTree()

            self.TypeNames = [typename.upper() for typename in self.Controler.GetDataTypes(self.TagName, True, self.Debug)]
            self.EnumeratedValues = [value.upper() for value in self.Controler.GetEnumeratedDataValues()]

            self.Functions = {}
            for category in self.Controler.GetBlockTypes(self.TagName, self.Debug):
                for blocktype in category["list"]:
                    blockname = blocktype["name"].upper()
                    if blocktype["type"] == "function" and blockname not in self.Keywords and blockname not in self.Variables.keys():
                        interface = dict([(name, {}) for name, _type, _modifier in blocktype["inputs"] + blocktype["outputs"] if name != ''])
                        for param in ["EN", "ENO"]:
                            if param not in interface:
                                interface[param] = {}
                        if blockname in self.Functions:
                            self.Functions[blockname]["interface"].update(interface)
                            self.Functions[blockname]["extensible"] |= blocktype["extensible"]
                        else:
                            self.Functions[blockname] = {"interface": interface,
                                                         "extensible": blocktype["extensible"]}

        self.Colourise(0, -1)

    def RefreshVariableTree(self):
        words = self.TagName.split("::")
        self.Variables = self.GenerateVariableTree([
            (variable.Name, variable.Type, variable.Tree)
            for variable in
            self.Controler.GetEditedElementInterfaceVars(
                self.TagName, True, self.Debug)
        ])
        if self.Controler.GetEditedElementType(self.TagName, self.Debug)[1] == "function" or words[0] == "T" and self.TextSyntax == "IL":
            return_type, (var_tree, _var_dimension) = self.Controler.GetEditedElementInterfaceReturnType(self.TagName, True, self.Debug)
            if return_type is not None:
                self.Variables[words[-1].upper()] = self.GenerateVariableTree(var_tree)
            else:
                self.Variables[words[-1].upper()] = {}

    def GenerateVariableTree(self, list):
        tree = {}
        for var_name, _var_type, (var_tree, _var_dimension) in list:
            tree[var_name.upper()] = self.GenerateVariableTree(var_tree)
        return tree

    def IsValidVariable(self, name, context):
        return context is not None and context.get(name, None) is not None

    def IsCallParameter(self, name, call):
        if call is not None:
            return (call["interface"].get(name.upper(), None) is not None or
                    call["extensible"] and EXTENSIBLE_PARAMETER.match(name.upper()) is not None)
        return False

    def RefreshLineFolding(self, line_number):
        if self.TextSyntax in ["ST", "ALL"]:
            level = wx.stc.STC_FOLDLEVELBASE + self.Editor.GetLineIndentation(line_number)
            line = self.Editor.GetLine(line_number).strip()
            if line == "":
                if line_number > 0:
                    if LineStartswith(self.Editor.GetLine(line_number - 1).strip(), self.BlockEndKeywords):
                        level = self.Editor.GetFoldLevel(self.Editor.GetFoldParent(line_number - 1)) & wx.stc.STC_FOLDLEVELNUMBERMASK
                    else:
                        level = self.Editor.GetFoldLevel(line_number - 1) & wx.stc.STC_FOLDLEVELNUMBERMASK
                if level != wx.stc.STC_FOLDLEVELBASE:
                    level |= wx.stc.STC_FOLDLEVELWHITEFLAG
            elif LineStartswith(line, self.BlockStartKeywords):
                level |= wx.stc.STC_FOLDLEVELHEADERFLAG
            elif LineStartswith(line, self.BlockEndKeywords):
                if LineStartswith(self.Editor.GetLine(line_number - 1).strip(), self.BlockEndKeywords):
                    level = self.Editor.GetFoldLevel(self.Editor.GetFoldParent(line_number - 1)) & wx.stc.STC_FOLDLEVELNUMBERMASK
                else:
                    level = self.Editor.GetFoldLevel(line_number - 1) & wx.stc.STC_FOLDLEVELNUMBERMASK
            self.Editor.SetFoldLevel(line_number, level)

    def OnStyleNeeded(self, event):
        self.TextChanged = True
        line_number = self.Editor.LineFromPosition(self.Editor.GetEndStyled())
        if line_number == 0:
            start_pos = last_styled_pos = 0
        else:
            start_pos = last_styled_pos = self.Editor.GetLineEndPosition(line_number - 1) + 1
        self.RefreshLineFolding(line_number)
        end_pos = event.GetPosition()
        self.StartStyling(start_pos, 0xff)

        current_context = self.Variables
        current_call = None

        current_pos = last_styled_pos
        state = SPACE
        line = ""
        word = ""
        while current_pos < end_pos:
            char = chr(self.Editor.GetCharAt(current_pos)).upper()
            line += char
            if char == NEWLINE:
                self.ContextStack = []
                current_context = self.Variables
                if state == COMMENT:
                    self.SetStyling(current_pos - last_styled_pos, STC_PLC_COMMENT)
                elif state == NUMBER:
                    self.SetStyling(current_pos - last_styled_pos, STC_PLC_NUMBER)
                elif state == WORD:
                    if word in self.Keywords or word in self.TypeNames:
                        self.SetStyling(current_pos - last_styled_pos, STC_PLC_WORD)
                    elif self.IsValidVariable(word, current_context):
                        self.SetStyling(current_pos - last_styled_pos, STC_PLC_VARIABLE)
                    elif self.IsCallParameter(word, current_call):
                        self.SetStyling(current_pos - last_styled_pos, STC_PLC_PARAMETER)
                    elif word in self.Functions:
                        self.SetStyling(current_pos - last_styled_pos, STC_PLC_FUNCTION)
                    elif self.TextSyntax == "IL" and word in self.Jumps:
                        self.SetStyling(current_pos - last_styled_pos, STC_PLC_JUMP)
                    elif word in self.EnumeratedValues:
                        self.SetStyling(current_pos - last_styled_pos, STC_PLC_NUMBER)
                    else:
                        self.SetStyling(current_pos - last_styled_pos, STC_PLC_EMPTY)
                        if word not in ["]", ")"] and (self.GetCurrentPos() < last_styled_pos or self.GetCurrentPos() > current_pos):
                            self.StartStyling(last_styled_pos, wx.stc.STC_INDICS_MASK)
                            self.SetStyling(current_pos - last_styled_pos, wx.stc.STC_INDIC0_MASK)
                            self.StartStyling(current_pos, 0xff)
                else:
                    self.SetStyling(current_pos - last_styled_pos, STC_PLC_EMPTY)
                last_styled_pos = current_pos
                if (state != DPRAGMA) and (state != COMMENT):
                    state = SPACE
                line = ""
                line_number += 1
                self.RefreshLineFolding(line_number)
            elif line.endswith("(*") and state != COMMENT:
                self.SetStyling(current_pos - last_styled_pos - 1, STC_PLC_EMPTY)
                last_styled_pos = current_pos
                if state == WORD:
                    current_context = self.Variables
                state = COMMENT
            elif line.endswith("{") and state not in [PRAGMA, DPRAGMA]:
                self.SetStyling(current_pos - last_styled_pos, STC_PLC_EMPTY)
                last_styled_pos = current_pos
                if state == WORD:
                    current_context = self.Variables
                state = PRAGMA
            elif line.endswith("{{") and state == PRAGMA:
                self.SetStyling(current_pos - last_styled_pos, STC_PLC_EMPTY)
                last_styled_pos = current_pos
                state = DPRAGMA
            elif state == COMMENT:
                if line.endswith("*)"):
                    self.SetStyling(current_pos - last_styled_pos + 2, STC_PLC_COMMENT)
                    last_styled_pos = current_pos + 1
                    state = SPACE
                    if len(self.CallStack) > 0:
                        current_call = self.CallStack.pop()
                    else:
                        current_call = None
            elif state == PRAGMA:
                if line.endswith("}"):
                    self.SetStyling(current_pos - last_styled_pos, STC_PLC_EMPTY)
                    last_styled_pos = current_pos
                    state = SPACE
            elif state == DPRAGMA:
                if line.endswith("}}"):
                    self.SetStyling(current_pos - last_styled_pos + 1, STC_PLC_EMPTY)
                    last_styled_pos = current_pos + 1
                    state = SPACE
            elif (line.endswith("'") or line.endswith('"')) and state not in [STRING, WSTRING]:
                self.SetStyling(current_pos - last_styled_pos, STC_PLC_EMPTY)
                last_styled_pos = current_pos
                if state == WORD:
                    current_context = self.Variables
                if line.endswith("'"):
                    state = STRING
                else:
                    state = WSTRING
            elif state == STRING:
                if line.endswith("'") and not line.endswith("$'"):
                    self.SetStyling(current_pos - last_styled_pos + 1, STC_PLC_STRING)
                    last_styled_pos = current_pos + 1
                    state = SPACE
            elif state == WSTRING:
                if line.endswith('"') and not line.endswith('$"'):
                    self.SetStyling(current_pos - last_styled_pos + 1, STC_PLC_STRING)
                    last_styled_pos = current_pos + 1
                    state = SPACE
            elif char in LETTERS:
                if state == NUMBER:
                    word = "#"
                    state = WORD
                elif state == SPACE:
                    self.SetStyling(current_pos - last_styled_pos, STC_PLC_EMPTY)
                    word = char
                    last_styled_pos = current_pos
                    state = WORD
                else:
                    word += char
            elif char in NUMBERS or char == '.' and state != WORD:
                if state == SPACE:
                    self.SetStyling(current_pos - last_styled_pos, STC_PLC_EMPTY)
                    last_styled_pos = current_pos
                    state = NUMBER
                elif state == WORD and char != '.':
                    word += char
            elif char == '(' and state == SPACE:
                self.CallStack.append(current_call)
                current_call = None
            else:
                if state == WORD:
                    if word in self.Keywords or word in self.TypeNames:
                        self.SetStyling(current_pos - last_styled_pos, STC_PLC_WORD)
                    elif self.IsValidVariable(word, current_context):
                        self.SetStyling(current_pos - last_styled_pos, STC_PLC_VARIABLE)
                    elif self.IsCallParameter(word, current_call):
                        self.SetStyling(current_pos - last_styled_pos, STC_PLC_PARAMETER)
                    elif word in self.Functions:
                        self.SetStyling(current_pos - last_styled_pos, STC_PLC_FUNCTION)
                    elif self.TextSyntax == "IL" and word in self.Jumps:
                        self.SetStyling(current_pos - last_styled_pos, STC_PLC_JUMP)
                    elif word in self.EnumeratedValues:
                        self.SetStyling(current_pos - last_styled_pos, STC_PLC_NUMBER)
                    else:
                        self.SetStyling(current_pos - last_styled_pos, STC_PLC_EMPTY)
                        if word not in ["]", ")"] and (self.GetCurrentPos() < last_styled_pos or self.GetCurrentPos() > current_pos):
                            self.StartStyling(last_styled_pos, wx.stc.STC_INDICS_MASK)
                            self.SetStyling(current_pos - last_styled_pos, wx.stc.STC_INDIC0_MASK)
                            self.StartStyling(current_pos, 0xff)
                    if char == '.':
                        if word != "]":
                            if current_context is not None:
                                current_context = current_context.get(word, None)
                            else:
                                current_context = None
                    elif char == '(':
                        self.CallStack.append(current_call)
                        current_call = self.Functions.get(word, None)
                        if current_call is None and self.IsValidVariable(word, current_context):
                            current_call = {"interface": current_context.get(word, {}),
                                            "extensible": False}
                        current_context = self.Variables
                    else:
                        if char == '[' and current_context is not None:
                            self.ContextStack.append(current_context.get(word, None))
                        current_context = self.Variables

                    word = ""
                    last_styled_pos = current_pos
                    state = SPACE
                elif state == NUMBER:
                    self.SetStyling(current_pos - last_styled_pos, STC_PLC_NUMBER)
                    last_styled_pos = current_pos
                    state = SPACE
                if char == ']':
                    if len(self.ContextStack) > 0:
                        current_context = self.ContextStack.pop()
                    else:
                        current_context = self.Variables
                    word = char
                    state = WORD
                elif char == ')':
                    current_context = self.Variables
                    if len(self.CallStack) > 0:
                        current_call = self.CallStack.pop()
                    else:
                        current_call = None
                    word = char
                    state = WORD
            current_pos += 1
        if state == COMMENT:
            self.SetStyling(current_pos - last_styled_pos + 2, STC_PLC_COMMENT)
        elif state == NUMBER:
            self.SetStyling(current_pos - last_styled_pos, STC_PLC_NUMBER)
        elif state == WORD:
            if word in self.Keywords or word in self.TypeNames:
                self.SetStyling(current_pos - last_styled_pos, STC_PLC_WORD)
            elif self.IsValidVariable(word, current_context):
                self.SetStyling(current_pos - last_styled_pos, STC_PLC_VARIABLE)
            elif self.IsCallParameter(word, current_call):
                self.SetStyling(current_pos - last_styled_pos, STC_PLC_PARAMETER)
            elif self.TextSyntax == "IL" and word in self.Functions:
                self.SetStyling(current_pos - last_styled_pos, STC_PLC_FUNCTION)
            elif word in self.Jumps:
                self.SetStyling(current_pos - last_styled_pos, STC_PLC_JUMP)
            elif word in self.EnumeratedValues:
                self.SetStyling(current_pos - last_styled_pos, STC_PLC_NUMBER)
            else:
                self.SetStyling(current_pos - last_styled_pos, STC_PLC_EMPTY)
        else:
            self.SetStyling(current_pos - start_pos, STC_PLC_EMPTY)
        self.ShowHighlights(start_pos, end_pos)
        event.Skip()

    def OnMarginClick(self, event):
        if event.GetMargin() == 2:
            line = self.Editor.LineFromPosition(event.GetPosition())
            if self.Editor.GetFoldLevel(line) & wx.stc.STC_FOLDLEVELHEADERFLAG:
                self.Editor.ToggleFold(line)
        event.Skip()

    def OnUpdateUI(self, event):
        selected = self.Editor.GetSelectedText()
        if self.ParentWindow and selected != "":
            self.ParentWindow.SetCopyBuffer(selected, True)
        event.Skip()

    def Cut(self):
        self.ResetBuffer()
        self.DisableEvents = True
        self.Editor.CmdKeyExecute(wx.stc.STC_CMD_CUT)
        self.DisableEvents = False
        self.RefreshModel()
        self.RefreshBuffer()

    def Copy(self):
        self.Editor.CmdKeyExecute(wx.stc.STC_CMD_COPY)
        if self.ParentWindow:
            self.ParentWindow.RefreshEditMenu()

    def Paste(self):
        self.ResetBuffer()
        self.DisableEvents = True
        self.Editor.CmdKeyExecute(wx.stc.STC_CMD_PASTE)
        self.DisableEvents = False
        self.RefreshModel()
        self.RefreshBuffer()

    def Search(self, criteria):
        return self.Controler.SearchInPou(self.TagName, criteria, self.Debug)

    def Find(self, direction, search_params):
        if self.SearchParams != search_params:
            self.ClearHighlights(SEARCH_RESULT_HIGHLIGHT)

            self.SearchParams = search_params
            self.SearchResults = [
                (infos[1:], start, end, SEARCH_RESULT_HIGHLIGHT)
                for infos, start, end, _text in
                self.Search(search_params)]
            self.CurrentFindHighlight = None

        if len(self.SearchResults) > 0:
            if self.CurrentFindHighlight is not None:
                old_idx = self.SearchResults.index(self.CurrentFindHighlight)
                if self.SearchParams["wrap"]:
                    idx = (old_idx + direction) % len(self.SearchResults)
                else:
                    idx = max(0, min(old_idx + direction, len(self.SearchResults) - 1))
                if idx != old_idx:
                    self.RemoveHighlight(*self.CurrentFindHighlight)
                    self.CurrentFindHighlight = self.SearchResults[idx]
                    self.AddHighlight(*self.CurrentFindHighlight)
            else:
                self.CurrentFindHighlight = self.SearchResults[0]
                self.AddHighlight(*self.CurrentFindHighlight)

        else:
            if self.CurrentFindHighlight is not None:
                self.RemoveHighlight(*self.CurrentFindHighlight)
            self.CurrentFindHighlight = None

    def RefreshModel(self):
        self.RefreshJumpList()
        self.Colourise(0, -1)
        self.Controler.SetEditedElementText(self.TagName, self.GetText())
        self.ResetSearchResults()

    def OnKeyDown(self, event):
        key = event.GetKeyCode()
        if self.Controler is not None:

            if self.Editor.CallTipActive():
                self.Editor.CallTipCancel()

            key_handled = False

            line = self.Editor.GetCurrentLine()
            if line == 0:
                start_pos = 0
            else:
                start_pos = self.Editor.GetLineEndPosition(line - 1) + 1
            end_pos = self.GetCurrentPos()
            lineText = self.Editor.GetTextRange(start_pos, end_pos).replace("\t", " ")

            # Code completion
            if key == wx.WXK_SPACE and event.ControlDown():

                words = lineText.split(" ")
                words = [word for i, word in enumerate(words) if word != '' or i == len(words) - 1]

                kw = []

                if self.TextSyntax == "IL":
                    if len(words) == 1:
                        kw = self.Keywords
                    elif len(words) == 2:
                        if words[0].upper() in ["CAL", "CALC", "CALNC"]:
                            kw = self.Functions
                        elif words[0].upper() in ["JMP", "JMPC", "JMPNC"]:
                            kw = self.Jumps
                        else:
                            kw = self.Variables.keys()
                else:
                    kw = self.Keywords + self.Variables.keys() + self.Functions.keys()
                if len(kw) > 0:
                    if len(words[-1]) > 0:
                        kw = [keyword for keyword in kw if keyword.startswith(words[-1])]
                    kw.sort()
                    self.Editor.AutoCompSetIgnoreCase(True)
                    self.Editor.AutoCompShow(len(words[-1]), " ".join(kw))
                key_handled = True
            elif key == wx.WXK_RETURN or key == wx.WXK_NUMPAD_ENTER:
                if self.TextSyntax in ["ST", "ALL"]:
                    indent = self.Editor.GetLineIndentation(line)
                    if LineStartswith(lineText.strip(), self.BlockStartKeywords):
                        indent = (indent // 2 + 1) * 2
                    self.Editor.AddText("\n" + " " * indent)
                    key_handled = True
            elif key == wx.WXK_BACK:
                if self.TextSyntax in ["ST", "ALL"]:
                    if not self.Editor.GetSelectedText():
                        indent = self.Editor.GetColumn(self.Editor.GetCurrentPos())
                        if lineText.strip() == "" and len(lineText) > 0 and indent > 0:
                            self.Editor.DelLineLeft()
                            self.Editor.AddText(" " * ((max(0, indent - 1) // 2) * 2))
                            key_handled = True
            if not key_handled:
                event.Skip()
        else:
            event.Skip()

    def OnKillFocus(self, event):
        self.Editor.AutoCompCancel()
        event.Skip()

    # -------------------------------------------------------------------------------
    #                        Highlights showing functions
    # -------------------------------------------------------------------------------

    def OnRefreshHighlightsTimer(self, event):
        self.RefreshView()
        event.Skip()

    def ClearHighlights(self, highlight_type=None):
        EditorPanel.ClearHighlights(self, highlight_type)

        if highlight_type is None:
            self.Highlights = []
        else:
            highlight_type = HIGHLIGHT_TYPES.get(highlight_type, None)
            if highlight_type is not None:
                self.Highlights = [(infos, start, end, highlight) for (infos, start, end, highlight) in self.Highlights if highlight != highlight_type]
        self.RefreshView()

    def AddHighlight(self, infos, start, end, highlight_type):
        EditorPanel.AddHighlight(self, infos, start, end, highlight_type)

        highlight_type = HIGHLIGHT_TYPES.get(highlight_type, None)
        if infos[0] == "body" and highlight_type is not None:
            self.Highlights.append((infos[1], start, end, highlight_type))
            self.Editor.GotoPos(self.Editor.PositionFromLine(start[0]) + start[1])
            self.RefreshHighlightsTimer.Start(int(REFRESH_HIGHLIGHT_PERIOD * 1000), oneShot=True)

    def RemoveHighlight(self, infos, start, end, highlight_type):
        EditorPanel.RemoveHighlight(self, infos, start, end, highlight_type)

        highlight_type = HIGHLIGHT_TYPES.get(highlight_type, None)
        if infos[0] == "body" and highlight_type is not None and \
           (infos[1], start, end, highlight_type) in self.Highlights:
            self.Highlights.remove((infos[1], start, end, highlight_type))
            self.RefreshHighlightsTimer.Start(int(REFRESH_HIGHLIGHT_PERIOD * 1000), oneShot=True)

    def ShowHighlights(self, start_pos, end_pos):
        for indent, start, end, highlight_type in self.Highlights:
            if start[0] == 0:
                highlight_start_pos = start[1] - indent
            else:
                highlight_start_pos = self.Editor.GetLineEndPosition(start[0] - 1) + start[1] - indent + 1
            if end[0] == 0:
                highlight_end_pos = end[1] - indent + 1
            else:
                highlight_end_pos = self.Editor.GetLineEndPosition(end[0] - 1) + end[1] - indent + 2
            if highlight_start_pos < end_pos and highlight_end_pos > start_pos:
                self.StartStyling(highlight_start_pos, 0xff)
                self.SetStyling(highlight_end_pos - highlight_start_pos, highlight_type)
                self.StartStyling(highlight_start_pos, 0x00)
                until_end = max(0, len(self.Editor.GetText()) - highlight_end_pos)
                self.SetStyling(until_end, wx.stc.STC_STYLE_DEFAULT)


from transformers import ColorTransformer

from ..blend.blend import *
from ..palettes.core_palette import *
from ..scheme.scheme import *
from .image_utils import *
from .string_utils import *

# /**
#  * Generate custom color group from source and target color
#  *
#  * @param source Source color
#  * @param color Custom color
#  * @return Custom color group
#  *
#  * @link https://m3.material.io/styles/color/the-color-system/color-roles
#  */
# NOTE: Changes made to output format to be Dictionary
def customColor(source, color):
    value = color["value"]
    from_v = value
    to = source
    if color["blend"]:
        value = Blend.harmonize(from_v, to)
    palette = CorePalette.of(value)
    tones = palette.a1
    return {
        "color": color,
        "value": value,
        "light": {
            "color": tones.tone(40),
            "onColor": tones.tone(100),
            "colorContainer": tones.tone(90),
            "onColorContainer": tones.tone(10),
        },
        "dark": {
            "color": tones.tone(80),
            "onColor": tones.tone(20),
            "colorContainer": tones.tone(30),
            "onColorContainer": tones.tone(90),
        },
    }

# /**
#  * Generate a theme from a source color
#  *
#  * @param source Source color
#  * @param customColors Array of custom colors
#  * @return Theme object
#  */
# NOTE: Changes made to output format to be Dictionary
def themeFromSourceColor(source: int, customColors=[]):
    palette = CorePalette.of(source)
    return {
        "source": source,
        "schemes": {
            "light": Scheme.light(source),
            "dark": Scheme.dark(source),
        },
        "palettes": {
            "primary": palette.a1,
            "secondary": palette.a2,
            "tertiary": palette.a3,
            "neutral": palette.n1,
            "neutralVariant": palette.n2,
            "error": palette.error,
        },
        "customColors": [customColor(source, c) for c in customColors],
    }

# /**
#  * Generate a theme from an image source
#  *
#  * @param image Image element
#  * @param customColors Array of custom colors
#  * @return Theme object
#  */
def themeFromImage(image, customColors=[]):
    colors = topColorsFromImage(image)
    return themeFromSourceColor(colors[0], customColors), [
        ColorTransformer.argb_to_hex(color) for color in colors
    ]

# Not really applicable to python CLI
# # /**
# #  * Apply a theme to an element
# #  *
# #  * @param theme Theme object
# #  * @param options Options
# #  */
# export function applyTheme(theme, options) {
#     var _a;
#     const target = (options === null || options === void 0 ? void 0 : options.target) || document.body;
#     const isDark = (_a = options === null || options === void 0 ? void 0 : options.dark) !== null && _a !== void 0 ? _a : false;
#     const scheme = isDark ? theme.schemes.dark : theme.schemes.light;
#     for (const [key, value] of Object.entries(scheme.toJSON())) {
#         const token = key.replace(/([a-z])([A-Z])/g, "$1-$2").toLowerCase();
#         const color = hexFromArgb(value);
#         target.style.setProperty(`--md-sys-color-${token}`, color);
#     }
# }
# //# sourceMappingURL=theme_utils.js.map


from collections import defaultdict

# Utility function to create dictionary
def multi_dict(K, type):
    if K == 1:
        return defaultdict(type)
    else:
        return defaultdict(lambda: multi_dict(K-1, type))

with open('input-10.txt') as f:
    lines = [row.strip() for row in f]

print(lines)

X=1
cycles = []

def cycle():
    global cycles
    cycles.append(X)

def execute_instruction(instr):
    global X
    if instr[0] == 'addx':
        print(f"addx {instr[1]}")
        cycle()
        cycle()
        X += int(instr[1])

    if instr[0] == "noop":
        cycle()

for line in lines:
    instr = line.split(' ')
    execute_instruction(instr)

print(cycles)

ss=0
for ix in range(19,len(cycles),40):
    print(cycles[ix], cycles[ix] * (ix+1))
    ss += cycles[ix] * (ix+1)

print(ss)


import unittest
import subprocess
import os
import numpy as np
from openfermion import (
    QubitOperator, InteractionOperator, FermionOperator, IsingOperator,
    get_interaction_operator, hermitian_conjugated
)
from zquantum.core.circuit import build_uniform_param_grid
from zquantum.core.utils import create_object
from ._utils import evaluate_operator_for_parameter_grid
from ._io import (
    load_qubit_operator, save_qubit_operator, load_interaction_operator,
    save_interaction_operator, convert_qubitop_to_dict, convert_dict_to_qubitop,
    convert_interaction_op_to_dict, convert_dict_to_interaction_op,
    convert_isingop_to_dict, convert_dict_to_isingop,
    save_ising_operator, load_ising_operator, save_parameter_grid_evaluation
)

class TestQubitOperator(unittest.TestCase):

    def test_qubitop_to_dict_io(self):
        # Given
        qubit_op = QubitOperator(((0, 'Y'), (1, 'X'), (2, 'Z'), (4, 'X')), 3.j)
        qubit_op += hermitian_conjugated(qubit_op)

        # When
        qubitop_dict = convert_qubitop_to_dict(qubit_op)
        recreated_qubit_op = convert_dict_to_qubitop(qubitop_dict)

        # Then
        self.assertEqual(recreated_qubit_op, qubit_op)

    def test_qubit_operator_io(self):
        # Given
        qubit_op = QubitOperator(((0, 'Y'), (3, 'X'), (8, 'Z'), (11, 'X')), 3.j)

        # When
        save_qubit_operator(qubit_op, 'qubit_op.json')
        loaded_op = load_qubit_operator('qubit_op.json')

        # Then
        self.assertEqual(qubit_op, loaded_op)
        os.remove('qubit_op.json')

    def test_interaction_op_to_dict_io(self):
        # Given
        test_op = FermionOperator('1^ 2^ 3 4')
        test_op += hermitian_conjugated(test_op)
        interaction_op = get_interaction_operator(test_op)
        interaction_op.constant = 0.0

        # When
        interaction_op_dict = convert_interaction_op_to_dict(interaction_op)
        recreated_interaction_op = convert_dict_to_interaction_op(interaction_op_dict)

        # Then
        self.assertEqual(recreated_interaction_op, interaction_op)

    def test_interaction_operator_io(self):
        # Given
        test_op = FermionOperator('1^ 2^ 3 4')
        test_op += hermitian_conjugated(test_op)
        interaction_op = get_interaction_operator(test_op)
        interaction_op.constant = 0.0

        # When
        save_interaction_operator(interaction_op, 'interaction_op.json')
        loaded_op = load_interaction_operator('interaction_op.json')

        # Then
        self.assertEqual(interaction_op, loaded_op)
        os.remove('interaction_op.json')

    def test_qubitop_io(self):
        # Given
        qubit_op = QubitOperator(((0, 'Y'), (1, 'X'), (2, 'Z'), (4, 'X')), 3.j)

        # When
        save_qubit_operator(qubit_op, 'qubit_op.json')
        loaded_op = load_qubit_operator('qubit_op.json')

        # Then
        self.assertEqual(qubit_op, loaded_op)
        os.remove('qubit_op.json')

    def test_isingop_to_dict_io(self):
        # Given
        ising_op = IsingOperator('[] + 3[Z0 Z1] + [Z1 Z2]')

        # When
        isingop_dict = convert_isingop_to_dict(ising_op)
        recreated_isingop = convert_dict_to_isingop(isingop_dict)

        # Then
        self.assertEqual(recreated_isingop, ising_op)

    def test_isingop_io(self):
        # Given
        ising_op = IsingOperator('[] + 3[Z0 Z1] + [Z1 Z2]')

        # When
        save_ising_operator(ising_op, 'ising_op.json')
        loaded_op = load_ising_operator('ising_op.json')

        # Then
        self.assertEqual(ising_op, loaded_op)
        os.remove('ising_op.json')

    def test_save_parameter_grid_evaluation(self):
        # Given
        ansatz = {'ansatz_type': 'singlet UCCSD', 'ansatz_module': 'zquantum.qaoa.ansatz', 'ansatz_func': 'build_qaoa_circuit', 'ansatz_grad_func': 'build_qaoa_circuit_grads', 'supports_simple_shift_rule': False, 'ansatz_kwargs': {'hamiltonians': [{'schema': 'zapata-v1-qubit_op', 'terms': [{'pauli_ops': [], 'coefficient': {'real': 0.5}}, {'pauli_ops': [{'qubit': 1, 'op': 'Z'}], 'coefficient': {'real': 0.5}}]}, {'schema': 'zapata-v1-qubit_op', 'terms': [{'pauli_ops': [{'qubit': 0, 'op': 'X'}], 'coefficient': {'real': 1.0}}, {'pauli_ops': [{'qubit': 1, 'op': 'X'}], 'coefficient': {'real': 1.0}}]}]}, 'n_params': [2]}
        grid = build_uniform_param_grid(ansatz, 1, 0, np.pi, np.pi/10)
        backend = create_object({'module_name': 'zquantum.core.interfaces.mock_objects', 'function_name': 'MockQuantumSimulator'})
        op = QubitOperator('0.5 [] + 0.5 [Z1]')
        parameter_grid_evaluation = evaluate_operator_for_parameter_grid(ansatz, grid, backend, op)
        # When
        save_parameter_grid_evaluation(parameter_grid_evaluation, "parameter-grid-evaluation.json")
        # Then
        # TODO

    def tearDown(self):
        subprocess.run(["rm", "parameter-grid-evaluation.json"])


import streamlit as st
from streamlit_player import st_player

column1, column2,  = st.columns(2)

st.subheader("Send Email Receipts using automation")
st_player("https://youtu.be/G3fTz6VnnTc")

st.divider()

st.subheader("Recording Videos using Flonnect")
st_player("https://youtu.be/id_Oj7cG0Hs")

st.divider()

st.subheader("Fund Raising Knowledge Transfer")
st_player("https://youtu.be/gWe0NEzDwGo")

st.divider()

st.subheader("Fund Raising Tracker For Filling/Tracking Tasks")
st_player("https://youtu.be/6NNCgoUWXo0")

st.divider()
hide_st_style = """
<style>
#Mainmenu {Visibility : hidden;}
footer {Visibility : hidden;}
header {Visibility : hidden;}
</style>
"""
st.markdown(hide_st_style,unsafe_allow_html=True)


### This is the LSTM training module ###

from keras.preprocessing.text import Tokenizer
from keras.preprocessing.sequence import pad_sequences
from keras.models import Sequential
from keras.layers import Dense, Flatten, LSTM, Conv1D, MaxPooling1D, Dropout, Activation
from keras.layers.embeddings import Embedding
from keras.layers import Bidirectional
import numpy as np
import pandas as pd
from matplotlib import pyplot

data = pd.read_csv('C:/Users/Swars/Desktop/FYP/FYP/processed_req_offer.csv')
column = data.label

for i in range(len(column)):
    if data.label[i]=='request':
        data.label[i]=0
    elif data.label[i]=='offer':
        data.label[i]=1
    elif data.label[i]=='RO':
        data.label[i]=2

tokenizer = Tokenizer()
tokenizer.fit_on_texts(data['tweettext'])
vocabulary_size=len(tokenizer.word_index) + 1
sequences = tokenizer.texts_to_sequences(data['tweettext'])
#print sequences[0]

#TRAINING USING GLOVE PRETRAINED
embeddings_index= dict()
f=open('C:/Users/Swars/Desktop/FYP/glove.6B.100d.txt',encoding='utf8')
for line in f:
		values=line.split()
		word=values[0]
		coefs=np.asarray(values[1:],dtype='float32')
		embeddings_index[word]=coefs
f.close()

embedding_matrix=np.zeros((vocabulary_size,100))
for word, i in tokenizer.word_index.items():
	embedding_vector=embeddings_index.get(word)
	if embedding_vector is not None:
		embedding_matrix[i]=embedding_vector

df = pad_sequences(sequences, maxlen=30)
model = Sequential()
model.add(Embedding(vocabulary_size, 100,weights=[embedding_matrix], input_length=30,trainable=False))
model.add(Bidirectional(LSTM(100,return_sequences=True, dropout=0.2, recurrent_dropout=0.2)))
model.add(Bidirectional(LSTM(50, dropout=0.2, recurrent_dropout=0.2)))
model.add(Dense(1, activation='sigmoid'))
model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])
history=model.fit(df, np.array(data.label), validation_split=0.2, epochs=20)
model.summary()

X=['hi hike is donating rs 10 lacs towards kashmir flood relief go to menu gt rewards gt donate for kashmir and make it count kashmirflood','india offers help to pakistan on floods']
tokenizer.fit_on_texts(X)
sequence = tokenizer.texts_to_sequences(X)
#print sequences[0]
seq = pad_sequences(sequence, maxlen=30)
Y=model.predict_classes(seq)
print (Y)
print ("Training completed 100%")
#score=model.evaluate(xtest,ytest,batchsize)
pyplot.plot(history.history['acc'], label='train')
pyplot.plot(history.history['val_acc'], label='test')
pyplot.legend()
pyplot.show()
#plot_model(model, to_file='model_plot1.png', show_shapes=True, show_layer_names=True)


from rest_framework.permissions import (
    DjangoModelPermissions, BasePermission, IsAdminUser, SAFE_METHODS)

class IsProfileOwnerOrReadOnly(BasePermission):

    def has_object_permission(self, request, view, obj):
        print(obj)
        if request.method in SAFE_METHODS:
            return True

        return obj.user == request.user

class IsOwnerOrReadOnly(BasePermission):

    def has_object_permission(self, request, view, obj):
        print(obj)
        if request.method in SAFE_METHODS:
            return True

        return obj == request.user

class IsAuthorOrReadOnly(BasePermission):

    def has_object_permission(self, request, view, obj):
        if request.method in SAFE_METHODS:
            return True
        print(obj.author.user == request.user)
        return obj.author.user == request.user


#!/usr/bin/env python3
import json
import requests
import subprocess

session = requests.Session()
proc = subprocess.run(['git', 'for-each-ref', '--format=%(refname:lstrip=3)', 'refs/remotes/origin/??????????????????????????????????'],
    stdout=subprocess.PIPE,
    check=True,
)
to_delete = []
for branch in proc.stdout.decode().strip().split('\n'):
    product = json.loads(subprocess.run(['git', 'show', f'refs/remotes/origin/{branch}:product.json'],
        stdout=subprocess.PIPE,
        check=True,
    ).stdout)
    rsp = session.head(product['DistributionURL'], allow_redirects=False)
    if rsp.status_code == 200:
        continue
    if rsp.status_code != 404:
        print(f'[WARNING] {branch} {rsp.status_code} {rsp.reason}')
    to_delete.append('refs/heads/'+branch)
if to_delete:
    subprocess.run(['git', 'push', '--delete', 'origin'] + to_delete, check=True)


from django import forms
from .models import Image

from urllib import request
from django.core.files.base import ContentFile
from django.utils.text import slugify

class ImageCreateForm(forms.ModelForm):
    class Meta:
        model = Image
        fields = ('title','url','description')
        #我们的用户不会在表单中直接为图片添加 URL
        #他们将会使用一个 JavaScropt 工具来从其他网站中选择一张图片然后我们的
        #表单将会以参数的形式接收这张图片的 URL
        #我们覆写 url 字段的默认控件（widget）为一个 HiddenInput 控件，这个控件将
        #会被渲染为属性是 type="hidden" 的 HTML 元素
        #用这个控件是因为我们不想让用户看见这个字段
        widgets={
            'url':forms.HiddenInput,
        }
    #通过使用以 clean_<fieldname> 形式
    #命名的方法来实现。这个方法会在你为一个表单实例执行 is_valid() 时执行
    def clean_url(self):
        url = self.cleaned_data['url']
        valid_extensions = ['jpg','jpeg']
        extension = url.rsplit('.',1)[1].lower()
        if extension not in valid_extensions:
            raise forms.ValidationError('The given url does not match valid image extensions')
        return url
    #ModelForm 提供了一个 save() 方法来保存目前的模型实例到数据库中，并且返回一个对象
    #如果 commit 是 False ， save() 方法将会返回一个模型实例但是并不会把这个对象保存到数据库中
    def save(self, force_insert=False,force_update=False,commit=True):
        image = super(ImageCreateForm, self).save(commit=False)
        image_url = self.cleaned_data['url']
        image_name = '{}.{}'.format(slugify(image.title),image_url.rsplit('.', 1)[1].lower())
        # 从给定的 URL 中下载图片
        response = request.urlopen(image_url)
        #使用 Python 的 urllib 模块来下载图片，然后调用 save() 方法把图片传递给一个
        #ContentFiel 对象，这个对象被下载的文件所实例化
        image.image.save(image_name,ContentFile(response.read()),save=False)
        if commit:
            image.save()
        return image


# Author: Abdulaminkhon Khaydarov
# Date: 06/11/22
# Problem URL: https://leetcode.com/problems/running-sum-of-1d-array/

from typing import List

class Solution:
    def runningSum(self, nums: List[int]) -> List[int]:
        for i in range(1, len(nums)):
            nums[i] = nums[i] + nums[i - 1]
        return nums

if __name__ == '__main__':
    solution = Solution()

    # Example 1
    print(solution.runningSum([1, 2, 3, 4]) == [1, 3, 6, 10])

    # Example 2
    print(solution.runningSum([1, 1, 1, 1, 1]) == [1, 2, 3, 4, 5])

    # Example 3
    print(solution.runningSum([3, 1, 2, 10, 1]) == [3, 4, 6, 16, 17])


# -*-coding:utf-8 -*-
import numpy as np
from sklearn.ensemble import AdaBoostClassifier
from sklearn.tree import DecisionTreeClassifier

"""
Author:
	Jack Cui
Blog:
    http://blog.csdn.net/c406495762
Zhihu:
    https://www.zhihu.com/people/Jack--Cui/
Modify:
	2017-10-11
"""

def loadDataSet(fileName):
	numFeat = len((open(fileName).readline().split('\t')))
	dataMat = []; labelMat = []
	fr = open(fileName)
	for line in fr.readlines():
		lineArr = []
		curLine = line.strip().split('\t')
		for i in range(numFeat - 1):
			lineArr.append(float(curLine[i]))
		dataMat.append(lineArr)
		labelMat.append(float(curLine[-1]))

	return dataMat, labelMat

if __name__ == '__main__':
	dataArr, classLabels = loadDataSet('horseColicTraining2.txt')
	testArr, testLabelArr = loadDataSet('horseColicTest2.txt')
	bdt = AdaBoostClassifier(DecisionTreeClassifier(max_depth = 2), algorithm = "SAMME", n_estimators = 10)
	bdt.fit(dataArr, classLabels)
	predictions = bdt.predict(dataArr)
	errArr = np.mat(np.ones((len(dataArr), 1)))
	print('训练集的错误率:%.3f%%' % float(errArr[predictions != classLabels].sum() / len(dataArr) * 100))
	predictions = bdt.predict(testArr)
	errArr = np.mat(np.ones((len(testArr), 1)))
	print('测试集的错误率:%.3f%%' % float(errArr[predictions != testLabelArr].sum() / len(testArr) * 100))


import queue
from threading import Thread
import numpy as np
from transformers import *
from openie import StanfordOpenIE
from utility.utility import *
#from bert_serving.client import BertClient
from rouge import Rouge
from stanfordcorenlp import StanfordCoreNLP
import pickle
from data.raw_data_loader import *
import argparse
'''
nlp = StanfordCoreNLP('/home/ziqiang/stanfordnlp_resources/stanford-corenlp-full-2018-10-05')
bc = BertClient(ip='localhost')
client = StanfordOpenIE()
rougex = Rouge()
'''
g_b=0

import threading

class threadsafe_generator:
    def __init__(self, it):
        self.it = it
        self.lock = threading.Lock()

    def __iter__(self):
        return self

    def __next__(self):
        with self.lock:
            return self.it.__next__()

class Example(object):
  """Class representing a train/val/test example for text summarization."""

  def __init__(self, article, abstract, tokenizer, rougex, nlp):

    """
    Initializes the Example, performing tokenization and truncation to produce the encoder, decoder and target sequences, which are stored in self.
    Args:
      article: source text; list of strings. each token is separated by a single space.
      abstract_sentences: list of strings, one per abstract sentence. In each sentence, each token is separated by a single space.
      vocab: Vocabulary object
      hps: hyperparameters
    """
    self.rougex=rougex
    self.nlp=nlp
    self.tokenizer=tokenizer
    article=article[:60]
    self.article=article
    self.abstract=abstract
    # Process the article
    self.article_fact=[]
    self.article_sent=[]
    self.article_fact_tag=[]
    for count,sent in enumerate(article):

        self.article_sent.append(self.tokenizer.encode(sent))
        sent=sent.strip(',')
        sent=sent.strip(':')

        sentfact=sent_split(sent,self.nlp)

        sentfact_file=[]
        for i in sentfact:
            if word_len(i) >50:
                ii=i.split(' ')
                ii=ii[0:50]
                sentfact_file.append(' '.join(ii))
                continue
            if len(i) >= 20:
                sentfact_file.append(i)

        self.article_fact_tag.append(len(sentfact_file))
        self.article_fact+=sentfact_file
    self.article_id=[]
    for fact in self.article_fact:
        self.article_id.append(self.tokenizer.encode(fact,add_special_tokens=False))
    self.article_len = len(self.article_id) # store the number of sentences of the article

    # Process the abstract
    self.original_abstract=[]
    self.abstract_fact=[]
    self.abstract_fact_all=[]
    for sent in abstract:

        self.original_abstract.append(self.tokenizer.encode(sent))

        if word_len(sent) > 20:
            sent=sent.strip(',')
            sent=sent.strip(':')
            sentfact=sent_split(sent,self.nlp)
        else:
            sentfact=[sent]

        self.abstract_fact_all+=sentfact

    for i in self.abstract_fact_all:
        if word_len(i) >50:
            ii=i.split(' ')
            ii=ii[0:50]
            self.abstract_fact.append(' '.join(ii))
        elif len(i) < 15:
            continue
        else:
            self.abstract_fact.append(i)
    self.abstract_id=[]
    for fact in self.abstract_fact:
        self.abstract_id.append(self.tokenizer.encode(fact,add_special_tokens=False))

    self.abstract_len = len(self.abstract_id) # store the number of sentences of the article

    self.enc_fact=[]
    self.enc_sent=[]
    self.dec_fact=[]

    self.dec_label_bert=[]
    self.dec_label_rouge=[]
    self.dec_label_sent=[]

    self.grap_sim_bert=np.zeros((self.article_len, self.article_len), dtype=np.float16)
    self.grap_sim_rouge=np.zeros((self.article_len, self.article_len), dtype=np.float16)
    self.grap_entity=np.zeros((self.article_len, self.article_len), dtype=np.float16)
    self.grap_cosent=np.zeros((self.article_len, self.article_len), dtype=np.float16)
    self.grap_sent=np.zeros((len(self.article), len(self.article)), dtype=np.float16)
  def get_enc_fact(self, max_len):

    """Pad the encoder input sequence with pad_id up to max_len."""

    for i in self.article_id:
        if len(i) > max_len:
            self.enc_fact.append(i[0:max_len])
        else:
            self.enc_fact.append(i)

    for i in self.article_sent:
        if len(i) > max_len*2:
            self.enc_sent.append(i[0:max_len*2])
        else:
            self.enc_sent.append(i)

  def get_dec_fact(self, max_len):

    """Pad the encoder input sequence with pad_id up to max_len."""

    for i in self.abstract_id:
        if len(i) > max_len:
            self.dec_fact.append(i[0:max_len])
        else:
            self.dec_fact.append(i)

  def get_grap(self):

      """Get the sim bert graph """

      """Get the sim rouge graph """
      for i,facti in enumerate(self.article_fact):
          for j,factj in enumerate(self.article_fact):
              scores = self.rougex.get_scores(facti, factj)
              self.grap_sim_rouge[i][j]=(scores[0]['rouge-1']['f']+scores[0]['rouge-2']['f'])/2

      """Get the sim sent graph """
      for i,facti in enumerate(self.article):
          for j,factj in enumerate(self.article):

              scores = self.rougex.get_scores(facti, factj)
              self.grap_sent[i][j]=(scores[0]['rouge-1']['f']+scores[0]['rouge-2']['f'])/2

      """Get the entity graph"""

      """Get the co-sent graph"""
      now=0
      for i in self.article_fact_tag:
          for x in range(now+i)[now:now+i]:
              for y in range(now+i)[now:now+i]:
                  self.grap_cosent[x][y]=1
          now=now+i

  def get_dec_label_bert(self):
      self.dec_label_bert=[]
      self.oral_score_bert=0

  def get_dec_label_rouge(self):
      rouge=[]
      score_rouge=[]
      index_rouge=[]
      for j in self.abstract_fact:
          score=[]
          for k in self.article_fact:
              scores = self.rougex.get_scores(j, k)
              score.append((scores[0]['rouge-1']['f']+scores[0]['rouge-2']['f'])/2)
          choose=score.index(max(score))
          index_rouge.append(choose)
          rouge.append(self.article_fact[choose])
          score_rouge.append(max(score))
      for i in range(len(self.article_fact)):
          if i in index_rouge:
              self.dec_label_rouge.append(1)
          else:
              self.dec_label_rouge.append(0)

      self.oral_score_rouge = self.rougex.get_scores(' . '.join(rouge), ' . '.join(self.abstract))

  def get_dec_label_rouge_sent(self):
    get_dec_label_sent=self.greedy_selection(self.article, self.abstract, 3, self.rougex)
    for i in range(len(self.article)):
      if i in get_dec_label_sent:
          self.dec_label_sent.append(1)
      else:
          self.dec_label_sent.append(0)

  def greedy_selection(self, doc_sent_list, abstract_sent_list, summary_size, rougex):
    selected = []
    max_rouge = 0.0
    reference=''
    for i in abstract_sent_list:
        reference+=i
        reference+=' . '
    for s in range(summary_size):
        cur_max_rouge = max_rouge
        cur_id = -1
        for i in range(len(doc_sent_list)):
            if (i in selected):
                continue
            c = selected + [i]
            candidates = ''
            for j in c:
                candidates+=doc_sent_list[j]
                candidates+=' . '
            scores = rougex.get_scores(candidates, reference)
            rouge_score = (scores[0]['rouge-1']['f']+scores[0]['rouge-2']['f'])/2
            if rouge_score > cur_max_rouge:
                cur_max_rouge = rouge_score
                cur_id = i
        if (cur_id == -1):
            return selected
        selected.append(cur_id)
        max_rouge = cur_max_rouge
    return sorted(selected)

class Batch(object):

  """Class representing a minibatch of train/val/test examples for text summarization."""

  def __init__(self, example_list, max_len):

    """
    Turns the example_list into a Batch object.
    Args:
       example_list: List of Example objects
       hps: hyperparameters
       vocab: Vocabulary object
    """

    self.init_encoder(example_list, max_len) # initialize the input to the encoder
    self.init_decoder(example_list, max_len) # initialize the input and targets for the decoder
    self.init_result(example_list)

  def init_result(self, example_list):
    self.original_article=[]
    self.original_abstract=[]
    self.original_sent=[]
    self.sent_to_fact=[]
    for ex in example_list:
        self.original_sent.append(ex.article)
        self.original_article.append(ex.article_fact)
        self.original_abstract.append(ex.abstract)
        self.sent_to_fact.append(ex.article_fact_tag)

  def init_encoder(self, example_list, max_len):
    self.enc_fact=[]
    self.enc_sent=[]
    self.grap_sim_bert=[]
    self.grap_sim_rouge=[]
    self.grap_entity=[]
    self.grap_cosent=[]
    self.grap_sent=[]

    for ex in example_list:
      ex.get_enc_fact(max_len)
      ex.get_grap()

    # Fill in the numpy arrays
    for ex in example_list:
      self.enc_fact.append(ex.enc_fact)
      self.enc_sent.append(ex.enc_sent)
      self.grap_sim_bert.append(ex.grap_sim_bert)
      self.grap_sim_rouge.append(ex.grap_sim_rouge)
      self.grap_entity.append(ex.grap_entity)
      self.grap_cosent.append(ex.grap_cosent)
      self.grap_sent.append(ex.grap_sent)

  def init_decoder(self, example_list, max_len):
    self.dec_fact=[]
    self.dec_label_sent=[]
    self.dec_label_bert=[]
    self.dec_label_rouge=[]
    self.dec_score_bert=[]
    self.dec_score_rouge=[]
    # Pad the inputs and targets
    for ex in example_list:
        ex.get_dec_fact(max_len)
        ex.get_dec_label_bert()
        ex.get_dec_label_rouge()
        ex.get_dec_label_rouge_sent()
    # Fill in the numpy arrays
    for ex in example_list:
      self.dec_fact.append(ex.dec_fact)
      self.dec_label_sent.append(ex.dec_label_sent)
      self.dec_label_bert.append(ex.dec_label_bert)
      self.dec_label_rouge.append(ex.dec_label_rouge)
      self.dec_score_bert.append(ex.oral_score_bert)
      self.dec_score_rouge.append(ex.oral_score_rouge)

class Batcher(object):

  """A class to generate minibatches of data. Buckets examples together based on length of the encoder sequence."""

  BATCH_QUEUE_MAX = 100 # max number of batches the batch_queue can hold

  def __init__(self, data_path, nlp_path):

    """Initialize the batcher. Start threads that process the data into batches.
    Args:
      data_path: tf.Example filepattern.
      vocab: Vocabulary object
      hps: hyperparameters
      single_pass: If True, run through the dataset exactly once (useful for when you want to run evaluation on the dev or test set). Otherwise generate random batches indefinitely (useful for training).
    """
    self._data_path = data_path
    self._max_len=50
    self._batch_size=4

    # Initialize a queue of Batches waiting to be used, and a queue of Examples waiting to be batched
    self._batch_queue = queue.Queue(self.BATCH_QUEUE_MAX)
    self._example_queue = queue.Queue(self.BATCH_QUEUE_MAX * self._batch_size)
    # Initialize the tool
    self.tokenizer=BertTokenizer.from_pretrained('bert-base-uncased')
    self.rougex=Rouge()
    self.nlp=StanfordCoreNLP(nlp_path)
    # Different settings depending on whether we're in single_pass mode or not
    self._num_example_q_threads = 1 # just one thread, so we read through the dataset just once
    self._num_batch_q_threads = 1  # just one thread to batch examples
    self._bucketing_cache_size = 50 # only load one batch's worth of examples before bucketing; this essentially means no bucketing
    self._finished_reading = False # this will tell us when we're finished reading the dataset
    #prepear dataloader

    self.input_gen = threadsafe_generator(example_generator_DMCNN(self._data_path))

    print('finish prepearing')
    # Start the threads that load the queues

    self._example_q_threads = []
    for _ in range(self._num_example_q_threads):
      self._example_q_threads.append(Thread(target=self.fill_example_queue))
      self._example_q_threads[-1].daemon = True
      self._example_q_threads[-1].start()

    self._batch_q_threads = []
    for _ in range(self._num_batch_q_threads):
      self._batch_q_threads.append(Thread(target=self.fill_batch_queue))
#      self._batch_q_threads[-1].daemon = True
      self._batch_q_threads[-1].start()

    print('threads started')

  def next_batch(self):

    """
    Return a Batch from the batch queue.
    batch: a Batch object, or None if we're in single_pass mode and we've exhausted the dataset.
    """
    # If the batch queue is empty, print a warning
    if self._batch_queue.qsize() == 0:
#      tf.logging.warning('Bucket input queue is empty when calling next_batch. Bucket queue size: %i, Input queue size: %i', self._batch_queue.qsize(), self._example_queue.qsize())
      pass
      if self._finished_reading and self._example_queue.qsize() == 0:
        print("Finished reading dataset in single_pass mode.")
        return None
    batch = self._batch_queue.get() # get the next Batch
    return batch

  def fill_example_queue(self):

    """Reads data from file and processes into Examples which are then placed into the example queue."""
    global g_b
    while True:
      g_b+=1
      if g_b%100==0:
          print('--------'+str(g_b)+'--------')
          print(self._example_queue.qsize())
          print(self._batch_queue.qsize())
      try:
        article, abstract = self.input_gen.__next__() # read the next example from file. article and abstract are both strings.
      except StopIteration: # if there are no more examples:
        print("The example generator for this example queue filling thread has exhausted data.")
        self._finished_reading = True
        break
      example = Example(article, abstract, self.tokenizer, self.rougex, self.nlp) # Process into an Example.
      self._example_queue.put(example) # place the Example in the example queue.

  def fill_batch_queue(self):

    """
    Takes Examples out of example queue, sorts them by encoder sequence length, processes into Batches and places them in the batch queue.
    In decode mode, makes batches that each contain a single example repeated.
    """
    while True:
    # Get bucketing_cache_size-many batches of Examples into a list, then sort
      inputs = []
      for _ in range(self._batch_size * self._bucketing_cache_size):
          if  self._finished_reading and self._example_queue.qsize() == 0:
              break
          inputs.append(self._example_queue.get())
      # Group the sorted Examples into batches, optionally shuffle the batches, and place in the batch queue.
      inputs.sort(key=self.get_sort)
      '''
      splits = []
      len_pre=-1
      for indexi,i in enumerate(inputs):
          len_now = i.article_len
          if len_pre != len_now:
              splits.append(indexi)
          len_pre=len_now
      batches=[]
      for indexi,i in enumerate(splits):
          if indexi+1 == len(splits):
              batches.append(inputs[i:])
          else:
              batches.append(inputs[i:splits[indexi+1]])
      batches_max=[]
      for i in batches:
          if len(i) <= self._batch_size:
              batches_max.append(i)
          else:
              batches_max+=[i[j:j+self._batch_size] for j in range(0, len(i), self._batch_size)]
      '''
      batches_max=[]
      for indexi,i in enumerate(inputs):
          if indexi % self._batch_size ==0:
              batches_max.append(inputs[indexi:indexi+self._batch_size])
      for b in batches_max:  # each b is a list of Example objects
        self._batch_queue.put(Batch(b, self._max_len))

  def get_sort(self, x):
      return x.article_len

'''
train_data_loader=Batcher('data/DMCNN/train_*', 'DMCNN')

count=0
countx=0
while True:
    batch = train_data_loader.next_batch()
    each_batch_size=len(batch.enc_fact)
    if train_data_loader._finished_reading == True:
        break
    f=open('data_file/DMCNN/train_file/'+str(count)+'_train_batch_of '+str(each_batch_size)+' examples.pkl','wb')
    pickle.dump(batch,f)
    f.close()
    count+=1
    countx+=each_batch_size
print('Total train data:')
print(countx)

train_data_loader=Batcher('data/DMCNN/val_*', 'DMCNN')

count=0
countx=0
while True:
    batch = train_data_loader.next_batch()
    each_batch_size=len(batch.enc_fact)
    if train_data_loader._finished_reading == True:
        break
    f=open('data_file/DMCNN/val_file/'+str(count)+'_val_batch_of '+str(each_batch_size)+' examples.pkl','wb')
    pickle.dump(batch,f)
    f.close()
    count+=1
    countx+=each_batch_size
print('Total val data:')
print(countx)
'''

def argLoader():

    parser = argparse.ArgumentParser()

    #device

    parser.add_argument('--nlp_path', type=str, default='/home/ziqiang/stanfordnlp_resources/stanford-corenlp-full-2018-10-05')

    # Data Setting

    parser.add_argument('--data_path', type=str, default='data/DMCNN/train*')

    parser.add_argument('--output_path', type=str, default='data_file/DMCNN/train_file/')

    args = parser.parse_args()

    return args

args = argLoader()

train_data_loader=Batcher(args.data_path, args.nlp_path)

count=0
countx=0
while True:
    batch = train_data_loader.next_batch()
    each_batch_size=len(batch.enc_fact)
    if train_data_loader._finished_reading == True and train_data_loader._batch_queue.qsize() == 0 and train_data_loader._example_queue.qsize() == 0:
        break
    f=open(args.output_path+str(count)+'_batch_of '+str(each_batch_size)+' examples.pkl','wb')
    pickle.dump(batch,f)
    f.close()
    count+=1
    countx+=each_batch_size

print('finish all')


"""Возьмите любую из задач с прошлых семинаров (например сериализация данных),
которые вы уже решали. Превратите функции в методы класса, а параметры в свойства.
Задачи должны решаться через вызов методов экземпляра."""
import csv
import json

class SaveToCsv:
    def __init__(self, input_file_name, output_file_name):
        self.input_file_name = input_file_name
        self.output_file_name = output_file_name

    def save_to_csv(self):
        with open(self.input_file_name, "r") as input_file:
            data = [["level", "id", "name"]]
            for level, value in json.load(input_file).items():
                for id_, name in value.items():
                    data.append([level, id_, name])

        with open(self.output_file_name, "w", newline="") as file:
            csv_writer = csv.writer(file)
            for each in data:
                csv_writer.writerow(each)

if __name__ == '__main__':
    save_to_csv = SaveToCsv("D:\\dev\\study\\Immersion _in_Python\\sem_8\\task_8_2.json",
                "hw_10_2.csv")
    save_to_csv.save_to_csv()


from django.http import HttpResponseRedirect, HttpResponse
from django.core.mail import send_mail
from django.shortcuts import render
from contacto.forms import FormularioContactos

from django.template import loader
# Create your views here.

def contactos(request):
    #form=FormularioContactos()
    if request.method == 'POST':
        form=FormularioContactos(request.POST)
        if form.is_valid():
            cd = form.cleaned_data
            send_mail(
                cd['asunto'],
                cd['mensaje'],
                cd.get('email', 'noreply@example.com'),['siteowner@example.com'],
            )
            return HttpResponseRedirect('/contactos/gracias/')
    else:
        form = FormularioContactos(initial={'asunto':'adoro!'})
    template = loader.get_template('contactos/formulario_contactos.html')
    #return render(request, 'contactos/formulario_contactos.html', {'form': form})
    return HttpResponse(template.render({'form': form}, request))


# -*- coding: utf-8 -*-
# file: __init__.py
# date: 2021-07-20

import os
import _io
import json
import logging
import time
import datetime
import pyspark
import pyspark.sql
from typing import Any, Union, Dict, List, Tuple

from ... import pysparkit

LOGGER: logging.Logger = pysparkit.get_logger(__name__, level=logging.INFO)

def json_file2dict(json_path: str) -> Dict:
    """ Loads a json file as python `Dict` instance. """
    output: Dict
    json_file: _io.TextIOWrapper = open(json_path)
    output = json.load(json_file)
    json_file.close()
    return output

def get_fs_proto(path: str) -> str:
    """Get file-system's type/proto from path string.

    Args:
        path: The path(directory or file path) waiting to judge.

    Returns:
       The file-system proto type, "file" represents local file-
       system.
    """
    decompose: Tuple = path.split(":")
    if len(decompose) < 2 or decompose[0] == "file":
        return "file"
    else:
        return decompose[0]

def if_fs_client_ok(fs_client: str) -> bool:
    """If file-system executable file ok for using with command line.

    Args:
        fs_client: Ref to `py_dict_rdd2disk`.
    """
    client_path: str = os.popen("which %s" % fs_client).read().strip("\n")
    return len(client_path) > 2

def hadoop_reset_directory(
        directory: str, backup_postfix: str="_bak") -> None:
    """Resets an (existing) directory which using hadoop as client.

    Mainly includes following process:
        1. Remove historical backup directory.
        2. Backup `directory` if it already exist.
        3. Remove `directory`, but it should actually not exists after
           backup process.
        4. Build `directory`'s parent directory in case it not actually
           exists.

    Args:
        directory: The directory waiting to reset with hadoop client.
        backup_postfix: Ref to `py_dict_rdd2disk`.
    """
    backup_dir: str = directory + backup_postfix

    clean_bak_cmd: str = "hadoop fs -rm -r %s" % backup_dir
    backup_cmd: str = "hadoop fs -mv %s %s" % (directory, backup_dir)
    clean_cmd: str = "hadoop fs -rm -r %s" % directory
    build_cmd: str = "hadoop fs -mkdir -p %s" % os.path.dirname(directory)

    LOGGER.info(os.popen(clean_bak_cmd).read())
    LOGGER.info(os.popen(backup_cmd).read())
    LOGGER.info(os.popen(clean_cmd).read())
    LOGGER.info(os.popen(build_cmd).read())

def before_data2disk(target_directory: str,
        fs_client: str="default", backup_postfix: str="_bak") -> None:
    """Preprocessing before `RDD` data persistence.

    Mainly include get the file-system type/proto, do some directory
    backup/building job.

    Args:
        target_directory: Ref to `py_dict_rdd2disk`.
        fs_client: Ref to `py_dict_rdd2disk`.
        backup_postfix: Ref to `py_dict_rdd2disk`.
    """
    if get_fs_proto(target_directory) != "file" and fs_client == "default":
        fs_client = "hadoop"

    if not if_fs_client_ok(fs_client):
        raise Exception("Your %s client is not OK, check it." % fs_client)

    if fs_client == "hadoop":
        hadoop_reset_directory(target_directory, backup_postfix)
    else:
        # TODO@202107211350
        raise Exception("For now only support hadoop fs client.")

def py_dict_rdd2disk(py_dict_rdd: pyspark.RDD,
        target_directory: str, fs_client: str="default",
        backup_postfix: str="_bak") -> None:
    """python `Dict` rdd persistence function.

    Persistence a python `Dict` spark rdd to file-system, which could
    be local file-system or hdfs style distributed fs.

    Args:
        py_dict_rdd:
            Spark `RDD` waiting to persistence, each record should be
            a python `Dict` instance.
        target_directory:
            The directory path to which we hope persistence `py_dict_rdd`.
        fs_client:
            The file-system interaction client, not necessary for local-
            file-system, but necessary for remote or distributed file-
            system, for example, hadoop for hdfs. And `fs_client` is
            the name of certain file-system executable file name.
        backup_postfix:
            If the `target_directory` already exists, we will backup it
            first under the same parent directory, with appending
            `backup_postfix` as the postfix of backup directory.
    """
    before_data2disk(target_directory, fs_client, backup_postfix)

    json_rdd: pyspark.RDD = py_dict_rdd\
            .map(lambda x: json.dumps(x, separators=(',', ':')))\
            .saveAsTextFile(target_directory)

def hadoop_if_path_exists(path: str) -> bool:
    if not if_fs_client_ok("hadoop"):
        raise Exception("hadoop client is not OK")

    hadoop_cmd: str = "hadoop fs -ls %s" % path
    cmd_result: str = os.popen(hadoop_cmd).read()

    if "No such file or directory" in cmd_result:
        return False
    return True

def hadoop_waiting_util_path_ready(
        path: str, waiting_seconds: int=1,
        logging_period: int=30
) -> None:
    start_time: datetime.datetime = datetime.datetime.now()
    while True:
        if hadoop_if_path_exists(path):
            LOGGER.info("path '%s' has been ready." % path)
            break
        else:
            now: datetime.datetime = datetime.datetime.now()
            waiting_seconds_: datetime.timedelta = (now - start_time).seconds
            if waiting_seconds_ > waiting_seconds:
                LOGGER.info("Out of waiting time for path '%s'..." % path)
                break
            else:
                if waiting_seconds_ % logging_period == 0:
                    LOGGER.info("Waiting for path '%s' ready..." % path)

def json_line_files2py_dict_rdd(
        sc: pyspark.sql.SparkSession, path: str
) -> pyspark.RDD:
    return sc.sparkContext.textFile(path)\
            .map(lambda x: json.loads(x))


import collections
def calcEquation(equations, values, queries):
    """
    :type equations: List[List[str]]
    :type values: List[float]
    :type queries: List[List[str]]
    :rtype: List[float]
    """
    record = collections.defaultdict(lambda: collections.defaultdict(int))
    for (var1, var2), v in zip(equations, values):
        record[var1][var2] = v
        record[var2][var1] = 1.0 / v

    for i in record:
        record[i][i] = 1
        for j in record:
            for k in record:
                if record[j][i] and record[i][k]:
                    record[j][k] = record[j][i] * record[i][k]
                else:
                    record[j][k] = -1
    res = []
    for q in queries:
        res.append(record[q[0]][q[1]])

    return res

print(calcEquation([["a","b"],["e","f"],["b","e"]], [3.4,1.4,2.3], [["b","a"],["a","f"],["f","f"],["e","e"],["c","c"],["a","c"],["f","e"]]))
print(calcEquation([["a","b"],["b","c"],["bc","cd"]], [1.5,2.5,5.0], [["a","c"],["c","b"],["bc","cd"],["cd","bc"]]))


from io import StringIO

from django.core.management import call_command
from django.core.management.base import CommandError
from django.test import TestCase

from geostore.models import Layer
from geostore.tests.factories import LayerFactory
from geostore.tests.utils import get_files_tests

class ImportGeojsonTest(TestCase):
    def test_default_group(self):
        output = StringIO()
        call_command(
            'import_geojson',
            get_files_tests('empty.json'),
            '--verbosity=1',
            stdout=output
        )

        # Retrieve the layer
        layer = Layer.objects.first()
        self.assertIn(f'The created layer pk is {layer.pk}', output.getvalue())
        self.assertEqual(layer.layer_groups.count(), 1)
        self.assertEqual(layer.layer_groups.first().name, 'default')

    def test_default_group_nogroup_rollback(self):
        output = StringIO()
        call_command(
            'import_geojson',
            get_files_tests('empty.json'),
            '--dry-run',
            '--verbosity=1', stdout=output)
        self.assertIn("The created layer pk is", output.getvalue())
        # Retrieve the layer
        self.assertEqual(Layer.objects.count(), 0)

    def test_schema_generated(self):
        call_command(
            'import_geojson',
            get_files_tests('bati.geojson'),
            '--generate-schema',
            verbosity=0)

        # Retrieve the layer
        layer = Layer.objects.get()

        # Assert schema properties are presents
        self.assertNotEqual(
            layer.schema.get('properties').keys() -
            ['ALTITUDE', 'ETIQUETTE', 'HAUTEUR', 'ID', 'ID_PG', 'NATURE', 'NOM',
             'ORIGIN_BAT', 'PUB_XDECAL', 'PUB_YDECAL', 'ROTATION', 'ROTATION_S',
             'XDECAL', 'XDECAL_SYM', 'YDECAL', 'YDECAL_SYM', 'Z_MAX', 'Z_MIN', ], True)

    def test_import_geojson_layer_with_bad_settings(self):
        bad_json = get_files_tests('bad.json')
        with self.assertRaises(CommandError) as error:
            call_command(
                'import_geojson',
                get_files_tests('empty.json'),
                f'--layer-settings={bad_json}',
                verbosity=0)
        self.assertEqual("Please provide a valid layer settings file", str(error.exception))

    def test_import_geojson_layer_with_pk_layer(self):
        layer = LayerFactory()
        self.assertEqual(len(layer.features.all()), 0)
        call_command(
            'import_geojson',
            get_files_tests('toulouse.geojson'),
            layer_pk=layer.pk,
            verbosity=0
        )
        self.assertEqual(len(layer.features.all()), 838)

    def test_import_geojson_layer_with_wrong_pk_layer(self):
        geojson_sample = get_files_tests('toulouse.geojson')
        with self.assertRaises(CommandError) as error:
            call_command(
                'import_geojson',
                geojson_sample,
                '--layer-pk=999',
                '--generate-schema',
                '--verbosity=0'
            )
        self.assertIn("Layer with pk 999 doesn't exist", str(error.exception))


"""
318. Maximum Product of Word Lengths
Medium

514

47

Favorite

Share
Given a string array words, find the maximum value of length(word[i]) * length(word[j]) where the two words do not share common letters. You may assume that each word will contain only lower case letters. If no such two words exist, return 0.

Example 1:

Input: ["abcw","baz","foo","bar","xtfn","abcdef"]
Output: 16
Explanation: The two words can be "abcw", "xtfn".
Example 2:

Input: ["a","ab","abc","d","cd","bcd","abcd"]
Output: 4
Explanation: The two words can be "ab", "cd".
Example 3:

Input: ["a","aa","aaa","aaaa"]
Output: 0
Explanation: No such pair of words.
"""
"""
Runtime: 1924 ms, faster than 7.93% of Python3 online submissions for Maximum Product of Word Lengths.
Memory Usage: 14 MB, less than 28.14% of Python3 online submissions for Maximum Product of Word Lengths.
"""
from collections import defaultdict
class Solution:
    def maxProduct(self, words: List[str]) -> int:
        stats=defaultdict(set)
        for i,word in enumerate(words):
            for a in word:
                    stats[a].add(i)
        res=0
        for i in range(len(words)-1):
            for j in range(i+1,len(words)):
                word0,word1=words[i],words[j]
                valid=True
                for a in word0:
                    if i in stats[a] and j in stats[a]:
                        valid=False
                        break
                if valid is True:
                    res=max(res,len(word0)*len(word1))
        return res

# 位运算存储状态
"""
Runtime: 396 ms, faster than 66.52% of Python3 online submissions for Maximum Product of Word Lengths.
Memory Usage: 13.4 MB, less than 62.39% of Python3 online submissions for Maximum Product of Word Lengths
"""

class Solution:
    def maxProduct(self, words: List[str]) -> int:
        stats = []
        for word in words:
            tmp = 0
            for a in word:
                tmp = tmp | (1 << ord(a) - ord('a'))
            stats.append(tmp)
        res = 0
        for i in range(len(words)):
            for j in range(i + 1, len(words)):
                if stats[i] & stats[j] == 0:
                    res = max(res, len(words[i]) * len(words[j]))
        return res


#Dependencies
from relu import relu
from convolutional_mlp import LeNetConvPoolLayer
from logistic_sgd import LogisticRegression
from mlp import HiddenLayer
from dropout import dropout_neurons_from_layer
from theano.tensor.signal import downsample
from theano.tensor.nnet import conv
import theano

class RetinopathyNet(object):

    def __init__(self,
                 rng,
                 x,
                 y,
                 use_dropout,
                 dropout_rates,
                 train_batch_size,
                 nkerns,
                 parameters=[]):

        #Setup layer0
        layer0_input = dropout_neurons_from_layer(rng, x, dropout_rates[0], use_dropout)
        layer0_input = layer0_input.reshape((train_batch_size, 1, 512, 512))
        layer0 = LeNetConvPoolLayer(
            rng,
            input=layer0_input,
            image_shape=(train_batch_size, 1, 512, 512),
            filter_shape=(nkerns[0], 1, 5, 5),
            poolsize=(2, 2)
        )
        layer0.output = dropout_neurons_from_layer(rng, layer0.output, dropout_rates[1], use_dropout)

        #Setup layer 1
        layer1 = LeNetConvPoolLayer(
            rng,
            input=layer0.output,
            image_shape=(train_batch_size, nkerns[0], 254, 254),
            filter_shape=(nkerns[1], nkerns[0], 5, 5),
            poolsize=(2, 2)
        )
        layer1.output = dropout_neurons_from_layer(rng, layer1.output, dropout_rates[2], use_dropout)

        #Setup layer 2
        layer2_input = layer1.output.flatten(2)
        layer2 = HiddenLayer(
            rng,
            input=layer2_input,
            n_in=nkerns[1] * 125 * 125,
            n_out=500,
            activation=relu
        )
        layer2.output = dropout_neurons_from_layer(rng, layer2.output, dropout_rates[3], use_dropout)

        #Setup layer 3
        layer3 = LogisticRegression(input=layer2.output, n_in=500, n_out=5)

        #Load parameters if they are passed in
        if len(parameters) > 0:
            layer0.params[0].set_value(parameters[0])
            layer0.params[1].set_value(parameters[1])
            layer1.params[0].set_value(parameters[2])
            layer1.params[1].set_value(parameters[3])
            layer2.params[0].set_value(parameters[4])
            layer2.params[1].set_value(parameters[5])
            layer3.params[0].set_value(parameters[6])
            layer3.params[1].set_value(parameters[7])

        #Relevant functions and attributes for this class
        self.layer3 = layer3
        self.cost = layer3.negative_log_likelihood(y)
        self.errors = layer3.errors(y)
        self.params = layer0.params + layer1.params + layer2.params + layer3.params
        self.classify_function = theano.function([x, use_dropout], self.layer3.y_pred)

    #Pass in a data matrix to get the models predicted labels for it
    def classify_images(self, x):
        results = self.classify_function(x, 0.0)
        return results


from common.FrontendTexts import FrontendTexts

view_texts = FrontendTexts('materials')
labels = view_texts.getComponent()['selector']['choices']

ACTION_CHOICES = (
    (1, labels['edit']),
    (2, labels['weight'])
)

UNIT_CHOICES = (
    (1, "M"),
    (2, "M2"),
    (3, "M3"),
    (4, "EA")
)


from typing import List

DISTANCE_END = 5

def determine_place(n: int, distance_list: List[int]) -> int:
    """
    Функция которая определяет, максимально высокое место участника.

    :param n: длинна входного списка с расстояниями бросков участников
    :type n: int
    :param distance_list: список с расстояниями бросков участников
    :type distance_list: List[int]

    :return: максимально высокое место участника, или 0,
    если не существует ни одного участника, который удовлетворяет условиям
    :rtype: int
    """
    required_distance = 0
    max_distance = max(distance_list)
    winner_flag = False

    for player_number in range(1, n - 1):
        player_distance = distance_list[player_number]
        if distance_list[player_number - 1] == max_distance:
            winner_flag = True
        if player_distance % 10 == DISTANCE_END and winner_flag and player_distance > distance_list[player_number + 1]:
            required_distance = max(player_distance, required_distance)

    if not required_distance:
        return 0

    required_player_place = 1
    for player_distance in distance_list:
        if player_distance > required_distance:
            required_player_place += 1
    return required_player_place

def main():
    """Основная функция для чтения входных данных и вывода результата."""
    n = int(input())
    distance_list = list(map(int, input().split()))
    print(determine_place(n, distance_list))

if __name__ == '__main__':
    main()