from django.urls import path, include
from rest_framework import routers

from . import api
from . import views

router = routers.DefaultRouter()
router.register("theme", api.themeViewSet)
router.register("themes", api.unAuthThemeViewSet, basename='theme')
router.register("post", api.postViewSet)
router.register("post_image", api.post_imageViewSet)

urlpatterns = (
    path("api/v1/", include(router.urls)),
    path("core/theme/", views.themeListView.as_view(), name="core_theme_list"),
    path("core/theme/create/", views.themeCreateView.as_view(), name="core_theme_create"),
    path("core/theme/detail/<int:pk>/", views.themeDetailView.as_view(), name="core_theme_detail"),
    path("core/theme/update/<int:pk>/", views.themeUpdateView.as_view(), name="core_theme_update"),
    path("core/post/", views.postListView.as_view(), name="core_post_list"),
    path("core/post/create/", views.postCreateView.as_view(), name="core_post_create"),
    path("core/post/detail/<int:pk>/", views.postDetailView.as_view(), name="core_post_detail"),
    path("core/post/update/<int:pk>/", views.postUpdateView.as_view(), name="core_post_update"),
    path("core/post_image/", views.post_imageListView.as_view(), name="core_post_image_list"),
    path("core/post_image/create/", views.post_imageCreateView.as_view(), name="core_post_image_create"),
    path("core/post_image/detail/<int:pk>/", views.post_imageDetailView.as_view(), name="core_post_image_detail"),
    path("core/post_image/update/<int:pk>/", views.post_imageUpdateView.as_view(), name="core_post_image_update"),
    path("core/post_image/updateNew/<int:pk>/", views.post_imageUpdate, name="core_post_image_updateNew"),
)


"""
997. Find the Town Judge
In a town, there are N people labelled from 1 to N.  There is a rumor that one of these people is secretly the town judge.

If the town judge exists, then:

The town judge trusts nobody.
Everybody (except for the town judge) trusts the town judge.
There is exactly one person that satisfies properties 1 and 2.
You are given trust, an array of pairs trust[i] = [a, b] representing that the person labelled a trusts the person labelled b.

If the town judge exists and can be identified, return the label of the town judge.  Otherwise, return -1.

Example 1:

Input: N = 2, trust = [[1,2]]
Output: 2
Example 2:

Input: N = 3, trust = [[1,3],[2,3]]
Output: 3
Example 3:

Input: N = 3, trust = [[1,3],[2,3],[3,1]]
Output: -1
Example 4:

Input: N = 3, trust = [[1,2],[2,3]]
Output: -1
Example 5:

Input: N = 4, trust = [[1,3],[1,4],[2,3],[2,4],[4,3]]
Output: 3
"""

N = 4
trust = [[1, 3], [1, 4], [2, 3], [2, 4], [4, 3]]

def findJudge(N, trust):
    # initialize dict to hold trust relationships
    trusted = {}
    # create an empty trusted array for each person (N) in the trusted dict
    for i in range(1, N + 1):
        trusted[i] = []
    # add the relationships to the dict
    for groups in range(len(trust)):
        if trust[groups][0] not in trusted:
            trusted[trust[groups][0]] = []
        trusted[trust[groups][0]].append(trust[groups][1])
    # initialize the judge to not exist
    judge = -1
    # iterate the trusted relationships
    for person in trusted:
        # if someone trusts nobody
        if trusted[person] == []:
            # set the judge to that person
            judge = person
            # check to see if everyone else trusts that pers
    for person in trusted:
        # if anyone does not trust the judge return -1 there is no judge
        if judge not in trusted[person] and person != judge:
            return -1
    # if we reach the end the judge is valid
    return judge

# print(findJudge(N, trust))


def relatar(conexao):
    cursor = conexao.cursor()

    sql = '''
        SELECT cliente.nome, cliente.cpf ,transporte.descricao FROM transporte
        INNER JOIN cliente ON trasnporte.idcli = cliente.rowid
        ORDER BY 1 ASC
    '''

    cursor.execute(sql)
    listarel = cursor.fetchall()

    print("==== Relatório de transporte ====")

    for c in listarel:
        print("""
        Cliente: {}
        CPF: {}
        Produto: {}

        """.format(c[0], c[1], c[2]))
        print("------------------------------")


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

class LinkedList:
    def __init__(self):
        self.head = None
        self.size = 0

    def add_node(self, data):
        new_node = Node(data)
        if self.head is None:
            self.head = new_node
            self.size += 1
        else:
            current_node = self.head
            while current_node.next_node is not None:
                current_node = current_node.next_node
            current_node.next_node = new_node
            self.size += 1

    def print_list(self):
        current_node = self.head
        while current_node is not None:
            print(current_node.data)
            current_node = current_node.next_node

    def get_size(self):
        return self.size

    def remove_middle_node(self):
        num_node = self.get_size()//2
        current_node = self.head
        i = 0
        while current_node is not None and i != num_node:
            i += 1
            prev_node = current_node
            current_node = current_node.next_node
        prev_node.next_node = current_node.next_node

def sum_list(LinkedList: List1, LinkedList: List2) -> int:
    current_node1 = List1.head
    current_node2 = List2.head
    string_sum1 = ""
    string_sum2 = ""
    while current_node1 is not None:
        string_sum1 += str(current_node1.data)
        current_node1 = current_node1.next_node
    while current_node2 is not None:
        string_sum2 += str(current_node2.data)
        current_node2 = current_node2.next_node
    return int(string_sum1) + int(string_sum2)

if __name__ == "__main__":
    l = LinkedList()
    l.add_node(3)
    l.add_node(0)
    l.add_node(0)
    l.add_node(0)

    q = LinkedList()
    q.add_node(1)
    q.add_node(0)
    q.add_node(0)
    q.add_node(0)
    print(sum_list(l,q))


# Fed_Boston.py
# The purpose of this script is to scrape metadata from the most recent Boston Fed working papers. This script uses
# the Boston Fed's Working Paper landing page.
# Lorae Stojanovic
#
# Special thanks to ChatGPT for coding assistance in this project.
# LE: 21 Aug 2023

from bs4 import BeautifulSoup
from selenium import webdriver
import time
import requests
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
import PyPDF2
from io import BytesIO
import io
from datetime import datetime
import pandas as pd

def get_soup(url):
    # Create a new instance of the Firefox driver
    driver = webdriver.Firefox()

    # Go to the page
    driver.get(url)

    # Wait for the button with the specific aria-label and then click it
    button = WebDriverWait(driver, 10).until(
        EC.element_to_be_clickable((By.XPATH, '//a[@aria-label="2023 Series"]'))
    )
    button.click()

    # Wait until a certain number of 'event-list-item' divs appear. Adjust the number '10' as needed.
    WebDriverWait(driver, 30).until(
        EC.presence_of_all_elements_located((By.CLASS_NAME, 'event-list-item'))
    )
    time.sleep(5)

    # Get the page source and parse it
    soup = BeautifulSoup(driver.page_source, 'html.parser')

    # Don't forget to close the driver
    driver.quit()

    return soup

def extract_pdf_metadata_from_url(pdf_url):
    # Download the PDF
    response = requests.get(pdf_url)
    response.raise_for_status()  # Raise an exception for HTTP errors

    # Use BytesIO to convert the downloaded content to a file-like object so it can be read by PyPDF2
    with BytesIO(response.content) as pdf_file:
        # Create a PDF reader object
        pdf_reader = PyPDF2.PdfReader(pdf_file)

        # Extract metadata
        metadata = pdf_reader.metadata

    return metadata

def extract_and_format_moddate(metadata):
    # Extract the ModDate string
    mod_date_str = metadata['/ModDate'][2:16]  # Extracts '20230303104258' from 'D:20230303104258-05'00''

    # Parse the ModDate string into a datetime object
    mod_date = datetime.strptime(mod_date_str, '%Y%m%d%H%M%S')

    # Format the datetime object in the desired format
    formatted_date = mod_date.strftime('%B %d, %Y')

    return formatted_date

def scrape():
    url = "https://www.bostonfed.org/publications/research-department-working-paper/"
    soup = get_soup(url)
    #print(soup)

    elements = soup.find('div', {'class': 'event-list'}).find_all('div', {'class': 'event-body-wrapper'})
    #print(elements)

    # Initialize lists
    Title = []
    Link = []
    Number = []
    Author = []
    Date = []
    Abstract = []

    for el in elements:
        # Getting the title from the landing page
        title = el.find('h2', {'class': 'card-title'}).find('a')['title'].strip()
        Title.append(title)

        # Getting the link from the landing page
        link = "https://www.bostonfed.org" + el.find('h2', {'class': 'card-title'}).find('a')['href']
        Link.append(link)

        # Now we visit the individual entry page to extract authors, abstract, and number.
        headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:66.0) Gecko/20100101 Firefox/66.0"}
        page = requests.get(link, headers=headers) # Include headers in request
        soup = BeautifulSoup(page.content, 'html.parser') # Parse the HTML content using BeautifulSoup

        # Getting the authors from the individual WP page
        author = soup.find('div', {'class': 'row working-paper-by-author-row'}).get_text().strip().replace("By ", "")
        Author.append(author)

        # Getting the abstract from the individual WP page
        abstract = soup.find('div', {'id': 'collapse3'}).get_text().strip()
        Abstract.append(abstract)

        # Getting the number from the individual WP page
        number = soup.find('p', {'class': 'doi-text'}).get_text().split("No. ")[1].split("https:")[0].replace(".", "").strip()
        Number.append(number)

        # Now we use the PDF metadata to get the date
        # But first, we need the link to the pdf.
        pdf_link = "https://www.bostonfed.org" + soup.find('div', {'class': 'row working-paper-download-bttn-row'}).find('a', {'role': 'button'})['href']
        # Now we download the PDF and access its metadata using the user-defined extract_pdf_metadata_from_url function
        metadata = extract_pdf_metadata_from_url(pdf_link)
        # Now we further extract and format the date of last modification
        date = extract_and_format_moddate(metadata)
        Date.append(date)

    # Create a dictionary of the six lists, where the keys are the column names.
    data = {'Title': Title,
            'Link': Link,
            'Date': Date,
            'Author': Author,
            'Number': Number,
            'Abstract': Abstract}

    # Create a DataFrame from the dictionary.
    df = pd.DataFrame(data)

    # Instead of the data frame having row names (indices) equalling 1, 2, etc,
    # we set them to be an identifier that is unique. In the case of Chicago, we combine
    # Chicago with the number of the paper (eg. 999) to get an identifier Chicago999 that
    # is completely unique across all papers scraped.
    df["Source"] = "FED-BOSTON"
    df.index = df["Source"] + df['Number'].astype(str)
    df.index.name = None

    print(df)
    return(df)


# Uma vez fornecido um dicionário composto de seus itens próprios, converta tal contêiner de dados em um DataFrame, em seguida adicionando uma coluna nomeada 'Preço'. Exiba em tela o conteúdo do DataFrame assim como seu tipo de dado:
estoque = {'Cel Xiaomi Redmi Note 11': 1699,
           'Cel Samsung Galaxy s22': 3999,
           'Cel Motorola Moto G200': 2999,
           'Cel LG V60 ThinQ': 1999}

pdestoque = pd.Series(data = estoque)
pdestoque = pd.DataFrame(pdestoque, columns = ['Preço'])

print(pdestoque)
print(type(pdestoque))

Banco de Códigos/Pandas/pd.DataFrame( ).py


# native
import sys, getopt, json
from os.path import join, basename, splitext

# misc
import pandas as pd # easy load of csv
from util.setup_directories import setup
from paf.util import load_humans, save_humans
from util.remove_bg_humans import remove_bg_humans

def load_partial_jsons(path, no_partial_graphs):
    dicts = [None]*(no_partial_graphs+1)

    for i in range(no_partial_graphs+1):
        path_partial_graphs = join(path, str(i) + '.json')
        with open(path_partial_graphs) as f:
            dicts[i] = json.load(f)

    return dicts

