# This file is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This file is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# See the GNU General Public License, <https://www.gnu.org/licenses/>.
#

# QueryParam (should be called form:->)
# Given a list of parameters (params) and current values (selected)
# and descriptions. Creates a form to turn on param options and
# add more to a param list and edit param values.
try:
    import wx
    import wx.lib.scrolledpanel
except Exception:
    print("Failed to import wx, install instructions:")
    print("sudo apt-get install -y libsdl2-2.0-0")
    print("sudo apt-get install libgtk-3-dev")
    print("pip3 install -U -f https://extras.wxpython.org/wxPython4/extras/linux/gtk3/ubuntu-18.04 wxPython")
    exit(1)

class NamedButton(wx.Button):
    def __init__(self, parent, title: str, name:str):
        wx.Button.__init__(self, parent, label=title)
        self.name = name

class NamedComboBox(wx.ComboBox):
    def __init__(self, parent, choices: list, name: str):
        wx.Button.__init__(self, parent, choices=choices)
        self.name = name

class QueryParams(wx.Frame):
#class QueryParams(wx.Dialog):
    def __init__(self, parent, title: str, style: int, params: dict, selected: dict, verify: any, sample: any, descriptions: dict, getOptions: any, on_close: any = None, data: any = None):
        wx.Frame.__init__(self, parent=parent, title=title, style=wx.RESIZE_BORDER | wx.CLOSE_BOX)
        if on_close is not None:
            self.Bind(wx.EVT_CLOSE, on_close)
        self.title = title
        self.data = data
        self.verify = verify
        self.sample = sample
        self.getOptions = getOptions
        self.params = {}
        self.titles = {}
        self.desc = {}
        self.res = wx.OK
        self.panel = wx.Panel(self)
        self.vbox = wx.BoxSizer(wx.VERTICAL)
        hbox = wx.BoxSizer(wx.HORIZONTAL)
        if style & wx.NO:
            self.noButton = wx.Button(self.panel, label="NO")
            self.noButton.Bind(wx.EVT_BUTTON, self.on_no)
            hbox.Add(self.noButton,proportion=1, flag=wx.EXPAND)
        if style & wx.CANCEL:
            self.deleteButton = wx.Button(self.panel, label="DELETE")
            self.deleteButton.Bind(wx.EVT_BUTTON, self.on_delete)
            hbox.Add(self.deleteButton, proportion=1, flag=wx.EXPAND)
        if style & wx.OK:
            self.okButton = wx.Button(self.panel, label="OK")
            self.okButton.Bind(wx.EVT_BUTTON, self.on_ok)
            hbox.Add(self.okButton, proportion=1, flag=wx.EXPAND)
        if style & wx.YES:
            self.yesButton = wx.Button(self.panel, label="YES")
            self.yesButton.Bind(wx.EVT_BUTTON, self.on_yes)
            hbox.Add(self.yesButton, proportion=1, flag=wx.EXPAND)
        if style & wx.CAPTION:
            self.verifyButton = wx.Button(self.panel, label="VERIFY")
            self.verifyButton.Bind(wx.EVT_BUTTON, self.on_verify)
            hbox.Add(self.verifyButton, proportion=1, flag=wx.EXPAND)
        self.vbox.Add(hbox, proportion=0, flag=wx.EXPAND)
        self.spanel = wx.lib.scrolledpanel.ScrolledPanel(self.panel)
        self.spanel.SetupScrolling()
        self.svbox = wx.BoxSizer(wx.VERTICAL)
        self.spanel.SetSizer(self.svbox)
        self.vbox.Add(self.spanel, proportion=1, flag=wx.EXPAND)
        self.descriptions = {}
        self.updateParams("", params, selected, descriptions)
        self.spanel.Layout()
        self.panel.SetSizer(self.vbox)
        self.panel.Layout()
        self.showFields()

    def updateParams(self, after: str, params: dict, selected: dict, descriptions: dict) -> None:
        for name in descriptions:
            if name not in self.descriptions:
                self.descriptions[name] = descriptions[name]
        pos = 0
        for i, n in enumerate(self.params.keys()):
            if n.startswith(after):
                pos = i
        beforeparams = {}
        for i, n in enumerate(self.params.keys()):
            beforeparams[n] = self.params[n]
            if i == pos:
                break
        afterparams = {}
        for i, n in enumerate(self.params.keys()):
            if i <= pos:
                continue
            afterparams[n] = self.params[n]
        self.params = {}
        for name, typ in params.items():
            if name in beforeparams or name in afterparams:
                continue  # Param already in params, only update new params.
            pos += 1
            value = str(selected.get(name, ""))
            flags = wx.ALL | wx.EXPAND
            proportion = 0
            descname = name
            if typ == "str":
                proportion = 1
                if value is None:
                    hint = selected.get("default"+name,"enter value")
                    self.params[name] = wx.TextCtrl(self.spanel, style=wx.TE_MULTILINE)
                    if hint:
                        self.params[name].SetHint(hint)
                else:
                    self.params[name] = wx.TextCtrl(self.spanel, style=wx.TE_MULTILINE, value=value)
            elif typ == "option":
                if selected[name]:
                    label = "OPTION OFF"
                else:
                    label = "OPTION ON"
                self.params[name] = NamedButton(self.spanel, label, name)
                self.params[name].Bind(wx.EVT_BUTTON, self.on_optButton)
            elif typ == "addbutton":
                self.params[name] = NamedButton(self.spanel, "ADD", name)
                self.params[name].Bind(wx.EVT_BUTTON, self.on_addButton)
            elif typ == "deletebutton":
                self.params[name] = NamedButton(self.spanel, "DELETE", name)
                self.params[name].Bind(wx.EVT_BUTTON, self.on_deleteButton)
            elif typ == "samplebutton":
                self.params[name] = NamedButton(self.spanel, "SAMPLE", value)
                self.params[name].Bind(wx.EVT_BUTTON, self.on_sampleButton)
            elif typ == "int":
                proportion = 1
                self.params[name] = wx.TextCtrl(self.spanel, value=value)
            elif typ == "YYYYMMDD HH:MM:SS":
                proportion = 1
                self.params[name] = wx.TextCtrl(self.spanel, value=value)
            elif typ == "password":
                proportion = 1
                self.params[name] = wx.TextCtrl(self.spanel, value=value)
            elif isinstance(typ, list):  # Choice
                if len(value) == 0:
                    value = typ[0]  # No selection, default to first choice.
                self.params[name] = NamedComboBox(self.spanel, choices=typ,name=name)
                self.params[name].SetValue(value)
                self.params[name].Bind(event=wx.EVT_COMBOBOX, handler=self.on_choice)
                descname = value
            else:
                raise Exception("Exception unknown type=" + str(typ))
            hbox = wx.BoxSizer(wx.HORIZONTAL)
            self.titles[name] = wx.StaticText(self.spanel, -1, name)
            hbox.Add(self.titles[name], proportion=0, flag=wx.ALIGN_LEFT)
            hbox.Add(self.params[name], proportion=proportion, flag=wx.ALL | wx.EXPAND)
            if descname in descriptions:
                self.desc[name] = wx.TextCtrl(self.spanel, value=descriptions[descname], style=wx.TE_MULTILINE|wx.TE_READONLY)
                hbox.Add(self.desc[name], proportion=1, flag=flags)
            if pos < self.svbox.GetItemCount():
                self.svbox.Insert(pos, hbox, flag=flags)
            else:
                self.svbox.Add(hbox, proportion=proportion, flag=flags)
        newparams = {}
        for n, e in beforeparams.items():
            newparams[n] = e
        for n, e in self.params.items():
            newparams[n] = e
        for n, e in afterparams.items():
            newparams[n] = e
        self.params = newparams

    def showFields(self) -> None:
        show = [True]  # Whether to show or hide the next field.
        nested = []  # name to match to pop the stack.
        choice = []  # name to match to start the choice selection
        for name in self.params.keys():
            e = self.params[name]
            # Pop end of field group
            while len(nested) > 0 and not name.startswith(nested[-1]):
                del show[-1]
                del nested[-1]
            # Look out for the start of chosen fields.
            if (len(choice) > 0 and
                (len(nested) == 0 or nested[-1] != choice[-1]) and
                name.startswith(choice[-1])):
                nested.append(name)
                show.append(True)
            showfield = show[-1]
            if isinstance(e, NamedButton) and e.GetLabel().startswith("OPTION"):
                nested.append(name[:name.rfind(".")])
                # OFF means turn it off, and it is currently ON!
                if self.params[name].GetLabel() == "OPTION OFF":
                    show.append(show[-1])
                else:
                    show.append(False)
            elif isinstance(e, wx.ComboBox):  # Choice
                if showfield:
                    nested.append(name)
                    show.append(False)
                    choice.append(name+"."+self.params[name].GetValue())
            if showfield:
                self.params[name].Show()
                self.titles[name].Show()
                if name in self.desc:
                    self.desc[name].Show()
            else:
                self.params[name].Hide()
                self.titles[name].Hide()
                if name in self.desc:
                    self.desc[name].Hide()
        self.panel.Layout()
        self.Layout()
        self.Show()

    def getSelected(self) -> dict:
        selected = {}
        for name, e in self.params.items():
            if e.IsShown():
                if isinstance(e,NamedButton):
                    selected[name] = e.GetLabel().endswith("OFF")
                else:
                    selected[name] = e.GetValue()
                    if e.GetHint() and not selected[name]:
                        selected[name] = None
                        selected["default"+name] = e.GetHint()
        return selected

    def getValue(self, name: str, typ: str) -> (any, str):
        if typ == "str":
            return self.params[name].GetValue(), typ
        elif typ == "int":
            # noinspection PyBroadException
            try:
                return int(self.params[name].GetValue()), typ
            except Exception:
                return -1
        elif typ == "YYYYMMDD HH:MM:SS":
            return self.params[name].GetValue(), typ
        elif typ == "password":
            v = self.params[name].GetValue()
            if v:
                # Cut'n'paste the password adds a return to the end.
                if v[-1] == "\n":
                    return v[0:-1], typ
            return v, typ
        else:
            raise ("Exception unknown type=" + typ)

    def on_no(self, _event):
        self.res = wx.NO
        self.Close()
        self.Destroy()

    def on_delete(self, _event):
        if wx.MessageBox("", "Confirm delete of command", wx.YES | wx.NO, self) == wx.YES:
            self.res = wx.CANCEL
            self.Close()
            self.Destroy()

    def on_yes(self, _event):
        self.res = wx.YES
        self.Close()
        self.Destroy()

    def on_ok(self, _event):
        if self.verify is not None:
            error = self.verify(self)
            if error:
                wx.MessageBox(
                    "Failed:"+error,
                    "verification",
                    wx.OK, self)
                return
        self.res = wx.OK
        self.Close()
        self.Destroy()

    def on_verify(self, _event):
        if self.verify is None:
            raise Exception("No verify callback method")
        error = self.verify(self)
        if error:
            wx.MessageBox(
                "Faild:"+error,
                "verification",
                wx.OK, self)
            return
        wx.MessageBox("Passed", "verification", wx.OK, self)

    def on_choice(self, event):
        cb = event.GetEventObject()
        value = cb.GetValue()
        name = cb.name
        if name in self.desc:
            if value in self.descriptions:
                self.desc[name].SetValue(self.descriptions[value])
            else:
                self.desc[name].SetValue("")
        self.showFields()

    def on_sampleButton(self, event) -> None:
        if self.sample is None:
            return
        cb = event.GetEventObject()
        self.sample(cb.name)

    def on_deleteButton(self, event) -> None:
        b = event.GetEventObject()
        if wx.MessageBox("", "Confirm delete of parameters", wx.YES | wx.NO, self) != wx.YES:
            return
        d = []
        for i, n in enumerate(self.params.keys()):
            if n.startswith(b.name):
                d.append((i, n))
        for i, n in reversed(d):
            self.params[n].Hide()
            del self.params[n]
            self.titles[n].Hide()
            del self.titles[n]
            if n in self.desc:
                self.desc[n].Hide()
                del self.desc[n]
            self.svbox.Remove(i)
        self.showFields()

    def on_addButton(self, event) -> None:
        b = event.GetEventObject()
        (params, selected, desc) = self.getOptions(cmd=None,at=b.name)
        prev = None
        for n in self.params.keys():
            if n.startswith(b.name):
                if self.params[n].GetLabel() == "DELETE":
                   prev = n
        if prev:
            x = prev[len(b.name)+1:]  # Cut main title and first dot.
            oldname = b.name + ".0"
            newname = b.name + "." + str(int(x) + 1)
            newparams = {}
            newselected = {}
            newdesc = {}
            for n, t in params.items():
                newn = n.replace(oldname,newname)
                newparams[newn] = params[n]
                if n in selected:
                    newselected[newn] = selected[n]
                if n in desc:
                    newdesc[newn] = desc[n]
            self.updateParams(b.name, newparams, newselected, newdesc)
        else:
            self.updateParams(b.name, params, selected, desc)
        self.showFields()

    def on_optButton(self, event) -> None:
        b = event.GetEventObject()
        if b.GetLabel().endswith("ON"):
            b.SetLabel("OPTION OFF")
            n = b.name
            if n.rindex("."):
                n = n[0:n.rindex(".")]
            (params, selected, desc) = self.getOptions(cmd=None, at=n)
            self.updateParams(n, params, selected, desc)
        else:
            b.SetLabel("OPTION ON")
        self.showFields()


