'''
Script to save xyz files.
'''
import numpy as np
import sys
import simulation_analysis as sa
from quaternion import Quaternion

if __name__ == '__main__':
  # Set parameters
  file_prefix = '/home/fbalboa/simulations/RigidMultiblobsWall/FreeSlip/data/run0/run1/run1.0.0.0'
  files_method = 'File' # 'sequence'
  file_start = 0
  file_end = 0
  file_prefix_config = '/home/fbalboa/simulations/RigidMultiblobsWall/rheology/data/run2000/run2131/run2131.3.0.'
  file_suffix_config = '.star_run2131.3.0.'
  files_config = ['/home/fbalboa/simulations/RigidMultiblobsWall/FreeSlip/data/run0/run1/run1.0.0.0.shell.config']
  structure = 'shell'
  name_vertex = '/home/fbalboa/sfw/RigidMultiblobsWall/multi_bodies/Structures/shell_N_42_Rg_0_8913_Rh_1.vertex'
  num_frames = 10000
  n_save_xyz = 1
  save_blobs = True
  save_dipole = True
  save_velocity = False
  save_dat_index = []

  # Get names config files
  if files_method == 'sequence':
    files_config = []
    for i in range(file_start, file_end + 1):
      name = file_prefix_config + str(i) + file_suffix_config + str(i) + '.config'
      files_config.append(name)

  # Read inputfile
  name_input = file_prefix + '.inputfile'
  read = sa.read_input(name_input)

  # Read vertex
  r_vectors = sa.read_vertex(name_vertex)

  # Get number of particles
  N = sa.read_particle_number(files_config[0])

  # Set some parameters
  dt = float(read.get('dt'))
  n_save = int(read.get('n_save'))
  dt_sample = dt * n_save * n_save_xyz
  eta = float(read.get('eta'))
  if 'quaternion_B' in read:
    print('quaternion_B = ', read.get('quaternion_B'))
    quaternion_B = Quaternion(np.fromstring(read.get('quaternion_B'), sep=' ') / np.linalg.norm(np.fromstring(read.get('quaternion_B'), sep=' ')))
    R_B = quaternion_B.rotation_matrix()
  print('file_prefix = ', file_prefix)
  print('dt          = ', dt)
  print('dt_sample   = ', dt_sample)
  print('n_save      = ', n_save)
  print('eta         = ', eta)
  print(' ')

  # Loop over config files
  x = sa.read_config_list(files_config, print_name=True)
  x = x[0::n_save_xyz]

  # Concatenate config files
  t = np.arange(x.shape[0]) * dt_sample
  print('total number of frames = ', x.shape[0])
  print('num_frames             = ', num_frames)
  print(' ')

  # Save xyz for blobs
  if save_blobs:
    name = file_prefix + '.' + structure + '.xyz'
    num_blobs = r_vectors.shape[0] * x.shape[1]
    blob_vector_constant = np.zeros((x.shape[1], r_vectors.shape[0]))
    for i in range(x.shape[1]):
      blob_vector_constant[i,:] = x[0,i,0]
    sa.save_xyz(x, r_vectors, name, num_frames=num_frames, letter=structure[0].upper(), blob_vector_constant=blob_vector_constant)

  # Save velocity as xyz file
  if save_velocity:
    # Compute velocity
    name = file_prefix + '.' + structure + '.velocity.xyz'
    velocity = sa.compute_velocities(x, dt=dt_sample)
    sa.save_xyz(x, np.zeros(3), name, num_frames=num_frames, letter=structure[0].upper(), body_vector=velocity, header='Columns: r, velocity')

  # Save dat file
  if save_dat_index is not None:
    for i in save_dat_index:
      name = file_prefix + '.' + structure + '.' + str(i) + '.dat'
      sa.save_dat(x, t, i, name)

  # Save dipole as xyz file
  if save_dipole:
    dipole_0 = np.fromstring(read.get('mu'), sep=' ')
    B0 = float(read.get('B0'))
    omega = float(read.get('omega'))
    dipole = np.zeros((x.shape[1], 3))
    dipole[:] = dipole_0
    B_xy = np.zeros((x.shape[0], 3))
    B_xy[:,0] = B0 * np.cos(omega * t)
    B_xy[:,1] = B0 * np.sin(omega * t)
    B = np.einsum('ij,kj->ki', R_B, B_xy)
    name = file_prefix + '.' + structure + '.dipole.xyz'
    print('B0    = ', B0)
    print('omega = ', omega)
    print('name  = ', name)
    sa.save_xyz(x, np.zeros(3), name, num_frames=num_frames, letter=structure[0].upper(), body_frame_vector=dipole, global_vector=B, header='Columns: r, dipole, magnetic field')


from Classes.Configuracoes import Configuracoes
from Classes.CarroJson import CarroJson
import requests
import _thread
import webbrowser
import json

#responsavel so por enviar imagem/dados para o webbservice

class WebService:
    def __init__(self, carro):
        self.Carro = carro
        self.Json = CarroJson()
        self.UltimoCarro = self.Json.Carro
        self.Config = Configuracoes()
        self.ValidaVeiculo()

    def ValidaVeiculo(self):
        try:
            if (self.Carro.Placa != self.UltimoCarro.Placa or self.UltimoCarro.Placa == ""):
                self.ConsultaWebService()
                self.Json.Escrever(self.Carro)
            if (self.Carro.Placa == self.UltimoCarro.Placa):
                tempo = self.Carro.Data - self.UltimoCarro.Data
            if (tempo.seconds > self.Config.TempoParada):
                self.ConsultaWebService()
                self.Json.Escrever(self.Carro)
            else:
                print("############################")
                print("Mesmo Veiculo")
        except Exception as e:
            print("ERRO " + str(e))

    def ConsultaWebService(self):
        try:
            # print("\n\n########################\n\n")
            # print(self.Dados())
            # print("\n\n########################\n\n")
            # print("ENVIANDO PARA SERVER")
            self.PostWebService(self.Config.RegistraVeiculo)
        except:
            return 0

    def Dados(self):
        dados = { "placa": self.Carro.Placa, "taxa": str(self.Carro.Taxa), "imagem": str(self.Carro.Imagem), "cor": str(self.Carro.Cor) }
        return dados

    def PostWebService(self, endereco):
        try:
            env = requests.post(url=self.Config.Api + endereco, data=self.Dados())
            print(env.text)
        except:
            print("erro ao enviar")


import numpy as np
import MNN
from PIL import Image
F = MNN.expr

# adapted from pycaffe
def load_image(filename, color=True):
    """
    Load an image converting from grayscale or alpha as needed.

    Parameters
    ----------
    filename : string
    color : boolean
        flag for color format. True (default) loads as RGB while False
        loads as intensity (if image is already grayscale).

    Returns
    -------
    image : an image with type np.float32 in range [0, 1]
        of size (H x W x 3) in RGB or
        of size (H x W x 1) in grayscale.
    """
    img = Image.open(filename)
    img = np.array(img)
    if img.ndim == 2:
        img = img[:, :, np.newaxis]
        if color:
            img = np.tile(img, (1, 1, 3))
    elif img.shape[2] == 4:
        img = img[:, :, :3]
    return img

def resize_image(image, shape):
    im = Image.fromarray(image)
    im = im.resize(shape)
    resized_image = np.array(im)

    return resized_image

class FinetuneDataset(MNN.data.Dataset):
    def __init__(self, image_folder, image_txt):
        super(FinetuneDataset, self).__init__()
        self.image_folder = image_folder
        self.image_txt = image_txt
        f = open(image_txt)
        self.image_list = f.readlines()

    def __getitem__(self, index):
        image_name = self.image_list[index].split(" ")[0]
        image_label = int(self.image_list[index].split(" ")[1])
        image_file = self.image_folder + image_name

        image_data = load_image(image_file)
        image_data = resize_image(image_data, (224, 224))

        image_data = (image_data - 127.5) / 127.5

        dv = F.const(image_data.flatten().tolist(), [224, 224, 3], F.data_format.NHWC)
        dl = F.const([image_label], [], F.data_format.NHWC, F.dtype.int)
        # first for inputs, and may have many inputs, so it's a list
        # second for targets, also, there may be more than one targets
        return [dv], [dl]

    def __len__(self):
        # size of the dataset
        return len(self.image_list)


from flask import Flask, render_template
import requests
from bs4 import BeautifulSoup
import json
import time

app = Flask(__name__)
@app.route('/')
def index():
    with open('data.json') as f:
        data = json.load(f)
    return json.dumps(data)

def scrape_articles(chosencategory, articletype, category):
    url = ("https://shalhevetboilingpoint.com/category/" + chosencategory)
    page = 1
    articles = []
    while True:
        response = requests.get(f"{url}/page/{page}")
        soup = BeautifulSoup(response.content, 'html.parser')
        posts = soup.find_all("div", class_=articletype)
        if not posts:
            break
        for post in posts:
            article = {}
            article["title"] = post.find('a', {'class': 'homeheadline'}).text.strip()
            article["url"] = post.find('a')['href']
            article["description"] = post.find('div', {'class': 'catlist-teaser'}).text.strip()
            try:
                article["urlToImage"] = post.find('img')['src']
            except TypeError:
                pass
            try:
                article["author"] = post.find('span', {'class': 'catlist-writer'}).text.strip()
                # article["author"] = "Written By: Benjy Kolieb"
            except AttributeError:
                pass
            try:
                article["publishedAt"] = post.find('span', {'class': 'time-wrapper'}).text.strip()
            except AttributeError:
                pass
            article["category"] = category
            articles.append(article)
        page += 1
    return articles
def update_data():
    while True:
        def nw_data():
            articles = {}
            articles["top_stories"] = scrape_articles("top-stories/", "profile-rendered catlist-panel catlist_sidebar",
                                                      "top")
            articles["community"] = scrape_articles("community/", "profile-rendered catlist-panel catlist_sidebar",
                                                    "community")
            articles["arts"] = scrape_articles("arts/", "profile-rendered catlist-panel catlist_fullwidth", "arts")
            articles["torah"] = scrape_articles("torah/", "profile-rendered catlist-panel catlist_fullwidth", "torah")
            articles["outside_news"] = scrape_articles("outside-news/", "catlist-tile-inner", "outside")
            articles["opinion"] = scrape_articles("opinion/", "catlist-tile-inner", "opinion")
            articles["alumni"] = scrape_articles("alumni/", "catlist-tile-inner", "alumni")
            articles["features"] = scrape_articles("features/", "profile-rendered catlist-panel catlist_fullwidth",
                                                   "feature")
            return json.dumps(articles)
        new_data = nw_data()
        with open('data.json', 'w') as f:
            json.dump(new_data, f)
        time.sleep(1800)  # wait for 30 minutes

if __name__ == '__main__':
    # Start a new thread to update the data in the background
    import threading
    update_thread = threading.Thread(target=update_data)
    update_thread.start()

    # Start the Flask app
    app.run(debug=True)


""" View validation code (using assertions, not the RNG schema). """

import ast
import collections
import logging
import os
import re

from lxml import etree
from odoo import tools
from odoo.osv.expression import DOMAIN_OPERATORS

_logger = logging.getLogger(__name__)

_validators = collections.defaultdict(list)
_relaxng_cache = {}

READONLY = re.compile(r"\breadonly\b")

# predefined symbols for evaluating attributes (invisible, readonly...)
IGNORED_IN_EXPRESSION = {
    'True', 'False', 'None',    # those are identifiers in Python 2.7
    'self',
    'uid',
    'context',
    'context_today',
    'allowed_company_ids',
    'current_company_id',
    'time',
    'datetime',
    'relativedelta',
    'current_date',
    'today',
    'now',
    'abs',
    'len',
    'bool',
    'float',
    'str',
    'unicode',
    'set',
}