def merge_dicts(dicts):

    new_frames = []
    frame_count = 0
    for d in dicts:
        f = d["frames"]
        frame_count += len(f)
        new_frames.extend(d["frames"])

    # assert correct ordering
    for i in range(1, len(new_frames)):
        prev_frame = new_frames[i-1]
        current_frame = new_frames[i]
        assert(prev_frame["frame_id"] < current_frame["frame_id"] or current_frame["frame_id"] == 0)

    # assign new frame id
    for i in range(len(new_frames)):
        new_frames[i]["frame_id"] = i

    metadata = dicts[0]["metadata"]
    metadata["filename"] = basename(metadata["filename"])
    del metadata["subpart"] # only used in this script

    new_dict = {}
    new_dict["frames"] = new_frames
    new_dict["metadata"] = metadata

    return new_dict

def main(input_dir, output_dir):
    annotations_path = join(input_dir, "annotations.csv")
    annotations = pd.read_csv(annotations_path)

    annotations_out = join(output_dir, "annotations.csv")

    paths = annotations.iloc[:,0]
    labels = annotations.iloc[:,1]
    no_partial_graphs = annotations.iloc[:,2]
    for p, l, no in zip(paths, labels, no_partial_graphs):
        dicts = load_partial_jsons(join(input_dir, p), no)
        merged_dicts = merge_dicts(dicts)

        merged_dicts["frames"] = remove_bg_humans(merged_dicts["frames"])

        name, _ = splitext(basename(p))
        filename = join(output_dir, "data", l, name + ".json")
        print("Merged {}".format(filename))

        with open(filename, 'w') as f:
            f.write(json.dumps(merged_dicts, indent=4, sort_keys=True))

        annotations_filename = join("data", l, name + ".json")
        with open(annotations_out, "a") as f:
            f.write("{},{},{}\n".format(annotations_filename, l, len(merged_dicts["frames"])))

    print("\nOutput can be found at {}".format(output_dir))

def parse_args(argv):
    try:
        opts, _ = getopt.getopt(argv, 'hi:o:', ['input_dir=', 'output_dir='])
    except getopt.GetoptError:
       sys.exit(2)
    input_dir = ""
    output_dir = ""
    for opt, arg in opts:
        if opt == '-h':
            sys.exit()
        elif opt in ("-i", "--input"):
            input_dir = arg
        elif opt in ("-o", "--output"):
            output_dir = arg
    return input_dir, output_dir

if __name__ == "__main__":
    input_dir, output_dir = parse_args(sys.argv[1:])
    output_dir = setup(input_dir, output_dir, "graphs", "filename,label,no_frames")
    main(input_dir, output_dir)


# !/usr/bin/python
# -*- conding: utf-8 unicode -*
# vim: tabstop=4 shiftwidth=4 softtabstop=4

from pyudev import Context
import os,sys
import mounted
import sas2ircu_parser

def wwn_to_local_name(wwn):
    disk_by_id_path = "/dev/disk/by-id"

    for link in os.listdir(disk_by_id_path):
        if link.find("wwn") < 0:
            continue
        link_path = disk_by_id_path + "/" + link

        if not os.path.islink(link_path):
            continue
        if link == wwn:
            return os.path.realpath(link_path)
    return None

def wwns_to_local_names(wwns):
    devs = []

    for wwn in wwns:
        dev = wwn_to_local_name(wwn)
        if None == dev:
            raise Exception("wwn %s can not be convert to local name" % wwn)
        devs.append(dev)
    return devs

def disk_block_name_list():
    names = []
    context = Context()
    #get system disk
    boot_dev = mounted.boot_dev()

    for block_dev in context.list_devices(subsystem='block',DEVTYPE='disk'):
        if block_dev.__str__().find("/sys/devices/pci") < 0:
            continue
        else:
            ##filter the system disk
            if boot_dev.find(block_dev.device_node) >= 0:
                continue
            names.append(block_dev.device_node)
    return names

class CPhyDisk:
    def __init__(self):
        self.name = None
        self.size = None
        self.slot = None
        self.wwn  = None
        self.rotational = None
        self.protocol = None

    def string(self):
        ret = {}
        ret['name'] = self.name
        ret['size'] = self.size
        ret['slot'] = self.slot
        ret['wwn'] = self.wwn
        ret['rotational'] = self.rotational
        ret['protocol'] = self.protocol
        return ret

def disk_block_sasaddress(disk_block_name):
    path = '/sys/block/' + disk_block_name.split('/')[2] + '/device/sas_address'
    if not os.path.exists(path):
        return None
    try:
        file_ = open(path)
        address = file_.read()
    except:
        return None

    return address.strip()

def disk_block_slot_protocol(hard_disks,disk_block_name):
    def sas_address_format(address):
        return '0x' + address.replace('-','')
    if not hard_disks:
        return None
    for hard_disk in hard_disks:
        if sas_address_format(hard_disk.sas_address) == disk_block_sasaddress(disk_block_name):
            return (hard_disk.enclosure + ":" + hard_disk.slot,hard_disk.protocol)
    return None

def disk_block_size(disk_block_name):
    dev_size_path = "/sys/block/" + disk_block_name.split("/")[2] + "/size"
    try:
        dev_size_file = open(dev_size_path)
        disk_size = dev_size_file.read()
        dev_size_file.close()
    except:
        return None
    return int(disk_size)

def disk_block_roational(disk_block_name):
    rotational_path = "/sys/block/" + disk_block_name.split("/")[2] + "/queue/rotational"
    try:
        rotational_file = open(rotational_path)
        rotational = rotational_file.read()
        rotational_file.close()
    except:
        return None
    return int(rotational)

def disk_block_wwn(disk_block_name):
    disk_by_id_path = "/dev/disk/by-id"
    for link in os.listdir(disk_by_id_path):
        if link.find("wwn") < 0:
            continue
        link_path = disk_by_id_path + "/" + link

        if not os.path.islink(link_path):
            continue
        if disk_block_name == os.path.realpath(link_path):
            return link
    return None

def disk_block_wwns(disk_block_names):
    wwns = []
    for name in disk_block_names:
        wwns.append(disk_block_wwn(name))
    return wwns

def _disk_block_obj_list(hard_disks):
    objs = []
    for name in disk_block_name_list():
        obj = CPhyDisk()
        obj.name = name
        obj.size = disk_block_size(name)
        obj.wwn  = disk_block_wwn(name)
        obj.rotational  = disk_block_roational(name)

        if hard_disks:
            (slot,protocol) = disk_block_slot_protocol(hard_disks,name)
            obj.slot = slot
            obj.protocol = protocol
        objs.append(obj)
    return objs

def disk_block_obj_list():
    hard_disks = sas2ircu_parser.sasutil_harddisk_list()
    return _disk_block_obj_list(hard_disks)


"""
==================
Data Type Mutation
==================

This performs inferences for the data type (element types) of hypervectors
to optimize the memory size of hypervectors
"""

import numpy as np
import sympy as sp

import ast
from ast import iter_fields
from collections import defaultdict

from ..dev import debug

from ..jit import jit_codegen as codegen

from ..jit import HYPERVECTOR_TYPE, HYPERMATRIX_TYPE, HYPERELEMNT_TYPE
from ..jit import ARG_PREFIX, STRIDE_POSTFIX
from ..jit import NP_INT_ARRAY_TYPE, NP_FLOAT_ARRAY_TYPE

TAG = "jit.date_type_mutator"

def mutate_data_type(node, chunk, arg_variables):
    """ Data type mutation """

    # Debugging code
    debug.log(debug.DEV, TAG, "<<--------------------------")
    debug.log(debug.DEV, TAG, str(ast.dump(node)))
    debug.log(
            debug.DEV, TAG,
            codegen.to_source(node), add_lineno=True)
    for var, var_type in chunk.used_var_types.items():
        debug.log(debug.DEV, TAG, ">> %s : %s" % (var, str(var_type)))
    debug.log(debug.DEV, TAG, "-------------------------->>")
    # End of debugging

    # 1. Convert node to expression tree
    expTreeGenerator = ExpressionTreeGenerator(chunk)
    expTree = expTreeGenerator.visit(node)
    expTree.print_debug()

    for var, var_type in chunk.used_var_types.items():
        #if ARG_PREFIX not in var:
        #    continue
        if var_type == HYPERMATRIX_TYPE or var_type == HYPERVECTOR_TYPE:
            if ARG_PREFIX + var in chunk.used_var_types:
                continue
            chunk.used_var_types[var] = "float*"

        elif var_type == HYPERELEMNT_TYPE:
            chunk.used_var_types[var] = float

    return node

def is_hyper_type(item_type):
    return item_type in [HYPERVECTOR_TYPE, HYPERMATRIX_TYPE, HYPERELEMNT_TYPE]

# TODO: Maybe move to anotehr file
class ExpTree(object):
    def __init__(self, node):
        # possible type for Node
        # 1. ast.Node, 2. string (if-statement) or dominator overriding)
        self.node = node
        self.statement = None # (var_name::string, expr)
        self.node_to_repeat = None
        self.children = []

    def add(self, child):
        if child is None:
            return

        assert(isinstance(child, ExpTree))
        self.children.append(child)
        return self

    def set_statement(self, var, expr):
        self.statement = (var, expr)
        return self

    def print_debug(self):
        msg = ExpTree._debug_str_gen(self, 0)
        debug.log(debug.ERROR, TAG, '\n' + msg)

    @staticmethod
    def _debug_str_gen(eTree, indent): # Recursive call
        line = "  " * indent

        name = ""
        if isinstance(eTree.node, str):
            name += eTree.node
        else:
            name += str(type(eTree.node))

        line += name + " : "

        if eTree.statement is not None:
            var, expr = eTree.statement
            line += " [%s : %s]" % (var, str(expr))
            assert(len(eTree.children) == 0)

        if eTree.node_to_repeat is not None:
            if isinstance(eTree.node_to_repeat, ast.Name):
                arg_str = eTree.node_to_repeat.id
            else:
                arg_str = eTree.node_to_repeat.n

            line += " <RPT: %s>" % (arg_str)

        line += '\n'

        child_lines = ''.join(
                ExpTree._debug_str_gen(c, indent + 1)
                for c in eTree.children)

        return line + child_lines

