from typing import List
from adventures_sl.abilities import *

MELEE = 'melee'
RANGED = 'ranged'

class Unit:
    health: int = 0
    attack: int = 0
    max_health: int = 0
    abilities: List[Ability] = []

    def __init__(self,
                 health: int = 0,
                 attack: int = 0,
                 max_health: int=None,  # If None, healht is used
                 ):
        self.attack = attack
        self.health = health
        self.max_health = health if max_health is None else max_health

    def set_callback_dead(self, f):
        self.callback_dead = f

    def reduce_hp(self, value: int):
        value = int(value)
        assert value >= 0
        self.health = max(0, self.health - value)

        if self.health <= 0:
            print(f'{self} - dead')
            self.callback_dead()
        # TODO check dead state

    def increase_hp(self, value: int):
        value = int(value)
        assert value >= 0

        self.health = min(self.max_health, self.health + value)

    def get_attack(self):
        return self.attack

    def buff_attack(self, value: int):
        self.attack += int(value)

    def fight(self, battle):
        move = Melee(self, self.get_attack())
        d_log = [move.do(battle)]

        for ability in self.abilities:
            d_log.append(ability.do(battle))

        return d_log

    def __str__(self):
        return f'{self.__class__.__name__}(hp={self.health})'

class Enemy(Unit):
    def __init__(self,
                 lvl: int = 0,
                 health: int = 0,
                 attack: int = 0):
        self.health = health
        self.attack = attack
        self.lvl = lvl

class Friendly(Unit):

    def __init__(self,
                 lvl: int = 0,
                 health: int = 0,
                 attack: int = 0):
        self.health = health
        self.attack = attack
        self.lvl = lvl

# For testing
class ExampleEnemy(Enemy):
    def __init__(self,
                 health=250,
                 attack=10):
        super(ExampleEnemy, self).__init__(health=health, attack=attack)

    def __str__(self):
        return "Example enemy"

class ExampleFriendly(Friendly):
    def __init__(self, health=180,
                 attack=20):
        super(ExampleFriendly, self).__init__(health=health, attack=attack)

    def __str__(self):
        return "Example friendly"

class DarkGoliath(Enemy):
    """
    From "Dark Goliath's Rampage".
    """

    def __init__(self, lvl):
        if lvl == 14:
            health = 4452
            attack = 72
        else:
            # TODO
            raise NotImplemented()

        super(DarkGoliath, self).__init__(health=health, attack=attack)

        self.abilities = [GoliathSlam(self, lvl=lvl)]

class Gorgelimb(Friendly):
    """Necrolords"""

    def __init__(self, lvl):
        if lvl == 16:
            health = 1040
            attack = 52
        else:
            # TODO
            raise NotImplemented()

        super(Gorgelimb, self).__init__(health=health, attack=attack)

        self.abilities = [FleshEruption(self, lvl=lvl)]

class Emeni(Friendly):
    """Necrolords"""

    def __init__(self, lvl):
        self.role = MELEE
        if lvl == 8:
            health = 540
            attack = 108
        else:
            # TODO
            raise NotImplemented()

        super(Emeni, self).__init__(health=health, attack=attack)

        self.abilities = [SulfuricEmission(self, lvl=lvl),
                          GnashingChompers(self, lvl=lvl)]

class SecutorMevix(Friendly):
    """Necrolords"""

    def __init__(self, lvl):
        if lvl == 13:
            health = 805
            attack = 92

        else:
            # TODO
            raise NotImplemented()

        super(SecutorMevix, self).__init__(health=health, attack=attack)

        self.abilities = [SecutorsJudgement(self, lvl=lvl),
                          ]

class PlagueDeviserMarileth(Friendly):
    """Necrolords"""

    def __init__(self, lvl):
        if lvl == 20:  # TODO
            health = 900  # TODO
            attack = 180
        else:
            # TODO
            raise NotImplemented()

        super(PlagueDeviserMarileth, self).__init__(health=health, attack=attack)

        self.abilities = [VolatileSolvent(self, lvl=lvl),
                          OozeFrictionlessCoating(self, lvl=lvl)]

class MaldraxxusPlaguesinger(Friendly):
    """Necrolords normal unit"""

    def __init__(self, lvl):
        self.role = RANGED

        if lvl == 14:
            health = 240
            attack = 222
        else:
            raise NotImplementedError()

        super(MaldraxxusPlaguesinger, self).__init__(health=health, attack=attack)

        self.abilities = [PlagueSong(self, lvl=lvl)]


from selenium.webdriver.common.by import By

search_type = {
    'xpath': By.XPATH,
    'tag_name': By.TAG_NAME,
    'id': By.ID
}

movie_list = [
        "American Dreamz",
        "Animal Factory",
        "Aurora Borealis",
        "Baadasssss!",
        "The Ballad of Little Jo",
        "Better than Sex",
        "The Big Hit",
        "Blood and Wine",
        "Brick",
        "Brothers",
        "Bubba Ho-Tep",
        "Career Girls",
        "Casanova",
        "Chop Shop",
        "Citizen Ruth",
        "Connie and Carla",
        "C.R.A.Z.Y",
        "Criminal",
        "Crush",
        "Dark Days",
        "The Dead Girl",
        "The Devil's Backbone",
        "Diamond Men",
        "Dick",
        "The Dinner Game",
        "Dinner Rush",
        "The Dish",
        "Teacher's Pet",
        "The Door in the Floor",
        "Driving Lessons",
        "Duck Season",
        "East is East",
        "Everything Put Together",
        "Fast, Cheap and Out of Control",
        "15 Minutes",
        "Find Me Guilty",
        "Firelight",
        "Following",
        "Gilles' Wife",
        "Gloomy Sunday",
        "Go Tigers!",
        "Going in Style",
        "The Great Buck Howard",
        "The Greatest Game Ever Played",
        "The Hard Word",
        "The Harmonists",
        "Hedwig and the Angry Inch",
        "Hidalgo",
        "A Home at the End of the World",
        "The House of Sand",
        "How to Lose Friends & Alienate People",
        "I Served the King of England",
        "Idiocracy",
        "In the Shadow of the Moon",
        "Indigenes",
        "Innocent Blood",
        "Intermission",
        "Island in the Sky",
        "Julia",
        "Keeping Mum",
        "Kill Me Later",
        "King of California",
        "The King of Masks",
        "King of the Hill",
        "Kontroll",
        "Las Ciudad",
        "La Petite Lili",
        "La Promesse",
        "Lady for a Day",
        "The Last Shot",
        "Lawless Heart",
        "Levity",
        "Look Both Ways",
        "The Lookout",
        "Love and Death On Long Island",
        "Mad Money",
        "The Maltese Falcon",
        "The Man from Elysian Fields",
        "Man Push Cart",
        "Marvin's Room",
        "The Matador",
        "Matchstick Men",
        "Matewan",
        "Maybe Baby",
        "The Merry Gentleman",
        "Metroland",
        "A Midnight Clear",
        "The Mighty",
        "Millions",
        "Mirrormask",
        "Moonlighting",
        "Mountains of the Moon",
        "Mrs. Palfrey at the Claremont",
        "My First Mister",
        "The Mystery of Picasso",
        "Nine Lives",
        "Nothing But the Truth",
        "October Sky",
        "Off the Map",
        "Once Were Warriors",
        "One Fine Day",
        "Owning Mahowny",
        "The Painted Veil",
        "Paradise Now",
        "Peter's Friends",
        "Phoebe in Wonderland",
        "The Pledge",
        "Priceless",
        "Prisoner of Paradise",
        "The Prize Winner of Defiance, Ohio",
        "Queen of Hearts",
        "Quinceanera",
        "Raising Victor Vargas",
        "Resurrecting the Champ",
        "Resurrection",
        "Safe Men",
        "Scarecrow",
        "Seven Men from Now",
        "Shadowboxer",
        "Something New",
        "Son of Rambow",
        "Songcatcher",
        "Spring Forward",
        "Starting Out in the Evening",
        "Startup.com",
        "State of the Union",
        "The Steel Helmet",
        "Still Crazy",
        "Stone Reader",
        "Sweet Land",
        "The Tao of Steve",
        "Taste of Cherry",
        "The Third Miracle",
        "Thumbsucker",
        "Tristram Shandy: A Cock and Bull Story",
        "Tumbleweeds",
        "Tuvalu",
        "The TV Set",
        "Two Family House",
        "Two Lovers",
        "Walking the Dead",
        "The Weather Man",
        "Welcome to Sarajevo",
        "Went to Coney Island on a Mission from God… Be Back by Five",
        "What Doesn’t Kill You",
        "The Whole Wide World",
        "The Wide Blue Road",
        "Winter Solstice",
        "Word Wars",
        "The World's Fastest Indian",
        "Zathura: A Space Adventure",
]


# Program Name: Mp3 Music Player
# Created by: Bryant Liu
# Date Created: December 08 2021

try:
    from PyQt5 import QtCore, QtGui, QtWidgets
    from PyQt5.QtWidgets import *
    from PyQt5.QtGui import QIcon, QPixmap
    from songhandling import *
    from readwrite import *
    import getpass
    import os
    import math
    import random
    from pygame import mixer
    from time import sleep
    from threading import *
except:
    input("error")