from io import StringIO

from .file_client import FileClient

def list_from_file(filename,
                   prefix='',
                   offset=0,
                   max_num=0,
                   encoding='utf-8',
                   file_client_args=None):
    """Load a text file and parse the content as a list of strings.

    Note:
        In v1.3.16 and later, ``list_from_file`` supports loading a text file
        which can be storaged in different backends and parsing the content as
        a list for strings.

    Args:
        filename (str): Filename.
        prefix (str): The prefix to be inserted to the beginning of each item.
        offset (int): The offset of lines.
        max_num (int): The maximum number of lines to be read,
            zeros and negatives mean no limitation.
        encoding (str): Encoding used to open the file. Default utf-8.
        file_client_args (dict, optional): Arguments to instantiate a
            FileClient. See :class:`mmcv.fileio.FileClient` for details.
            Default: None.

    Examples:
        >>> list_from_file('/path/of/your/file')  # disk
        ['hello', 'world']
        >>> list_from_file('s3://path/of/your/file')  # ceph or petrel
        ['hello', 'world']

    Returns:
        list[str]: A list of strings.
    """
    cnt = 0
    item_list = []
    file_client = FileClient.infer_client(file_client_args, filename)
    with StringIO(file_client.get_text(filename, encoding)) as f:
        for _ in range(offset):
            f.readline()
        for line in f:
            if 0 < max_num <= cnt:
                break
            item_list.append(prefix + line.rstrip('\n\r'))
            cnt += 1
    return item_list

def dict_from_file(filename,
                   key_type=str,
                   encoding='utf-8',
                   file_client_args=None):
    """Load a text file and parse the content as a dict.

    Each line of the text file will be two or more columns split by
    whitespaces or tabs. The first column will be parsed as dict keys, and
    the following columns will be parsed as dict values.

    Note:
        In v1.3.16 and later, ``dict_from_file`` supports loading a text file
        which can be storaged in different backends and parsing the content as
        a dict.

    Args:
        filename(str): Filename.
        key_type(type): Type of the dict keys. str is user by default and
            type conversion will be performed if specified.
        encoding (str): Encoding used to open the file. Default utf-8.
        file_client_args (dict, optional): Arguments to instantiate a
            FileClient. See :class:`mmcv.fileio.FileClient` for details.
            Default: None.

    Examples:
        >>> dict_from_file('/path/of/your/file')  # disk
        {'key1': 'value1', 'key2': 'value2'}
        >>> dict_from_file('s3://path/of/your/file')  # ceph or petrel
        {'key1': 'value1', 'key2': 'value2'}

    Returns:
        dict: The parsed contents.
    """
    mapping = {}
    file_client = FileClient.infer_client(file_client_args, filename)
    with StringIO(file_client.get_text(filename, encoding)) as f:
        for line in f:
            items = line.rstrip('\n').split()
            assert len(items) >= 2
            key = key_type(items[0])
            val = items[1:] if len(items) > 2 else items[1]
            mapping[key] = val
    return mapping


import sqlite3

def main():
    conn = sqlite3.connect('Data/chocolate.db')
    cur = conn.cursor()

    pid = int(input('Enter product ID: '))

    cur.execute('''SELECT Description, RetailPrice FROM Products
                    WHERE ProductID == ?''', (pid,))
    results = cur.fetchone()

    if results != None:
        print(f'The current price for "{results[0]}" is: '
              f'${results[1]:.2f}')

        new_price = float(input('Enter the new price: '))

        cur.execute('''UPDATE Products
                    SET RetailPrice = ?
                    WHERE ProductID == ?''',
                    (new_price, pid))

        conn.commit()
        print('The price was changed.')
    else:
        print(f'The "{pid}" ID wasnt found.')

    print(cur.rowcount)
    conn.close()

if __name__ == '__main__':
    main()


from abc import abstractmethod
from math import ceil

from PyQt5 import QtCore
from PyQt5.QtGui import QFont, QCursor
from PyQt5.QtWidgets import QWidget, QVBoxLayout, QPushButton, QHBoxLayout, QScrollArea

class PageHelper:
    def __init__(self, UI, PageItemNum):
        self._UI = UI
        self._PageItemNum = PageItemNum
        self._currentPageNum = 0
        self._isFilter = False
        self._tempHL_List = []
        self._numBTN_List = []

        self._initClick()
    def _initClick(self):
        def leftClick(evt):
            if self._currentPageNum>0:
                self.toPage(self._currentPageNum-1)
        self._UI.leftBTN.clicked.connect(leftClick)
        def rightClick(evt):
            if self._currentPageNum<self.pageCount-1:
                self.toPage(self._currentPageNum+1)
        self._UI.rightBTN.clicked.connect(rightClick)
        def toFirst(evt):
            if self._currentPageNum!=0:
                self.toPage(0)
        self._UI.toFirstBtn.clicked.connect(toFirst)
    def _initScrollArea(self, scrollArea:QScrollArea):
        widget = QWidget()
        self._VL = QVBoxLayout()
        self._VL.setContentsMargins(0,0,0,0)
        self._scrollArea = scrollArea
        self._scrollArea.setWidget(widget)
        widget.setLayout(self._VL)

    @abstractmethod
    def _generatePage(self,newDataList):
        '''
        生成每个页面的布局
        :return:
        '''
        pass
    @abstractmethod
    def dataList(self):
        if not self._isFilter:
            return []
        else:
            return []
    @property
    def _currentPageDataList(self):
        # 生成卡牌列表
        oldDataList = self.dataList()
        endValue = (self._currentPageNum + 1) * self._PageItemNum
        if endValue>len(oldDataList):endValue=len(oldDataList)
        newDataList = oldDataList[self._currentPageNum * self._PageItemNum:endValue]
        return newDataList

    @property
    def pageCount(self):
        return ceil((len(self.dataList()) / self._PageItemNum))

    def _clearScroll(self):
        while len(self._tempHL_List)>0:
            tempHL = self._tempHL_List[0]           # type: QHBoxLayout
            self._tempHL_List.remove(tempHL)
            while tempHL.count()>0:
                child = tempHL.takeAt(0)
                if child.widget():
                    child.widget().setParent(None)
                    del child
            tempHL.deleteLater();del tempHL
    def _refreshBtnList(self):
        while len(self._numBTN_List)>0:
            numBTN = self._numBTN_List[0]           # type: QPushButton
            self._numBTN_List.remove(numBTN)
            numBTN.setParent(None)
            numBTN.deleteLater();del numBTN
        # 生成按钮列表
        font = QFont()
        font.setFamily("Adobe 黑体 Std R")
        font.setPointSize(12)
        count = 0;continueFlag = False
        start = self._currentPageNum
        if self.pageCount - start<5:
            start = self.pageCount - 5
        for i in range(start, self.pageCount):
            if i < 0 or i == self.pageCount:continue
            if continueFlag and i != self.pageCount-1:continue
            count += 1
            numBTN = QPushButton(None)
            self._UI.pageBTN_List.insertWidget(count, numBTN)
            self._numBTN_List.append(numBTN)
            numBTN.setMinimumSize(QtCore.QSize(28, 28));numBTN.setMaximumSize(QtCore.QSize(28, 28))
            numBTN.setFont(font)

            if count == 4 and self.pageCount-1-start>5:
                numBTN.setText("...")
                continueFlag=True;continue
            else:
                numBTN.setText(str(i + 1))
            def numBTNClick(index):
                def __numBTNClick():
                    self.toPage(index)
                return __numBTNClick
            numBTN.clicked.connect(numBTNClick(i))
            numBTN.setCursor(QCursor(QtCore.Qt.PointingHandCursor))
            if i == self._currentPageNum:
                numBTN.setStyleSheet("background-color:rgb(69, 138, 202);")
            else:
                numBTN.setStyleSheet("")

        # 刷新指针状态
        if self._currentPageNum<=0: self._UI.leftBTN.setCursor(QCursor(QtCore.Qt.ForbiddenCursor))
        else:self._UI.leftBTN.setCursor(QCursor(QtCore.Qt.PointingHandCursor))
        if self._currentPageNum>=self.pageCount-1: self._UI.rightBTN.setCursor(QCursor(QtCore.Qt.ForbiddenCursor))
        else:self._UI.rightBTN.setCursor(QCursor(QtCore.Qt.PointingHandCursor))
    def _refreshEle(self):
        self._clearScroll()
        self._generatePage(self._currentPageDataList)
        self._refreshBtnList()

    def filter(self,filterStr):
        self.filterStr = filterStr
        if self.filterStr == "":
            self._isFilter = False
        else:
            self._isFilter = True
        self._refreshEle()
    def toPage(self,pageNum:int=0):
        if pageNum<0: return
        self._currentPageNum = pageNum
        self._refreshEle()