class ExpressionTreeGenerator(object):
    def __init__(self, chunk):
        self.chunk = chunk
        self.symdict = dict()

        # Scala dominators
        self.__booldmt__ = sp.symbols("__booldmt__", integer=True)
        self.symdict["__booldmt__"] = self.__booldmt__
        self.__intdmt__ = sp.symbols("__intdmt__", integer=True)
        self.symdict["__intdmt__"] = self.__intdmt__
        self.__floatdmt__ = sp.symbols("__floatdmt__", integer=True)
        self.symdict["__floatdmt__"] = self.__floatdmt__

        self.__zero__ = sp.symbols("__zero__", integer=True)
        self.symdict["__zero__"] = self.__zero__
        self.__one__ = sp.symbols("__one__", integer=True)
        self.symdict["__one__"] = self.__one__

        # Function type mapping - {ftnname : overriding_symbol}
        # If the symbol is None, it will bypass the type from the argument
        self.ftn_to_symbol = {
            # Built-in python function
            'int' : self.__intdmt__,
            'float' : self.__floatdmt__,
            'bool' : self.__booldmt__,

            # OpenHD to declare
            'draw_random_hypervector': self.__one__,
            'draw_gaussian_hypervector': self.__floatdmt__,
            'hypervector' : self.__zero__,

            # Functions not included in the chunk
            #'hypermatrix' : (HYPERMATRIX_TYPE, False)

            # Functions called only for assigned target
            #'*__hx_shuffle__' : None,

            # OpenHD built-in operators - bypass the type
            'flip' : None,
            '*__permute__' : None, # The name was changed when unnesting
            '*__hvdim__': None,
            '*__hxdim__': None,

            # TODO: npdim
            }

        # The followings must cover all ast nodes that may change the HV type
        # See also is_transformable_ast in "transpile_planner"
        self.evalutable_node = [
                ast.Assign,
                ast.AugAssign,
                ast.While,
                ast.If,
                ast.For,
                #ast.Call,
                #ast.Expr
                ]

    def get_sym(self, var_name):
        if var_name in self.symdict:
            return self.symdict[var_name]

        new_sym = sp.symbols(var_name)
        self.symdict[var_name] = new_sym
        return new_sym

    def visit(self, node):
        # node: ast node
        # return: inference function expression (sub)tree or
        # expression in a statement
        """ Visit an AST node """
        method = 'visit_' + node.__class__.__name__
        visitor = getattr(self, method, self.generic_visit)
        return visitor(node)

    def visit_body(self, node_list, eTree):
        for node in node_list:
            if not any(isinstance(node, t) for t in self.evalutable_node):
                continue
            subTree = self.visit(node)
            if subTree is None:
                continue
            eTree.add(subTree)

        return eTree

    def visit_Module(self, node):
        eTree = ExpTree(node)
        return self.visit_body(node.body[0].body, eTree)

    def visit_For(self, node):
        # Currently, it can be statically analyzed
        # only when it is called with range in a predictable variable
        try:
            cond = isinstance(node.target, ast.Name)
            cond &= isinstance(node.iter, ast.Call)
            cond &= node.iter.func.id == "range"
            arg = node.iter.args[0]
            cond &= isinstance(arg, ast.Name) or (arg, ast.Num)
        except:
            # override all variables to inf like while loop
            return self.visit_While(node)

        if not cond:
            return self.visit_While(node)

        eTree = ExpTree(node)
        eTree.node_to_repeat = arg
        eTree = self.visit_body(node.body, eTree)
        if len(eTree.children) == 0:
            return None

        return eTree

    def visit_While(self, node):
        eTree = ExpTree(node)
        eTree = self.visit_body(node.body, eTree)

        # Dominator overriding:
        # all assigned variables in the tree will be __floatdmt__ and flattened
        all_vars = set()
        def collect_all_vars(eTree, all_vars):
            if eTree.statement is not None:
                all_vars.add(eTree.statement[0])

            for sub_eTree in eTree.children:
                collect_all_vars(sub_eTree, all_vars)

        collect_all_vars(eTree, all_vars)
        eTree_flatten = ExpTree(node)
        for var in all_vars:
            eTree_flatten.add(
                    ExpTree("OVERRIDING").set_statement(var, self.__floatdmt__))

        if len(eTree_flatten.children) == 0:
            return None

        return eTree_flatten

    def visit_If(self, node):
        eTree = ExpTree(node)

        eTree_then = ExpTree('then')
        eTree_then = self.visit_body(node.body, eTree_then)
        eTree_else = ExpTree('else')
        eTree_else = self.visit_body(node.orelse, eTree_else)

        if len(eTree_then.children) == 0 and len(eTree_else.children) == 0:
            return None

        eTree.add(eTree_then)
        eTree.add(eTree_else)
        return eTree

    def visit_Assign(self, node):
        # This function returns only when assigning HYPERVECTOR or MATRIX
        if len(node.targets) != 1:
            # NOTE: When it happens?
            assert(False)

        target_node = node.targets[0]

        if isinstance(target_node, ast.Call):
            # Case 1: Assignment to pointer retrieved by built-in access ftns
            ftn_name = target_node.func.id
            if ftn_name not in ["*__hxdim__", "*__hvdim__", "*__hx_shuffle__"]:
                return None # Skip evaluation for non-hv type assignment
            var_name = target_node.args[0].id
        elif isinstance(target_node, ast.Name) and node.targets[0].id:
            # Case 2: Assignment to hypervector element
            var_name = target_node.id
            if not self.chunk.used_var_types[var_name] == HYPERELEMNT_TYPE:
                return None
        else:
            return None

        expr = self.visit(node.value)
        if var_name == str(expr): # Assign the same
            return None

        return ExpTree(node).set_statement(var_name, expr)

    def visit_AugAssign(self, node):
        # Convert it to normal assignment to evalute
        return self.visit(
                ast.Assign(
                    [node.target],
                    ast.BinOp(
                        op=node.op,
                        left=node.target,
                        right=node.value
                        )
                    )
                )

    def visit_BinOp(self, node):
        left_expr = self.visit(node.left)
        rght_expr = self.visit(node.right)

        def is_either(left_expr, right_expr, symbol):
            return left_expr == symbol or right_expr == symbol

        # Early type domination
        # NOTE: Bool may not dominate the type
        if is_either(left_expr, rght_expr, self.__floatdmt__):
            return self.__floatdmt__
        if is_either(left_expr, rght_expr, self.__intdmt__):
            return self.__intdmt__

        if isinstance(node.op, ast.Mult):
            return left_expr * rght_expr
        elif isinstance(node.op, ast.Add):
            return left_expr + rght_expr
        elif isinstance(node.op, ast.Sub):
            # In the range computation, the subtraction can be regarded as +
            return left_expr + rght_expr
        elif isinstance(node.op, ast.Div):
            # concise computation is not supported yet
            # Instead, use float dominator
            return self.__floatdmt__
        else:
            debug.log(debug.ERROR, TAG, "Unsupported operator: " % str(node.op))
            assert(False)

    def visit_Num(self, node):
        if isinstance(node.n, int):
            return self.__intdmt__
        elif isinstance(node.n, float):
            return self.__floatdmt__
        else:
            assert(False)

    boolean_constants = frozenset(['True', 'False'])
    def visit_Name(self, node):
        var_name = node.id
        if var_name in self.boolean_constants:
            return self.warn_bool_node(node)

        debug.thrifty_assert(
                var_name in self.chunk.used_var_types,
                "Cannot find the variable type of [%s]" % var_name
                )

        var_type = self.chunk.used_var_types[var_name]
        if var_type == int:
            return self.__intdmt__
        elif var_type == float:
            return self.__floatdmt__
        elif var_type == bool:
            return self.warn_bool_node(node)
        elif is_hyper_type(var_type):
            # NOTE: NP_INT_ARRAY_TYPE or HD_FLOAT_ARRAY_TYPE, etc, must be
            # handled with Subscript
            return self.get_sym(var_name)
        else:
            print(var_name, var_type)
            assert(False)

    def visit_Subscript(self, node):
        var_name = node.value.id
        var_type = self.chunk.used_var_types[var_name]

        if var_type == NP_INT_ARRAY_TYPE or HD_INT_ARRAY_TYPE:
            return self.__intdmt__
        elif var_type == NP_FLOAT_ARRAY_TYPE or HD_FLOAT_ARRAY_TYPE:
            return self.__floatdmt__
        elif var_type == HYPERMATRIX_TYPE:
            return self.get_sym(var_name)
        else:
            assert(False)

        return self.get_sym(node.id)

    def visit_Call(self, node):
        if isinstance(node.func, ast.Attribute):
            fname = node.func.attr # TODO: package name - node.func.value.id
        elif isinstance(node.func, ast.Name):
            fname = node.func.id

        if fname not in self.ftn_to_symbol:
            debug.log(
                    debug.ERROR, TAG,
                    "Unrecognizable function in hypervector computation: %s" % \
                            fname)
            assert(False)

        symbol = self.ftn_to_symbol[fname]
        if symbol is None:
            symbol = self.visit(node.args[0])
            debug.thrifty_assert(
                    symbol in self.symdict.values(),
                    "The first argument of the function %s is not an HV type" \
                            % fname)

        return symbol

    def visit_BoolOp(self, node):
        return self.warn_bool_node(node)

    def warn_bool_node(self, node):
        MSG = "Ast node that returns boolean scala dominator is not "
        MSG += "fully tested yet."
        debug.log(debug.WARNING, TAG, MSG)
        return self.__booldmt__

    # The below ast types cannot be included in the jit-available chunk
    def visit_Expr(self, node):
        assert(False)

    def visit_Str(self, node):
        assert(False)

    def visit_List(self, node):
        assert(False)

    def visit_Tuple(self, node):
        assert(False)

    def visit_Compare(self, node):
        assert(False)

    def generic_visit(self, node):
        # must be unrechable
        debug.log(debug.ERROR, TAG, "Unrecognizable node: %s" % str(node))
        assert(False)


"""Set up the package"""
from os import path

from setuptools import setup, find_packages

HERE = path.abspath(path.dirname(__file__))

with open(path.join(HERE, 'README.md'), encoding='utf-8') as f:
    long_description = f.read()

setup(
    name="useful-lva-sdk",
    version="0.1.7",
    description="Unofficial Vision AI Live Video Analytics SDK",
    long_description=long_description,
    long_description_content_type="text/markdown",
    author="Yan Xue",
    author_email="xueyan.sjtu@gmail.com",
    license="MIT",
    classifiers=[
        "Intended Audience :: Developers",
        "License :: OSI Approved :: MIT License",
        "Programming Language :: Python",
        "Programming Language :: Python :: 3",
        "Programming Language :: Python :: 3.9",
        "Programming Language :: Python :: 3.10",
        "Programming Language :: Python :: 3.11",
        "Operating System :: OS Independent"
    ],
    packages=find_packages(),
    include_package_data=True,
    install_requires=[
        "google-api-core",
        "google-auth",
        "googleapis-common-protos",
        "graphviz",
        "grpcio",
        "protobuf",
    ]
)


import os
import azure.cognitiveservices.speech as speechsdk
from dotenv import load_dotenv

load_dotenv()
speech_key = os.environ['KEY']
service_location = os.environ['LOCATION']

# Creates an instance of a speech config with specified subscription key and service region.
speech_config = speechsdk.SpeechConfig(subscription=speech_key, region=service_location)
speech_config.speech_synthesis_language = "en-GB"
speech_config.speech_synthesis_voice_name = "en-GB-MiaNeural"

# Creates a speech synthesizer using the default speaker as audio output.
speech_synthesizer = speechsdk.SpeechSynthesizer(speech_config=speech_config)

print("Hello, I'm Mia. What do you want me to say?")

# Loop forever
while True:
    # Get what the user wants to say
    speech_input = input()

    # Say the text
    speech_synthesizer.speak_text(speech_input)


fh = open( 'SPAMTrain.label')

i=0
j=0
compter= 0
account=0
listline = []

for line in fh.readlines():
    listline.append(line.split(" ")[0])

while j < 139:
    compter += int(listline[j])
    j += 1
print(compter)

while i < 202:
    account += int(listline[i])
    i += 1
print(account)


import gym
from gym import spaces
from bot_game import BotGame
from stable_baselines.common.policies import MlpPolicy
from stable_baselines import PPO2
from stable_baselines.common.env_checker import check_env
from stable_baselines.common.callbacks import CheckpointCallback
from stable_baselines.common.vec_env import DummyVecEnv, SubprocVecEnv
from setuptools import  setup
from gym.envs.registration import register
import caffeine
import os
import shutil
from timeout_callback import TimeoutCallback
from stable_baselines.gail import ExpertDataset
import numpy as np

class GameEnv(gym.Env):

    """Custom Environment that follows gym interface"""

    metadata = {"render.modes": ["human"]}

    def __init__(self, num_players=2, num_epidemics=4):
        super(GameEnv, self).__init__()

        self.game = BotGame(num_players, num_epidemics)

        # Define action and observation space
        # They must be gym.spaces objects
        # Example when using discrete actions:

        self.action_list = list(self.game.action_dict.keys())
        self.action_space = spaces.Discrete(len(self.action_list))

        self.observation_space = self.game.create_observation_space()

    def step(self, action):
        action_name = self.action_list[action]
        observation, reward, done, info = self.game.step(action_name)
        return observation, reward, done, info

    def reset(self):

        observation = self.game.reset()
        return observation  # reward, done, info can't be included

    def render(self, mode="human"):
        self.game.render(mode)

    def close(self):
        pass

    def reward_level(self):
        return self.game.reward_level()

