# based on code from https://stackabuse.com/minimax-and-alpha-beta-pruning-in-python

import time

class Game:
    MINIMAX = 0
    ALPHABETA = 1
    HUMAN = 2
    AI = 3

    def __init__(self, n=3, b=0, bboard=[], s=3, d1=0, d2=0, t=0.0):
        self.n = n # board size
        self.b = b #number of blocks
        self.bboard = bboard
        self.s = s #winning size
        self.d1 = d1  # Max depth adversial search value
        self.d2 = d2  # Max depth adversial search value
        self.t = t  # Max value of time t
        self.initialize_game()

    def initialize_game(self):
        self.current_state = [['.' for x in range(self.n)] for y in range(self.n)]

        if self.bboard == []:
            for i in range(self.b):
                X = random.randint(0, self.n - 1)
                Y = random.randint(0, self.n - 1)
                while self.current_state[X][Y] == '#':
                    X = random.randint(0, self.n - 1)
                    Y = random.randint(0, self.n - 1)
                self.current_state[X][Y] = '#'
                self.bboard.append([X, Y])
        else:
            for element in self.bboard:
                self.current_state[element[0]][element[1]] = '#'

        # Player X always plays first
        self.player_turn = 'X'

    def draw_board(self):
        print()
        for y in range(self.n):
            for x in range(self.n):
                print(F'{self.current_state[x][y]}', end="")
            print()
        print()

    def is_valid(self, px, py):
        if px not in range(self.n) or py not in range(self.n):
            return False
        elif self.current_state[px][py] != '.':
            return False
        else:
            return True

    def is_end(self):

        # Vertical win
        for i in range(self.n):
            lineWin = 0
            for j in range(self.n - 1):
                if self.current_state[j][i] == '.' or self.current_state[j][i] == '*' \
                        or self.current_state[j][i] != self.current_state[j + 1][i]:
                    lineWin = 0
                else:
                    lineWin += 1

                if lineWin == self.line_size - 1:
                    return self.current_state[j][i]

        # Horizontal win
        for j in range(self.n):
            lineWin = 0
            for i in range(self.n - 1):
                if self.current_state[j][i] == '.' or self.current_state[j][i] == '*' \
                        or self.current_state[j][i] != self.current_state[j][i + 1]:
                    lineWin = 0
                else:
                    lineWin += 1

                if lineWin == self.s - 1:
                    return self.current_state[j][i]

        # Main diagonal win
        # Takes into account off-diagonals (Top half left to right)
        for j in range((self.n + 1) - self.s):
            lineWin = 0
            for i in range(self.n - 1 - j):
                if self.current_state[i][i + j] == '.' or self.current_state[i][i + j] == '*' \
                        or self.current_state[i][i + j] != self.current_state[i + 1][i + j + 1]:
                    lineWin = 0
                else:
                    lineWin += 1

                if lineWin == self.s - 1:
                    return self.current_state[i][i + j]

        # Second diagonal win
        # Takes into account off-diagonals (Top half right to left)
        for j in range((self.n + 1) - self.s):
            lineWin = 0
            for i in range(self.n - 1 - j):
                if self.current_state[i][self.n - 1 - i - j] == '.' \
                        or self.current_state[i][self.n - 1 - i - j] == '*' \
                        or self.current_state[i][self.n - 1 - i - j] \
                        != self.current_state[i + 1][self.n - 1 - (i + 1) - j]:
                    lineWin = 0
                else:
                    lineWin += 1

                if lineWin == self.s - 1:
                    return self.current_state[i][self.n - 1 - i - j]

        # Need to account for off-diagonals for board size > line size
        if self.n > self.s:

            # Off-diagonal left side
            # Excludes main diagonal
            for j in range(self.n - self.s):
                lineWin = 0
                for i in range(self.n - 2 - j):
                    if self.current_state[i + j + 1][i] == '.' or self.current_state[i + j + 1][i] == '*' \
                            or self.current_state[i + j + 1][i] != self.current_state[i + j + 2][i + 1]:
                        lineWin = 0
                    else:
                        lineWin += 1

                    if lineWin == self.s - 1:
                        return self.current_state[i + j + 1][i]

            # Off-diagonal right side
            # Excludes second diagonal
            for j in range(self.n - self.s):
                lineWin = 0
                for i in range(self.n - 2 - j):
                    if self.current_state[i + j + 1][self.n - 1 - i] == '.' \
                            or self.current_state[i + j + 1][self.n - 1 - i] == '*' \
                            or self.current_state[i + j + 1][self.n - 1 - i] != self.current_state[i + j + 2][
                        self.n - 1 - (i + 1)]:
                        lineWin = 0
                    else:
                        lineWin += 1

                    if lineWin == self.s - 1:
                        return self.current_state[i + j + 1][self.n - 1 - i]

        # Is whole board full?
        for i in range(self.n):
            for j in range(self.n):
                # There's an empty field, we continue the game
                if self.current_state[i][j] == '.':
                    return None
        # It's a tie!
        return '.'

    def check_end(self):
        self.result = self.is_end()
        # Printing the appropriate message if the game has ended
        if self.result is not None:
            if self.result == 'X':

                print('The winner is X!')
                self.winning_e = self.heuristics[0]
            elif self.result == 'O':

                print('The winner is O!')
                self.winning_e = self.heuristics[1]
            elif self.result == '.':

                print("It's a tie!")
                self.winning_e = -1
            self.initialize_game()
        return self.result

    def input_move(self):
        while True:
            print(F'Player {self.player_turn}, enter your move:')
            px = int(input('enter the x coordinate: '))
            py = int(input('enter the y coordinate: '))

            if px in self.colLabels:
                px = self.colLabels[px]
            else:
                print('The move is not valid! Try again.')
                continue

            if self.is_valid(px, py):
                return px, py
            else:
                print('The move is not valid! Try again.')

    def switch_player(self):
        if self.player_turn == 'X':
            self.player_turn = 'O'
        elif self.player_turn == 'O':
            self.player_turn = 'X'
        return self.player_turn

    def minimax(self, max=False, depth=0):
        # Minimizing for 'X' and maximizing for 'O'
        # Possible values are:
        # -inf - win for 'X'
        # 0  - a tie
        # inf  - loss for 'X'
        # We're initially setting it to large positive and negative numbers as worse than the worst case:

        value = 10000000
        if max: value = -10000000
        x = None
        y = None
        result = self.is_end()
        if round(time.time() - self.currentTime, 7) >= (9.5 / 10) * self.max_AI_time:
            self.number_of_evaluated_nodes += 1

            if str(depth) in self.depth_dict:
                self.depth_dict[str(depth)] += 1
            else:
                self.depth_dict[str(depth)] = 1

        elif result == 'X':
            return -1000000, x, y
        elif result == 'O':
            return 1000000, x, y
        elif result == '.':
            return 0, x, y
        elif self.max_depth[0] == depth + 1:
            self.number_of_evaluated_nodes += 1

            if str(depth) in self.depth_dict:
                self.depth_dict[str(depth)] += 1
            else:
                self.depth_dict[str(depth)] = 1

        elif self.max_depth[1] == depth + 1:
            self.number_of_evaluated_nodes += 1

            if str(depth) in self.depth_dict:
                self.depth_dict[str(depth)] += 1
            else:
                self.depth_dict[str(depth)] = 1

        for i in range(self.n):
            for j in range(self.n):
                if self.current_state[i][j] == '.':
                    if max:
                        self.current_state[i][j] = 'O'
                        (v, _, _) = self.minimax(max=False, depth=depth + 1)
                        if v > value:
                            value = v
                            x = i
                            y = j
                    else:
                        self.current_state[i][j] = 'X'
                        (v, _, _) = self.minimax(max=True, depth=depth + 1)
                        if v < value:
                            value = v
                            x = i
                            y = j
                    self.current_state[i][j] = '.'

        return value, x, y

    def alphabeta(self, alpha=-2, beta=2, max=False, depth=0):
        # Minimizing for 'X' and maximizing for 'O'
        # Possible values are:
        # -inf - win for 'X'
        # 0  - a tie
        # inf  - loss for 'X'
        # We're initially setting it to inf++  or -inf-- as worse than the worst case:

        value = 10000000
        if max: value = -10000000
        x = None
        y = None
        result = self.is_end()
        if round(time.time() - self.currentTime, 7) >= (9.5 / 10) * self.max_AI_time:
            self.number_of_evaluated_nodes += 1

            if str(depth) in self.depth_dict:
                self.depth_dict[str(depth)] += 1
            else:
                self.depth_dict[str(depth)] = 1

        elif result == 'X':
            return -1000000, x, y
        elif result == 'O':
            return 1000000, x, y
        elif result == '.':
            return 0, x, y
        elif self.max_depth[0] == depth + 1:
            self.number_of_evaluated_nodes += 1

            if str(depth) in self.depth_dict:
                self.depth_dict[str(depth)] += 1
            else:
                self.depth_dict[str(depth)] = 1

        elif self.max_depth[1] == depth + 1:
            self.number_of_evaluated_nodes += 1

            if str(depth) in self.depth_dict:
                self.depth_dict[str(depth)] += 1
            else:
                self.depth_dict[str(depth)] = 1

        for i in range(self.n):
            for j in range(self.n):
                if self.current_state[i][j] == '.':
                    if max:
                        self.current_state[i][j] = 'O'
                        (v, _, _) = self.alphabeta(alpha, beta, max=False, depth=depth + 1)
                        if v > value:
                            value = v
                            x = i
                            y = j
                    else:
                        self.current_state[i][j] = 'X'
                        (v, _, _) = self.alphabeta(alpha, beta, max=True, depth=depth + 1)
                        if v < value:
                            value = v
                            x = i
                            y = j
                    self.current_state[i][j] = '.'
                    if max:
                        if value >= beta:
                            return value, x, y
                        if value > alpha:
                            alpha = value
                    else:
                        if value <= alpha:
                            return value, x, y
                        if value < beta:
                            beta = value
        return value, x, y

    def play(self, algo=None, player_x=None, player_o=None):
        if algo is None:
            algo = self.ALPHABETA
        if player_x is None:
            player_x = self.HUMAN
        if player_o is None:
            player_o = self.HUMAN

        self.turn_number = 1
        self.total_time = 0
        self.total_evaluated_nodes = 0
        self.total_average_depths = 0
        self.total_depth_dict = {}

        while True:
            self.currentTime = 0
            self.draw_board(f=f)
            if self.check_end(f=f):
                return
            start = time.time()
            self.currentTime = time.time()

            self.number_of_evaluated_nodes = 0
            self.depth_dict = {}

            if algo == self.MINIMAX:
                if self.player_turn == 'X':
                    (_, x, y) = self.minimax(max=False)
                else:
                    (_, x, y) = self.minimax(max=True)
            else:
                if self.player_turn == 'X':
                    (m, x, y) = self.alphabeta(max=False)
                else:
                    (m, x, y) = self.alphabeta(max=True)
            end = time.time()

            self.total_time += round(end - start, 7)
            self.total_evaluated_nodes += self.number_of_evaluated_nodes

            for key in self.depth_dict:
                if str(int(key) + (self.turn_number - 1)) in self.total_depth_dict:
                    self.total_depth_dict[str(int(key) + (self.turn_number - 1))] += self.depth_dict[key]
                else:
                    self.total_depth_dict[str(int(key) + (self.turn_number - 1))] = self.depth_dict[key]

            print(F'Evaluation time: {round(end - start, 7)}s\n')
            print(F'Number of evaluated nodes: {self.number_of_evaluated_nodes}\n')
            print(F'Evaluations by depth: {self.depth_dict}\n')

            if self.number_of_evaluated_nodes > 0:
                sum = 0
                for key in self.depth_dict:
                    sum += int(key) * self.depth_dict[key]
                print(F'Average evaluation depth: {sum / self.number_of_evaluated_nodes}\n')
                self.total_average_depths += sum / self.number_of_evaluated_nodes

            if (self.player_turn == 'X' and player_x == self.HUMAN) or \
                    (self.player_turn == 'O' and player_o == self.HUMAN):
                if self.recommend:
                    print(F'Evaluation time: {round(end - start, 7)}s')
                    print(F'Recommended move: '
                          F'x = {list(self.colLabels.keys())[list(self.colLabels.values()).index(x)]}, '
                          F'y = {y}')
                (x, y) = self.input_move()
                print(F'Player {self.player_turn} plays: '
                        F'x = {x} '
                        F'y = {y}\n')
            if (self.player_turn == 'X' and player_x == self.AI) or (self.player_turn == 'O' and player_o == self.AI):
                print(F'Evaluation time: {round(end - start, 7)}s')
                print(F'Player {self.player_turn} under AI control plays: '
                        F'x = {list(self.colLabels.keys())[list(self.colLabels.values()).index(x)]}, '
                        F'y = {y}\n')
                print(F'Player {self.player_turn} under AI control plays: '
                      F'x = {list(self.colLabels.keys())[list(self.colLabels.values()).index(x)]}, '
                      F'y = {y}')
            self.current_state[x][y] = self.player_turn
            self.switch_player()
            self.turn_number += 1

