import sys
import os
import imghdr
from PyQt5.QtWidgets import QApplication, QMainWindow, QAction
from PyQt5.QtWidgets import QWidget, QDesktopWidget, QMessageBox
from PyQt5.QtWidgets import QHBoxLayout, QVBoxLayout, QGridLayout
from PyQt5.QtWidgets import QGroupBox, QPushButton, QSlider
from PyQt5.QtWidgets import QLabel, QFileDialog, QSizePolicy, QSpacerItem
from PyQt5.QtGui import QIcon, QDrag, QPixmap, QImage
from PyQt5.QtCore import Qt, pyqtSignal
from timelapse_processing import ImageList, Image, loadImage, toRGB

"""
QApplication: manages application object.
QWidget: base class of all user interface objects. Receives events from the window system.
QMainWindow: main application window - framework to build the apps' user interface.
QDesktopWidget: provides access to user screen information.
"""

class DropButton(QPushButton):
    """
    Drag n Drop area widget
    """
    itemDropped = pyqtSignal(list)

    def __init__(self, title, width, height, parent):
        super().__init__(title, parent)
        self.setVisible(True)
        self.setAcceptDrops(True)
        self.setStyleSheet("background-color: rgba(85, 153, 255, 10%);"
                           "border-style: dashed;"
                           "border-width: 1px;"
                           "border-color: gray;"
                           "color: gray;")
        self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        self.setMinimumSize(width, height)

    def dragEnterEvent(self, e):
        m = e.mimeData()
        if m.hasUrls():
            e.accept()
        else:
            e.ignore()

    def dropEvent(self, e):
        m = e.mimeData()
        if m.hasUrls():
            e.accept()
            links = []
            [links.append(u.toLocalFile()) for u in m.urls()]
            self.itemDropped.emit(links)
            self.setVisible(False)
        else:
            e.ignore()

class TimelapseApp(QMainWindow):
    """
    Timelapse exposure fix application window
    """
    def __init__(self):
        super().__init__()
        self.title = 'Timelapse Exposure Fix'
        self.icon = 'camera_icon.png'
        self.left = 100
        self.top = 100
        self.width = 640
        self.height = 480
        self.minSize = 100
        self.imgScale = 0.45
        self.origImages = ImageList()
        self.processedImages = ImageList()
        self.imageFormat = ''
        self.initUI()

    def initUI(self):
        # Menu bar
        mainMenu = self.menuBar()
        self.fileMenu = mainMenu.addMenu('File')
        reloadAct = QAction('New Session', self)
        reloadAct.setShortcut('Ctrl+R')
        reloadAct.triggered.connect(self.reloadSession)
        reloadAct.setStatusTip('Reload a new session for timelapse processing')
        self.fileMenu.addAction(reloadAct)
        saveAct = QAction('Save Images', self)
        saveAct.setShortcut('Ctrl+S')
        saveAct.triggered.connect(self.saveImages)
        saveAct.setStatusTip('Save processed images')
        self.fileMenu.addAction(saveAct)
        saveAct.setDisabled(True)
        exitAct = QAction('Exit', self)
        exitAct.setShortcut('Ctrl+Q')
        exitAct.triggered.connect(self.close)
        exitAct.setStatusTip('Exit timelapse processing tool')
        self.fileMenu.addAction(exitAct)
        helpMenu = mainMenu.addMenu('Help')
        aboutAct = QAction('Drag n Drop', self)
        aboutAct.triggered.connect(self.helpWindow)
        aboutAct.setStatusTip('Drag n Drop information')
        helpMenu.addAction(aboutAct)

        # Grid layout
        self.createGridLayout()
        self.dragndrop.itemDropped.connect(self.pictureDropped)

        # Status bar
        self.statusBar()
        self.statusBar().setStyleSheet("background-color: white;")

        # Window settings
        self.setWindowTitle(self.title)
        self.setGeometry(self.left, self.top, self.width, self.height)
        self.setWindowIcon(QIcon(self.icon))
        self.center()
        self.show()

    def createGridLayout(self):
        self.centralWidget = QWidget(self)
        self.centralWidget.setStyleSheet("background-color: white;")
        self.centralWidget.setStatusTip('Ready')
        self.setCentralWidget(self.centralWidget)

        self.sld = QSlider(Qt.Horizontal, self)

        mainLayout = QHBoxLayout()
        vLayout = QVBoxLayout()
        grid = QGridLayout()
        grid.setSpacing(25)
        grid.setContentsMargins(25, 25, 25, 25)

        self.dragndrop = DropButton('Drop images here', self.width - self.minSize, self.minSize, self)
        grid.addWidget(self.dragndrop, 0, 0, 1, 4)

        self.viewerGroupBox = QGroupBox('Time-lapse viewer')
        self.img1 = QLabel(self.centralWidget)
        self.img1.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        self.img1.setMinimumSize(self.minSize, self.minSize)

        self.img2 = QLabel(self.centralWidget)
        self.img2.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        self.img2.setMinimumSize(self.minSize, self.minSize)

        imgviewer = QHBoxLayout()
        leftSpacer = QSpacerItem(self.minSize/10, self.minSize, QSizePolicy.Expanding, QSizePolicy.Minimum)
        imgviewer.addSpacerItem(leftSpacer)
        imgviewer.addWidget(self.img1)
        imgviewer.addWidget(self.img2)
        rightSpacer = QSpacerItem(self.minSize/10, self.minSize, QSizePolicy.Expanding, QSizePolicy.Minimum)
        imgviewer.addSpacerItem(rightSpacer)
        self.viewerGroupBox.setLayout(imgviewer)
        self.viewerGroupBox.setVisible(False)

        grid.addWidget(self.viewerGroupBox, 2, 1)

        grid.addWidget(self.sld, 3, 1)
        self.sld.setValue(0)
        self.sld.setRange(0,0)
        self.sld.valueChanged.connect(self.updateViewerIndex)
        self.sld.setVisible(False)

        # Encapsulate grid layout in VBox and HBox
        vLayout.addLayout(grid)
        verticalSpacer = QSpacerItem(self.minSize, 20, QSizePolicy.Minimum, QSizePolicy.Expanding)
        vLayout.addItem(verticalSpacer)
        hLeftSpacer = QSpacerItem(self.minSize/10, self.minSize, QSizePolicy.Expanding, QSizePolicy.Minimum)
        mainLayout.addItem(hLeftSpacer)
        mainLayout.addLayout(vLayout)
        hRightSpacer = QSpacerItem(self.minSize/10, self.minSize, QSizePolicy.Expanding, QSizePolicy.Minimum)
        mainLayout.addItem(hRightSpacer)
        self.centralWidget.setLayout(mainLayout)

    def updateViewerIndex(self):
        self.updateViewer(self.sld.value())

    def updateViewer(self, imageNumber):
        if len(self.origImages) > 0:
            rgb = toRGB(self.origImages[imageNumber].img)
            qimage = QImage(rgb, rgb.shape[1], rgb.shape[0], QImage.Format_RGB888)
            pixmap1 = QPixmap(qimage)
            pixmap1 = pixmap1.scaledToWidth(self.width * self.imgScale)
            self.img1.setPixmap(pixmap1)

        if len(self.processedImages) > 0:
            rgb = toRGB(self.processedImages[imageNumber].img)
            qimage = QImage(rgb, rgb.shape[1], rgb.shape[0], QImage.Format_RGB888)
            pixmap2 = QPixmap(qimage)
            pixmap2 = pixmap2.scaledToWidth(self.width * self.imgScale)
            self.img2.setPixmap(pixmap2)

    def pictureDropped(self, links):
        self.statusBar().showMessage('Processing...')
        self.imageFormat = imghdr.what(links[0])
        [self.origImages.append(Image(loadImage(link))) for link in links]
        newImages = ImageList(self.origImages[:])
        newImages.computeStats()
        newImages.fixExposure()
        self.processedImages = newImages

        self.fileMenu.actions()[1].setDisabled(False)

        self.updateViewer(0)
        self.sld.setRange(0, len(self.origImages) - 1)
        self.sld.setValue(0)
        self.statusBar().showMessage('Ready')

        self.viewerGroupBox.setVisible(True)
        self.sld.setVisible(True)

    def saveImages(self):
        self.statusBar().showMessage('Saving Images...')
        newDir = '/processed-images'
        destDir = QFileDialog.getExistingDirectory(self, "Select Directory") + newDir
        if not os.path.exists(destDir):
            os.makedirs(destDir)
        for i,obj in enumerate(self.processedImages):
            rgb = toRGB(obj.img)
            qimage = QImage(rgb, rgb.shape[1], rgb.shape[0], QImage.Format_RGB888)
            qimage.save(destDir + '/processed_image' + str(i+1).zfill(4) + '.' + self.imageFormat)
        self.statusBar().showMessage('Ready')

    def reloadSession(self):
        mboxtitle = 'Warning'
        mboxmsg = 'Are you sure you want to start a new session?\nAll unsaved changes will be lost.'
        reply = QMessageBox.warning(self, mboxtitle, mboxmsg,
                                    QMessageBox.Yes | QMessageBox.No, QMessageBox.No)
        if reply == QMessageBox.Yes:
            del self.origImages[:]
            del self.processedImages[:]
            self.img1.clear()
            self.img2.clear()
            self.sld.setValue(0)
            self.sld.setRange(0,0)
            self.dragndrop.setVisible(True)
            self.viewerGroupBox.setVisible(False)
            self.sld.setVisible(False)

    def helpWindow(self):
        mboxtitle = 'Help'
        mboxmsg = ('If your time-lapse is not displaying in the proper order, or there seems to be a jump '
        'cut to previous frames, make sure the last item clicked when the images were dragged was '
        'the first image of your sequence. The order of selection is preserved during drag and drop.')

        reply = QMessageBox.information(self, mboxtitle, mboxmsg,
                                        QMessageBox.Ok, QMessageBox.Ok)

    def center(self):
        qtRectangle = self.frameGeometry()
        centerPoint = QDesktopWidget().availableGeometry().center()
        qtRectangle.moveCenter(centerPoint)
        self.move(qtRectangle.topLeft())

    def closeEvent(self, event):
        mboxtitle = 'Message'
        mboxmsg = 'Are you sure you want to quit?'
        reply = QMessageBox.warning(self, mboxtitle, mboxmsg,
                                    QMessageBox.Yes | QMessageBox.No, QMessageBox.No)
        if reply == QMessageBox.Yes:
            event.accept()
        else:
            event.ignore()

if __name__ == '__main__':
    app = QApplication(sys.argv)
    w = TimelapseApp()
    sys.exit(app.exec_())


# Тестики
import pytest
from Project import combination, if_possible, choice_deck, step_success, install_auto_mod, best_consistent_exchange

def test_choice_deck():
    """Проверка наличия всех карт в коллоде."""
    deck = choice_deck()
    card1 = {'color': 'П', 'value': 'К'}
    card2 = {'color': 'П', 'value': '9'}
    choice_deck()
    assert card1 in deck and card2 in deck

def test_combination():
    """Проверка исправной работы комбинаций."""
    card1 = {'color': '♣', 'value': 'Т'}
    card2 = {'color': '♢', 'value': 'Т'}
    combination(card1, card2)
    assert combination(card1, card2)
    card1 = {'color': '♣', 'value': 'Т'}
    card2 = {'color': '♣', 'value': '7'}
    combination(card1, card2)
    assert combination(card1, card2)
    card1 = {'color': '♢', 'value': 'Т'}
    card2 = {'color': '♣', 'value': '7'}
    assert not combination(card1, card2)

def test_if_possible():
    """Проверка корректной работы прыжков."""
    num_stack = 4
    list_stack = [{'color': '♢', 'value': '9'}, {'color': '♣', 'value': '7'}, {'color': '♢', 'value': 'К'}]
    if_possible(list_stack, num_stack)
    assert not if_possible(list_stack, num_stack)