if __name__ == "__main__":

    register(
        id='pandemic-v0',
        entry_point='gym_foo.envs:FooEnv',
    )

    game_env = GameEnv()
    print("Checking")
    check_env(game_env)

    # Create save dir
    save_dir = "../logs/"
    model_filename = "rl_model"

    checkpoint_dir = save_dir + "most_recent_models/"
    try:
        shutil.rmtree(checkpoint_dir)
    except OSError as e:
        print(e)

    os.mkdir(checkpoint_dir)

    # load the model, and when loading set verbose to 1
    print("Loading")
    # loaded_model = PPO2.load(save_dir + model_filename, verbose=1, env=SubprocVecEnv([GameEnv, GameEnv, GameEnv, GameEnv]))
    # loaded_model = PPO2(MlpPolicy, SubprocVecEnv([GameEnv, GameEnv]), verbose=1)

    # print(("pretraining"))
    # dataset = ExpertDataset(expert_path=save_dir + 'expert_pandemic.npz',
    #                     traj_limitation=1, batch_size=128)
    loaded_model = PPO2(MlpPolicy, env=SubprocVecEnv([GameEnv, GameEnv]), verbose=1)
    # Pretrain the PPO2 model
    # loaded_model.pretrain(dataset, n_epochs=1000)

    # show the save hyperparameters
    print("loaded:", "gamma =", loaded_model.gamma, "n_steps =", loaded_model.n_steps)

    checkpoint_callback = CheckpointCallback(save_freq=50000, save_path=checkpoint_dir,
                                             name_prefix=model_filename)

    print("Learning")
    loaded_model.learn(total_timesteps=2000000, callback=checkpoint_callback)

    print("Saving")
    os.remove(save_dir + model_filename + ".zip")
    loaded_model.save(save_dir + model_filename)

    # obs = game_env.reset()
    #
    # for i in range(1000):
    #     action, _states = loaded_model.predict(obs)
    #     obs, rewards, dones, info = game_env.step(action)
    #     game_env.render()


import smbus
import time

def delayMicroseconds(t):
  time.sleep(float(t)/1000000.0)

def delay(t):
  time.sleep(float(t)/1000.0)

class LiquidCrystal_I2C:

  # commands
  LCD_CLEARDISPLAY = 0x01
  LCD_RETURNHOME = 0x02
  LCD_ENTRYMODESET = 0x04
  LCD_DISPLAYCONTROL = 0x08
  LCD_CURSORSHIFT = 0x10
  LCD_FUNCTIONSET = 0x20
  LCD_SETCGRAMADDR = 0x40
  LCD_SETDDRAMADDR = 0x80

  # flags for display entry mode
  LCD_ENTRYRIGHT = 0x00
  LCD_ENTRYLEFT = 0x02
  LCD_ENTRYSHIFTINCREMENT = 0x01
  LCD_ENTRYSHIFTDECREMENT = 0x00

  # flags for display on/off control
  LCD_DISPLAYON = 0x04
  LCD_DISPLAYOFF = 0x00
  LCD_CURSORON = 0x02
  LCD_CURSOROFF = 0x00
  LCD_BLINKON = 0x01
  LCD_BLINKOFF = 0x00

  # flags for display/cursor shift
  LCD_DISPLAYMOVE = 0x08
  LCD_CURSORMOVE = 0x00
  LCD_MOVERIGHT = 0x04
  LCD_MOVELEFT = 0x00

  # flags for function set
  LCD_8BITMODE = 0x10
  LCD_4BITMODE = 0x00
  LCD_2LINE = 0x08
  LCD_1LINE = 0x00
  LCD_5x10DOTS = 0x04
  LCD_5x8DOTS = 0x00

  # flags for backlight control
  LCD_BACKLIGHT = 0x08
  LCD_NOBACKLIGHT = 0x00

  En = 0x04 # B00000100  Enable bit
  Rw = 0x02 # B00000010 Read/Write bit
  Rs = 0x01 # B00000001 Register select bit

  def __init__(self, addr, lcd_cols, lcd_rows, charsize = 0):
    self.addr = addr
    self.lcd_cols = lcd_cols
    self.lcd_rows = lcd_rows
    self.charsize = charsize
    self.backlightval = self.LCD_BACKLIGHT

  def begin(self, busNo = 0):
    self.bus = smbus.SMBus(busNo)
    self.displayfunction = self.LCD_4BITMODE | self.LCD_1LINE | self.LCD_5x8DOTS

    if self.lcd_rows > 1:
      self.displayfunction |= self.LCD_2LINE

    # for some 1 line displays you can select a 10 pixel high font
    if self.charsize != 0 and self.lcd_rows == 1:
      self.displayfunction |= self.LCD_5x10DOTS

    # SEE PAGE 45/46 FOR INITIALIZATION SPECIFICATION!
    # according to datasheet, we need at least 40ms after power rises above 2.7V
    # before sending commands. Arduino can turn on way befer 4.5V so we'll wait 50
    delay(50)

    # Now we pull both RS and R/W low to begin commands
    self.expanderWrite(self.backlightval)
    delay(1000)

    # put the LCD into 4 bit mode
    # this is according to the hitachi HD44780 datasheet
    # figure 24, pg 46

    # we start in 8bit mode, try to set 4 bit mode
    self.write4bits(0x03 << 4)
    delayMicroseconds(4500) # wait min 4.1ms

    # second try
    self.write4bits(0x03 << 4)
    delayMicroseconds(4500) # wait min 4.1ms

    # third go!
    self.write4bits(0x03 << 4)
    delayMicroseconds(150)

    # finally, set to 4-bit interface
    self.write4bits(0x02 << 4)

    # set # lines, font size, etc.
    self.command(self.LCD_FUNCTIONSET | self.displayfunction)

    # turn the display on with no cursor or blinking default
    self.displaycontrol = self.LCD_DISPLAYON | self.LCD_CURSOROFF | self.LCD_BLINKOFF
    self.display()

    # clear it off
    self.clear()

    # Initialize to default text direction (for roman languages)
    self.displaymode = self.LCD_ENTRYLEFT | self.LCD_ENTRYSHIFTDECREMENT;

    # set the entry mode
    self.command(self.LCD_ENTRYMODESET | self.displaymode);

    self.home()

  #********** high level commands, for the user! *#

  def clear(self):
    self.command(self.LCD_CLEARDISPLAY) # clear display, set cursor position to zero
    delayMicroseconds(2000) # this command takes a long time!

  def home(self):
    self.command(self.LCD_RETURNHOME) # set cursor position to zero
    delayMicroseconds(2000) # this command takes a long time!

  def setCursor(self, col, row):
    row_offsets = [ 0x00, 0x40, 0x14, 0x54 ]
    if row > self.lcd_rows:
      row = self.lcd_rows-1 # we count rows starting w/0

    self.command(self.LCD_SETDDRAMADDR | (col + row_offsets[row]));

  # Turn the display on/off (quickly)
  def noDisplay(self):
    self.displaycontrol &= ~self.LCD_DISPLAYON;
    self.command(self.LCD_DISPLAYCONTROL | self.displaycontrol);

  def display(self):
    self.displaycontrol |= self.LCD_DISPLAYON
    self.command(self.LCD_DISPLAYCONTROL | self.displaycontrol)

  def noBacklight(self):
    self.backlightval = self.LCD_NOBACKLIGHT;
    self.expanderWrite(0);

  def backlight(self):
    self.backlightval = self.LCD_BACKLIGHT;
    self.expanderWrite(0);

  #*********** print functions ***************************#

  def writeBuf(self, buffer):
    n = 0;
    while n < len(buffer):
      if self.write(ord(buffer[n])):
        n+=1
      else:
        break

    return n

  def printStr(self, s):
    return self.writeBuf(s)

  def printNumber(self, n):
    return self.writeBuf(str(n))

  #*********** mid level commands, for sending data/cmds *#

  def command(self, value):
    self.send(value, 0)

  def write(self, value):
    self.send(value, self.Rs)
    return 1

  #************ low level data pushing commands **********#

  # write either command or data
  def send(self, value, mode):
    highnib = value & 0xF0
    lownib = (value << 4) & 0xF0
    self.write4bits((highnib)|mode)
    self.write4bits((lownib)|mode)

  def write4bits(self, value):
    self.expanderWrite(value)
    self.pulseEnable(value)

  def expanderWrite(self, data):
    self.bus.write_byte(self.addr, data | self.backlightval)

  def pulseEnable(self, data):
    self.expanderWrite(data | self.En)
    delayMicroseconds(1)
    self.expanderWrite(data & ~self.En)
    delayMicroseconds(50)


import numpy as np
import pandas as pd
from Source.case_base import CaseBase
from Source.utils.aux_functions import menu, euclidean, find_song_properties
from Source.spotify_api import normalize_vars

# ----------------------------------------------------------------------------------------------------------------------
# PARAMETERS
# ----------------------------------------------------------------------------------------------------------------------

# Paths
DATA_PATH  = '../Data/'
TRAIN_PATH = DATA_PATH + 'songs_train.csv'
TEST_PATH  = DATA_PATH + 'songs_test.csv'
SONGS_PATH = DATA_PATH + 'all_songs.csv'

# CBR
PLAYLIST_LENGTH  = 5    # x >= 1
N_SIM            = 2    # x >= 1
RETAIN_THRESHOLD = 0.6  # 0 < x < 1
EVALUATION_AUTO  = True
MODE             = 'ask'   # ['ask', 'tests', 'example']
RETAIN_WHEN      = 'good'  # [None, 'good', 'bad' (Do not use), 'all' (Do not use)]

# Example instance
EXAMPLE_CASE = [37, 'Male', "Instrumental-Classical,Dance,Blues", 'some concentration', 'really unhappy',
                'calm', 'I keep the same', 'I keep the same']

# Do not modify
NUM_ATTRIB_SOLUTION = 7
TYPE_ATTRIB_SOLUTION = ['num_continuous'] * NUM_ATTRIB_SOLUTION
ATTR_CATEG = 2

# ----------------------------------------------------------------------------------------------------------------------
# MAIN
# ----------------------------------------------------------------------------------------------------------------------
def main():
    # For debugging purposes
    np.random.seed(3)

    # Read files
    data_test = pd.read_csv(TEST_PATH)
    data_train = pd.read_csv(TRAIN_PATH)
    data_songs = pd.read_csv(SONGS_PATH)
    data_train = data_train.drop(data_train.columns[[8, 9, 10, 13, 15, 16, 19, 22, 23, 24, 25, 26]], axis=1)
    data_test = data_test.drop(data_test.columns[[8, 9, 10, 13, 15, 16, 19, 22, 23, 24, 25, 26]], axis=1)

    # Run the example
    if MODE == 'example':
        cb = CaseBase(data_train, NUM_ATTRIB_SOLUTION, ATTR_CATEG, data_songs)
        playlist, _, goodness = run(cb, EXAMPLE_CASE, print_playlist=True)
        print('Solution quality [0,1]:', goodness)

    # Run the CBR in a normal case
    elif MODE == 'ask':
        cb = CaseBase(data_train, NUM_ATTRIB_SOLUTION, ATTR_CATEG, data_songs)
        playlist, _, goodness = run(cb, menu(), print_playlist=True)
        print('Solution quality [0,1]:', goodness)
        print('Process finished successfully')

    # Run tests for the CBR
    elif MODE == 'tests':
        for retain in [None, 'good', 'bad', 'all']:
            results, count_retained = run_tests(data_test, data_train, data_songs, retain_when=retain)
            print('Tests performance: {:.4f} Avg Sim (retain: {:s}, retained: {:d})'.format(
                results, str(retain), count_retained))

# ----------------------------------------------------------------------------------------------------------------------
# RUN AN INSTANCE OF THE CBR IN A CASE
# ----------------------------------------------------------------------------------------------------------------------
def run(cb, new_case, retain_when=RETAIN_WHEN, evaluation_auto=EVALUATION_AUTO, print_playlist=False, plot_retain=False):
    # [R1]: RETRIEVE ****
    retrieved_cases = cb.retrieve_v2(new_case)
    # [R2]: REUSE ****
    solution = cb.update(retrieved_cases, TYPE_ATTRIB_SOLUTION, new_case)
    # [EXTRA]: PLAYLIST CREATION FROM solution ****
    playlist = cb.create_playlist(new_case, solution, max_length=PLAYLIST_LENGTH, norm_feats=True, debug=False)
    if print_playlist:
        print('\nThe generated playlist is:\n{:s}\n'.format(playlist.to_string()))

    # [R3]: REVISE ****
    goodness = cb.revise(solution, new_case, evaluation_auto, plot=plot_retain)

    # Check if the solution should be retained based in the goodness
    if retain_when is None:
        retain = False
    elif retain_when == 'good':
        retain = goodness > RETAIN_THRESHOLD
    elif retain_when == 'bad':
        retain = (1 - goodness) > RETAIN_THRESHOLD
    elif retain_when == 'all':
        retain = True
    else:
        retain = False

    # [R4]: RETAIN ****
    if retain:
        cb.retain(solution, new_case)

    return playlist, retain, goodness