def get_domain_value_names(domain):
    """ Return all field name used by this domain
    eg: [
            ('id', 'in', [1, 2, 3]),
            ('field_a', 'in', parent.truc),
            ('field_b', 'in', context.get('b')),
            (1, '=', 1),
            bool(context.get('c')),
        ]
        returns {'id', 'field_a', 'field_b'}, {'parent', 'parent.truc', 'context'}

    :param domain: list(tuple) or str
    :return: set(str), set(str)
    """
    contextual_values = set()
    field_names = set()

    try:
        if isinstance(domain, list):
            for leaf in domain:
                if leaf in DOMAIN_OPERATORS or leaf in (True, False):
                    # "&", "|", "!", True, False
                    continue
                left, _operator, _right = leaf
                if isinstance(left, str):
                    field_names.add(left)
                elif left not in (1, 0):
                    # deprecate: True leaf and False leaf
                    raise ValueError()

        elif isinstance(domain, str):
            def extract_from_domain(ast_domain):
                if isinstance(ast_domain, ast.IfExp):
                    # [] if condition else []
                    extract_from_domain(ast_domain.body)
                    extract_from_domain(ast_domain.orelse)
                    return
                if isinstance(ast_domain, ast.BoolOp):
                    # condition and []
                    # this formating don't check returned domain syntax
                    for value in ast_domain.values:
                        if isinstance(value, (ast.List, ast.IfExp, ast.BoolOp, ast.BinOp)):
                            extract_from_domain(value)
                        else:
                            contextual_values.update(_get_expression_contextual_values(value))
                    return
                if isinstance(ast_domain, ast.BinOp):
                    # [] + []
                    # this formating don't check returned domain syntax
                    if isinstance(ast_domain.left, (ast.List, ast.IfExp, ast.BoolOp, ast.BinOp)):
                        extract_from_domain(ast_domain.left)
                    else:
                        contextual_values.update(_get_expression_contextual_values(ast_domain.left))

                    if isinstance(ast_domain.right, (ast.List, ast.IfExp, ast.BoolOp, ast.BinOp)):
                        extract_from_domain(ast_domain.right)
                    else:
                        contextual_values.update(_get_expression_contextual_values(ast_domain.right))
                    return
                for ast_item in ast_domain.elts:
                    if isinstance(ast_item, ast.Constant):
                        # "&", "|", "!", True, False
                        if ast_item.value not in DOMAIN_OPERATORS and ast_item.value not in (True, False):
                            raise ValueError()
                    elif isinstance(ast_item, (ast.List, ast.Tuple)):
                        left, _operator, right = ast_item.elts
                        contextual_values.update(_get_expression_contextual_values(right))
                        if isinstance(left, ast.Constant) and isinstance(left.value, str):
                            field_names.add(left.value)
                        elif isinstance(left, ast.Constant) and left.value in (1, 0):
                            # deprecate: True leaf (1, '=', 1) and False leaf (0, '=', 1)
                            pass
                        elif isinstance(right, ast.Constant) and right.value == 1:
                            # deprecate: True/False leaf (py expression, '=', 1)
                            contextual_values.update(_get_expression_contextual_values(left))
                        else:
                            raise ValueError()
                    else:
                        raise ValueError()

            expr = domain.strip()
            item_ast = ast.parse(f"({expr})", mode='eval').body
            if isinstance(item_ast, ast.Name):
                # domain="other_field_domain"
                contextual_values.update(_get_expression_contextual_values(item_ast))
            else:
                extract_from_domain(item_ast)

    except ValueError:
        raise ValueError("Wrong domain formatting.") from None

    value_names = set()
    for name in contextual_values:
        if name == 'parent':
            continue
        root = name.split('.')[0]
        if root not in IGNORED_IN_EXPRESSION:
            value_names.add(name if root == 'parent' else root)
    return field_names, value_names

def _get_expression_contextual_values(item_ast):
    """ Return all contextual value this ast

    eg: ast from '''(
            id in [1, 2, 3]
            and field_a in parent.truc
            and field_b in context.get('b')
            or (
                True
                and bool(context.get('c'))
            )
        )
        returns {'parent', 'parent.truc', 'context', 'bool'}

    :param item_ast: ast
    :return: set(str)
    """

    if isinstance(item_ast, ast.Constant):
        return set()
    if isinstance(item_ast, ast.Str):
        return set()
    if isinstance(item_ast, (ast.List, ast.Tuple)):
        values = set()
        for item in item_ast.elts:
            values |= _get_expression_contextual_values(item)
        return values
    if isinstance(item_ast, ast.Name):
        return {item_ast.id}
    if isinstance(item_ast, ast.Attribute):
        values = _get_expression_contextual_values(item_ast.value)
        if len(values) == 1:
            path = sorted(list(values)).pop()
            values = {f"{path}.{item_ast.attr}"}
            return values
        return values
    if isinstance(item_ast, ast.Index): # deprecated python ast class for Subscript key
        return _get_expression_contextual_values(item_ast.value)
    if isinstance(item_ast, ast.Subscript):
        values = _get_expression_contextual_values(item_ast.value)
        values |= _get_expression_contextual_values(item_ast.slice)
        return values
    if isinstance(item_ast, ast.Compare):
        values = _get_expression_contextual_values(item_ast.left)
        for sub_ast in item_ast.comparators:
            values |= _get_expression_contextual_values(sub_ast)
        return values
    if isinstance(item_ast, ast.BinOp):
        values = _get_expression_contextual_values(item_ast.left)
        values |= _get_expression_contextual_values(item_ast.right)
        return values
    if isinstance(item_ast, ast.BoolOp):
        values = set()
        for ast_value in item_ast.values:
            values |= _get_expression_contextual_values(ast_value)
        return values
    if isinstance(item_ast, ast.UnaryOp):
        return _get_expression_contextual_values(item_ast.operand)
    if isinstance(item_ast, ast.Call):
        values = _get_expression_contextual_values(item_ast.func)
        for ast_arg in item_ast.args:
            values |= _get_expression_contextual_values(ast_arg)
        return values
    if isinstance(item_ast, ast.IfExp):
        values = _get_expression_contextual_values(item_ast.test)
        values |= _get_expression_contextual_values(item_ast.body)
        values |= _get_expression_contextual_values(item_ast.orelse)
        return values
    if isinstance(item_ast, ast.Dict):
        values = set()
        for item in item_ast.keys:
            values |= _get_expression_contextual_values(item)
        for item in item_ast.values:
            values |= _get_expression_contextual_values(item)
        return values

    raise ValueError(f"Undefined item {item_ast!r}.")

def get_expression_field_names(expression):
    """ Return all field name used by this expression

    eg: expression = '''(
            id in [1, 2, 3]
            and field_a in parent.truc.id
            and field_b in context.get('b')
            or (True and bool(context.get('c')))
        )
        returns {'parent', 'parent.truc', 'parent.truc.id', 'context', 'context.get'}

    :param expression: str
    :param ignored: set contains the value name to ignore.
                    Add '.' to ignore attributes (eg: {'parent.'} will
                    ignore 'parent.truc' and 'parent.truc.id')
    :return: set(str)
    """
    item_ast = ast.parse(expression.strip(), mode='eval').body
    contextual_values = _get_expression_contextual_values(item_ast)

    value_names = set()
    for name in contextual_values:
        if name == 'parent':
            continue
        root = name.split('.')[0]
        if root not in IGNORED_IN_EXPRESSION:
            value_names.add(name if root == 'parent' else root)

    return value_names

def get_dict_asts(expr):
    """ Check that the given string or AST node represents a dict expression
    where all keys are string literals, and return it as a dict mapping string
    keys to the AST of values.
    """
    if isinstance(expr, str):
        expr = ast.parse(expr.strip(), mode='eval').body

    if not isinstance(expr, ast.Dict):
        raise ValueError("Non-dict expression")
    if not all(isinstance(key, ast.Str) for key in expr.keys):
        raise ValueError("Non-string literal dict key")
    return {key.s: val for key, val in zip(expr.keys, expr.values)}

def _check(condition, explanation):
    if not condition:
        raise ValueError("Expression is not a valid domain: %s" % explanation)

def valid_view(arch, **kwargs):
    for pred in _validators[arch.tag]:
        check = pred(arch, **kwargs)
        if not check:
            _logger.warning("Invalid XML: %s", pred.__doc__)
            return False
    return True

def validate(*view_types):
    """ Registers a view-validation function for the specific view types
    """
    def decorator(fn):
        for arch in view_types:
            _validators[arch].append(fn)
        return fn
    return decorator

def relaxng(view_type):
    """ Return a validator for the given view type, or None. """
    if view_type not in _relaxng_cache:
        with tools.file_open(os.path.join('base', 'rng', '%s_view.rng' % view_type)) as frng:
            try:
                relaxng_doc = etree.parse(frng)
                _relaxng_cache[view_type] = etree.RelaxNG(relaxng_doc)
            except Exception:
                _logger.exception('Failed to load RelaxNG XML schema for views validation')
                _relaxng_cache[view_type] = None
    return _relaxng_cache[view_type]

@validate('calendar', 'graph', 'pivot', 'search', 'tree', 'activity')
def schema_valid(arch, **kwargs):
    """ Get RNG validator and validate RNG file."""
    validator = relaxng(arch.tag)
    if validator and not validator.validate(arch):
        result = True
        for error in validator.error_log:
            _logger.warning(tools.ustr(error))
            result = False
        return result
    return True


import duckdb
import pytest
from conftest import NumpyPandas, ArrowPandas

class TestPandasAcceptFloat16(object):
    @pytest.mark.parametrize('pandas', [NumpyPandas(), ArrowPandas()])
    def test_pandas_accept_float16(self, duckdb_cursor, pandas):
        df = pandas.DataFrame({'col': [1, 2, 3]})
        df16 = df.astype({'col': 'float16'})
        con = duckdb.connect()
        con.execute('CREATE TABLE tbl AS SELECT * FROM df16')
        con.execute('select * from tbl')
        df_result = con.fetchdf()
        df32 = df.astype({'col': 'float32'})
        assert (df32['col'] == df_result['col']).all()


from queue_array import Queue

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