def test_step_success_test():
    """
    Проверка корректного добавления первой карты из коллоды
    на стол и не подмешал дубляжа (Без мошенничества со стороны крупье :) ).
    """
    list_stack = [{'color': 'К', 'value': '10'}, {'color': 'П', 'value': 'Т'}]
    deck = [{'color': 'Б', 'value': 'Д'}, {'color': 'П', 'value': '9'}, {'color': 'Б', 'value': 'К'},
            {'color': 'Б', 'value': '9'}, {'color': 'Ч', 'value': 'Д'}, {'color': 'Ч', 'value': 'К'},
            {'color': 'Ч', 'value': '9'}, {'color': 'Б', 'value': 'В'}, {'color': 'П', 'value': 'В'},
            {'color': 'Б', 'value': '10'}, {'color': 'Б', 'value': '8'}, {'color': 'П', 'value': 'К'},
            {'color': 'Ч', 'value': '7'}, {'color': 'К', 'value': 'Д'}, ...]
    D = deck[0]
    step_success(list_stack, deck)
    assert D in list_stack and not deck[0] in list_stack

def test_best_consistent_exchange():
    """Проверка, что при использовании подкрученной колоды ваш результат будет лучше."""
    deck = choice_deck()
    res = len(install_auto_mod(deck))
    colod = len(install_auto_mod(best_consistent_exchange(deck)))
    assert colod < res


import random

handvalues = []
handsymbols = []
valuecomparisons = []
prozent = []
realProbability = [0.000154, 0.00139, 0.0240, 0.1441, 0.1965, 0.3925, 2.1128, 4.7539, 42.2569, 50.1177]
statistic = {
    "Royal Flush": 0,
    "Straight Flush": 0,
    "Flush": 0,
    "Four of a Kind": 0,
    "Full House": 0,
    "Straight": 0,
    "Three of a Kind": 0,
    "Two pairs": 0,
    "Pair": 0,
    "High Card": 0
}

def getsymbol(numbers):
    numbers %= 4
    if numbers == 0:
        return "Heart"
    if numbers == 1:
        return "Club"
    if numbers == 2:
        return "Diamond"
    if numbers == 3:
        return "Spade"

def getcardnumber(number):
    #geht von 0 bis 12 dann 13 bis 25 ergibt auch wieder 0 bis 12 usw. 4Mal da karo,piek,...
    number %= 13
    return number

def getcards(minimum, maximum, amount):
    cards = []
    for g in range(minimum, maximum + 1):
        cards.append(g)
    for j in range(amount):
        randindex = random.randrange(0, maximum)

        lastPosition = len(cards) - 1 - j
        cards[randindex], cards[lastPosition] = cards[lastPosition], cards[randindex]
    return cards[-amount:]

def checkforpairs(values):
    duplicates = [number for number in values if values.count(number) > 1]
    uniques = list(set(duplicates))
    return len(duplicates), uniques

def checkforcombos(symbols, values):
    combo = False
    if symbols.count(symbols[0]) == len(symbols):
        symbols.sort()
        if values[0] == values[-1] - 4 and values[-1] == 12:
            statistic["Royal Flush"] += 1
            combo = True
        elif values[0] == values[-1] - 4:
            statistic["Straight Flush"] += 1
            combo = True
        elif not combo:
            statistic["Flush"] += 1
    if checkforpairs(values)[0] == 4 and len(checkforpairs(values)[1]) == 1:
        statistic["Four of a Kind"] += 1
        combo = True
    elif checkforpairs(values)[0] == 5 and len(checkforpairs(values)[1]) >= 2:
        statistic["Full House"] += 1
        combo = True
    elif checkforpairs(values)[0] == 3:
        statistic["Three of a Kind"] += 1
        combo = True
    elif checkforpairs(values)[0] == 4 and len(checkforpairs(values)[1]) >= 2:
        statistic["Two pairs"] += 1
        combo = True
    elif checkforpairs(values)[0] == 2:
        statistic["Pair"] += 1
        combo = True
    values.sort()
    if values[0] == values[-1] - 4 and len(checkforpairs(values)[1]) == 0:
        statistic["Straight"] += 1
        combo = True
    if not combo:
        statistic["High Card"] += 1
def valuecomparison():
    for f in range (10):
        valuecomparisons.append(((prozent[f] - realProbability[f]) / realProbability[f]))
if __name__ == "__main__":
    x = input("How many rounds?")
    x = int(x)
    for x in range(x):
        myCards = getcards(1, 52, 5)
        for i in myCards:
            handvalues.append(getcardnumber(i))
            handsymbols.append(getsymbol(i))
        checkforcombos(handsymbols, handvalues)
        handvalues = []
        handsymbols = []

    for i in statistic:
         a = statistic[i] / x * 100
         prozent.append(a)
    valuecomparison()
    print("Berechnete Wahrscheinlichkeiten:\n",prozent)
    print("Differenz zwischen Berechneten Wslktn und tatsächlichen Wslktn in Prozent:\n",valuecomparisons)


from graph_tool.all import Graph,Vertex,graph_draw,radial_tree_layout
from GN0.alpha_zero.MCTS_cached import MCTS as MCTS_old,Node,Leafnode,upper_confidence_bound
from GN0.alpha_zero.MCTS import MCTS
from GN0.alpha_zero.NN_interface import NNetWrapper
from graph_game.shannon_node_switching_game import Node_switching_game
from graph_game.graph_tools_games import get_graph_only_hex_game,Hex_game
import numpy as np
from typing import Union
import os
import time
from GN0.models import get_pre_defined
from argparse import Namespace
from graph_game.graph_tools_hashing import get_unique_hash
import torch

def dummy_nn(game:Node_switching_game):
    moves = game.get_actions()
    prob = np.array(list(range(len(moves))),dtype=float)+1
    prob/=np.sum(prob)
    value = 0.7 if len(moves)%2==0 else 0.3
    return moves,torch.from_numpy(prob),torch.tensor([value])

def graph_state(game,prob=None):
    if prob is None:
        prior_map = None
    else:
        prior_map = game.view.new_vertex_property("double")
        for i,vertex in enumerate(game.get_actions()):
            prior_map[vertex] = prob[i]
    os.system("pkill -f 'mupdf node_state.pdf'")
    game.draw_me(fname="node_state.pdf",vprop1=prior_map,decimal_places=3)
    os.system("nohup mupdf node_state.pdf > /dev/null 2>&1 &")

def graph_node(node:Node,prob=None):
    if prob is None:
        prob = node.priors
    game = Node_switching_game.from_graph(node.storage)
    prior_map = game.view.new_vertex_property("double")
    for vertex in game.get_actions():
        prior_map[vertex] = prob[list(node.moves).index(vertex)]

    os.system("pkill -f 'mupdf node_state.pdf'")
    game.draw_me(fname="node_state.pdf",vprop1=prior_map,decimal_places=3)
    os.system("nohup mupdf node_state.pdf > /dev/null 2>&1 &")

def graph_from_hash_mcts(mcts:MCTS,root:Node_switching_game,to_show="num_visits",last_hash=int):
    def recursive_add(state:Graph,cur_vertex:Vertex):
        game.set_to_graph(Graph(state))
        s = get_unique_hash(game.view)
        if s not in mcts.Ps:
            return
        actions = game.get_actions()
        if s in mcts.Qsa:
            ucb_many = mcts.Qsa[s] + mcts.cpuct * mcts.Ps[s] * np.sqrt(mcts.Ns[s]) / (1 + mcts.Nsa[s])
        else:
            ucb_many = 0.5 + mcts.cpuct * mcts.Ps[s] * np.sqrt(mcts.Ns[s])
        nsa = mcts.Nsa[s] if s in mcts.Nsa else np.zeros_like(mcts.Ps[s])
        qsa = mcts.Qsa[s] if s in mcts.Qsa else np.ones_like(mcts.Ps[s])*0.5
        for ucb,prior,visits,q,action in zip(ucb_many,mcts.Ps[s],nsa,qsa,game.get_actions()):
            game.set_to_graph(Graph(state))
            game.make_move(action)
            new_state = Graph(game.graph)
            new_s = get_unique_hash(game.view)
            v = g.add_vertex()
            g.add_edge(cur_vertex,v)
            color[v] = "blue" if state.gp["m"] else "red"
            if to_show=="num_visits":
                text[v] = str(visits)
            elif to_show == "q":
                text[v] = f"{q:.2f}"[1:] if q<1 else "1"
            elif to_show == "prior":
                text[v] = f"{prior:.2f}"
            elif to_show == "m":
                text[v] = str(action)
            elif to_show=="numbers":
                text[v] = str(int(v))
            elif to_show=="ucb":
                text[v] = f"{float(ucb):.2f}"

            number_to_state[int(v)] = new_state
            if last_hash==new_s:
                halo_color[v] = [0,1,0,0.5]
                weather_halo[v] = True
            else:
                weather_halo[v] = False
                halo_color[v] = [0,0,0,0]
            if new_s in mcts.Ps:
                shape[v] = "circle"
                recursive_add(new_state,v)
            else:
                shape[v] = "square"

    state = Graph(root.graph)
    game = root

    number_to_state = {}
    g = Graph(directed=True)
    color = g.new_vertex_property("string")
    shape = g.new_vertex_property("string")
    text = g.new_vertex_property("string")
    size = g.new_vertex_property("int")
    pen_width = g.new_vertex_property("int")
    halo_color = g.new_vertex_property("vector<double>")
    weather_halo = g.new_vertex_property("bool")
    halo_size = g.new_vertex_property("double")

    g.vp.l = halo_size
    g.vp.h = halo_color
    g.vp.g = size
    g.vp.c = color
    g.vp.s = shape
    g.vp.t = text
    g.vp.p = pen_width
    g.vp.b = weather_halo

    root_hash = get_unique_hash(game.view)
    number_to_state[0] = Graph(state)

    v = g.add_vertex()
    halo_color[v] = [0,0,0,0]
    if root_hash==last_hash:
        halo_color[v] = [0,1,0,0.5]
        weather_halo[v] = True

    recursive_add(state,v)

    halo_size.a = 1.1
    makerturn = state.gp["m"]
    color[v] = "red" if makerturn else "blue"
    shape[v] = "circle" if root_hash in mcts.Ps else "square"
    text[v] = ""
    size.a = 25
    return g,number_to_state

def graph_from_root(root:Union[Node,Leafnode],to_show="num_visits",last_node=None):
    def recursive_add(cur_node:Node,cur_vertex:Vertex):
        ucb = upper_confidence_bound(cur_node,1)
        for tv,child,q,visits,one_ucb,prior in zip(cur_node.total_value,cur_node.children,cur_node.Q,cur_node.visits,ucb,cur_node.priors):
            v = g.add_vertex()
            g.add_edge(cur_vertex,v)
            color[v] = "blue" if cur_node.storage.gp["m"] else "red"
            if to_show=="num_visits":
                text[v] = str(visits)
            elif to_show == "q":
                text[v] = f"{q:.2f}"[1:] if q<1 else "1"
            elif to_show == "value":
                if isinstance(child,Node):
                    text[v] = f"{tv:.2f}"
                else:
                    text[v] = child.value
            elif to_show == "prior":
                text[v] = f"{prior:.2f}"
            elif to_show == "m":
                if isinstance(child,Node):
                    text[v] = ""
                else:
                    text[v] = "" if child.move is None else child.move
            elif to_show=="numbers":
                text[v] = str(int(v))
            elif to_show=="ucb":
                text[v] = f"{float(one_ucb):.2f}"

            number_to_node[int(v)] = child
            if last_node is not None and last_node==child:
                halo_color[v] = [0,1,0,0.5]
                weather_halo[v] = True
            else:
                weather_halo[v] = False
                halo_color[v] = [0,0,0,0]
            if isinstance(child,Node):
                shape[v] = "circle"
                recursive_add(child,v)
            else:
                shape[v] = "square"

    number_to_node = {}
    g = Graph(directed=True)
    color = g.new_vertex_property("string")
    shape = g.new_vertex_property("string")
    text = g.new_vertex_property("string")
    size = g.new_vertex_property("int")
    pen_width = g.new_vertex_property("int")
    halo_color = g.new_vertex_property("vector<double>")
    weather_halo = g.new_vertex_property("bool")
    halo_size = g.new_vertex_property("double")

    g.vp.l = halo_size
    g.vp.h = halo_color
    g.vp.g = size
    g.vp.c = color
    g.vp.s = shape
    g.vp.t = text
    g.vp.p = pen_width
    g.vp.b = weather_halo

    v = g.add_vertex()
    halo_color[v] = [0,0,0,0]
    if root==last_node:
        halo_color[v] = [0,1,0,0.5]
        weather_halo[v] = True
    if isinstance(root,Node):
        recursive_add(root,v)

    halo_size.a = 1.1
    makerturn = root.makerturn if isinstance(root,Leafnode) else root.storage.gp["m"]
    color[v] = "red" if makerturn else "blue"
    shape[v] = "square" if isinstance(root,Leafnode) else "circle"
    text[v] = ""
    size.a = 25
    return g,number_to_node