# ----------------------------------------------------------------------------------------------------------------------
# TESTS
# ----------------------------------------------------------------------------------------------------------------------
def run_tests(data_test, data_train, data_songs, retain_when='good'):
    variables = list(data_test)[8:]
    euclidean_max = euclidean([0] * 7, [1] * 7)
    # print(distances_between_all_songs(data_test, euclidean_max))

    # Create CB
    cb = CaseBase(data_train, NUM_ATTRIB_SOLUTION, ATTR_CATEG, data_songs)

    # Distances between returned songs and target
    mean_sims = 0
    count_retained = 0
    for idx, row in data_test.iterrows():
        # Run the CBR
        data = row.values[:8]
        result = row.values[8:]
        result = normalize_vars(variables, result)
        playlist, retained, _ = run(cb, data, evaluation_auto=True, retain_when=retain_when)

        # Count if the solution was retained
        if retained:
            count_retained += 1

        # Measure distance between ground truth song and playlist songs
        distances = []
        for _, song in playlist.iterrows():
            output = find_song_properties(data_songs, song['Song'], song['Artist'], song['Genre'], variables)
            output = normalize_vars(variables, output)
            distances.append(euclidean(output, result))

        # Get mean similarity of n bests
        similarities = 1 - np.array(distances) / euclidean_max
        similarities = np.sort(similarities)[-N_SIM:]
        mean_sims += np.mean(similarities) / len(data_test)

    return mean_sims, count_retained

# ----------------------------------------------------------------------------------------------------------------------
# RUN MAIN
# ----------------------------------------------------------------------------------------------------------------------
if __name__ == '__main__':
    main()


#%%
import pandas as pd
import torch
import torch.nn as nn
from sklearn.preprocessing import LabelEncoder
from sklearn.model_selection import train_test_split
from torch.utils.data import Dataset, DataLoader
import torch.optim as optim
from torch.nn.utils.rnn import pad_sequence, pack_padded_sequence, pad_packed_sequence

#%%
# Read the data
data = pd.read_csv('D:\\ProgramData\\Lund\\Thesis\\data\\simdata.csv')

# Encode behaviors as integers
le = LabelEncoder()
data['behavior_code'] = le.fit_transform(data['behavior'])

# Filter out sessions that have length less than 3 or more than 250
grouped = data.groupby('index')
data = grouped.filter(lambda x: 3 <= len(x) <= 250)

#identify daytime and night time
data['timestamp'] = pd.to_datetime(data['timestamp'])
data['daytime'] = (data['timestamp'].dt.hour >= 6) & (data['timestamp'].dt.hour < 18)
data['daytime'] = data['daytime'].astype(int)  # convert boolean to integer (1 or 0)

# identify weekend or weekday
data['day_of_week'] = data['timestamp'].dt.dayofweek
data['is_weekend'] = (data['day_of_week'] >= 5).astype(int)  # 5 and 6 correspond to Saturday and Sunday

#%%
# Compute the time spent in each action using shift()
data['next_timestamp'] = data['timestamp'].shift(-1)
data['next_index'] = data['index'].shift(-1)
time_diff = pd.to_timedelta(data['next_timestamp'] - data['timestamp'])
data['time_spent'] = time_diff.where(data['index'] == data['next_index'], pd.Timedelta(0)).dt.total_seconds()

# Drop the auxiliary columns
data.drop(columns=['next_timestamp', 'next_index'], inplace=True)

# Compute the average time spent for each behavior code
behavior_avg_time = data[data['time_spent'] != 0].groupby('behavior_code')['time_spent'].mean()
# Add the average time spent to the original data
data['average_time'] = data['behavior_code'].map(behavior_avg_time)
data['time_spent'] = data.apply(lambda x: x['average_time'] if x['time_spent'] == 0 else x['time_spent'], axis=1)

# Group the data by user sessions
session_data = data.groupby('index').agg({'time_spent': lambda x: list(x),
                                          'behavior_code': lambda x: list(x),
                                          'daytime': lambda x: list(x),
                                          'is_weekend': lambda x: list(x)})

print(session_data.head(10))

#%%
input_seq = []
target_seq = []

# Define the prediction window size

for _, row in session_data.iterrows():
    session_sequence = []
    behavior_codes = row['behavior_code']
    time_spent = row['time_spent']
    daytime = row['daytime']
    is_weekend = row['is_weekend']

    for i, behavior_code in enumerate(behavior_codes):
        # Create a vector with zeros
        vector = [0] * (len(le.classes_) + 2)  # add two additional positions for daytime and is_weekend

        # Set the value at the index corresponding to the behavior code to the time spent
        vector[behavior_code] = 1 if time_spent[i] > 0 else 0

        # Set the value at the last but one position to daytime (1 for daytime, 0 for nighttime)
        vector[-2] = daytime[i]

        # Set the value at the last position to is_weekend (1 for weekend, 0 for weekday)
        vector[-1] = is_weekend[i]

        session_sequence.append(vector)

    # Remove the last 'prediction_window' elements for the input sequence
    input_seq.append(session_sequence[:-1])

    # Remove the first 'prediction_window' elements for the target sequence
    # Only the last action is kept for the target sequence
    target_seq.append(session_sequence[-1])

print(input_seq[:5])
print(target_seq[:5])
#%%

unique_item_id = data['itemid'].nunique()
unique_category_id = data['categoryid'].nunique()
unique_product_city = data['product city'].nunique()
print("Number of unique item id:", unique_item_id)
print("Number of unique category id:", unique_category_id)
print("Number of unique product city:", unique_product_city)
#%%
import math

item_id_embedding_dim = min(50, round(math.log2(unique_item_id) * 2))
item_category_embedding_dim = min(50, round(math.log2(unique_category_id) * 2))
product_city_embedding_dim = min(50, round(math.log2(unique_product_city) * 2))

# Define the maximum size of each category (the number of unique values in each category)
# You'll need to compute these values from your data
max_item_id =  unique_item_id
max_item_category = unique_category_id
max_product_city = unique_product_city

#%%
# Preprocessing
data['itemid'] = data['itemid'].astype('category').cat.codes
data['categoryid'] = data['categoryid'].astype('category').cat.codes
data['product city'] = data['product city'].astype('category').cat.codes
grouped = data.groupby('index').agg(list)
#%%
from torch.nn.utils.rnn import pad_sequence

# Convert the lists to tensors and pad them
item_ids = pad_sequence([torch.tensor(i, dtype=torch.long) for i in grouped['itemid'].values], batch_first=True)[:,:-1]
category_ids = pad_sequence([torch.tensor(i, dtype=torch.long) for i in grouped['categoryid'].values], batch_first=True)[:,:-1]
product_cities = pad_sequence([torch.tensor(i, dtype=torch.long) for i in grouped['product city'].values], batch_first=True)[:,:-1]

#%%
# Convert your sequences to tensors and put them in a list
input_tensors = [torch.tensor(seq, dtype=torch.float32) for seq in input_seq]
target_tensors = [torch.tensor(seq, dtype=torch.float32) for seq in target_seq]

# Pad the sequences
padded_input = pad_sequence(input_tensors, batch_first=True, padding_value=0)

# Convert the target tensors to a tensor
target_tensor = torch.stack(target_tensors)
# Convert the target sequences to tensors directly
target_seq_tensor = torch.tensor(target_seq, dtype=torch.float32)
target_indices = torch.argmax(target_tensor, dim=1)

#%%
import math

class TransformerModelConfig:
    def __init__(self, feature_size, d_model, nhead, num_layers, dim_feedforward, dropout):
        self.feature_size = feature_size
        self.d_model = d_model
        self.nhead = nhead
        self.num_layers = num_layers
        self.dim_feedforward = dim_feedforward
        self.dropout = dropout

config = TransformerModelConfig(
    feature_size=len(le.classes_) + 2 + item_id_embedding_dim + item_category_embedding_dim + product_city_embedding_dim,  # number of unique behaviors + 2 for daytime and is_weekend
    d_model=len(le.classes_) + 2 + item_id_embedding_dim + item_category_embedding_dim + product_city_embedding_dim
,
    nhead=1,
    num_layers=2,
    dim_feedforward=512,
    dropout=0.1
)
def positional_encoding(seq_len, d_model, device):
    PE = torch.zeros(seq_len, d_model)
    for pos in range(seq_len):
        for i in range(0, d_model, 2):
            PE[pos, i] = math.sin(pos / (10000 ** ((2 * i)/d_model)))
            if i + 1 < d_model:
                PE[pos, i + 1] = math.cos(pos / (10000 ** ((2 * (i + 1))/d_model)))
    PE = PE.to(device)
    return PE

class TransformerModel(nn.Module):
    def __init__(self, config, max_item_id, max_item_category, max_product_city, item_id_embedding_dim, item_category_embedding_dim, product_city_embedding_dim):
        super(TransformerModel, self).__init__()
        self.feature_size = config.feature_size
        self.d_model = config.d_model

        # Define the embedding layers for item_id, item_category, and product_city
        self.item_id_embedding = nn.Embedding(max_item_id, item_id_embedding_dim)
        self.item_category_embedding = nn.Embedding(max_item_category, item_category_embedding_dim)
        self.product_city_embedding = nn.Embedding(max_product_city, product_city_embedding_dim)

        self.transformer_encoder = nn.TransformerEncoder(
            nn.TransformerEncoderLayer(
                d_model=config.d_model,
                nhead=config.nhead,
                dim_feedforward=config.dim_feedforward,
                dropout=config.dropout,
                activation='relu',
                batch_first=True
            ),
            num_layers=config.num_layers,
            norm=nn.LayerNorm(config.d_model)
        )
        self.output_layer = nn.Linear(config.d_model , config.feature_size)

    def forward(self, src, item_ids, item_categories, product_cities):
        # Compute the embeddings for item_ids, item_categories, and product_cities
        item_id_embeds = self.item_id_embedding(item_ids)
        item_category_embeds = self.item_category_embedding(item_categories)
        product_city_embeds = self.product_city_embedding(product_cities)

        # Concatenate the embeddings with the source tensor along the feature dimension
        src = torch.cat([src, item_id_embeds, item_category_embeds, product_city_embeds], dim=-1)

        current_seq_len = src.size(1)
        pos_encoder = positional_encoding(current_seq_len, self.d_model, device)
        src = src + pos_encoder
        transformed = self.transformer_encoder(src)
        output = self.output_layer(transformed[:, -1, :])
        return output

model = TransformerModel(config, max_item_id, max_item_category, max_product_city,
                         item_id_embedding_dim, item_category_embedding_dim,
                         product_city_embedding_dim)
#%%
class SessionDataset(Dataset):
    def __init__(self, X, y, item_ids, category_ids, product_cities):
        self.X = X
        self.y = y
        self.item_ids = item_ids
        self.category_ids = category_ids
        self.product_cities = product_cities

    def __len__(self):
        return len(self.X)

    def __getitem__(self, index):
        return self.X[index], self.y[index], self.item_ids[index], self.category_ids[index], self.product_cities[index]

# Ensure target_indices is a 1D tensor with the same length as the first dimension of the other tensors
target_indices = target_indices.squeeze()

# Split your data
X_train, X_test, y_train, y_test, item_ids_train, item_ids_test, category_ids_train, category_ids_test, product_cities_train, product_cities_test = train_test_split(padded_input, target_indices, item_ids, category_ids, product_cities, test_size=0.2, random_state=42)
X_train, X_val, y_train, y_val, item_ids_train, item_ids_val, category_ids_train, category_ids_val, product_cities_train, product_cities_val = train_test_split(X_train, y_train, item_ids_train, category_ids_train, product_cities_train, test_size=0.25, random_state=42)  # 0.25 * 0.8 = 0.2