class BinarySearchTree:

    def __init__(self): # Returns empty BST
        self.root = None

    def is_empty(self): # returns True if tree is empty, else False
        if self.root is None:
            return True
        return False

    def search(self, key): # returns True if key is in a node of the tree, else False

        if self.is_empty():
            return False

        if self.search_helper(key, self.root):
            return True

    def search_helper(self, key, root):
        if root is None:
            return False
        if key == root.key:
            return True
        elif key < root.key:
            return self.search_helper(key, root.left)

        elif key > root.key:
            return self.search_helper(key, root.right)

    def insert(self, key, data=None): # inserts new node w/ key and data
        # If an item with the given key is already in the BST,
        # the data in the tree will be replaced with the new data
        newNode = TreeNode(key, data)

        if (self.is_empty()):
            self.root = newNode

        else:
            self.insert_recursion_helper(self.root, newNode)

    def insert_recursion_helper(self, root, newNode):
        if newNode.key == root.key:
            root.data = newNode.data

        elif newNode.key < root.key:
            if root.left is None:
                root.left = newNode

            else:
                self.insert_recursion_helper(root.left, newNode)

        elif newNode.key > root.key:
            if root.right is None:
                root.right = newNode

            else:
                self.insert_recursion_helper(root.right, newNode)

    def find_min(self): # returns a tuple with min key and data in the BST
        # returns None if the tree is empty
        currentNode = self.root

        if self.is_empty():
            return None

        while(currentNode.left is not None):
            currentNode = currentNode.left

        return (currentNode.key, currentNode.data)

    def find_max(self): # returns a tuple with max key and data in the BST
        # returns None if the tree is empty
        currentNode = self.root

        if self.is_empty():
            return None

        while(currentNode.right is not None):
            currentNode = currentNode.right

        return (currentNode.key, currentNode.data)

    def tree_height(self): # return the height of the tree
        # returns None if tree is empty
        if self.is_empty():
            return None
        else:
            currentNode = self.root
            return self.tree_height_recursive(currentNode)

    def tree_height_recursive(self, currentNode):
        if currentNode is None:
            return -1
        left_height = self.tree_height_recursive(currentNode.left)
        right_height = self.tree_height_recursive(currentNode.right)

        return 1 + max(left_height, right_height)

    def inorder_list(self): # return Python list of BST keys representing in-order traversal of BST
        if self.is_empty():
            return []
        currentNode = self.root
        return self.inorder_list_recursive(currentNode)

    def inorder_list_recursive(self, currentNode):
        if(currentNode is None):
            return []

        if (currentNode.left is None) and (currentNode.right is None):
            return [currentNode.key]

        leftRoot = self.inorder_list_recursive(currentNode.left)
        rightRoot = self.inorder_list_recursive(currentNode.right)

        keyList = []
        keyList = leftRoot
        keyList.append(currentNode.key)
        keyList = keyList + rightRoot

        return keyList

    def preorder_list(self):  # return Python list of BST keys representing pre-order traversal of BST
        if self.is_empty():
            return []
        currentNode = self.root
        return self.preorder_list_recursive(currentNode)

    def preorder_list_recursive(self, currentNode):
        if(currentNode is None):
            return []

        if (currentNode.left is None) and (currentNode.right is None):
            return [currentNode.key]

        leftRoot = self.preorder_list_recursive(currentNode.left)
        rightRoot = self.preorder_list_recursive(currentNode.right)

        keyList = []
        keyList = leftRoot
        keyList.insert(0, currentNode.key)
        keyList = keyList + rightRoot

        return keyList

    def level_order_list(self):  # return Python list of BST keys representing level-order traversal of BST
        # You MUST use your queue_array data structure from lab 3 to implement this method
        q = Queue(25000) # Don't change this!

        if self.is_empty():
            return []

	    # Create an empty queue for level order traversal
        listOfKeys = []

	    # Enqueue Root and initialize height
        q.enqueue(self.root)

        while(not q.is_empty()):
		    # Print front of queue and remove it from queue
            node = q.dequeue()
            listOfKeys.append(node.key)

		    #Enqueue left child
            if node.left is not None:
                q.enqueue(node.left)

		    # Enqueue right child
            if node.right is not None:
                q.enqueue(node.right)

        return listOfKeys


"""
  Name     : c3_28_merge_different_names.py
  Book     : Hands-on Data Science with Anaconda)
  Publisher: Packt Publishing Ltd.
  Author   : Yuxing Yan and James Yan
  Date     : 1/15/2018
  email    : yany@canisius.edu
             paulyxy@hotmail.com
"""

import pandas as pd
import scipy as sp
x= pd.DataFrame({'YEAR': [2010,2011, 2012, 2013],
                 'IBM': [0.2, -0.3, 0.13, -0.2],
                 'WMT': [0.1, 0, 0.05, 0.23]})
y = pd.DataFrame({'date': [2011,2013,2014, 2015],
                 'C': [0.12, 0.23, 0.11, -0.1],
                 'SP500': [0.1,0.17, -0.05, 0.13]})
print(pd.merge(x,y, left_on='YEAR',right_on='date'))


import pytest

from ark import items, tools

def test_craft_without_subcomponents() -> None:
    available = {items.PASTE: 2000, items.METAL_INGOT: 1500}
    amount, plan, cost = tools.compute_crafting_plan(items.METAL_FOUNDATION, available)
    assert not plan
    assert amount == 30
    assert cost == {items.PASTE: 450, items.METAL_INGOT: 1500}

def test_craft_with_2_layers() -> None:

    available = {
        items.PASTE: 2000,
        items.METAL_INGOT: 1500,
        items.CRYSTAL: 150,
        items.SILICA_PEARL: 2250,
        items.ORGANIC_POLYMER: 500,
    }
    amount, plan, cost = tools.compute_crafting_plan(items.C4_DETONATOR, available)

    assert amount == 15
    assert plan == {items.ELECTRONICS: 750}
    assert cost == {
        items.PASTE: 225,
        items.CRYSTAL: 150,
        items.ELECTRONICS: 0,
        items.METAL_INGOT: 900,
        items.ORGANIC_POLYMER: 300,
        items.SILICA_PEARL: 2250,
    }

def test_craft_2layers_without_subcomponents() -> None:

    available = {
        items.PASTE: 2000,
        items.METAL_INGOT: 1500,
        items.CRYSTAL: 150,
        items.ELECTRONICS: 49,
        items.ORGANIC_POLYMER: 500,
    }
    amount, plan, cost = tools.compute_crafting_plan(items.C4_DETONATOR, available)
    assert not amount
    assert not plan
    assert not any(v for v in cost.values())

def test_raise_error_no_recipe_item() -> None:

    with pytest.raises(ValueError):
        tools.compute_crafting_plan(items.METAL_INGOT, {items.PASTE: 200})

def test_deep_layer_crafting() -> None:
    available = {
        items.METAL_INGOT: 2550,
        items.PASTE: 550,
        items.CRYSTAL: 200,
        items.ELECTRONICS: 70,
        items.SILICA_PEARL: 8000,
        items.ORGANIC_POLYMER: 10000,
        items.AUTO_TURRET: 1,
    }
    amount, plan, cost = tools.compute_crafting_plan(items.HEAVY_AUTO_TURRET, available)

    assert amount == 3
    assert plan == {items.ELECTRONICS: 670, items.AUTO_TURRET: 2}
    assert cost == {
        items.PASTE: 550,
        items.ELECTRONICS: 70,
        items.METAL_INGOT: 2150,
        items.ORGANIC_POLYMER: 190,
        items.SILICA_PEARL: 2010,
        items.AUTO_TURRET: 1,
    }

    available[items.AUTO_TURRET] = 0
    available[items.PASTE] = 600

    amount, plan, cost = tools.compute_crafting_plan(items.HEAVY_AUTO_TURRET, available)
    assert amount == 3
    assert plan == {items.ELECTRONICS: 740, items.AUTO_TURRET: 3}
    assert cost == {
        items.PASTE: 600,
        items.ELECTRONICS: 70,
        items.METAL_INGOT: 2360,
        items.ORGANIC_POLYMER: 210,
        items.SILICA_PEARL: 2220,
        items.AUTO_TURRET: 0,
    }

def test_amount_flattened() -> None:
    available = {
        items.SILICA_PEARL: 5211,
        items.PASTE: 2600,
        items.METAL_INGOT: 8757,
        items.ELECTRONICS: 1100,
        items.CRYSTAL: 10000,
        items.HIDE: 20000,
        items.ORGANIC_POLYMER: 10000,
    }

    amount, plan, cost = tools.compute_crafting_plan(items.HEAVY_AUTO_TURRET, available)
    assert amount == 10
    assert plan == {items.AUTO_TURRET: 10, items.ELECTRONICS: 1620}
    assert cost == {
        items.PASTE: 2000,
        items.ELECTRONICS: 1080,
        items.METAL_INGOT: 7020,
        items.ORGANIC_POLYMER: 700,
        items.SILICA_PEARL: 4860,
        items.AUTO_TURRET: 0,
    }

def test_tek_turret() -> None:
    available = {
        items.SILICA_PEARL: 5211,
        items.PASTE: 2600,
        items.METAL_INGOT: 8757,
        items.ELECTRONICS: 1100,
        items.CRYSTAL: 10000,
        items.HIDE: 20000,
        items.ORGANIC_POLYMER: 10000,
        items.ELEMENT: 18
    }
    amount, plan, cost = tools.compute_crafting_plan(items.TEK_TURRET, available)
    assert amount == 6
    assert not plan
    assert cost == {
        items.PASTE: 300,
        items.ELECTRONICS: 600,
        items.METAL_INGOT: 600,
        items.ORGANIC_POLYMER: 300,
        items.ELEMENT: 18
    }


import os
import shutil
from fastapi import HTTPException, UploadFile, status
from fastapi.encoders import jsonable_encoder
from app.api.v1.models.user import User

URL_USER_IMAGE_FOLDER = "app/api/v1/images_users"

async def upload_user_photo(username: str, file: UploadFile):
    try:
        file.filename = username
        image_url = f"{URL_USER_IMAGE_FOLDER}/{file.filename}.JPG"
        async with open(image_url, "wb") as buffer:
            await shutil.copyfileobj(file.file, buffer)
            print(file.filename)
    except:
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="Error Occurred when upload file ",
        )
    return image_url

UPLOAD_FOLDER = "app/api/v1/images"

def upload_file(user_id: int, file: UploadFile, db):
    if not user_id:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND, detail="User Id not found"
        )

    file.filename = str(user_id)
    file_location = f"{UPLOAD_FOLDER}/{file.filename}.jpg"
    with open(file_location, "wb") as buffer:
        shutil.copyfileobj(file.file, buffer)
        print("---------")
    image_data = {"user_id": user_id, "path": file_location}
    image = UserImage(**image_data)
    db.add(image)
    db.commit()
    db.refresh(image)
    return jsonable_encoder(image)

def delete_file(user_id: int, db):
    file_location = f"{UPLOAD_FOLDER}/{user_id}.jpg"
    image = db.query(UserImage).filter_by(user_id=user_id).first()
    if os.path.exists(file_location):
        os.remove(file_location)
        db.delete(image)
        db.commit()
        return jsonable_encoder("Photo is deleted")
    else:
        return jsonable_encoder("Photo not found!")


import os
import upy
UPY_PATH = upy.__path__[0]

HOST = {"blender24":"blender"+os.sep+"v249",
        "blender25":"blender"+os.sep+"v257",
        "maya":"autodeskmaya",
        "c4d":"cinema4d",
        "dejavu":"dejavuTk",
        "qt":"pythonUI"+os.sep,
        "tk":"pythonUI"+os.sep,
}

class Tools:
    def __init__(self,**kw):
        self.functionCode=""
        self.classType="helper" #or adaptor
        self.functionName=""
        self.anchor=""

    def deploy(self,position=None):
        #will write everywhere?
        if position == None :
            #append at the end
            position = self.anchor
        f = open(UPY_PATH+os.sep+HOST[host]+os.sep+host+self.classType)

    def write(self,host,position=None):
        #will write everywhere?
        if position == None :
            #append at the end
            position = self.anchor
        f = open(UPY_PATH+os.sep+HOST[host]+os.sep+host+self.classType)
        f.replace(self.anchor,self.functionCode+self.anchor)#indentation?


#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import faiss

from faiss import cast_integer_to_float_ptr as cast_float
from faiss import cast_integer_to_int_ptr as cast_int
from faiss import cast_integer_to_long_ptr as cast_long

from .util import *

class FAISSIndex(object):

  def __init__(self, cell_size=20, nr_cells=1024, K=4, num_lists=32, probes=32, res=None, train=None, gpu_id=-1):
    super(FAISSIndex, self).__init__()
    self.cell_size = cell_size
    self.nr_cells = nr_cells
    self.probes = probes
    self.K = K
    self.num_lists = num_lists
    self.gpu_id = gpu_id

    # BEWARE: if this variable gets deallocated, FAISS crashes
    self.res = res if res else faiss.StandardGpuResources()
    self.res.setTempMemoryFraction(0.01)
    if self.gpu_id != -1:
      self.res.initializeForDevice(self.gpu_id)

    nr_samples = self.nr_cells * 100 * self.cell_size
    train = train if train is not None else T.randn(self.nr_cells * 100, self.cell_size)

    self.index = faiss.GpuIndexIVFFlat(self.res, self.cell_size, self.num_lists, faiss.METRIC_L2)
    self.index.setNumProbes(self.probes)
    self.train(train)

  def cuda(self, gpu_id):
    self.gpu_id = gpu_id

  def train(self, train):
    train = ensure_gpu(train, -1)
    T.cuda.synchronize()
    self.index.train_c(self.nr_cells, cast_float(ptr(train)))
    T.cuda.synchronize()

  def reset(self):
    T.cuda.synchronize()
    self.index.reset()
    T.cuda.synchronize()

  def add(self, other, positions=None, last=None):
    other = ensure_gpu(other, self.gpu_id)

    T.cuda.synchronize()
    if positions is not None:
      positions = ensure_gpu(positions, self.gpu_id)
      assert positions.size(0) == other.size(0), "Mismatch in number of positions and vectors"
      self.index.add_with_ids_c(other.size(0), cast_float(ptr(other)), cast_long(ptr(positions + 1)))
    else:
      other = other[:last, :] if last is not None else other
      self.index.add_c(other.size(0), cast_float(ptr(other)))
    T.cuda.synchronize()

  def search(self, query, k=None):
    query = ensure_gpu(query, self.gpu_id)

    k = k if k else self.K
    (b,n) = query.size()

    distances = T.FloatTensor(b, k)
    labels = T.LongTensor(b, k)

    if self.gpu_id != -1: distances = distances.cuda(self.gpu_id)
    if self.gpu_id != -1: labels = labels.cuda(self.gpu_id)

    T.cuda.synchronize()
    self.index.search_c(
      b,
      cast_float(ptr(query)),
      k,
      cast_float(ptr(distances)),
      cast_long(ptr(labels))
    )
    T.cuda.synchronize()
    return (distances, (labels-1))