def main():
    {}

if __name__ == "__main__":
    main()


__author__ = "X."
__email__ = "xzhang@westwoodrobotics.io"
__copyright__ = "Copyright 2021 Westwood Robotics"
__date__ = "Apr. 07, 2021"

__version__ = "0.0.1"
__status__ = "Prototype"

import pdb
import struct
import time
import sys

from itertools import chain

import numpy as np
import serial

from bruce_sense.TIMING_TABLE import *
from bruce_sense.CONTROL_TABLE import *

class PKT(object):
    def __init__(self, port, baudrate, timeout=0.0):
        if not self.debug:
            self.ser = serial.Serial(
                port,
                baudrate,
                bytesize=serial.EIGHTBITS,
                parity=serial.PARITY_NONE,
                stopbits=serial.STOPBITS_ONE,
                timeout=timeout  # Default to 0 for non-blocking mode
            )
        else:
            pass

        if sys.version_info[0] < 3: # Python 2
            self.ord_adapt = lambda x : ord(x)
            self.sustr_adapt = lambda val: ''.join(chr(idx) for idx in val)
            self.sustr_loop_adapt = lambda idx, val: ''.join(chr(idx) for idx in val[idx:idx+4])
            pass
        else:  # Python 3
            self.ord_adapt = lambda x : x
            self.sustr_adapt = lambda val: bytearray(val)
            self.sustr_loop_adapt = lambda idx, val: bytearray(val[idx:idx+4])

    def close(self):
        """
        Close the serial port
        """
        if self.ser:
            self.ser.close()

    def __del__(self):
        self.close()

    def __write_packet(self, packet):
        if not self.debug:
            self.ser.reset_input_buffer()
            self.ser.write(bytearray(packet))
        else:
            print("[DEBUG] :: __write_packet(): {}".format(packet))
            pdb.set_trace()

    def __read_packet(self):
        # TODO: Should we use checksum to verify return?
        status_packet = []
        while self.ser.inWaiting() < 3:
            pass
        status_packet.extend(self.ser.read(3))
        if status_packet:
            extlen = self.ord_adapt(status_packet[2])
            while self.ser.inWaiting() < extlen:
                pass
            status_packet.extend(self.ser.read(extlen))
            # Temporary absolute error watch:
            if len(status_packet) < (extlen+3):
                print("ser.read() returned too soon, status_packet length is only", len(status_packet))
                error_code = 0b10000001
                status_packet = [self.ord_adapt(idx) for idx in status_packet[4:-1]]
            else:
                error_code = status_packet[3]
                status_packet = [self.ord_adapt(idx) for idx in status_packet[4:-1]]
        return status_packet, error_code

    def __write_data(self, add_list, data, reg_type=None):
        if reg_type == 'cfg':
            instruction = INSTRUCTION.WRITE_CFG
        elif reg_type == 'stat':
            instruction = INSTRUCTION.WRITE_STAT

        # Convert float32 data into 4 bytes and make add_data_pair
        hex_data = []
        for d in data:
            hex = self.__float32_to_hex(d)
            hex = [hex[i:i + 2] for i in range(2, len(hex), 2)]
            hex = tuple([int(x, 16) for x in hex])
            hex_data.append(hex)
        add_data_pair = []
        for i in range(len(add_list)):
            add_data_pair.append(add_list[i])
            add_data_pair.extend(hex_data[i])
        pkt_len = len(add_data_pair)+2

        checksum = self.chksum(pkt_len, instruction, add_data_pair)

        # Generate packet
        packet = self.__packet_generator(pkt_len, instruction, add_data_pair, checksum)

        # Write packet
        self.__write_packet(packet)

    def write_status_data(self, add_list, data_list):
        """
        This command is to write data to the status registers.
        :type add_list: list
        :type data_list: list
        """
        self.__write_data(add_list, data_list, reg_type='stat')
        time.sleep(DATA_WRITE_DELAY)

    def write_config_data(self, add_list, data_list):
        """
        This command is to write data to the config registers.
        :type add_list: list
        :type data_list: list
        """
        self.__write_data(add_list, data_list, reg_type='cfg')
        time.sleep(DATA_WRITE_DELAY)

    def __read_data(self, add_list, reg_type):
        """
        :type add_list: list
        """
        if reg_type == 'cfg':
            instruction = INSTRUCTION.READ_CFG
        elif reg_type == 'stat':
            instruction = INSTRUCTION.READ_STAT

        pkt_len = len(add_list)+2

        checksum = self.chksum(pkt_len, instruction, add_list)

        packet = self.__packet_generator(pkt_len, instruction, add_list, checksum)

        self.__write_packet(packet)

        rtn_pkt_len = 4*pkt_len - 3  # Return packet length

        # Timeout prevention if communication error starts occuring
        t_bus_init = time.time()
        while True:
            if self.ser.inWaiting() > rtn_pkt_len-1:
                # Whole return packet has arrived
                break
            if time.time() - t_bus_init > TIMEOUT_MAX:
                print("[BRUCE_SENSE | WARNING] :: Status response timed out. Re-sending the same packet.")
                print(self.ser.inWaiting())
                self.ser.reset_output_buffer()
                self.__write_packet(packet)
                t_bus_init = time.time()
        # while self.ser.inWaiting() < 4:
        #     pass

        status, error_code = self.__read_packet()

        return self.__hex_to_float32(status), error_code

    def read_status_data(self, add_list):
        """
        This command is to read data from the status registers.
        """
        return self.__read_data(add_list, reg_type='stat')

    def read_config_data(self, add_list):
        """
        This command is to read data from the config registers.
        """
        return self.__read_data(add_list, reg_type='cfg')

    def _ping(self):
        """
        Function used to detect a motor. Will return firmware and hardware version info.
        Return None if pinging unsuccessful.
        """
        # Type of instruction
        instruction = INSTRUCTION.PING

        # Number of parameters
        pkt_len = 2

        # Create checksum
        checksum = self.chksum(pkt_len, instruction, (0,))

        # Write packet
        self.__write_packet((0xFF, 0xFF, pkt_len, instruction, checksum))
        start_time = time.time()
        while self.ser.inWaiting() < 1:
            if time.time()- start_time > PING_TIMEOUT:
                # Timeout
                return None
            else:
                pass

        # Read status
        ping_status, error_code = self.__read_packet()

        return ping_status, error_code

    def _read_dump(self):
        """
        This command is to read data from dumper
        :return:
        """
        # Timeout prevention if communication error starts occuring
        incoming_bytes = [0, 0]
        got_packet = False
        t_bus_init = time.time()
        self.ser.reset_input_buffer()
        while True:
            if self.ser.inWaiting() > 1:
                # Check for start of packet
                incoming_bytes.extend(self.ser.read(1))
                incoming_bytes.pop(0)
                if ((incoming_bytes[1]<<8)|incoming_bytes[0]) == 0xFFFF:
                    # This is the beginning of the packet
                    got_packet = True
                    incoming_bytes.extend(self.ser.read(1))
                    break
            if time.time() - t_bus_init > TIMEOUT_MAX:
                print("[BRUCE_SENSE | WARNING] :: Status response timed out. Is dumper alright?")
                t_bus_init = time.time()
        if got_packet:
            t_bus_init = time.time()
            pktlen = incoming_bytes[2]
            while self.ser.inWaiting() < pktlen:
                if time.time() - t_bus_init > TIMEOUT_MAX:
                    print("[BRUCE_SENSE | WARNING] :: Status response timed out waiting for rest of packet")
            status_packet = self.ser.read(pktlen)
        # Temporary absolute error watch:
        if len(status_packet) < pktlen:
            print("ser.read() returned too soon, status_packet length is only", len(status_packet))
            error_code = 0b00000001
        elif status_packet[-1] is not 0x0F:
            print("Corrupted packet.")
            error_code = 0b00000010
        else:
            error_code = status_packet[0]
            contact = status_packet[-2]
        status_packet = [self.ord_adapt(idx) for idx in status_packet[1:-2]]
        return self.__hex_to_float32(status_packet), contact, error_code

    def _read_dump_YOLO(self):
        """
        This command is to read data from dumper, but it only read once and return None if no data in buffer
        :return:
        """
        # Timeout prevention if communication error starts occuring
        incoming_bytes = [0, 0]
        got_packet = False
        t_bus_init = time.time()
        while True:
            if self.ser.inWaiting() > 1:
                # Check for start of packet
                incoming_bytes.extend(self.ser.read(1))
                incoming_bytes.pop(0)
                if ((incoming_bytes[1]<<8)|incoming_bytes[0]) == 0xFFFF:
                    # This is the beginning of the packet
                    got_packet = True
                    incoming_bytes.extend(self.ser.read(1))
                    break
            if time.time() - t_bus_init > TIMEOUT_MAX:
                # Timeout with no data
                return None
        if got_packet:
            t_bus_init = time.time()
            pktlen = incoming_bytes[2]
            while self.ser.inWaiting() < pktlen:
                if time.time() - t_bus_init > TIMEOUT_MAX:
                    print("[BRUCE_SENSE | WARNING] :: Status response timed out waiting for rest of packet")
            status_packet = self.ser.read(pktlen)
            self.ser.reset_input_buffer()
        # Temporary absolute error watch:
        if len(status_packet) < pktlen:
            print("ser.read() returned too soon, status_packet length is only", len(status_packet))
            error_code = 0b00000001
        elif status_packet[-1] is not 0x0F:
            print("Corrupted packet.")
            error_code = 0b00000010
        else:
            error_code = status_packet[0]
            contact = status_packet[-2]
        status_packet = [self.ord_adapt(idx) for idx in status_packet[1:-2]]
        return self.__hex_to_float32(status_packet), contact, error_code

    # ===== Utility functions
    def __packet_generator(self, length, instruction, add_data_pair, checksum):
        """
        :type add_data_pair: list
        """
        l = (0xFF, 0xFF, length, instruction, add_data_pair, checksum)
        return tuple((chain(*(i if isinstance(i, list) else (i,) for i in l))))
        # return (0xFF, 0xFF, m_id, length, instruction, param_n, data, checksum)

    def __float32_to_hex(self, val):
        retval = hex(struct.unpack('<I', struct.pack('>f', val))[0])
        if retval[-1] == 'L':
            retval = retval[:-1]
        if len(retval) < 10:
            length = 10-len(retval)
            retval = '0x'+length*'0'+retval[2:]
        return retval

    def __hex_to_float32(self, val):
        if len(val) > 4:
            tmpval = []
            for idx in range(0, len(val), 4):
                tmpval.append(struct.unpack('<f', self.sustr_loop_adapt(idx, val))[0])
        else:
            tmpval = struct.unpack('<f', self.sustr_adapt(val))[0]
        return tmpval

    def chksum(self, length, instruction, param_n):
        return 255 - ((length + instruction + sum(param_n)) % 256)

    def _echo(self, add_list):
        """
        :type add_list: list
        """
        instruction = INSTRUCTION.READ_STAT

        pkt_len = len(add_list) + 2

        checksum = self.chksum(pkt_len, instruction, add_list)

        packet = self.__packet_generator(pkt_len, instruction, add_list, None, checksum)

        self.__write_packet(packet)

        rtn_pkt_len = 4 * pkt_len - 3  # Return packet length

        # Timeout prevention if communication error starts occuring
        rtn = []
        t_bus_init = time.time()
        while True:
            if time.time() - t_bus_init > TIMEOUT_MAX:
                print("Timeout.")
                break
        if self.ser.in_waiting > 0:
            rtn = list(self.ser.read(50))
            print("rtn: {}".format(rtn))
        return rtn