def visualize_MCTS(new_version=True):
    print("""
Instructions:
n: Node number          v: number of visits
q: Q-values             t: Total Values
m: moves                p: Priors
u: ucb                  r: get result
c: select best child for next iteration
[number]: show graph for number.
          """)
    size = 2
    game = get_graph_only_hex_game(size)
    show_game = Hex_game(size)
    # nn = get_pre_defined_mcts_model("misty-firebrand-26/11")
    nnet = get_pre_defined("policy_value",args=Namespace(**{"hidden_channels":25,"num_layers":8,"head_layers":2}))
    nn = NNetWrapper(nnet=nnet)

    if new_version:
        mcts = MCTS(game.copy(),dummy_nn,args=Namespace(cpuct=1),remove_dead_and_captured=False)
        last_hash = get_unique_hash(game.view)
    else:
        mcts = MCTS_old(game,nn.predict_for_mcts,remove_dead_captured=False)
        last_node = mcts.root
    mode = "num_visits"
    while 1:
        if new_version:
            g,number_to_state = graph_from_hash_mcts(mcts,game.copy(),to_show=mode,last_hash=last_hash)
        else:
            g,number_to_node = graph_from_root(mcts.root,to_show=mode,last_node=last_node)
        graph_draw(g,radial_tree_layout(g,g.vertex(0)),vprops={"halo_size":g.vp.l,"halo":g.vp.b,"halo_color":g.vp.h,"pen_width":g.vp.p,"shape":g.vp.s,"fill_color":g.vp.c,"text":g.vp.t,"size":g.vp.g},bg_color="black",output="mcts.pdf")
        os.system("pkill -f 'mupdf mcts.pdf'")
        os.system("nohup mupdf mcts.pdf > /dev/null 2>&1 &")
        time.sleep(0.1)
        os.system("bspc node -f west")
        while 1:
            command = input()
            if command=="n":
                mode = "numbers"
                break
            elif command=="v":
                mode = "num_visits"
                break
            elif command=="q":
                mode = "q"
                break
            elif command=="t":
                mode = "value"
                break
            elif command=="c":
                if new_version:
                    moves,probs = mcts.extract_result(Graph(game.graph),temp=0)
                else:
                    moves,probs = mcts.extract_result(0)
                action = moves[np.argmax(probs)]
                child = mcts.root.children[np.argmax(probs)]
                if isinstance(child,Leafnode):
                    print("Failed, child is leafnode")
                else:
                    mcts.next_iter_with_child(action,child.storage)
                    break

            elif command=="m":
                mode = "m"
                break
            elif command=="p":
                mode = "prior"
                break
            elif command=="u":
                mode = "ucb"
                break
            elif command=="r":
                if new_version:
                    moves,probs = mcts.extract_result(Graph(game.graph),temp=0)
                    graph_state(game.copy(),probs)
                else:
                    moves,probs = mcts.extract_result(0)
                    graph_node(mcts.root,probs)
                print(moves,probs)

            elif command=="":
                if new_version:
                    value = mcts.single_iteration(Graph(game.graph))
                    g = Node_switching_game.from_graph(mcts.leaf_graph)
                    s = get_unique_hash(g.view)
                    if s in mcts.Ps:
                        graph_state(g,mcts.Ps[s])
                    else:
                        graph_state(g)
                    last_hash = s
                else:
                    leaf,value = mcts.single_iteration()
                    if isinstance(leaf,Node):
                        graph_node(leaf)
                    if mcts.done:
                        print(mcts.extract_result(1))
                        print("MCTS is done")
                print(f"got value {value}")
                break
            else:
                if new_version:
                    state = number_to_state[int(command)]
                    g = Node_switching_game.from_graph(state)
                    graph_state(g,mcts.Ps[get_unique_hash(g.view)])
                else:
                    if int(command)==0:
                        node = mcts.root
                    else:
                        node = number_to_node[int(command)]
                    if isinstance(node,Node):
                        show_game.set_to_graph(node.storage)
                        show_game.draw_me(fname="uff.pdf")
                        os.system("nohup mupdf uff.pdf > /dev/null 2>&1 &")
                        time.sleep(0.1)
                        os.system("bspc node -f west")
                    nd = node.__dict__.copy()
                    del nd["parent"]
                    del nd["children"]

if __name__=="__main__":
    visualize_MCTS()


from numpy import ndarray as array, tanh, dot
import numpy as np

class Layer:

    N: int
    v: float
    weights: array

    def __init__(self, N: int, v=1.0):
        self.N = N
        self.v = v

        # initial random weight values
        self.weights = np.random.uniform(size=N)

        # weights normalization
        weights_length = np.sqrt(np.sum(self.weights ** 2))
        self.weights /= weights_length


# -*- coding: utf-8 -*-
'''
Functions used for CLI argument handling
'''
from __future__ import absolute_import

# Import python libs
import re
import inspect

# Import salt libs
from salt.ext.six import string_types, integer_types
import salt.ext.six as six

#KWARG_REGEX = re.compile(r'^([^\d\W][\w.-]*)=(?!=)(.*)$', re.UNICODE)  # python 3
KWARG_REGEX = re.compile(r'^([^\d\W][\w.-]*)=(?!=)(.*)$')

def condition_input(args, kwargs):
    '''
    Return a single arg structure for the publisher to safely use
    '''
    ret = []
    for arg in args:
        if isinstance(arg, long):
            ret.append(str(arg))
        else:
            ret.append(arg)
    if isinstance(kwargs, dict) and kwargs:
        kw_ = {'__kwarg__': True}
        for key, val in six.iteritems(kwargs):
            kw_[key] = val
        return ret + [kw_]
    return ret

def parse_input(args, condition=True):
    '''
    Parse out the args and kwargs from a list of input values. Optionally,
    return the args and kwargs without passing them to condition_input().

    Don't pull args with key=val apart if it has a newline in it.
    '''
    _args = []
    _kwargs = {}
    for arg in args:
        if isinstance(arg, string_types):
            arg_name, arg_value = parse_kwarg(arg)
            if arg_name:
                _kwargs[arg_name] = yamlify_arg(arg_value)
            else:
                _args.append(yamlify_arg(arg))
        elif isinstance(arg, dict):
            # Yes, we're popping this key off and adding it back if
            # condition_input is called below, but this is the only way to
            # gracefully handle both CLI and API input.
            if arg.pop('__kwarg__', False) is True:
                _kwargs.update(arg)
            else:
                _args.append(arg)
        else:
            _args.append(arg)
    if condition:
        return condition_input(_args, _kwargs)
    return _args, _kwargs

def parse_kwarg(string_):
    '''
    Parses the string and looks for the following kwarg format:

    "{argument name}={argument value}"

    For example: "my_message=Hello world"

    Returns the kwarg name and value, or (None, None) if the regex was not
    matched.
    '''
    try:
        return KWARG_REGEX.match(string_).groups()
    except AttributeError:
        return None, None

def yamlify_arg(arg):
    '''
    yaml.safe_load the arg
    '''
    if not isinstance(arg, string_types):
        return arg

    if arg.strip() == '':
        # Because YAML loads empty strings as None, we return the original string
        # >>> import yaml
        # >>> yaml.load('') is None
        # True
        # >>> yaml.load('      ') is None
        # True
        return arg

    elif '_' in arg and all([x in '0123456789_' for x in arg.strip()]):
        return arg

    try:
        # Explicit late import to avoid circular import. DO NOT MOVE THIS.
        import salt.utils.yamlloader as yamlloader
        original_arg = arg
        if '#' in arg:
            # Only yamlify if it parses into a non-string type, to prevent
            # loss of content due to # as comment character
            parsed_arg = yamlloader.load(arg, Loader=yamlloader.SaltYamlSafeLoader)
            if isinstance(parsed_arg, string_types) or parsed_arg is None:
                return arg
            return parsed_arg
        if arg == 'None':
            arg = None
        else:
            arg = yamlloader.load(arg, Loader=yamlloader.SaltYamlSafeLoader)

        if isinstance(arg, dict):
            # dicts must be wrapped in curly braces
            if (isinstance(original_arg, string_types) and
                    not original_arg.startswith('{')):
                return original_arg
            else:
                return arg

        elif arg is None \
                or isinstance(arg, (list, float, integer_types, string_types)):
            # yaml.safe_load will load '|' as '', don't let it do that.
            if arg == '' and original_arg in ('|',):
                return original_arg
            # yaml.safe_load will treat '#' as a comment, so a value of '#'
            # will become None. Keep this value from being stomped as well.
            elif arg is None and original_arg.strip().startswith('#'):
                return original_arg
            else:
                return arg
        else:
            # we don't support this type
            return original_arg
    except Exception:
        # In case anything goes wrong...
        return original_arg

def get_function_argspec(func):
    '''
    A small wrapper around getargspec that also supports callable classes
    '''
    if not callable(func):
        raise TypeError('{0} is not a callable'.format(func))

    if inspect.isfunction(func):
        aspec = inspect.getargspec(func)
    elif inspect.ismethod(func):
        aspec = inspect.getargspec(func)
        del aspec.args[0]  # self
    elif isinstance(func, object):
        aspec = inspect.getargspec(func.__call__)
        del aspec.args[0]  # self
    else:
        raise TypeError('Cannot inspect argument list for {0!r}'.format(func))

    return aspec


# # # # # # # #ДЕКОРАТОРЫ
# # # # # # #
# # # # # # # from datetime import datetime
# # # # # # #
# # # # # # # def time(function):
# # # # # # #     def wrapper():
# # # # # # #         start = datetime.now()
# # # # # # #         function()
# # # # # # #         end = datetime.now() - start
# # # # # # #         print(end)
# # # # # # #     return wrapper
# # # # # # #
# # # # # # # @time
# # # # # # # def function1():
# # # # # # #
# # # # # # #     lists = []
# # # # # # #     for i in range(1,10000):
# # # # # # #         lists.append(i)
# # # # # # #     return lists
# # # # # # #
# # # # # # # @time
# # # # # # # def function2():
# # # # # # #     lists = [x for x in range(1,10000)]
# # # # # # #     return lists
# # # # # # #
# # # # # # # function1()
# # # # # # # function2()
# # # # # #
# # # # # #
# # # # # #
# # # # # def humburger(cotlet):
# # # # #     def wrapper(*args, **kwargs):
# # # # #         print("Upper bread")
# # # # #         cotlet(*args, **kwargs)
# # # # #         print("Down bread")
# # # # #     return wrapper
# # # # # #
# # # # # @humburger
# # # # # def cotlet(ingridient):
# # # # #     print(f'Cotleta by {ingridient}' )
# # # # #
# # # # # cotlet("chicken")
# # # #
# # # #
# # # # lists = ['Kyal', 'Saikal', 'Meerim', 'Isko']
# # # # print(f'S-{lists[1]} M-{lists[2]}')
# # # # print("{0} {2} {1} {3}".format(lists[1], lists[3], lists[0], lists[2]))
# # #
# # #
# # # name = {
# # #         'name': 'Vika',
# # #         'age': 18+4,
# # #        }
# # # a = name.pop('name')
# # # name.update({'name': "Eldar"})
# # # print(name)
# # # #print(a)
# # import math
# #
# # print(pow(3, 2)) #возвидение в корни
# # print(math.sqrt(4))
#
#
# number = int(input("Any number for factorial function: "))
#
# def fact(s):
#     count = 1
#     for i in range(1, s+1):
#         count *= i
#     return count
# print(fact(number))