# Using linked list-ish disjoint set data structures

#rectangles = ("0 292 399 307",)
rectangles = ("0 192 399 207", "0 392 399 407", "120 0 135 599", "260 0 275 599")
height = 400
width = 600
#height = 3
#width = 4
#rectangles = ("0 1 2 3",)

def createSet(gridPoint):
    gridPoint.cSet = []
    gridPoint.cSet.append(gridPoint)
    return gridPoint.cSet

def findSet(gridPoint):
    return gridPoint.cSet

def union(gridPoint1, gridPoint2):
    if gridPoint1.cSet == gridPoint2.cSet:
        return gridPoint1.cSet

    if len(gridPoint1.cSet) > len(gridPoint2.cSet):
        larger = gridPoint1
        smaller = gridPoint2
    else:
        larger = gridPoint2
        smaller = gridPoint1

        larger.cSet.extend(smaller.cSet)
        smaller.cSet = larger.cSet
        return larger.cSet

class GridPoint:
    def __init__(self, x, y):
        self.x = x
        self.y = y
        self.cSet = None

grid = [[True for i in range(width)] for j in range(height)]
for rectangle in rectangles:
    tlx, tly, brx, bry = map(lambda x : int(x), rectangle.split())
    for x in range(tlx, brx + 1):
        for y in range(tly, bry + 1):
            # Blocked
            grid[x][y] = False

gridPoints = [[None for i in range(width)] for j in range(height)]
for x in range(0, height):
    for y in range(0, width):
        gridPoints[x][y] = GridPoint(x, y)
        createSet(gridPoints[x][y])

for x in range(0, height):
    for y in range(0, width):
        if grid[x][y]:
            # Open space, merge sets to the left and above
            if x - 1 >= 0 and grid[x - 1][y]:
                union(gridPoints[x][y], gridPoints[x - 1][y])
            if y - 1 >= 0 and grid[x][y - 1]:
                union(gridPoints[x][y], gridPoints[x][y - 1])

areas = []
for x in range(0, height):
    for y in range(0, width):
        if grid[x][y]:
            cSet = findSet(gridPoints[x][y])
            area = 0
            for gridPoint in cSet:
                grid[gridPoint.x][gridPoint.y] = False
                area += 1
            areas.append(area)

print("Sorted areas: ")
areas.sort()
print(areas)


from collections import deque
from copy import deepcopy
import time

# S = [1, 2, 3, 0, 4, 5, 6, 7, 8]
# G = [1, 2, 3, 4, 0, 5, 6, 7, 8]

# 0探索
def search_zero(l):
    for i in l:
        if i == 0:
            return l.index(i)

def bfs(s, g):
    # 探索済みかどうか状態をログでとる
    log = {}
    S_dash = deepcopy(s)
    # 上下左右に行く時の配列移動
    up_down_left_right = [-3, 3, -1, 1]
    que = deque()
    g_tuple = tuple(g)
    log[tuple(S_dash)] = 1
    que.append(S_dash)

    while not (len(que) == 0):
        ss = que.popleft()
        ss_tuple = tuple(ss)
        zero = search_zero(ss)
        for i in range(4):
            # 左端だったら左にはいけない
            if zero % 3 == 0 and i == 2:
                continue
            # 右端だったら右にはいけない
            if zero % 3 == 2 and i == 3:
                continue
            point = zero + up_down_left_right[i]
            # 上限・下限は超えない
            if point < 0 or point > 8:
                continue
            # シャローコピーをせずに0からスワップ
            S_dash_dash = deepcopy(ss)
            swap = S_dash_dash[point]
            S_dash_dash[point] = 0
            S_dash_dash[zero] = swap
            S_dd_tuple = tuple(S_dash_dash)
            # 過去に探索したことがあるかログを探索する。なければログとキューに追加する。
            if log.get(S_dd_tuple) is None:
                log[S_dd_tuple] = log[ss_tuple] + 1
                que.append(S_dash_dash)
            # ゴールに訪問していれば終了
            if log.get(g_tuple) is not None:
                return log[g_tuple]

    return -1

if __name__ == "__main__":
    start = time.time()
    S = list(map(int, input().split()))
    G = list(map(int, input().split()))
    print(bfs(S, G))
    elapsed_time = time.time() - start
    print("elapsed_time:{0}".format(elapsed_time) + "[sec]")


global pd, np, os, csv, sys, plt, json
import numpy as np
import os, csv, sys, json
from pin_analysis_tools import *
from PinAnalysis import *
sys.dont_write_bytecode = True
import pandas as pd
import matplotlib.pyplot as plt
import xlsxwriter
box_path = get_box_pathway()
# location for saving data files
save_directory = box_path + "Engineering\Pin_Analysis\AnalysisData"
# adds tech dev tool box to path
sys.path.insert(0, box_path + "Engineering\Tech_Dev_Software\PythonDev\TechDevPythonAnalyticsTools")
from tech_dev_python_analytics_tools import *

def set_boundaries(**kwargs):
    """
    Go through each instument and create a lower and upper cutoff based on cartridge to cartridge_to_cartridge_pin_variation
    """

    if 'num_stds' not in kwargs:
        kwargs['num_stds'] = [5,10]

    # Read in data set averages
    os.chdir(box_path + "Engineering\Pin_Analysis\AnalysisData")
    df = pd.read_csv('good pin data by instrument.csv')
    odf_keys = list(df)
    # take each key in order and get average and pin variation
    instrument_list = []
    for key in odf_keys:
        if 'average' in key:
            split_key = key.split(' ')
            instrument_list.append(split_key[-1])
            #df['Upper Bound ' + split_key[-1]] = df[key] + kwargs['num_stds'][0]*df['cartridge_to_cartridge_pin_variation ' + split_key[-1]]
            df['Lower Bound ' + split_key[-1]] = df[key] - kwargs['num_stds'][1]*df['cartridge_to_cartridge_pin_variation ' + split_key[-1]]
    return df, instrument_list

def evaluate_csvs(df, md_by_inst, add_path, histogram_name):

    os.chdir(box_path + add_path)
    number_of_pins = 108
    number_of_trials = 8

    z_score = pd.DataFrame()

    for inst in md_by_inst.keys():
        # go through each experiment in instrument set
        experiments = md_by_inst[inst]
        all_exp = []
        for i_file in experiments:
            all_exp.append(i_file)
            impedance_matrix = np.zeros((number_of_pins,number_of_trials))
            myread = read_whole_csv_file(i_file, True, unnecessary_lines=[0,1])
            for i_row, row in enumerate(myread):
                float_array = [float(i) for i in row[4:12]]
                impedance_matrix[i_row, :] = float_array
            df['Average Trial ' + i_file] = np.mean(impedance_matrix, axis=1)
            df['Lower Bounds Failure ' + i_file] = df['Average Trial ' + i_file]<df['Lower Bound ' + inst]
            #df['Upper Bounds Failure '+ i_file] = df['Average Trial ' + i_file]>df['Upper Bound ' + inst]

            z_score['Z score ' + i_file] = (df['Average Trial ' + i_file]-df['pin average impedances ' + inst])/df['cartridge_to_cartridge_pin_variation ' + inst]
            df['Z score ' + i_file] = z_score['Z score ' + i_file]
            plt.hist(z_score['Z score ' + i_file], bins=np.arange(-70,10, 0.5))
            boolean_array = (df['Average Trial ' + i_file]<df['Lower Bound ' + inst]) #| (df['Average Trial ' + i_file]>df['Upper Bound ' + inst])
            failed_pins = []
            for index, i in enumerate(boolean_array):
                if i:
                    failed_pins.append(index+9)
            df['Failed Pins ' + i_file] = pd.Series(failed_pins)

        plt.xlabel('z score')
        plt.ylabel('Number of instances')
        plt.title('Z Score of ' + histogram_name + 'Cartridges on Instrument ' + inst)
        plt.legend(all_exp)
        os.chdir(save_directory)
        plt.savefig(histogram_name + ' ' + inst)
        os.chdir(box_path+add_path)
        plt.clf()
    return df, z_score

def plot_pin_distribution(pin_number, df, histogram_name):
    column_frames = list(df)
    temp = []
    for column_frame in list(df):
        if "Average Trial" in column_frame:
            temp.append(df.loc[pin_number-9, column_frame])
    plt.hist(temp)
    plt.xlabel('Impedance')
    plt.ylabel('Number of instances')
    plt.title('Impedance Distribution of Pin ' + str(pin_number))
    plt.savefig(histogram_name + " " + str(pin_number))
    plt.clf()

def main():
    df, instrument_list = set_boundaries(num_stds=[5,10])

    # grabs the metadata of the bad trials
    good_md, bad_md = get_json_file('Good_and_Bad_Json_Data.txt')
    bad_md_list = sort_by_instrument(bad_md)
    df.to_csv('Bounds&Averages.csv')
    df, z_score = evaluate_csvs(df, bad_md_list, "Engineering\Pin_Analysis\BadCSVs", "bad")
    good_md_list = sort_by_instrument(good_md)
    df, z_score = evaluate_csvs(df, good_md_list, "Engineering\Pin_Analysis\GoodCSVs", "good")
    os.chdir(save_directory)
    #plot_pin_distribution(35,df, "Distribution of Pin")
    df.to_csv('All Relevant Data.csv')
    z_score.to_csv('Z Scores.csv')

main()


import matplotlib
matplotlib.use('TkAgg')

import time
import pandas as pd
from src.portfolio import PortfolioTrader
import yaml

# I was getting a weird error with numpy and plotting, this next line seemed to fix.
pd.plotting.register_matplotlib_converters()

def main():
    with open('./config/config.yaml') as f:
        TRADECONFIG = yaml.safe_load(f)
    start_time = time.time()

    pf = PortfolioTrader(
        symbols=TRADECONFIG['TICKER_LIST'],
        start_date=TRADECONFIG['START_DATE'],
        end_date=TRADECONFIG['END_DATE'],
        min_short=TRADECONFIG['MIN_SHORT'],
        max_short=TRADECONFIG['MAX_SHORT'],
        min_window_diff=TRADECONFIG['MIN_LONG_DIFFERENCE'],
        max_long=TRADECONFIG['MAX_LONG'],
        parallelize=TRADECONFIG.get('USE_MULTIPROCESSING', False),
    )

    # NOTE: mp_trade() doesn't work on windows because the spawn method is 'spawn' not 'fork'
    pf.grid_search()
    pf.print_results(TRADECONFIG['DISPLAY_INDIVIDUAL_PLOTS'])

    end_time = time.time()
    run_time = end_time - start_time
    print('Portfolio took {:>10.2} minutes to run.'.format(run_time/60))
    pf.managed_returns.to_csv('./examples/example_results.csv', index=False)

if __name__ == "__main__":
    main()