class Ui_UnidentifiedPlayer(object):
    """window class"""
    def setupUi(self, UnidentifiedPlayer):
        """setup window inputs and other beginning processes"""
        mixer.init()
        self.t1 = Thread(target=self.play_pause)
        self.volume_level = 50
        self.shuffle = "off"
        self.repeat = "off"
        self.slider_pressed = False
        self.fname = None
        self.ready_to_play = False
        self.playing_state = False
        self.song_list = []
        (self.title, self.artist, self.duration, self.file,
         self.ftype, self.fsize, self.bitrate, self.directory,
         self.rawsecs) = get_song_data(self.fname)
        self.nulltime = 0
        # window settings
        UnidentifiedPlayer.setObjectName("UnidentifiedPlayer")
        UnidentifiedPlayer.setWindowTitle("Unidentified Player")
        UnidentifiedPlayer.resize(700, 340)
        UnidentifiedPlayer.setFixedSize(700, 340)
        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred,
                                           QtWidgets.QSizePolicy.Preferred)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(UnidentifiedPlayer.sizePolicy().
                                     hasHeightForWidth())
        UnidentifiedPlayer.setSizePolicy(sizePolicy)
        icon = QtGui.QIcon("iconUP.png")
        UnidentifiedPlayer.setWindowIcon(icon)
        self.centralwidget = QtWidgets.QWidget(UnidentifiedPlayer)
        self.centralwidget.setObjectName("centralwidget")
        # song slider
        self.songtimeslider = QtWidgets.QSlider(self.centralwidget)
        self.songtimeslider.setGeometry(QtCore.QRect(230, 140, 300, 22))
        self.songtimeslider.setMinimum(0)
        self.songtimeslider.setMaximum(100000)
        self.songtimeslider.setPageStep(0)
        self.songtimeslider.setOrientation(QtCore.Qt.Horizontal)
        self.songtimeslider.setObjectName("songtimeslider")
        self.songtimeslider.sliderPressed.connect(self.disableslider)
        self.songtimeslider.sliderReleased.connect(self.changetime)
        # play/pause button
        self.playpausebutton = QtWidgets.QPushButton(self.centralwidget)
        self.playpausebutton.setGeometry(QtCore.QRect(340, 170, 81, 81))
        font = QtGui.QFont()
        font.setPointSize(24)
        self.playpausebutton.setFont(font)
        self.playpausebutton.setIconSize(QtCore.QSize(16, 16))
        self.playpausebutton.setObjectName("playpausebutton")
        self.playpausebutton.clicked.connect(self.thread)
        # volume dial
        self.volumedial = QtWidgets.QDial(self.centralwidget)
        self.volumedial.setGeometry(QtCore.QRect(560, 20, 121, 121))
        self.volumedial.setMaximum(100)
        self.volumedial.setPageStep(1)
        self.volumedial.setProperty("value", 50)
        self.volumedial.setSliderPosition(50)
        self.volumedial.setTracking(True)
        self.volumedial.setOrientation(QtCore.Qt.Horizontal)
        self.volumedial.setInvertedAppearance(False)
        self.volumedial.setInvertedControls(True)
        self.volumedial.setWrapping(False)
        self.volumedial.setNotchTarget(7.7)
        self.volumedial.setNotchesVisible(True)
        self.volumedial.setObjectName("volumedial")
        self.volumedial.valueChanged.connect(lambda: self.vol_change())
        self.volumedial.sliderReleased.connect(self.update_config)
        # forwards button
        self.forwardsbutton = QtWidgets.QPushButton(self.centralwidget)
        self.forwardsbutton.setGeometry(QtCore.QRect(420, 170, 111, 81))
        font = QtGui.QFont()
        font.setPointSize(20)
        self.forwardsbutton.setFont(font)
        self.forwardsbutton.setObjectName("forwardbutton")
        self.forwardsbutton.clicked.connect(self.forwards)
        # backwards button
        self.backwardsbutton = QtWidgets.QPushButton(self.centralwidget)
        self.backwardsbutton.setGeometry(QtCore.QRect(230, 170, 111, 81))
        font = QtGui.QFont()
        font.setPointSize(20)
        self.backwardsbutton.setFont(font)
        self.backwardsbutton.setObjectName("backwardsbutton")
        self.backwardsbutton.clicked.connect(self.backwards)
        # shuffle button
        self.shufflebutton = QtWidgets.QPushButton(self.centralwidget)
        self.shufflebutton.setGeometry(QtCore.QRect(230, 250, 151, 41))
        self.shufflebutton.setObjectName("shufflebutton")
        self.shufflebutton.clicked.connect(self.shuffle_change)
        # repeat button
        self.repeatbutton = QtWidgets.QPushButton(self.centralwidget)
        self.repeatbutton.setGeometry(QtCore.QRect(380, 250, 151, 41))
        self.repeatbutton.setObjectName("repeatbutton")
        self.repeatbutton.clicked.connect(self.repeat_change)
        # stop button (eject)
        self.stopsongbutton = QtWidgets.QPushButton(self.centralwidget)
        self.stopsongbutton.setGeometry(QtCore.QRect(225, 0, 18, 120))
        font = QtGui.QFont()
        font.setPointSize(14)
        self.stopsongbutton.setFont(font)
        self.stopsongbutton.setObjectName("stopsongbutton")
        self.stopsongbutton.clicked.connect(self.stop)
        # load song(s) button
        self.loadsongsbutton = QtWidgets.QPushButton(self.centralwidget)
        self.loadsongsbutton.setGeometry(QtCore.QRect(10, 0, 200, 21))
        self.loadsongsbutton.setObjectName("loadsongsbutton")
        self.loadsongsbutton.clicked.connect(self.add_songs)
        # remove selection button
        self.removeselectionbutton = QtWidgets.QPushButton(self.centralwidget)
        self.removeselectionbutton.setGeometry(QtCore.QRect(10, 300, 200, 21))
        self.removeselectionbutton.setObjectName("removeselection")
        self.removeselectionbutton.clicked.connect(self.remove)
        # songtime label
        self.songtimelabel = QtWidgets.QLabel(self.centralwidget)
        self.songtimelabel.setGeometry(QtCore.QRect(500, 120, 47, 13))
        self.songtimelabel.setObjectName("songtimelabel")
        # volume value label
        self.volumevaluelabel = QtWidgets.QLabel(self.centralwidget)
        self.volumevaluelabel.setGeometry(QtCore.QRect(610, 70, 31, 31))
        font = QtGui.QFont()
        font.setPointSize(12)
        self.volumevaluelabel.setFont(font)
        self.volumevaluelabel.setObjectName("volumelabel")
        # volume label
        self.volumelabel = QtWidgets.QLabel(self.centralwidget)
        self.volumelabel.setGeometry(QtCore.QRect(600, 140, 47, 13))
        self.volumelabel.setObjectName("volumelabel")
        # plus sign label
        self.pluslabel = QtWidgets.QLabel(self.centralwidget)
        self.pluslabel.setGeometry(QtCore.QRect(660, 130, 16, 16))
        font = QtGui.QFont()
        font.setPointSize(14)
        font.setBold(True)
        font.setWeight(75)
        self.pluslabel.setFont(font)
        self.pluslabel.setObjectName("pluslabel")
        # minus sign label
        self.minuslabel = QtWidgets.QLabel(self.centralwidget)
        self.minuslabel.setGeometry(QtCore.QRect(570, 130, 16, 16))
        font = QtGui.QFont()
        font.setPointSize(14)
        font.setBold(True)
        font.setWeight(75)
        self.minuslabel.setFont(font)
        self.minuslabel.setObjectName("minuslabel")
        # image
        self.image = QtWidgets.QLabel(self.centralwidget)
        self.image.setGeometry(QtCore.QRect(550, 170, 130, 130))
        pixmap = QPixmap("iconUP.png")
        pixmap = pixmap.scaled(130, 130, QtCore.Qt.KeepAspectRatio)
        self.image.setPixmap(pixmap)
        self.image.setObjectName("imagelabel")
        # title label
        self.titlelabel = QtWidgets.QLabel(self.centralwidget)
        self.titlelabel.setGeometry(QtCore.QRect(250, 10, 47, 13))
        self.titlelabel.setObjectName("titlelabel")
        # artist label
        self.artistlabel = QtWidgets.QLabel(self.centralwidget)
        self.artistlabel.setGeometry(QtCore.QRect(250, 23, 47, 13))
        self.artistlabel.setObjectName("artistlabel")
        # duration label
        self.durationlabel = QtWidgets.QLabel(self.centralwidget)
        self.durationlabel.setGeometry(QtCore.QRect(250, 36, 47, 13))
        self.durationlabel.setObjectName("durationlabel")
        # filename label
        self.filenamelabel = QtWidgets.QLabel(self.centralwidget)
        self.filenamelabel.setGeometry(QtCore.QRect(250, 61, 47, 13))
        self.filenamelabel.setObjectName("filenamelabel")
        # type label
        self.typelabel = QtWidgets.QLabel(self.centralwidget)
        self.typelabel.setGeometry(QtCore.QRect(250, 74, 47, 13))
        self.typelabel.setObjectName("typelabel")
        # size label
        self.sizelabel = QtWidgets.QLabel(self.centralwidget)
        self.sizelabel.setGeometry(QtCore.QRect(250, 87, 47, 13))
        self.sizelabel.setObjectName("sizelabel")
        # bitrate label
        self.bitratelabel = QtWidgets.QLabel(self.centralwidget)
        self.bitratelabel.setGeometry(QtCore.QRect(250, 100, 47, 13))
        self.bitratelabel.setObjectName("bitratelabel")
        # seperator line
        self.line = QtWidgets.QFrame(self.centralwidget)
        self.line.setGeometry(QtCore.QRect(210, 6, 20, 334))
        self.line.setFrameShape(QtWidgets.QFrame.VLine)
        self.line.setFrameShadow(QtWidgets.QFrame.Sunken)
        self.line.setObjectName("line")
        # info label
        self.infolabel = QtWidgets.QLabel(self.centralwidget)
        self.infolabel.setGeometry(QtCore.QRect(230, 290, 301, 16))
        self.infolabel.setObjectName("infolabel")
        # list widget for songs
        self.list_widget = QListWidget(self.centralwidget)
        self.list_widget.setGeometry(5, 25, 210, 270)
        self.list_widget.setDragEnabled(True)
        self.list_widget.setDragDropMode(QAbstractItemView.InternalMove)
        self.list_widget.itemActivated.connect(self.loader)
        self.scroll_bar = QScrollBar(self.centralwidget)
        self.list_widget.setVerticalScrollBar(self.scroll_bar)
        self.list_widget.itemPressed.connect(self.update_songs)
        # menubar and statusbar settings
        UnidentifiedPlayer.setCentralWidget(self.centralwidget)
        self.menubar = QtWidgets.QMenuBar(UnidentifiedPlayer)
        self.menubar.setGeometry(QtCore.QRect(0, 0, 700, 21))
        self.menubar.setObjectName("menubar")
        UnidentifiedPlayer.setMenuBar(self.menubar)
        self.statusbar = QtWidgets.QStatusBar(UnidentifiedPlayer)
        self.statusbar.setObjectName("statusbar")
        UnidentifiedPlayer.setStatusBar(self.statusbar)
        # update labels
        self.retranslateUi(UnidentifiedPlayer)
        self.settings_inquire()
        self.song_inquire()
        # connecting events
        QtCore.QMetaObject.connectSlotsByName(UnidentifiedPlayer)

    ###########
    def retranslateUi(self, UnidentifiedPlayer):
        """label widgets"""
        _translate = QtCore.QCoreApplication.translate
        UnidentifiedPlayer.setWindowTitle(_translate("UnidentifiedPlayer",
                                                     "Unidentified Player"))
        self.playpausebutton.setText(_translate("UnidentifiedPlayer", "►"))
        self.forwardsbutton.setText(_translate("UnidentifiedPlayer", "►▌"))
        self.backwardsbutton.setText(_translate("UnidentifiedPlayer", "▐◄"))
        self.shufflebutton.setText(_translate("UnidentifiedPlayer",
                                              "Shuffle: Off"))
        self.repeatbutton.setText(_translate("UnidentifiedPlayer",
                                             "Repeat: Off"))
        self.stopsongbutton.setText(_translate("UnidentifiedPlayer", "■"))
        self.loadsongsbutton.setText(_translate("UnidentifiedPlayer",
                                                "Add Song(s)"))
        self.removeselectionbutton.setText(_translate("UnidentifiedPlayer",
                                                      "Remove Selection"))
        self.songtimelabel.setText(_translate("UnidentifiedPlayer", "00:00"))
        self.volumevaluelabel.setText(_translate("UnidentifiedPlayer",
                                                 str(self.volume_level)))
        self.artistlabel.setText(_translate("UnidentifiedPlayer", "Artist:"))
        self.titlelabel.setText(_translate("UnidentifiedPlayer", "Title:"))
        self.durationlabel.setText(_translate("UnidentifiedPlayer",
                                              "Duration:"))
        self.filenamelabel.setText(_translate("UnidentifiedPlayer", "File:"))
        self.typelabel.setText(_translate("UnidentifiedPlayer", "Type:"))
        self.sizelabel.setText(_translate("UnidentifiedPlayer", "Size:"))
        self.bitratelabel.setText(_translate("UnidentifiedPlayer", "Bitrate:"))
        self.pluslabel.setText(_translate("UnidentifiedPlayer", "+"))
        self.minuslabel.setText(_translate("UnidentifiedPlayer", "-"))
        self.volumelabel.setText(_translate("UnidentifiedPlayer", "VOLUME"))
        self.infolabel.setText(_translate("UnidentifiedPlayer",
                                          "(Note: Currently, only mp3s and" +
                                          "flacs are supported!)"))
        self.updatelabels()

    def updatelabels(self):
        """update labels"""
        self.titlelabel.setText(f"Title: {self.title}")
        self.titlelabel.adjustSize()
        self.artistlabel.setText(f"Artist: {self.artist}")
        self.artistlabel.adjustSize()
        self.durationlabel.setText(f"Duration: {self.duration}")
        self.durationlabel.adjustSize()
        self.filenamelabel.setText(f"File: {self.file}")
        self.filenamelabel.adjustSize()
        self.typelabel.setText(f"Type: {self.ftype}")
        self.typelabel.adjustSize()
        self.sizelabel.setText(f"Size : {self.fsize} MB")
        self.sizelabel.adjustSize()
        self.bitratelabel.setText(f"Bitrate: {self.bitrate} kbps")
        self.bitratelabel.adjustSize()

    def settings_inquire(self):
        """extract settings from config.txt"""
        self.volume_level, self.shuffle, self.repeat = get_settings()
        mixer.music.set_volume(self.volume_level/100)
        self.volumevaluelabel.setText(str(self.volume_level))
        self.volumedial.setProperty("value", self.volume_level)
        if self.shuffle == "off":
            self.shuffle = "off"
            self.shufflebutton.setText("Shuffle: Off")
        elif self.shuffle == "on":
            self.shuffle = "on"
            self.shufflebutton.setText("Shuffle: On")
        if self.repeat == "off":
            self.repeat = "off"
            self.repeatbutton.setText("Repeat: Off")
        elif self.repeat == "queue":
            self.repeat = "queue"
            self.repeatbutton.setText("Repeat: Queue")
        elif self.repeat == "track":
            self.repeat = "track"
            self.repeatbutton.setText("Repeat: Track")

    def song_inquire(self):
        """extract songs from queue.txt"""
        self.song_list = get_songs()
        for item in self.song_list:
            self.list_widget.addItem(item)

    ###########
    def add_songs(self):
        """add songs to queue"""
        try:
            self.fname = QFileDialog.getOpenFileNames(None,
                                                      'Add Song(s)',
                                                      'c:\\Users\\' +
                                                      getpass.getuser() +
                                                      '\\Music',
                                                      "Audio Files \
                                                      (*.mp3 *.flac)")
            if self.fname[0][0] not in ("", " ", None):
                for item in self.fname[0]:
                    self.list_widget.addItem(item)
                    self.song_list.append(item)
                self.update_songs()

        except:
            pass

    def loader(self):
        """load song into player"""
        try:
            self.stop()
        except:
            pass
        try:
            item = self.list_widget.currentItem()
            self.songd = item.text()
            (self.title, self.artist, self.duration, self.file,
             self.ftype, self.fsize, self.bitrate, self.directory,
             self.rawsecs) = get_song_data(self.songd)
            self.updatelabels()
            self.playing_state = False
            self.ready_to_play = True
            mixer.music.load(self.directory)
            mixer.music.play()
            mixer.music.pause()
        except:
            self.stop()
            self.remove()

    def thread(self):
        """thread for timebar"""
        self.t1 = Thread(target=self.play_pause)
        self.t1.start()

    def play_pause(self):
        """manages playing and puasing"""
        global dead
        if self.ready_to_play is False:
            self.loader()
        if self.ready_to_play is True and self.playing_state is False:
            mixer.music.unpause()
            self.slider_pressed = False
            self.playing_state = True
            self.playpausebutton.setText("▌▌")

            totaltime = self.rawsecs
            x = 0
            while self.playing_state and dead is False:
                x = mixer.music.get_pos()
                time = (x/1000) + self.nulltime
                self.songtimelabel.setText(time_convert(round(time)))
                decimal = (time/totaltime)*100000
                if self.slider_pressed is False:
                    self.songtimeslider.setValue(round(decimal))
                # check if song end
                if math.ceil(time) >= math.floor(totaltime):
                    self.song_end()
                sleep(0.5)
        elif self.ready_to_play is True and self.playing_state is True:
            mixer.music.pause()
            self.playing_state = False
            self.playpausebutton.setText("►")

    def disableslider(self):
        """disables slider"""
        self.slider_pressed = True

    def changetime(self):
        """allows user to adjust time duration with time bar"""
        try:
            if self.playing_state is True:
                position = self.songtimeslider.value()
                ratio = position/100000
                newtime = ratio*self.rawsecs
                self.nulltime = newtime
                mixer.music.stop()
                mixer.music.play(start=newtime)
                self.slider_pressed = False
            else:
                pass
        except:
            # fail proof
            self.stop()

    def song_end(self):
        """handles the actions taken after song ends"""
        self.playing_state = False
        # shuffle overrides repeat
        if self.shuffle == "on":
            self.song_list = [self.list_widget.item(i).text()
                              for i in range(self.list_widget.count())]
            x = len(self.song_list)
            ran_num = random.randint(1, x)
            ran_num -= 1
            self.list_widget.setCurrentRow(ran_num)
            self.loader()
            self.playpausebutton.setText("▌▌")
            self.playing_state = True
            self.ready_to_play = True
            mixer.music.unpause()
        # repeat
        else:
            if self.repeat == "queue":
                self.playing_state = True
                self.forwards()
            elif self.repeat == "track":
                mixer.music.stop()
                mixer.music.play()
                self.playing_state = True
            else:
                mixer.music.stop()
                mixer.music.play()
                mixer.music.pause()
                self.playing_state = False
                self.songtimeslider.setValue(0)
                self.playpausebutton.setText("►")
                self.songtimelabel.setText("00:00")
        self.nulltime = 0

    def stop(self):
        """completely stops the playing song"""
        mixer.music.stop()
        mixer.music.unload()
        (self.title, self.artist, self.duration, self.file,
         self.ftype, self.fsize, self.bitrate, self.directory,
         self.rawsecs) = get_song_data("")
        self.updatelabels()
        self.fname = None
        self.playing_state = False
        self.ready_to_play = False
        self.songtimeslider.setValue(0)
        self.playpausebutton.setText("►")
        self.songtimelabel.setText("00:00")
        self.nulltime = 0

    def vol_change(self):
        """adjusts volume"""
        self.volume_level = self.volumedial.value()
        self.volumevaluelabel.setText(str(self.volume_level))
        mixer.music.set_volume(self.volume_level/100)

    def shuffle_change(self):
        """changes state of shuffle"""
        if self.shuffle == "off":
            self.shuffle = "on"
            self.shufflebutton.setText("Shuffle: On")
        elif self.shuffle == "on":
            self.shuffle = "off"
            self.shufflebutton.setText("Shuffle: Off")
        self.update_config()

    def repeat_change(self):
        """changes state of repeat"""
        if self.repeat == "off":
            self.repeat = "queue"
            self.repeatbutton.setText("Repeat: Queue")
        elif self.repeat == "queue":
            self.repeat = "track"
            self.repeatbutton.setText("Repeat: Track")
        elif self.repeat == "track":
            self.repeat = "off"
            self.repeatbutton.setText("Repeat: Off")
        self.update_config()

    def update_config(self):
        """updates config.txt"""
        write_settings(self.volume_level, self.shuffle, self.repeat)

    def update_songs(self):
        """updates queue.txt"""
        self.song_list = [self.list_widget.item(i).text()
                          for i in range(self.list_widget.count())]
        write_songs(self.song_list)

    def backwards(self):
        """moves selection backwards in queue"""
        try:
            if self.shuffle == "on":
                self.song_list = [self.list_widget.item(i).text()
                                  for i in range(self.list_widget.count())]
                x = len(self.song_list)
                ran_num = random.randint(1, x)
                ran_num -= 1
                self.list_widget.setCurrentRow(ran_num)
                self.loader()
                self.playpausebutton.setText("▌▌")
                self.playing_state = True
                self.ready_to_play = True
                mixer.music.unpause()
                return
            self.song_list = [self.list_widget.item(i).text()
                              for i in range(self.list_widget.count())]
            row = self.list_widget.currentRow()-1
            if row <= -1:
                index = len(self.song_list) - 1
                row = index
            self.list_widget.setCurrentRow(row)
            if self.playing_state is True:
                self.stop()
                self.t1.join()
                self.thread()
            elif self.playing_state is False:
                self.stop()
                self.loader()
        except:
            pass

    def forwards(self):
        """moves selection forwards in queue"""
        try:
            if self.shuffle == "on":
                self.song_list = [self.list_widget.item(i).text()
                                  for i in range(self.list_widget.count())]
                x = len(self.song_list)
                ran_num = random.randint(1, x)
                ran_num -= 1
                self.list_widget.setCurrentRow(ran_num)
                self.loader()
                self.playpausebutton.setText("▌▌")
                self.playing_state = True
                self.ready_to_play = True
                mixer.music.unpause()
                return
            self.song_list = [self.list_widget.item(i).text()
                              for i in range(self.list_widget.count())]
            row = self.list_widget.currentRow()+1
            if row >= len(self.song_list):
                row = 0
            self.list_widget.setCurrentRow(row)
            if self.playing_state is True:
                self.stop()
                self.t1.join()
                self.thread()
            elif self.playing_state is False:
                self.stop()
                self.loader()
        except:
            pass

    def remove(self):
        """removes item from queue"""
        self.stop()
        row = self.list_widget.currentRow()
        self.list_widget.takeItem(row)
        self.update_songs()