"""
@file: detect_edges.py
@brief: This script finds you the edges of the conveyor band in an image.
@author: Gökhan Koçmarlı (github.com/electricalgorithm)
@company: YongaTek (yongatek.com)
"""
import cv2
import numpy
import math
import argparse

def apply_gaussian_filter(image: numpy.ndarray, window_size=51, gaussian_sigma=5) -> numpy.ndarray:
    """
    Function returns the cv2 Image instance that
    has Gaussian blur with predefined window size
    and gaussian sigma ratio.
    :param image: Original image to perform blur onto.
    :param window_size: Default is 5.
    :param gaussian_sigma: Default is 5.
    :return: The blurred image as a numpy.ndarray.
    """
    return cv2.GaussianBlur(image, (window_size, window_size), gaussian_sigma)

def apply_binarization(image: numpy.ndarray) -> numpy.ndarray:
    """
    The function gets an image input, and apply Otsu's Method
    to find its binary representation.
    :param image: Original 3-channel image to perform Otsu's method.
    :return: The binary image as a numpy.ndarray.
    """
    grayscale_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    _, binary_image = cv2.threshold(grayscale_image, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)
    return binary_image

def apply_dilation_erosion(image: numpy.ndarray, kernel_size=35) -> numpy.ndarray:
    """
    The function removes unnecassary objects in the picture with using
    dilation firstly with very-high kernel size, and erosion to save
    real sizes of the object considered.
    :param image: A binary image that has more than one object.
    :param kernel_size: Default is 35 (experimentally set).
    :return: The image's numpy.ndarray that has less objects.
    """
    element = cv2.getStructuringElement(cv2.MORPH_RECT,
                                        (2 * kernel_size + 1, 2 * kernel_size + 1),
                                        (kernel_size, kernel_size))
    dilated_image = cv2.dilate(image, element)
    return cv2.erode(dilated_image, element)

def apply_canny_detection(image: numpy.ndarray, min_threshold=100, max_threshold=250) -> numpy.ndarray:
    """
    This function applies the Canny algorithm to distinguish a object border.
    :param image: A binary image.
    :param min_threshold: Default is 100.
    :param max_threshold: Default is 250.
    :return: A numpy.ndarray that has only borders of the image.
    """
    return cv2.Canny(image, min_threshold, max_threshold)

def apply_hough_lines(original_image: numpy.ndarray, dilated_image: numpy.ndarray, threshold=175) -> None:
    """
    This method firstly finds the border lines using Hough's transformation method with experimentally
    predetermined threshold. Afterwards, it marks the original image with that border line.
    :param original_image: A image to put found lines into.
    :param dilated_image: The image that will be looked for lines.
    :param threshold: Default is 175.
    :return: None.
    """
    # Find the line.
    lines = cv2.HoughLines(dilated_image, 1, numpy.pi / 180, threshold, None, 0, 0)

    # Mark the line into the original image.
    if lines is not None:
        for i in range(0, len(lines)):
            rho = lines[i][0][0]
            theta = lines[i][0][1]
            a = math.cos(theta)
            b = math.sin(theta)
            x0 = a * rho
            y0 = b * rho
            pt1 = (int(x0 + 1000 * (-b)), int(y0 + 1000 * a))
            pt2 = (int(x0 - 1000 * (-b)), int(y0 - 1000 * a))
            cv2.line(original_image, pt1, pt2, (0, 0, 255), 3, cv2.LINE_AA)

def get_image_location_from_argparser() -> str:
    """
    This function creates the argument parser and returns the image file location.
    :return: File location as string
    """
    parser = argparse.ArgumentParser(description="This script finds you the edges of the conveyor band in an image.")
    parser.add_argument("-i", "--inputImage", nargs="+", required=True, help="Provide the image file location.")
    args = parser.parse_args()
    return args.inputImage[0]

if __name__ == "__main__":
    # Get the file location, and check it.
    file_location = get_image_location_from_argparser()
    if not file_location:
        raise Exception("You have to give a file location using --inputImage flag.")

    # Read the image as ndarray.
    input_img = cv2.imread(file_location)
    if input_img.size == 0:
        raise Exception("The file you provided couldn't find.")

    # Make the operations.
    blurred_img = apply_gaussian_filter(input_img)
    binary_img = apply_binarization(blurred_img)
    dilated_img = apply_dilation_erosion(binary_img)
    cannyed_img = apply_canny_detection(dilated_img)

    # Create a copy of original to show line in that photo.
    output_img = numpy.copy(input_img)
    apply_hough_lines(output_img, cannyed_img)

    # Show the results.
    cv2.imshow("Conveyor Edge Detection Results | YongaTek", output_img)
    cv2.waitKey(0)


# Задача 10
# На столе лежат n монеток. Некоторые из них лежат вверх решкой, а некоторые – гербом.
# Выведите минимальное количество монет, которые нужно перевернуть.

import random
try:

    n = int(input("Введите число монет: "))
    coins = []
    for i in range(n):
        coins.append(random.randint(0,1))

    print(coins)
    heads = sum(coins)
    tails = n - heads

    if heads == 0 or tails == 0:
        print("Ничего переворачивать не нужно")
    elif heads > tails:
        print(f"Вам нужно перевернуть  {tails} монеток")
    else:
        print(f"Вам нужно перевернуть  {heads} монеток")
except:
    print("У вас нет монет, в следующий раз приходите с монетками!")


import pytest, time, requests, re, os
import pandas as pd
from unittest.mock import call
from pandas.util.testing import assert_frame_equal, assert_series_equal

from crypto_analytics.data_source import DataSource
from crypto_analytics.types import Interval
from crypto_analytics.types.symbol import Symbol, SymbolPair, CryptoCompareSymbolPairConverter, CryptoCompareSymbolPair
from crypto_analytics import utils

# mock data

cc_ohclv_success = {'Response': 'Success', 'Type': 100, 'Aggregated': False, 'Data': [{'time': 1560042540, 'close': 7906.14, 'high': 7906.45, 'low': 7903.86, 'open': 7903.86, 'volumefrom': 3.41, 'volumeto': 26958.13}, {'time': 1560042600, 'close': 7906.14, 'high': 7906.14, 'low': 7906.14, 'open': 7906.14, 'volumefrom': 0, 'volumeto': 0}], 'TimeTo': 1560042600, 'TimeFrom': 1560042540, 'FirstValueInArray': True, 'ConversionType': {'type': 'direct', 'conversionSymbol': ''}, 'RateLimit': {}, 'HasWarning': False}
cc_ohclv_success_df = pd.DataFrame([cc_ohclv_success['Data'][0]])
cc_ohclv_null_fsym_param = {'Response': 'Error', 'Message': 'fsym param is empty or null.', 'HasWarning': False, 'Type': 2, 'RateLimit': {}, 'Data': {}, 'ParamWithError': 'fsym'}
cc_ohclv_warning = {'Response': 'Warning', 'Message': 'rate limit reached.', 'Type': 100, 'Aggregated': False, 'Data': [{'time': 1560042540, 'close': 7906.14, 'high': 7906.45, 'low': 7903.86, 'open': 7903.86, 'volumefrom': 3.41, 'volumeto': 26958.13}, {'time': 1560042600, 'close': 7906.14, 'high': 7906.14, 'low': 7906.14, 'open': 7906.14, 'volumefrom': 0, 'volumeto': 0}], 'TimeTo': 1560042600, 'TimeFrom': 1560042540, 'FirstValueInArray': True, 'ConversionType': {'type': 'direct', 'conversionSymbol': ''}, 'RateLimit': {}, 'HasWarning': True}

# fixtures

@pytest.fixture(scope='function')
def setup_existing_file(tmp_dir):
    def setup_fn(filename, data_frame):
        filepath = os.path.join(tmp_dir, filename)
        data_frame.to_csv(filepath, index=False)
        return filepath

    return setup_fn

# DataSource tests

def test_data_source_data(init_abc):
    # get
    data_source = init_abc(DataSource)
    data_source._data = pd.DataFrame([[1, 2], [3, 4]], columns=['a', 'b'])
    # when
    result = data_source.data
    # then
    expected = pd.DataFrame([[1, 2], [3, 4]], columns=['a', 'b'])
    assert_frame_equal(result, expected)

def test_data_source_first_write(init_abc, tmp_dir):
    # given
    data_source = init_abc(DataSource)
    data_source._data = pd.DataFrame([[4, 3], [2, 1]], columns=['a', 'b'])
    filepath = os.path.join(tmp_dir, 'test_data_source_first_write.csv')
    # when
    data_source.write(filepath)
    # then
    result = pd.read_csv(filepath)
    expected = pd.DataFrame([[4, 3], [2, 1]], columns=['a', 'b'])
    assert_frame_equal(result, expected)

def test_data_source_write_existing_file(init_abc, setup_existing_file):
    # given
    existing_file_data = pd.DataFrame([[1, 2], [3, 4]], columns=['a', 'b'])
    filepath = setup_existing_file('test_data_source_write_existing_file.csv', existing_file_data)
    data_source = init_abc(DataSource)
    data_source._data = pd.DataFrame([[4, 3], [2, 1]], columns=['a', 'b'])
    # when
    data_source.write(filepath)
    # then
    result = pd.read_csv(filepath)
    expected = pd.DataFrame([[1, 2], [3, 4], [4, 3], [2, 1]], columns=['a', 'b'])
    assert_frame_equal(result, expected)

def test_data_source_validate_success(init_abc):
    # get
    data_source = init_abc(DataSource)
    data_source._data = pd.DataFrame([[1, 2], [3, 4]], columns=['a', 'b'])
    # when
    data_source.validate()
    # then
    # (no exception)


import urllib.request, urllib.error  # 制定URL，获取网页数据
from bs4 import BeautifulSoup

context = ''

def askURL(url):
    head = {  # 模拟服务器头部信息，向豆瓣服务器发送消息
        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.107 Safari/537.36"
    }
    # 用户代理表示告诉豆瓣我们是什么样的机器，本质上是告诉我们可以接受什么样的内容

    request = urllib.request.Request(url, headers=head)
    html = ""
    try:
        response = urllib.request.urlopen(request)
        html = response.read().decode("utf-8")
        # print(html)
    except urllib.error.URLError as e:
        if hasattr(e, "code"):
            print(e.code)
        if hasattr(e, "reason"):
            print(e.reason)
    return html

def getLocation(url):
    html = askURL(url)
    soup = BeautifulSoup(html, 'html.parser')
    paras = soup.select('.topbar h2')
    paras = paras[0].get_text() + "\n"
    return paras

def getWeather(url):
    html = askURL(url)
    soup = BeautifulSoup(html, 'html.parser')
    paras = soup.select('.txt')
    paras = "今天" + paras[0].get_text() + "\n"
    if paras.find("雨") + 1:
        paras += "出门记得带伞(～￣▽￣)～\n "
    if paras.find("晴") + 1:
        paras += "美美的享受你的阳光呀q(≧▽≦q)\n "
    if paras.find("云") + 1:
        paras += "乌云也遮不住你的好心情呀(^///^)\n "
    return paras