batch_size = 64
train_dataset = SessionDataset(X_train, y_train, item_ids_train, category_ids_train, product_cities_train)
train_dataloader = DataLoader(train_dataset, batch_size=batch_size, shuffle=True)

val_dataset = SessionDataset(X_val, y_val, item_ids_val, category_ids_val, product_cities_val)
val_dataloader = DataLoader(val_dataset, batch_size=batch_size, shuffle=False)

test_dataset = SessionDataset(X_test, y_test, item_ids_test, category_ids_test, product_cities_test)
test_dataloader = DataLoader(test_dataset, batch_size=batch_size, shuffle=False)

#%%
class EarlyStopping:
    def __init__(self, patience=10, delta=0.0):
        self.patience = patience
        self.delta = delta
        self.best_score = None
        self.counter = 0
        self.early_stop = False

    def __call__(self, val_loss):
        score = -val_loss

        if self.best_score is None:
            self.best_score = score
        elif score < self.best_score + self.delta:
            self.counter += 1
            if self.counter >= self.patience:
                self.early_stop = True
        else:
            self.best_score = score
            self.counter = 0

device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
model.to(device)

criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=0.001)

num_epochs = 100

early_stopping = EarlyStopping(patience=10, delta=0.0)

for epoch in range(num_epochs):
    model.train()
    train_loss = 0.0
    for batch in train_dataloader:
        inputs, targets, item_ids, category_ids, product_cities = [tensor.to(device) for tensor in batch]
        optimizer.zero_grad()
        outputs = model(inputs, item_ids, category_ids, product_cities)
        loss = criterion(outputs, targets.long())
        loss.backward()
        optimizer.step()
        train_loss += loss.item()

    train_loss /= len(train_dataloader)
    print(f"Epoch: {epoch+1}, Train Loss: {train_loss:.4f}")

    model.eval()
    val_loss = 0.0
    with torch.no_grad():
        for batch in test_dataloader:
            inputs, targets, item_ids, category_ids, product_cities = [tensor.to(device) for tensor in batch]
            outputs = model(inputs, item_ids, category_ids, product_cities)
            loss = criterion(outputs, targets.long())
            val_loss += loss.item()

    val_loss /= len(val_dataloader)
    print(f"Epoch: {epoch+1}, Validation Loss: {val_loss:.4f}")

    early_stopping(val_loss)

    if early_stopping.early_stop:
        print("Early stopping")
        break

# Evaluate the model on the test set
model.eval()
test_loss = 0.0
with torch.no_grad():
    for batch in test_dataloader:
        inputs, targets, item_ids, category_ids, product_cities = [tensor.to(device) for tensor in batch]
        outputs = model(inputs, item_ids, category_ids, product_cities)
        loss = criterion(outputs, targets.long())

test_loss /= len(test_dataloader)
print(f"Test Loss: {test_loss:.4f}")
#%%
from sklearn.metrics import confusion_matrix
from sklearn.metrics import precision_recall_fscore_support
import numpy as np

model.eval()
all_outputs = []
all_targets = []

with torch.no_grad():
    for batch in test_dataloader:
        inputs, targets, item_ids, category_ids, product_cities = [tensor.to(device) for tensor in batch]
        outputs = model(inputs, item_ids, category_ids, product_cities)
        _, predicted = torch.max(outputs.data, 1)
        all_outputs.extend(predicted.cpu().numpy())
        all_targets.extend(targets.cpu().numpy())

all_outputs = np.array(all_outputs)
all_targets = np.array(all_targets)

# Compute confusion matrix
cm = confusion_matrix(all_targets, all_outputs)

# After evaluation, for the confusion matrix
class_names = le.classes_
cm = confusion_matrix(all_targets, all_outputs)

# Print the confusion matrix
print("Confusion Matrix:")
print(cm)

# Print the class each row is representing for
for i, class_name in enumerate(class_names):
    print(f"Row {i}: {class_name}")

# Compute precision, recall, f-score and support for each class
prfs = precision_recall_fscore_support(all_targets, all_outputs)

# Print precision, recall, f-score and support for each class
for i, class_name in enumerate(class_names):
    print(f"Class: {class_name}")
    print(f"Precision: {prfs[0][i]}")
    print(f"Recall: {prfs[1][i]}")
    print(f"F-score: {prfs[2][i]}")
    print(f"Support: {prfs[3][i]}")
    print("\n")

# %%


# inbuilt libs
import datetime
from copy import deepcopy

# 3rd party libs
import pytest

# project libs
from member_account import MemberAccount
from energy_reading import EnergyReading
from custom_exception import ReadingNotFound, EnergyTypeNotSupported

@pytest.mark.usefixtures('account_reading')
@pytest.mark.usefixtures('full_reading')
class TestAccount:
    """Test for MemberAccount class"""

    def test_init_account_id(self):
        """Test to check if Member Account is initialized with correct account id"""
        account = MemberAccount('account-abc', self.account_reading)
        assert account.account_id == 'account-abc'

    def test_init_invalid_energy_type(self):
        """MemberAccount should throw an InvalidEnergyType exception for invalid energy type"""
        invalid_energy_type = deepcopy(self.account_reading)
        invalid_energy_type[0]['water'] = []
        with pytest.raises(EnergyTypeNotSupported):
            MemberAccount('account-abc', invalid_energy_type)

    def test_billing_readings_len(self):
        """Test to check if member account has correct number of readings for an energy type"""
        account = MemberAccount('account-abc', self.account_reading)
        assert len(account.billing_readings['electricity']) == 2

    def test_billing_readings_instance_of_energy_reading(self):
        """Test to check if member account has correct reading object"""
        account = MemberAccount('account-abc', self.account_reading)
        assert isinstance(account.billing_readings['electricity'][0], EnergyReading)
        assert isinstance(account.billing_readings['electricity'][1], EnergyReading)

    def test_billing_readings_sorted(self):
        """Test to check if billing readings is sorted and lowest date should appear first"""
        account = MemberAccount('account-abc', self.account_reading)
        assert account.billing_readings['electricity'][0].reading_date == datetime.datetime(2017, 2, 28, 0, 0)

    def test_get_month_reading_for_bill_date(self):
        """Test to check if billing date exists in readings and return that reading object correctly"""
        account = MemberAccount('account-abc', self.account_reading)
        reading = account.get_month_reading_for_billing_date('electricity', datetime.datetime(2017, 3, 15, 0, 0))
        assert reading.reading_date == datetime.datetime(2017, 3, 28, 0, 0)

    def test_get_month_reading_for_bill_date_exception(self):
        """Test to check if non-existing billing date in readings should raise exception"""
        account = MemberAccount('account-abc', self.account_reading)
        with pytest.raises(ReadingNotFound):
            account.get_month_reading_for_billing_date('electricity', datetime.datetime(2020, 3, 15, 0, 0))

    def test_calculate_monthly_bill_for_billing_type(self):
        """
        Test if monthly bill is calculated correctly for electricity and matches the expected output.
        """
        account = MemberAccount('account-abc', self.account_reading)
        total_cost, total_units = account.calculate_monthly_bill_for_billing_type('electricity',
                                                                                datetime.datetime(2017, 3, 15, 0, 0))
        assert total_cost == 24659.36
        assert total_units == 2000

    def test_calculate_monthly_bill(self):
        """Test if monthly bill is calculated correctly for an account"""
        account = MemberAccount('account-abc', self.account_reading)
        total_cost, total_units = account.calculate_monthly_bill(datetime.datetime(2017, 3, 15, 0, 0))
        assert total_cost == 246.59
        assert total_units == 2000

    def test_calculate_monthly_bill_with_gas_reading(self):
        """Test if monthly bill is calculated correctly for an account with gas readings"""
        account = MemberAccount('account-abc', self.full_reading)
        total_cost, total_units = account.calculate_monthly_bill(datetime.datetime(2017, 3, 15, 0, 0))
        assert total_cost == 258.01
        assert total_units == 2100

    def test_calculate_monthly_bill_no_reading(self):
        """Monthly bill should be 0 if no readings exists for energy types"""
        empty_reading = deepcopy(self.account_reading)
        empty_reading[0]['electricity'] = []
        empty_reading[0]['gas'] = []
        account = MemberAccount('account-abc', empty_reading)
        total_cost, total_units = account.calculate_monthly_bill(datetime.datetime(2017, 3, 15, 0, 0))
        assert total_cost == 0
        assert total_units == 0


"""Create the input data pipeline using `tf.data`"""

import pandas as pd
import tensorflow as tf
import tensorflow.contrib.eager as tfe
import numpy as np

def load_dataset_from_text(path_dataset):
    """Create tf.data Instance from python pickle file

    Args:
        path_txt: (string) path to pickle file

    Returns:
        dataset: (tf.Dataset) yielding a document, label pair
    """

    # Load and pre prepare the dataset
    data_train = pd.read_pickle(path_dataset)

    docs = data_train[["Sent"]].values.tolist()
    docs = [doc[0] for doc in docs]

    trees = data_train[["Tree"]].values.tolist()
    trees = [tree[0] for tree in trees]

    labels = data_train[["rating"]].values.tolist()
    labels = [label[0] for label in labels]

    def gen():
        for label, doc, tree in zip(labels, docs, trees):
            yield label, doc, tree

    ds = tf.data.Dataset.from_generator(gen, (tf.int32, tf.string, tf.string), ([], [None], [None]))

    return ds

def prepare_batch(ds, vocab, trans, params):
    """Input function HAN

    Args:
        ds: tf.data instance where each element comrrises a document, label tuple
        vocab: pvocab: (tf.lookuptable)
        params: (Params) contains hyperparameters of the model (ex: `params.num_epochs`)

    """
    # Load all the dataset in memory for shuffling is training

    #extract SHIFT-REDUCE transitions as a string from S-expression
    def transition_parser(st):
        tokens = st.split()
        string = ""
        for tok in tokens:
            if tok == ")" :
                string += "REDUCE "
            elif tok == "(":
                pass
            else:
                string += "SHIFT "
        return string

    def _read_py_function(label, sentences, trees):
        doc_len = len(sentences)
        label = label - 1
        sen_len = [len(str(sentence).split(" ")) for sentence in sentences]
        trees_ = [tree.decode('utf-8') for tree in trees]
        transitions = [transition_parser(tree) for tree in trees_]
        return label, doc_len, sen_len, sentences, transitions

    ds = ds.map(lambda label, sentences, trees : tuple(tf.py_func(
     _read_py_function, [label, sentences, trees], [tf.int32, tf.int32, tf.int32, tf.string, tf.string])), num_parallel_calls=4)

    #replace tokens with ids
    def transform(doc, default_value = params.pad_word):
        # Split sentence
        out = tf.string_split(doc)

        # Convert to Dense tensor, filling with default value
        out = tf.sparse_tensor_to_dense(out, default_value=default_value)

        out = vocab.lookup(out)
        out = tf.cast(out, tf.int32)
        return out

    #replace SHIFT with 1, REDUCE with 2, all other entries are dummy paddings
    def transform2(doc, default_value = params.pad_word):
        # Split sentence
        out = tf.string_split(doc)

        # Convert to Dense tensor, filling with default value
        out = tf.sparse_tensor_to_dense(out, default_value=default_value)

        out = trans.lookup(out)
        out = tf.cast(out, tf.int32)
        out += 1
        return out

    ds= ds.map(lambda label, doc_len, sen_len, sentences, transitions : (label, doc_len, sen_len, transform(sentences), transform2(transitions)), num_parallel_calls=4)

    # Create batches and pad the sentences of different length
    padded_shapes = (tf.TensorShape([]),
                     tf.TensorShape([]),   # doc of unknown size
                     tf.TensorShape([None]),  # sentence lengths
                     tf.TensorShape([None, None]), # sentence tokens
                     tf.TensorShape([None, None])) # transition tokens

    padding_values = (0,0,0,params.id_pad_word,0)

    ds = (ds
        .padded_batch(params.batch_size, padded_shapes=padded_shapes, padding_values=padding_values)
        .prefetch(4))  # make sure you always have one batch ready to serve

    #SPINN Preprocessing step: reverse the entries in sentences and prepend a dummy token
    def pad_reverse(label, doc_len, sen_len, sentences, transitions):
        # Reverse sequence and pad an extra one.
        sentences_ = np.reshape(sentences, (sentences.shape[0]*sentences.shape[1],sentences.shape[2]))
        sentences_ = np.fliplr(np.array(sentences_, dtype=np.int32))
        sentences_ = np.concatenate([np.ones([sentences_.shape[0] , 1], dtype=np.int32)*params.id_pad_word, sentences_], axis=1)
        sentences_ = sentences_.T
        transitions = np.reshape(transitions, (transitions.shape[0]*transitions.shape[1],-1)).T
        return label, doc_len, sen_len, sentences_, transitions

    ds = ds.map(lambda label, doc_len, sen_len, sentences, transitions : tuple(tf.py_func(
     pad_reverse, [label, doc_len, sen_len, sentences, transitions], [tf.int32, tf.int32, tf.int32, tf.int32, tf.int32])), num_parallel_calls=4)

    """

    # Create initializable iterator from this dataset so that we can reset at each epoch
    iterator = ds.make_initializable_iterator()

    # Query the output of the iterator for input to the model
    labels, document_sizes, sentence_lengths, sentences, transitions =  iterator.get_next()
    init_op = iterator.initializer
    inputs = {
        'labels': labels,
        'document_sizes': document_sizes,
        'sentence_lengths': sentence_lengths,
        'sentences': sentences,
        'transitions': transitions,
        'iterator_init_op': init_op
       }

    return inputs
    """
    return ds