a = int(input('A side of bisictrisa: '))
b = int(input('B side of bisictrisa: '))


minutos=int(input('Minutos: '))
if minutos < 200:
    Tminutos = 0.2
elif minutos <= 400:
    Tminutos= 0.18
elif minutos <= 800:
        Tminutos = 0.15
else:
        Tminutos= 0.08
print("conta a ser paga : R$ %6.2f " % (minutos * Tminutos))
    ### o util do ELIF é que ele nao precisa de identação, igual o if


import datetime

import gym
import numpy as np
from gym import spaces, error
from gym import utils
from gym.utils import seeding
from entity.time_window import time_window
from tool.kuhn_munkras import kuhn_munkras

class MatchEnv(gym.Env):
    def __init__(self, max_car_num=30, max_lp_num=300, time_district_num=12, max_time_window_length=10):
        self.max_time_window_length = max_time_window_length
        self.action_spaces = spaces.Discrete(self.max_time_window_length)
        self.observation_space = spaces.MultiDiscrete(
            [max_car_num, max_lp_num, max_time_window_length, time_district_num])
        self.time_window = time_window
        self.matcher = kuhn_munkras(self.time_window)

    """
            #Description: 时间窗口内左右节点匹配
        """

    def match(self):
        self.matcher.change_batch(self.time_window)
        reward, match_res = self.matcher.km()
        unbound_lp_list = self.time_window.node_clear(match_res)
        self.time_window.drop_sent_load_plan(unbound_lp_list)
        return reward

    def time_minus(self, front_time_str: str, rear_time_str:str)->datetime.timedelta:
        front = datetime.datetime.strptime(front_time_str, "%Y%m%d%H%M%S")
        rear = datetime.datetime.strptime(rear_time_str, "%Y%m%d%H%M%S")
        tmp = rear - front
        return tmp

    @property
    def _get_obs(self):
        ob = np.zeros(4,dtype=int)
        time_str = self.time_window.time
        ob[0] = len(time_window.car_list)
        ob[1] = len(time_window.can_be_sent_load_plan)
        ob[2] = int(self.time_window.time[8:10]) / 2
        if len(self.time_window.car_list) != 0:
            first_car_time_Str = self.time_window.car_list[0].arrive_time
            time_delta = self.time_minus(first_car_time_Str, time_str)
            ob[3] = int(time_delta.seconds / 60) + 1
        else:
            ob[3] = 0
        return ob

    def step(self, a):
        reward = 0.0
        self.time_window.get_next_min()
        ob = self._get_obs
        if a <= ob[2] and a != 0:
            reward = self.match()
            ob = self._get_obs
        done = False
        if time_window.time >= time_window.end_time:
            done = True
        return ob, reward, done, {}

    def reset(self):
        self.time_window.reset()
        return self._get_obs


#!/usr/bin/env python3
#python crawl.py --iocp http://www.website.com/
import asyncio
import logging
import re
import signal
import os
import sys
import urllib.parse

import aiohttp

@asyncio.coroutine
def download(url,data):
    filename=url.replace('http://','').replace('https://','')
    path=filename.split('/')
    path='/'.join(path[0:-1])
    if not os.path.exists(path):os.makedirs(path)
    if os.path.exists(filename) or os.path.exists(filename+".html"):return
    if not filename.endswith('.html'):filename += 'index.html'
    with open(filename,'w') as f:
        f.write(data)

class Crawler:

    def __init__(self, rooturl, loop, maxtasks=100):
        self.rooturl = rooturl
        self.loop = loop
        self.todo = set()
        self.busy = set()
        self.done = {}
        self.tasks = set()
        self.sem = asyncio.Semaphore(maxtasks, loop=loop)

        # connector stores cookies between requests and uses connection pool
        self.session = aiohttp.ClientSession(loop=loop)

    @asyncio.coroutine
    def run(self):
        t = asyncio.ensure_future(self.addurls([(self.rooturl, '')]),
                                  loop=self.loop)
        yield from asyncio.sleep(1, loop=self.loop)
        while self.busy:
            yield from asyncio.sleep(1, loop=self.loop)

        yield from t
        yield from self.session.close()
        self.loop.stop()

    @asyncio.coroutine
    def addurls(self, urls):
        # print(urls)
        for url, parenturl in urls:
            url = urllib.parse.urljoin(parenturl, url)
            url, _ = urllib.parse.urldefrag(url)
            if (
                # url.startswith(self.rooturl) and
                    url not in self.busy and
                    url not in self.done and
                    url not in self.todo):
                self.todo.add(url)
                yield from self.sem.acquire()
                task = asyncio.ensure_future(self.process(url), loop=self.loop)
                task.add_done_callback(lambda t: self.sem.release())
                task.add_done_callback(self.tasks.remove)
                self.tasks.add(task)

    @asyncio.coroutine
    def process(self, url):
        print('processing:', url)

        self.todo.remove(url)
        self.busy.add(url)
        try:
            resp = yield from self.session.get(url)
        except Exception as exc:
            print('...', url, 'has error', repr(str(exc)))
            self.done[url] = False
        else:
            if (resp.status == 200 and
                    ('text/html' in resp.headers.get('content-type'))):
                data = (yield from resp.read()).decode('utf-8', 'replace')
                # print(url)
                yield download(url,data)
                urls = re.findall(r'(?i)href=["\']?([^\s"\'<>]+)', data)
                # print(urls)

                asyncio.Task(self.addurls([(u, url) for u in urls]))

            resp.close()
            self.done[url] = True

        self.busy.remove(url)
        print(len(self.done), 'completed tasks,', len(self.tasks),
              'still pending, todo', len(self.todo))

def main():
    loop = asyncio.get_event_loop()

    c = Crawler(sys.argv[1], loop)
    asyncio.ensure_future(c.run(), loop=loop)

    try:
        loop.add_signal_handler(signal.SIGINT, loop.stop)
    except RuntimeError:
        pass
    loop.run_forever()
    print('todo:', len(c.todo))
    print('busy:', len(c.busy))
    print('done:', len(c.done), '; ok:', sum(c.done.values()))
    print('tasks:', len(c.tasks))

if __name__ == '__main__':
    if '--iocp' in sys.argv:
        from asyncio import events, windows_events
        sys.argv.remove('--iocp')
        logging.info('using iocp')
        el = windows_events.ProactorEventLoop()
        events.set_event_loop(el)

    main()


import plotly.express as px
import csv
import numpy as np

def getDataSource(dataPath):
    marks = []
    days = []

    with open(dataPath) as csvFile:
        reader = csv.DictReader(csvFile)
        for row in reader:
            days.append(float(row["Days"]))
            marks.append(float(row["Marks"]))

    return {"x":days, "y":marks}

def findCorrelation(dataSource):
    correlation = np.corrcoef(dataSource["x"], dataSource["y"])
    print(correlation[0,1])

def setup():
    dataPath = "p106/marksPresent.csv"
    dataSource = getDataSource(dataPath)
    findCorrelation(dataSource)

setup()

#medium direct proportional


import dash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output

import pandas as pd
import plotly.express as px

df = pd.read_csv("../datasets/Los_Angeles_International_Airport_-_Passenger_Traffic_By_Terminal.csv")
df['ReportPeriod']=pd.to_datetime(df['ReportPeriod'])

external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']

app = dash.Dash(__name__, external_stylesheets=external_stylesheets)

app.layout = html.Div(children=[
    html.H1(children='ECS 272 Assignment 3'),

    html.Div(children='''
        Choose a terminal you are interested in.
    '''),

    dcc.Dropdown(
        id = 'terminal_dropdown',
        options = [
            {'label': 'Imperial Terminal', 'value': 'Imperial Terminal'},
            {'label': 'Misc. Terminal', 'value': 'Misc. Terminal'},
            {'label': 'Terminal 1', 'value': 'Terminal 1'},
            {'label': 'Terminal 2', 'value': 'Terminal 2'},
            {'label': 'Terminal 3', 'value': 'Terminal 3'},
            {'label': 'Terminal 4', 'value': 'Terminal 4'},
            {'label': 'Terminal 5', 'value': 'Terminal 5'},
            {'label': 'Terminal 6', 'value': 'Terminal 6'},
            {'label': 'Terminal 7', 'value': 'Terminal 7'},
            {'label': 'Terminal 8', 'value': 'Terminal 8'},
            {'label': 'Tom Bradley International Terminal', 'value': 'Tom Bradley International Terminal'},
        ],
        value = 'Imperial Terminal'
    ),

    dcc.Graph(
        id='basic_graph'
    ),

    html.Div(children='''
        Choose a year you are interested in.
    '''),

    dcc.Slider(
        id = 'year_slider',
        min = 2006,
        max = 2019,
        marks = {i: '{}'.format(i) for i in range(2006,2020)},
        value = 2006
    ),

    dcc.Graph(
        id='adv_graph'
    )
])

@app.callback(
    Output('basic_graph', 'figure'),
    [Input('terminal_dropdown', 'value')])
def update_basic_figure(terminal):
    figure={
        'data': [
            {'x': ["Domestic", "International"], 'y': [sum(df[df.Domestic_International == "Domestic"][df.Terminal == str(terminal)]["Passenger_Count"]),
                                                       sum(df[df.Domestic_International == "International"][df.Terminal == str(terminal)]["Passenger_Count"])],
                                                       'type': 'bar',
                                                       'name': 'temp'},
        ],
        'layout': {
            'title': 'Basic graph view'
        }
    }
    return figure

@app.callback(
    Output('adv_graph', 'figure'),
    [Input('year_slider', 'value')])
def update_advanced_figure(year):
    filtered_df = df[df['ReportPeriod'].dt.year == year][['Terminal', 'Domestic_International', 'Arrival_Departure']]
    figure = px.parallel_categories(filtered_df, dimensions_max_cardinality = 12)
    return figure

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


import re
import random

def get_response(user_input):
    split_message = re.split(r'\s|[,:;.?!-_]\s*', user_input.lower())
    response = check_all_messages(split_message)
    return response

def message_probability(user_message, recognized_words, single_response=False, required_word=[]):
    message_certainty = 0
    has_required_words = True

    for word in user_message:
        if word in recognized_words:
            message_certainty +=1

    percentage = float(message_certainty) / float (len(recognized_words))

    for word in required_word:
        if word not in user_message:
            has_required_words = False
            break
    if has_required_words or single_response:
        return int(percentage * 100)
    else:
        return 0