def getWet(url):
    html = askURL(url)
    soup = BeautifulSoup(html, 'html.parser')
    paras = soup.select('.b2')
    paras = paras[0].get_text() + "\n"
    return paras

def getWind(url):
    html = askURL(url)
    soup = BeautifulSoup(html, 'html.parser')
    paras = soup.select('.b3')
    paras = paras[0].get_text() + "\n\n"
    return paras

def saveFile(text):
    global context
    context += text

def getAll(url):
    location = getLocation(url)
    saveFile(location)
    weather = getWeather(url)
    saveFile(weather)
    wet = getWet(url)
    saveFile(wet)
    wind = getWind(url)
    saveFile(wind)

def Weather():
    wuhan = 'https://m.tianqi.com/wuhan/'
    dalian = 'https://m.tianqi.com/dalian/'
    getAll(wuhan)
    getAll(dalian)
    return context


# %%

import numpy as np
import matplotlib.pyplot as plt
import math
import matplotlib.image as mpimg
import glob
import json
import os
import torch
import torch.nn as nn
import torch
from torch.autograd import Variable
import torch.nn.functional as F
import torch.optim as optim
from torch.utils.data import DataLoader, sampler
import pandas as pd
import copy
from tqdm import tqdm
from joblib import Parallel, delayed
import subprocess
import sys
import os
# import the necessary packages
from skimage.exposure import rescale_intensity
from skimage.segmentation import slic, mark_boundaries
from skimage.util import img_as_float
from skimage import io
from scipy import misc
import numpy as np
import argparse
from PIL import Image
import glob
from tqdm import tqdm
import os
from joblib import Parallel, delayed

def main(base_path):
    SEGMENTATION_PATH = base_path + "fake/segmentation"
    ATTRIBUTES_PATH = base_path + "fake/attributes"
    IMAGE_PATH = base_path + "fake/images"

    BASE_RESIZED_PATH = base_path + "fake/pix2pix"

    SEGMENTATION_RESIZED_PATH = os.path.join(BASE_RESIZED_PATH, "segmentation_resized")
    ATTRIBUTES_RESIZED_PATH = os.path.join(BASE_RESIZED_PATH, "attribute_resized")
    IMAGE_RESIZED_PATH = os.path.join(BASE_RESIZED_PATH, "image_resized")

    SEGMENTATION_512p_PATH = os.path.join(BASE_RESIZED_PATH, "seg_512p")
    ATTRIBUTES_512p_PATH = os.path.join(BASE_RESIZED_PATH, "attribute_512p")
    IMAGES_512p_PATH = os.path.join(BASE_RESIZED_PATH, "images_512p")

    INSTANCE_MAP_NO_BORDER_PATH = os.path.join(BASE_RESIZED_PATH, "instance_map_no_border")
    INSTANCE_MAP_PATH = os.path.join(BASE_RESIZED_PATH, "instance_map")

    os.makedirs(SEGMENTATION_RESIZED_PATH, exist_ok=True)
    os.makedirs(ATTRIBUTES_RESIZED_PATH, exist_ok=True)
    os.makedirs(IMAGE_RESIZED_PATH, exist_ok=True)

    os.makedirs(IMAGES_512p_PATH, exist_ok=True)
    os.makedirs(SEGMENTATION_512p_PATH, exist_ok=True)
    os.makedirs(ATTRIBUTES_512p_PATH, exist_ok=True)
    os.makedirs(INSTANCE_MAP_PATH, exist_ok=True)
    os.makedirs(INSTANCE_MAP_NO_BORDER_PATH, exist_ok=True)

    # %%

    def process_items(item, to_dir):
        name = item.split("/")[-1]
        to_dir_name = os.path.join(to_dir, name)
        cmd = "convert {} -resize 1024x512 -size 1024x512 xc:red +swap -gravity center -composite {}"
        cmd_formatted = cmd.format(item, to_dir_name)
        subprocess.run(cmd_formatted.split(), capture_output=True).check_returncode()

    def process_items_512p(item, to_dir):
        name = item.split("/")[-1]
        to_dir_name = os.path.join(to_dir, name)
        cmd = "convert {} -resize 1024x512 {}"
        cmd_formatted = cmd.format(item, to_dir_name)
        subprocess.run(cmd_formatted.split(), capture_output=True).check_returncode()

    def process_items_instance_map(item, to_dir):
        name = item.split("/")[-1]
        to_dir_name = os.path.join(to_dir, name)
        cmd = "convert {} -resize 1024x512 -size 1024x512 xc:black +swap -gravity center -composite {}"
        cmd_formatted = cmd.format(item, to_dir_name)
        subprocess.run(cmd_formatted.split(), capture_output=True).check_returncode()

    def resize_from_to(from_dir, to_dir, fnct, jobs_cnt=10):
        res = sorted(glob.glob(os.path.join(from_dir, "*.png")))
        Parallel(n_jobs=jobs_cnt)(delayed(fnct)(i, to_dir) for i in tqdm(res))

    # %%

    resize_from_to(SEGMENTATION_PATH, SEGMENTATION_RESIZED_PATH, process_items, 30)
    resize_from_to(ATTRIBUTES_PATH, ATTRIBUTES_RESIZED_PATH, process_items, 30)
    resize_from_to(IMAGE_PATH, IMAGE_RESIZED_PATH, process_items, 30)

    # %%

    d = sorted(glob.glob(os.path.join(SEGMENTATION_RESIZED_PATH, "*.png")))
    for i in range(100):
        img = np.array(Image.open(d[i]))
        print(np.unique(img))
        plt.imshow(img)
        plt.show()
        np.unique(img)

    # %%

    resize_from_to(SEGMENTATION_RESIZED_PATH, SEGMENTATION_512p_PATH, process_items_512p, 30)
    resize_from_to(ATTRIBUTES_RESIZED_PATH, ATTRIBUTES_512p_PATH, process_items_512p, 30)
    resize_from_to(IMAGE_RESIZED_PATH, IMAGES_512p_PATH, process_items_512p, 30)

    # %%

    def process_segmentation_map(base_path):
        atri_dir = os.path.join(base_path, 'attribute_resized/')
        mask_dir = os.path.join(base_path, 'segmentation_resized/')
        output_dir = os.path.join(base_path, 'semantic_map/')

        print(atri_dir)
        print(mask_dir)
        print(output_dir)

        file_name_arr = []  # [ISIC_00000, ISIC_000001, ISIC_000003, ...]
        for file in glob.glob(atri_dir + '*.png'):
            temp = file.split('/')[-1].split('_')
            file_name = temp[0] + '_' + temp[1]
            if file_name not in file_name_arr:
                file_name_arr.append(file_name)
        if not os.path.exists(output_dir):
            os.makedirs(output_dir, exist_ok=True)

        cnt = 0
        file_name_arr = sorted(file_name_arr)
        # file_name_arr = file_name_arr[0:17]
        for family in tqdm(file_name_arr):
            # Create a zero filled base image
            for i, file in enumerate(glob.glob(atri_dir + family + '*.png')):
                # Read the image
                # print(file)
                read_image = np.array(Image.open(file))
                assert read_image.shape == (512, 1024)
                assert len(np.unique(read_image)) >= 2
                border_color = read_image[0, 0]
                read_image[read_image == border_color] = 0
                read_image[read_image != 2] = 0
                read_image[read_image == 2] = 1

                if i == 0:
                    mask = np.array(Image.open(mask_dir + family + '_segmentation.png'))
                    assert mask.shape == (512, 1024)
                    assert len(np.unique(mask)) >= 2

                    base_image = np.ones(read_image.shape)  # Healthy Skin is 1
                    border_mask_color = mask[0, 0]
                    base_image[mask == border_mask_color] = 0
                    mask[mask == border_mask_color] = 0
                    mask[mask != 2] = 0
                    mask[mask == 2] = 1

                    base_image += mask  # Common Lesion is 2

                type_file = file.split('/')[-1].split('_')[3]

                if type_file == 'pigment':  # 3
                    base_image += read_image
                    if base_image[base_image > 3].any():
                        base_image[base_image > 3] = 3
                elif type_file == 'negative':  # 4
                    base_image += read_image * 2
                    if base_image[base_image > 4].any():
                        base_image[base_image > 4] = 4
                elif type_file.startswith('streaks'):  # 5
                    base_image += read_image * 3
                    if base_image[base_image > 5].any():
                        base_image[base_image > 5] = 5
                elif type_file == 'milia':  # 6
                    base_image += read_image * 4
                    if base_image[base_image > 6].any():
                        base_image[base_image > 6] = 6
                elif type_file.startswith('globules'):  # 7
                    base_image += read_image * 5
                    if base_image[base_image > 7].any():
                        base_image[base_image > 7] = 7
                else:
                    print('ERROR: Invalid File Found!!!!')
            # plt.clf()
            # plt.imshow(base_image)
            # plt.show()

            # break
            Image.fromarray((base_image).astype(np.uint8)).save(output_dir + family + '_semantic.png')
            # print(np.unique((base_image).astype(np.uint8)))
            # plt.imshow(np.array(Image.open(output_dir + family + '_semantic.png')))
            # plt.show()
            # cnt += 1
            # if cnt == 1000:
            #    break
            # toimage(base_image, cmin=0, cmax=255).save(output_dir + family + '_semantic.png')

    process_segmentation_map(BASE_RESIZED_PATH)

    # %%

    # Directories
    atri_dir = os.path.join(BASE_RESIZED_PATH, 'attribute_512p/')
    image_dir = os.path.join(BASE_RESIZED_PATH, 'images_512p/')
    segmentation_dir = os.path.join(BASE_RESIZED_PATH, 'seg_512p/')
    output_dir = os.path.join(BASE_RESIZED_PATH, 'instance_map_no_border/')
    print("atri_dir", atri_dir)
    print("image_dir", image_dir)
    print("segmentation_dir", segmentation_dir)
    print("output_dir", output_dir)

    if not os.path.exists(output_dir):
        os.makedirs(output_dir)

    file_name_arr = []
    for file in glob.glob(atri_dir + '*.png'):
        temp = file.split('/')[-1].split('_')
        file_name = temp[0] + '_' + temp[1]
        if file_name not in file_name_arr:
            file_name_arr.append(file_name)

    def create_instance_map(family):
        # Create a zero filled base image
        # Load original image
        image = np.array(Image.open(image_dir + family + '_image.png'))
        # print(image.shape)
        instance_map = np.zeros(image.shape[:2], dtype=int)
        segments = slic(img_as_float(image), n_segments=1000,
                        slic_zero=True, compactness=1, sigma=2)

        for i, file in enumerate(glob.glob(atri_dir + family + '*.png')):
            # Read Mask
            mask = np.array(Image.open(file))
            # print(mask.shape)
            border_color = mask[0, 0]
            mask[mask == border_color] = 0
            mask[mask != 2] = 0
            mask[mask == 2] = 1
            type_file = file.split('/')[-1].split('_')[3]
            if i == 0:
                segmentation = np.array(Image.open(segmentation_dir + family + '_segmentation.png'))
                border_color = segmentation[0, 0]
                segmentation[segmentation == border_color] = 0
                segmentation[segmentation != 2] = 0
                segmentation[segmentation == 2] = 1

                last_lesion = 2000
                last_background = 1000
                for v in np.unique(segments):
                    union = segmentation[segments == v]
                    if float(len(union[union > 0])) / float(len(union)) > 0.5:
                        instance_map[segments == v] = last_lesion
                        last_lesion += 1
                    else:
                        instance_map[segments == v] = last_background
                        last_background += 1

            if type_file == 'pigment':  # 3
                last = 3000
            elif type_file == 'negative':  # 4
                last = 4000
            elif type_file.startswith('streaks'):  # 5
                last = 5000
            elif type_file == 'milia':  # 6
                last = 6000
            elif type_file.startswith('globules'):  # 7
                last = 7000
            else:
                print('ERROR: Invalid File Found!!!!')
            # For each superpixel in the selected mask,
            # update the pixel values incrementing the value for each superpixel found.
            for v in np.unique(segments):
                union = mask[segments == v]
                if float(len(union[union > 0])) / float(len(union)) > 0.5:
                    instance_map[segments == v] = last
                    last += 1
        instance_map = instance_map.astype(np.uint32)
        im = Image.fromarray(instance_map)
        im.save(output_dir + family + '_instance.png')

    res = Parallel(n_jobs=30)(delayed(create_instance_map)(family) for family in tqdm(file_name_arr))
    print(res)

    resize_from_to(INSTANCE_MAP_NO_BORDER_PATH, INSTANCE_MAP_PATH, process_items_instance_map, 30)