def prepare_dataset(ds, vocab, trans, params):
    #ds = load_dataset_from_text(path_data)
    ds = prepare_batch(ds, vocab, trans, params)
    return ds


import csv

import os

class CsvFileManager4:

    def reader(self,filename):

        list = [] #声明一个空列表

       # path = r"C:\Users\51Testing\PycharmProjects\selenium7th\data\testdata.csv"

        #更好的方法是：
        #os.path.dirname(__file__)这是一个固定写法，用来获取当前文件的目录结构
        #os操作系统，path路径，dirname目录名，__file__是Python内置的变量，表示当前文件
        base_path = os.path.dirname(__file__)
        print(base_path)
        #用base_path的好处，不管项目方在任何路径下面，都可以找到文件的绝对路径
        path = base_path.replace('day5','data/'+ filename)
        print(path)

        #3.打开指定文件
        #file = open(path,'r')
        #每次打开文件，用完之后要记得关闭该文件，释放系统资源
        #我们上节课用的是try ...finally的方法
        #更常用的方式是with ...as的语法结构
        with open(path,'r')as file:
            date_table = csv.reader(file)
            for row in date_table:
                #循环遍历数据表中的每一行
                print(row)
#       打印出来不是我们的目的，我们的测试用例需要调用这些数据
#       所以，要给这个方法设一个返回值，把数据提取出来
#       5.声明一个二维列表，保存data_table中的所有数据
                list.append(row)
            #在read方法末尾，返回这个列表  # # return list
        return list
        print(list)

if __name__ == '__main__':
    list = CsvFileManager4().reader('testdata.csv')
    print(list[0][0])


# Dictionary mapping each position abbreviation to details about the position

position_typ_map = {
    "P": {
        "code": "1",
        "displayName": "Pitcher",
        "fielder": False,
        "formalName": "Pitcher",
        "fullName": "Pitcher",
        "gamePosition": True,
        "outfield": False,
        "pitcher": True,
        "shortName": "Pitcher",
        "type": "Pitcher"
    },
    "C": {
        "code": "2",
        "displayName": "Catcher",
        "fielder": True,
        "formalName": "Catcher",
        "fullName": "Catcher",
        "gamePosition": True,
        "outfield": False,
        "pitcher": False,
        "shortName": "Catcher",
        "type": "Catcher"
    },
    "1B": {
        "code": "3",
        "displayName": "First Base",
        "fielder": True,
        "formalName": "First Baseman",
        "fullName": "First Base",
        "gamePosition": True,
        "outfield": False,
        "pitcher": False,
        "shortName": "1st Base",
        "type": "Infielder"
    },
    "2B": {
        "code": "4",
        "displayName": "Second Base",
        "fielder": True,
        "formalName": "Second Baseman",
        "fullName": "Second Base",
        "gamePosition": True,
        "outfield": False,
        "pitcher": False,
        "shortName": "2nd Base",
        "type": "Infielder"
    },
    "3B": {
        "code": "5",
        "displayName": "Third Base",
        "fielder": True,
        "formalName": "Third Baseman",
        "fullName": "Third Base",
        "gamePosition": True,
        "outfield": False,
        "pitcher": False,
        "shortName": "3rd Base",
        "type": "Infielder"
    },
    "SS": {
        "code": "6",
        "displayName": "Shortstop",
        "fielder": True,
        "formalName": "Shortstop",
        "fullName": "Shortstop",
        "gamePosition": True,
        "outfield": False,
        "pitcher": False,
        "shortName": "Shortstop",
        "type": "Infielder"
    },
    "LF": {
        "code": "7",
        "displayName": "Outfielder",
        "fielder": True,
        "formalName": "Left Fielder",
        "fullName": "Outfielder",
        "gamePosition": True,
        "outfield": True,
        "pitcher": False,
        "shortName": "Left Field",
        "type": "Outfielder"
    },
    "CF": {
        "code": "8",
        "displayName": "Outfielder",
        "fielder": True,
        "formalName": "Center Fielder",
        "fullName": "Outfielder",
        "gamePosition": True,
        "outfield": True,
        "pitcher": False,
        "shortName": "Center Field",
        "type": "Outfielder"
    },
    "RF": {
        "code": "9",
        "displayName": "Outfielder",
        "fielder": True,
        "formalName": "Right Fielder",
        "fullName": "Outfielder",
        "gamePosition": True,
        "outfield": True,
        "pitcher": False,
        "shortName": "Right Field",
        "type": "Outfielder"
    },
    "DH": {
        "code": "10",
        "displayName": "Designated Hitter",
        "fielder": False,
        "formalName": "Designated Hitter",
        "fullName": "Designated Hitter",
        "gamePosition": True,
        "outfield": False,
        "pitcher": False,
        "shortName": "Designated Hitter",
        "type": "Hitter"
    },
    "PH": {
        "code": "11",
        "displayName": "Pinch Hitter",
        "fielder": False,
        "formalName": "Pinch Hitter",
        "fullName": "Pinch Hitter",
        "gamePosition": True,
        "outfield": False,
        "pitcher": False,
        "shortName": "Pinch Hitter",
        "type": "Hitter"
    },
    "PR": {
        "code": "12",
        "displayName": "Pinch Runner",
        "fielder": False,
        "formalName": "Pinch Runner",
        "fullName": "Pinch Runner",
        "gamePosition": True,
        "outfield": False,
        "pitcher": False,
        "shortName": "Pinch Runner",
        "type": "Runner"
    },
    "EH": {
        "code": "13",
        "displayName": "Extra Hitter",
        "fielder": False,
        "formalName": "Extra Hitter",
        "fullName": "Extra Hitter",
        "gamePosition": True,
        "outfield": False,
        "pitcher": False,
        "shortName": "Extra Hitter",
        "type": "Hitter"
    },
    "BR": {
        "code": "BR",
        "displayName": "Base Runner",
        "fielder": False,
        "formalName": "Base Runner",
        "fullName": "Base Runner",
        "gamePosition": False,
        "outfield": False,
        "pitcher": False,
        "shortName": "Base Runner",
        "type": "Runner"
    },
    "OF": {
        "code": "O",
        "displayName": "Outfield",
        "fielder": True,
        "formalName": "Outfield",
        "fullName": "Outfield",
        "gamePosition": False,
        "outfield": True,
        "pitcher": False,
        "shortName": "Outfield",
        "type": "Outfielder"
    },
    "IF": {
        "code": "I",
        "displayName": "Infield",
        "fielder": True,
        "formalName": "Infield",
        "fullName": "Infield",
        "gamePosition": False,
        "outfield": False,
        "pitcher": False,
        "shortName": "Infield",
        "type": "Infielder"
    },
    "SP": {
        "code": "S",
        "displayName": "Starting Pitcher",
        "fielder": False,
        "formalName": "Starting Pitcher",
        "fullName": "Starting Pitcher",
        "gamePosition": False,
        "outfield": False,
        "pitcher": True,
        "shortName": "Starting Pitcher",
        "type": "Pitcher"
    },
    "RP": {
        "code": "E",
        "displayName": "Relief Pitcher",
        "fielder": False,
        "formalName": "Relief Pitcher",
        "fullName": "Relief Pitcher",
        "gamePosition": False,
        "outfield": False,
        "pitcher": True,
        "shortName": "Relief Pitcher",
        "type": "Pitcher"
    },
    "CP": {
        "code": "C",
        "displayName": "Closer",
        "fielder": False,
        "formalName": "Closer",
        "fullName": "Closer",
        "gamePosition": False,
        "outfield": False,
        "pitcher": True,
        "shortName": "Closer",
        "type": "Pitcher"
    },
    "UT": {
        "code": "U",
        "displayName": "Utility",
        "fielder": True,
        "formalName": "Utility",
        "fullName": "Utility",
        "gamePosition": False,
        "outfield": False,
        "pitcher": False,
        "shortName": "Utility",
        "type": "Infielder"
    },
    "UI": {
        "code": "V",
        "displayName": "Utility Infielder",
        "fielder": True,
        "formalName": "Utility Infielder",
        "fullName": "Utility Infielder",
        "gamePosition": False,
        "outfield": False,
        "pitcher": False,
        "shortName": "Utility Infielder",
        "type": "Infielder"
    },
    "UO": {
        "code": "W",
        "displayName": "Utility Outfielder",
        "fielder": True,
        "formalName": "Utility Outfielder",
        "fullName": "Utility Outfielder",
        "gamePosition": False,
        "outfield": True,
        "pitcher": False,
        "shortName": "Utility Outfielder",
        "type": "Outfielder"
    },
    "RHP": {
        "code": "K",
        "displayName": "Right-Handed Pitcher",
        "fielder": False,
        "formalName": "Right-Handed Pitcher",
        "fullName": "Right-Handed Pitcher",
        "gamePosition": False,
        "outfield": False,
        "pitcher": True,
        "shortName": "Right-Handed Pitcher",
        "type": "Pitcher"
    },
    "LHP": {
        "code": "L",
        "displayName": "Left-Handed Pitcher",
        "fielder": False,
        "formalName": "Left-Handed Pitcher",
        "fullName": "Left-Handed Pitcher",
        "gamePosition": False,
        "outfield": False,
        "pitcher": True,
        "shortName": "Left-Handed Pitcher",
        "type": "Pitcher"
    },
    "RHS": {
        "code": "M",
        "displayName": "Right-Handed Starter",
        "fielder": False,
        "formalName": "Right-Handed Starter",
        "fullName": "Right-Handed Starter",
        "gamePosition": False,
        "outfield": False,
        "pitcher": True,
        "shortName": "Right-Handed Starter",
        "type": "Pitcher"
    },
    "LHS": {
        "code": "N",
        "displayName": "Left-Handed Starter",
        "fielder": False,
        "formalName": "Left-Handed Starter",
        "fullName": "Left-Handed Starter",
        "gamePosition": False,
        "outfield": False,
        "pitcher": True,
        "shortName": "Left-Handed Starter",
        "type": "Pitcher"
    },
    "LHR": {
        "code": "G",
        "displayName": "Left-Handed Reliever",
        "fielder": False,
        "formalName": "Left-Handed Reliever",
        "fullName": "Left-Handed Reliever",
        "gamePosition": False,
        "outfield": False,
        "pitcher": True,
        "shortName": "Left-Handed Reliever",
        "type": "Pitcher"
    },
    "RHR": {
        "code": "F",
        "displayName": "Right-Handed Reliever",
        "fielder": False,
        "formalName": "Right-Handed Reliever",
        "fullName": "Right-Handed Reliever",
        "gamePosition": False,
        "outfield": False,
        "pitcher": True,
        "shortName": "Right-Handed Reliever",
        "type": "Pitcher"
    },
    "P-IF": {
        "code": "A",
        "displayName": "Pitcher - Infielder",
        "fielder": True,
        "formalName": "Pitcher - Infielder",
        "fullName": "Pitcher - Infielder",
        "gamePosition": False,
        "outfield": False,
        "pitcher": True,
        "shortName": "Pitcher - Infielder",
        "type": "Two-Way Player"
    },
    "P-OF": {
        "code": "J",
        "displayName": "Pitcher - Outfielder",
        "fielder": True,
        "formalName": "Pitcher - Outfielder",
        "fullName": "Pitcher - Outfielder",
        "gamePosition": False,
        "outfield": True,
        "pitcher": True,
        "shortName": "Pitcher - Outfielder",
        "type": "Two-Way Player"
    },
    "P-UT": {
        "code": "Z",
        "displayName": "Pitcher - Utility",
        "fielder": True,
        "formalName": "Pitcher - Utility",
        "fullName": "Pitcher - Utility",
        "gamePosition": False,
        "outfield": False,
        "pitcher": True,
        "shortName": "Pitcher - Utility",
        "type": "Two-Way Player"
    },
    "TWP": {
        "code": "Y",
        "displayName": "Two-Way Player",
        "fielder": False,
        "formalName": "Two-Way Player",
        "fullName": "Two-Way Player",
        "gamePosition": False,
        "outfield": False,
        "pitcher": True,
        "shortName": "Two-Way Player",
        "type": "Two-Way Player"
    },
    "B": {
        "code": "10",
        "displayName": "Batter",
        "fielder": False,
        "formalName": "Batter",
        "fullName": "Batter",
        "gamePosition": False,
        "outfield": False,
        "pitcher": False,
        "shortName": "Batter",
        "type": "Batter"
    },
    "X": {
        "code": "X",
        "displayName": "Unknown",
        "fielder": False,
        "formalName": "Unknown",
        "fullName": "Unknown",
        "gamePosition": False,
        "outfield": False,
        "pitcher": False,
        "shortName": "Unknown",
        "type": "Unknown"
    },
    "R1": {
        "code": "R1",
        "displayName": "Runner on First",
        "fielder": False,
        "formalName": "Runner on First",
        "fullName": "Runner on First",
        "gamePosition": False,
        "outfield": False,
        "pitcher": False,
        "shortName": "Runner on First",
        "type": "Runner"
    },
    "R2": {
        "code": "R2",
        "displayName": "Runner on Second",
        "fielder": False,
        "formalName": "Runner on Second",
        "fullName": "Runner on Second",
        "gamePosition": False,
        "outfield": False,
        "pitcher": False,
        "shortName": "Runner on Second",
        "type": "Runner"
    },
    "R3": {
        "code": "R3",
        "displayName": "Runner on Third",
        "fielder": False,
        "formalName": "Runner on Third",
        "fullName": "Runner on Third",
        "gamePosition": False,
        "outfield": False,
        "pitcher": False,
        "shortName": "Runner on Third",
        "type": "Runner"
    }
}