def check_all_messages(message):
        highest_prob = {}

        def response(bot_response, list_of_words, single_response = False, required_words = []):
            nonlocal highest_prob
            highest_prob[bot_response] = message_probability(message, list_of_words, single_response, required_words)

        response('Hola', ['hola',  'saludos', 'buenas'], single_response = True)
        response('Estoy bien y tu?', ['como', 'estas', 'va', 'vas', 'sientes', 'onda'], single_response=True)
        response('Si', ['eres', 'inteligente', 'sabes'], single_response=True)
        response('no tengo sabor para poder decirte pero te recomiendo los tacos de barbacoa xd', ['cual', 'gusta', 'comida'], single_response=True)
        response('lo se :( ', ['triste', 'que'], single_response=True)
        response('estoy hecho para responder solo algunas preguntas :( ', ['para', 'estas', 'hecho'], single_response=True)
        response('4', ['2', 'mas'], single_response=True)
        response('lo siento no  hablo ese idioma', ['hi', 'hello'], single_response=True)
        response('te menti xd nose', ['por', 'menos', 'entre'], single_response=True)
        response('Siempre a la orden', ['gracias', 'te lo agradezco', 'thanks'], single_response=True)

        best_match = max(highest_prob, key=highest_prob.get)
        #print(highest_prob)

        return unknown() if highest_prob[best_match] < 1 else best_match

def unknown():
    response = ['nose, puedes decirlo de nuevo?', 'No estoy seguro de lo quieres',][random.randrange(3)]
    return response

while True:
    print("ChatBot: " + get_response(input('Persona: ')))


# class to represent an element of P_n

import turtle
import math
import random

class Element:
    # global variables
    n = 0  # number of points to compute
    dist = 150  # distance between points
    points = []  # points that compose P_n

    moving = False
    angle_step = 1
    error_margin = 0.01

    # constructor to create initial graph
    def __init__(self, window, n):
        self.window = window
        self.n = n

        self.initializeGraph()

        # mapper turtle to find the location of initial vertices
        mapper = turtle.Turtle()
        mapper.hideturtle()
        self.initializeTurtle(mapper)

        # send mapper to complex number 1
        mapper.setpos(self.dist, 0)

        # determine the angle between sides
        angle = 360 / n
        for i in range(0, n - 2):
            mapper.left(angle)
            mapper.forward(self.dist)
            v = turtle.Turtle()
            self.initializeTurtle(v)
            v.setpos(mapper.pos())
            self.points.append(v)

    def animate(self, x, y):
        if (self.moving == False):
            self.moving = True
            # print("starting animation")
            self.tick(2)
        else:
            # print("ending animation")
            self.moving = False

    def tick(self, index):
        if (self.moving == True):
            if (index < self.n):
                # assume curr is the (n-1) point
                curr = self.points[index]

                # set theta to radians
                theta = math.radians(self.angle_step)

                # iterate around circle
                for angle in range(0, 361):
                    # recursive call
                    self.tick(index + 1)
                    # identify prev and next
                    prev = self.points[0]
                    # change prev if curr is not (n-1) point
                    if (index < self.n - 1):
                        prev = self.points[index - 1]
                    # compute phi
                    phi = self.computePhi(curr, prev)
                    # compute new position
                    newx = self.dist * math.sin(phi + theta)  # trig function is like so since phi is measured of y-axis
                    newy = self.dist * math.cos(phi + theta)
                    prevpos = prev.pos()
                    newpos = prevpos + [newx, newy]
                    if (self.moving == True):
                        valid = self.checkValid(curr, prev)
                        if (index == self.n - 1):
                            valid = self.checkValid(curr, self.points[self.n - 2])
                        if (valid == True):
                            curr.setpos(newpos)

    # function to return phi, the angle the point off the y-axis
    def computePhi(self, curr, prev):
        # compute direction vector
        vec = curr.pos() - prev.pos()
        # dot vector with j-hat leaves only y component
        vecy = vec[1]
        # magnitude of vector
        vec_mag = math.sqrt(math.pow(vec[0], 2) + math.pow(vec[1], 2))
        phi = math.acos(vecy / vec_mag)
        # check quadrant
        if (vec[0] < 0):
            phi = 2 * math.pi - phi
        return phi

    def checkValid(self, curr, prev):
        # compute distances
        dist1 = self.computeDist(curr, prev)
        # print(dist1, dist2)
        # compute error margin
        margin = [self.dist - self.error_margin, self.dist + self.error_margin]
        # return false if distance is outside margin
        if (dist1 < margin[0] or dist1 > margin[1]):
            return False
        # otherwise return true
        return True

    def computeDist(self, p1, p2):
        # get coordinates
        p1pos = p1.pos()
        p2pos = p2.pos()
        # compute differences
        diffx = p2pos[0] - p1pos[0]
        diffy = p2pos[1] - p1pos[1]
        # compute distance
        dist = math.sqrt(math.pow(diffx, 2) + math.pow(diffy, 2))
        return dist

    def initializeGraph(self):
        # variables to represent the origin
        origin = turtle.Turtle()
        self.initializeTurtle(origin)
        origin.color([0, 0, 0])
        origin.setpos(0, 0)

        # variable to represent the complex number 1
        one = turtle.Turtle()
        self.initializeTurtle(one)
        one.color([0, 0, 0])
        one.setpos(self.dist, 0)

        self.points.append(origin)
        self.points.append(one)

    def initializeTurtle(self, turt):
        turt.shape("circle")
        turt.shapesize(0.9, 0.9)
        rand_color = self.chooseColor()
        turt.color(rand_color)
        turt.up()
        turt.speed(0)

    def chooseColor(self):
        red = random.random()
        green = random.random()
        blue = random.random()
        return [red, green, blue]


from flask import jsonify, make_response, Blueprint, abort, redirect, request
from atexit import register
from time import sleep
from threading import Thread
from flasgger import swag_from
import utils
import logging
import json

bp = Blueprint('db', __name__)
search_q = utils.RedisQueue('searched')
expand_q = utils.RedisQueue('expanded')

def on_startup():
    def acquire_user(q, threshold):
        while True:
            try:
                if q.qsize() < threshold:
                    rows = db.view(f'tree/{q.name}', limit=threshold, reduce=False,
                                   include_docs=True)[[False]:[False, {}]].rows
                    users = []
                    for row in rows:
                        user = row.doc
                        user[q.name] = 'queue'
                        users.append(user)

                    if users:   # wait for 5 seconds to next fetch
                        results = db.update(users)
                        logging.warning(
                            f'Put {sum([r[0] for r in results])} into {q.name} queue ...')
                        for user, (suc, uid, rev) in zip(users, results):
                            if suc:
                                user['_rev'] = rev
                                q.put(user)
                    else:
                        sleep(5)
                else:
                    sleep(1)
            except Exception as e:
                logging.error(repr(e))
                sleep(1)

    Thread(target=acquire_user, daemon=True, args=(search_q, 200,)).start()
    Thread(target=acquire_user, daemon=True, args=(expand_q, 10,)).start()

@register
def on_exit():
    for q in [search_q, expand_q]:
        users = []
        while not q.empty():
            user = json.loads(q.get())
            user['searched'] = False
            users.append(user)
        result = db.update(users)
        logging.warning(
            f'Put back {sum([r[0] for r in result])} users from {q.name} queue to db.')

db = utils.db(name='users')
on_startup()

@bp.route('/monitor/<level>/')
@swag_from('docs/db_monitor.yml')
def monitor(level):
    search = []
    for item in db.view('tree/searched', group_level=level):
        search.append({str(item.key): item.value})
    return {
        '# of Docs': utils.db().info()['doc_count'],
        'Search': search
    }

@bp.route('/next_search')
@swag_from('docs/next_search.yml')
def next_search():
    user = search_q.get_nowait()
    return user if user else {}

@bp.route('/next_expand')
@swag_from('docs/next_expand.yml')
def next_expand():
    user = expand_q.get_nowait()
    return user if user else {}

@bp.route('/queue_stat')
@swag_from('docs/q_stat.yml')
def q_stat():
    return {'search': search_q.qsize(), 'expand': expand_q.qsize()}

@bp.route('/active_tasks')
def active_tasks():
    return redirect(f'{utils.base()}/_active_tasks')


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

""" Autoruns
    2015 fightnight
    2022 bittor7x0"""

import xbmc,xbmcvfs,xbmcaddon,xbmcgui,xbmcplugin,urllib.request,urllib.parse,urllib.error,os,re,sys
import xml.etree.ElementTree as ET

SERVICE_DISABLED = 'Autoruns_service_disabled'

def list_addons():
      #info directory
      addDir('[COLOR blue][B]%s[/B][/COLOR]' % (translate(30001)),'None',None,xbmcaddon.Addon().getAddonInfo('icon'))

      #get the path of addons
      pathofaddons = xbmcvfs.translatePath('special://home/addons')

      #list with addons
      listofaddons = os.listdir(pathofaddons)
      for individual_addon in listofaddons:
            #path to individual addon, cycle for all the addons
            path_to_addon = os.path.join(pathofaddons, individual_addon)

            #define addon.xml path
            addon_xml_path=os.path.join(path_to_addon,'addon.xml')

            #check the existence of addon.xml, if true, we continue
            if os.path.exists(addon_xml_path):

                  #get addon.xml content
                  xml_content=openfile(addon_xml_path)

                  #get icon from addon.xml because creating a xbmcaddon.Addon(individual_addon) object causes the exception "Unknown addon id 'xxxx'" with installed addons but not enabled
                  root = ET.fromstring(xml_content)
                  xml_icon = root.findall("./extension/assets/icon")
                  addon_icon_path = os.path.join(path_to_addon,xml_icon[0].text if xml_icon else 'icon.png')

                  if re.search(SERVICE_DISABLED,xml_content):
                        #addon with service off
                        addDir('[B][COLOR gold]%s[/B] (off)[/COLOR]' % (individual_addon),path_to_addon,1,addon_icon_path)
                  elif re.search('point="xbmc.service"',xml_content):
                        #addon with service on
                        addDir('%s (on)' % (individual_addon),path_to_addon,1,addon_icon_path)
                  else:
                        #addon with no service
                        pass

def change_state(name,path):
      #define addon.xml path to change
      addon_xml_path=os.path.join(path,'addon.xml')

      #get addon.xml content
      content=openfile(addon_xml_path)

      if re.search('COLOR gold',name):
            #service off to on, so we uncomment the service element
            content=content.replace('<!--%s ' % (SERVICE_DISABLED),'').replace(' %s-->' % (SERVICE_DISABLED),'')
      else:
            #service on to off, so we comment the service element
            root = ET.fromstring(content)
            parent = root.findall("./extension[@point='xbmc.service']/..")[0]
            child = parent.findall("./extension[@point='xbmc.service']")[0]
            commented = '%s \n%s %s' % (SERVICE_DISABLED, ET.tostring(child).decode("utf-8"), SERVICE_DISABLED)
            parent.remove(child)
            parent.append(ET.Comment(commented))
            content=ET.tostring(root, encoding='utf8', method='xml')

      #change state on addon.xml
      savefile(addon_xml_path,content)

      #refresh the list
      xbmc.executebuiltin("Container.Refresh")

def openfile(path_to_the_file):
    try:
        fh = xbmcvfs.File(path_to_the_file, 'rb')
        contents=fh.read()
        fh.close()
        return contents
    except:
        print("Wont open: %s" % filename)
        return None

def savefile(path_to_the_file,content):
    try:
        fh = xbmcvfs.File(path_to_the_file, 'wb')
        fh.write(content)
        fh.close()
    except: print("Wont save: %s" % filename)

def addDir(name,path,mode,iconimage):
      listItem = xbmcgui.ListItem(label=name)
      listItem.setArt({'icon': "DefaultFolder.png"})
      listItem.setArt({'thumb': iconimage})
      return xbmcplugin.addDirectoryItem(handle=int(sys.argv[1]),url="%s?path=%s&mode=%s&name=%s" % (sys.argv[0],urllib.parse.quote_plus(path),mode,urllib.parse.quote_plus(name)),listitem=listItem,isFolder=False)

def get_params():
      param=[]
      paramstring=sys.argv[2]
      if len(paramstring)>=2:
            params=sys.argv[2]
            cleanedparams=params.replace('?','')
            if (params[len(params)-1]=='/'):
                  params=params[0:len(params)-2]
            pairsofparams=cleanedparams.split('&')
            param={}
            for i in range(len(pairsofparams)):
                  splitparams={}
                  splitparams=pairsofparams[i].split('=')
                  if (len(splitparams))==2:
                        param[splitparams[0]]=splitparams[1]
      return param