import sys

if __name__ == '__main__':
    main(sys.argv[1])


from django.conf.urls import url
from . import views

print(dir(views))

urlpatterns = [
	url(r'^$', views.HoldingView.as_view(), name='holdings'),
	url(r'^createportfolio$', views.UserCreatePortfolio.as_view(), name='create_portfolio'),
	url(r'^list_portfolio$', views.ListViewPortfolio.as_view(), name='list_portfolio'),
	url(r'^buysell/$', views.BuySellView.as_view(), name='buysell'),
	url(r'^add/$', views.SecurityAddView.as_view(), name='add'),
	url(r'^add_holding/(?P<portfolio_id>[0-9]+)/$', views.HoldingAddView.as_view(), name='add_holding'),
	url(r'^all_holding/(?P<portfolio_id>[0-9]+)/$', views.HoldingAllView.as_view(), name='all_holding'),
	url(r'^all_holding/(?P<portfolio_id>[0-9]+)/update_holding/(?P<holding_id>[0-9]+)/$', views.HoldingUpdateView.as_view(), name='update_holding'),
]


def numeros_perfumeria():
    for n in range(1,1000):
        yield f"P - {n}"

def numeros_farmacia():
    for n in range(1,1000):
        yield f"F - {n}"

def numeros_cosmetico():
    for n in range(1,1000):
        yield f"C - {n}"

perfumeria=numeros_perfumeria()
farmacia=numeros_farmacia()
cosmeticos=numeros_cosmetico()

def decorador(rubro):
    print("\n"+"*"*23)
    print("Su número es: ")
    if rubro == 'P':
        print(next(perfumeria))
    elif rubro=='F':
        print(next(farmacia))
    else:
        print(next(cosmeticos))
    print("Aguarde su turno para ser atendido")
    print("*"*23+"\n")


import pandas as pd
import numpy as np

# Importing dataset
dataset = pd.read_csv("train.csv")

# Feature Types
categorical_features = [feature for feature in dataset.columns if dataset[feature].dtype == "object"]
numerical_features = [feature for feature in dataset.columns if feature not in categorical_features and feature != "Transported"]

# Numerical Features
skewed = ['Age']
extremely_skewed = [feature for feature in numerical_features if feature not in skewed]

# Splitting the Dataset
from sklearn.model_selection import train_test_split

X_train, X_test, y_train, y_test = train_test_split(
    dataset.drop(['Transported'], axis=1),
    dataset['Transported'],
    test_size = 0.3,
    random_state = 12
    )

# Missing Values

    # Numerical Features
mean_value = X_train['Age'].mean() # Can try different metric other than mean

# X_train['Age'].replace(0, np.nan, inplace = True)
X_train['Age'] =  X_train['Age'].fillna(mean_value)

# X_test['Age'].replace(0, np.nan, inplace = True)
X_test['Age'] =  X_test['Age'].fillna(mean_value)

    # Handling Missing values in ['RoomService', 'FoodCourt', 'ShoppingMall', 'Spa', 'VRDeck']
for feature in extremely_skewed:
    median_value = int(X_train[feature].median())

#    X_train[feature + '_na'] = np.where(X_train[feature].isnull(), 1, 0)
#    X_test[feature + '_na'] = np.where(X_test[feature].isnull(), 1, 0)

    X_train[feature] = X_train[feature].fillna(median_value)
    X_test[feature] = X_test[feature].fillna(median_value)

    # Categorical Features
from feature_engine.imputation import RandomSampleImputer

random_imputer = RandomSampleImputer(random_state = 12)
random_imputer.fit(X_train[categorical_features])

X_train[categorical_features] = random_imputer.transform(X_train[categorical_features])
X_test[categorical_features] = random_imputer.transform(X_test[categorical_features])

print(X_train[categorical_features].isnull().sum())
print(X_test[categorical_features].isnull().sum())

"""
# Adding Additional Features
X_train.insert(1, 'GroupID', X_train['PassengerId'].apply(lambda x : int(x.split('_')[0])))
X_train.insert(2, 'PeopleInEachGroup', X_train['PassengerId'].apply(lambda x : int(x.split('_')[1])))

X_test.insert(1, 'GroupID', X_test['PassengerId'].apply(lambda x : int(x.split('_')[0])))
X_test.insert(2, 'PeopleInEachGroup', X_test['PassengerId'].apply(lambda x : int(x.split('_')[1])))

X_train.insert(6, 'Deck', X_train['Cabin'].apply(lambda x: str(x).split('/')[0]))
X_train.insert(7, 'DeckNum', X_train['Cabin'].apply(lambda x: int(x.split('/')[1])))
X_train.insert(8, 'DeckSide', X_train['Cabin'].apply(lambda x: str(x).split('/')[2]))

X_test.insert(6, 'Deck', X_test['Cabin'].apply(lambda x: str(x).split('/')[0]))
X_test.insert(7, 'DeckNum', X_test['Cabin'].apply(lambda x: int(x.split('/')[1])))
X_test.insert(8, 'DeckSide', X_test['Cabin'].apply(lambda x: str(x).split('/')[2]))
"""
"""
# Dropping Features
X_train.drop(['PassengerId', 'Cabin'], axis=1, inplace=True)
X_test.drop(['PassengerId', 'Cabin'], axis=1, inplace=True)
"""

# Change Additional Features datatypes

# Check Same Names: dataset['Name'].value_counts().head(21)
    # There are 20 names repeated.
        # 1. Drop Name columns
        # 2. Remove duplicate Names
X_train.drop(['Name', 'PassengerId'], axis=1, inplace=True)
X_test.drop(['Name', 'PassengerId'], axis=1, inplace=True)

# Encoding the Categorical Features

    # Monotonic Relationships Encoding

# Destination -> 3 unique categories -> One Hot Encoding of top categories (Top 2)
# Deck -> 8 unique categories -> OneHotEncoding of top categories (Top 5 or 6 or 7)

# HomePlanet -> 3 unique categories -> Weight Of Evidence (Test Set is not monotonic)
# CryoSleep -> 2 unique categories (Y/N) -> Weight Of Evidence (Monotonic)
# VIP -> 2 unique categories (Y/N) -> Weight Of Evidence (Monotonic)
# DeckSide -> 2 unique categories -> Weight Of Evidence (Monotonic)

"""
# Decision Tree Discretisation
from feature_engine.discretisation import DecisionTreeDiscretiser

to_decision_tree_disc = ['RoomService', 'FoodCourt', 'ShoppingMall', 'Spa', 'VRDeck']

decision_tree_disc = DecisionTreeDiscretiser(cv = 5, scoring = 'roc_auc',
                                               variables = to_decision_tree_disc,
                                              regression = False,
                                               param_grid = {'max_depth': [1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
                                                             'min_samples_leaf' : [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]})
decision_tree_disc.fit(X_train, y_train)

# print(decision_tree_disc.get_params())

X_train = decision_tree_disc.transform(X_train)
X_test = decision_tree_disc.transform(X_test)
"""

# Categorical Encoding
"""
    # Weight Of Evidence Encoding
to_woe = ['HomePlanet', 'CryoSleep', 'VIP']

from feature_engine.encoding import WoEEncoder

woe_encoder = WoEEncoder(variables = to_woe)
woe_encoder.fit(X_train, y_train)

X_train = woe_encoder.transform(X_train)
X_test = woe_encoder.transform(X_test)
"""

    # One Hot Encoder Top Categories
to_OHE_top_two = ['Destination']
# to_OHE_top_five = ['Deck']

from feature_engine.encoding import OneHotEncoder

destination_encoder = OneHotEncoder(top_categories=2, variables = to_OHE_top_two,
                                    drop_last = True)
destination_encoder.fit(X_train)

X_train = destination_encoder.transform(X_train)
X_test = destination_encoder.transform(X_test)

remaining_categorical_features = ['HomePlanet', 'CryoSleep', 'VIP']
rcf = OneHotEncoder(variables = remaining_categorical_features,
                                    drop_last = True)
rcf.fit(X_train)

X_train = rcf.transform(X_train)
X_test = rcf.transform(X_test)

X_train.drop(['Cabin'], axis = 1, inplace = True)
X_test.drop(['Cabin'], axis = 1, inplace = True)

print(X_train.isnull().sum())
print(X_test.isnull().sum())

# Feature Scaling
from sklearn.preprocessing import MinMaxScaler
# import joblib

scaler = MinMaxScaler()
scaler.fit(X_train)

X_train = pd.DataFrame(scaler.transform(X_train), columns=X_train.columns)
X_test = pd.DataFrame(scaler.transform(X_test), columns=X_test.columns)

X_train.to_csv('xtrain.csv', index = False)
X_test.to_csv('xtest.csv', index = False)

y_train.to_csv('ytrain.csv', index = False)
y_test.to_csv('ytest.csv', index = False)

# joblib.dump(scaler, 'standard_scalar.joblib')

Space ship Titanic/Feature Engineering.py


# TODO перебрать список зависимостей
import csv
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtPrintSupport import *
import sys, sqlite3, time
from MainWindow import *
import os
import pandas

class InsertDialog(QDialog):
    def __init__(self, *args, **kwargs):
        super(InsertDialog, self).__init__(*args, **kwargs)

        self.QBtn = QPushButton()
        self.QBtn.setText("Register")

        self.setWindowTitle("Add Employee")
        self.setFixedWidth(300)
        self.setFixedHeight(250)

        self.QBtn.clicked.connect(self.addemployee)

        layout = QVBoxLayout()

        self.nameinput = QLineEdit()
        self.nameinput.setPlaceholderText("Name")
        layout.addWidget(self.nameinput)

        self.branchinput = QComboBox()
        self.branchinput.addItem("Manager")
        self.branchinput.addItem("Accountant")
        self.branchinput.addItem("CEO Deputy")
        self.branchinput.addItem("CEO")
        self.branchinput.addItem("System Adm.")
        self.branchinput.addItem("Security Adm.")
        layout.addWidget(self.branchinput)

        self.seminput = QComboBox()
        self.seminput.addItem("Non Confidential")
        self.seminput.addItem("Confidential")
        self.seminput.addItem("Secret")
        self.seminput.addItem("Top Secret")
        layout.addWidget(self.seminput)

        self.mobileinput = QLineEdit()
        self.mobileinput.setPlaceholderText("Mobile")
        self.mobileinput.setInputMask('999 999 99 99')
        layout.addWidget(self.mobileinput)

        self.addressinput = QLineEdit()
        self.addressinput.setPlaceholderText("Department")
        layout.addWidget(self.addressinput)

        layout.addWidget(self.QBtn)
        self.setLayout(layout)

    def addemployee(self):

        name = self.nameinput.text()
        branch = self.branchinput.itemText(self.branchinput.currentIndex())
        sem = self.seminput.itemText(self.seminput.currentIndex())
        mobile = self.mobileinput.text()
        address = self.addressinput.text()
        try:
            self.conn = sqlite3.connect("database.db")
            self.c = self.conn.cursor()
            self.c.execute("INSERT INTO employee (name,branch,sem,Mobile,address) VALUES (?,?,?,?,?)",
                           (name, branch, sem, mobile, address))
            self.conn.commit()
            self.c.close()
            self.conn.close()
            QMessageBox.information(QMessageBox(), 'Successful', 'Student is added successfully to the database.')
            self.close()
        except Exception:
            QMessageBox.warning(QMessageBox(), 'Error', 'Could not add student to the database.')