if __name__ == "__main__":
    import sys
    app = QtWidgets.QApplication(sys.argv)
    UnidentifiedPlayer = QtWidgets.QMainWindow()
    ui = Ui_UnidentifiedPlayer()
    ui.setupUi(UnidentifiedPlayer)
    UnidentifiedPlayer.show()
    dead = False
    app.exec_()
    dead = True
    sys.exit()


from os.path import splitext
from os import walk
import easygui as eg
from cv2 import imread, imwrite, resize

path = eg.diropenbox()
fileExt = list(input("File extentions (write comma seperated): ").split(","))
new_shape = (int(input("width: ")), int(input("height: ")))

try:
    _, _, filenames = next(walk(path))

    for f in filenames:
        _, ext = splitext(f)
        if ext[1:] in fileExt:
            filepath = path + '/' + f
            img = imread(filepath)
            img = resize(img, new_shape)
            imwrite(filepath, img)
            print("Saved:", filepath)

except Exception as e:
    print("Error:", e)


#!/usr/bin/env python3

from useful.csv import Reader as CSVReader
from useful.small import invoke, dictzip
from useful.mstring import s

from argparse import ArgumentParser
from collections import OrderedDict
from statistics import mean,pstdev
from random import choice
from itertools import cycle
import numpy as np
import pickle
import os

import matplotlib as mpl
if 'DISPLAY' not in os.environ:
  mpl.use('Agg')
import pylab as p

def ci_student(a, confidence=0.9):
  from scipy.stats import sem, t
  import numpy as np

  n = len(a)
  mean = np.mean(a)  # mean value
  se = sem(a)        # standart error
  h = se * t.ppf((1+confidence)/2, n-1)
  # std  = np.std(y)
  # avgerr = np.mean([abs(mean-datum) for datum in y])
  # print("mean: {:.3f}, STD: {:.3f}, RSTD: {:.3%}, AVGERR: {:.3%} {:.3f}".format(mean, std, std/mean, avgerr/mean, se))
  return (2*h)/mean

def precision(samples, truevalue):
  return 1 - abs(1-mean(samples)/truevalue)

def precision2(samples1, samples2):
  return 1 - abs(1-mean(samples1)/mean(samples2))

def single(path, label=None, lw=4, ms=10, **kwargs):
  lw = float(lw)
  with open(path) as csvfile:
    ts, cycles = [], []
    cur_cycles = 0
    cur_instr = 0
    for t, val, cnt in CSVReader(csvfile, type=(float,int,str)):
      if cnt == 'instructions':
        cur_instr = val
      elif cnt == 'cycles':
        cur_cycles = val
        cycles.append(cur_instr/cur_cycles)
        ts.append(t)
      else:
        raise Exception("I accept only cycles and instructions")
  print(ts[:10], cycles[:10])
  #args = {}
  #if color: args['color'] = color
  p.plot(ts, cycles, label=label, lw=lw, ms=ms, **kwargs)

def annotate(y:float, start:float, stop:float, text, notch:float=0.07, color='black', lw:float=2):
  # from http://stackoverflow.com/questions/7684475/plotting-labeled-intervals-in-matplotlib-gnuplot
  p.hlines(y, start, stop, color, lw=lw*2)
  p.vlines(start, y+notch, y-notch, color, lw=lw)
  p.vlines(stop, y+notch, y-notch, color, lw=lw)
  p.text((stop-start)/2, y+0.015 , text, horizontalalignment='center', fontsize=30)

def myboxplot(data, *args, labels=None, legend=["isolated env", "frozen env"], **kwargs):
  alpha=0.6
  positions = [n+y+1 for n,y in zip(range(len(data)),cycle([+0.2,-0.2]))]
  box = p.boxplot(data, *args, positions=positions, patch_artist=True, **kwargs)
  p.plot(positions, [mean(d) for d in data], 'r*', markeredgecolor='red', lw=10)
  if labels:
    p.xticks(np.arange(len(labels))*2+1.5, labels, rotation=25)

  # set colors
  for patch, color in zip(box['boxes'], cycle(['green', 'blue'])):
    patch.set_facecolor(color)
    patch.set_alpha(alpha)

  iso = p.Rectangle((0, 0), 1, 1, fc='green', ec='black', alpha=alpha)
  fro = p.Rectangle((0, 0), 1, 1, color='blue', ec='black', alpha=alpha)
  p.legend([iso, fro], legend)

  return box