import socket
import json
import threading

import serial
from serial import SerialException
from serial.tools import list_ports

PORT = 7223
READ_TIMEOUT = 1
SCAN_TIMEOUT = 3

class PortNotOpenException(Exception):
    pass

class CommsErrorException(Exception):
    pass

class SerialConnection():
    DEFAULT_WRITE_TIMEOUT = 3
    DEFAULT_READ_TIMEOUT = 1
    timeout = DEFAULT_READ_TIMEOUT
    writeTimeout = DEFAULT_WRITE_TIMEOUT

    ser = None

    def __init__(self, **kwargs):
        pass

    def get_available_devices(self):
        print("SerialConnection: getting available devices")
        devices = [x[0] for x in list_ports.comports()]
        devices.sort()
        filtered_devices = filter(lambda device: not device.startswith('/dev/ttyUSB') and not device.startswith('/dev/ttyS') and not device.startswith('/dev/cu.Bluetooth-Incoming-Port'), devices)
        return list(filtered_devices)

    def isOpen(self):
        return self.ser != None

    def open(self, device):
        self.ser = serial.Serial(device, timeout=self.timeout, write_timeout=self.writeTimeout)

    def close(self):
        if self.ser != None:
            self.ser.close()
        self.ser = None

    def read(self, count):
        ser = self.ser
        if ser == None: raise PortNotOpenException()
        try:
            return ser.read(count)
        except SerialException as e:
            if str(e).startswith('device reports readiness'):
                return ''
            else:
                raise

    def read_line(self):
        msg = ''
        while True:
            c = self.read(1)
            c = c.decode('utf8')
            if c == '':
                return None
            msg += c
            if msg[-2:] == '\r\n':
                msg = msg[:-2]
                return msg

    def write(self, data):
        try:
            return self.ser.write(data.encode('utf8'))
        except SerialException as e:
            raise CommsErrorException(cause=e)

    def flushInput(self):
        try:
            self.ser.flushInput()
        except SerialException as e:
            raise CommsErrorException(cause=e)

    def flushOutput(self):
        try:
            self.ser.flushOutput()
        except SerialException as e:
            raise CommsErrorException(cause=e)

class SocketConnection(object):

    def __init__(self):
        self.socket = None

    def get_available_devices(self):
        """
        Listens for RC WiFi's UDP beacon, if found it returns the ips that the RC wifi beacon says it's available on
        :return: List of ip addresses
        """
        # Logger.info("SocketConnection: listening for RC wifi...")
        print("SocketConnection: getting available devices")
        # Listen for UDP beacon from RC wifi
        sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        sock.settimeout(SCAN_TIMEOUT)

        # Bind the socket to the port
        server_address = ('0.0.0.0', PORT)
        sock.bind(server_address)

        try:
            data, address = sock.recvfrom(4096)

            if data:
                # Logger.info("SocketConnection: got UDP data {}".format(data))
                # print(f"got data: {data}")
                print(data)
                message = json.loads(data)
                if message['beacon'] and message['beacon']['ip']:
                    sock.close()
                    return message['beacon']['ip']
        except socket.timeout:
            sock.close()
            # Logger.info("SocketConnection: found no RC wifi (timeout listening for UDP beacon)")
            print("found no RC wifi")
            return []

    def isOpen(self):
        """
        Returns True or False if socket is open or not
        :return: Boolean
        """
        return self.socket is not None

    def open(self, address):
        """
        Opens a socket connection to the specified address
        :param address: IP address to connect to
        :return: None
        """
        # Connect to ip address here
        rc_address = (address, 7223)
        self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.socket.connect(rc_address)
        self.socket.settimeout(READ_TIMEOUT)

    def close(self):
        """
        Closes the socket connection
        :return: None
        """
        self.socket.close()
        self.socket = None

    def read(self, keep_reading):
        """
        Reads data from the socket. Will continue to read until either "\r\n" is found in the data read from the
        socket or keep_reading.is_set() returns false
        :param keep_reading: Event object that is checked while data is read
        :type keep_reading: threading.Event
        :return: String or None
        """
        msg = ''
        # Logger.info("SocketConnection: reading...")
        print("reading...")

        while keep_reading.is_set():
            try:
                data = self.socket.recv(4096)
                data = data.decode('utf8')
                if data == '':
                    return None

                msg += data

                print(data)

                if msg[-2:] == '\r\n':
                    if msg != '':
                        # Logger.info("SocketConnection: returning data {}".format(msg))
                        # print(f"returning data: {data}")
                        return msg
                    else:
                        return None
            except socket.timeout:
                print("here")

    def write(self, data):
        """
        Writes data to the socket
        :param data: Data to write
        :type data: String
        :return: None
        """
        self.socket.send(data.encode('utf8'))

    def flushInput(self):
        pass

    def flushOutput(self):
        pass

def open_socket():
    should_read = threading.Event()
    should_read.set()

    sock = SocketConnection()
    devices = sock.get_available_devices()
    print(devices)
    sock.open(devices[0])

    # cmd = {'s':None}
    # cmd = {'getCapabilities': None}
    cmd = {'s':{'meta':1}}
    cmdStr = json.dumps(cmd, separators=(',', ':')) + '\r'
    sock.write(cmdStr)

    sock.read(should_read)

def open_serial():
    serial = SerialConnection()
    devices = serial.get_available_devices()
    print(devices)
    serial.open(devices[0])

    cmd = {'s':{'meta':1}}
    cmdStr = json.dumps(cmd, separators=(',', ':')) + '\r'
    serial.write(cmdStr)

    print(serial.read_line())

if __name__ == '__main__':
    # open_socket()
    open_serial()

'''
b'{"beacon":{"name":"RCP_MK3","port":7223,"serial":"3F005A000B51343034323934","ip":["192.168.4.1"]}}\r\n'
['192.168.4.1']
'''

'''
IMU on channel 1 will return:
{"imuCfg":{"1":{"nm":"AccelY","ut":"G","min":-3.0,"max":3.0,"prec":2,"sr":25,"mode":1,"chan":1,"zeroVal":-248,"alpha":0.1}}}

{"capabilities":{"flags":["activetrack","adc","bt","can","can_term","cell","gpio","gps","imu","lua","obd2","telemstream","timer","tracks","usb","wifi","sd","camctl"],"channels":{"analog":9,"imu":6,"gpio":3,"timer":4,"can":2,"obd2":20,"canChan":100},"sampleRates":{"gps":50,"sensor":1000},"db":{"script":16384,"tracks":50,"sectors":20}}}
'''

'''
Sample data: 's'

{"s":{"t":0,"d":[304359,0,302,302,0,0.0,4.26,-0.24,-0.28,0.69,12,-29,122,0.37,0,0.0,0.0,0.0,0.0,0,0,0.0,0,0.0,-1,0.0,0.0,0.0,0,0.0,5.0726,2147483647]}}
'''


# File: ./examples2D/Vortex_Precession_2D.py
# Run as    python3 bpm.py Vortex_Precession_2D 2D
# Vortex precession within a harmonic potential

import numpy as np

Nx = 300						# Grid points
Ny = Nx
dt = 0.001					# Evolution step
tmax = 80		            # End of propagation
xmax = 8 					# x-window size
ymax = xmax					# y-window size
images = 800				# number of .png images
absorb_coeff = 0		# 0 = periodic boundary
output_choice = 3     # If 1, it plots on the screen but does not save the images
							# If 2, it saves the images but does not plot on the screen
							# If 3, it saves the images and plots on the screen
fixmaximum= 2             # Fixes a maximum scale of |psi|**2 for the plots. If 0, it does not fix it.

def psi_0(x,y):

      # Initial wavefunction: a vortex configuration

	z=x+1.j*y
	absz2=x**2+y**2
	f = (1-1.2*z)*np.exp(z)*np.exp(-absz2/2)

	return f;

def V(x,y,t,psi):		# A harmonic trap and a repulsive cubic potential

	V = (x**2+y**2)/2 + abs(psi)**2
	return V;


"""
You are given an array of integers.

Write a function that will take this array
as input and return the sorted array using merge sort

Sorted Array
---------------

Time complexity ==> O(n+m)
Space complexity ==> O(n+m)

Unsorted Array
----------------
Time complexity ==> O(n log n)
Space complexity ==> O(n)

"""

def merge_sorted_list(list_one, list_two):
  merged_list = []
  i = 0
  j = 0

  while(i < len(list_one) and j < len(list_two)):

    if list_one[i] <= list_two[j]:
      merged_list.append(list_one[i])
      i+=1
    else:
      merged_list.append(list_two[j])
      j+=1

  while i < len(list_one):
    merged_list.append(list_one[i])
    i+=1

  while j < len(list_two):
    merged_list.append(list_two[j])
    j+=1

  return merged_list

def merge_sort(list):
  if len(list) <= 1: return list

  middle = len(list) // 2

  left_side = merge_sort(list[:middle])
  right_side = merge_sort(list[middle:len(list)])

  return merge_sorted_list(left_side, right_side)

print(merge_sort([5,4,3,2]))
print(merge_sort([5, 3, 7, 8, 1, 9, 12]))