class UpdateDialog(QDialog):
    def __init__(self, *args, **kwargs):
        super(UpdateDialog, self).__init__(*args, **kwargs)

        self.QBtn = QPushButton()
        self.QBtn.setText("Update")

        self.setWindowTitle("Update Employee")
        self.setFixedWidth(300)
        self.setFixedHeight(250)

        self.QBtn.clicked.connect(self.updateEmployee)

        layout = QVBoxLayout()

        self.idinput = QLineEdit()
        self.idinput.setPlaceholderText("ID")
        layout.addWidget(self.idinput)

        self.nameinput = QLineEdit()
        self.nameinput.setPlaceholderText("Name")
        layout.addWidget(self.nameinput)

        self.branchinput = QComboBox()
        self.branchinput.addItem("Manager")
        self.branchinput.addItem("Accountant")
        self.branchinput.addItem("CEO Deputy")
        self.branchinput.addItem("CEO")
        self.branchinput.addItem("System Adm.")
        self.branchinput.addItem("Security Adm.")
        layout.addWidget(self.branchinput)

        self.seminput = QComboBox()
        self.seminput.addItem("Non Confidential")
        self.seminput.addItem("Confidential")
        self.seminput.addItem("Secret")
        self.seminput.addItem("Top Secret")
        layout.addWidget(self.seminput)

        self.mobileinput = QLineEdit()
        self.mobileinput.setPlaceholderText("Mobile")
        self.mobileinput.setInputMask('999 999 99 99')
        layout.addWidget(self.mobileinput)

        self.addressinput = QLineEdit()
        self.addressinput.setPlaceholderText("Department")
        layout.addWidget(self.addressinput)

        layout.addWidget(self.QBtn)
        self.setLayout(layout)

    def updateEmployee(self):

        id = self.idinput.text()
        name = self.nameinput.text()
        branch = self.branchinput.itemText(self.branchinput.currentIndex())
        sem = self.seminput.itemText(self.seminput.currentIndex())
        mobile = self.mobileinput.text()
        address = self.addressinput.text()

        try:
            # Check if ID is available
            self.conn = sqlite3.connect("database.db")
            self.c = self.conn.cursor()
            result = self.c.execute("SELECT * from employee WHERE roll=" + str(id))
            row = result.fetchone()
            serachresult = "ID : " + str(row[0]) + '\n' + "Name : " + str(row[1]) + '\n' + "Role : " + str(
                row[2]) + '\n' + "Access Level : " + str(row[3]) + '\n' + "Department : " + str(row[4])
            QMessageBox.information(QMessageBox(), 'Successful', serachresult)
            self.conn.commit()
            self.c.close()
            self.conn.close()

            # Update employee data
            self.conn = sqlite3.connect("database.db")
            self.c = self.conn.cursor()
            # self.c.execute("INSERT INTO employee (name,branch,sem,Mobile,address) VALUES (?,?,?,?,?)",
            #                (name, branch, sem, mobile, address))
            self.c.execute(f"UPDATE employee SET name = '{name}',"
                           f"branch = '{branch}',"
                           f"sem = '{sem}',"
                           f"Mobile = '{mobile}',"
                           f"address = '{address}'"
                           f"WHERE roll = {id};")
            self.conn.commit()
            self.c.close()
            self.conn.close()
            QMessageBox.information(QMessageBox(), 'Successful', 'Employee was updated successfully.')
            self.close()
        except Exception:
            QMessageBox.warning(QMessageBox(), 'Error', 'Could not update employee data. Check ID')

class SearchDialog(QDialog):
    def __init__(self, *args, **kwargs):
        super(SearchDialog, self).__init__(*args, **kwargs)

        self.QBtn = QPushButton()
        self.QBtn.setText("Search")

        self.setWindowTitle("Search user")
        self.setFixedWidth(300)
        self.setFixedHeight(100)
        self.QBtn.clicked.connect(self.searchstudent)
        layout = QVBoxLayout()

        self.searchinput = QLineEdit()
        self.onlyInt = QIntValidator()
        self.searchinput.setValidator(self.onlyInt)
        self.searchinput.setPlaceholderText("Employee ID")
        layout.addWidget(self.searchinput)
        layout.addWidget(self.QBtn)
        self.setLayout(layout)

    def searchstudent(self):

        searchrol = self.searchinput.text()
        try:
            self.conn = sqlite3.connect("database.db")
            self.c = self.conn.cursor()
            result = self.c.execute("SELECT * from employee WHERE roll=" + str(searchrol))
            row = result.fetchone()
            serachresult = "ID : " + str(row[0]) + '\n' + "Name : " + str(row[1]) + '\n' + "Role : " + str(
                row[2]) + '\n' + "Access Level : " + str(row[3]) + '\n' + "Department : " + str(row[4])
            QMessageBox.information(QMessageBox(), 'Successful', serachresult)
            self.conn.commit()
            self.c.close()
            self.conn.close()
        except Exception:
            QMessageBox.warning(QMessageBox(), 'Error', 'Could not Find employee from the database.')

class DeleteDialog(QDialog):
    def __init__(self, *args, **kwargs):
        super(DeleteDialog, self).__init__(*args, **kwargs)

        self.QBtn = QPushButton()
        self.QBtn.setText("Delete")

        self.setWindowTitle("Delete Student")
        self.setFixedWidth(300)
        self.setFixedHeight(100)
        self.QBtn.clicked.connect(self.deletestudent)
        layout = QVBoxLayout()

        self.deleteinput = QLineEdit()
        self.onlyInt = QIntValidator()
        self.deleteinput.setValidator(self.onlyInt)
        self.deleteinput.setPlaceholderText("ID")
        layout.addWidget(self.deleteinput)
        layout.addWidget(self.QBtn)
        self.setLayout(layout)

    def deletestudent(self):

        delrol = self.deleteinput.text()
        try:
            self.conn = sqlite3.connect("database.db")
            self.c = self.conn.cursor()
            self.c.execute("DELETE from employee WHERE roll=" + str(delrol))
            self.conn.commit()
            self.c.close()
            self.conn.close()
            QMessageBox.information(QMessageBox(), 'Successful', 'Deleted From Table Successful')
            self.close()
        except Exception:
            QMessageBox.warning(QMessageBox(), 'Error', 'Could not Delete employee from the database.')

class LoginDialog(QDialog):
    def __init__(self, *args, **kwargs):
        super(LoginDialog, self).__init__(*args, **kwargs)

        self.setFixedWidth(300)
        self.setFixedHeight(120)

        layout = QVBoxLayout()

        self.passinput = QLineEdit()
        self.passinput.setEchoMode(QLineEdit.Password)
        self.passinput.setPlaceholderText("Enter Password.")
        self.QBtn = QPushButton()
        self.QBtn.setText("Login")
        self.setWindowTitle('Login')
        self.QBtn.clicked.connect(self.login)

        title = QLabel("Login")
        font = title.font()
        font.setPointSize(16)
        title.setFont(font)

        layout.addWidget(title)
        layout.addWidget(self.passinput)
        layout.addWidget(self.QBtn)
        self.setLayout(layout)

    # Я в ИБ 4 года, всё безопасно, гарантирую
    def login(self):
        if self.passinput.text() == "pass":
            self.accept()
        else:
            QMessageBox.warning(self, 'Error', 'Wrong Password')

class ExportToCsvDialog(QDialog):
    def __init__(self, *args, **kwargs):
        super(ExportToCsvDialog, self).__init__(*args, **kwargs)

        self.setWindowTitle("Export To Csv File")
        self.setFixedWidth(300)
        self.setFixedHeight(100)

        self.saveFileDialog()

    def saveFileDialog(self):
        options = QFileDialog.Options()
        options |= QFileDialog.DontUseNativeDialog
        fileName, _ = QFileDialog.getSaveFileName(self, "QFileDialog.getSaveFileName()", "",
                                                  "All Files (*);;Text Files (*.csv)", options=options)
        if fileName:
            self.exportToDict(fileName)

    def exportToDict(self, filename):

        exportFile = filename
        self.conn = sqlite3.connect("database.db")

        self.conn.row_factory = sqlite3.Row
        self.c = self.conn.cursor()
        self.c.execute('select * from employee')

        result = [dict(row) for row in self.c.fetchall()]

        self.exportToCsv(result, exportFile)

        self.c.close()
        self.conn.close()
        QMessageBox.information(QMessageBox(), 'Successful', 'Export Successful')
        self.close()

    def exportToCsv(self, result, filename):
        print(result)
        toCSV = result
        keys = toCSV[0].keys()
        with open(filename, 'w', newline='') as output_file:
            dict_writer = csv.DictWriter(output_file, keys)
            dict_writer.writeheader()
            dict_writer.writerows(toCSV)

class ImportFromCsvDialog(QDialog):
    def __init__(self, *args, **kwargs):
        super(ImportFromCsvDialog, self).__init__(*args, **kwargs)

        self.setWindowTitle("Import From Csv File")
        self.setFixedWidth(300)
        self.setFixedHeight(100)

        self.open()

    def open(self):
        options = QFileDialog.Options()
        options |= QFileDialog.DontUseNativeDialog
        fileName, _ = QFileDialog.getOpenFileName(self, 'Open a file', '',
                                           'Text Files (*.csv)', options=options)
        if fileName:
            self.import_to_db(fileName)

    def import_to_db(self, filename):
        self.conn = sqlite3.connect("database.db")
        self.c = self.conn.cursor()
        self.c.execute("DROP TABLE IF EXISTS employee")
        self.c.execute("""
                    CREATE TABLE IF NOT EXISTS employee(roll INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT,branch TEXT,
                    sem TEXT,mobile INTEGER,address TEXT)""")

        table_name = "employee"
        orders = pandas.read_csv(filename)  # load to DataFrame
        orders.to_sql(table_name, self.conn, if_exists='append', index=False)

class AboutDialog(QDialog):
    def __init__(self, *args, **kwargs):
        super(AboutDialog, self).__init__(*args, **kwargs)

        self.setFixedWidth(300)
        self.setFixedHeight(250)

        QBtn = QDialogButtonBox.Ok  # No cancel
        self.buttonBox = QDialogButtonBox(QBtn)
        self.buttonBox.accepted.connect(self.accept)
        self.buttonBox.rejected.connect(self.reject)

        layout = QVBoxLayout()

        title = QLabel("Database management \nsystem")
        font = title.font()
        font.setPointSize(20)
        title.setFont(font)

        labelpic = QLabel()
        pixmap = QPixmap('icon/logo.png')
        pixmap = pixmap.scaledToWidth(275)
        labelpic.setPixmap(pixmap)
        labelpic.setFixedHeight(150)

        layout.addWidget(title)

        layout.addWidget(QLabel("Version 0.1"))
        layout.addWidget(QLabel("Created by Panov Sergey, RTU MIREA 2021"))
        layout.addWidget(labelpic)

        layout.addWidget(self.buttonBox)

        self.setLayout(layout)

if __name__ == '__main__':
    app = QApplication(sys.argv)

    # Request a password to db
    passdlg = LoginDialog()

    if passdlg.exec_() == QDialog.Accepted:
        window = MainWindow()
        window.show()
        window.loaddata()
    sys.exit(app.exec_())


# coding: utf-8

# pywebaudioplayer for Jupyter Notebook. Loads external javascript libraries with RequireJS and uses built-in Bootstrap, jQuery and font-awesome.
from .core import Image, _id, _js, _figure_margins, _write_samples, waveform_playlist