import requests

def testOpenCourse():
    api="http://127.0.0.1:8000/api/teacher/opencourse"
    postdata={
        "account_id":"000123",
        "id":"00010000",
        "capacity":50

    }
    response=requests.post(url=api,data=postdata)
    print(response.text)

def testTeacherInfo():
    api = "http://127.0.0.1:8000/api/teacher/info"
    postdata = {
        "account_id": "000456"
    }
    response = requests.get(url=api, params=postdata)
    print(response.text)

if __name__=="__main__":
    testTeacherInfo()


from pygame import *
import math_tools
import math as pmath
class Bullet2:

    class BulletType:
        HITSCAN = 0
        PROJECTILE = 1

    def __init__(self, x, y, angle, damage, faction, range, speed, colour, hitColour, length, gravity, slowdown,
                 thickness, isExplosive=0, explosiveRadius=0, explosiveFalloff=0,
                 fuse=0,isCrit = 0):  # Gravity reduces vY, slowdown decreases vX
        self.x, self.y = x, y
        self.vX, self.vY = speed * math_tools.cosd(angle), speed * math_tools.sind(angle)
        self.damage = damage
        self.faction = faction
        self.range = range
        self.speed = speed
        self.colour = colour
        self.hitColour = hitColour
        self.length = length
        self.gravity = gravity
        self.slowdown = slowdown
        self.thickness = thickness
        self.isExplosive = isExplosive
        self.explosiveRadius = explosiveRadius
        self.explosiveFalloff = explosiveFalloff
        self.fuse = fuse
        self.isCrit = isCrit
    def move(self):
        self.x += self.vX
        self.y += self.vY
        if self.vX > 0:
            self.vX -= self.slowdown
        elif self.vX < 0:
            self.vX += self.slowdown
        self.vY += self.gravity
        self.range -= 1

    def draw(self, surface, player):
        surface.set_at((int(self.x), int(self.y)), self.colour)
        angle = pmath.degrees(pmath.atan2(self.vY, self.vX))
        draw.line(surface, self.colour, (self.x + 640 - player.X, self.y + 360 - player.Y), (
            int((self.length * math_tools.cosd(angle)) + self.x + (640 - player.X)),
            int((self.length * math_tools.sind(angle)) + self.y + (360 - player.Y))), self.thickness)


import scipy.stats as ss
from decimal import Decimal
import math as m
import numpy as np
from datetime import date,timedelta
import requests
import json
import pandas as pd
import time
import datetime as dt
from sklearn.preprocessing import PolynomialFeatures
from sklearn.linear_model import LinearRegression
from sqlalchemy import select, create_engine, MetaData, Table, Column, Integer, String
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
from matplotlib import colors
from matplotlib import cm

def call_bsm (S0,K,r,T,Otype,sig):
        d1 = (np.log(S0 / K) + (r + 0.5 * sig ** 2) * T) / (sig * np.sqrt(T))
        d2 = (np.log(S0 / K) + (r - 0.5 * sig ** 2) * T) / (sig * np.sqrt(T))

        if (Otype == "Call"):
            price = (S0 * ss.norm.cdf(d1, 0.0, 1.0) - K * np.exp(-r * T) * ss.norm.cdf(d2, 0.0, 1.0))
            return (price)

        elif (Otype == "Put"):
            price = (K * np.exp(-r * T) * ss.norm.cdf(-d2, 0.0, 1.0) - S0 * ss.norm.cdf(-d1, 0.0, 1.0))
            return (price)

def vega (S0,K,r,T,sig):

    d1 = float(m.log(S0/K))/(sig*float(m.sqrt(T))) + float((r+ (sig*sig)/2)*T/(sig*float(m.sqrt(T))))
    vega = S0*float(ss.norm.pdf(np.float(d1)))*float(m.sqrt(T))
    return(vega)

def imp_vol(S0, K, T, r, market,flag):

    e = .00000001; x0 = float(1);
    def newtons_method(S0, K, T, r, market,flag,x0, e):
        delta = call_bsm (S0,K,r,T,flag,x0) - market
        max_iter = 1

        while delta > e and max_iter <= 100:
            vega_data = vega (S0,K,r,T,x0)

            if vega_data <= .000000001:
                max_iter = max_iter+1
                return(0)
            else:
                x0 = float(x0 - (call_bsm (S0,K,r,T,flag,x0) - market)/vega_data)
                delta = abs(call_bsm (S0,K,r,T,flag,x0) - market)
                max_iter = max_iter+1

        return(float(x0))

    sig = newtons_method(S0, K, T, r, market,flag,x0 , e)
    return(sig*100)

def get_dates(key,ticker):
    global dates
    response = requests.get('https://sandbox.tradier.com/v1/markets/options/expirations',
    params={'symbol': ticker},
    headers={'Authorization': 'Bearer ' + key, 'Accept': 'application/json'})

    j = json.loads(response.text)

    dates = []
    for date in j['expirations']['date']:
        dates.append(date)
    return dates

def data(key,date,ticker,quote):
    def Get_DTE(expiration_data):

        e_year = int(expiration_data[0:4])
        e_month = int(expiration_data[5:7])
        e_day = int(expiration_data[8:10])
        now = dt.datetime.now()
        year = int(now.year)
        month = int(now.month)
        day = int(now.day)

        now = dt.date(year,month,day)
        exp = dt.date(e_year,e_month,e_day)
        days_data = np.busday_count(now,exp)
        return days_data

    response = requests.get('https://sandbox.tradier.com/v1/markets/options/chains',
    params={'symbol': ticker, 'expiration': date},
    headers={'Authorization': 'Bearer ' + key, 'Accept': 'application/json'})

    j = json.loads(response.text)

    symbols = []
    last = []
    ask = []
    bid = []
    change = []
    expiration = []
    volume = []
    open_interest =[]
    strike = []
    DTE = []
    delta = []
    flag = []
    weighted_volume = []
    low = []
    high = []
    time = []
    Underlying = []
    iv = []

    for option in j['options']['option']:
        Underlying_data = quote
        symbol = option['symbol']
        last_data = option['last']
        ask_data = option['ask']
        bid_data = option['bid']
        change_data =option['change']
        expiration_data = option['expiration_date']
        volume_data = option['volume']
        open_interest_data = option['open_interest']
        strike_data = option['strike']
        low_data = option['low']
        high_data = option['high']

        dte_data = Get_DTE(expiration_data)
        dte_float = float(dte_data)
        time_data = dt.datetime.now()

        if last_data is None:
            weighted_volume_data = 0
        elif last_data >= 0:
            if high_data is None or low_data is None:
                weighted_volume_data = float(last_data)*float(volume_data)*100
            else:
                scalar = float((high_data+low_data)/2)
                weighted_volume_data = float(scalar)*float(volume_data)*100

        if len(ticker) == 4:
            j = 10
        elif len(ticker) == 3:
            j = 9
        elif len(ticker) == 2:
            j = 8
        else:
            j = 7

        if symbol[j] == 'C':
            flag_data = "Call"
            flag.append(flag_data)
        else:
            flag_data = 'Put'
            flag.append(flag_data)

        T = dte_float + 1
        S0 = float(Underlying_data)
        K = float(strike_data)
        r = float(0.0225)
        market = float(ask_data)
        call_put = flag_data

        if market is not None:
            iv_data = imp_vol(S0, K, T/365, r, market,flag_data)

        else:
            iv_data = 0

        symbols.append(symbol)
        last.append(last_data)
        ask.append(ask_data)
        bid.append(bid_data)
        change.append(change_data)
        expiration.append(expiration_data)
        volume.append(volume_data)
        open_interest.append(open_interest_data)
        DTE.append(dte_data)
        strike.append(strike_data)
        weighted_volume.append(weighted_volume_data)
        low.append(low_data)
        high.append(high_data)
        time.append(time_data)
        Underlying.append(Underlying_data)
        iv.append(iv_data)

    data = pd.DataFrame()
    data['contract'] = symbols
    data['last']= last
    data['ask'] = ask
    data['bid'] = bid
    data['change'] = change
    data['expiration'] = expiration
    data['volume'] = volume
    data['open_interest'] = open_interest
    data['DTE'] = DTE
    data['strike'] = strike
    data['flag'] = flag
    data['weighted_volume'] = weighted_volume
    data['IV'] = iv
    data['time'] = time
    data['Ticker'] = Underlying

    call_df = pd.DataFrame(columns = data.columns)

    put_df = pd.DataFrame(columns = data.columns)
    for index, row in data.iterrows():

        if row['flag'] == 'Call':
            call_df.loc[len(call_df)] = row
        else:
            put_df.loc[len(put_df)] = row

    frame = [call_df, put_df]
    global df
    df = pd.concat(frame)

def get_quote(key,ticker):

    response = requests.get('https://sandbox.tradier.com/v1/markets/quotes',
    params={'symbols': ticker},
    headers={'Authorization': 'Bearer ' + key, 'Accept': 'application/json'})
    j = json.loads(response.text)

    global quote
    quote = j["quotes"]["quote"]["last"]
    return quote

def Single_Pull(ticker, csv, sql):
    print('Pulling data for' + str(ticker))
    engine = create_engine('sqlite:///C:\\OptionDB\\MAIN.db', echo = True)
    conn = engine.connect()

    meta = MetaData(engine,reflect=True)
    dict_keys = meta.tables.keys()
    list_tables = list(dict_keys)

    table = meta.tables['User_Account']
    my_select = select([table])

    res = conn.execute(my_select)
    for row in res:
        key = str(row)
        key = key[2:]
        key = key[:-3]

    get_quote(key, ticker)
    get_dates(key, ticker)
    main_df = pd.DataFrame()
    for date in dates:
        print(date)
        data(key,date,ticker,quote)
        frames = [main_df, df]
        main_df = pd.concat(frames)

    if sql == 'yes':
        if ticker in list_tables:
            main_df.to_sql(ticker,engine, if_exists = 'append')

        else:
            main_df.to_sql(ticker,engine)
    else:
        print("Skip SQL update")

    if csv == 'yes':
        main_df.to_csv("Data.csv")
    else:
        print("Skip CSV export")

def Custom_Pull(tickers, expirations, strikes, csv, sql):

    engine = create_engine('sqlite:///C:\\OptionDB\\MAIN.db', echo = True)
    conn = engine.connect()

    meta = MetaData(engine,reflect=True)
    table = meta.tables['User_Account']
    my_select = select([table])

    res = conn.execute(my_select)
    for row in res:
        key = str(row)
        key = key[2:]
        key = key[:-3]
        print(key)

    tickers = tickers.replace(' ','').split(',')
    if expirations != "0":
        expirations = expirations.replace(' ','').split(',')
    else:
        expirations = get_dates(key, tickers[0])
    if strikes != "0":
        strikes = strikes.replace(' ','').split(',')

    for ticker in tickers:
        csv_link = str(ticker) + ".csv"
        get_quote(key, ticker)
        main_df = pd.DataFrame()

        for date in expirations:
            print(date)
            data(key,date,ticker,quote)
            frames = [main_df, df]
            main_df = pd.concat(frames)

        if strikes != "0":
            for index,row in main_df.iterrows():
                strike = row['strike']

                if strike not in strikes:

                    df.drop(index, inplace = True)

        print(main_df)

        if sql == 'yes':
            if ticker in list_tables:
                main_df.to_sql(ticker,engine, if_exists = 'append')

            else:
                main_df.to_sql(ticker,engine)
        else:
            print("Skip SQL update")

        if csv == 'yes':
            main_df.to_csv(csv_link)
        else:
            print("Skip CSV export")

def ExportDayPull(ticker, day):

    engine = create_engine('sqlite:///C:\\OptionDB\\MAIN.db')
    conn = engine.connect()

    meta = MetaData(engine,reflect=True)
    dict_keys = meta.tables.keys()
    list_tables = list(dict_keys)
    print(list_tables)

    df = pd.read_sql_table(str(ticker), engine)

    for index, row, in df.iterrows():
        string = str(row['time'])
        date = string[:10]
        if date != day:
            df.drop(index, inplace=True)

    string = str(ticker) + ".csv"
    df.to_csv(string)
    print("CSV exported to root directory")