def translate(text):
      return xbmcaddon.Addon().getLocalizedString(text)

params=get_params()
path=None
name=None
mode=None

try: path=urllib.parse.unquote_plus(params["path"])
except: pass
try: name=urllib.parse.unquote_plus(params["name"])
except: pass
try: mode=int(params["mode"])
except: pass

if mode==None: list_addons()
elif mode==1: change_state(name,path)

xbmcplugin.endOfDirectory(int(sys.argv[1]))


import matplotlib.patches as patches
import matplotlib.pyplot as plt

path = [
    [.1, .3],
    [.2, .9],
    [.8, .4],
]
fig = plt.figure()
ax = fig.gca()
ax.add_patch(patches.Polygon(path))
fig.savefig("triangle_patch.png", dpi=150)
plt.close()

path = [
    [.1, .3],
    [.2, .9],
    [.8, .4],
]
fig = plt.figure()
ax = fig.gca()
ax.add_patch(patches.Polygon(
  path,
  alpha=.7,
  edgecolor="darkblue",
  facecolor="red",
  hatch="+",
  joinstyle="miter",
  linestyle="--",
  linewidth=5,
))
fig.savefig("fancy_patch.png", dpi=150)
plt.close()


import numpy as np
import matplotlib.pyplot as plt

# 1. Linear regression for classifying noisy data

fig, axs = plt.subplots(3)
N = 100     # data set size
d = 2       # 2 classes of data

# Generate random training data
X = np.random.uniform(-1, 1, size=(N, d+1))
X[:, 0] = 1
# Calculate weights vector
w = np.random.uniform(-1, 1, size=(d+1))
# Compute true labels for the training data
Y = np.sign(np.dot(X, w))

# Add Noise
n = np.random.randint(0, 100, 1)
Y[n[0]] = Y[n[0]]*-1

ind_pos = np.where(Y == 1)[0]   # positive examples
ind_neg = np.where(Y == -1)[0]  # negative examples

# Plot points
axs[0].plot(X[ind_pos, 1], X[ind_pos, 2], 'ro')    # red dot points
axs[0].plot(X[ind_neg, 1], X[ind_neg, 2], 'bx')    # blue 'x' points

# Generate random target function: f(x) = w^Tx
X2 = (-w[1]/w[2]*X) - w[0]/w[2]
line_x = np.linspace(-1, 1, 100)
# Plot target function
axs[0].plot(X, X2, label='Target fxn', color='yellow')

# Perceptron algorithm
def perceptron(X, Y, pocket=False):
    # List of in-sample errors
    eins = []
    best_ein = 1000
    # To be trained
    w_train = np.random.uniform(-1, 1, size=(d + 1))
    best_w = w_train

    for i in range(1000):
        Y1 = np.sign(np.dot(X, w_train))
        # Check for misclassified point
        j = np.random.randint(0, 100, 1)

        if Y1[j] != Y[j]:
            # Update hypothesis
            w_train += X[j][0]*Y[j]

        # Calculate error
        ein = np.count_nonzero(Y1-Y) / 100
        if pocket:
            if ein < best_ein:
                best_w = w_train
                best_ein = ein  ###
        eins.append(best_ein if pocket else ein)

    return best_w if pocket else w_train, eins

# Run PLA
l = np.linspace(0, 1000, 1000)
result = perceptron(X, Y, pocket=False)
g = result[0]
g_x = -(g[0]/g[2]) + (-(g[1]*X)/g[2])
ein_pla = result[1]
axs[0].plot(X, g_x, label='PLA final hypothesis', color='orange')
axs[1].plot(l, ein_pla, label='Ein PLA', color='green')

# Run Pocket Algorithm
result2 = perceptron(X, Y, pocket=True)
g2 = result2[0]
g_x2 = -(g2[0]/g2[2]) + (-(g2[1]*X)/g2[2])
ein_pocket = result2[1]
axs[0].plot(X, g_x2, label='Pocket final hypothesis', color='blue')
axs[2].plot(l, ein_pocket, label='Ein Pocket', color='red')

# Linear Regression     eqn 3.4
Xdag = np.matmul(np.linalg.pinv(np.matmul(X.transpose(), X)), X.transpose())
w = np.matmul(Xdag, Y)
wTx = np.matmul(w, X.transpose())
xw = np.matmul(X, w)
p1 = np.matmul(wTx, xw)
p2 = np.multiply(np.matmul(wTx, Y), 2)
p3 = np.matmul(Y.transpose(), Y)
ein_lin_reg = np.add(np.subtract(p1, p2), p3)/100
print(ein_lin_reg)

# Plot Linear Regression
lin_reg = (-(w[0])/w[2]) + (-w[1]*X/w[2])
axs[0].plot(X, lin_reg, label='Linear Regression', color='purple')

plt.show()

Linear Regression, PLA, and Pocket Algorithm/Lab3_Code.py


import threading
import numpy as np
import cv2
import time

class CameraReader(threading.Thread):
    def __init__(self,dev):
        self.dev = dev
        self.lock = threading.Lock()
        self.frame = np.empty((480,640,3), dtype=np.uint8)
        self.running = False
        self.cap = None
        threading.Thread.__init__(self)

    def run(self):
        while self.running:
            self.lock.acquire()
            ret, _ = self.cap.read(self.frame)
            self.lock.release()
            time.sleep(0.01)

    def __enter__(self):
        self.cap = cv2.VideoCapture(self.dev)
        self.running = True
        self.start()
        return self

    def __exit__(self,exception_type, exception_value, traceback):
        self.stop()
        if self.cap is not None:
            self.cap.release()

    def read(self,frame=None):
        self.lock.acquire()
        if frame is None:
            frame = self.frame.copy()
        else:
            np.copyto(frame,self.frame)
        self.lock.release()
        return frame

    def stop(self):
        self.running = False

import rospy
from cv_bridge import CvBridge
from sensor_msgs.msg import Image
class ROSCameraReader(object):
    def __init__(self, topic):
        self.topic = topic
        self.sub = None
        self.bridge = CvBridge()
        self.img = np.zeros((480,640,3), dtype=np.uint8)
    def __enter__(self):
        self.sub = rospy.Subscriber(self.topic, Image, self.img_cb)
        return self
    def __exit__(self,a,b,c):
        if self.sub is not None:
            self.sub.unregister()
            self.sub = None
    def img_cb(self,msg):
        self.img = self.bridge.imgmsg_to_cv2(msg, desired_encoding="bgr8")
    def read(self,frame):
        np.copyto(frame, self.img)


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

from ..enums import ScanTypesEnum
from ..errors import ClosedProcess
from ..process import AbstractProcess
from .functions import (
    get_memory_regions,
    read_process_memory,
    search_addresses_by_value,
    search_values_by_addresses,
    write_process_memory
)
from typing import Generator, Optional, Sequence, Tuple, Type, TypeVar, Union

T = TypeVar("T")

class LinuxProcess(AbstractProcess):
    """
    Class to open a Linux process for reading and writing memory.
    """

    def __init__(
        self,
        *,
        window_title: Optional[str] = None,
        process_name: Optional[str] = None,
        pid: Optional[int] = None,
        **kwargs
    ):
        """
        :param window_title: window title of the target program.
        :param process_name: name of the target process.
        :param pid: process ID.
        """
        super().__init__(
            window_title = window_title,
            process_name = process_name,
            pid = pid
        )
        self.__closed = False

    def close(self) -> bool:
        """
        Close the process handle.
        """
        self.__closed = True
        return True

    def get_memory_regions(self) -> Generator[dict, None, None]:
        """
        Generates dictionaries with the address, size and other
        information of each memory region used by the process.
        """
        if self.__closed: raise ClosedProcess()

        return get_memory_regions(self.pid)

    def read_process_memory(
        self,
        address: int,
        pytype: Type[T],
        bufflength: int
    ) -> T:
        """
        Return a value from a memory address.

        :param address: target memory address (ex: 0x006A9EC0).
        :param pytype: type of the value to be received (bool, int, float, str or bytes).
        :param bufflength: value size in bytes (1, 2, 4, 8).
        """
        if self.__closed: raise ClosedProcess()

        return read_process_memory(self.pid, address, pytype, bufflength)

    def search_by_addresses(
        self,
        pytype: Type[T],
        bufflength: int,
        addresses: Sequence[int],
        *,
        raise_error: bool = False,
    ) -> Generator[Tuple[int, Optional[T]], None, None]:
        """
        Search the whole memory space, accessible to the process,
        for the provided list of addresses, returning their values.
        """
        if self.__closed: raise ClosedProcess()
        return search_values_by_addresses(self.pid, pytype, bufflength, addresses, raise_error=raise_error)

    def search_by_value(
        self,
        pytype: Type[T],
        bufflength: int,
        value: Union[bool, int, float, str, bytes],
        scan_type: ScanTypesEnum = ScanTypesEnum.EXACT_VALUE,
        *,
        progress_information: bool = False,
        writeable_only: bool = False,
    ) -> Generator[Union[int, Tuple[int, dict]], None, None]:
        """
        Search the whole memory space, accessible to the process,
        for the provided value, returning the found addresses.

        :param pytype: type of value to be queried (bool, int, float, str or bytes).
        :param bufflength: value size in bytes (1, 2, 4, 8).
        :param value: value to be queried (bool, int, float, str or bytes).
        :param scan_type: the way to compare the values.
        :param progress_information: if True, a dictionary with the progress information will be return.
        :param writeable_only: if True, search only at writeable memory regions.
        """
        if self.__closed: raise ClosedProcess()

        if scan_type in [ScanTypesEnum.VALUE_BETWEEN, ScanTypesEnum.NOT_VALUE_BETWEEN]:
            raise ValueError("Use the method search_by_value_between(...) to search within a range of values.")

        return search_addresses_by_value(self.pid, pytype, bufflength, value, scan_type, progress_information, writeable_only)

    def search_by_value_between(
        self,
        pytype: Type[T],
        bufflength: int,
        start: Union[bool, int, float, str, bytes],
        end: Union[bool, int, float, str, bytes],
        *,
        not_between: bool = False,
        progress_information: bool = False,
        writeable_only: bool = False,
    ) -> Generator[Union[int, Tuple[int, dict]], None, None]:
        """
        Search the whole memory space, accessible to the process,
        for a value within the provided range, returning the found addresses.

        :param pytype: type of value to be queried (bool, int, float, str or bytes).
        :param bufflength: value size in bytes (1, 2, 4, 8).
        :param start: minimum inclusive value to be queried (bool, int, float, str or bytes).
        :param end: maximum inclusive value to be queried (bool, int, float, str or bytes).
        :param not_between: if True, return only addresses of values that are NOT within the range.
        :param progress_information: if True, a dictionary with the progress information will be return.
        :param writeable_only: if True, search only at writeable memory regions.
        """
        if self.__closed: raise ClosedProcess()

        scan_type = ScanTypesEnum.NOT_VALUE_BETWEEN if not_between else ScanTypesEnum.VALUE_BETWEEN
        return search_addresses_by_value(self.pid, pytype, bufflength, (start, end), scan_type, progress_information, writeable_only)

    def write_process_memory(
        self,
        address: int,
        pytype: Type[T],
        bufflength: int,
        value: Union[bool, int, float, str, bytes]
    ) -> T:
        """
        Write a value to a memory address.

        :param address: target memory address (ex: 0x006A9EC0).
        :param pytype: type of value to be written into memory (bool, int, float, str or bytes).
        :param bufflength: value size in bytes (1, 2, 4, 8).
        :param value: value to be written (bool, int, float, str or bytes).
        """
        if self.__closed: raise ClosedProcess()

        return write_process_memory(self.pid, address, pytype, bufflength, value)


from pymongo import MongoClient
import numpy as np
import datetime