def analyze_reverse2(data):
  data = pickle.load(open(data, 'rb')).result
  isolated = data.isolated
  shared = data.shared
  plots, labels = [], []
  tuples = []
  for test, isolated, shared in dictzip(isolated, shared):
     prec = precision2(shared, isolated)
     tuples.append((test, isolated, shared, prec))
  tuples = sorted(tuples, key=lambda x: x[3])
  for test, isolated, shared, prec in tuples:
      # if prec >0.1: continue
      plots.append(isolated)
      plots.append(shared)
      labels.append("{} {:.1%}".format(test, prec))
  myboxplot(plots, labels=labels)

def analyze_reverse(ref, exp, prec:float=0.95, maxtries:int=50, mode='hist', confidence:float=0.9):
  refdata = pickle.load(open(ref, 'rb')).result
  expdata = pickle.load(open(exp, 'rb')).result
  # unpack reference data
  for k,v in refdata.items():
    refdata[k] = v[0]

  # HIST
  if mode == 'hist':
    for i, (test, truevalue) in enumerate(refdata.items(), 1):
      measurements = expdata[test]
      label = " -> ".join(test)
      p.subplot(12,1,i)
      p.xlim(0,2)
      p.hist(measurements, bins=50, label=label, normed=True, histtype='stepfilled', linewidth=2, alpha=0.7)
    p.subplots_adjust(left=0, right=1, top=1, bottom=0)
  # MONTE CARLO
  elif mode == 'montecarlo':
    results = []
    failures = 0
    for test, truevalue in refdata.items():
      for _ in range(1000):
        samples = []
        for x in range(maxtries):
          samples.append(choice(expdata[test]))
          # samples.append(random())  # absolute random junk
          if precision(samples, truevalue) > prec:
            num = len(samples)
            if num > 50: print("achtung!")
            results.append(num)
            # print(truevalue, samples)
            break
        else:
          # we failed to achieve precision
          failures += 1
    frate = failures/(len(results)+failures)
    print("-= for precision %s =-" % prec)
    print("mean={:.2f}({:.0%}), failure rate={:.2%}".format(mean(results), pstdev(results), frate))
  # CONFIDENCE INTERVAL
  elif mode == 'ci':
    for test, truevalue in sorted(refdata.items()):
      ci = ci_student(expdata[test], confidence=0.95)
      print("{}: ci {:.2%}".format(test, ci))
  else:
    sys.exit(s("unknown mode ${mode}"))

def compare(data1, data2, legend):
  assert data1, "data1 cannot be empty"
  assert data2, "data2 cannot be empty"
  def ipc(data): return [t[0]/t[1] for t in data]

  data, labels = [], []
  for test, p, s in sorted(dictzip(data1,data2)):
    print(test, p[:2], s[:2])
    labels.append(test)
    data.append(p)
    data.append(ipc(s))
    myboxplot(data, labels=labels, legend=legend, notch=True)

def cmp(path1, path2):
  pure   = pickle.load(open(path1, 'rb')).result.pure
  shared = pickle.load(open(path2, 'rb')).result
  return compare(pure, shared, legend=["isolated meas.", "shared meas."])

def delay(path):
  struct = pickle.load(open(path, 'rb'))
  without   = struct.result.without
  withdelay = struct.result.withdelay
  return compare(without, withdelay, legend=["without delay", "with delay"])

def distribution(data, mode='hist'):
  data = pickle.load(open(data, 'rb'))
  pure = data.result.pure    # data from pure performance isolation
  quasi = data.result.quasi  # data from quasi isolation
  if mode == 'hist':
    for i, (test, ref, measurements) in enumerate(dictzip(pure, quasi)):
      # print(test, len(ref), len(measurements))
      print(ref)
      p.subplot(4,2,i+1)
      p.title(test)
      p.hist(ref, bins=50, label="real isolation", alpha=0.7)
      p.hist(measurements, bins=50, label="quasi-isolation", alpha=0.7)
      p.legend(loc="best")
      p.xlim(0,3)

  elif mode == 'boxplot':
    labels = []
    data = []
    for i, (test, ref, measurements) in enumerate(sorted(dictzip(pure, quasi))):
      labels.append(test)
      data.append(ref)
      data.append(measurements)
    box = myboxplot(data, labels=labels, notch=True)

def distribution_with_subsampling(data, skip=22, mode='hist'):
  standard = data.standard
  withskip = data.withskip

  plots, labels = [], []
  tuples = []
  for test, st_ipcs, raw_skp in dictzip(standard, withskip):
      skp_ipc = []
      for skp in raw_skp:
        instr  = mean(skp['instructions'][skip:])
        cycles = mean(skp['cycles'][skip:])
        if not cycles:
          continue
        skp_ipc.append(instr/cycles)

      tuples.append((test, st_ipcs, skp_ipc))

  tuples = sorted(tuples, key=lambda x: x[0])
  for test, isolated, shared in tuples:
      # if prec >0.1: continue
      plots.append(isolated)
      plots.append(shared)
      labels.append(test)
  myboxplot(plots, labels=labels,
            legend=["frozen env meas. 50ms", "frozen with skip %sms" % (skip*2)])

def analyze(real, samples, skip=0, thr=0.9):
  real = pickle.load(open(real, 'rb'))
  samples = pickle.load(open(samples, 'rb'))
  thr=float(thr)

  def flatten(measurements):
    shared, exclusive = [], []
    for es, ss in measurements:
      exclusive.extend(es[skip:])
      shared.extend(ss[skip:])
    return exclusive, shared

  true_values = OrderedDict()
  for vm, measurements in real.results.items():
    shared, exclusive = flatten(measurements)
    true_values[vm] = mean(shared)/mean(exclusive)
  print(true_values)

  means = OrderedDict()
  nums = []
  avgms, avgdevs = [], []
  #for vm, measurements in sorted(samples.results.items()):
  for vm, measurements in sorted(samples.results.items()):
    print("calculating", vm)
    shared, exclusive = flatten(measurements)
    def myfilter(l): return [e for e in l if e != 0]
    shared = myfilter(shared)
    exclusive = myfilter(exclusive)
    ns = []
    true = true_values[vm]
    for _ in range(1000):
      sh_samples, exc_samples = [], []
      n = 0
      while True:
        n += 1
        sh_samples.append(choice(shared))
        exc_samples.append(choice(exclusive))
        cur = mean(sh_samples)/mean(exc_samples)
        prec = 1 - abs(1-cur/true)
        if prec > thr:
          ns.append(n)
          break
        if n > 20:
          print(vm, "max precision:", prec)
          break
    if not ns:
      print("no data points for", vm)
      continue
    nums.append(ns)
    #m = mean(ns)
    #d = pstdev(ns)
    #rd = d/m*100
    #avgdevs.append(rd)
    #avgms.append(m)
    #print("{vm}: {m:.1f} {rd:.1f}%".format(vm=vm, m=m,d=d,rd=rd))
    #means[vm]=mean(nums)
  ticks = real.mapping
  p.xticks(range(len(ticks)), ticks)
  p.boxplot(nums)
  #import pdb; pdb.set_trace()
  #print(mean(avgms), mean(avgdevs))
  #print("RESULT for thr=%s:" % thr, result)

def ragged(path, label=None, lw=4, color=None):
  lw = float(lw)
  with open(path) as csvfile:
    ts, cycles = [], []
    for t, c, _, typ in CSVReader(csvfile, type=(float,int,str,str)):
        cycles.append(c)
        ts.append(t)
        assert typ == 'cycles'
  print(ts[:10], cycles[:10])
  args = {}
  if color: args['color'] = color
  p.plot(ts, cycles, label=label, lw=lw, **args)

def main():
  parser = ArgumentParser()
  parser.add_argument('-o', '--output', default=None, help="where to save image")
  parser.add_argument('--show', action='store_const', const=True, default=False, help="show plot?")
  parser.add_argument('-t', '--title', help="plot title")
  parser.add_argument('-a', '--annotations', default=None, nargs='+')
  parser.add_argument('--xlim', type=float, nargs=2, help="limit X axis of the plot")
  parser.add_argument('--ylim', type=float, nargs=2, help="limit Y axis of the plot")
  parser.add_argument('-x', '--xlabel', default=None)
  parser.add_argument('-y', '--ylabel', default=None)
  parser.add_argument('-f', '--freq', type=int, default=None, help="CPU frequency")
  parser.add_argument('-p', '--plots', nargs='+', default=[])
  parser.add_argument('-l', '--legacy', action='store_const', const=True, default=False,
                      help="legacy mode")
  args = parser.parse_args()
  print(args)

  if args.legacy:
    for plot in args.plots:
      func, params = invoke(plot, globals())
      print(params)
      func(**params)
  else:
    for plot in args.plots:
      results = pickle.load(open(plot, 'rb'))
      fname = results.f
      func  = globals()[fname]
      func(results.result)

  if args.output or args.show:
    p.legend(loc="best")
    p.tight_layout(pad=0.5)
    font = {'family' : 'normal',
            'weight' : 'bold',
            'size'   : 18}
    p.rc('font', **font)
    if args.xlabel: p.xlabel(args.xlabel)
    if args.ylabel: p.ylabel(args.ylabel)
    if args.xlim: p.xlim(args.xlim)
    if args.ylim: p.ylim(args.ylim)
    if args.title: p.title(args.title)
    if args.output:
      p.savefig(args.output, dpi=300, bbox_inches='tight')
    # p.tight_layout()
    if args.show: p.show()

if __name__ == '__main__':
  main()


from alpha_vantage.timeseries import TimeSeries
from alpha_vantage.techindicators import TechIndicators
import matplotlib.pyplot as plt
from datetime import datetime
import time
import pandas as pd
import numpy as np
from enum import Enum
from statsmodels.tsa.stattools import coint
from staticData import ALPHAVANTAGE_APIKEY, eqArr , INTERVAL_1,INTERVAL_15,INTERVAL_60,OUTPUT_SIZE_FULL,PRICE_CLOSE,OPEN ,HIGH,LOW,CLOSE,VOLUME, NUM_DAYS
from plotFunctions import plotCointegratedPairs, plotZScore
from alphavantageFunctions import getAverageAlphaVantageDataframe

ts = TimeSeries(key=ALPHAVANTAGE_APIKEY, output_format='pandas')
ti = TechIndicators(key=ALPHAVANTAGE_APIKEY, output_format='pandas')

def convertDateIndex(df):
    convertedDate = []
    for i in df:
        newDate = i + ":00"
        convertedDate.append(newDate)

    return convertedDate

def getCorrelationValue(column1, column2):
    return column1.corr(column2)

def getCointegrationScore(equity1, equity2):
    score, pvalue, _ = coint(equity1, equity2)

    return score

def getCointegrationPvalue(equity1, equity2):
    score, pvalue, _ = coint(equity1, equity2)

    return pvalue

def zscore(series):
    return (series - series.mean()) / np.std(series)

def getZScoreSignal(equity1, equity2):
    eq1 = getAverageAlphaVantageDataframe(equity1)
    eq2 = getAverageAlphaVantageDataframe(equity2)
    combinedData = pd.concat([eq1, eq2], axis=1)
    combinedData = combinedData.dropna()

    combinedData['ratios'] = combinedData[equity1] / combinedData[equity2]
    combinedData = combinedData.iloc[::-1] # correct timeline
    combinedData['z'] = zscore(combinedData['ratios'])

    signal = combinedData['z'].iloc[-1]
    print(signal)
    if (signal < 0): # buy bc expect to revert to mean ratio
        buysell = "Buy the ratio(" + str(signal) + ") ---> Buy " + equity1 + " Sell " + equity2
        return buysell
    else:
        buysell = "Sell the ratio(" + str(signal) + ") ---> Sell " + equity1 + " Buy " + equity2
        return buysell