import sys
from collections import defaultdict

if __name__ == '__main__':
    N, K = map(int, sys.stdin.readline().split())
    chess_board = [list(map(int, sys.stdin.readline().split())) for _ in range(N)]
    chess_pieces, pieces_count = defaultdict(dict), defaultdict(list)
    for idx in range(K):
        r, c, d = map(int, sys.stdin.readline().split())
        chess_pieces[idx] = {'location': (r-1, c-1), 'direction': d-1}
        pieces_count[(r-1, c-1)].append(idx)

    directions = [(0, 1), (0, -1), (-1, 0), (1, 0)]
    change_directions = {0: 1, 1: 0, 2: 3, 3: 2}

    play_count = 1
    break_flag = False
    while True:
        if play_count > 1000:
            play_count = -1
            break

        for id in range(K):
            (r, c), d = chess_pieces[id].values()

            move_piece_index = pieces_count[(r, c)].index(id)
            move_pieces = pieces_count[(r, c)][move_piece_index:]
            if pieces_count[(r, c)][:move_piece_index]:
                pieces_count[(r, c)] = pieces_count[(r, c)][:move_piece_index]
            else:
                pieces_count.pop((r, c))

            dr = r + directions[d][0]
            dc = c + directions[d][1]
            if (0 <= dr < N and 0 <= dc < N) and chess_board[dr][dc] != 2:
                if chess_board[dr][dc] == 1:
                    move_pieces = move_pieces[::-1]

                pieces_count[(dr, dc)].extend(move_pieces)
                for mp in move_pieces:
                    chess_pieces[mp]['location'] = (dr, dc)
            else:
                cd = change_directions[d]
                chess_pieces[id]['direction'] = cd
                dr = r + directions[cd][0]
                dc = c + directions[cd][1]
                if (0 <= dr < N and 0 <= dc < N) and chess_board[dr][dc] != 2:
                    if chess_board[dr][dc] == 1:
                        move_pieces = move_pieces[::-1]

                    pieces_count[(dr, dc)].extend(move_pieces)
                    for mp in move_pieces:
                        chess_pieces[mp]['location'] = (dr, dc)
                else:
                    dr, dc = r, c
                    pieces_count[(dr, dc)].extend(move_pieces)

            if len(pieces_count[(dr, dc)]) >= 4:
                break_flag = True
                break

        if break_flag:
            break

        play_count += 1

    print(play_count)

백준/삼성 SW 역량 테스트 기출 문제/[17837] 새로운 게임2/지민.py


# -*- coding: utf-8 -*-
import datetime
from io import BytesIO

import pytz
from django.core.files.storage import default_storage
from django.http import HttpResponse
from ledger.payments.pdf import BrokenLine
from ledger.settings_base import TIME_ZONE
from reportlab.lib.colors import red, green, blue
from reportlab.lib.enums import TA_RIGHT, TA_CENTER
from reportlab.lib.pagesizes import A4
from reportlab.pdfgen import canvas
from reportlab.platypus import BaseDocTemplate, PageTemplate, Frame, Paragraph, Spacer, Table, TableStyle, PageBreak
from reportlab.lib.styles import ParagraphStyle, StyleSheet1
from reportlab.lib.units import mm
from reportlab.lib import colors

from wildlifecompliance.components.main.pdf_utils import gap, ParagraphOffeset, ParagraphCheckbox, get_font_str

PAGE_MARGIN = 5 * mm
PAGE_WIDTH, PAGE_HEIGHT = A4