client = MongoClient()
db = client.twitter

cursor = db.tweets.aggregate(
    [{
        "$project": {
            "y": { "$year": "$timestamp_obj"},
            "m": { "$month": "$timestamp_obj"},
            "d": { "$dayOfMonth": "$timestamp_obj" },
            "h": { "$hour": "$timestamp_obj" }
        }
    },
    {
        "$group": {
            "_id": { "year": "$y", "month": "$m", "day": "$d", "hour": "$h" },
            "count": { "$sum": 1 }
        }
    },
    {
        "$sort": {
            "_id.year": -1,
            "_id.month": 1,
            "_id.day": 1,
            "_id.hour": 1
        }
    }]
)

hours = [[] for i in range(24)]
counts = {}
earliest, latest = None, None

for doc in cursor:
    d = doc['_id']
    time = datetime.datetime(int(d['year']), int(d['month']), int(d['day']), int(d['hour']))

    counts[time] = doc['count']

    if earliest == None or time < earliest: earliest = time
    if latest == None or time > latest: latest = time

    hours[int(d['hour'])].append(int(doc['count']))
    print (str(doc).encode('utf-8'))

for i in range(0, len(hours)):
    hours[i] = sum(hours[i]) / len(hours[i])

starttime = earliest
sortedcounts = []
sortedhours = []
while not starttime >= latest:
    try:
        sortedcounts.append(counts[starttime])
        sortedhours.append(hours[starttime.hour])
    except:
        sortedcounts.append(0)
        sortedhours.append(0)

    starttime += datetime.timedelta(hours=1)

N = len(sortedcounts)
# sample spacing
T = 1.0 / 100.0

yf = np.fft.fft(sortedcounts) # fft computing and normalization
xf = np.linspace(0.0, 1.0/(2.0*T), N/2)

yf[0] = 0

import matplotlib.pyplot as plt

fig, ax = plt.subplots(4, 1)

ax[0].plot(sortedcounts)
ax[0].set_xlabel('Time')
ax[0].set_ylabel('Count')

ax[1].plot(xf, 2.0/N * np.abs(yf[:N/2])) # plotting the spectrum

print(yf)
for i in range(0, 27):
    yf[i] = 0

for i in range(28, len(yf)-1):
    yf[i] = 0

ax[2].plot(xf, 2.0/N * np.abs(yf[:N/2]), 'rx') # plotting the spectrum

ixf = np.fft.ifft(yf)
ax[3].plot(ixf)
ax[3].plot(sortedcounts)
ax[3].plot(sortedhours)
ax[3].set_xlabel('Time')
ax[3].set_ylabel('Count')

plt.show()


import menus
import pitch_trainer
import interval_trainer
import chord_trainer
import scale_trainer
import chimes

'''
Main CLI menu for the Tone Trainer game
'''

chimes.welcome()
menus.title()
menus.print_play_menu()
while True:
  sel = input()
  sel = sel.strip()
  if sel == '1':
      r = pitch_trainer.run()
  if sel == '2':
      r = interval_trainer.run()
  if sel == '3':
      r = chord_trainer.run()
  if sel == '4':
      r = scale_trainer.run()
  if sel == 'q':
      chimes.correct()
      print("You entered 'q'. Quitting program. Thanks for playing!\n\n")
      exit(0)
  if r == 'm!':
      menus.print_play_menu()
      continue
  else:
      print('invalid input!')
      continue


import pygame
from typing import List, Callable, Tuple

GREEN = (0, 255, 0)
RED = (255, 0, 0)
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
GREY = (57, 57, 57)
LIGHT_GREY = (99, 99, 99)
LIGHT_BLUE = (141, 182, 205)
# BACKGROUND_COLOR = (158, 58, 64)
BACKGROUND_COLOR = (113, 155, 158)

SIDEBAR_IMAGE_SCALE = 1.5  # make cards and nobles 1.5x bigger

def dim_screen(screen, color=(0, 0, 0), alpha=128):
    """
    Dim the screen with a color and alpha value
    """
    dim = pygame.Surface(screen.get_size())
    dim.fill(color)
    dim.set_alpha(alpha)
    screen.blit(dim, (0, 0))

def get_selection_box(screen: pygame.Surface, width=0.5, height=0.5, color=BACKGROUND_COLOR):
    """
    Creates a selection box on the screen. Centered by default.
    :param screen: used for relative positioning
    :param width: the width of the box relative to the screen size
    :param height: the height of the box relative to the screen size
    :param color: the color of the box
    :return: The surface of the selection box, and the rect of the selection box
    """
    x = screen.get_width() * (1 - width) / 2
    y = screen.get_height() * (1 - height) / 2
    width = screen.get_width() * width
    height = screen.get_height() * height
    box = pygame.Surface((width, height))
    box.fill(color)
    rect = pygame.Rect(x, y, width, height)
    return box, rect

def button(text, width, height, color, border_radius=10):
    """
    Create a green button with the given text.
    :param text: the text to display on the button
    :param width: the width of the button
    :param height: the height of the button
    :param color: the color of the button
    :param border_radius: the border radius of the button
    :return: the button
    """
    # create a transparent surface
    button = pygame.Surface((width, height), pygame.SRCALPHA)
    pygame.draw.rect(button, color, (0, 0, width, height), border_radius=border_radius)
    write_on(button, text)
    return button

def flash_message(screen, text, color=GREEN, opacity=255):
    """
    Display a message
    :param color: the color of the box
    :param screen: the screen to display the message on
    :param text: the text to display
    :param: color: the color of the text
    :param opacity: the opacity of the box
    """
    box = pygame.Surface((screen.get_width() / 2, screen.get_height() / 10))
    box.set_alpha(opacity)
    box.fill(color)
    write_on(box, text)
    screen.blit(box, (screen.get_width() / 2 - box.get_width() / 2, 0))

def flash_right_side(screen, text, color=GREEN, opacity=255, font_size=20):
    """
    Display a message in the top right corner
    :param color: the color of the box
    :param screen: the screen to display the message on
    :param text: the text to display
    :param: color: the color of the text
    :param opacity: the opacity of the box
    :param font_size: the size of the font
    """
    font = pygame.font.Font(None, font_size)
    text_surface = font.render(text, True, color)
    box_width = text_surface.get_rect().width + 10
    box_height = screen.get_height() / 10
    box = pygame.Surface((box_width, box_height))
    box.set_alpha(opacity)
    box.fill(color)
    write_on(box, text, font_size=font_size)
    screen.blit(box, (screen.get_width() - box.get_width() - 30, 0))

def write_on(surface, text, color=BLACK, font='Arial', font_size=20, center=None):
    """
    Write text to a surface
    :param center: center the text on the surface
    :param text: the text to write
    :param surface: the rect to write to
    :param color: the color of the text
    :param font: the font of the text
    :param font_size: the size of the font
    """
    font = pygame.font.SysFont(font, font_size)
    text = font.render(text, True, color)
    text_rect = text.get_rect()
    if center is None:
        text_rect.center = (surface.get_width() / 2, surface.get_height() / 2)
    else:
        text_rect.center = center
    surface.blit(text, text_rect)

def outlined_text(surface, text, outline_color=BLACK, color=WHITE, font='Arial', font_size=20, center=None):
    """
    Write text to a surface
    :param outline_color: the color of the outline
    :param center: center the text on the surface
    :param text: the text to write
    :param surface: the rect to write to
    :param color: the color of the text
    :param font: the font of the text
    :param font_size: the size of the font
    """
    if center is None:
        center = (surface.get_width() / 2, surface.get_height() / 2)
    # top left
    write_on(surface, text, outline_color, font, font_size, (center[0] - 1, center[1] - 1))
    # top right
    write_on(surface, text, outline_color, font, font_size, (center[0] + 1, center[1] - 1))
    # btm left
    write_on(surface, text, outline_color, font, font_size, (center[0] - 1, center[1] + 1))
    # btm right
    write_on(surface, text, outline_color, font, font_size, (center[0] + 1, center[1] + 1))

    # TEXT FILL

    write_on(surface, text, color, font, font_size, center)

class Button:
    def __init__(self,rectangle : pygame.Rect, on_click_event : Callable[[None], None], color: Tuple[int,int,int] = LIGHT_GREY, text: str = "") -> None:
        self.rectangle = rectangle
        self.activation = on_click_event
        self.color = color
        self.text = text

    def set_text(self, text):
        self.text = text

    def display(self, screen):
        pygame.draw.rect(screen,self.color,self.rectangle)


#!/usr/bin/python
import sys
import numpy as np
import scipy.signal as signal
from scipy.io import wavfile
import sklearn as sk
import librosa
import heartpy as hp
import soundfile as sf
from scipy.fft import fft, ifft, fftfreq
import matplotlib.pyplot as plt

src_signal = librosa.load("LAB5_500HzFHR.wav", sr=None)

sample_rate = src_signal[1]
source_signal = src_signal[0]

N = source_signal.size

Ts = 1.0 / sample_rate
fft_src = fft(source_signal)