def wavesurfer(audio_path=None, controls={}, display={}, behaviour={}, samples=None):
    # Set defaults
    if 'text_controls' not in controls:
        controls['text_controls'] = True
    if 'backward_button' not in controls:
        controls['backward_button'] = True
    if 'forward_button' not in controls:
        controls['forward_button'] = True
    if 'mute_button' not in controls:
        controls['mute_button'] = True
    if 'height' not in display:
        display['height'] = 128
    if 'cursor_colour' not in display:
        display['cursor_colour'] = '#333'
    if 'played_wave_colour' not in display:
        display['played_wave_colour'] = '#555'
    if 'unplayed_wave_colour' not in display:
        display['unplayed_wave_colour'] = '#999'
    if 'bar_width' not in display:
        display['bar_width'] = None
    if 'normalize' not in behaviour:
        behaviour['normalize'] = False
    if 'mono' not in behaviour:
        behaviour['mono'] = True

    unique_id = _id()
    if not audio_path and not samples:
        raise ValueError('Provide either a path to an audio file or samples')

    html_code = '''

    '''.format(unique_id)

    if controls['backward_button']:
        html_code += '''
          <button class="btn btn-primary" onclick="wavesurfer{}.skipBackward()">

            {}
          </button>'''.format(unique_id, 'Backward' if controls['text_controls'] else '')

    html_code += '''
      <button class="btn btn-success" onclick="wavesurfer{}.playPause()">

        {} /

        {}
      </button>'''.format(unique_id, 'Play' if controls['text_controls'] else '', 'Pause' if controls['text_controls'] else '')

    if controls['forward_button']:
        html_code += '''
          <button class="btn btn-primary" onclick="wavesurfer{}.skipForward()">

            {}
          </button>'''.format(unique_id, 'Forward' if controls['text_controls'] else '')

    if controls['mute_button']:
        html_code += '''
          <button class="btn btn-danger" onclick="wavesurfer{}.toggleMute()">

            {}
          </button>'''.format(unique_id, 'Toggle Mute' if controls['text_controls'] else '')

    html_code += '\n
'

    html_code += '''
    '''.format(
        id=unique_id, path=audio_path, cursor=display['cursor_colour'], progress=display['played_wave_colour'], wave=display['unplayed_wave_colour'], split=_js(not behaviour['mono']), height=display['height'], norm=_js(behaviour['normalize']),
        bar_width=', barWidth: {}'.format(display['bar_width']) if display['bar_width'] else '')
    return html_code

def trackswitch(tracks, text='', seekable_image=None, seek_margin=None, mute=True, solo=True, globalsolo=True, repeat=False, radiosolo=False, onlyradiosolo=False, spacebar=False, tabview=False):
    unique_id = _id()
    if isinstance(seekable_image, str):
        seekable_image_path = seekable_image
        with Image.open(seekable_image) as image_file:
            image_width = image_file.size[0]
    elif seekable_image:
        fig, seekable_image_path = seekable_image
        image_width = fig.get_size_inches()[0] * fig.get_dpi()
        seek_margin = _figure_margins(fig.gca())
        fig.savefig(seekable_image_path, dpi='figure')
    html_code = '''
    <link rel="stylesheet" href="//audiolabs.github.io/trackswitch.js/css/trackswitch.min.css" />

'''.format(unique_id, ' style="width:{}px"'.format(image_width) if seekable_image else '')
    if text:
        html_code += '''

            {}

'''.format(text)
    if seekable_image:
        html_code += '''
        '''.format(seekable_image_path, unique_id, image_width, ' data-seek-margin-left="{}" data-seek-margin-right="{}"'.format(*seek_margin) if seek_margin else '')
    for track in tracks:
        html_code += '''
        <ts-track{}{}>
          <ts-source src='''.format(' title="{}"'.format(track['title']) if 'title' in track else '',
                                     ' data-img="{}"'.format(track['image']) if 'image' in track else '')
        if 'samples' in track:
            path_or_bytestring = _write_samples(track)
            html_code += '"{}" type="audio/wav"'.format(path_or_bytestring)
        elif 'path' in track:
            html_code += '"{}"{}'.format(track['path'], ' type="{}"'.format(track['mimetype']) if 'mimetype' in track else '')
        else:
            raise ValueError('Provide either a path to an audio file or raw samples')
        html_code += '''></ts-source>
        </ts-track>'''

    html_code += '''

    '''.format(unique_id, _js(mute), _js(solo), _js(globalsolo), _js(repeat), _js(radiosolo), _js(onlyradiosolo), _js(spacebar), _js(tabview))

    return html_code


# 20. 有效的括号
# 给定一个只包括 '('，')'，'{'，'}'，'['，']' 的字符串，判断字符串是否有效。
class Solution:
    def isValid(self, s):
        """
        :type s: str
        :rtype: bool
        """
        stack = []
        d = ["()", "[]", "{}"]
        for i in range(0, len(s)):
            stack.append(s[i])
            if len(stack) >= 2 and stack[-2] + stack[-1] in d:
                stack.pop()
                stack.pop()
        return len(stack) == 0

if __name__ == '__main__':
    s = Solution()
    s1 = "()[]{}"
    isValid = s.isValid(s1)
    print(isValid)


'''
Created on 2018年11月23日

@author: Administrator
'''
#coding=utf-8

import requests
from urllib import parse
import urllib.request #获取网址模块
from bs4 import BeautifulSoup
from selenium import webdriver
import os

class Zymk:
    #知音漫客列表url
    url =''
    #漫画存储位置
    outPath=''

    #下载数量 0表示全部
    limit=0

    __title=''

    '''
            获取章节页面
    '''
    def getHtml(self):
        papg = urllib.request.urlopen(self.url) #打开图片的网址
        html = papg.read()  #用read方法读成网页源代码，格式为字节对象
        html = html.decode('UTF-8') #定义编码格式解码字符串(字节转换为字符串)
        return html

    def getChapterList(self):
        soup = BeautifulSoup(self.getHtml(), 'html.parser')
        #print(soup.prettify())
        browser = webdriver.Firefox()
        #browser.minimize_window()
        count =0
        try:
            for chapter in soup.find(id='chapterList'):
                #print(chapter)
                self.title = chapter.find('a').get('title')
                imgUrl = self.url+chapter.find('a').get('href')
                if self.title.isdigit() == False:
                    self.title = self.title.replace(self.title.split("话")[0],('%03d' %int(self.title.split("话")[0])),1)
                #print(title)
                #print(imgUrl)
                browser.get(imgUrl)
                browser.implicitly_wait(10)
                self.downloadImage(browser.page_source)

                count =count+1
                if self.limit != 0 and count >= self.limit:
                    break
        finally:
            browser.close()

    '''
            下载图片
    '''
    def downloadImage(self,pageSource):
        #print(pageSource)
        soup = BeautifulSoup(pageSource, 'html.parser')
        img = "https:"+soup.find("img", "comicimg").get('src')
        self.storeImage(img)

    '''
            储存图片
    '''
    def storeImage(self,url):
        url = parse.unquote(url)
        print(url)
        count=1
        res = self.sendRequest(self.handleUrl(url,count))
        if res.status_code != 200:
            print("链接不存在:"+url)

        if not os.path.exists(self.outPath):
            os.makedirs(self.outPath)

        while res.status_code == 200:
            path = self.outPath+self.title+'_'+('%02d' %count)+'.jpg'
            print(path)
            f = open(path,'ab') #存储图片，多媒体文件需要参数b（二进制文件）
            f.write(res.content) #多媒体存储content
            f.close()
            count = count+1
            res=self.sendRequest(self.handleUrl(url,count))

    def handleUrl(self,url,count):
        urlStrs = url.split('/')
        imgName = urlStrs[len(urlStrs)-1]
        return url.replace(imgName,imgName.replace(imgName.split(".")[0],str(count)))

    def sendRequest(self,url):
        return requests.get(url)

    def dealUrl(self,url):
        if not url.endswith("/"):
            url = url+"/"
        return url
    '''
            构造方法
    '''
    def __init__(self,url,outPath):
        self.url = self.dealUrl(url)
        self.outPath= self.dealUrl(outPath)

zymk = Zymk('https://www.zymk.cn/1/','D:/漫画/斗破苍穹/')
zymk.limit =2
zymk.getChapterList()


# Path Operations for posts

from fastapi import Depends, Response, status, HTTPException, APIRouter
from .. import schemas, oauth2, models
from typing import List
from ..database_orm import get_db
from sqlalchemy.orm import Session
from sqlalchemy import func
#from .. import database

router = APIRouter(prefix="/posts", tags=['Posts ORM'])

# By adding -> limit: int = 5 in our get_posts, we are setting up Query Paramater
# Anything after the question mark in the website "www.website.com/posts?limit=3" is key value pair that allows users to filter the results of a request
# In our case "limit", "skip" & "search" is the Query Paramater
# int = 5 means we setting default value of limit
@router.get("/", response_model=List[schemas.PostResponseWithLikes])
def get_posts(token_data: int = Depends(oauth2.get_current_user_id), db: Session = Depends(get_db), limit: int = 5, skip: int = 0, search: str = ""):
    search = "%"+search+"%"

    # SQL Equivalent
    # record = database.cursor.execute("""
    # SELECT P.*, COUNT(V.post_id) likes FROM posts P LEFT JOIN votes V
    # ON P.id = V.post_id
    # WHERE P.user_id = %s AND P.title ILIKE %s
    # GROUP BY P.id
    # LIMIT %s OFFSET %s
    # """, (token_data.id, search, limit, skip)).fetchall()

    record = db.query(models.Post.id, models.Post.user_id, models.Post.title, models.Post.content, models.Post.published, models.Post.created_at, func.count(models.Vote.post_id).label("likes")).join(models.Vote, models.Post.id == models.Vote.post_id, isouter=True).filter(models.Post.user_id == token_data.id, models.Post.title.ilike(search)).group_by(models.Post.id).limit(5).offset(0)
    #print(record)
    orm_record = record.all()
    #print(f"Typeof Data Received {type(record)} \n Data Retrieved from DB: {record}")
    return orm_record

# Adding token_data: int = Depends(oauth2.get_current_user_id) in the below function forces user to provide Token so they are Authorized before they can create a post
@router.post("/", status_code=status.HTTP_201_CREATED, response_model=schemas.PostResponse)
def create_post(payLoad: schemas.PostRequest, token_data: int = Depends(oauth2.get_current_user_id), db: Session = Depends(get_db)):
    # Getting Email using User ID from DB
    # current_user = oauth2.get_current_user(token_data.id)

    # SQL Equivalent
    # record = database.cursor.execute(""" INSERT INTO posts (title, content, published, user_id) VALUES (%s, %s, %s, %s) RETURNING * """, (payLoad.title, payLoad.content, payLoad.published, token_data.id)).fetchone()
    # database.conn.commit()
    payload = payLoad.dict()
    payLoadCopy = payload.copy()
    payLoadCopy.update({"user_id": token_data.id})
    # new_posts = models.Post(title=payLoad.title, content=payLoad.content, published=payLoad.published)
    # new_posts = models.Post(**payLoad.dict()) is similar to above comment
    new_posts = models.Post(**payLoadCopy)
    db.add(new_posts)
    db.commit()
    # refresh will retrieves the newly created post and stores it back to variable new_posts
    db.refresh(new_posts)

    return new_posts