def getCorrelationAndCointegratedPairs(equity1, equity2):
    print("-------------------------- getCorrelationAndCointegratedPairs() --------------------------------")
    time.sleep(30) #alphavantage time lock

    priceData, priceMetadata = ts.get_daily(symbol=equity1, outputsize=OUTPUT_SIZE_FULL)
    priceData['avg1'] = (priceData[HIGH] + priceData[LOW])/2 #assume midpoint of high and low is executed price
    priceData.drop([OPEN, HIGH, LOW, CLOSE, VOLUME], axis=1, inplace=True)
    priceData = priceData.head(NUM_DAYS)

    priceData2, priceMetadata2 = ts.get_daily(symbol=equity2, outputsize=OUTPUT_SIZE_FULL)
    priceData2['avg2'] = (priceData2[HIGH] + priceData2[LOW])/2 #assume midpoint of high and low is executed price
    priceData2.drop([OPEN, HIGH, LOW, CLOSE, VOLUME], axis=1, inplace=True)
    priceData2 = priceData2.head(NUM_DAYS)

    combinedData = pd.concat([priceData, priceData2], axis=1)
    combinedData = combinedData.dropna()

    corr = getCorrelationValue(combinedData['avg1'], combinedData['avg2'])
    pvalue =  getCointegrationPvalue(combinedData['avg1'], combinedData['avg2'])

    print(equity1 + " & " + equity2 + " correlation: " + str(corr) + " coint: " + str(pvalue))
    #print(combinedData)

    return [corr, pvalue, equity1, equity2]

def getAllPairs():
    print("-------------------------- getAllPairs() --------------------------------")
    MIN_PVALUE = 0.05
    correlationArr = []

    for i in range(len(eqArr)):
        for j in range(len(eqArr)):
            if (eqArr[i]['name'] != eqArr[j]['name'] ):
                corrListObj = getCorrelationAndCointegratedPairs(eqArr[i]['name'] , eqArr[j]['name'] )
                print(corrListObj)
                if (corrListObj[1] < MIN_PVALUE):
                    correlationArr.append(corrListObj)

    return correlationArr

def mainzz():

    #res = equities_correlation()
    #print(res)
    res = [[0.8303010316568781, 0.008999534116927945, 'GOOGL', 'NKE'], [0.8465877548675863, 0.014318468108434462, 'GOOGL', 'AMZN'], [0.9230483904816502, 0.013301862473843282, 'NKE', 'AMZN'], [0.8677516812739479, 0.03705038629479192, 'COKE', 'PEP'], [0.8676595604577452, 0.027009363509322395, 'PEP', 'COKE'], [0.9217183557694564, 0.027048611523533345, 'AMZN', 'NKE']]

    equity1 = "COKE"
    equity2 = "PEP"
    #plotCointegratedPairs(equity1,equity2)
    #res = getCorrelationAndCointegratedPairs(equity1,equity2)
    #print(res)
    '''

    for x in range(len(res)):
        signalResult = getZScoreSignal(res[x][2], res[x][3])
        print(signalResult)
    '''
    #signalResult = getZScoreSignal(equity1, equity2)
    getAllPairs()

#mainzz()


# je vais mettre en place des modules pour permettre de manipulaer cette  base de donnée
# me concentrer sur cette base donnée
import sqlite3
from email_slicer import mail_slicer
0
class Manages:
    # dans ces cas si je voie l'utilisation de with conn , c'est
    # mise en place de la base de donnée
    connection = sqlite3.Connection("text.db")
    manage = connection.cursor()

    # toutes les tables dans une liste
    list_table = ["apartment", "user_apartment_wishlist,worksite","floor_plan","restaurant", "plaza","grocery,park"]

    # ! la prochaine fois essaye de faire de telle sorte que dès qu'on rentre un mail il puisse utiliser l'email slicer
    # ! comment sont nommées les variables dans les propriétés
    #! est ce obligé de creer des variables dans le contructeur
    #! pourquoi sauvagarder  les fichiers sql pour une entreprise : est ce pour les migrations ou est ce juste pour faire des requêtes
    # def __init__(self):
    with manage:
        def email_slicer(self):
            emails=[]
            user=[]
            select_tab = self.manage.execute("select email_address from user")
            long_user = select_tab.fetchall()
            for i,der in enumerate(long_user, start = 1): # ! affiche une erreur lorqu'il n' y pas de fetchall() et que tu fais un len
                emails.append(der)
                user.append(mail_slicer(der[0])) # * der[0] pour capturer le mail et le faire dans le mail_slicer
            for j in range(len(long_user)):
                update_user=self.manage.execute("""UPDATE user SET user_names=:user_names WHERE email_address=:email_address""",
                {'email_address':emails[j][0].strip(),'user_names':user[j][0]})
                """
                j = pour retenir le tuple , mais le tuple il y'as une virgule et le mail
                j[0] = pour capturer l'email
                user = une liste de tuple de deux valeurs : le  user et le domaine
                user[j] = pour couple de tuple
                user[j][0] = pour le user uniquement
                user[j][1] = pour le domaine
                """
                update_mail=self.manage.execute("""UPDATE user SET domaine=:domaine WHERE email_address=:email_address""",
                {'email_address':emails[j][0].strip(),'domaine':user[j][1]}
                                            )
                # conn.commit()
    with manage:
        def drop_table(self):
            for tables in self.list_table:
                self.manage.execute(f"DROP TABLE IF EXISTS {tables}")
        # creation des indexes pour faciliter l'utilisation de la table


"""
=================
Template Matching
=================

We use template matching to identify the occurrence of an image patch
(in this case, a sub-image centered on a single coin). Here, we
return a single match (the exact same coin), so the maximum value in the
``match_template`` result corresponds to the coin location. The other coins
look similar, and thus have local maxima; if you expect multiple matches, you
should use a proper peak-finding function.

The ``match_template`` function uses fast, normalized cross-correlation [1]_
to find instances of the template in the image. Note that the peaks in the
output of ``match_template`` correspond to the origin (i.e. top-left corner) of
the template.

.. [1] J. P. Lewis, "Fast Normalized Cross-Correlation", Industrial Light and
       Magic.

"""
# import numpy as np
# import matplotlib.pyplot as plt
#

from skimage import data
from skimage.feature import match_template
# import time
#
#
# image = data.coins()
# coin = image[170:220, 75:130]
#
#
# start_time = time.time()
# result = match_template(image, coin)
# end_time = time.time()
# print("the image size is :", image.shape)
# print("the match cost:", (end_time - start_time)*1000)
# ij = np.unravel_index(np.argmax(result), result.shape)
# x, y = ij[::-1]
#
# fig = plt.figure(figsize=(8, 3))
# ax1 = plt.subplot(1, 3, 1)
# ax2 = plt.subplot(1, 3, 2)
# ax3 = plt.subplot(1, 3, 3, sharex=ax2, sharey=ax2)
#
# ax1.imshow(coin, cmap=plt.cm.gray)
# ax1.set_axis_off()
# ax1.set_title('template')
#
# ax2.imshow(image, cmap=plt.cm.gray)
# ax2.set_axis_off()
# ax2.set_title('image')
# # highlight matched region
# hcoin, wcoin = coin.shape
# rect = plt.Rectangle((x, y), wcoin, hcoin, edgecolor='r', facecolor='none')
# ax2.add_patch(rect)
#
# ax3.imshow(result)
# ax3.set_axis_off()
# ax3.set_title('`match_template`\nresult')
# # highlight matched region
# ax3.autoscale(False)
# ax3.plot(x, y, 'o', markeredgecolor='r', markerfacecolor='none', markersize=10)
#
# plt.show()

import cv2
import numpy as np
import time
from matplotlib import pyplot as plt

img_rgb = cv2.imread('D:/pictures/barcode/3.png')
img_gray = cv2.cvtColor(img_rgb, cv2.COLOR_BGR2GRAY)
template = cv2.imread('D:/pictures/barcode/bar.png', 0)
w, h = template.shape[::-1]

start_time = time.time()
res = cv2.matchTemplate(img_gray, template, cv2.TM_CCOEFF_NORMED)
end_time = time.time()
print("match cost : ", (end_time - start_time) * 1000)
threshold = 0.8
start_time = time.time()
result = match_template(img_gray, template)
end_time = time.time()
print("the image size is :", img_gray.shape)
print("the match cost:", (end_time - start_time)*1000)

# umpy.where(condition[, x, y])
# Return elements, either from x or y, depending on condition.
# If only condition is given, return condition.nonzero().
loc = np.where(res >= threshold)

for pt in zip(*loc[::-1]):
    cv2.rectangle(img_rgb, pt, (pt[0] + w, pt[1] + h), (0, 0, 255), 2)

cv2.imwrite('res.png', img_rgb)


class Node:
    def __init__(self, data):
        self.right = self.left = None
        self.data = data

class Solution:
    def insert(self, root, data):
        if root is None:
            return Node(data)
        else:
            if data <= root.data:
                cur = self.insert(root.left, data)
                root.left = cur
            else:
                cur = self.insert(root.right, data)
                root.right = cur
        return root

    def level_order(self, root):
        tree_height = self.get_height(root)
        for level in range(1, tree_height + 1):
            self.print_nodes_in_level(root, level)

    def print_nodes_in_level(self, root, level):
        if root is not None:
            if level == 1:
                print(root.data, end=' ')
            elif level > 1:
                self.print_nodes_in_level(root.left, level - 1)
                self.print_nodes_in_level(root.right, level - 1)

    def get_height(self, root):
        if root is None:
            return 0
        else:
            current = root
            height_left = self.get_height(current.left)
            height_right = self.get_height(current.right)
            return 1 + max(height_left, height_right)

T = int(input())
myTree = Solution()
root = None
for i in range(T):
    data = int(input())
    root = myTree.insert(root, data)
myTree.level_order(root)


'''
The Module can be used to read file and analyse the data. It has thr parts:
1) Read csv file, convert data into list, such that each row is a list and there is a dictionary which allow
access to different columns.
2) Data imputation: This involves changing strings to integers (list converts all objects into strings)
imputing no values to some value.
3) Summarizing the quantitative and qualitative variables. Provides, mean, median, max and min for quantitative
data and mode, categories for qualitative variables.
4) Print the summaries.
'''

import csv
from collections import Counter
import statistics as st
import re

csv_file = open('data.csv', encoding = "utf8", newline = '')
data_csv = csv.reader(csv_file, delimiter=',')

def convert_csv_into_list(data_csv):
	'''For data in csv file is converted into a list of all values. Also an access dictionary is
	drawn to access all columns of the data. This returns'''
	line_count = 0
	data = []
	access = {}
	for row in data_csv:
		if line_count == 0:
			start = 0
			for keys in row:
				access.update({keys:start})
				start += 1
			col_list = row
			line_count += 1
		else:
			line_count += 1
			data.append(row)
	return (data, access, col_list)

def convert_string_to_integer(data, access):
	'''returns the columns Positive Feedback Count, Rating and Age are converted to integers. The first
	column is unnamed and gives the serial number. This is also converted to integers.'''
	for i, row in enumerate(data):
		index = [0, 2, 5, 7]
		for j in index:
			data[i][j] = int(data[i][j])

# We can use col_name_cat = ['Division Name', 'Department Name', 'Class Name']
def summary_of_qualitative(data, access, column):
	'''the function returns unique set of categories and the counts of that categories.'''
	list_of_column = [row[access[column]] for row in data]
	column_unique = set(list_of_column)
	value_cnt = Counter(list_of_column)
	print('Counts : {}'.format(len(list_of_column)))
	print('Unique categories are:')
	for i in column_unique:
		print(i)
	print('Mode of the categories is {}'.format(max(value_cnt)))