def ExportCustomPull(ticker, days, strikes, expirations):

    if days != "0":
        days = days.replace(' ','').split(',')
        day_string = str(days)
        day_string = day_string[1:-1]
        day_string = '(' + day_string + ')'

    if strikes != "0":
        strikes = strikes.replace(' ','').split(',')
        strike_string = str(strikes)
        strike_string = strike_string[1:-1]
        strike_string = '(' + strike_string + ')'

    if expirations != "0":
        expirations = expirations.replace(' ','').split(',')
        expiration_string = str(expirations)
        expiration_string = expiration_string[1:-1]
        expiration_string = '(' + expiration_string + ')'

    engine = create_engine('sqlite:///C:\\OptionDB\\MAIN.db', echo = True)
    conn = engine.connect()

    if days == '0' and strikes == '0' and expirations == '0':

            statement = '''SELECT * FROM {}'''.format(ticker)

    if days == '0' and strikes == '0' and expirations != '0':

            statement = '''SELECT * FROM {} WHERE expiration IN {} '''.format(ticker, expiration_string)

    if days == '0' and strikes != '0' and expirations == '0':

            statement = '''SELECT * FROM {} WHERE strike IN {} '''.format(ticker, strike_string)

    if days == '0' and strikes != '0' and expirations != '0':

            statement = '''SELECT * FROM {} WHERE strike IN {} and
                        expiration IN {} '''.format(ticker, strike_string, expiration_string)

    df = pd.read_sql(statement, engine)

    string = str(ticker) + ".csv"
    df.to_csv(string)
    print("CSV exported to root directory")

def mesh(df,target,dates):

    global main_call_df
    global main_put_df
    main_call_df = pd.DataFrame()
    main_put_df = pd.DataFrame()

    for date in dates:
        call_date_df = pd.DataFrame()
        put_date_df = pd.DataFrame()

        calls_strikes = []
        puts_strikes = []

        calls_data = []
        puts_data = []

        for index, row in df.iterrows():

            if row['flag'] == 'Call':
                if row['expiration'] == date:

                    strike = row['strike']
                    data = row[target]

                    calls_strikes.append(strike)
                    calls_data.append(data)

            elif row['flag'] == 'Put':
                if row['expiration'] == date:
                    strike = row['strike']
                    data = row[target]

                    puts_strikes.append(strike)
                    puts_data.append(data)

        call_date_df[date] = calls_strikes
        call_date_df[date+'Data'] = calls_data

        put_date_df[date] = puts_strikes
        put_date_df[date+'Data'] = puts_data

        main_call_df = pd.concat([main_call_df.reset_index(drop=True)
                                            , call_date_df.reset_index(drop=True)], axis=1)
        main_put_df = pd.concat([main_put_df.reset_index(drop=True)
                                            , put_date_df.reset_index(drop=True)], axis=1)

def poly(inputs,outputs,df, target, min_strike, max_strike):
    lin = LinearRegression()
    y_df = pd.DataFrame()

    global lower_bound
    global upper_bound
    date = dates[0]
    lower_bound = min_strike
    upper_bound = max_strike

    new_strikes = np.arange(lower_bound,upper_bound,1)
    new_strikes = new_strikes[np.logical_not(np.isnan(new_strikes))]
    strikes = new_strikes.reshape(-1,1)

    n_rows = int(len(inputs))
    gap_df = pd.DataFrame(np.zeros((n_rows,1)))
    gap_df.index = inputs
    gap_df['Data'] = outputs

    del gap_df[0]
    data_list = []

    for strike in new_strikes:

        if strike in gap_df.index and target is not "IV":
            y = float(gap_df.loc[strike].sum())
            data_list.append(y)
        else:
            if target == 'IV':
                X = inputs[np.logical_not(np.isnan(inputs))]
                X = X.reshape(-1,1)
                Y = outputs[np.logical_not(np.isnan(outputs))]
                Y = Y.reshape(-1,1)

                poly = PolynomialFeatures(degree = 4)
                X_poly = poly.fit_transform(X)
                poly.fit(X_poly, Y)

                lin2 = LinearRegression()
                lin2.fit(X_poly, Y)
                x = strike
                strike = x.reshape(-1,1)
                y = lin2.predict(poly.fit_transform(strike))
                y_float = y.astype(float)
                data_list.append(y_float)
            else:
                y_float = 0
                data_list.append(y_float)

    [float(i) for i in data_list]
    appended_data.append(data_list)

def plot3d(Otype, target, min_strike, max_strike, dates, csv):

    date_list = []
    for date in dates:

        if Otype == 'Call':

            print('Solving for ' + date)
            data = main_call_df[date+'Data'].values
            df = main_call_df
            poly(main_call_df[date].values,data,df, target, min_strike, max_strike)
        else:

            data = main_put_df[date+'Data'].values
            print('Solving for ' + date)
            df = main_put_df
            poly(main_put_df[date].values,data,df, target, min_strike, max_strike)

        date_list.append(date)
    dte_list = []

    for date in dates:
        e_year = int(date[0:4])
        e_month = int(date[5:7])
        e_day = int(date[8:10])

        now = dt.datetime.now()
        year = int(now.year)
        month = int(now.month)
        day = int(now.day)

        now = dt.date(year,month,day)
        exp = dt.date(e_year,e_month,e_day)
        days_data = int(np.busday_count(now,exp))
        dte_list.append(days_data)

    new_strikes = np.arange(lower_bound,upper_bound,1)
    new_strikes = new_strikes[np.logical_not(np.isnan(new_strikes))]
    df = pd.DataFrame(appended_data,columns=new_strikes)
    df = df.T
    df = df.astype(float)

    if target == 'IV':
            for column in df:
                lin = LinearRegression()
                y_df = pd.DataFrame()

                X = df.index.values
                X = X.reshape(-1,1)

                Y = df[column].values
                Y = Y.reshape(-1,1)

                pol = PolynomialFeatures(degree = 3)
                X_pol = pol.fit_transform(X)
                pol.fit(X_pol, Y)

                lin2 = LinearRegression()
                lin2.fit(X_pol, Y)

                y = lin2.predict(pol.fit_transform(X))

                df[column] = y

    X,Y = np.meshgrid(df.columns.astype(float), df.index)

    df.columns = dates
    if csv == 'yes':
            df.to_csv('Mesh.csv')

    Z = df.values
    title = str(target + ' ' + str(Otype) + " " + str(target))

    fig = plt.figure()
    ax = fig.add_subplot(111, projection='3d')
    surf = ax.plot_surface(X, Y, Z,cmap=cm.coolwarm,label = title, antialiased=True)

    ax.set_zlabel(target)
    ax.set_ylabel('Strike')
    ax.set_xlabel('Time')
    fig.set_title = (target + ' ' + str(Otype) + " " + str(target))

def Create_Mesh(ticker, day, target, csv, flag, min_strike, max_strike):
    global appended_data
    appended_data = []
    engine = create_engine('sqlite:///C:\\OptionDB\\MAIN.db', echo = True)
    conn = engine.connect()

    print('Gathering Data from sqlite:///C:\\OptionDB\\MAIN.db...')

    year = day[0:4]
    month = day[5:7]
    today = day[8:10]
    statement = '''SELECT * FROM {} WHERE strftime('%d', time) = '{}'
                AND strftime('%m', time) = '{}'
                AND strftime('%Y', time) = '{}' '''.format(ticker, today, month, year)
    df = pd.read_sql(statement, engine)

    meta = MetaData(engine,reflect=True)
    dict_keys = meta.tables.keys()
    list_tables = list(dict_keys)

    table = meta.tables['User_Account']
    my_select = select([table])

    res = conn.execute(my_select)
    for row in res:
        key = str(row)
        key = key[2:]
        key = key[:-3]
    get_dates(key, ticker)

    mesh(df, target, dates)
    plot3d(str(flag), target, int(min_strike), int(max_strike), dates, csv)
    plt.show()


import ipaddress
from pathlib import Path
import pickle

from backend import constants
import requests

TRACKER_FILE = "./tracker_list.dat"

# creates a new local tracker initialized with a placeholder local
def create_local_tracker_list():
    tracker_file_path = Path(TRACKER_FILE)

    with tracker_file_path.open(mode="wb") as tracker_file:
        tracker_data = {
            "primary": None,
            "backups": [],
        }
        pickle.dump(tracker_data, tracker_file)

    return

# gets a list of local trackers
def get_local_tracker_list():
    tracker_file_path = Path(TRACKER_FILE)

    if(not tracker_file_path.is_file()):
        create_local_tracker_list()

    with tracker_file_path.open(mode="rb") as tracker_file:
        tracker_data = pickle.load(tracker_file)
        primary_ip = tracker_data["primary"]
        ip_list = tracker_data["backups"]

        if(primary_ip is not None):
            ip_list.insert(0, primary_ip)

    return ip_list

# adds a new tracker ip to the local list
def add_tracker_ip_local(ip):
    try:
        ipaddress.IPv4Address(ip)
    except ValueError:
        return False

    tracker_file_path = Path(TRACKER_FILE)

    if(not tracker_file_path.is_file()):
        create_local_tracker_list()

    with tracker_file_path.open(mode="r+b") as tracker_file:
        tracker_data = pickle.load(tracker_file)
        tracker_data["backups"].append(ip)
        tracker_file.seek(0)
        pickle.dump(tracker_data, tracker_file)

    return True

# changes the primary tracker in the local list
def update_primary_tracker(new_primary_ip):
    try:
        ipaddress.IPv4Address(new_primary_ip)
    except ValueError:
        return {
            "success": False,
            "error": "Invalid ip address",
        }

    tracker_file_path = Path(TRACKER_FILE)

    if(not tracker_file_path.is_file()):
        create_local_tracker_list()

    pull_response = pull_remote_tracker_list(new_primary_ip)

    if(not pull_response["success"]):
        return {
            "success": False,
            "error": "Error pulling tracker list from tracker",
        }

    with tracker_file_path.open("r+b") as tracker_file:
        tracker_data = pickle.load(tracker_file)
        tracker_data["primary"] = new_primary_ip
        tracker_data["backups"] = [t["ip"] for t in pull_response["trackers"]]

        tracker_file.seek(0)
        pickle.dump(tracker_data, tracker_file)

    return {
        "success": True,
    }

# gets the tracker list from the primary tracker
def pull_remote_tracker_list(tracker_ip):
    try:
        r = requests.get(
            f"http://{tracker_ip}:{constants.TRACKER_PORT}/tracker_list",
            timeout=constants.REQUEST_TIMEOUT,
        )
        r.raise_for_status()
        return r.json()
    except (requests.HTTPError, requests.ConnectionError, requests.Timeout, ValueError) as e:
        return {
            "success": False,
            "error": str(e),
        }


from collections import namedtuple
from game_data.game_graph import GameGraph
from game_data.game_utils.plans import Plan
from game_data.iteration_utils.admissible import Admissible
from game_data.iteration_utils.threat_pair import ThreatPair