yf = 2.0/N * np.abs(fft_src[:N//2])

x = np.linspace(0.0, N*Ts, N)
xf = np.linspace(0.0, 1.0/(2.0*Ts), N//2)

b, a =  signal.iirdesign(1, 3, gpass=1, gstop=40, fs=sample_rate)
signal_filtered = signal.lfilter(b, a, source_signal)

freq_s = fftfreq(N, Ts)[:N//2]
fft_flt = fft(signal_filtered)

plt.plot(freq_s, yf)
plt.show(block=False)

# print(b)
# print(a)
plt.plot(freq_s, 2.0/N * np.abs(fft_flt[0:N//2]))
plt.show(block=False)

plt.plot(x, signal_filtered)
plt.show(block=False)

# print(signal_filtered)

sf.write("test.wav", signal_filtered, sample_rate)

working_data, measures = hp.process(source_signal, 500.0)
working_data_flt, measures_flt = hp.process(signal_filtered, 500.0)

bpm_flt = hp.plotter(working_data, measures, show=True)
plt.show(block=False)

# hp.plotter(working_data, measures)
bpm_flt = hp.plotter(working_data_flt, measures_flt, show=True)
plt.show(block=False)

y1 = 0.01 * np.sin(1.2 * x * 2 * np.pi)
y2 = -0.005 * np.sin(1.6 * x * 2 * np.pi)
Y = y1+y2
working_data_t, measures_t = hp.process(Y, 500.0)
bpm_flt = hp.plotter(working_data_t, measures_t, show=True)
plt.show(block=False)
fig, (ax1, ax2) = plt.subplots(2)

ax1.plot(x, y1+y2)
ax2.plot(x, signal_filtered)

plt.show()


import tensorflow as tf
import numpy as np
from tensorflow.python.ops import control_flow_ops
from tensorflow.python.training import moving_averages
from tensorflow.python.training.moving_averages import assign_moving_average

import cfg

class resnet_mcnn(object):
    def __init__(self):
        self.batch_size = cfg.batch_size
        self.test_x = cfg.size_x
        self.test_y = cfg.size_y
        self.train_x = cfg.train_size_x
        self.train_y = cfg.train_size_y
        self.is_training = True
        self.BN_DECAY = 0.9997
        self.UPDATE_OPS_COLLECTION = 'resnet_update_ops'
        self.BN_EPSILON = 0.001
        self.RESNET_VARIABLES = 'resnet_variables'

    def weight_variable(self, shape):
        initial = tf.truncated_normal(shape, stddev=0.1, name="weight")
        return tf.Variable(initial)

    def biases_variable(self, shape):
        initial = tf.constant(0.1, shape=shape,name="bais")
        return tf.Variable(initial)

    def prelu(self, x_):
        alpha = tf.get_variable('alpha', x_.get_shape()[-1], initializer=tf.constant_initializer(0.25), dtype=tf.float32)
        pos = tf.nn.relu(x_)
        neg = alpha * (x_ - abs(x_))
        return pos+neg

    def conv(self, x_input, shape ,name):
        with tf.variable_scope(name):
            weight = self.weight_variable(shape)
            bias = self.weight_variable([shape[-1]])
            result = tf.nn.relu(tf.nn.bias_add(tf.nn.conv2d(x_input, weight, strides=[1,1,1,1], padding='SAME'), bias))
            return result

    def conv_p(self, x_input, shape, name):
        with tf.variable_scope(name):
            weight = self.weight_variable(shape)
            bias = self.weight_variable([shape[-1]])
            result = self.prelu(tf.nn.bias_add(tf.nn.conv2d(x_input, weight, strides=[1,1,1,1], padding='SAME'), bias))
            return result

    def fc_layer(self, in_feature, out_shape, name):
        with tf.variable_scope(name+"_fc"):
            in_shape = 1
            for d in in_feature.get_shape().as_list()[1:]:
                in_shape *= d
            weight = tf.get_variable(initializer=tf.truncated_normal([in_shape, out_shape], 0, 1), dtype=tf.float32, name=name+'_fc_weight')
            bias = tf.get_variable(initializer=tf.truncated_normal([out_shape], 0, 1), dtype=tf.float32, name=name+'_fc_bias')
            result = tf.reshape(in_feature, [-1, in_shape])
            result = tf.nn.xw_plus_b(result, weight, bias, name=name+'_fc_do')
            return result

    def batch_norm_layer(self, x, is_training, name):
        with tf.variable_scope(name):
            beta = tf.Variable(tf.constant(0.0, shape=[x.shape[-1]]), name='beta', trainable=True)
            gamma = tf.Variable(tf.constant(1.0, shape=[x.shape[-1]]), name='gamma', trainable=True)
            axises = np.arange(len(x.shape) - 1)
            batch_mean, batch_var = tf.nn.moments(x, axises, name='moments')
            ema = tf.train.ExponentialMovingAverage(decay=0.5)
            def mean_var_with_update(self):
                ema_apply_op = ema.apply([batch_mean, batch_var])
                with tf.control_dependencies([ema_apply_op]):
                    return tf.identity(batch_mean), tf.identity(batch_var)

            mean, var = tf.cond(is_training, mean_var_with_update,lambda: (ema.average(batch_mean), ema.average(batch_var)))
            normed = tf.nn.batch_normalization(x, mean, var, beta, gamma, 1e-3)
        return normed

    def batch_norm(self, x, is_training, eps=1e-05, decay=0.9, affine=True, name=None):
        with tf.variable_scope(name, default_name='BatchNorm2d'):
            params_shape = x.get_shape().as_list()[-1:]#tf.shape(x)[-1:]
            moving_mean = tf.get_variable('mean', params_shape, initializer=tf.zeros_initializer, trainable=False)
            moving_variance = tf.get_variable('variance', params_shape, initializer=tf.ones_initializer, trainable=False)
            def mean_var_with_update():
                #mean, variance = tf.nn.moments(x, tf.shape(x)[:-1], name='moments')
                mean, variance = tf.nn.moments(x, x.get_shape().as_list()[-1:], name='moments')
                with tf.control_dependencies([assign_moving_average(moving_mean, mean, decay), assign_moving_average(moving_variance, variance, decay)]):
                    return tf.identity(mean), tf.identity(variance)
            mean, variance = tf.cond(tf.cast(is_training, tf.bool), mean_var_with_update, lambda: (moving_mean, moving_variance))
            if affine:
                beta = tf.get_variable('beta', params_shape, initializer=tf.zeros_initializer)
                gamma = tf.get_variable('gamma', params_shape, initializer=tf.ones_initializer)
                x = tf.nn.batch_normalization(x, mean, variance, beta, gamma, eps)
            else:
                x = tf.nn.batch_normalization(x, mean, variance, None, None, eps)
            return x

    def Batch_Normalization(self, x, is_training, scope):
        arg_scope = tf.contrib.framework.arg_scope
        with arg_scope([batch_norm],
                   scope=scope,
                   updates_collections=None,
                   decay=0.9,
                   center=True,
                   scale=True,
                   zero_debias_moving_mean=True) :
            return tf.cond(is_training,
                       lambda : batch_norm(inputs=x, is_training=is_training, reuse=None),
                       lambda : batch_norm(inputs=x, is_training=is_training, reuse=True))

    def bn(self, x, is_training):
        x_shape = x.get_shape()
        params_shape = x_shape[-1:]
        axis = list(range(len(x_shape) - 1))
        beta = self._get_variable('beta', params_shape, initializer=tf.zeros_initializer())
        gamma = self._get_variable('gamma', params_shape, initializer=tf.ones_initializer())
        moving_mean = self._get_variable('moving_mean', params_shape, initializer=tf.zeros_initializer(), trainable=False)
        moving_variance = self._get_variable('moving_variance', params_shape, initializer=tf.ones_initializer(), trainable=False)
        # These ops will only be preformed when training.
        mean, variance = tf.nn.moments(x, axis)
        update_moving_mean = moving_averages.assign_moving_average(moving_mean, mean, self.BN_DECAY)
        update_moving_variance = moving_averages.assign_moving_average(moving_variance, variance, self.BN_DECAY)
        tf.add_to_collection(self.UPDATE_OPS_COLLECTION, update_moving_mean)
        tf.add_to_collection(self.UPDATE_OPS_COLLECTION, update_moving_variance)
        mean, variance = control_flow_ops.cond(
            is_training, lambda: (mean, variance),
            lambda: (moving_mean, moving_variance))
        return tf.nn.batch_normalization(x, mean, variance, beta, gamma, self.BN_EPSILON)

    def _get_variable(self,name,
                      shape,
                      initializer,
                      weight_decay=0.0,
                      dtype='float',
                      trainable=True):
        "A little wrapper around tf.get_variable to do weight decay and add to"
        "resnet collection"
        if weight_decay > 0:
            regularizer = tf.contrib.layers.l2_regularizer(weight_decay)
        else:
            regularizer = None
        collections = [tf.GraphKeys.VARIABLES, self.RESNET_VARIABLES]
        return tf.get_variable(name, shape=shape, initializer=initializer, dtype=dtype, regularizer=regularizer, collections=collections, trainable=trainable)

    def model(self, x_input1, x_input2, x_input3):
        with tf.name_scope('resmcnn1'):
            c1_conv1 = self.conv(x_input1, [7, 7, 64, 32], 'conv1')
            c1_pool1 = tf.nn.max_pool(c1_conv1, ksize=[1,4,4,1], strides=[1,4,4,1], padding='SAME', name='pool1')
            c1_conv2 = self.conv(c1_pool1, [7,7,32,8],'conv2')
            c1_conv3 = self.conv(c1_conv2, [5,5,8,1], 'conv3')
        with tf.name_scope('resmcnn2'):
            c2_conv1 = self.conv(x_input2, [3,3,256,64], 'conv1')
            c2_pool1 = tf.nn.max_pool(c2_conv1, ksize=[1,2,2,1], strides=[1,2,2,1], padding='SAME', name='pool2')
            c2_conv2 = self.conv(c2_pool1, [5,5,64,8], 'conv2')
            c2_conv3 = self.conv(c2_conv2, [5,5,8,1], 'conv3')
        with tf.name_scope('resmcnn3'):
            c3_conv1 = self.conv(x_input3, [3,3,512,64], 'conv1')
            c3_conv2 = self.conv(c3_conv1, [5,5,64,8], 'conv2')
            c3_conv3 = self.conv(c3_conv2, [5,5,8,1], 'conv3')

        with tf.name_scope('merge'):
            m_node = []
            m_node.append(c1_conv3)
            m_node.append(c2_conv3)
            m_node.append(c3_conv3)
            merge = tf.concat(m_node, 3)
            merge_conv1 = self.conv(merge, [3,3,3,3], 'conv1')
            merge_conv2 = self.conv(merge_conv1, [5,5,3,1], 'conv2')
            #merge_out = self.batch_norm(merge_conv2, is_training=True)
            merge_out = tf.layers.batch_normalization(merge_conv2, training=True)
        return merge_out

    def loss_layer(self, pred, gt, stage='train'):
        if stage=='test':
            ground = tf.reshape(gt, [self.test_x//8, self.test_y//8, 1])
        else:
            ground = tf.reshape(gt, [-1, self.train_x//8, self.train_y//8, 1])
        loss = 10000*tf.reduce_sum(tf.square(tf.subtract(pred, ground)))
        return loss


from datetime import datetime

from flask import render_template, url_for, redirect, flash, request, Blueprint
from flask_login import current_user, login_required

from website import db, settings
from website.hours.forms import LogHoursForm
from website.models import User, Event, Hours
from website.events.utils import week_n

hours = Blueprint('hours', __name__)

@hours.route('/log_hours/<int:event_id>', methods=['GET', 'POST'])
@login_required
def log_hours(event_id):
    event = Event.query.get_or_404(event_id)
    previously_existing = Hours.query.filter_by(user_id=current_user.id, event_id=event.id).first()
    form = LogHoursForm(event.start_date, event.end_date)
    form.event = event

    if form.validate_on_submit():
        start_datetime = datetime.combine(form.end_date.data, form.end_time.data)
        end_datetime = datetime.combine(form.start_date.data, form.start_time.data)
        duration_hrs = (start_datetime - end_datetime).total_seconds() / 3600
        logged_hours = Hours(duration=duration_hrs, approved=False, user_id=current_user.id, event_id=event.id)

        if previously_existing:
            db.session.delete(previously_existing)
        db.session.add(logged_hours)
        db.session.commit()
        flash(f"{duration_hrs} hours logged for {event.title}, {event.category}.", 'success')
        return redirect(url_for('events.weekly_events', weeks_diff=week_n(datetime.fromtimestamp(event.start_date))))

    elif request.method == 'GET':
        form.start_date.data = datetime.fromtimestamp(event.start_date).date()
        form.end_date.data = datetime.fromtimestamp(event.end_date).date()
        form.start_time.data = datetime.fromtimestamp(event.start_date).time()
        form.end_time.data = datetime.fromtimestamp(event.end_date).time()
    return render_template('log_hours.html', title="Log Hours", event=event, form=form,
                           previously_existing=bool(previously_existing))

@hours.route('/manage_hours')
@login_required
def manage_hours():
    if not current_user.admin:
        return redirect(request.referrer)
    hours_types = settings['event_categories']
    students = User.query.filter(User.position.in_(settings['student_types'])).all()
    mentors = User.query.filter(User.position.in_(settings['mentor_types'])).all()
    if students:
        students.sort(key=lambda x: (x.last_name, x.first_name))
    if mentors:
        mentors.sort(key=lambda x: (x.last_name, x.first_name))
    hours_list = Hours.query.filter_by(approved=False).all()
    return render_template('manage_hours.html', title="Manage Hours", students=students, mentors=mentors,
                           hours_list=hours_list, hours_types=hours_types)

@hours.route('/approve_hours/<int:hours_id>')
@login_required
def approve_hours(hours_id):
    if not current_user.admin:
        return redirect(request.referrer)
    hours_for_approval = Hours.query.get_or_404(hours_id)
    hours_for_approval.approved = True
    db.session.commit()
    flash(f"{hours_for_approval.duration} hours approved for {hours_for_approval.user.first_name} "
          f"{hours_for_approval.user.last_name}.", 'success')
    return redirect(url_for('hours.manage_hours'))

@hours.route('/delete_hours/<int:hours_id>')
@login_required
def delete_hours(hours_id):
    if not current_user.admin:
        return redirect(request.referrer)
    hours_to_delete = Hours.query.get_or_404(hours_id)
    db.session.delete(hours_to_delete)
    db.session.commit()
    flash(f"Hours not approved for {hours_to_delete.user.first_name} {hours_to_delete.user.last_name}.", 'success')
    return redirect(url_for('hours.manage_hours'))