def summary_of_quantitative(data, access, column):
	'''function returns the summary of the quatitative data in the column specified.'''
	list_of_column = [row[access[column]] for row in data]
	counts = len(list_of_column)
	mean_col = st.mean(list_of_column)
	median_col = st.median(list_of_column)
	min_col = min(list_of_column)
	max_col = max(list_of_column)
	print('Counts : {:20}'.format(counts))
	print('Mean : {:22.2f}'.format(mean_col))
	print('Median : {:20.1f}'.format(median_col))
	print('Minimum :{:20}'.format(min_col))
	print('Maximum :{:20}'.format(max_col))

def print_summary(data, access, col_list):
	'''something to add....'''
	col_name = ', '.join(col_list) #row 23
	print("Column names are {}".format(col_name[1:]))
	print("Processed {} lines.".format(len(data)))
	print('The following are the columns with type:')
	for key in access:
		print('{0:35} type is : {1}'.format(key, type(data[0][access[key]])))

def impute_data(data, access, column, from_value, to_value):
	'''function imputes the data accoding from the value to a given value. For example if we want to
	impute the quantitative values with mean or median.'''
	for i, row in enumerate(data):
		if row[access[column]] == from_value:
			row[access[column]] = to_value

### Analyse the data:
(data, access, col_list) = convert_csv_into_list(data_csv)
def analyse_data():
	'''Analysis part.'''
	print_summary(data, access, col_list)
	print('')
	print('All columns are in string format. We have to convert some columns to integer format.')
	convert_string_to_integer(data, access)
	print_summary(data, access, col_list)
	print('')
	print('Now the columns Age, Positive Feedback Count and Rating are integers.')
	col_list2 = ['Rating', 'Positive Feedback Count', 'Age']
	for column in col_list2:
		print('The summary of {} is:'.format(column))
		summary_of_quantitative(data, access, column)

analyse_data()
col_list3 = ['Division Name', 'Department Name', 'Class Name']
for i in col_list3:
	impute_data(data, access, i, '', 'Others')
for i in col_list3:
	print('The summary of {} is:'.format(i))
	summary_of_qualitative(data, access, i)

csv_file.close()


import asyncio
from typing import Final, List, Tuple

from libs.pmon.pmon import (  # noqa: E402
    PMON,
    Devices,
    Events,
    PMONDevice,
    Registers,
    Size,
)
from libs.logger import pmon_logger as logger
from libs.vme_constants import PCI_INTEL_VENDORID

def get_bitmask(hibit: int, lobit: int) -> int:
    maskhi: int = 1 << (hibit + 1)
    masklo: int = 1 << lobit
    return maskhi - masklo

def get_bitfield(data: int, startbit: int, endbit: int) -> int:
    value: int = data >> startbit
    mask: int = (1 << (endbit - startbit + 1)) - 1
    result = value & mask
    logger.debug(
        "[BITFIELD] {0:032b}[{1}:{2}] = {3:0b} x {4:0b} = {5:0b}".format(
            data, startbit, endbit, value, mask, result
        )
    )
    return result

def get_bitvalue(nr: int) -> int:
    return 1 << nr

async def measure(
    pmon: PMON,
    node: str,
    unit_ctrl: Registers,
    unit_ctr: Registers,
    event: Events,
    time: int,
) -> int:
    # Function set_event is : setting counter, enabling, reseting init value
    pmon[node].reg(unit_ctrl).set_event(event)
    await asyncio.sleep(time)
    value: int = pmon[node].reg(unit_ctr).get(Size.COUNTER)
    return value

def humanbytes(data: int) -> str:
    """Return the given bytes as a human friendly KB, MB, GB, or TB string."""
    b = float(data)
    kb = float(1024)
    mb = float(kb**2)  # 1,048,576
    gb = float(kb**3)  # 1,073,741,824
    tb = float(kb**4)  # 1,099,511,627,776

    if b < kb:
        return "{0} {1}".format(int(b), "Byte/s" if 0 == b > 1 else "Bytes/s")
    elif kb <= b < mb:
        return "{0:.2f} KB/s".format(b / kb)
    elif mb <= b < gb:
        return "{0:.2f} MB/s".format(b / mb)
    elif gb <= b < tb:
        return "{0:.2f} GB/s".format(b / gb)
    return "{0:.2f} TB/s".format(b / tb)

def count_bw(cas_count_rd: int, cas_count_wr: int) -> Tuple[int, int, int]:
    mem_bw_rd: int = cas_count_rd * 64
    mem_bw_wr: int = cas_count_wr * 64
    mem_bw_total: int = mem_bw_rd + mem_bw_wr
    return (mem_bw_rd, mem_bw_wr, mem_bw_total)