class IterationSolver:
    def __init__(self, game_graph: GameGraph):

        self.game_graph = game_graph
        self.states = game_graph.states
        self.action_map = game_graph.action_map
        self.plans = game_graph.plans

        self.viable_plans = None
        self.safe_steps = None
        self.plateaus = None
        self.alpha_safe_combinations = None
        self.viacomp_plans = None
        self.admissible_plans = None

        self.alpha = None

    def perform_iteration(self, alpha, itr_num):
        self.alpha = alpha
        self.find_viable_plans()
        self.find_safe_steps()
        self.find_plateaus()
        self.find_viacomp_plans()
        self.find_admissible_plans()

        return self.admissible_plans.copy(), self.safe_steps.copy(), self.viable_plans.copy()

    def find_viable_plans(self):
        self.viable_plans = dict()
        for state in self.states:
            self.viable_plans[state] = find_viable(state, self.plans, self.alpha)
            self.viable_plans[state.terminal_state] = [Plan([state.terminal_state])]

    def find_safe_steps(self):
        self.safe_steps = dict()
        for state in self.states:
            self.safe_steps[state] = find_state_safe_steps(state,
                                                           self.viable_plans,
                                                           self.action_map,
                                                           self.alpha)

    def find_plateaus(self):
        self.plateaus = dict()
        for state in self.states:
            plateau = Plateau(state.player, self.alpha[state])

            if self.plateaus.get(plateau) is None:
                self.plateaus[plateau] = {state}
                continue

            self.plateaus[plateau].add(state)

    def find_viacomp_plans(self):
        self.viacomp_plans = dict()
        for plateau in self.plateaus:
            plateau_set = self.plateaus[plateau]
            plateau_combinations = find_subsets(plateau_set)
            for subset in plateau_combinations:
                self.viacomp_plans[subset] = find_subset_viacomp_plans(subset, self.viable_plans, self.safe_steps)

    def find_admissible_plans(self):
        self.admissible_plans = dict()
        for subset_u in self.viacomp_plans:
            self.admissible_plans[subset_u] = find_subset_admissible_plans(self.viacomp_plans[subset_u],
                                                                           self.viable_plans,
                                                                           self.action_map,
                                                                           self.alpha)

def find_viable(state, plans, alpha):
    viable_plans = []

    for plan in plans[state]:
        if alpha_sat(plan, alpha):
            viable_plans.append(plan)

    return viable_plans

def find_state_safe_steps(state_t, viable_plans, action_map, alpha):
    safe = []

    for state_u in action_map[state_t]:
        if all(alpha_sat(plan, alpha, [state_t]) for plan in viable_plans[state_u]):
            safe.append(state_u)

    return safe

def find_subset_viacomp_plans(plateau_set, viabel_plans, safe_steps):
    viacomp_plans = {}

    for state_t in plateau_set:
        for plan in viabel_plans[state_t]:

            if not plateau_set.issubset(plan.plan_set()):
                continue

            u_map = {}
            is_viacomp = True

            for state_u in plateau_set:

                action_u = first_action(plan, state_u)
                if action_u in safe_steps[state_u]:
                    u_map[state_u] = action_u
                    continue

                is_viacomp = False
                break

            if is_viacomp:
                u_map = frozenset(u_map.items())
                if viacomp_plans.get(u_map) is None:
                    viacomp_plans[u_map] = [plan]
                    continue

                viacomp_plans[u_map].append(plan)

    return viacomp_plans

def find_subset_admissible_plans(viacomp_plans, viable_plans, action_map, alpha):
    admissible_plans = {}

    for u_map in viacomp_plans:
        admissible_plans[u_map] = []
        for plan in viacomp_plans[u_map]:
            state_t = plan[0]

            if alpha[state_t] > 0:
                admissible_plans[u_map].append(Admissible(state_t, plan, u_map, 'AD-i'))
                continue

            if not plan.is_absorbing:
                admissible_plans[u_map].append(Admissible(state_t, plan, u_map, 'AD-ii'))
                continue

            visited_dict = {state: False for state in u_map}
            appeared_once = True
            is_threat = False
            threat_pair = None
            AD_i = False

            for state_u in plan:

                if visited_dict.get(state_u) is not None:
                    if visited_dict[state_u]:
                        appeared_once = False

                    visited_dict[state_u] = True

                if state_u.is_terminal:
                    continue

                # AD-i: Different payoffs so state_t != state_u
                if appeared_once and state_t.player == state_u.player and alpha[state_u] > alpha[state_t]:
                    admissible_plans[u_map].append(Admissible(state_t, plan, u_map, 'AD-i'))
                    AD_i = True
                    break

                # AD-iv (b)
                if state_t.player != state_u.player and appeared_once:
                    is_threat, threat_pair = is_threat_pair(state_t, state_u, viable_plans, alpha, action_map, plan)

            if AD_i:
                continue

            if is_threat:
                admissible_plans[u_map].append(Admissible(state_t, plan, u_map, threat_pair))
                continue

            if appeared_once:
                admissible_plans[u_map].append(Admissible(state_t, plan, u_map, 'AD-iii'))
                continue

    return admissible_plans

def is_threat_pair(state_t, state_x, viable_plans, alpha, action_map, plan_g):
    # (c)
    for state_v in action_map[state_x]:
        # (d)
        if first_action(plan_g, state_x) == state_v:
            continue
        # (e)
        for plan_v in viable_plans[state_v]:
            if not alpha_sat(plan_v, alpha, [state_x]) and not alpha_sat(plan_v, alpha, [state_t]):
                return True, ThreatPair(state_t, state_x, plan_v)

    return False, None

def alpha_sat(plan, alpha, check_states=None):
    if check_states is None:
        check_states = plan

    for state in check_states:
        if state.is_terminal:
            continue

        if plan.get_payoff(state) < alpha[state]:
            return False

    return True

def first_action(plan_g, state_t):
    if state_t.is_terminal:
        return state_t

    return plan_g[first_occurrence_index(plan_g, state_t) + 1]

def first_occurrence_index(plan_g, state_t):
    return next((index for index, state in enumerate(plan_g) if state == state_t),
                Exception(f'{state_t} not in plan plan'))

def find_subsets(states):
    subsets = [[]]  # Start with an empty set

    # Generate subsets for each element in the original set
    for state in states:
        subsets += [subset + [state] for subset in subsets]

    subsets = {frozenset(subset) for subset in subsets[1:]}
    return subsets

# Named Tuples
Viacomp = namedtuple('Viacomp', ['plan', 'u_map'])
Plateau = namedtuple('Plateau', ['player', 'alpha'])
Alpha_Safe_Combination = namedtuple('Alpha_Safe_Combination', ['state', 'safe_step'])


from maya.api import _OpenMaya_py2 as om2

def is_control_rig(mob):
    fn = om2.MFnDagNode(mob)
    is_named_correctly = fn.name() == "rig"

    is_two_from_world = False
    if (is_named_correctly):
        parent_mob = fn.parent(0)
        parent_fn = om2.MFnDagNode(parent_mob)

        if parent_fn.name() != 'world':
            granny_mob = parent_fn.parent(0)
            granny_fn = om2.MFnDagNode(granny_mob)

            is_two_from_world = granny_fn.name() == 'world'

    return is_named_correctly and is_two_from_world

def is_component(mob):
    fn = om2.MFnDagNode(mob)

    is_under_rig = is_control_rig(fn.parent(0))
    if is_under_rig:
        return fn.name().endswith('_cmpnt')
    else:
        return False

def iter_components(rig_mob):
    if is_control_rig(rig_mob):
        fn = om2.MFnDagNode(rig_mob)
        child_count = fn.childCount()

        for i in range(child_count):
            child_mob = fn.child(i)
            child_name = om2.MFnDagNode(child_mob).name()
            if child_name.endswith('_cmpnt'):
                yield child_mob

def container_from_component(component_mob):
    assert is_component(component_mob)

    comp_fn = om2.MFnDagNode(component_mob)
    comp_dag_name = comp_fn.name()

    container_name = "{}_container".format(comp_dag_name[:-6])

    sel = om2.MSelectionList()
    sel.add(container_name)

    container_mob = sel.getDependNode(0)

    return container_mob

def iter_component_members(component_mob):
    container_fn = om2.MFnContainerNode(container_from_component(component_mob))

    members = container_fn.getMembers()
    for each_member in members:
        yield each_member

def iter_input(component_mob):
    if is_component(component_mob):
        fn = om2.MFnDagNode(component_mob)
        child_count = fn.childCount()

        for i in range(child_count):
            child_mob = fn.child(i)
            child_name = om2.MFnDagNode(child_mob).name()
            if child_name.endswith('_input'):
                yield child_mob

def iter_output(component_mob):
    if is_component(component_mob):
        fn = om2.MFnDagNode(component_mob)
        child_count = fn.childCount()

        for i in range(child_count):
            child_mob = fn.child(i)
            child_name = om2.MFnDagNode(child_mob).name()
            if child_name.endswith('_output'):
                yield child_mob

                itr_dag = om2.MItDag()
                itr_dag.reset(child_mob)
                itr_dag.next()

                while (not itr_dag.isDone()):
                    curr_node = itr_dag.currentItem()

                    yield curr_node
                    itr_dag.next()


"""Write a Python function that checks whether a word or phrase is palindrome or not.
Note: A palindrome is word, phrase, or sequence that reads the same backward as forward, e.g., madam
"""
s = str(input())

def palindrome(s):
    if s == s[::-1]: #[::-1] - reverse
        return True
    else:
        return False

print(palindrome(s))


from typing import Union, Iterable, Tuple, List
import numpy as np
from matplotlib import pyplot as plt
import tikzplotlib

from netcal.metrics.regression import QCE