def _create_pdf(invoice_buffer, legal_case, offenders):
    every_page_frame = Frame(PAGE_MARGIN, PAGE_MARGIN, PAGE_WIDTH - 2 * PAGE_MARGIN, PAGE_HEIGHT - 2 * PAGE_MARGIN, id='EveryPagesFrame', )  #showBoundary=Color(0, 1, 0))
    every_page_template = PageTemplate(id='EveryPages', frames=[every_page_frame,], )
    doc = BaseDocTemplate(invoice_buffer, pageTemplates=[every_page_template, ], pagesize=A4,)  # showBoundary=Color(1, 0, 0))

    # Common
    col_width_head = [95*mm, 15*mm, 85*mm,]
    col_width_details = [28*mm, 28*mm, 71*mm, 23*mm, 41*mm]
    FONT_SIZE_L = 12
    FONT_SIZE_M = 10
    FONT_SIZE_S = 8
    topLeftTableRowHeights = [23.5*mm, ]
    topRightTableRowHeights = [7.8*mm, 15.6*mm, ]

    styles = StyleSheet1()
    styles.add(ParagraphStyle(name='Normal',
                              fontName='Helvetica',
                              fontSize=FONT_SIZE_M,
                              spaceBefore=2,  # space before paragraph
                              spaceAfter=2,   # space after paragraph
                              leading=11))       # space between lines
    styles.add(ParagraphStyle(name='BodyText',
                              parent=styles['Normal'],
                              spaceBefore=6))
    styles.add(ParagraphStyle(name='Italic',
                              parent=styles['BodyText'],
                              fontName='Helvetica-Italic'))
    styles.add(ParagraphStyle(name='Bold',
                              parent=styles['BodyText'],
                              fontName='Helvetica-Bold',
                              alignment = TA_CENTER))
    styles.add(ParagraphStyle(name='Right',
                              parent=styles['BodyText'],
                              alignment=TA_RIGHT))
    styles.add(ParagraphStyle(name='Centre',
                              parent=styles['BodyText'],
                              alignment=TA_CENTER))

    court_date_qs = legal_case.court_proceedings.court_dates.all().order_by('court_datetime')
    court_date_obj = None
    if court_date_qs:
        # Retrieve earliest one
        court_date_obj = court_date_qs[0]

    elements = []
    for offender in offenders:
        offender_full_name = ''
        court_date_txt = ''
        court_time_txt = ''
        court_place_txt = ''

        if offender.person:
            offender_full_name = offender.person.get_full_name()
        if court_date_obj and court_date_obj.court_datetime:
            local_datetime = court_date_obj.court_datetime.astimezone(pytz.timezone(TIME_ZONE))
            court_date_txt = local_datetime.strftime('%d/%m/%Y')
            court_time_txt = local_datetime.strftime('%H:%M')
        if court_date_obj and court_date_obj.court:
            court_place_txt = court_date_obj.court.location

        ###
        # 1st page
        ###

        # Header small text
        header_small_text_p1 = ParagraphOffeset('Copy to be attached to court copy of prosecution notice',
                                                styles['Right'],
                                                x_offset=-3*mm, y_offset=0)

        # Head (col, row)
        invoice_table_style = TableStyle([
            ('VALIGN', (0, 0), (-1, -1), 'TOP'),
            ('GRID', (0, 0), (-1, -1), 0, colors.white),
            ('ALIGN', (0, 0), (-1, -1), 'LEFT'),
        ])
        style_tbl_left = TableStyle([
            ('VALIGN', (0, 0), (-1, -1), 'MIDDLE'),
            ('GRID', (0, 0), (-1, -1), 0.5, colors.black),
            ('ALIGN', (0, 0), (-1, -1), 'LEFT'),
        ])
        style_tbl_right = TableStyle([
            ('VALIGN', (0, 0), (-1, -1), 'MIDDLE'),
            ('GRID', (0, 0), (-1, -1), 0.5, colors.black),
            ('ALIGN', (0, 0), (-1, -1), 'LEFT'),
        ])
        data_left = Table([
            [Paragraph('MAGISTRATES COURT of WESTERN
'
                       'AUSTRALIA
'
                       'COURT HEARING NOTICE
'
                       'Criminal Procedure Act 2004
'
                       'Criminal Procedure Regulations 2005 - Form 5', styles['Centre']),]
        ], style=style_tbl_left, rowHeights=topLeftTableRowHeights)
        data_right = Table([
            [Paragraph('Court number', styles['Normal']), ''],
            [Paragraph('Magistrates court at', styles['Normal']), ''],
        ], style=style_tbl_right, rowHeights=topRightTableRowHeights)
        tbl_head = Table([[data_left, '', data_right]], style=invoice_table_style, colWidths=col_width_head, )

        # Accused's Details, etc
        rowHeights = [6*mm, 6*mm, 6*mm, 30*mm, 6*mm]
        style_tbl_accused_details = TableStyle([
            ('VALIGN', (0, 0), (0, 0), 'MIDDLE'),
            ('GRID', (0, 0), (-1, -1), 0.5, colors.black),
            ('ALIGN', (0, 0), (-1, -1), 'LEFT'),
            ('SPAN', (0, 0), (0, 1)),
            ('SPAN', (2, 0), (4, 0)),
            ('SPAN', (2, 1), (4, 1)),
        ])
        data = []
        data.append([
            Paragraph('Accused\'s Details
', styles['Normal']),
            Paragraph('Full name', styles['Normal']),  # ,
            Paragraph(get_font_str(offender_full_name), styles['Normal']),
            '',
            '',
        ])
        data.append([
            '',
            Paragraph('Address', styles['Normal']),
            '', '', '',
        ])
        tbl_accused_details = Table(data, style=style_tbl_accused_details, colWidths=col_width_details, )  # rowHeights=rowHeights)

        # Hearing details, etc
        style_tbl_hearing_details = TableStyle([
            ('VALIGN', (0, 0), (-1, -1), 'MIDDLE'),
            ('GRID', (0, 0), (-1, -1), 0.5, colors.black),
            ('ALIGN', (0, 0), (-1, -1), 'LEFT'),
            ('SPAN', (1, 0), (4, 0)),
            ('SPAN', (1, 2), (4, 2)),
        ])
        data = []
        data.append([
            Paragraph('Hearing details', styles['Normal']),
            Paragraph('The charge(s) in the attached prosecution notice dated [insert date]
will be first dealt with by the above court at the time, date and place stated below.', styles['Normal']),
            '', '', '',
        ])
        data.append([
            Paragraph('Date and time', styles['Normal']),
            Paragraph('Date', styles['Normal']),
            Paragraph(get_font_str(court_date_txt), styles['Normal']),
            Paragraph('Time', styles['Normal']),
            Paragraph(get_font_str(court_time_txt), styles['Normal']),
        ])
        data.append([
            Paragraph('Place', styles['Normal']),
            Paragraph(get_font_str(court_place_txt), styles['Normal']),
            '', '', '',
        ])
        tbl_hearing_details = Table(data, style=style_tbl_hearing_details, colWidths=col_width_details, )  # rowHeights=rowHeights)

        # Notice to accused
        col_width_notice_to_accused = [28*mm, 163*mm, ]
        style_tbl_notice_to_accused = TableStyle([
            ('VALIGN', (0, 0), (-1, -1), 'MIDDLE'),
            ('VALIGN', (0, 0), (0, -1), 'TOP'),
            ('GRID', (0, 0), (-1, -1), 0.5, colors.black),
            ('ALIGN', (0, 0), (-1, -1), 'LEFT'),
        ])
        data = []
        data.append([
            Paragraph('Notice to accused', styles['Normal']),
            Paragraph('Your options are set out below. You should read them carefully.
If you do not know what to do, you should get advice from a lawyer, the Legal Aid Commission or the Aboriginal Legal Service. If you will need an interpreter in court, please contact the court', styles['Normal']),
        ])
        data.append([
            Paragraph('Options', styles['Normal']),
            Paragraph('1. You can attend the above hearing.
'
                      '2. You can do nothing.
'
                      '3. You can plead not guilty in writing.
'
                      '4. You can plead guilty in writing.
'
                      'Options 2, 3 and 4 are explained below.', styles['Normal']),
        ])
        data.append([
            [
                Paragraph('Doing nothing', styles['Normal']),
                Spacer(0, 5*mm),
                Paragraph('[Options 2]', styles['Normal']),
            ],
            [
                Paragraph('If you do not appear at the above hearing and you do not send the court a written plea in time, the court may determine the charge(s) at the above hearing in your absence.', styles['Normal']),
                Paragraph('In some cases the court can take as proved any allegation in the attached prosecution notice without hearing evidence.', styles['Normal']),
                Paragraph('The court may decide to summons you to court or have you arrested and brought before the court.', styles['Normal']),
                Paragraph('If the court finds you guilty, it may fine you and order you to pay court costs and the prosecutor’s costs.', styles['Normal']),
            ],
        ])
        data.append([
            [
                Paragraph('Pleading not guilty in writing', styles['Normal']),
                Spacer(0, 5 * mm),
                Paragraph('[Option 3]', styles['Normal']),
            ],
            [
                Paragraph('Pleading not guilty to a charge in the prosecution notice means you do not admit the charge.', styles['Normal']),
                Paragraph('If you send the court a written plea of not guilty, you need not attend the above hearing. If the court receives your written plea in time it will send you a notice of another hearing, at which the court will deal with the charge(s) (in your absence if you are not there) and hear any evidence you wish to give and any witnesses you call.', styles['Normal']),
                Paragraph('To send the court a written plea of not guilty, fill out page 2 of this form and send page 2 to the address on it at least three days before the above hearing date.', styles['Normal']),
            ],
        ])
        data.append([
            [
                Paragraph('Pleading guilty in writing', styles['Normal']),
                Spacer(0, 5 * mm),
                Paragraph('[Option 4]', styles['Normal']),
            ],
            [
                Paragraph('Pleading guilty to a charge in the prosecution notice means you admit the charge.', styles['Normal']),
                Paragraph('If you send the court a written plea of guilty, you need not attend the above hearing unless you want to tell the court something.', styles['Normal']),
                Paragraph('If the court receives your written plea in time it will deal with the charge(s) at the above hearing (in your absence if you are not there) and may fine you and order you to pay court costs and the prosecutor’s costs.', styles['Normal']),
                Paragraph('To send the court a written plea of guilty, fill out page 2 of this form, include any written explanation or information you want the court to consider, and send it all to the address on the form at least three days before the above hearing date.', styles['Normal']),
                Paragraph('The court might not accept your plea of guilty if what you tell the court suggests you do not admit the charge. If that happens you will be notified.', styles['Normal']),
            ],
        ])
        tbl_notice_to_accused = Table(data, style=style_tbl_notice_to_accused, colWidths=col_width_notice_to_accused)

        # Issuing details
        col_width_issuing_details = col_width_notice_to_accused
        style_tbl_issuing_details = TableStyle([
            ('VALIGN', (0, 0), (-1, -1), 'MIDDLE'),
            ('GRID', (0, 0), (-1, -1), 0.5, colors.black),
            ('ALIGN', (0, 0), (-1, -1), 'LEFT'),
        ])
        data = []
        data.append([
            Paragraph('Issuing details', styles['Normal']),
            [
                Paragraph('This notice is issued on [date]', styles['Normal']),
                Spacer(0, 8*mm),
                BrokenLine(50*mm),
                Paragraph('[Title of person issuing notice]', styles['Normal']),
            ]
        ])
        tbl_issuing_details = Table(data, style=style_tbl_issuing_details, colWidths=col_width_issuing_details)

        # Service details
        col_width_service_details = col_width_notice_to_accused
        style_tbl_service_details = TableStyle([
            ('VALIGN', (0, 0), (-1, -1), 'MIDDLE'),
            ('GRID', (0, 0), (-1, -1), 0.5, colors.black),
            ('ALIGN', (0, 0), (-1, -1), 'LEFT'),
            ('SPAN', (0, 0), (0, 1))
        ])
        data = []
        data.append([
            [
                Paragraph('Service details', styles['Normal']),
                Spacer(0, 5 * mm),
                Paragraph('[*Police only]', styles['Normal']),
            ],
            Paragraph('[Service must be in one of the manners in the CPA Schedule 2 clauses 2, 3 or 4 (see s. 33(3)). Insert here whichever manner of service was used.]', styles['Normal'])
        ])
        tbl_style_internal = TableStyle([
            ('VALIGN', (0, 0), (-1, -1), 'MIDDLE'),
        ])
        data.append([
            '',
            [
                Paragraph('On' + gap(30) + '20' + gap(10) + ', the accused was served with a copy of this notice and the prosecution notice referred to above in the following manner:', styles['Normal']),
                Table([
                    [Paragraph('Name of server:', styles['Normal']), Paragraph('*Registered No:', styles['Normal'])],
                    [Paragraph('Signature:', styles['Normal']), Paragraph(gap(1) + 'Station:', styles['Normal'])],
                ], style=tbl_style_internal, rowHeights=[8*mm, 8*mm, ])
            ]
        ])
        tbl_service_details = Table(data, style=style_tbl_service_details, colWidths=col_width_service_details)

        ###
        # 2nd page
        ###
        # Head (col, row)
        data_left_p2 = Table([
            [Paragraph('MAGISTRATES COURT of WESTERN
'
                       'AUSTRALIA
'
                       'WRITTEN PLEA BY ACCUSED
'
                       'Criminal Procedure Act 2004
'
                       'Criminal Procedure Regulations 2005 - Form 5 page 2', styles['Centre']),]
        ], style=style_tbl_left, rowHeights=topLeftTableRowHeights)
        data_right_p2 = Table([
            [Paragraph('Court number', styles['Normal']), ''],
            [Paragraph('Magistrates court at', styles['Normal']), ''],
        ], style=style_tbl_right, rowHeights=topRightTableRowHeights)
        tbl_head_p2 = Table([[data_left_p2, '', data_right_p2]], style=invoice_table_style, colWidths=col_width_head, )

        # Accused's Details
        # This is common among the pages

        # Accused's plea
        col_width_p2 = [28*mm, 28*mm, 71*mm, 23*mm, 41*mm]
        tbl_style_p2 = (
            ('VALIGN', (0, 0), (-1, -1), 'MIDDLE'),
            ('VALIGN', (0, 0), (0, -1), 'TOP'),
            ('GRID', (0, 0), (-1, -1), 0.5, colors.black),
            ('ALIGN', (0, 0), (-1, -1), 'LEFT'),
            ('SPAN', (1, 0), (4, 0)),
            ('SPAN', (1, 1), (4, 1)),
            ('SPAN', (1, 2), (4, 2)),
            ('SPAN', (1, 3), (4, 3)),
            ('SPAN', (1, 4), (4, 4)),
            ('SPAN', (1, 5), (4, 5)),
            ('SPAN', (1, 6), (2, 6)),
            ('SPAN', (1, 7), (4, 7)),
            ('SPAN', (0, 5), (0, 6)),
        )
        data = []
        data.append([
            Paragraph('Accused\'s plea', styles['Normal']),
            [
                Paragraph('I have received a prosecution notice dated' + gap(40) + 'and a court hearing notice advising me of the hearing on [date]', styles['Normal']),
                Paragraph('I understand or have had explained to me the charge(s) in the prosecution notice and the contents of the court hearing notice and I understand the effect of this written plea I am sending to the court.', styles['Normal']),
            ],
            '', '', '',
        ])
        data.append([
            [
                Paragraph('Plea of guilty', styles['Normal']),
                Paragraph('[Tick on box]', styles['Normal']),
                Spacer(0, 20*mm),
                Paragraph('[Tick on box]', styles['Normal']),
            ],
            [
                ParagraphCheckbox('I plead guilty to the charge(s) in the prosecution notice.', styles['Normal']),
                ParagraphCheckbox('I plead guilty to the following charges in the prosecution notice.', styles['Normal']),
                Paragraph('[If the prosecution notice contains more than one charge and you want to plead guilty to only some of them, write the numbers of the charges here.]', styles['Normal']),
                Spacer(0, 8*mm),
                Paragraph('Attendance at court:', styles['Normal']),
                ParagraphCheckbox('I will be attending the hearing on the above date.', styles['Normal']),
                ParagraphCheckbox('I will not be attending the hearing on the above date.', styles['Normal']),
                Paragraph('I would like the court to take account of the following:', styles['Normal']),
                Paragraph('[If you are pleading guilty you can (but need not) explain why you committed the offence(s) and give any information that you want the court to consider when deciding what sentence to impose on you.]', styles['Normal']),
                Spacer(0, 10 * mm),
            ],
            '', '', '',
        ])
        data.append([
            [
                Paragraph('Plea of not guilty', styles['Normal']),
                Paragraph('[Tick on box]', styles['Normal']),
                Spacer(0, 20 * mm),
                Paragraph('[Tick on box]', styles['Normal']),
            ],
            [
                ParagraphCheckbox('I plead not guilty to the charge(s) in the prosecution notice.', styles['Normal']),
                ParagraphCheckbox('I plead not guilty to the following charges in the prosecution notice.', styles['Normal']),
                Paragraph('[If the prosecution notice contains more than one charge and you want to plead not guilty to only some of them, write the numbers of them here]', styles['Normal']),
                Spacer(0, 8 * mm),
                Paragraph('Attendance at court:', styles['Normal']),
                ParagraphCheckbox('I will be attending the hearing on the above date.', styles['Normal']),
                ParagraphCheckbox('I will not be attending the hearing on the above date.', styles['Normal']),
                Paragraph('At the trial of the charge(s) I intend to call' + gap(40) + 'witnesses (including myself).', styles['Normal']),
                Paragraph('[Please insert the number of witnesses to assist the court in deciding how long the trial might last]', styles['Normal']),
                Paragraph('When setting a date for the trial please take account of the following:', styles['Normal']),
                Paragraph('[Please provide any information that might assist the court when setting the date for the trial such as dates when you will be overseas or in hospital.]', styles['Normal']), Spacer(0, 10 * mm),
            ],
            '', '', '',
        ])
        data.append([
            Paragraph('Contact details', styles['Normal']),
            [
                Paragraph('My contact details are:', styles['Normal']),
                Spacer(0, 2*mm),
                Paragraph('Address (if different to the one above):', styles['Normal']),
                Spacer(0, 2*mm),
                Paragraph('Telephone no.' + gap(40) + 'Fax no.' + gap(40) + 'Mobile no.', styles['Normal']),
            ],
            '', '', '',
        ])
        data.append([
            [
                Paragraph('Lawyer\'s details', styles['Normal']),
                Paragraph('[If a lawyer will appear for you]', styles['Normal']),
            ],
            [
                Paragraph('Name:', styles['Normal']),
                Paragraph('Firm name', styles['Normal']),
            ],
            '', '', '',
        ])
        data.append([
            Paragraph('Accused\'s signature', styles['Normal']),
            Paragraph('This may be signed by the accused’s lawyer or, if the accused is a corporation, made in accordance with the Criminal Procedure Act 2004 section 154(1).', styles['Normal']),
            '', '', '',
        ])
        data.append([
            '',
            '',
            '',
            Paragraph('Date', styles['Normal']),
            '',
        ])
        data.append([
            Paragraph('Court address', styles['Normal']),
            [
                Paragraph('Send this document to:', styles['Normal']),
                Spacer(0, 2*mm),
                Paragraph('at:', styles['Normal']),
                Spacer(0, 2 * mm),
            ],
            '', '', '',
        ])
        tbl_main_p2 = Table(data, style=tbl_style_p2, colWidths=col_width_p2, )

        ###
        # 3rd page
        ###
        header_small_text_p3 = ParagraphOffeset('Copy to be attached to accused copy of prosecution notice',
                                                styles['Right'],
                                                x_offset=-3*mm, y_offset=0)

        ###
        # 4th page
        ###
        # Same as 2nd page

        ###
        # 5th page
        ###
        header_small_text_p5 = ParagraphOffeset('Return of service copy',
                                                styles['Right'],
                                                x_offset=-3*mm, y_offset=0)

        ###
        # 6th page
        ###

        gap_between_tables = 1.5*mm
        odd_page = []
        odd_page.append(tbl_head)
        odd_page.append(tbl_accused_details)
        odd_page.append(Spacer(0, gap_between_tables))
        odd_page.append(tbl_hearing_details)
        odd_page.append(Spacer(0, gap_between_tables))
        odd_page.append(tbl_notice_to_accused)
        odd_page.append(Spacer(0, gap_between_tables))
        odd_page.append(tbl_issuing_details)
        odd_page.append(Spacer(0, gap_between_tables))
        odd_page.append(tbl_service_details)
        even_page = []
        even_page.append(tbl_head_p2)
        even_page.append(tbl_accused_details)
        even_page.append(Spacer(0, gap_between_tables))
        even_page.append(tbl_main_p2)

        # 1st page
        elements.append(header_small_text_p1)
        elements += odd_page
        elements.append(PageBreak())
        # 2nd page
        elements += even_page
        elements.append(PageBreak())
        # 3rd page
        elements.append(header_small_text_p3)
        elements += odd_page
        elements.append(PageBreak())
        # 4th page
        elements += even_page
        elements.append(PageBreak())
        # 5th page
        elements.append(header_small_text_p5)
        elements += odd_page
        elements.append(PageBreak())
        # 6th page
        elements += even_page

    doc.build(elements)
    return invoice_buffer

def create_court_hearing_notice_pdf_bytes(filename, legal_case):
    with BytesIO() as invoice_buffer:
        _create_pdf(invoice_buffer, legal_case)

        # # Get the value of the BytesIO buffer
        # value = invoice_buffer.getvalue()
        #
        # # START: Save the pdf file to the database
        # document = legal_case.documents.create(name=filename)
        # path = default_storage.save('wildlifecompliance/{}/{}/documents/{}'.format(legal_case._meta.model_name, legal_case.id, filename), invoice_buffer)
        # document._file = path
        # document.save()
        # invoice_buffer.close()
        # return document
    invoice_buffer.seek(0)

    response = HttpResponse(invoice_buffer, content_type='application/pdf')
    response['Content-Disposition'] = 'attachment; filename="{}"'.format(filename)
    return response


import os
import numpy as np
import pandas as pd
from datetime import datetime as dt
import logging
import csv
import time

from telemanom.helpers import Config
from telemanom.errors import Errors
import telemanom.helpers as helpers
from telemanom.channel import Channel
from telemanom.modeling import Model
from telemanom.find_hp import FindHP
from pathlib import Path
from functools import reduce

logger = helpers.setup_logging()

def secondsToStr(t):
    return "%dh:%02dm:%02ds.%d" % \
           reduce(lambda ll, b: divmod(ll[0], b) + ll[1:],
                  [(t * 1000,), 1000, 60, 60])

def write_csv(first_part_path, row, col_header):
    path = first_part_path+"_ms.csv"
    csv_file = Path(path)
    if csv_file.is_file():
        with open(path, 'a', newline='') as filedata:
            writer = csv.DictWriter(filedata, delimiter=',', fieldnames=col_header)
            writer.writerow(row)
    else:
        with open(path, 'a', newline='') as filedata:
            writer = csv.DictWriter(filedata, delimiter=',', fieldnames=col_header)
            writer.writeheader()
            writer.writerow(row)

    for key in row:
        if key == "model":
            continue
        else:
            row[key] = secondsToStr(float(row[key]))

    path = first_part_path+".csv"
    csv_file = Path(path)
    if csv_file.is_file():
        with open(path, 'a', newline='') as filedata:
            writer = csv.DictWriter(filedata, delimiter=',', fieldnames=col_header)
            writer.writerow(row)
    else:
        with open(path, 'a', newline='') as filedata:
            writer = csv.DictWriter(filedata, delimiter=',', fieldnames=col_header)
            writer.writeheader()
            writer.writerow(row)

class Detector:
    def __init__(self, labels_path=None, result_path='results/',
                 config_path='config.yaml'):
        """
        Top-level class for running anomaly detection over a group of channels
        with values stored in .npy files. Also evaluates performance against a
        set of labels if provided.

        Args:
            labels_path (str): path to .csv containing labeled anomaly ranges
                for group of channels to be processed
            result_path (str): directory indicating where to stick result .csv
            config_path (str): path to config.yaml

        Attributes:
            labels_path (str): see Args
            results (list of dicts): holds dicts of results for each channel
            result_df (dataframe): results converted to pandas dataframe
            chan_df (dataframe): holds all channel information from labels .csv
            result_tracker (dict): if labels provided, holds results throughout
                processing for logging
            config (obj):  Channel class object containing train/test data
                for X,y for a single channel
            y_hat (arr): predicted channel values
            id (str): datetime id for tracking different runs
            result_path (str): see Args
        """

        self.labels_path = labels_path
        self.results = []
        self.result_df = None
        self.chan_df = None

        self.precision = None
        self.recall = None

        self.result_tracker = {
            'true_positives': 0,
            'false_positives': 0,
            'false_negatives': 0,
            'true_negatives': 0
        }

        self.config = Config(config_path)
        self.y_hat = None

        # trains new models
        if self.config.execution == "train" or self.config.execution == "train_and_predict":
            if self.config.use_id != "":
                self.id = self.config.use_id
            else:
                architecture = self.config.model_architecture
                name = self.config.name
                self.id = "{}_{}_{}".format(architecture, name, dt.now().strftime('%Y-%m-%d_%H.%M.%S'))

        # load existing models or predictions
        if self.config.execution == "predict" or self.config.execution == "search_p":
            self.id = self.config.use_id

        if self.config.execution == "find_hp":
            architecture = self.config.model_architecture
            name = self.config.name
            self.id = "{}_{}_{}".format(architecture, name, dt.now().strftime('%Y-%m-%d_%H.%M.%S'))

        helpers.make_dirs(self.id)

        # add logging FileHandler based on ID
        hdlr = logging.FileHandler('data/logs/%s.log' % self.id)
        formatter = logging.Formatter('%(asctime)s %(levelname)s %(message)s')
        hdlr.setFormatter(formatter)
        logger.addHandler(hdlr)

        self.result_path = result_path

        if self.labels_path:
            self.chan_df = pd.read_csv(labels_path)
        else:
            chan_ids = [x.split('.')[0] for x in os.listdir('data/test/')]
            self.chan_df = pd.DataFrame({"chan_id": chan_ids})

        logger.info("{} channels found for processing."
                    .format(len(self.chan_df)))

    def evaluate_sequences(self, errors, label_row):
        """
        Compare identified anomalous sequences with labeled anomalous sequences.

        Args:
            errors (obj): Errors class object containing detected anomaly
                sequences for a channel
            label_row (pandas Series): Contains labels and true anomaly details
                for a channel

        Returns:
            result_row (dict): anomaly detection accuracy and results
        """

        result_row = {
            'false_positives': 0,
            'false_negatives': 0,
            'true_positives': 0,
            'fp_sequences': [],
            'tp_sequences': [],
            'num_true_anoms': 0
        }

        matched_true_seqs = []

        label_row['anomaly_sequences'] = eval(label_row['anomaly_sequences'])
        result_row['num_true_anoms'] += len(label_row['anomaly_sequences'])
        result_row['scores'] = errors.anom_scores

        if len(errors.E_seq) == 0:
            result_row['false_negatives'] = result_row['num_true_anoms']

        else:
            true_indices_grouped = [list(range(e[0], e[1]+1)) for e in label_row['anomaly_sequences']]
            true_indices_flat = set([i for group in true_indices_grouped for i in group])

            for e_seq in errors.E_seq:
                i_anom_predicted = set(range(e_seq[0], e_seq[1]+1))

                matched_indices = list(i_anom_predicted & true_indices_flat)
                valid = True if len(matched_indices) > 0 else False

                if valid:

                    result_row['tp_sequences'].append(e_seq)

                    true_seq_index = [i for i in range(len(true_indices_grouped)) if
                                      len(np.intersect1d(list(i_anom_predicted), true_indices_grouped[i])) > 0]

                    if not true_seq_index[0] in matched_true_seqs:
                        matched_true_seqs.append(true_seq_index[0])
                        result_row['true_positives'] += 1

                else:
                    result_row['fp_sequences'].append([e_seq[0], e_seq[1]])
                    result_row['false_positives'] += 1

            result_row["false_negatives"] = len(np.delete(label_row['anomaly_sequences'],
                                                          matched_true_seqs, axis=0))

        if self.config.execution != "search_p":
            logger.info('Channel Stats: TP: {}  FP: {}  FN: {}'.format(result_row['true_positives'],
                                                                   result_row['false_positives'],
                                                                   result_row['false_negatives']))

        for key, value in result_row.items():
            if key in self.result_tracker:
                self.result_tracker[key] += result_row[key]

        return result_row

    def log_final_stats(self):
        """
        Log final stats at end of experiment.
        """
        if self.config.execution == "search_p":
            logger.info('P value: {}'.format(self.config.p))

        if self.labels_path:

            logger.info('Final Totals:')
            logger.info('-----------------')
            logger.info('True Positives: {}'
                        .format(self.result_tracker['true_positives']))
            logger.info('False Positives: {}'
                        .format(self.result_tracker['false_positives']))
            logger.info('False Negatives: {}'
                        .format(self.result_tracker['false_negatives']))
            try:
                self.precision = float(self.result_tracker['true_positives']) / (float(self.result_tracker['true_positives'] + self.result_tracker['false_positives']))
                self.recall = float(self.result_tracker['true_positives']) / (float(self.result_tracker['true_positives'] + self.result_tracker['false_negatives']))

                self.f1 = 2*((self.precision*self.recall)/(self.precision+self.recall))

                #calcola f1 score e scrivi nel file di log

                logger.info('Precision: {0:.2f}'.format(self.precision))
                logger.info('Recall: {0:.2f}'.format(self.recall))
                logger.info('F1 Score: {0:.2f}\n'.format(self.f1))
            except ZeroDivisionError:

                logger.info('Precision: NaN')
                logger.info('Recall: NaN')
                logger.info('F1 Score: NaN\n')

        else:
            logger.info('Final Totals:')
            logger.info('-----------------')
            logger.info('Total channel sets evaluated: {}'
                        .format(len(self.result_df)))
            logger.info('Total anomalies found: {}'
                        .format(self.result_df['n_predicted_anoms'].sum()))
            logger.info('Avg normalized prediction error: {}'
                        .format(self.result_df['normalized_pred_error'].mean()))
            logger.info('Total number of values evaluated: {}\n'
                        .format(self.result_df['num_test_values'].sum()))

    def execute_detection(self):
        col_header = ["model", "total_elapsed_time"]
        training_times_row = {
            'model': self.id,
            'total_elapsed_time': 0
        }

        execution_times_row = {
            'model': self.id,
            'total_elapsed_time': 0
        }

        training_total_elapsed_time = 0
        training_start_time = 0
        training_end_time = 0

        execution_total_elapsed_time = 0
        execution_start_time = 0
        execution_end_time = 0

        if self.config.execution == "train":
            filename = "./data/{}/losses.csv".format(self.id)
            if os.path.isfile(filename):
                losses_df = pd.read_csv(filename)
            else:
                losses_df = pd.DataFrame()
                losses_df["Channel"] = self.chan_df["chan_id"]

            train_loss = []
            validation_loss = []

            path = './data/{}/models/seeds.log'.format(self.id)
            seed_file = Path(path)
            if seed_file.is_file():
                os.remove(path)

        for i, row in self.chan_df.iterrows():
            if self.config.execution != "search_p" and self.config.execution != "find_hp":
                logger.info('Stream # {}: {}'.format(i + 1, row.chan_id))

            channel = Channel(self.config, row.chan_id)
            channel.load_data()

            if self.config.execution == "train":
                model = Model(self.config, self.id, channel)
                train_loss.append(model.history.history["loss"][-1])
                validation_loss.append(model.history.history["val_loss"][-1])
                continue

            elif self.config.execution == "find_hp":
                training_start_time = time.time()
                tuner = FindHP(self.id, channel, self.config, self.config.model_architecture)
                training_end_time = (time.time() - training_start_time)

                f = open('hp/{}/times.log'.format(self.id), "a")
                f.write("{} {}\n".format(row.chan_id, training_end_time))
                f.close()

                col_header.append(row.chan_id)
                training_times_row[row.chan_id] = training_end_time

                training_total_elapsed_time += training_end_time

                training_start_time = 0
                training_end_time = 0
                continue

            elif self.config.execution == "train_and_predict" or self.config.execution == "predict":
                if self.config.execution == "train_and_predict":
                    training_start_time = time.time()
                    execution_start_time = training_start_time

                model = Model(self.config, self.id, channel)

                if self.config.execution == "train_and_predict":
                    training_end_time = (time.time() - training_start_time)

                    col_header.append(row.chan_id)
                    training_times_row[row.chan_id] = training_end_time

                    training_total_elapsed_time += training_end_time

                    training_start_time = 0
                    training_end_time = 0

                channel = model.batch_predict(channel)

            elif self.config.execution == "search_p":
                channel.y_hat = np.load(os.path.join('data', self.id, 'y_hat',
                                                     '{}.npy'
                                                     .format(channel.id)))

            errors = Errors(channel, self.config, self.id)
            errors.process_batches(channel)
            if self.config.execution == "search_p":
                result_row = {
                    'run_id': self.id+"_{}".format(str(self.config.p)),
                    'chan_id': row.chan_id,
                    'num_train_values': len(channel.X_train)+len(channel.X_valid),
                    'num_test_values': len(channel.X_test),
                    'n_predicted_anoms': len(errors.E_seq),
                    'normalized_pred_error': errors.normalized,
                    'anom_scores': errors.anom_scores
                }
            else:
                result_row = {
                    'run_id': self.id,
                    'chan_id': row.chan_id,
                    'num_train_values': len(channel.X_train) + len(channel.X_valid),
                    'num_test_values': len(channel.X_test),
                    'n_predicted_anoms': len(errors.E_seq),
                    'normalized_pred_error': errors.normalized,
                    'anom_scores': errors.anom_scores
                }

            if self.labels_path:
                result_row = {**result_row,
                              **self.evaluate_sequences(errors, row)}
                result_row['spacecraft'] = row['spacecraft']
                result_row['anomaly_sequences'] = row['anomaly_sequences']
                result_row['class'] = row['class']
                self.results.append(result_row)

                if self.config.execution != "search_p":
                    logger.info('Total true positives: {}'
                                .format(self.result_tracker['true_positives']))
                    logger.info('Total false positives: {}'
                                .format(self.result_tracker['false_positives']))
                    logger.info('Total false negatives: {}'
                                .format(self.result_tracker['false_negatives']))

            else:
                result_row['anomaly_sequences'] = errors.E_seq
                self.results.append(result_row)

                if self.config.execution != "search_p":
                    logger.info('{} anomalies found'
                                .format(result_row['n_predicted_anoms']))
                    logger.info('anomaly sequences start/end indices: {}'
                                .format(result_row['anomaly_sequences']))
                    logger.info('number of test values: {}'
                                .format(result_row['num_test_values']))
                    logger.info('anomaly scores: {}\n'
                                .format(result_row['anom_scores']))

            if self.config.execution != "search_p":
                self.result_df = pd.DataFrame(self.results)
                self.result_df.to_csv(
                    os.path.join(self.result_path, '{}.csv'.format(self.id)),
                    index=False)

            if self.config.execution == "train_and_predict":
                execution_end_time = (time.time() - execution_start_time)
                execution_times_row[row.chan_id] = execution_end_time
                execution_total_elapsed_time += execution_end_time

                execution_start_time = 0
                execution_end_time = 0

        if self.config.execution == "train":
            columns = list(losses_df.columns)
            columns_number=1
            for elem in columns:
                if "train" in elem:
                    columns_number+=1

            losses_df["train_loss_"+str(columns_number)] = train_loss
            losses_df["valid_loss_"+str(columns_number)] = validation_loss

            losses_df.to_csv('./data/{}/losses.csv'.format(self.id), sep=',', index=False)

        if self.config.execution != "train" and self.config.execution != "find_hp":
            self.log_final_stats()

        if self.config.execution == "find_hp":
            first_part_path = "./hp/hp_times".format(self.id)
            training_times_row["total_elapsed_time"] = training_total_elapsed_time
            write_csv(first_part_path, training_times_row, col_header)

        if self.config.execution == "train_and_predict":

            training_times_row["total_elapsed_time"] = training_total_elapsed_time
            execution_times_row["total_elapsed_time"] = execution_total_elapsed_time

            write_csv("./results/training_times", training_times_row, col_header)
            write_csv("./results/execution_times", execution_times_row, col_header)

    def run(self):
        """
        Initiate processing for all channels.
        """
        logger.info("Execution mode: {}\n".format(self.config.execution))

        if self.config.execution == "search_p":
            # header for csv file
            col_header = ["P", "Precision", "Recall", "Total True Positives", "Total False Positives", "Total False Negatives"]

            df = pd.DataFrame(columns=col_header)

            # creates the array of values for p
            array = np.linspace(0.00, 1, 100).tolist()
            formatted_array = [round(elem, 2) for elem in array]

            i=0
            for elem in formatted_array:
                self.config.p = elem

                self.execute_detection()

                row = [self.config.p, self.precision, self.recall, self.result_tracker['true_positives'],
                       self.result_tracker['false_positives'], self.result_tracker['false_negatives']]

                df.loc[i] = row
                i += 1

                self.result_tracker = {
                    'true_positives': 0,
                    'false_positives': 0,
                    'false_negatives': 0
                }
            df.to_csv('./data/{}/p_values.csv'.format(self.id), sep=',')

        else:
            self.execute_detection()


import os.path
import numpy as np
import itertools
import Tools
from pyquaternion import Quaternion

# mult, multvec, inverse, conjugate, normalize rot2quat, quat2rot , norm
def flattenQuat(l):
    return(np.array([list(x) for x in l]).reshape(4*len(l)))

def flattenRot(l):
    return(np.array([list(x) for x in l]).reshape(9*len(l)))

# q and -q are representing the same rotation.
# So there is an ambiguity for the tests.
# We force the real part of be positive.
def mkQuaternion(mat):
    q=Quaternion(matrix=mat)
    if q.scalar < 0:
        return(-q)
    else:
        return(q)

def writeTests(config,format):
    NBSAMPLES=128

    a=[Quaternion.random() for x in range(NBSAMPLES)]
    b=[Quaternion.random() for x in range(NBSAMPLES)]

    config.writeInput(1, flattenQuat(a))
    config.writeInput(2, flattenQuat(b))

    normTest = [x.norm for x in a]
    config.writeReference(1, normTest)

    inverseTest = [x.inverse for x in a]
    config.writeReference(2, flattenQuat(inverseTest))

    conjugateTest = [x.conjugate for x in a]
    config.writeReference(3, flattenQuat(conjugateTest))

    normalizeTest = [x.normalised for x in a]
    config.writeReference(4, flattenQuat(normalizeTest))

    multTest = [a[i] * b[i] for i in range(NBSAMPLES)]
    config.writeReference(5, flattenQuat(multTest))

    quat2RotTest = [x.rotation_matrix for x in a]
    config.writeReference(6, flattenRot(quat2RotTest))

    config.writeInput(7, flattenRot(quat2RotTest))
    rot2QuatTest = [mkQuaternion(x) for x in quat2RotTest]
    config.writeReference(7, flattenQuat(rot2QuatTest))

def generatePatterns():
    PATTERNDIR = os.path.join("Patterns","DSP","QuaternionMaths","QuaternionMaths")
    PARAMDIR = os.path.join("Parameters","DSP","QuaternionMaths","QuaternionMaths")

    configf32=Tools.Config(PATTERNDIR,PARAMDIR,"f32")
    configf16=Tools.Config(PATTERNDIR,PARAMDIR,"f16")

    writeTests(configf32,0)
    writeTests(configf16,16)

    # Params just as example
    someLists=[[1,3,5],[1,3,5],[1,3,5]]

    r=np.array([element for element in itertools.product(*someLists)])
    configf32.writeParam(1, r.reshape(81))

if __name__ == '__main__':
  generatePatterns()


from django.shortcuts import render
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import serializers

class Encoder(APIView):

    def get(self, request):
        number = self.request.query_params['NumToEncode']
        numberInt = int(number)

        # Add 8192 to the value.
        translated_number = numberInt + 8192

        # Encoding requires to form two bytes from the value.
        # Most significant bit of each byte has to be cleared. In binary: bits 1 to 0
        # Using & operator that compares 1 to 1 return 0
        firstByte = translated_number & 0x007F
        secondByte = translated_number & 0xFF80

        # In binary second_byte bits are shifted to the left by 1 places inserting a 0
        shiftedSecondByte = secondByte << 1
        encodedValue = firstByte + shiftedSecondByte

        # Format the two bytes as a hexadecimal string and return it as key.
        key = hex(encodedValue)[2:]
        print(key)
        return Response({'key': key})

class Decoder(APIView):

    def get(self, request):
        s1 = self.request.query_params['Num1T0Decode']
        s2 = self.request.query_params['Num2ToDecode']

        firstNumberToDecode = int(s1, 16)
        SeconNumberToDecode = int(s2, 16)

        # Return bits shifted to the left by 7 places inserting 0
        # If f_byte is 7f which in binary is 1111111, gives 11111110000000
        # This gives back a 14-bit range number
        ShiftedFirstNumberToDecode = firstNumberToDecode << 7

        decodedValue = (ShiftedFirstNumberToDecode + SeconNumberToDecode) - 8192
        key = decodedValue
        print(key)
        return Response({'key': key})


import argparse
import os
import sys

#krun --directory src/stf  -cPGM="`cat test/semantics/basic_routing/basic_routing.p4`" -pPGM="kast --directory src/ -o kore" -cSTF="`cat src/x.stf`" -pSTF="kast -s STFPgm -m STF-TEST-SYNTAX --directory src/stf -o kore"  --save-temps --verbose
def run_cli(args):
    command = """krun                                                 \\
     --directory src/cli                                                \\
     -cPGM="`cat {p4}`"                                                 \\
     -pPGM="kast -s P4Program -m P4-SYNTAX --directory src/cli -o kore" \\
     -cCLI="`cat {cli}`"                                                \\
     -pCLI="kast -s CLIPgm -m CLI-SYNTAX --directory src/cli -o kore"   \\
     {debugger} {args}                                                 \\
      """
    command = command.format(
        p4=args.p4,
        cli=args.cli,
        debugger="--debugger" if args.debugger else "",
        args=args.krun_args
    )
    print(command, file=sys.stderr)
    os.system(command)

def search_cli(args):
    command = """krun                                                 \\
     --directory src/cli                                                \\
     -cPGM="`cat {p4}`"                                                 \\
     -pPGM="kast -s P4Program -m P4-SYNTAX --directory src/cli -o kore" \\
     -cCLI="`cat {cli}`"                                                \\
     -pCLI="kast -s CLIPgm -m CLI-SYMBOLIC-SYNTAX --directory src/cli -o kore"   \\
      {args}                                                 \\
      """
    command = command.format(
        p4=args.p4,
        cli=args.cli,
        args=args.krun_args
    )
    print(command, file=sys.stderr)
    os.system(command)

def p4assert(args):
    command = """krun                                                 \\
     --directory src/p4assert                                                \\
     -cPGM="`cat {p4}`"                                                 \\
     -pPGM="kast -s P4Program -m P4ASSERT-SYNTAX --directory src/p4assert -o kore" \\
     -cCLI="`cat {cli}`"                                                \\
     -pCLI="kast -s CLIPgm -m CLI-SYMBOLIC-SYNTAX --directory src/p4assert -o kore"   \\
      {args}                                                 \\
      """
    command = command.format(
        p4=args.p4,
        cli=args.cli,
        args=args.krun_args
    )
    print(command, file=sys.stderr)
    os.system(command)

if __name__ == "__main__":
    parser = argparse.ArgumentParser(prog='p4k')
    parser.add_argument('--krun-args', type=str, help='Additional arguments to be passed to krun', default="--verbose --save-temps")
    subparsers = parser.add_subparsers(dest='command')

    parser_run_cli = subparsers.add_parser('run-cli', help='Runs P4 code with CLI file')
    parser_run_cli.add_argument('p4', type=str, help='P4 file')
    parser_run_cli.add_argument('cli', type=str, help='CLI file')
    parser_run_cli.add_argument('--debugger', action='store_true', help='Run in debugger mode', default=False)

    parser_search_cli = subparsers.add_parser('search-cli', help='Symbolically run P4 code with CLI file')
    parser_search_cli.add_argument('p4', type=str, help='P4 file')
    parser_search_cli.add_argument('cli', type=str, help='CLI file')

    parser_p4assert = subparsers.add_parser('p4assert', help='P4 assert')
    parser_p4assert.add_argument('p4', type=str, help='P4 file')
    parser_p4assert.add_argument('cli', type=str, help='CLI file')

    args = parser.parse_args()
    if args.command == 'run-cli':
        run_cli(args)
    if args.command == 'search-cli':
        search_cli(args)
    if args.command == 'p4assert':
        p4assert(args)


import os
from lxml import etree
from io import StringIO
import codecs

__location__ = os.path.realpath(os.path.join(os.getcwd(), os.path.dirname(__file__)))

filename = __location__ + "/html/allcameras.html"

file = codecs.open(filename, 'r', 'utf-8')

content = file.read()
file.close()

parser =etree.HTMLParser()

page = etree.parse(StringIO(content), parser).getroot()

cameras = page.xpath('//div[contains(@class, "pane")]/table//tr/td/table')

print("Found %s cameras" % len(cameras))

for camera in cameras:
    rows = camera.xpath('.//tr')
    # print("%s rows" % len(rows))

    url = rows[1].xpath('.//a')[0].get('href')

    print('Url: %s' % url)


from flask import Flask, request, jsonify
app = Flask(__name__)

languages = [{'name' : 'javascript'},{'name' : 'python'}]
@app.route('/test', methods=['GET'])
def returnAll():
  return jsonify({'languages' : languages})

@app.route('/test', methods=['POST'])
def addOne():
  language = {'name' : request.json['name']}
  languages.append(language)
  return jsonify({'languages' : languages})

if __name__ == '__main__':
  app.run(host='0.0.0.0', port=8000)


# coding: utf-8
import pytest

from contextlib import contextmanager

@contextmanager
def assert_raises(exception_class, msg=None):
    """Check that an exception is raised and its message contains `msg`."""
    with pytest.raises(exception_class) as exception:
        yield
    if msg is not None:
        message = "%s" % exception
        assert msg.lower() in message.lower()


#!/usr/bin/env python
# coding=utf-8
"""
Author: Deean
Date: 2022-02-11 23:49:14
LastEditTime: 2022-02-11 23:55:39
Description:
FilePath: 2001.可互换矩形的组数.py
"""
#
# @lc app=leetcode.cn id=2001 lang=python3
#
# [2001] 可互换矩形的组数
#

# @lc code=start
from typing import List
from math import gcd
from collections import defaultdict

class Solution:
    def interchangeableRectangles(self, rectangles: List[List[int]]) -> int:
        counts = defaultdict(int)
        for item in rectangles:
            counts[(item[0]//gcd(*item), item[1]//gcd(*item))] += 1
        count = 0
        for item in filter(lambda el: el > 1, counts.values()):
            count += item * (item - 1)
        return count // 2
# @lc code=end


import numpy as np
from scipy.stats import pearsonr, spearmanr
import src.data_preprocessing.utils as utils
import pandas as pd
import numpy.testing as nptest

def test_assign_continents():
    continents = utils.assign_continents()
    assert continents.loc['Russia', 'continent'] == 'Europe'
    assert continents.loc['Kazakhstan', 'continent'] == 'Asia'
    assert continents.loc['Czechia', 'continent'] == 'Europe'

def test_get_continents():
    print(utils.get_continents())

class TestComputeDependencyMatrix:

    def test_compute_pearson_dependency(self):
        X = np.arange(0, 10)
        Y = X * 2 + 1
        metrics = pd.DataFrame(data=np.c_[X, Y])
        nptest.assert_almost_equal(np.array([[1.0, 1], [0, 1]]),
                                   utils.compute_dependency_matrix(metrics, pearsonr), decimal=1)

    def test_compute_spearmanr_dependency(self):
        X = np.arange(0, 10)
        Y = X * 2 + 1
        metrics = pd.DataFrame(data=np.c_[X, Y])
        nptest.assert_almost_equal(np.array([[1.0, 1], [0, 1]]),
                                   utils.compute_dependency_matrix(metrics, spearmanr), decimal=1)


from StandardWienerProcess import *
import matplotlib.pyplot as plt
from Rating import drift, diffusion, Model
#%%
# Setup for Wiener Process
Tn = 100
N = 10000
nW = 1
Ns = 5

T, W, dW = StandardWienerProcess(Tn,N,nW,Ns,seed=None)

p = [1,0.05]   # Parameter
x0 = [0.1]        # Initial State

#%%
from Rating import drift, diffusion, Model
from DormandPrince54 import Solve

p = [1,0.5,1,0]
x0 = 0.2
h0 = 0.1
abstol = 10**(-6)
reltol = 10**(-6)
tspan = [0, 10]

T,X = Solve(Model, tspan, x0, h0, abstol, reltol, args=(p,))

plt.plot(T,X)
#plt.axhline(0)
#plt.axhline(p)

#%%

# SDE solve using the EulerMaruyama ExplicitExplicit
from EulerMaruyamaExplicitExplicit import Solve
X = Solve(drift,diffusion,T,x0,W,args=(p,))

plt.figure(1)

for i in range(Ns):
# We unpack each state
    plt.plot(T,X[:,0,i])

#%%

x = np.linspace(0,10,1000)

plt.plot(x,diffusion(x, x, p))

#%%


import json
from pathlib import Path

icons = json.loads(Path('icons.json').read_text())
recipe_data = json.load(open('recipes.json'))

icons_created = []

target_items = ['LOGISTIC_SCIENCE_PACK']

def create_recipe(target_items, recipe_data, nodes, diagram):
    for item in target_items:
        if item not in recipe_data:
            return
        nodes[item] = f"{item}((  ))"
        for ingredient in recipe_data[item]:
            nodes[
                ingredient] = f"{ingredient}((  ))"
            try:
                diagram[item].append(ingredient)
            except KeyError:
                diagram[item] = [
                    ingredient,
                ]
            create_recipe([
                ingredient,
            ], recipe_data, nodes, diagram)

nodes = {}
diagram = {}

target_items = [
    'LOGISTIC_SCIENCE_PACK', 'AUTOMATION_SCIENCE_PACK',
    'MILITARY_SCIENCE_PACK', 'CHEMICAL_SCIENCE_PACK',
    'PRODUCTION_SCIENCE_PACK', 'UTILITY_SCIENCE_PACK', 'ROCKET_SILO'
]
# target_items = [
#     'ROCKET_SILO',
# ]

create_recipe(target_items, recipe_data, nodes, diagram)

with open('factorio.md', 'w') as f:
    f.write('```mermaid\n')
    f.write('graph TD\n\n')

    for node in nodes.values():
        f.write(f"{node}\n")

    f.write('\n\n')

    for product, ingredients in diagram.items():
        for ingredient in set(ingredients):
            f.write(f"{ingredient:50} --> {product}\n")

    f.write('\n\n\n```\n')


"""This is the main convolutional neural network that's used by the agent
   both in RLlib and the non-distributed variant."""
import tensorflow as tf
from tensorflow.keras.models import Sequential, Model
from tensorflow.keras.layers import Dense, Flatten, Permute, Input
from tensorflow.keras.layers import Conv2D
from tensorflow.keras.activations import relu, linear
from ray.rllib.models.tf.tf_modelv2 import TFModelV2

def create_dqn_model(num_actions):
    """Just creates the model and returns it, and is used by the agent to
       create the prediction and target networks."""
    return Sequential([
        Permute((2, 3, 1)),
        Conv2D(32, 8, strides=4, activation=relu),
        Conv2D(64, 4, strides=2, activation=relu),
        Conv2D(64, 3, strides=1, activation=relu),

        Flatten(),
        Dense(512, activation=relu),
        Dense(num_actions, activation=linear),
    ])

class DQNRLlibModel(TFModelV2):
    """This is the same model as above for RLlib. It requires the class to implement
       some API which is needed for RLlib to generate the graph."""
    def __init__(self, obs_space, action_space, num_outputs, model_config, name):
        super().__init__(obs_space, action_space, num_outputs, model_config, name)
        inputs = Input(obs_space.shape)
        cnn1 = Conv2D(32, 8, strides=4, activation=relu)(inputs)
        cnn2 = Conv2D(64, 4, strides=2, activation=relu)(cnn1)
        cnn3 = Conv2D(64, 3, strides=1, activation=relu)(cnn2)
        flatten = Flatten()(cnn3)
        fnn1 = Dense(512, activation=relu)(flatten)
        fnn2 = Dense(num_outputs, activation=linear)(fnn1)
        value_out = Dense(1, activation=None)(fnn2)
        self.base_model = Model(inputs, [fnn2, value_out])
        self.register_variables(self.base_model.variables)

    def forward(self, input_dict, state, seq_lens):
        model_out, self._value_out = self.base_model(input_dict['obs'])
        return model_out, state

    def value_function(self):
        return tf.reshape(self._value_out, [-1])

    def import_from_h5(self, h5_file: str) -> None:
        self.base_model.load_weights(h5_file)


from models.credit_card import Card
from models.person import Person
from flask import request, jsonify
from app import app, db

@app.route('/card/<id>', methods=['GET'])
def get_card(id):
    card = Card.query.get(id)

    result = {
        'id': card.id,
        'person_cpf': card.person_cpf,
        'card_number': card.card_number,
        'card_company': card.card_company,
        'limit': card.limit,
        'card_statement': card.card_statement
    }

    return jsonify(result)

@app.route('/card', methods=['POST'])
def insert_card():
    person_cpf = request.json['person_cpf']
    card_number = request.json['card_number']
    card_company = request.json['card_company']
    limit = request.json['limit']
    card_statement = request.json['card_statement']

    card = Card(person_cpf, card_number, card_company, limit, card_statement)
    db.session.add(card)
    db.session.commit()

    return "Cartão inserido com sucesso!"

@app.route('/card', methods=['PUT'])
def update_card():

    id = request.json['id']

    card = Card.query.get(id)

    card.person_cpf = request.json['person_cpf']
    card.card_number = request.json['card_number']
    card.card_company = request.json['card_company']
    card.limit = request.json['limit']
    card.card_statement = request.json['card_statement']

    db.session.commit()

    return "Cartão atualizado com sucesso!"

@app.route('/card/<id>', methods=['DELETE'])
def delete_card(id):
    card = Card.query.get(id)

    db.session.delete(card)
    db.session.commit()

    return "Cartão deletado com sucesso!"

@app.route('/person/card/<person_cpf>', methods=['GET'])
def get_person_cards(person_cpf):
    person = Person.query.get(person_cpf)

    cards = person_cards(person.cards)

    return jsonify(cards)

def person_cards(cards):
    result = []

    for card in cards:
        data = {}

        data['id'] = card.id
        data['person_cpf'] = card.person_cpf
        data['card_number'] = card.card_number
        data['card_company'] = card.card_company
        data['limit'] = card.limit
        data['card_statement'] = card.card_statement

        result.append(data)
    return result


import flask
import wtforms
from flask.ext import wtf

from main import app
import auth
import config
import model
import util
import task
import views.public
import json
from google.appengine.ext import ndb
from google.appengine.datastore.datastore_query import Cursor
from werkzeug import exceptions, routing

###############################################################################
# Sitemap
###############################################################################

@app.route('/sitemap.xml')
def sitemap():
  resp_model = {}
  resp_model['pages'] = []
  fetch_home(resp_model)
  fetch_stories(resp_model)
  fetch_about(resp_model)
  fetch_contact(resp_model)
  response = flask.make_response(flask.render_template(
      'share/sitemap/sitemap.xml',
      model = resp_model,
      lastmod=config.CURRENT_VERSION_DATE.strftime('%Y-%m-%d'),
  ))
  response.headers['Content-Type'] = 'application/xml'
  return response

def fetch_about(resp_model):
  about = model.ModuleConfig.get_by('module_id', 'about-page')
  sitemap_item = module_to_sitemap_item(about, 'about')
  sitemap_item['priority'] = '0.2'
  resp_model['pages'].append(sitemap_item)

def fetch_contact(resp_model):
  about = model.ModuleConfig.get_by('module_id', 'contact-page')
  sitemap_item = module_to_sitemap_item(about, 'contact')
  sitemap_item['priority'] = '0.2'
  resp_model['pages'].append(sitemap_item)

def fetch_home(resp_model):
  about = model.ModuleConfig.get_by('module_id', 'home-page')
  sitemap_item = module_to_sitemap_item(about, 'home')
  sitemap_item['priority'] = '1'
  resp_model['pages'].append(sitemap_item)

def fetch_stories(resp_model):
  story_dbs = model.Story.query().filter(
      model.Story.story_item_count > 0).fetch()
  for story_db in story_dbs :
    story = story_to_sitemap(story_db)
    resp_model['pages'].append(story)

def story_to_sitemap(story):
  sitemap = {}
  sitemap['url'] = flask.url_for('story', story_key=util.story_key(story), _external=True)
  sitemap['lastmod'] = story.modified.strftime('%Y-%m-%d')
  sitemap['priority'] = '0.7'
  return sitemap

def module_to_sitemap_item(module, route_name):
  sitemap = {}
  sitemap['url'] = flask.url_for(route_name, _external=True)
  sitemap['lastmod'] = module.modified.strftime('%Y-%m-%d')
  sitemap['priority'] = '0.5'
  return sitemap


import brownie
import pytest
from brownie.test import given, strategy
from conftest import MAX_UINT256

pytestmark = pytest.mark.usefixtures("mint_alice", "approve_alice")

def test_simple_add(alice, swap):
    swap.addLiquidity([1e3, 1e3],1e3 , MAX_UINT256, {"from": alice})

@pytest.mark.parametrize("min_amount", [0, 2 * 10 ** 18])
def test_initial(
    chain, alice, swap, coins, liquidity, min_amount, decimals, n_coins, initial_amounts
):
    amounts = [10 ** i for i in decimals]

    swap.addLiquidity(amounts, min_amount, chain.time() + 60, {"from": alice})

    for coin, amount, initial in zip(coins, amounts, initial_amounts):
        assert coin.balanceOf(alice) == initial - amount
        assert coin.balanceOf(swap) == amount

    assert liquidity.balanceOf(alice) == n_coins * 10 ** 18
    assert liquidity.totalSupply() == n_coins * 10 ** 18

@given(idx=strategy('uint', min_value=0, max_value=1))
def test_initial_liquidity_missing_coin(chain, alice, swap, liquidity, idx, decimals):
    amounts = [10 ** i for i in decimals]
    amounts[idx] = 0

    with brownie.reverts():
        swap.addLiquidity(amounts, 0, chain.time() + 60, {"from": alice})


# first step is to import the libraries
import requests
from bs4 import BeautifulSoup
import csv
from itertools import zip_longest

# second step is to get the url and save it in a variable
result = requests.get(
    "https://wuzzuf.net/search/jobs/?q=frontend&a=hpb")

# third step is to parse the html code and save it in a variable
src = result.content
# print(src)

# fourth step is to create a soup object
soup = BeautifulSoup(src, 'lxml')
# print(soup.prettify())

# fifth step is to get the elements that we want to scrap
# job title , job skills ,company name , job location , job description

# job title
job_titles = soup.find_all('h2', class_='css-m604qf')
# print(job_titles)

# company name
company_names = soup.find_all('a', class_='css-17s97q8')

# job location
job_locations = soup.find_all('span', class_='css-5wys0k')

# job description
# job_descriptions = soup.find_all('div', class_='css-y4udm8')

# job skills
job_skills = soup.find_all('div', class_="css-y4udm8")
# print(job_skills)

# sixth step is to get text from the elements
# job title
job_titles_text = []
for job_title in job_titles:
    job_titles_text.append(job_title.text)
print(job_titles_text)

# company name
company_names_text = []
for company_name in company_names:
    company_names_text.append(company_name.text)
print(company_names_text)

# job location
job_locations_text = []
for job_location in job_locations:
    job_locations_text.append(job_location.text)
print(job_locations_text)

# job description
# job_descriptions_text = []
# for job_description in job_descriptions:
#     job_descriptions_text.append(job_description.text)
# print(job_descriptions_text)

# job skills
job_skills_text = []
for job_skill in job_skills:
    job_skills_text.append(job_skill.text)
print(job_skills_text)

# seventh step is to save the data in a csv file
d = [job_titles_text, company_names_text,
     job_locations_text, job_skills_text]
export_data = zip_longest(*d, fillvalue='')
with open('G:\web scraping/job.csv', 'w', encoding="ISO-8859-1", newline='') as myfile:
    wr = csv.writer(myfile)
    wr.writerow(("job title", "company name",
                 "job location", "job skills"))
    wr.writerows(export_data)
# myfile.close()
# illustarte the above code
# d is array of arrays that contains the data
# export_data is a variable that contains the data in a zip format
# with open is a function that creates a csv file and save the data in it
# w is a parameter that means write
# encoding is a parameter that means the encoding of the file
# newline is a parameter that means the new line
# wr is a variable that contains the csv writer
# wr.writerow is a function that writes the first row in the csv file
# wr.writerows is a function that writes the rest of the rows in the csv file
# myfile.close() is a function that closes the csv file

# eighth step is to save the data in a json file