class BitArray(object):
    def __init__(self, length: int):
        self.values = bytearray(b"\x00" * (length // 8 + (1 if length % 8 else 0)))
        self.length = length

    def __setitem__(self, index: int, value: int) -> None:
        value = int(bool(value)) << (7 - index % 8)
        mask = 0xFF ^ (7 - index % 8)
        self.values[index // 8] &= mask
        self.values[index // 8] |= value

    def __getitem__(self, index: int) -> int:
        mask = 1 << (7 - index % 8)
        return bool(self.values[index // 8] & mask)

    def __len__(self) -> int:
        return self.length

    def __repr__(self) -> str:
        return "<{}>".format(", ".join("{:d}".format(value) for value in self))  # type: ignore

class Dev2SocketID:
    LAST_BUSID: Final[int] = 256
    SOCKETS_MASK: Final[int] = 0x00000007
    socket_ranges: List[int] = []
    socket_nodeid: List[int] = []
    socket_devs: List[PMONDevice] = []

    @staticmethod
    def scan_socketids(pmon: PMON) -> None:
        Dev2SocketID.socket_devs = pmon.scan(
            deviceids=Devices.SKX_UBOX_DID, vendorids=PCI_INTEL_VENDORID
        )
        for dev in Dev2SocketID.socket_devs:
            # first get node id for the local socket (socket number 0-7)
            nodeid: int = (
                pmon[dev.path].reg(Registers.ubox_lnid_offset).get(Size.DWORD)
                & Dev2SocketID.SOCKETS_MASK
            )
            # Every 3bits of the Node ID mapping register maps to a specific node
            # Read the Node ID Mapping Register and find the node that matches
            # the gid read from the Node ID configuration register (above).
            # e.g. Bits 2:0 map to node 0, bits 5:3 maps to package 1, etc.
            mapping: int = pmon[dev.path].reg(Registers.ubox_gid_offset).get(Size.DWORD)
            for bits in range(0, 8):
                if nodeid == (mapping >> (3 * bits)) & Dev2SocketID.SOCKETS_MASK:
                    Dev2SocketID.socket_nodeid.append(bits)
                    Dev2SocketID.socket_ranges.append(dev.bus)
                    break
        # add the last bus number to the socketID range
        Dev2SocketID.socket_ranges.append(Dev2SocketID.LAST_BUSID)

    @staticmethod
    def get(pmon: PMON, dev: PMONDevice) -> int:
        # Lets optimize this function a bit.
        if not Dev2SocketID.socket_devs:
            Dev2SocketID.scan_socketids(pmon)
        # Find the socketID within two socket_ranges values
        for idx, range in enumerate(Dev2SocketID.socket_ranges):
            if (
                Dev2SocketID.socket_ranges[idx] <= dev.bus
                and dev.bus < Dev2SocketID.socket_ranges[idx + 1]
            ):
                return Dev2SocketID.socket_nodeid[idx]
        return -1


#24
# s = bin(10)
# outcome = int(s,2)
# if outcome is str:
#     print("is str")
# else:
#     print("not")

T = int(input())
for i in range(0,T):
    outcome = []
    n = int(input())
    for num in range(1,n+1):
        s = bin(num)
        flag = True
        for j in range(0,len(s)-1):
            if s[j] == s[j+1]:
                flag = False
                break
        if flag:
            outcome.append(num)
    for j in range(0,len(outcome)-1):
        print(outcome[j],end=" ")
    print(outcome[len(outcome)-1])


import pyxel
import random
import math

pyxel.init(200,200)

class Ball:
    speed = 3
    def __init__(self):
        self.x = random.randint(0, 199)
        self.y = 0
        angle = math.radians(random.randint(30, 150))
        self.vx = math.cos(angle) * Ball.speed
        self.vy = math.sin(angle) * Ball.speed

Var= [Ball(), Ball(), Ball()]
padx = 100
score = 0
miss = 0
balls = 1
p = 0
num1 = 10
num2 = 7
b = 0

pyxel.sound(0).set(note='c3e3g3c4c4', tone='s', volume='4', effect=('n' * 4 + 'f'), speed=7)
pyxel.sound(1).set(note='f3 b2 f2 b1  f1 f1 f1 f1',tone='p',volume=('4' * 4 + '4321'),effect=('n' * 7 + 'f'),speed=9,)

def update():
    global Var, padx, score, miss, balls, p, num1, num2, b
    for i in range(0, balls):
        if Var[i].x >= 200 or Var[i].x <= 0:
            Var[i].vx = -Var[i].vx
            num1 = random.randint(4,10)
            num2 = random.randint(1,15)
        Var[i].x += Var[i].vx
        Var[i].y += Var[i].vy
        if Var[i].y >= 200:
            pyxel.play(0, 1)
            Var[i].x = random.randint(0, 199)
            Var[i].y = 0
            angle = math.radians(random.randint(30,150))
            Var[i].x = math.cos(angle) * Ball.speed
            Var[i].y = math.sin(angle) * Ball.speed
            Var[i] = Ball()
            miss += 1
            num1 = random.randint(0, 10)
            num2 = random.randint(1,15)
        padx = pyxel.mouse_x
        if Var[i].y >= 195 and padx-20 <= Var[i].x <= padx+20:
            pyxel.play(0, 0)
            score += 10
            Var[i] = Ball()
            Ball.speed += 0.2
            Var[i].x = random.randint(0, 199)
            Var[i].y = 0
            angle =math.radians(random.randint(30,150))
            Var[i].vx = math.cos(angle) * Ball.speed
            Var[i].vy = math.sin(angle) * Ball.speed
            p += 1
            num1 = random.randint(4,10)
            num2 = random.randint(1,15)
            if p == 10 and balls < 3:
                balls += 1
                Ball.speed -= 2
                p = 0

def draw():
    global Var, padx, score, miss, balls, p, num1, num2, b
    if miss >= 10:
        pyxel.text(80, 90, "GAME OVER", 7)
        pyxel.stop()
    else:
        pyxel.cls(num2 - 1)
        for i in range(0, balls):
            pyxel.circ(Var[i].x, Var[i].y, num1, num2)
        pyxel.rect(padx-20, 195, 40, 5, 15)
        pyxel.text(10, 10, "score: " + str(score), 7)

pyxel.run(update, draw)


from __future__ import annotations
import os
import subprocess  # nosec - commands are trusted
import typing as ty
from dataclasses import dataclass

def is_available() -> bool:
    """ Returns true iff the current system has a SLURM controller enabled."""
    if not try_run_command(["sinfo"]):
        return False
    return True

def enable() -> None:
    """ Enable the use of SLURM for Loihi. """
    if not is_available():
        raise ValueError("Attempting to use SLURM for Loihi but "
                         "SLURM controller is not available.")

    os.environ["SLURM"] = "1"
    os.environ.pop("NOSLURM", None)

def disable() -> None:
    """ Disable the use of SLURM for Loihi. """
    os.environ.pop("SLURM", None)
    os.environ["NOSLURM"] = "1"

def set_board(board: ty.Optional[str],
              partition: ty.Optional[str] = None) -> None:
    """ Set the Loihi board in SLURM to run on, or clear
    any board set if board is None.

    Use `get_boards` to see all available boards.

    Parameters
    ----------
    board : Optional[str]
        The Loihi board to use. If None, no board will be specified.
    partition : Optional[str], default = None
        The partition that is being used for SLURM jobs. If not None,
        it will be compared against the partition of the specified
        board, and a ValueError will be raised if they are not equal.
    """
    if board is None:
        os.environ.pop("BOARD", None)
        return

    board_info = get_board_info(board)

    if board_info is None or "down" in board_info.state:
        raise ValueError(
            f"Attempting to use SLURM for Loihi but board {board} "
            f"is not found or board is down. Run sinfo to check "
            f"available boards.")

    if partition and partition != board_info.partition:
        raise ValueError(
            f"Attempting to use SLURM for Loihi with board {board} "
            f"and partition {partition} but board is not in partition. "
            f"Specify only board or partition.")

    os.environ["BOARD"] = board

def set_partition(partition: ty.Optional[str]) -> None:
    """ Set the partition in SLURM to run on, or clear any partition
    set if partition is None.

    Parameters
    ----------
    partition : Optional[str]
        The partition to use. If None, no partition will be specified.
    """
    if partition is None:
        os.environ.pop("PARTITION", None)
        return

    partition_info = get_partition_info(partition)

    if partition_info is None or "down" in partition_info.state:
        raise ValueError(
            f"Attempting to use SLURM for Loihi but partition {partition} "
            f"is not found or is down. Run sinfo to check available "
            f"partitions.")

    os.environ["PARTITION"] = partition

def partition() -> str:
    """Get the partition information."""
    if "PARTITION" in os.environ.keys():
        return os.environ["PARTITION"]

    return "Unspecified"

def get_partitions() -> ty.List[PartitionInfo]:
    """Returns the list of available partitions from the SLURM controller
    or an empty list if SLURM is not available or has no partitions.

    Returns
    -------
    List[PartitionInfo]
        A list of all available partitions.
    """
    if not is_available():
        return []

    lines = try_run_command(["sinfo"])
    del lines[0]  # Remove header of table

    def parse_partition(line: str) -> PartitionInfo:
        fields = line.split()
        name = fields[0]
        avail = fields[1] if len(fields) > 1 else ''
        limit = fields[2] if len(fields) > 2 else ''
        nodes = fields[3] if len(fields) > 3 else ''
        state = fields[4] if len(fields) > 4 else ''
        nodel = fields[5] if len(fields) > 5 else ''
        return PartitionInfo(name=name,
                             available=avail,
                             timelimit=limit,
                             nodes=nodes,
                             state=state,
                             nodelist=nodel)
    return [parse_partition(line) for line in lines]

def get_partition_info(partition_name: str) -> ty.Optional[PartitionInfo]:
    """Get the SLURM info for the specified partition, if available.

    Parameters
    ----------
    partition_name : str
        The name of the partition to return.

    Returns
    -------
    Optional[PartitionInfo]
        The partition information for the partition or None if the SLURM
        controller does not have the specified partition.
    """
    matching_partitions = [p for p in get_partitions()
                           if p.name == partition_name]

    return next(iter(matching_partitions), None)

@dataclass
class PartitionInfo:
    name: str = ""
    available: str = ""
    timelimit: str = ""
    nodes: str = ""
    state: str = ""
    nodelist: str = ""

def get_boards() -> ty.List[BoardInfo]:
    """Returns the list of available boards from the SLURM controller
    or an empty list if SLURM is not available or has no boards.

    Returns
    -------
    List[BoardInfo]
        A list of all available boards.
    """
    if not is_available():
        return []

    lines = try_run_command(["sinfo", "-N"])
    del lines[0]  # Remove header of table

    def parse_board(line: str) -> BoardInfo:
        fields = line.split()

        return BoardInfo(nodename=fields[0],
                         partition=fields[2],
                         state=fields[3])

    return [parse_board(line) for line in lines]

def get_board_info(nodename: str) -> ty.Optional[BoardInfo]:
    """Get the SLURM info for the specified board, if available.

    Parameters
    ----------
    nodename : str
        The name of the board to return.

    Returns
    -------
    Optional[BoardInfo]
        The information for the board or None if the SLURM
        controller does not have the specified board.
    """
    matching_boards = [b for b in get_boards()
                       if b.nodename == nodename]

    return next(iter(matching_boards), None)

@dataclass
class BoardInfo:
    nodename: str = ""
    partition: str = ""
    state: str = ""

def try_run_command(command: ty.List[str]) -> ty.List[str]:
    """Executes a command, captures the output, and splits it into a list of
    lines (strings). Returns an empty list if executing the command raises
    and exception.

    Parameters
    ----------
    command : List[str]
        Command and options, for instance 'sinfo -N' becomes ['sinfo', '-N']

    Returns
    -------
    List[str]
        Output of stdout of the command, separated into a list of lines (str).
    """
    try:
        kwargs = dict(capture_output=True, check=True, timeout=1)
        process = subprocess.run(command, text=True, **kwargs)  # nosec # noqa
        return process.stdout.split("\n")

    except subprocess.SubprocessError:
        return []


import unittest
from unittest import mock

class TestS3ObjectStore(unittest.TestCase):

    TEST_VALUE = "test-value"

    @classmethod
    def setUpClass(cls):
        cls.ray_mock = mock.MagicMock()

        cls.module_patcher = mock.patch.dict("sys.modules", {"ray": cls.ray_mock})
        cls.module_patcher.start()

        from deltacat.io.s3_object_store import S3ObjectStore

        cls.object_store = S3ObjectStore(bucket_prefix="test")

        super().setUpClass()

    @classmethod
    def tearDownClass(cls) -> None:
        cls.module_patcher.stop()

    @mock.patch("deltacat.io.s3_object_store.s3_utils.upload")
    def test_put_many_sanity(self, mock_upload):
        self.ray_mock.cloudpickle.dumps.return_value = self.TEST_VALUE
        result = self.object_store.put_many(["a", "b"])

        self.assertEqual(2, len(result))
        self.assertEqual(2, mock_upload.call_count)

    @mock.patch("deltacat.io.s3_object_store.s3_utils.download")
    def test_get_many_sanity(self, mock_download):
        self.ray_mock.cloudpickle.loads.return_value = self.TEST_VALUE

        result = self.object_store.get_many(["test", "test"])

        self.assertEqual(2, len(result))
        self.assertEqual(2, mock_download.call_count)

    @mock.patch("deltacat.io.s3_object_store.s3_utils.download")
    def test_get_sanity(self, mock_download):
        self.ray_mock.cloudpickle.loads.return_value = self.TEST_VALUE

        result = self.object_store.get("test")

        self.assertEqual(self.TEST_VALUE, result)
        self.assertEqual(1, mock_download.call_count)

    @mock.patch("deltacat.io.s3_object_store.s3_utils.upload")
    def test_put_sanity(self, mock_upload):
        self.ray_mock.cloudpickle.dumps.return_value = self.TEST_VALUE

        result = self.object_store.put("test")

        self.assertIsNotNone(result)
        self.assertEqual(1, mock_upload.call_count)


# -*- coding: utf-8 -*-
"""
Created on Tue Feb  4 21:33:55 2020

@author: EmrahSariboz
"""
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
from sklearn.datasets import load_breast_cancer
from sklearn.metrics import accuracy_score

class AdalineGD():
    def __init__(self, learning_rate = 0.01, epoch = 50, random_state = 1):
        self.learning_rate = learning_rate
        self.epoch = epoch
        self.random_state = random_state

    def fit(self, X, y):
        rgen = np.random.RandomState(self.random_state)
        self.w_ = rgen.normal(loc = 0.0, scale = 0.01, size = 1+X.shape[1])

        self.cost_= []

        for i in range(self.epoch):
            net_input = self.net_input(X)
            output = self.activation(net_input)

            errors = y - output

            self.w_[1:] += self.eta * X.T.dot(errors)
            self.w_[0] += self.eta * errors.sum()
            cost = (errors**2).sum() / 2.0
            self.cost_.append(cost)
        return self

    def net_input(self, X):
        print(np.dot(X, self.w_[1:]) + self.w_[0])
        print("fsdf")
        return np.dot(X, self.w_[1:]) + self.w_[0]

    def activation(self, X):
        return X
    def predict(self, X):
        """Return class label after unit step"""
        return np.where(self.activation(self.net_input(X))>= 0.0, 1, -1)

class Perceptron():
    def __init__(self, learning_rate, epoch= 50, random_state = 1):
        self.learning_rate = learning_rate
        self.epoch = epoch
        self.random_state = random_state

    def fit(self, X, y):
        rgen = np.random.RandomState(self.random_state)
        self.w_ = rgen.normal(loc = 0.0, scale = 0.01, size = 1+X.shape[1])
        self.errors_ = []
        for i in range(self.epoch):
            error = 0
            self.prediction_result = []
            for xi, yi in zip(X, y):
                misclassified = (yi - self.predict(xi))
                self.prediction_result.append(int(self.predict(xi)))
                update = self.learning_rate * (misclassified)
                self.w_[1:] += update * xi
                self.w_[0]  += update
                error += int(misclassified != 0.0)
            print("Accuracy score on Epoch {} is {} ".format(i, accuracy_score(self.prediction_result, y)))
            print("The cost at epoch {} is {}".format(i, error))
            self.errors_.append(error)
        return -1

    def net_input(self, X):
        return np.dot(X, self.w_[1:]) + self.w_[0]

    def predict(self, X):
        return np.where(self.net_input(X) >= 0.0, 1, -1)

ppn = AdalineGD(0.1, 10)

df = pd.read_csv("irishDataset.csv")

y= df.iloc[0:100, 4]
y = np.where(y == 'setosa', -1, 1)

X_irish = df.iloc[0:100, [0, 2]].values
ppn.fit(X_irish, y)

plt.plot(range(1, len(ppn.errors_) + 1), ppn.errors_, marker = 'o')

plt.show()


list_input = [("Alexander_1", "Paul_1"),
              ("Anna", "Petetr_1"),
              ("Elizabeth", "Petetr_1"),
              ("Petetr_2", "Alexei"),
              ("Petetr_3", "Anna"),
              ("Paul_1", "Petetr_3"),
              ("Alexei", "Petetr_1"),
              ("Nicolaus_1", "Paul_1")]

def find_couple(find, list_input):
    count = 1
    ch = 0
    leng = len(list_input)
    while True:
        if find == list_input[ch][0]:
            count = count + 1
            find = list_input[ch][1]
            ch = 0
        ch = ch + 1
        if ch == leng:
            break
    return count

def find(list_input):
    dict_res = {}
    for couple in list_input:
        count = find_couple(couple[1], list_input)
        dict_res[couple[0]] = count
    return dict_res

result_dic = find(list_input)
for i in sorted(result_dic):
    print(i, result_dic[i])


import numpy as np
import matplotlib.pyplot as plt

import csv
import math
from typing import List, Tuple
import time

class ActivationFunction:
    def __init__(self, activation_function: callable, activation_derivative: callable):
        self.activation_function = activation_function
        self.activation_derivative = activation_derivative

class RecursiveNeuralNetwork:
    def __init__(
        self, input_size: int, activation_function: ActivationFunction, seed: int = 0
    ):
        """A simple 1 layer recurent neural network

        Args:
            input_size (int): The size of the input / output / hidden layer
            activation_function (ActivationFunction): which activation function we will adjust our data by
            seed (int, optional): consistency is key! Try to use a seed to get repeatable data. Defaults to 0.
        """

        self.input_size = input_size
        self.activation_function = activation_function
        self.seed = seed

        self.recursion_predictions = np.array([])
        self.input_data = np.array([])

        # Setting a seed, so we can always reproduce results
        if self.seed:
            np.random.seed(self.seed)

        # We only want one output at a time, and we use that to recursively feed foward
        self.weights = np.random.rand(1, input_size)
        # Since we will always have an output size of 1, we want to have a bias of 1
        self.biases = np.random.rand(1, 1)

    def _forward_propagation(
        self, inputs: np.array, step_size: int = 0, is_training: bool = False
    ) -> np.array:
        """A function to recurently predict data

        Args:
            inputs (np.array): the data to start our model with
            step_size (int, optional): how far into the future to predict. Defaults to 0.
            is_training (bool, optional): an indicator letting us know if we need to store any data. Defaults to False.

        Returns:
            np.array: The predictions that the AI made
        """

        # if we are trainging, we want to store all of our predictions in a list, so we can adjust the model during back propigation
        if is_training:
            self.recursion_predictions = np.array([])
            self.input_data = inputs

        # Itterating over the stepsize to make a prediction, and then a followup prediction off of that prediction
        for _ in range(step_size):
            # forward prop
            prediction = self.activation_function.activation_function(
                np.dot(self.weights, inputs) + self.biases
            )

            # rolling our data and adding the prediction
            # ex.
            # [ 1, 2, 3 ] -> [ 2, 3, 1 ]
            #  pred 4 -> [2, 3, 4 ]
            inputs = np.roll(inputs, -1)
            inputs[-1] = prediction

            # if training we want to store our predictions
            if is_training:
                self.recursion_predictions = np.append(
                    self.recursion_predictions, prediction
                )

        return inputs

    def _backwards_propagation_through_time(
        self, error_derivatives: np.array, learning_rate: float = 0.1
    ):
        """A function to adjust the weights and biases of our RNN

        Args:
            error_derivatives (np.array): 2 * (prediction - target output) * actionvation_derivatives( prediction )
            learning_rate (float, optional): How fast to grow the model by. Defaults to .1.
        """
        # setting the weights and bias adjustment to 0
        weight_delta = 0
        bias_delta = 0

        # the error derivate should be a shape ( input_size, 1 )
        # we only want the want the final error derivate, because that is the predicted value
        # ex
        # with a step of 1, we get...
        # Input         : [ A, B, C ]
        #
        # Prediction    : [ B, C, P ]
        # Expected      ; [ B, C, D ]
        #
        # Notice how the error derivative for index, 0 and 1 are not needed, because we are not predicting with them
        # we are looking for the error of the last element that we should have gotten ( P & D )
        error_derivatives = error_derivatives[-1]

        # Itterating over the predictions and grabbing the updated error_derivatives until we reach the first prediction
        for index, prediction in enumerate(self.recursion_predictions[:-1]):
            '''
            When viewing back propigation through time, imagine that you are itterating over a model of that size. For instance...
            If I have a layer of 3 nodes, and I stepped forward 4 times in my prediction, my model can be represented as :

            W1
            W2
            W3

            in1 - h11 - h21 - h31 - out1
            in2 - h12 - h22 - h32 - out2
            in3 - h13 - h23 - h33 - out3

            each - represents a fully connected layer. This means that while we only have 1 set of weights and biases, we really
            made our model into a deep neural network by propigating the data forward 4 amount of times.
            This also means, that in adjusting the weights and biases,
            we too need to adjust them for the new 4 deep neural network that we created recurently
            '''
            # getting the input for the given state.
            # logic explained
            # predictions = [ 4, 5, 6 ]
            # input = [ 1, 2, 3 ]
            #
            # recursive predictions data = [ 4, 5 ]
            # since smaller than 3
            # recusive data inputs = [ 5, 4 ] join [ 3, 2, 1 ]
            # recusive data inputs = [ 5, 4, 3, 2, 1 ]
            # recusive data inputs = [ 5, 4, 3 ]
            #
            # if it was >= the size, we then just make sure that the predictions is the size
            recursive_input_data = self.recursion_predictions[ index + 1 : len(self.recursion_predictions) - 1 ]
            if len(recursive_input_data) < self.input_size:
                recursive_input_data = np.append(recursive_input_data[::-1], self.input_data[::-1])
                recursive_input_data = recursive_input_data[0 : self.input_size]
                recursive_input_data = recursive_input_data[::-1]
            else:
                recursive_input_data = recursive_input_data[0 : self.input_size]

            # Updating the weight and bias delta, before finding the new error derivative
            # We want to update a delta, because we still need the weights and biases that we used to predict our data in finding the new error derivative
            weight_delta += ( np.dot(np.array(recursive_input_data), error_derivatives) * learning_rate / len(self.recursion_predictions) )
            bias_delta += ( np.sum(error_derivatives, axis=0) * learning_rate / len(self.recursion_predictions) )

            # Calculating the new error derivative and grabbing its last elm (see comments above on why we want only the last elm)
            error_derivatives = np.dot( self.weights, error_derivatives ) * self.activation_function.activation_derivative(recursive_input_data)
            error_derivatives = [0][-1]

        # Updating the weight and bias delta
        weight_delta += (
            np.dot(np.array(self.input_data).T, error_derivatives)
            * learning_rate
            / len(self.recursion_predictions)
        )
        bias_delta += (
            np.sum(error_derivatives, axis=0)
            * learning_rate
            / len(self.recursion_predictions)
        )

        # updating the weights and biases by their delta
        self.weights -= np.array([weight_delta])
        self.biases -= bias_delta

    def predict_full(self, inputs: np.array, step_size: int = 0) -> np.array:
        """An abstracted function for forward propagation

        Args:
            inputs (np.array): The data that we are to predict off of
            step_size (int, optional): how far into the future to predict. Defaults to 0.

        Returns:
            np.array: an array that is the same size as the inputs. Containing the snippet of the final prediction(s)
        """
        _ = self._forward_propagation(
            inputs=np.array(inputs), step_size=step_size, is_training=True
        )
        return self.recursion_predictions

    def predict(self, inputs: np.array, step_size: int = 0) -> List[float]:
        """An abstracted function for forward propagation

        Args:
            inputs (np.array): The data that we are to predict off of
            step_size (int, optional): how far into the future to predict. Defaults to 0.

        Returns:
            List[float]: All of the predicted values from the start to the end of the step_size
        """
        return self._forward_propagation(inputs=inputs, step_size=step_size)

    def train(
        self,
        training_inputs: List[float],
        training_outputs: List[float],
        step_size: int = 0,
        learning_rate: float = 0.01,
    ):
        """An abstracted function of back propagation through time.

        Args:
            training_inputs (List[float]): The data that we are to predict off of
            training_outputs (List[float]): The data that we are to match
            step_size (int, optional): how far into the future to predict. Defaults to 0.
            learning_rate (float, optional): How fast to grow the model by. Defaults to .01.
        """
        # itterating  over a list of all of the training inputs and outputs
        for training_input, training_output in zip(training_inputs, training_outputs):
            # making a prediction
            prediction = self._forward_propagation(
                inputs=np.array(training_input), step_size=step_size, is_training=True
            )
            # calculating the error derivative
            error_derivatives = (
                2
                * (prediction - np.array(training_output))
                * self.activation_function.activation_derivative(prediction)
            )
            # adjusting the model
            self._backwards_propagation_through_time(
                error_derivatives=error_derivatives, learning_rate=learning_rate
            )

    def reset(self):
        """A function to rest the neural network"""
        self.recursion_predictions = np.array([])
        self.input_data = np.array([])

        if self.seed:
            np.random.seed(self.seed)
        # We only want one output at a time, and we use that to recursively feed foward
        self.weights = np.random.rand(1, self.input_size)
        # Since we will always have an output size of 1, we want to have a bias of 1
        self.biases = np.random.rand(1, 1)

"""
ACTIVATION FUNCTIONS
--------------------
"""

# Leaky Relu (BEST!!!)
def _leaky_relu(x, alpha=0.01):
    return np.maximum(x, alpha * x)

def _leaky_relu_derivative(x, alpha=0.01):
    dx = np.ones_like(x)
    dx[x < 0] = alpha
    return dx

LEAKY_RELU = ActivationFunction(
    activation_function=_leaky_relu, activation_derivative=_leaky_relu_derivative
)

# Relu
def _relu(x):
    return np.maximum(x, 0)

def _relu_derivative(x):
    return np.ones_like(x)

RELU = ActivationFunction(
    activation_function=_relu, activation_derivative=_relu_derivative
)

# Sigmoid
def _sigmoid(x):
    return 1 / (1 + np.exp(-x))

def _sigmoid_derivative(x):
    sigmoid_x = _sigmoid(x)
    return sigmoid_x * (1 - sigmoid_x)

SIGMOID = ActivationFunction(
    activation_function=_sigmoid, activation_derivative=_sigmoid_derivative
)

"""
GRAPHS
------
"""

def get_sin(size: int):
    return [(math.sin(x) + 1) / 2 for x in range(size)]

def get_y_x(size: int):
    return [float(x) / size for x in range(size)]

def get_sigmoid(size: int):
    return [_sigmoid(x / (size // 8)) for x in range(-(size // 2), (size // 2))]

def get_uber_2019_2022():
    # Open the CSV file
    # https://www.kaggle.com/datasets/varpit94/uber-stock-data
    # *NOTE* WARNING, this is not stock advice, this is to illistrate a use case for RNNs

    data = []

    REDUCE_RATIO = 10
    with open("UBER.csv", "r") as file:
        # Create a CSV reader object
        csv_reader = csv.reader(file)

        # Read the CSV file row by row
        for index, row in enumerate(csv_reader):
            if index % REDUCE_RATIO:
                continue
            # Concatenate all values in the row into a single string
            try:
                data.append((float(row[1]) - 25) / 40)
            except:
                continue

    return data

def get_training_in_out(
    data: List[float], input_size: int, step_size: int
) -> Tuple[List[float], List[float]]:
    """A function to turn 1 list into the input outputs needed for training

    Args:
        data (List[float]): the list that we have of Y points over X time
        input_size (int): how large the rnn input is
        step_size (int): how far into the future to make the prediction per model

    Returns:
        Tuple[List[float], List[float]]: training inputs and outputs
    """
    inputs = []
    outputs = []
    for index in range(len(data[: -(input_size + step_size - 1)])):
        inputs.append(list(data[index : index + input_size]))
        outputs.append(list(data[index + step_size : index + step_size + input_size]))

    return inputs, outputs

def main():
    INPUT_SIZE = 16
    STEP_SIZE = 1
    LEARNING_RATE = 0.01
    EPOCHES = 100
    PREDICT_LENGTH = 30

    rnn = RecursiveNeuralNetwork(
        input_size=INPUT_SIZE,
        activation_function=LEAKY_RELU,
        seed=1
    )

    data = get_uber_2019_2022()  # get_sin(INPUT_SIZE*2)

    training_inputs, training_outputs = get_training_in_out(data, INPUT_SIZE, STEP_SIZE)

    for _ in range(EPOCHES):
        rnn.train(
            training_inputs=training_inputs,
            training_outputs=training_outputs,
            step_size=STEP_SIZE,
            learning_rate=LEARNING_RATE,
        )
        time.sleep(0.01)

    # Creating the plot
    fig, axes = plt.subplots(2, 2, figsize=(10, 8))
    # Full Data Graph
    axes[0, 0].plot([i for i in range(len(data))], data, label="Full Data")
    axes[0, 1].set_title("True Data")
    axes[0, 0].legend()
    # AI vs Expected Start
    guess = rnn.predict_full( inputs=np.array(training_inputs[0]), step_size=PREDICT_LENGTH )
    axes[0, 1].plot( [i for i in range(PREDICT_LENGTH + len(training_inputs[0]))], np.append(training_inputs[0], guess), label="AI", )
    axes[0, 1].plot( [i for i in range(len(training_inputs[0]))], training_inputs[0], label="Given" )
    axes[0, 1].set_title("Plot of AI and Expected Start")
    axes[0, 1].legend()
    # AI vs Expected MidPoint
    guess2 = rnn.predict_full(inputs=np.array( training_inputs[len(training_inputs) // 2]), step_size=PREDICT_LENGTH, )
    axes[1, 0].plot( [i for i in range(PREDICT_LENGTH + len(data) // 2)], np.append(data[: len(data) // 2], guess2), label="AI", )
    axes[1, 0].plot( [i for i in range(len(data[: len(data) // 2]))], data[: len(data) // 2], label="Given", )
    axes[1, 0].set_title("Plot of AI and Expected MidPoint")
    axes[1, 0].legend()  # Display legend
    # AI vs Expected End
    guess3 = rnn.predict_full( inputs=np.array(training_outputs[-1]), step_size=PREDICT_LENGTH )
    axes[1, 1].plot( [i for i in range(PREDICT_LENGTH + len(data))], np.append(data, guess3), label="AI", )
    axes[1, 1].plot([i for i in range(len(data))], data, label="Given")
    axes[1, 1].set_title("Plot of AI and Expected End")
    axes[1, 1].legend()  # Display legend

    plt.show()

if __name__ == "__main__":
    main()