class ReliabilityQCE(object):
    """
    Visualizes the Conditional Quantile Calibration Error (C-QCE) in the scope of regression calibration as a bar chart
    for probabilistic regression models.
    See :class:`netcal.metrics.regression.QCE` for a detailed documentation of the C-QCE [1]_.
    This method is able to visualize the C-QCE in terms of multiple univariate distributions if the input is given
    as multiple independent Gaussians.
    This method is also able to visualize the multivariate C-QCE for a multivariate Gaussian if the input is given
    with covariance matrices.

    Parameters
    ----------
    bins : int or iterable, default: 10
        Number of bins used by the C-QCE binning.
        If iterable, use different amount of bins for each dimension (nx1, nx2, ... = bins).

    References
    ----------
    .. [1] Küppers, Fabian, Schneider, Jonas, and Haselhoff, Anselm:
       "Parametric and Multivariate Uncertainty Calibration for Regression and Object Detection."
       European Conference on Computer Vision (ECCV) Workshops, 2022.
       `Get source online <https://arxiv.org/pdf/2207.01242.pdf>`__
    """

    eps = np.finfo(np.float32).eps

    def __init__(self, bins: Union[int, Iterable[float], np.ndarray] = 10):
        """ Constructor. For detailed parameter documentation view classdocs. """

        self.qce = QCE(bins=bins, marginal=False)

    def plot(
            self,
            X: Union[Tuple[np.ndarray, np.ndarray], np.ndarray],
            y: np.ndarray,
            q: Union[float, Iterable[float], np.ndarray],
            *,
            kind: str = 'meanstd',
            range_: List[Tuple[float, float]] = None,
            filename: str = None,
            tikz: bool = False,
            title_suffix: str = None,
            fig: plt.Figure = None,
            **save_args
    ) -> Union[plt.Figure, str]:
        """
        Visualizes the C-QCE as a bar chart either for multiple univariate data (if standard deviations are given as
        input) or for a joint multivariate distribution (if covariance matrices are given as input).
        See parameter "kind" for a detailed description of the input format.

        Parameters
        ----------
        X : np.ndarray of shape (r, n, [d]) or (t, n, [d]), or Tuple of two np.ndarray, each of shape (n, [d])
            Input data obtained by a model that performs inference with uncertainty.
            See parameter "kind" for input format descriptions.
        y : np.ndarray of shape (n, [d])
            Target scores for each prediction estimate in X.
        q : np.ndarray of shape (q,)
            Quantile scores in [0, 1] of size q to compute the x-valued quantile boundaries for.
        kind : str, either "meanstd" or "cumulative"
            Specify the kind of the input data. Might be one of:
            - meanstd: if X is tuple of two NumPy arrays with shape (n, [d]) and (n, [d, [d]]), this method asserts the
                       first array as mean and the second one as the according stddev predictions for d dimensions.
                       If the second NumPy array has shape (n, d, d), this method asserts covariance matrices as input
                       for each sample. In this case, the NLL is calculated for multivariate distributions.
                       If X is single NumPy array of shape (r, n), this methods asserts predictions obtained by a stochastic
                       inference model (e.g. network using MC dropout) with n samples and r stochastic forward passes. In this
                       case, the mean and stddev is computed automatically.
            - cumulative: assert X as tuple of two NumPy arrays of shape (t, n, [d]) with t points on the cumulative
                          for sample n (and optionally d dimensions).
        range_ : list of length d with tuples (lower_bound: float, upper_bound: float)
            List of tuples that define the binning range of the standard deviation for each dimension separately.
            For example, if input data is given with only a few samples having high standard deviations,
            this might distort the calculations as the binning scheme commonly takes the (min, max) as the range
            for the binning, yielding a high amount of empty bins.
        filename : str, optional, default: None
            Optional filename to save the plotted figure.
        tikz : bool, optional, default: False
            If True, use 'tikzplotlib' package to return tikz-code for Latex rather than a Matplotlib figure.
        title_suffix : str, optional, default: None
            Suffix for plot title.
        fig: plt.Figure, optional, default: None
            If given, the figure instance is used to draw the reliability diagram.
            If fig is None, a new one will be created.
        **save_args : args
            Additional arguments passed to 'matplotlib.pyplot.Figure.savefig' function if 'tikz' is False.
            If 'tikz' is True, the argument are passed to 'tikzplotlib.get_tikz_code' function.

        Returns
        -------
        matplotlib.pyplot.Figure if 'tikz' is False else str with tikz code.
            Visualization of the C-QCE either as Matplotlib figure or as string with tikz code.
        """

        # measure QCE and return a miscalibration map
        _, qce_map, num_samples_hist = self.qce.measure(
            X=X,
            y=y,
            q=q,
            kind=kind,
            reduction="none",
            range_=range_,
            return_map=True,
            return_num_samples=True
        )  # (q, b)

        # get number of dimensions
        ndims = len(qce_map)

        # catch if bin_edges is None
        assert len(self.qce._bin_edges) != 0, "Fatal error: could not compute bin_edges for ReliabilityQCE."

        # initialize plot and create an own chart for each dimension
        if fig is None:
            fig, axes = plt.subplots(nrows=2, ncols=ndims, figsize=(7 * ndims, 6), squeeze=False)
        else:

            axes = [
                [fig.add_subplot(2, ndims, idx) for idx in range(1, ndims + 1)],
                [fig.add_subplot(2, ndims, idx) for idx in range(ndims + 1, 2 * ndims + 1)],
            ]

        for dim in range(ndims):

            # convert absolute number of samples to relative amount
            n_samples_hist = np.divide(num_samples_hist[dim], np.sum(num_samples_hist[dim]))

            # compute mean over all quantiles as well as mean over all bins separately
            mean_over_quantiles = np.mean(qce_map[dim], axis=0)  # (b,)

            # get binning boundaries for actual dimension
            bounds = self.qce._bin_edges[dim]  # (b+1)

            for ax, metric, title, ylabel in zip(
                [axes[0][dim], axes[1][dim]],
                [n_samples_hist, mean_over_quantiles],
                ["Sample Histogram", "QCE mean over quantiles"],
                ["% of Samples", "Quantile Calibration Error (QCE)"],
            ):

                # draw bar chart with given edges and metrics
                ax.bar(bounds[:-1], height=metric, width=np.diff(bounds), align='edge', edgecolor='black')

                # set axes edges
                ax.set_xlim((bounds[0], bounds[-1]))
                ax.set_ylim((0., 1.))

                # labels and grid
                if self.qce._is_cov:
                    title = title + ' - multivariate'
                    ax.set_xlabel("sqrt( Standardized Generalized Variance (SGV) )")
                else:
                    title = title + ' - dim %02d' % dim
                    ax.set_xlabel("Standard Deviation")

                ax.set_ylabel(ylabel)
                ax.grid(True)

                # set axis title
                if title_suffix is not None:
                    title = title + ' - ' + title_suffix

                ax.set_title(title)

        fig.tight_layout()

        # if tikz is true, create tikz code from matplotlib figure
        if tikz:

            # get tikz code for our specific figure and also pass filename to store possible bitmaps
            tikz_fig = tikzplotlib.get_tikz_code(fig, filepath=filename, **save_args)

            # close matplotlib figure when tikz figure is requested to save memory
            plt.close(fig)
            fig = tikz_fig

        # save figure either as matplotlib PNG or as tikz output file
        if filename is not None:
            if tikz:
                with open(filename, "w") as open_file:
                    open_file.write(fig)
            else:
                fig.savefig(filename, **save_args)

        return fig


from math import radians, cos, sin, asin, sqrt
import csv
from csv import writer
from ping import *
RADIUS = 6371
HOME_LAT = 38.000641
HOME_LONG = -121.287399

def haversine(lat1, long1, lat2, long2):
    lat1 = radians(lat1)
    long1 = radians(long1)
    lat2 = radians(lat2)
    long2 = radians(long2)

    inner_function = (sin((lat2 - lat1)/2))**2 + cos(lat1)*cos(lat2)*(sin((long2 -long1)/2))**2
    distance = 2 * RADIUS * asin(sqrt(inner_function))

    return distance

def haversine_checker(trucks):
    with open('invite_truckers.csv', 'w') as invite:
        writer_object = writer(invite)
        titles = ('ID', 'Latitude', 'Longitude')
        writer_object.writerow(titles)
        for key in trucks:
            if haversine(HOME_LAT, HOME_LONG, trucks[key][0], trucks[key][1]) <= 200:
                writer_object.writerow((key, trucks[key][0], trucks[key][1]))


# Given nums = [2, 7, 11, 15], target = 9,
#
# Because nums[0] + nums[1] = 2 + 7 = 9,
# return [0, 1].

class Solution(object):
    def twoSum(self, nums, target):
        """
        :type nums: List[int]
        :type target: int
        :rtype: List[int]
        """
        mydict = {}
        for index, value in enumerate(nums):
            if target - value in mydict:
                return [mydict[target-value], index]
            else:
                mydict[value] = index
        return []


class BSTNode:

    def __init__(self, key, val):
        self.key, self.val = key, val
        self.left = None
        self.right = None
        self.size = 1

    def __str__(self):
        return f'BSTNode({self.key}, {self.val})' + \
               '\n|\n|-(L)->' + '\n|      '.join(str(self.left ).split('\n')) + \
               '\n|\n|-(R)->' + '\n|      '.join(str(self.right).split('\n'))

class BSTTable:
    def __init__(self):
        self._root = None

    def __str__(self):
        return str(self._root)

    def __len__(self):
        return self._size(self._root)

    def put(self, key, val):
        self._root = self._put(self._root, key, val)

    def get(self, key):
        return self._get(self._root, key)

    def _put(self, node, key, val):
        '''
        _put should return the new root of this subtree.

        node is the root of the subtree into which the
        key-value pair is to be inserted into.

        After the insertion, the root of this subtree may change.

        The difference of the input subtree and the returned subtree is that
        in the returned subtree, a new key-value pair has been inserted.
        '''
        if node:
            if key == node.key:
                node.val = val
                return self._root

            elif key < node.key:
                if node.left == None:
                    new_table = BSTTable()
                    new_table.put(key,val)
                    node.left = new_table
                    node.size += 1
                    return node
                else:
                    node.left.put(key,val)
                    return node

            elif key > node.key:
                if node.right == None:
                    new_table = BSTTable()
                    new_table.put(key,val)
                    node.right = new_table
                    node.size += 1
                    return node
                else:
                    node.right.put(key,val)
                    return node
        else:
            #tree is empty
            return BSTNode(key,val)

    def _get(self, node, key):
        if node:
            if key == node.key:
                return node.val
            elif key < node.key:
                if node.left:
                    return node.left.get(key)
                else:
                    raise KeyError('No such key found')

            elif key > node.key:
                if node.right:
                    return node.right.get(key)
                else:
                    raise KeyError('No such key found')
        else:
            raise KeyError('No such key found')

    @staticmethod
    def _size(node):
        return node.size if node else 0


import math
import numpy as np
import scipy.io as sio
def classify(test_data,train_data,train_target,k):
    dist=[]
    m,n=train_data.shape
    # 计算测试数据到每个点的欧式距离
    for i in range(m):
        temp=test_data-train_data[i]
        sum_2=0
        for j in range(len(temp)):
            sum_2+=temp[j]**2
        each_dist=math.sqrt(sum_2)
        dist.append(each_dist) #测试样本到index=i训练样本的距离被存放在res列表的index=i的位置，index=i的样本是第i+1个样本
    sorted_dist=sorted(dist)

    # k个最近的值所属的类别
    Class_count={}
    for i in range(k):
        label=train_target[dist.index(sorted_dist[i])]
        if label  in Class_count.keys():
            Class_count[label]+=1
        else:
            Class_count[label]=1
    Sorted_Class_count=sorted(Class_count.items(), key=lambda x: x[1], reverse=True)
    return Sorted_Class_count[0]

def creatDataSet():
    group=np.array([[1,1.1],[1,1],[0,0],[0,0.1]])
    labels=['A','A','B','B']
    return group,labels
# 数据归一化
def autoNorm(dataset):
    m,n=dataset.shape # 注意.shape()与.shape的区别
    min_value=dataset.min(0)
    ''' .min()无参，返回所有中的最小值；.min(0)返回每列的最小值；.min(1)返回每行的最小值'''
    max_value=dataset.max(0)
    ranges=max_value-min_value
    normDataset=np.zeros((m,n))
    normDataset=dataset-min_value
    normDataset=normDataset/ranges
    return normDataset,ranges,min_value

# 定义测试算法的函数。
"""
衡量算法的准确性knn算法可以用正确率或者错误率来衡量。错误率为0，表示分类良好。因此可以将训练样本中的
10%用于测试，90%用于训练。
"""
#def datingClassTest():
hoRatio=0.1
matfn = 'data/balance_scale.mat' #数据集的路径
data = sio.loadmat(matfn) #将.mat数据集转换为适用于python的数据集（应该是.npy）
dataset = data['data'] #通过设置断点调试，查看data数据，发现里面的data属性是需要的数据集
Datasets = dataset[:, 0:-1] # 只含有特征的样本集
Labels = dataset[:, -1] # 样本集的标签集
m,n=Datasets.shape #注意.shape与.shape()的区别
test_data_num=int(m*hoRatio)
normDatasets,ranges,min_value=autoNorm(Datasets)
test_data=normDatasets[0,:]
test_target=Labels[0]
for i in range(1,5):
    test_data=np.vstack([test_data,normDatasets[i,:]])
    test_target=np.hstack([test_target,Labels[i]])
for i in range(2):
    for j in range(5):
        t=50*(i+1)+j
        test_data=np.vstack([test_data,normDatasets[t,:]])
        test_target=np.hstack([test_target,Labels[t]])
train_data=np.delete(normDatasets,[0,1,2,3,4,50,51,52,53,54,100,101,102,103,104],axis=0)
# axis=0表示按行删除元素
train_target=np.delete(Labels,[0,1,2,3,4,50,51,52,53,54,100,101,102,103,104],axis=0)
errorCount=0
for i in range(len(test_data)):
    pred_label=classify(test_data[i,:],train_data,train_target,3)
    if (pred_label - test_target[i]).all():
        errorCount+=1
print('the total error rate is :',errorCount/float(test_data_num))

"""
如果不打乱原本的数据集，则测试结果为0.0，即错误率为零，因为在这个数据集，属于某一类别的样本全部集中在一起了，所以误差为零
"""
"""
if __name__=='__main__':
    datasets,labels=creatDataSet()
    pred_label=classify([0,0.2],datasets,labels,3)
    print(pred_label)
"""
"""
# 加载.mat数据集，并提取特征集Datasets和标签集Labels
matfn='data/iris.mat'
data=sio.loadmat(matfn)
dataset=data['data']
Datasets=dataset[:,0:-1] #从完整数据集中提取全部的样本特征部分
Labels=dataset[:,-1]#从完整数据集中提取全面的标签集
"""