@router.get("/{id}", response_model=schemas.PostResponseWithLikes)
def get_post(id: int, token_data: int = Depends(oauth2.get_current_user_id), db: Session = Depends(get_db)):
    # SQL Equivalent
    # record = database.cursor.execute("""
    # SELECT P.*, COUNT(V.post_id) likes FROM posts P LEFT JOIN votes V
    # ON P.id = V.post_id
    # WHERE P.id = %s AND P.user_id = %s
    # GROUP BY P.id
    # """, (id, token_data.id)).fetchone()

    posts = db.query(models.Post.id, models.Post.user_id, models.Post.title, models.Post.content, models.Post.published, models.Post.created_at, func.count(models.Vote.post_id).label("likes")).join(models.Vote, models.Post.id == models.Vote.post_id, isouter=True).filter(models.Post.id == id, models.Post.user_id == token_data.id).group_by(models.Post.id)
    #print(posts)
    orm_record = posts.first()
    if not orm_record:
        raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=f"post id: {id} not found")
    #print(f"Data Retrieved from DB: {record}")
    return orm_record

@router.delete("/{id}", status_code=status.HTTP_204_NO_CONTENT)
def delete_post(id: int, token_data: int = Depends(oauth2.get_current_user_id), db: Session = Depends(get_db)):
    # SQL Equivalent
    # delete_record = database.cursor.execute(""" DELETE FROM posts WHERE id = %s AND user_id = %s returning * """, (id, token_data.id)).fetchone()
    # # print(f"Post Deleted : {delete_record}")
    # database.conn.commit()

    posts = db.query(models.Post).filter(models.Post.id == id, models.Post.user_id == token_data.id)
    if not posts.first():
        raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=f"post id: {id} not found")
    posts.delete(synchronize_session=False)
    db.commit()
    return Response(status_code=status.HTTP_204_NO_CONTENT)

@router.put("/{id}", response_model=schemas.PostResponse)
def update_post(id: int, payLoad: schemas.PostRequest, token_data: int = Depends(oauth2.get_current_user_id), db: Session = Depends(get_db)):
    # SQL Equivalent
    # update_record = database.cursor.execute(""" UPDATE posts SET title = %s, content = %s, published = %s WHERE id = %s AND user_id = %s RETURNING *""", (payLoad.title, payLoad.content, payLoad.published, id, token_data.id)).fetchone()
    # #print(f"Updated Post in DB : {update_record}")
    # database.conn.commit()

    posts = db.query(models.Post).filter(models.Post.id == id, models.Post.user_id == token_data.id)
    if not posts.first():
        raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=f"post id: {id} not found")

    posts.update(payLoad.dict(), synchronize_session=False)
    db.commit()
    # refresh will retrieves the newly created post and stores it back to variable new_posts
    #db.refresh(posts)
    return posts.first()


from tkinter import *

janela = Tk()
janela.title('Teste Janela')
janela.geometry('800x400')
janela.resizable(False,False)

Label(janela, text='Olá trouxa!', bg='blue', fg='white', padx=30,pady=30).grid(row=0, column=0)

janela.mainloop()


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

"""Test serialization."""

import importlib
import os
import tempfile
import unittest

from acsets import ACSet, Attr, AttrType, Hom, Ob, mira, petris

PYDANTIC_1 = importlib.metadata.version("pydantic").startswith("1.")

class TestSerialization(unittest.TestCase):
    """A test case for testing serialization."""

    def test_metadata(self):
        """Test metadata availability."""
        schema = petris.SchPropertyLabelledReactionNet
        for elements in [
            schema.schema.Ob,
            schema.schema.Hom,
            schema.schema.Attr,
            schema.schema.AttrType,
        ]:
            for elements in elements:
                self.assertIsNotNone(elements.name)
                self.assertIsNotNone(elements.title)

    def test_serialization(self):
        """Test serialization round trip."""
        for cls_name, cls, schema in [
            ("Petri", petris.Petri, petris.SchPropertyLabelledReactionNet),
            ("MiraNet", mira.MiraNet, mira.SchMira),
        ]:
            sir = cls()
            self.assertIsInstance(sir, petris.Petri)
            s, i, r = sir.add_species(3)
            inf, rec = sir.add_transitions([([s, i], [i, i]), ([i], [r])])

            pd_sir = sir.export_pydantic()
            self.assertEqual(pd_sir.S[1].id_field_internal, 2)
            serialized = sir.to_json_str()
            deserialized = cls.import_pydantic(cls_name, schema, pd_sir)
            pd_sir2 = deserialized.export_pydantic()
            reserialized = deserialized.to_json_str()
            deserialized2 = cls.read_json(cls_name, schema, reserialized)
            rereserialized = deserialized2.to_json_str()

            self.assertEqual(pd_sir2, pd_sir)
            self.assertEqual(serialized, reserialized)
            self.assertEqual(reserialized, rereserialized)

    def test_ob(self):
        """Test instantiating a hom."""
        ob1, ob2 = Ob(name="ob1"), Ob(name="ob2")
        hom1 = Hom(name="hom1", dom=ob1, codom=ob2)
        self.assertIsInstance(hom1.dom, str)
        self.assertIsInstance(hom1.codom, str)

    @unittest.skipUnless(
        PYDANTIC_1, reason="This functionality can not be made cross-compatible AFAIK"
    )
    def test_write_schema(self):
        """Test writing the schema does not error."""
        with tempfile.TemporaryDirectory() as directory:
            path = os.path.join(directory, "petri.json")
            petris.SchPropertyLabelledReactionNet.write_schema(path)


import torch

def kpixel_attack(X, X_pgd, k=3000):
    """
    K -pixel attack on the image X perturbed by PGD

    Parameters
    ----------
    X : torch.Tensor
        Image to attack
    X_pgd : torch.Tensor
        Perturbed image by PGD
    k : int
        Number of pixels to retain from PGD perturbation

    Returns
    -------
    X_kp : torch.Tensor
        Image with k pixels perturbed
    """
    attack_norm = torch.norm(X_pgd - X, dim=1, p=2)
    B, C, H, W = X.shape
    reshaped_norm = attack_norm.reshape(B, -1)
    topk = torch.topk(reshaped_norm, k=H * W - k, dim=1, largest=False)
    topkindices = topk.indices[:, :H * W - k]
    for i in range(B):
        reshaped_norm[i][topkindices[i]] = 0
    mask = torch.gt(reshaped_norm, 0).reshape(B, H, W)
    mask = torch.transpose(torch.stack([mask for _ in range(C)]), 0, 1)
    perturbation = torch.mul(X_pgd - X, mask)
    return X + perturbation

def mean_distance(perturbation, p=2):
    """
    Mean distance between the pixels of the perturbation

    Parameters
    ----------
    perturbation : torch.Tensor
        Perturbation
    p : int
        Norm to use

    Returns
    -------
    mean_distance : float
        Mean distance between the pixels of the perturbation
    """
    B, C, H, W = perturbation.shape
    norm = torch.norm(perturbation, dim=1, p=2)
    nz = torch.stack([norm[i].nonzero() for i in range(B)])
    distances = torch.cdist(nz.float(), nz.float(), p=2).reshape(B, -1)
    return distances[distances > 0].mean()

def mean_std_distance(perturbation, p=2):
    """
    Mean standard deviation distance between the pixels of the perturbation

    Parameters
    ----------
    perturbation : torch.Tensor
        Perturbation
    p : int
        Norm to use

    Returns
    -------
    mean_std_distance : float
        Mean standard deviation distance between the pixels of the perturbation
    """
    B, C, H, W = perturbation.shape
    norm = torch.norm(perturbation, dim=1, p=2)
    nz = torch.stack([norm[i].nonzero() for i in range(B)])
    distances = torch.cdist(nz.float(), nz.float(), p=2).reshape(B, -1)
    return distances[distances > 0].mean(), distances[distances > 0].std()

def mean_weighted_distance(perturbation, p=2):
    """
    Mean weighted distance between the pixels of the perturbation

    Parameters
    ----------
    perturbation : torch.Tensor
        Perturbation
    p : int
        Norm to use

    Returns
    -------
    mean_weighted_distance : float
        Mean weighted distance between the pixels of the perturbation
    """
    B, C, H, W = perturbation.shape
    norm = torch.norm(perturbation, dim=1)
    nz = torch.stack([norm[i].nonzero() for i in range(B)])
    distances = torch.cdist(nz.float(), nz.float(), p=2).to('cpu')
    t=torch.stack([norm[i, nz[i,:,0], nz[i,:,1]] for i in range(B)]).to('cpu')
    weighted_dist=torch.mul(t.reshape(B, -1, 1), torch.mul(distances, t.reshape(B, 1, -1))).reshape(B, -1)
    return weighted_dist[weighted_dist>0].mean()


from typing import TextIO, AnyStr

import yaml
from yaml.loader import SafeLoader

class ReadFile:

    def __init__(self, file_name):
        self.absolute_file_name = file_name
        self.data = None
        self.file: TextIO = TextIO()
        self.title: str = ""
        self.description: str = ""
        self.description2: str = ""
        self.url = ""
        self.references_list: dict[str, str] = {}

    def read_yaml(self):
        with open(self.absolute_file_name, 'r') as f:
            self.data = yaml.load(f, Loader=SafeLoader)
            f.close()
        if self.data is None:
            return []
        return self.data

    def read_openapi_yaml(self):
        try:
            with open(self.absolute_file_name, 'r') as f:
                self.data = yaml.load(f, Loader=SafeLoader)
                # print(data)
                self.set_info()
                self.set_external_docs()
                # self.set_other()
                f.close()
        except Exception:
            print(f"Error in file: {self.absolute_file_name}")
            raise RuntimeError("Error in file")

    def set_info(self):
        self.title = self.data['info']['title']
        self.description = self.data['info']['description']

    def get_title(self):
        return self.title

    def get_description(self):
        return self.description

    def set_external_docs(self):
        # print(f"ExternalDocs: {self.data['externalDocs']}")
        if 'externalDocs' in self.data:
            self.description2 = self.data['externalDocs']['description']
            self.url = self.data['externalDocs']['url']

    def get_description2(self):
        return self.description2

    def get_url(self):
        return self.url

    def set_other(self):
        for token in self.data:
            print(token)

    def get_references(self) -> dict[str, str]:
        file = open(self.absolute_file_name, 'r')
        lines: list[AnyStr] = file.readlines()
        for line in lines:
            if line.find("$ref: 'TS") != -1:
                # count = line.find("$ref: 'TS")
                # print(f"Count: {count}")
                count_start = line.find("TS")
                # print(f"Count Start: {count_start}")
                count_end = line.find(".yaml#") + 5
                # print(f"Count End: {count_end}")
                # print(f"Line: {line}")
                # print(f"file name: {line[count_start:count_end]}")
                file_name = line[count_start:count_end]
                self.references_list[file_name] = file_name
        file.close()
        return self.references_list


import math
import operator

class KNN :
    def __init__(self,instance,dataset,k) :
        self.instance = instance
        self.dataset = dataset
        self.k = k

    def distanceEcludienne(self,line1 , line2 , length):
        distance=0
        for x in range(length):
            if ((type(line1[x]) == str) | (type(line2[x]) == str)):
                if (line1[x]==line2[x]):
                    distance=0
                else:
                    distance=1
            else:
                distance += pow((line1[x]-line2[x]),2)

        return math.sqrt(distance)

    def VoisinKNN(self):
        distance = []
        length = len(self.instance)-1
        for x in range(len(self.dataset)):
            dist = self.distanceEcludienne(self.instance,self.dataset[x],length)
            distance.append((self.dataset[x],dist,x))
        distance.sort(key=operator.itemgetter(1))
        voisins=[]
        IndiceDist=[]
        for x in range (self.k+1):
            voisins.append(distance[x][0])
            IndiceDist.append((distance[x][2],distance[x][1]))
        return voisins

    def Classify (self):
        voisins=self.VoisinKNN().copy()
        VoisinOccurance = {}
        for y  in range (len(voisins)):
            ClasseChoisie = voisins[y][-1]
            if ClasseChoisie in VoisinOccurance:
                VoisinOccurance[ClasseChoisie]+=1
            else:
                VoisinOccurance[ClasseChoisie]=1
        VoisinOccSorted = sorted(VoisinOccurance.items(),key=operator.itemgetter(1),reverse=True)
        return VoisinOccSorted[0][0]