from MethodApproach import *

def hard_coded_experiment_five_plot():
    y1 = [0., 0., 0., 0., 0.02, 0.03, 0.15, 0.21, 0.28, 0.33, 0.43, 0.46, 0.53, 0.54, 0.57, 0.59, 0.61, 0.62, 0.63,
          0.65]
    y2 = [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.01, 0.05, 0.09, 0.16, 0.19, 0.22, 0.24, 0.25, 0.28, 0.39,
          0.48, 0.49, 0.53, 0.57, 0.58, 0.58, 0.59, 0.58, 0.63, 0.62, 0.62, 0.63, 0.63, 0.64, 0.64, 0.64, 0.65, 0.65]
    y3 = [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.01, 0.12, 0.21,
          0.3, 0.38, 0.42, 0.47, 0.49, 0.54, 0.56, 0.59, 0.61, 0.59, 0.63, 0.63, 0.64, 0.65]
    xdummies = np.arange(1, 41, 1)
    xdummies2 = np.arange(21, 41, 1)

    clusters = np.array([])
    means = np.array([])

    clusters = np.hstack((clusters, np.ones(20)))
    means = np.hstack((means, np.arange(0.05, 1.05, 0.05)))
    clusters2 = np.arange(1, 21, 1)
    clusters2 = [str(x) for x in clusters2]
    clusters2 = [''.join('(' + clusters2[i] + ')') for i in range(len(clusters2))]
    clusters = np.hstack((clusters, clusters2))
    means = np.hstack((means, np.ones(20)))

    clusters = np.hstack((clusters, np.arange(1, 21, 1)))
    means = np.hstack((means, np.full(20, 0.05)))
    clusters = np.hstack((clusters, np.full(20, 20)))
    means = np.round(means, 3)
    means2 = np.arange(0.05, 1.05, 0.05)
    means2 = np.round(means2, 3)
    means2 = [str(x) for x in means2]
    means2 = [''.join('(' + means2[i] + ')') for i in range(len(means2))]
    means = np.hstack((means, means2))

    strClusters = [str(x) for x in clusters]
    strMeans = [str(x) for x in means]
    upperAxis = np.zeros(40)
    upperAxis = [str(x) for x in upperAxis]
    lowerAxis = np.zeros(40)
    lowerAxis = [str(x) for x in lowerAxis]

    j = 0
    for i in range(len(strClusters)):
        if i <= len(strClusters) / 2 - 1:
            lowerAxis[i] = strMeans[i] + ' : ' + strClusters[i]
        else:
            upperAxis[j] = strMeans[i] + ' : ' + strClusters[i]
            j += 1

    fig, ax = plt.subplots(constrained_layout=True)
    ax.set_xticks(xdummies, lowerAxis, rotation=80, size=16)
    ax.tick_params(axis='x', colors='b')

    ax2 = ax.twiny()
    ax2.set_xticks(xdummies, upperAxis, rotation=80, size=16)
    ax2.tick_params(axis='x', colors='red')

    lns1 = ax2.plot(xdummies, y2, label='Set-up #1: Peaking y_mu first')
    lns2 = ax.plot(xdummies, y3, color='r', label='Set-up #2: Peaking cluster_par first')
    lns3 = ax.plot(xdummies2, y1, color='g', label='Set-up #3 Increasing both parameters simultaneously')
    ax.axvline(20.5, linestyle='--')

    ax.set_ylabel('Ratio of 3-d graph above threshold')
    ax2.set_xlabel('Parameters for set-up #3 - y_mu : cluster_par')
    ax.set_xlabel('Parameters for set-up #1 - y_mu : cluster_par ')

    ax.xaxis.label.set_size(30)
    ax2.xaxis.label.set_size(30)
    ax.yaxis.label.set_size(30)
    ax.tick_params(axis='y', labelsize=16)

    lns = lns1 + lns2 + lns3
    labs = [line.get_label() for line in lns]
    ax.legend(lns, labs, loc=0, title='Experiment set-ups:', fontsize=23)

    # ax.legend(title='Experiment set-ups:')
    plt.show()

# cluster_parameters_experiment_method((5, 5, 5), 100, 1, 0.1, 40, 40, 5, True)
def Experiment_6(dimensions, d_size, y_mu, increment, perm, iterations, cluster_par, plot):
    y_mu_list = np.arange(0, y_mu, increment)
    m = cluster_par / (y_mu / increment)
    cluster_size = np.arange(0, cluster_par, m)
    signi = np.zeros((len(y_mu_list), len(cluster_size)))
    k = 0
    for mu in y_mu_list:
        j = 0
        for size in cluster_size:
            sig = 0
            for i in range(iterations):
                g = create_grid_graph((dimensions[0], dimensions[1], dimensions[2]), d_size, 0, 1, mu, 1, size)
                sig = sig + method(g, 0.05, 'data', 100, perm)
            signi[k, j] = sig / iterations
            j = j + 1
        k = k + 1
        print('Ran cluster parameters experiment ', k, '/', len(y_mu_list), 'time(s)')

    if plot:
        y_mesh, cluster_mesh = np.meshgrid(cluster_size, y_mu_list)

        fig, ax = plt.subplots(subplot_kw={"projection": "3d"})
        surf = ax.plot_surface(cluster_mesh, y_mesh, signi, cmap=cm.coolwarm,
                               linewidth=0, antialiased=False)
        ax.zaxis.set_major_locator(LinearLocator(10))
        ax.zaxis.set_major_formatter('{x:.02f}')

        ax.set_ylabel('Cluster size')
        ax.set_xlabel('y_mu')
        ax.set_zlabel('Significance')
        ax.set_zlim(0, 1.00)
        fig.colorbar(surf, shrink=0.5, aspect=5)

        plt.show()
    print((signi > 0.40).sum())
    per = ((signi > 0.40).sum()) / (signi.shape[0] * signi.shape[1])
    return signi, per

def experiment_7():
    edge_ratios = [0.01, 0.04, 0.07, 0.1, 0.5, 0.65, 0.85, 1.0]
    edge_neighbors = [1, 3, 6, 9, 12, 15, 18, 21]

    iterations = 200
    perc = np.zeros(3)
    perc_random = np.zeros(len(edge_ratios))
    perc_PA = np.zeros(len(edge_neighbors))
    j = 0
    for i in range(iterations):
        g = create_circle_graph(125, 100, 0, 1, 0.2, 1, 5)
        perc[j] = perc[j] + method(g, 0.05, 'data', 100, 100)
    j = j + 1
    print('Done with circular graphs')
    for i in range(iterations):
        g = create_grid_graph((25, 5, 1), 100, 0, 1, 0.2, 1, 5)
        perc[j] = perc[j] + method(g, 0.05, 'data', 100, 100)
    j = j + 1
    print('Done with 2-d grids')
    for i in range(iterations):
        g = create_grid_graph((5, 5, 5), 100, 0, 1, 0.2, 1, 5)
        perc[j] = perc[j] + method(g, 0.05, 'data', 100, 100)
    j = j + 1
    print('Done with 3-d grids')
    j = 0
    for edges in edge_ratios:
        for i in range(iterations):
            g = simulate_network(100, 'random', edges, 0, 0, 1, 0.2, 1, 100, 5)
            perc_random[j] = perc_random[j] + method(g, 0.05, 'data', 100, 100)
        j = j + 1
        print('Done with ', j, ' / ', len(edge_ratios))
    print('Done with Random graphs')
    j = 0
    for edges in edge_neighbors:
        for i in range(iterations):
            g = simulate_network(100, 'PA', 0, edges, 0, 1, 0.2, 1, 100, 5)
            perc_PA[j] = perc_PA[j] + method(g, 0.05, 'data', 100, 100)
        j = j + 1
        print('Done with ', j, ' / ', len(edge_neighbors))
    print('Done with PA graphs')
    print('Percentages for preliminary graphs: ', perc / iterations)
    print('Percentages for random graphs: ', perc_random / iterations)
    print('Percentages for PA graphs: ', perc_PA / iterations)

if __name__ == '__main__':
    print()


from FileLoader import FileLoader
import pandas as pd

def proportionBySport(df, year, sport, gender):
    cut = df.loc[df['Year'] == year]
    cut = cut.loc[cut['Sex'] == gender]
    cut = cut.drop_duplicates(subset="Name")
    nb = len(cut.loc[cut["Sport"] == sport])
    prop = nb / cut.shape[0]
    print(prop)

# loader = FileLoader()
# data = loader.load('../data/athlete_events.csv')
# proportionBySport(data, 2004, 'Tennis', 'F')


import logging
import argparse
from magicalimport import import_symbol
from dictknife.loading import get_formats
from kamidana.debug import error_handler

def main():
    parser = argparse.ArgumentParser()
    parser.add_argument(
        "--data", action="append", help="support yaml, json, toml", default=[]
    )
    parser.add_argument(
        "--loader",
        default="kamidana.loader:TemplateLoader",
        help="default: kamidana.loader:TemplateLoader",
    )
    parser.add_argument(
        "--logging", choices=list(logging._nameToLevel.keys()), default="INFO"
    )
    parser.add_argument("-a", "--additionals", action="append", default=[])
    parser.add_argument("-e", "--extension", action="append", default=[])
    parser.add_argument("-i", "--input-format", default=None, choices=get_formats())
    parser.add_argument("-o", "--output-format", default="raw")
    parser.add_argument("--debug", action="store_true")
    parser.add_argument("--quiet", action="store_true")
    parser.add_argument("batch")
    parser.add_argument("--outdir", default=None)

    args = parser.parse_args()
    logging.basicConfig(level=getattr(logging, args.logging))
    with error_handler(debug=args.debug, quiet=args.quiet):
        loader_cls = import_symbol(args.loader, ns="kamidana.loader", cwd=True)
        extensions = [
            ("jinja2.ext.{}".format(ext) if "." not in ext else ext)
            for ext in args.extension
        ]
        loader = loader_cls(
            args.data, args.additionals, extensions, format=args.input_format
        )
        driver_cls = import_symbol("kamidana.driver:BatchCommandDriver", cwd=True)
        driver = driver_cls(loader, format=args.output_format)
        driver.run(args.batch, args.outdir)


from sys import stdin, stdout
from collections import defaultdict
import random
finput = stdin.readline
fprint = stdout.write

class Contributor:
    def __init__(self, name, skills):
        self.name = name
        self.skills = skills
        self.available = True

class Project:
    def __init__(self, name, days, score, best_before, roles):
        self.name = name
        self.days = days
        self.score = score
        self.best_before = best_before
        self.roles = roles
        self.assigned = [None] * len(roles)

n_contributors, n_projects = map(int, finput().split(" "))
contributors = []
for _ in range(n_contributors):
    name, n_skills = finput().split(" ")
    skills = defaultdict(int)
    for _ in range(int(n_skills)):
        skill_name, skill_level = finput().split(" ")
        skills[skill_name] = int(skill_level)
    new_contributor = Contributor(name, skills)
    contributors.append(new_contributor)
projects = []
for _ in range(n_projects):
    name, *params = finput().split(" ")
    days, score, best_before, n_roles = map(int, params)
    roles = []
    for _ in range(n_roles):
        skill_name, level_required = finput().split(" ")
        roles.append([skill_name, int(level_required)])
    new_project = Project(name, days, score, best_before, roles)
    projects.append(new_project)

cskills = defaultdict(list)
for contributor in contributors:
    for skill in contributor.skills:
        cskills[skill].append(contributor)

projects.sort(key=lambda p: (-p.best_before, -p.score, p.days))
for project in projects:
    assigned_contributors = []
    for i, role in enumerate(project.roles):
        for contributor in cskills[role[0]]:
            if  contributor.skills[role[0]] >= role[1] and contributor.available:
                assigned_contributors.append(contributor)
                project.assigned[i] = contributor.name
                contributor.available = False
                break
    for contributor in assigned_contributors:
        contributor.available = True

ans = []
for project in projects:
    assigned = project.assigned
    if all(assigned):
        ans.append(project.name + '\n' + ' '.join(assigned))
fprint(str(len(ans)) + '\n' + '\n'.join(ans))

# ----------------TEST---------------------
# print("Contributor List :", contributors)
# for contributor in contributors:
#     print("\n  Name   :", contributor.name)
#     print("  Skills :", contributor.skills)
# print("\nProjects List", projects)
# for project in projects:
#     print("\n  Name  :", project.name)
#     print("  Days  :", project.days)
#     print("  Score :", project.score)
#     print("  Best Before:", project.best_before)
#     print("  Roles :", project.roles)
# ----------------COMMENT-------------------


# hash_map.py
# ===================================================
# Implement a hash map with chaining
# ===================================================

class SLNode:
    def __init__(self, key, value):
        self.next = None
        self.key = key
        self.value = value

    def __str__(self):
        return '(' + str(self.key) + ', ' + str(self.value) + ')'

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

    def add_front(self, key, value):
        """Create a new node and inserts it at the front of the linked list
        Args:
            key: the key for the new node
            value: the value for the new node"""
        new_node = SLNode(key, value)
        new_node.next = self.head
        self.head = new_node
        self.size = self.size + 1

    def remove(self, key):
        """Removes node from linked list
        Args:
            key: key of the node to remove """
        if self.head is None:
            return False
        if self.head.key == key:
            self.head = self.head.next
            self.size = self.size - 1
            return True
        cur = self.head.next
        prev = self.head
        while cur is not None:
            if cur.key == key:
                prev.next = cur.next
                self.size = self.size - 1
                return True
            prev = cur
            cur = cur.next
        return False

    def contains(self, key):
        """Searches linked list for a node with a given key
        Args:
            key: key of node
        Return:
            node with matching key, otherwise None"""
        if self.head is not None:
            cur = self.head
            while cur is not None:
                if cur.key == key:
                    return cur
                cur = cur.next
        return None

    def __str__(self):
        out = '['
        if self.head is not None:
            cur = self.head
            out = out + str(self.head)
            cur = cur.next
            while cur is not None:
                out = out + ' -> ' + str(cur)
                cur = cur.next
        out = out + ']'
        return out

def hash_function_1(key):
    hash = 0
    for i in key:
        hash = hash + ord(i)
    return hash

def hash_function_2(key):
    hash = 0
    index = 0
    for i in key:
        hash = hash + (index + 1) * ord(i)
        index = index + 1
    return hash

class HashMap:
    """
    Creates a new hash map with the specified number of buckets.
    Args:
        capacity: the total number of buckets to be created in the hash table
        function: the hash function to use for hashing values
    """

    def __init__(self, capacity, function):
        self._buckets = []
        for i in range(capacity):
            self._buckets.append(LinkedList())
        self.capacity = capacity
        self._hash_function = function
        self.size = 0

    def clear(self):
        """
        Empties out the hash table deleting all links in the hash table.
        """
        self._buckets = []
        for i in range(self.capacity):
            self._buckets.append(LinkedList())
        self.size = 0

    def get(self, key):
        """
        Returns the value with the given key.
        Args:
            key: the value of the key to look for
        Return:
            The value associated to the key. None if the link isn't found.
        """
        # Find the index
        index = self._hash_function(key) % self.capacity
        # Grab the node
        node = self._buckets[index].contains(key)
        # If the link
        if node is not None:
            return node.value
        else:
            return None

    def get_buckets(self):
        """Returns the buckets list."""
        return self._buckets

    def resize_table(self, capacity):
        """
        Re-sizes the hash table to have a number of buckets equal to the given
        capacity. All links need to be rehashed in this function after resizing
        Args:
            capacity: the new number of buckets.
        """
        # Create a new array and initiate new linked lists
        temp = []
        for num in range(capacity):
            temp.append(LinkedList())

        # Iterate through each linked list in the previous array and retrieve new hashes
        # Add these into new existing array
        for bucket in self._buckets:
            if bucket.head is not None:
                curr = bucket.head
                while curr is not None:
                    new_index = self._hash_function(curr.key) % capacity
                    temp[new_index].add_front(curr.key, curr.value)
                    curr = curr.next
        # Update buckets to point to new array
        self._buckets = temp
        # Update to new capacity
        self.capacity = capacity

    def put(self, key, value):
        """
        Updates the given key-value pair in the hash table. If a link with the given
        key already exists, this will just update the value and skip traversing. Otherwise,
        it will create a new link with the given key and value and add it to the table
        bucket's linked list.

        Args:
            key: they key to use to has the entry
            value: the value associated with the entry
        """
        index = self._hash_function(key) % self.capacity
        node = self._buckets[index].contains(key)
        # Point to the linked list in this index
        if node is not None:
            node.value = value
        else:
            self._buckets[index].add_front(key, value)
            self.size += 1

    def remove(self, key):
        """
        Removes and frees the link with the given key from the table. If no such link
        exists, this does nothing. Remember to search the entire linked list at the
        bucket.
        Args:
            key: they key to search for and remove along with its value
        """
        index = self._hash_function(key) % self.capacity

        if self.contains_key(key) is True:
            self._buckets[index].remove(key)
            self.size -= 1
        else:
            return

    def contains_key(self, key: object) -> object:
        """
        Searches to see if a key exists within the hash table

        Returns:
            True if the key is found False otherwise

        """
        index = self._hash_function(key) % self.capacity
        # Used the contains method for the linked list to see if it's in the bucket
        if self._buckets[index].contains(key) is not None:
            return True
        else:
            return False

    def empty_buckets(self):
        """
        Returns:
            The number of empty buckets in the table
        """
        count = 0
        # Find buckets with empty heads and increment count
        for bucket in self._buckets:
            if bucket.head is None:
                count += 1
        return count

    def table_load(self):
        """
        Returns:
            the ratio of (number of links) / (number of buckets) in the table as a float.

        """
        return float(self.size/self.capacity)

    def __str__(self):
        """
        Prints all the links in each of the buckets in the table.
        """

        out = ""
        index = 0
        for bucket in self._buckets:
            out = out + str(index) + ': ' + str(bucket) + '\n'
            index = index + 1
        return out


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

# Copyright xmuspeech (Author: JFZhou 2020-05-31)

import numpy as np
import os
import sys

sys.path.insert(0, 'subtools/pytorch')

import libs.support.kaldi_io as kaldi_io
from plda_base import PLDA

class CORAL(object):

    def __init__(self,
                 mean_diff_scale=1.0,
                 within_covar_scale=0.8,
                 between_covar_scale=0.8):
        self.tot_weight = 0
        self.mean_stats = 0
        self.variance_stats = 0
        self.mean_diff_scale = 1.0
        self.mean_diff_scale = mean_diff_scale
        self.within_covar_scale = within_covar_scale
        self.between_covar_scale = between_covar_scale

    def add_stats(self, weight, ivector):
        ivector = np.reshape(ivector,(-1,1))
        if type(self.mean_stats)==int:
            self.mean_stats = np.zeros(ivector.shape)
            self.variance_stats = np.zeros((ivector.shape[0],ivector.shape[0]))
        self.tot_weight += weight
        self.mean_stats += weight * ivector
        self.variance_stats += weight * np.matmul(ivector,ivector.T)

    def update_plda(self,):

        dim = self.mean_stats.shape[0]
        #TODO:Add assert
        '''
        // mean_diff of the adaptation data from the training data.  We optionally add
        // this to our total covariance matrix
        '''
        mean = (1.0 / self.tot_weight) * self.mean_stats

        '''
        D（x）= E[x^2]-[E(x)]^2
        '''
        variance = (1.0 / self.tot_weight) * self.variance_stats - np.matmul(mean,mean.T)
        '''
        // update the plda's mean data-member with our adaptation-data mean.
        '''
        mean_diff = mean - self.mean
        variance += self.mean_diff_scale * np.matmul(mean_diff,mean_diff.T)
        self.mean = mean

        o_covariance = self.within_var + self.between_var
        eigh_o, Q_o = np.linalg.eigh(o_covariance)
        self.sort_svd(eigh_o, Q_o)

        eigh_i, Q_i = np.linalg.eigh(variance)
        self.sort_svd(eigh_i, Q_i)

        EIGH_O = np.diag(eigh_o)
        EIGH_I = np.diag(eigh_i)

        C_o = np.matmul(np.matmul(Q_o,np.linalg.inv(np.sqrt(EIGH_O))),Q_o.T)
        C_i = np.matmul(np.matmul(Q_i,np.sqrt(EIGH_I)),Q_i.T)
        A = np.matmul(C_i,C_o)
        S_w = np.matmul(np.matmul(A,self.within_var),A.T)
        S_b = np.matmul(np.matmul(A,self.between_var),A.T)

        self.between_var = S_b
        self.within_var =  S_w

    def sort_svd(self,s, d):

        for i in range(len(s)-1):
            for j in range(i+1,len(s)):
                if s[i] > s[j]:
                    s[i], s[j] = s[j], s[i]
                    d[i], d[j] = d[j], d[i]

    def plda_read(self,plda):

        with kaldi_io.open_or_fd(plda,'rb') as f:
            for key,vec in kaldi_io.read_vec_flt_ark(f):
                if key == 'mean':
                    self.mean = vec.reshape(-1,1)
                    self.dim = self.mean.shape[0]
                elif key == 'within_var':
                    self.within_var = vec.reshape(self.dim, self.dim)
                else:
                    self.between_var = vec.reshape(self.dim, self.dim)

    def plda_write(self,plda):

        with kaldi_io.open_or_fd(plda,'wb') as f:
            kaldi_io.write_vec_flt(f, self.mean, key='mean')
            kaldi_io.write_vec_flt(f, self.within_var.reshape(-1,1), key='within_var')
            kaldi_io.write_vec_flt(f, self.between_var.reshape(-1,1), key='between_var')

class CIP(object):
    """
    Reference:
    Wang Q, Okabe K, Lee K A, et al. A Generalized Framework for Domain Adaptation of PLDA in Speaker Recognition[C]//ICASSP 2020-2020 IEEE International Conference on Acoustics, Speech and Signal Processing (ICASSP). IEEE, 2020: 6619-6623.
    """
    def __init__(self,
                 interpolation_weight=0.5):

        self.interpolation_weight = interpolation_weight

    def interpolation(self,coral,plda_in_domain):

        mean_in,between_var_in,within_var_in = self.plda_read(plda_in_domain)

        self.mean = mean_in
        self.between_var = self.interpolation_weight*coral.between_var+(1-self.interpolation_weight)*between_var_in
        self.within_var = self.interpolation_weight*coral.within_var+(1-self.interpolation_weight)*within_var_in

    def plda_read(self,plda):

        with kaldi_io.open_or_fd(plda,'rb') as f:
            for key,vec in kaldi_io.read_vec_flt_ark(f):
                if key == 'mean':
                    mean = vec.reshape(-1,1)
                    dim = mean.shape[0]
                elif key == 'within_var':
                    within_var = vec.reshape(dim, dim)
                else:
                    between_var = vec.reshape(dim, dim)

        return mean,between_var,within_var

def main():

    if len(sys.argv)!=5:
        print('<plda-out-domain> <adapt-ivector-rspecifier> <plda-in-domain> <plda-adapt> \n',
            )
        sys.exit()

    plda_out_domain = sys.argv[1]
    train_vecs_adapt = sys.argv[2]
    plda_in_domain = sys.argv[3]
    plda_adapt = sys.argv[4]

    coral=CORAL()
    coral.plda_read(plda_out_domain)

    for _,vec in kaldi_io.read_vec_flt_auto(train_vecs_adapt):
        coral.add_stats(1,vec)
    coral.update_plda()

    cip=CIP()
    cip.interpolation(coral,plda_in_domain)

    plda_new = PLDA()
    plda_new.mean = cip.mean
    plda_new.within_var = cip.within_var
    plda_new.between_var = cip.between_var
    plda_new.get_output()
    plda_new.plda_trans_write(plda_adapt)

if __name__ == "__main__":
    main()


import setuptools

long_description = "a scanpy-based single-cell crosstalk analysis package"

setuptools.setup(
  name="depair",
  version="0.0.2",
  author="Sijie Chen",
  author_email="chansigit@gmail.com",
  description="A scanpy-based single-cell crosstalk analysis package",
  long_description=long_description,
  long_description_content_type="text/markdown",
  url="https://github.com/chansigit/depair",
  packages=setuptools.find_packages(),
  classifiers=[
  "Programming Language :: Python :: 3",
  "License :: OSI Approved :: MIT License",
  "Operating System :: OS Independent",
  ],
)


import sys
from collections import deque
input = sys.stdin.readline

board = []
customer = []
d = [(-1,0),(0,-1),(0,1),(1,0)]

def bfs_customer(taxi):
	q = deque([taxi+[0]])
	board_cnt = [[0]*len(board) for _ in range(len(board))]
	while q:
		row,col,cnt = q.popleft()
		if board[row][col] < 0:
			return [row,col,cnt]
		for i in d:
			dr,dc = i
			if board[row+dr][col+dc] == 0 and board_cnt[row+dr][col+dc] == 0:
				board_cnt[row+dr][col+dc] = cnt+1
				q.append([row+dr,col+dc,cnt+1])
			elif board[row+dr][col+dc] < 0:
				return [row+dr,col+dc,cnt+1]

def bfs_finish(customer):
	board_cnt = [[0]*len(board) for _ in range(len(board))]
	sr,sc,fr,fc = customer
	q = deque([[sr,sc,0]])
	while q:
		row,col,cnt = q.popleft()
		board_cnt[row][col] = cnt
		if row == fr and col == fc:
			return cnt
		for i in d:
			dr,dc = i
			if board[row+dr][col+dc] < 1 and board_cnt[row+dr][col+dc] == 0:
				board_cnt[row+dr][col+dc] = cnt+1
				q.append([row+dr,col+dc,cnt+1])

def solution(taxi,N,M,oil):
	cus = len(customer)
	cost = []
	for i in range(len(customer)):
		sr,sc,fr,fc = customer[i]
		if sr == sc == 0:
			continue
		board[sr][sc] = -1*(i+1)
		cost.append(bfs_finish(customer[i]))
		if cost[-1] == None:
			return -1

	while cus != 0:
		start = bfs_customer(taxi)
		row,col,l = start
		oil -= l
		if oil < 0:
			return -1
		idx = -1*board[row][col]-1
		if oil - cost[idx] < 0:
			return -1
		oil += cost[idx]
		if oil > 0:
			cus -= 1
		else:
			return -1
		taxi = [customer[idx][2],customer[idx][3]]
		board[customer[idx][0]][customer[idx][1]] = 0
		customer[idx] = [0,0,0,0]

	return oil

if __name__ == "__main__":
	N,M,oil = map(int,input().split())
	board.append([1]*(N+2))
	for _ in range(N):
		board.append([1]+list(map(int,input().split()))+[1])
	board.append([1]*(N+2))
	taxi = list(map(int,input().split()))
	for _ in range(M):
		customer.append(list(map(int,input().split())))
	print(solution(taxi,N,M,oil))


#!/usr/bin/env python3

from collections import defaultdict
# from pprint import pprint
import sys
from typing import DefaultDict, Tuple

# type hints not yet added to sortedcontainers
# https://github.com/grantjenks/python-sortedcontainers/pull/107
from sortedcontainers import SortedSet  # type: ignore

from wallet import Wallet
from coin import Coin
from transaction import Transaction
from protocols import SupportsWrite

def create_sorted_txn_set():
    return SortedSet(key=lambda txn: txn.date)

class FlowAnalyser:
    # Dict mapping wallet -> currency -> a set of txns directly
    # *or* directly funding that wallet with that coin.  We ensure
    # the sets are chronologically sorted by setting the default
    # leaf values to be SortedSet instances which sorts by
    # txn.date.
    wallet_fundings: DefaultDict[
        Wallet,
        DefaultDict[Coin, SortedSet]
    ]

    # Dict which tracks the number of indirect fundings from
    # (wallet A, coin X) to (wallet B, coin Y) already included in
    # B's list of fundings for coin Y.
    #
    # Maps (wallet B, coin Y) -> (wallet A, coin X) -> number of
    # transactions from self.wallet_fundings[A][X] which were already
    # added to self.wallet_fundings[B][Y] as indirect fundings, or
    # skipped.
    #
    # This allows us to transitively maintain indirect funding
    # transactions in an efficient manner, avoiding duplicate funding
    # events or the need to iterate through the txn lists over and
    # over again.
    num_indirect_wallet_fundings: DefaultDict[
        Tuple[Wallet, Coin],
        DefaultDict[
            Tuple[Wallet, Coin],
            int
        ]
    ]

    output: SupportsWrite

    def __init__(self, output: SupportsWrite = sys.stdout) -> None:
        self.wallet_fundings = defaultdict(
            lambda: defaultdict(create_sorted_txn_set))

        self.num_indirect_wallet_fundings = defaultdict(
            lambda: defaultdict(lambda: 0))

        self.output = output

    def write(self, s: str) -> None:
        if self.output:
            self.output.write(s + "\n")

    def add_txn(self, txn: Transaction) -> None:
        if not txn.recipient or not txn.received_amount:
            assert 'withdrawal' in txn.tx_type
            # self.write(f"!! Skipping {txn}")
            return

        self.check_txn(txn)
        self.add_funding(txn)

    def update_wallets(self, txn: Transaction) -> None:
        src = txn.sender
        src_currency = txn.sent_currency
        src_amount = txn.sent_amount
        if (not src.is_external and src_amount is not None and
                src_currency is not None):
            src.withdraw(src_currency, src_amount)
            self.report_balance(src, src_currency, " after sending")

        dst = txn.recipient
        dst_currency = txn.received_currency
        dst_amount = txn.received_amount
        if dst_amount is not None:
            dst.deposit(dst_currency, dst_amount)
            self.report_balance(dst, dst_currency, " after receiving")

        fee_currency = txn.fee_currency
        fee_amount = txn.fee_amount
        if fee_amount is not None and fee_currency is not None:
            src.withdraw(fee_currency, fee_amount)
            self.report_balance(src, fee_currency, " after fee")

    def report_balance(self, wallet: Wallet, coin: Coin,
                       extra="") -> None:
        # Avoid balances like 0.00009062999999999433 BTC
        # which are just artifacts of floating point storage.
        # This rough approach is one decent enough option:
        #
        # balance = f"{wallet[coin]:.11f}".rstrip('0').rstrip('.')
        #
        # numpy.format_float_positional is another potential option.
        # However for now, just mimic Koinly's formatting:
        balance = f"{wallet[coin]:.8f}"
        self.write(f"   = {wallet} {coin} balance now "
                   f"{balance} {coin}{extra}")

    def check_txn(self, txn: Transaction):
        if txn.is_swap:
            assert txn.tx_type in ('buy', 'sell', 'exchange'), txn
            assert txn.sent_currency != txn.received_currency, txn
        else:
            assert txn.sent_currency == txn.received_currency, txn

    def add_funding(self, txn: Transaction) -> None:
        # txn.tx_type=crypto_deposit when sender is external
        # txn.tx_type=transfer when sender is internal
        if txn.is_swap:
            self.write(f"Swapping in {txn.sender}: "
                       f"{txn.sent_currency} -> {txn.received_currency}:")
        else:
            self.write(f"Funding {txn.recipient} with " +
                       txn.received_currency)
        self.write(f"   + {txn}")
        self.update_wallets(txn)
        self.add_direct_funding(txn)
        self.add_indirect_funding(txn)
        fundings: SortedSet[Transaction] = \
            self.wallet_fundings[txn.recipient][txn.received_currency]
        t: Transaction
        # for t in fundings:
        #     self.write(f"   . {t}")

    def add_direct_funding(self, txn: Transaction) -> None:
        self.wallet_fundings[txn.recipient][txn.received_currency].add(txn)

    def add_indirect_funding(self, txn: Transaction) -> None:
        # Track funding transitively.  Any wallet which funded
        # txn.sender is also considered an indirect funder of
        # txn.recipient.
        if txn.sender.is_external:
            self.write("   skipping transitive funding for external sources")
            return

        src = (txn.recipient, txn.received_currency)
        dst = (txn.sender, txn.sent_currency)
        count: int = self.num_indirect_wallet_fundings[src][dst]
        self.write(f"   transitively funding from funders of "
                   f"{txn.sender} with {txn.sent_currency}, "
                   f"starting at index {count}")
        fundings: SortedSet[Transaction] = \
            self.wallet_fundings[txn.sender][txn.sent_currency]
        new_indirect_txns: SortedSet[Transaction] = fundings[count:]
        for indirect_txn in new_indirect_txns:
            if (indirect_txn.sender == txn.recipient and
                    indirect_txn.sent_currency ==
                    txn.received_currency):
                self.write("      ignoring funding cycle")
                continue

            # Note: could have transactions in the same second, e.g.
            # when an exchange automatically routes a swap between
            # currencies which don't have a direct trading pair.
            assert indirect_txn.date <= txn.date

            self.wallet_fundings[txn.recipient][
                txn.received_currency].add(indirect_txn)
            # self.write(f"      > {indirect_txn}")

        new_index = \
            len(self.wallet_fundings[txn.sender][txn.sent_currency])
        self.num_indirect_wallet_fundings[src][dst] = new_index
        self.write(f"   next will start at index {new_index}")


def queueRequests(target, wordlists):

    # if the target supports HTTP/2, use engine=Engine.BURP2 to trigger the single-packet attack
    # if they only support HTTP/1, use Engine.THREADED or Engine.BURP instead
    # for more information, check out https://portswigger.net/research/smashing-the-state-machine
    engine = RequestEngine(endpoint=target.endpoint,
                           concurrentConnections=1,
                           engine=Engine.BURP2
                           )

    # the 'gate' argument withholds part of each request until openGate is invoked
    # if you see a negative timestamp, the server responded before the request was complete
    for i in range(20):
        engine.queue(target.req, gate='race1')

    # once every 'race1' tagged request has been queued
    # invoke engine.openGate() to send them in sync
    engine.openGate('race1')

def handleResponse(req, interesting):
    table.add(req)


from __future__ import print_function
import math, csv

# For comparison only
def get_semitones(hertz):
    octaves = math.log(hertz) / math.log(2)
    return octaves * 12

def st_diff(freq1, freq2):
    return abs(get_semitones(freq1) - get_semitones(freq2))

def lerp(start, end, f):
    return start + f * (end - start)

def delerp(start, end, x):
    return float(x - start) / (end - start)

def rdp_formant_approx(formant_points, tolerance_st):
    first_point = formant_points[ 0]
    last_point  = formant_points[-1]

    max_st_dist = 0
    max_st_dist_index = 0
    for index in xrange(1, len(formant_points) - 1):
        current_point = formant_points[index]

        progress    = delerp(first_point[0], last_point[0], current_point[0])
        beeline_value = [lerp(start, end, progress) for start, end in zip(first_point[1], last_point[1])]

        current_st_dist = max([st_diff(smp_freq, bl_freq) for smp_freq, bl_freq in zip(current_point[1][1:], beeline_value[1:])])

        if current_st_dist > max_st_dist:
            max_st_dist_index = index
            max_st_dist = current_st_dist

    if max_st_dist > tolerance_st:
        left_result  = rdp_formant_approx(formant_points[:max_st_dist_index + 1], tolerance_st)
        right_result = rdp_formant_approx(formant_points[max_st_dist_index:], tolerance_st)
        result = left_result[:-1] + right_result
    else:
        result = [formant_points[0], formant_points[-1]]

    return result

# ==================================================

def halve(iterator):
    for i, line in enumerate(iterator):
        if not i % 2:
            yield line

def double(iterator):
    for line in iterator:
        yield line
        yield line

timestep = .01
'''
with open('formants classic.tsv', 'r') as formants_file, open('formants classic.tsv', 'r') as intensity_file, open('formant_points.txt', 'w') as formant_points_file:
    formants_file_rows  = csv.reader(formants_file,  delimiter ='\t')
    intensity_file_rows = csv.reader(intensity_file, delimiter ='\t')

    # Read list of frames (intensity, F1, F2, F3)
    formants_file_rows.next()
    intensity_file_rows.next()
    formant_data = [map(float, irow[0:1] + frow[1:4]) for irow, frow in zip(intensity_file_rows, formants_file_rows)]
    '''
'''
with open('formants.frm', 'r') as formants_file, open('room defric 2.pwr', 'r') as intensity_file, open('formant_points.txt', 'w') as formant_points_file:
    formants_file_rows  = csv.reader(formants_file, delimiter=' ')

    formant_data = [map(float, [intensity] + frow[0:3]) for intensity, frow in zip(intensity_file, formants_file_rows)]
'''
with open('formants.frm', 'r') as formants_file, open('formants classic.tsv', 'r') as intensity_file, open('formant_points.txt', 'w') as formant_points_file:
    formants_file_rows  = csv.reader(formants_file, delimiter=' ')
    intensity_file_rows = csv.reader(intensity_file, delimiter ='\t')

    intensity_file_rows.next()
    formant_data = [map(float, irow[0:1] + frow[0:3]) for irow, frow in zip(double(intensity_file_rows), formants_file_rows)]

    # Convert to list of [time, frame]
    formant_points = [[index * timestep, datum] for index, datum in enumerate(formant_data)]

    print('Original formant point count: %i' % len(formant_points))
    formant_points = rdp_formant_approx(formant_points, 4)
    print('Optimized formant point count: %i' % len(formant_points))

    # Write to file
    print('Phase step: ' + str(timestep))
    for formant_point in formant_points:
        print('FP(%.2f, %f, %.f., %.f., %.f.)' % (formant_point[0], formant_point[1][0], formant_point[1][1], formant_point[1][2], formant_point[1][3],), file=formant_points_file)

print('Done')


# -*- coding: utf-8 -*-
"""
Created on Thu Jun 22 12:41:36 2017

@author: tdong
"""

'Import functions'
import numpy as np
import mne
from matplotlib import pyplot as plt
from mne.preprocessing import ICA
import spectrum
from pylab import *
from scipy import signal
import statsmodels.tsa.api as tsa

'Initialize trials'
trialnumbers = np.arange(499)
frameerror = [0]*500
phaseerror = [0]*500

'Create cosine wave with noise, bandpass filtered between 0.1 and 70, mean subtracted'
noise = np.random.normal(0,1,512*500)
frequency = 512
f = 6
sample = 512 * 500
x = np.arange(sample)
#y = np.cos(2 * np.pi * f * x[:-512] / Fs) + noise
#y = np.cos(2 * np.pi * f * x[:-512] / frequency)
realsignal = np.cos(2 * np.pi * f * x / frequency)
noisysignal = realsignal + noise

'AIC'
order = arange(2, 100)
rho = [spectrum.aryule(noisysignal, i, norm='biased')[1] for i in order]
plt.plot(order, spectrum.AIC(len(noisysignal), rho, order), label='AIC')
index_min = np.argmin(spectrum.AIC(len(noisysignal),rho,order)) #pick minimum rho
plt.title(index_min)

for trials in trialnumbers:
    y = noisysignal[512*trials:512*(trials+1)]

    b,a = signal.butter(1, [0.1/(0.5*512), 70/(0.5*512)], btype='band')
    last1second = signal.filtfilt(b, a, y)
    last1second = last1second - mean(last1second)

    'Run algorithm'
    [ar, var, reflec] = spectrum.aryule(last1second, 27, norm= 'biased') #replace the number with order
    psd = spectrum.arma2psd(ar) #power spectrum analysis
    freqvals = np.linspace(0,frequency/2,len(psd)/2)

    freqrange = np.where((freqvals >= 4) & (freqvals <=9))
    newpowerspectrumvals = psd[0:round(len(psd)/2)][freqrange]
    x = 0
    y = 0
    totalpower = np.trapz(newpowerspectrumvals, dx=1.0/256)
    theta = totalpower

    while theta > 0.5 * totalpower:

        if np.trapz(newpowerspectrumvals[1:],dx=1.0/256) > np.trapz(newpowerspectrumvals[:-1], dx=1.0/256):
            x = x + 1
            newpowerspectrumvals = newpowerspectrumvals[1:]
        else:
            y = y +1
            newpowerspectrumvals = newpowerspectrumvals[:-1]
        theta = np.trapz(newpowerspectrumvals, dx = 1.0/256)

    if x == 0:
        newfreqrange = freqrange[0][:-y]
    elif y == 0:
        newfreqrange = freqrange[0][x:]
    else:
        newfreqrange = freqrange[0][x:-y]

    minfreq = freqvals[newfreqrange][0]
    maxfreq = freqvals[newfreqrange][-1]

    b,a = signal.butter(1, [minfreq/(0.5*512), maxfreq/(0.5*512)], btype='band') #use min and max freq to bandpass filter
    cleanlast1second = signal.filtfilt(b, a, last1second) #zero phase band pass

    predictionoverlaplength = 0.1 #how far forward you want to predict, in seconds
    frames = round(predictionoverlaplength*len(cleanlast1second)) #calculate that in frames
    ARmodel= tsa.AR(cleanlast1second[frames:(-1*frames)]) #get autoregressive model
    ARmodelfit = ARmodel.fit(ic='aic') #fit the model
    ARmodelpredict = ARmodel.predict(params=ARmodelfit.params, start = len(cleanlast1second)-2*frames, end = len(cleanlast1second)+0*frames, dynamic = True) #predict
    predicteddata = np.concatenate((cleanlast1second[:-frames],ARmodelpredict)) #get predicted data

    'plot the prediction'
    #plt.figure()
    #plt.plot(predicteddata,label='predict')
    #plt.plot(cleanlast1second, label='orig')
    #plt.plot(cleanlast1second[:(-1*frames)])
    #plt.legend()

    'Hilbert transform to get instantaneous phase and freq'
    Hilberttransform = signal.hilbert(predicteddata) #perform hilbert transform
    inst_phase = np.angle(Hilberttransform) #get the phases at each timepoint
    inst_freq = np.diff(inst_phase)/(2*np.pi)*frequency #get the frequencies at each timepoint
    phaseguess = degrees(inst_phase[512]) #instant phase at current time point
    freqguess = inst_freq[512] #instant frequency at current time point

    #'plot signal based on calculated instantaneous phase'
    #regenerated_carrier = np.cos(inst_phase)
    #plt.plot(regenerated_carrier)

    'calculate time delay'
    timedelay = (1.0/freqguess) * (phaseguess)/360 #get timedelay
    timedelay = (1.0/(2*freqguess)) - timedelay #get time to next trough
    timedelayframes = int(round(timedelay * 512)) #get timedelay in frames

    'calculate error'
    realtroughs = np.where(realsignal<=-0.999)[0]
    frameerror[trials] = min(abs(realtroughs-(512*(trials+1)+timedelayframes))) #in number of frames away
    phaseerror[trials] = abs(-1 - realsignal[512*(trials+1)+timedelayframes]) #in y distance from trough

'Plot error'
plt.figure()
plt.hist(frameerror,bins=100)
plt.axvline(x=median(frameerror))
plt.figure()
plt.hist(phaseerror,bins=100)
plt.axvline(x=median(phaseerror))


from flask import Flask

app = Flask(__name__)

import json
import random

@app.route('/')
def hello_world():
    return 'Hello World!'

# This route creates a random number from 1 to 12 and stores that value in a
# dice variable.  It then places those numbers in a dictionary and encodes them
@app.route('/roll')
def roll_the_dice():
    die1 = random.randint(1, 12)
    die2 = random.randint(1, 12)
    return json.JSONEncoder().encode({'die1': die1, 'die2': die2})

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


import json

import config
import db
import util
from protocol import app
from protocol import dns
from scapy.all import *

tcp_sql = "INSERT INTO `log_netflow` (`client_mac`, `ip_src`, `ip_dst`, `port_src`, `port_dst`, `pkt_list`," \
          " `len`, `time_start`, `time_end`, `type`, `host`)" \
          "VALUE ('{client_mac}', '{ip_src}', '{ip_dst}', {port_src}, {port_dst}, '{pkt_list}', " \
          "'{len}', '{time_start}', '{time_end}', 6, '{host}')"

sessions = {}
item = {
    "client_mac": "",
    "host": "",
    "ip_src": "",
    "ip_dst": "",
    "port_src": 0,
    "port_dst": 0,
    "time_start": 0,
    "time_end": 0,
    "len": 0,
    "pkt_list": [],
    "fin1": 0,
    "fin2": 0,
    "seq1": [],
    "seq2": []
}

def write_db(session):
    res = {
        "client_mac": session["client_mac"],
        "ip_src": session["ip_src"],
        "ip_dst": session['ip_dst'],
        "port_src": session['port_src'],
        "port_dst": session['port_dst'],
        "pkt_list": json.dumps(session['pkt_list']),
        "len": session['len'],
        "time_start": session['time_start'],
        "time_end": session['time_end'],
        "host": session['host']
    }
    sql = tcp_sql.format(**res)
    db.query(sql)
    return True

def deal_tcp(pkt, timestamp):
    # basic info
    client_mac = pkt[Ether].src
    ip_src = str(pkt["IP"].src)
    ip_dst = str(pkt["IP"].dst)
    port_src = str(pkt["TCP"].sport)
    port_dst = str(pkt["TCP"].dport)
    tcp_flag = str(pkt['TCP'].flags)
    payload_len = len(pkt['TCP'].payload)
    sequin_str = ','.join([ip_src, port_src, ip_dst, port_dst])
    rev_sequin_str = ','.join([ip_dst, port_dst, ip_src, port_src])
    seq_now = pkt["TCP"].seq

    # exist session
    if sequin_str in sessions:
        pkt_dir = 1
        if pkt['TCP'].flags == 'S':
            write_db(sessions[sequin_str])
            del sessions[sequin_str]
            return deal_tcp(pkt, timestamp)
    elif rev_sequin_str in sessions:
        sequin_str = rev_sequin_str
        pkt_dir = 2
        if pkt['TCP'].flags == 'S':
            write_db(sessions[sequin_str])
            del sessions[sequin_str]
            return deal_tcp(pkt, timestamp)

    # new session
    elif pkt['TCP'].flags == 'S':
        pkt_dir = 1
        sessions[sequin_str] = copy.deepcopy(item)
        sessions[sequin_str]["client_mac"] = client_mac
        sessions[sequin_str]["ip_src"] = ip_src
        sessions[sequin_str]["ip_dst"] = ip_dst
        sessions[sequin_str]["port_src"] = port_src
        sessions[sequin_str]["port_dst"] = port_dst
        sessions[sequin_str]["time_start"] = timestamp
        host = dns.dns_reverse(ip_dst)
        if host != ip_dst:
            sessions[sequin_str]["host"] = host
    else:
        return True

    session = sessions[sequin_str]

    # check app
    if pkt_dir == 1:
        tcp_features = app.get_features("TCP")
        for feature in tcp_features:
            app_name, sport, dport, host, dic = feature
            flag = True
            if sport != '' and sport != str(session['port_src']):
                continue
            if dport != '' and dport != str(session['port_dst']):
                continue
            if host != '' and host not in session['host']:
                continue
            flag = True
            try:
                for d in dic:
                    if len(d) == 2 and pkt['TCP'].payload.load[int(d[0])] != int(d[1], 16):
                        flag = False
                        break
            except:
                flag = False
            if flag:
                app.add(client_mac, app_name, timestamp, session["host"])
                break

    # check dup
    if seq_now in session['seq' + str(pkt_dir)]:
        return True
    # write session record
    session['len'] += payload_len
    session['seq' + str(pkt_dir)].append(seq_now)
    session['time_end'] = timestamp
    session['pkt_list'].append({
        "d": pkt_dir,
        "l": payload_len,
        "f": tcp_flag,
        "t": timestamp - session['time_start']
    })

    # check RST
    if 'R' in tcp_flag:
        result = write_db(session)
        del sessions[sequin_str]
        return result

    # check FIN
    if session['fin' + str(pkt_dir)] == 1:
        session['fin' + str(pkt_dir)] = 2
    if 'F' in tcp_flag:
        session['fin' + str(pkt_dir)] = 1

    if session['fin1'] == 2 and session['fin2'] == 2:
        result = write_db(session)
        del sessions[sequin_str]
        return result

    return True

def tcp_timeout():
    print("[TCP] check tcp timeout")
    _del = []
    for session in sessions:
        if sessions[session]["fin1"] + sessions[session]["fin2"] >= 2 and \
                int(time.time()) - sessions[session]['time_end'] >= 60:
            write_db(sessions[session])
            _del.append(session)
        elif int(time.time()) - sessions[session]["time_end"] >= config.tcp_timeout:
            write_db(sessions[session])
            _del.append(session)
    for i in _del:
        del sessions[i]

util.add_cron(tcp_timeout, 60)

def read(pkt, timestamp):
    try:
        if not (pkt.haslayer(IP) and pkt.haslayer(TCP)):
            return False
        else:
            return deal_tcp(pkt, timestamp)
        return False
    except Exception as e:
        print("[TCP] ", e)
        return False


import pandas as pd
import json

class Comparator:
    def __init__(self, dev_con, db_collection_con):
        self.dev_con = dev_con
        self.db_collection_con = db_collection_con
        self.device_vlan_df = self._get_device_vlan_df()
        self.db_vlan_df = self._get_db_vlan_df()
        #
        self.dev_db_vlan_df = self.deviceAndDBVlans()

    def _get_device_vlan_df(self):
        """
        dev_vlan_dd_ll = [
{'vlan_id': 1, 'name': 'default'},
{'vlan_id': 3, 'name': 'TEST3'},
{'vlan_id': 4, 'name': 'DEV_from_sw_201_NEW'}]
        """
        device_vlan_dd_ll = self.dev_con.get_vlans()
        if device_vlan_dd_ll is None:
            raise ValueError("we did not get vlans from the device. Please check connection logs.")
        device_vlan_df = pd.DataFrame(device_vlan_dd_ll)
        if device_vlan_df.empty:
            device_vlan_df = pd.DataFrame(columns = ['vlan_id', 'name'])
        return device_vlan_df

    def _get_db_vlan_df(self):
        """
        db_vlan_dd_ll = [
{'vlan_id': 1, 'name': 'default'},
{'vlan_id': 2, 'name': 'TEST33'},
{'vlan_id': 4, 'name': 'DEV_from_sw_201'}]
        """
        db_vlan_dd_ll = self.db_collection_con.objects.get_db_vlan_dd_ll()
        db_vlan_df = pd.DataFrame(db_vlan_dd_ll)
        if db_vlan_df.empty:
            db_vlan_df = pd.DataFrame(columns = ['vlan_id', 'name'])
        return db_vlan_df
    def deviceAndDBVlans(self):
        return pd.merge(self.device_vlan_df, self.db_vlan_df, on=['vlan_id'], how='outer', indicator='dev_db_diff', suffixes=('_dev', '_db'))

    def get_dev_vlans_only(self):
        """
        name_dev  vlan_id name_db dev_db_diff
         TEST3        3     NaN   left_only
        """
        dev_vlans_only_df = self.dev_db_vlan_df.query('dev_db_diff == "left_only"')
        dev_vlans_only_df = dev_vlans_only_df.rename(columns={'name_dev': 'name'})
        return json.loads(dev_vlans_only_df.to_json(orient='records'))

    def get_db_vlans_only(self):
        """
          name_dev  vlan_id name_db dev_db_diff
            NaN        2    TEST33  right_only
        """
        db_vlans_only_df = self.dev_db_vlan_df.query('dev_db_diff == "right_only"')
        db_vlans_only_df = db_vlans_only_df.rename(columns={'name_db': 'name'})
        return json.loads(db_vlans_only_df.to_json(orient='records'))

    def getVlanNameDiffWithDbDF(self):
        # when we received DB watch event - we rely on DB info
        dev_and_db_vlan_for_updates_df = pd.merge(self.device_vlan_df, self.db_vlan_df, on=['vlan_id', 'name'], how='right', indicator='dev_db_diff') # we can update only those vlans which has already exists in DB
        not_updated_vlans_on_db = dev_and_db_vlan_for_updates_df.query('dev_db_diff == "right_only"')
        return json.loads(not_updated_vlans_on_db.to_json(orient='records'))

    def getVlanNameDiffWithDeviceDF(self):
        # when we received SNMP trap - we rely on device info
        dev_and_db_vlan_for_updates_df = pd.merge(self.device_vlan_df, self.db_vlan_df, on=['vlan_id', 'name'], how='left', indicator='dev_db_diff')
        not_updated_vlans_on_db = dev_and_db_vlan_for_updates_df.query('dev_db_diff == "left_only"')
        return json.loads(not_updated_vlans_on_db.to_json(orient='records'))


def main():
    print(countZeros(n=300230, c=0))

def recursion(n):
    if n == 0:
        return
    #prints while stacking up the function calls
    print(n )
    recursion(n-1)

def recursionRev(n):
    if n == 0:
        return
    recursionRev(n-1)
    print(n) #prints while the function call stack is emptied

def infiniteRec(n):
    if n == 0:
        return
    print(n)
    infiniteRec(n)
    n-=1 #post decrement (n--) doest exist in python so this is the way, pre decrement exists as (--n)

def reverse(n, revnum):
    """
    def main():
    #n, revnum = 1234, 0
    #the above doesn't work as int in immutable & changes in reverse doesnt affect so array required
    n, revnum = 1234, [0]
    reverse(n, revnum)
    print(revnum[0])

    """
    if n == 0:
        return
    else:
        rem = n % 10
        revnum[0] = revnum[0]*10 + rem
        reverse(n//10, revnum)
        #return revnum

def countZeros(n, c):
    if n == 0:
        return c
    else:
        rem = n % 10
        if rem == 0:
            return countZeros(n//10, c+1)
        else:
            return countZeros(n//10, c)

main()


import copy
from packageship.libs.log import LOGGER
from packageship.application.query.depend import InstallRequires
from packageship.application.database.cache import buffer_cache
from .basedepend import BaseDepend
class InstallDepend(BaseDepend):

    """
    Description: query install depend of package

    Attributes:
        db_list: database priority list
        search_install_dict: stored bianry name for next install search loop
        binary_dict: stored the result for depend binary info
        source_dict: stored the resulth for depend source info
        depend_history: Query other dependent class
        com_not_found_pro: stored the comopent name which cannot find the provided pkg
        _search_set: stored the bianry name for this search loop
        __level: count the depend level
        __query_installreq: query databases for getting install requires
    """

    def __init__(self, db_list, depend=None):
        """
        Args:
            db_list: database priority list
            depend: the type of BaseDepend class
        """
        if not db_list:
            raise ValueError("the input of db_list is none")

        super(InstallDepend, self).__init__()

        self._init_search_dict(self.search_install_dict, db_list)
        self.__level = 0
        self.__query_installreq = InstallRequires(db_list)

        # for build and self depend, get the previous result from the input cls
        if isinstance(depend, BaseDepend):
            self.depend_history = depend
            self.binary_dict = depend.binary_dict
            self.source_dict = depend.source_dict
            self.com_not_found_pro = depend.com_not_found_pro
            self.search_install_dict = depend.search_install_dict
            # if the depend type is build,
            # there would be a build depend result in the source dict
            self.depend_type = "build" if self.source_dict else "self"

    def install_depend(self, bin_name, level=0):
        """
        Description: get binary rpm package(s) install depend relation
        Args:
            bin_name: the list of package names needed to be searched
            level: The number of levels of dependency querying,
                    the default value of level is 0, which means search all dependency
        Exception:
            AttributeError: the input value is invalid
       """
        if not isinstance(bin_name, list):
            raise AttributeError("the input is invalid")
        for binary in bin_name:
            if binary:
                self.search_install_dict.get("non_db").add(binary)

        while self._check_search(self.search_install_dict):
            self.__level += 1
            self.__query_one_level_dep(level)
            # Stop the query when the __level in the query reaches the input of level
            if self.__level == level:
                break

    def __query_one_level_dep(self, level):
        """
        Description: query the one level install dep in database
        Args:
            level: The number of levels of dependency querying,
                    the default value of level is 0, which means search all dependency
        Returns:
            resp: the response for one level depend result
       """
        resp = self._query_in_db(
            search_dict=self.search_install_dict,
            func=self.__query_installreq.get_install_req)

        if self.__level == 1:
            searched_pkg = copy.deepcopy(self._search_set)

        for pkg_info in resp:
            if not pkg_info:
                LOGGER.warning("There is a None type in resp")
                continue
            bin_name = pkg_info.get("binary_name")
            src_name = pkg_info.get("src_name")

            if not bin_name:
                continue
            # check the input packages searched result
            if self.__level == 1:
                searched_pkg.discard(bin_name)

            if not self._has_searched_dep(bin_name, "install"):
                # binary pkg which has not query the installdep yet,
                # put it into search dict based on the database which found it
                depend_set = set()
                #for non install depend, the list would be empty
                install_list = []
                for req in pkg_info.get("requires"):
                    com_bin_name = req.get("com_bin_name")
                    # insert req info in last level loop
                    if self.__level == level:
                        self._insert_com_info(req)

                    if self._checka_and_add_com_value(req, self.search_install_dict):
                        depend_set.add(com_bin_name)
                install_list = list(depend_set)

                # put the package binary info into binary result dict
                self._insert_into_binary_dict(
                    name=bin_name,
                    version=pkg_info.get("bin_version", "NOT FOUND"),
                    source_name=pkg_info.get("src_name", "NOT FOUND"),
                    database=pkg_info.get("database", "NOT FOUND"),
                    install=install_list
                )

            # put the package source info into source result dict
            if src_name and src_name not in self.source_dict:
                self._insert_into_source_dict(
                    name=src_name,
                    version=pkg_info.get("src_version", "NOT FOUND"),
                    database=pkg_info.get("database", "NOT FOUND")
                )

            if self.depend_history and self.depend_type == "self":
                self.depend_history.add_search_dict(
                    "install",
                    pkg_info.get("database"),
                    com_src_name=src_name)

        self._search_set.clear()
        if self.__level == 1 and searched_pkg and not self.depend_history:
            self.log_msg = f"Can not find the packages:{str(searched_pkg)}in all databases"
            LOGGER.warning(self.log_msg)

    def __call__(self, **kwargs):
        self.__dict__.update(
            dict(packagename=kwargs["packagename"], dependency_type="installdep"))

        @buffer_cache(depend=self)
        def _depend(**kwargs):
            self.install_depend(bin_name=kwargs["packagename"],
                                level=kwargs["parameter"]["level"])
        _depend(**kwargs)


#Criando String e concatenando
rua ='Rua do catete'
numero = "153"
bairro = 'Catete'
cidade = 'rio de janeiro'
estado = "Rj"
cep = '22220-000'

endereco = rua + numero + bairro + cidade + estado + cep
print (endereco)

rua ='Rua do catete, '
numero = "153, "
bairro = 'Catete, '
cidade = 'rio de janeiro, '
estado = "Rj, "
cep = '22220-000'

print (endereco)
endereco = rua + numero + bairro + cidade + estado + cep

#letraMaiusculas
endereco_maiuscula = endereco.upper()
print(endereco_maiuscula)

#letraMinuscula
endereco_maiuscula = endereco.lower()
print(endereco_maiuscula)


import json
from json import loads, dumps
from cassandra.cluster import Cluster
from datetime import datetime, timezone

def connect_to_cassandra():
    cluster= Cluster(['localhost'],port=9042)
    session= cluster.connect("twitt")
    return session, cluster

if __name__ == '__main__':
    session, cluster= connect_to_cassandra()
    session.set_keyspace('twitter')

    #query1
    result1= session.execute("SELECT twitt_id FROM twitts where day=15 AND hour>=20 AND minute>30")
    for r1 in result1:
        print (r1)

    #query2
    result2= session.execute("SELECT twitt_id FROM persons where user_name='Rahmadzade' AND (day=15 OR (day=14 AND hour>21)")
    for r2 in result2:
        print (r2)

    #query3
    result3 = session.execute("SELECT twitt_id FROM hashtags where hashtag='help' AND date>'2021-8-13' AND date<'2021-8-15'")
    for r3 in result3:
        print(r3)

    #query4
    result4 = session.execute("SELECT twitt_id FROM person where user_name='Rahmadzade' day IN (8,15)")
    for r4 in result4:
        print(r4)


from .core.edit import TextEditTuple
from .core.logging import debug
from .core.typing import List, Optional, Any, Generator, Iterable
from contextlib import contextmanager
import operator
import sublime
import sublime_plugin

@contextmanager
def temporary_setting(settings: sublime.Settings, key: str, val: Any) -> Generator[None, None, None]:
    prev_val = None
    has_prev_val = settings.has(key)
    if has_prev_val:
        prev_val = settings.get(key)
    settings.set(key, val)
    yield
    settings.erase(key)
    if has_prev_val and settings.get(key) != prev_val:
        settings.set(key, prev_val)

class LspApplyDocumentEditCommand(sublime_plugin.TextCommand):

    def run(self, edit: sublime.Edit, changes: Optional[List[TextEditTuple]] = None) -> None:
        # Apply the changes in reverse, so that we don't invalidate the range
        # of any change that we haven't applied yet.
        if not changes:
            return
        with temporary_setting(self.view.settings(), "translate_tabs_to_spaces", False):
            view_version = self.view.change_count()
            last_row, _ = self.view.rowcol_utf16(self.view.size())
            for start, end, replacement, version in reversed(_sort_by_application_order(changes)):
                if version is not None and version != view_version:
                    debug('ignoring edit due to non-matching document version')
                    continue
                region = sublime.Region(
                    self.view.text_point_utf16(*start, clamp_column=True),
                    self.view.text_point_utf16(*end, clamp_column=True)
                )
                if start[0] > last_row and replacement[0] != '\n':
                    # Handle when a language server (eg gopls) inserts at a row beyond the document
                    # some editors create the line automatically, sublime needs to have the newline prepended.
                    self.apply_change(region, '\n' + replacement, edit)
                    last_row, _ = self.view.rowcol(self.view.size())
                else:
                    self.apply_change(region, replacement, edit)

    def apply_change(self, region: sublime.Region, replacement: str, edit: sublime.Edit) -> None:
        if region.empty():
            self.view.insert(edit, region.a, replacement)
        else:
            if len(replacement) > 0:
                self.view.replace(edit, region, replacement)
            else:
                self.view.erase(edit, region)

def _sort_by_application_order(changes: Iterable[TextEditTuple]) -> List[TextEditTuple]:
    # The spec reads:
    # > However, it is possible that multiple edits have the same start position: multiple
    # > inserts, or any number of inserts followed by a single remove or replace edit. If
    # > multiple inserts have the same position, the order in the array defines the order in
    # > which the inserted strings appear in the resulting text.
    # So we sort by start position. But if multiple text edits start at the same position,
    # we use the index in the array as the key.

    return list(sorted(changes, key=operator.itemgetter(0)))


import socket
import ast
import time
import sys
from flask import Flask, render_template, Response, request
from flask_cors import CORS
import random
from threading import Thread
msgFromClient =""
localIP     = socket.gethostname()
localPort   = 20001
bufferSize          = 1024
bytesToSend         = str.encode(msgFromClient)
serverAddressPort   = (localIP, localPort)
list_ = []
app = Flask(__name__)
CORS(app)

class file_video:
    def __init__(self, file1):
        self.file1 = file1
class temps:
    def __init__(self, temps):
        self.temps = temps
file1 = file_video
temps1 = temps
def add_list(json):
    list_.append(json)

def receive_json():
    time_start = time.time()
    while temps1.temps == 1:
    # Create a UDP socket at client side

        UDPClientSocket = socket.socket(family=socket.AF_INET, type=socket.SOCK_DGRAM)
    # Send to server using created UDP socket

        UDPClientSocket.sendto(bytesToSend, serverAddressPort)
        msgFromServer = UDPClientSocket.recvfrom(bufferSize)
        msg = "{}".format(msgFromServer[0])
        a = msg.lstrip("b")
        a = a.lstrip('"')
        a = a.rstrip('"')
        res = ast.literal_eval(a)
        add_list(res)
        if time.time() - time_start >=20:
            break
        #print(res)
        #print(res)
        #jsonObj = json.loads(str(res))
        #print(jsonObj)
        # person = 0
        # for i in res:
        #     if i == "person":
        #         person = person + 1
        # print(person)
    # man = list_[0]
    # print(man["man"])
    # print(len(list_))
    return list_

def obj_max(list):
    man = 0
    girl = 0
    elder= 0
    children = 0
    obj = []
    for i in list:
       man = man + i["man"]
       girl = girl + i["girl"]
       elder = elder + i["elder"]
       children = children + i["children"]
    obj.append(man)
    obj.append(girl)
    obj.append(elder)
    obj.append(children)
    if max(obj) == 0:
        return 0
    else:
        for i in range(len(obj)):
            if max(obj) == obj[i]:
                return i + 1

def return_video(max_obj):
    if max_obj == 0:
        return random.randint(1,6)
    if max_obj == 1:
        return 1
    if max_obj == 2:
        return 2
    if max_obj == 3:
        return 3
    if max_obj == 4:
        return 4

@app.route('/videos', methods=['GET'])
def test():
    print("....")
    print(file1.file1)
    return str(file1.file1) +'.mp4'

@app.route('/videos', methods=['POST'])
def getvideo():
    #print("okela")
    temps_ = request.json
    temps1.temps = int(temps_['temp'])

    # print(temps1.temps['temp'])
    # value = request.form['projectFilePath']
    # file_name = random.randint(1, 6)
    # print(value)
    # print('==================response=============')
    # print(file_name)
    return temps_

def run_server():
    app.run(host='0.0.0.0', threaded=True)

def main_host():
    temps1.temps = 1
    class_id = obj_max(receive_json())
    file1.file1 = return_video(class_id)
    list_.clear()
    print(file1.file1)
    Thread(target=run_server, args=()).start()
    while True:
        if temps1.temps == 1:
            class_id = obj_max(receive_json())
            file1.file1 = return_video(class_id)
            list_.clear()
            print("classid")
            print(class_id)
            print("video")
            print(file1.file1)


import pricing
import misc
import statistics
import random
# import cProfile
from typing import List, Tuple
import os
Matrix = List[List[float]]

class Unit:
    def __init__(self, name: str, recruit_order: int):
        self.name = name
        self.recruit_order = recruit_order
        self.owner = -1
        self.bids = []
        # whenever iterating over bids, we also iterate over Units
        # Simplify loops and save on zips by storing the bids in the Units

class AuctionState:
    def __init__(self):
        self.players = []
        self.units = []

        self.max_team_size = 0

        # index by player last for printing/reading and for consistency
        # used for redundancy adjusted team values
        self.bid_sums = []

        self.synergies = []
        # P x U x U, players choose value to reduce/increase value of unit pairs
        # generally negative for redundant units
        # increment value of team by manual_synergy[i][j][valuer] if i and j on same team
        # should be triangular matrix since synergy i<->j == j<->i

        self.game_dir = ''
        self.auct_dir = ''
        self.log_strings = []
        self.logs_written = 0

    # need to print as the auction runs, not just when a log is ready for the next output file
    def print_and_log(self, text: str):
        print(text)
        self.log_strings.append(text)

    def write_logs(self, filename: str):
        print()
        file = open(f'{self.auct_dir}output/{self.logs_written:02d}_{filename}.txt', 'w')
        file.write('\n'.join(self.log_strings))
        file.close()
        self.log_strings = []
        self.logs_written += 1

    def format_bids(self):
        self.print_and_log('--BIDS--        ' + ' '.join([f'{player:10s}' for player in self.players]))
        for unit in self.units:
            self.print_and_log(f'{unit.name:15s}' + ' '.join([f' {bid:5.2f}    ' for bid in unit.bids]))

    def set_median_synergy(self):
        print(f'Setting median synergies for {self.players[len(self.synergies)]}')
        player_synergies = []
        for u_i in range(len(self.units)):
            next_synergy_row = []
            if len(self.synergies) > 0:
                for u_j in range(len(self.units)):
                    next_synergy_row.append(statistics.median([synergy[u_i][u_j] for synergy in self.synergies]))
            else:
                next_synergy_row = [0] * len(self.units)
            player_synergies.append(next_synergy_row)
        self.synergies.append(player_synergies)

    # checks that populated section of the matrix is triangular
    def format_synergy(self, player_i: int):
        self.print_and_log(f'  Synergies for {self.players[player_i]}')

        for u_i in range(len(self.units)):
            something_to_print = False
            unit_line = f'{self.units[u_i].name:12s}: '
            for u_j, synergy in enumerate(self.synergies[player_i][u_i]):
                if synergy != 0:
                    something_to_print = True
                    unit_line += f' {self.units[u_j].name:12s}{synergy:5.2f} '
                    if u_j <= u_i:
                        self.print_and_log('NOTE, synergy matrix not triangular, possible error')
            if something_to_print:
                self.print_and_log(unit_line)

    def remove_least_valued_unit(self):
        least_value = 99999
        least_value_i = -1
        for unit in self.units:
            if least_value > sum(unit.bids):
                least_value = sum(unit.bids)
                least_value_i = unit.recruit_order

        for unit in self.units[least_value_i:]:
            unit.recruit_order -= 1

        self.print_and_log(f'Removing least valued: {self.units[least_value_i].name} {least_value/len(self.players)}')
        self.units.pop(least_value_i)
        for player_synergy in self.synergies:
            player_synergy.pop(least_value_i)
            for row in player_synergy:
                row.pop(least_value_i)

    # assign units in order of satisfaction, not recruitment
    def format_initial_assign(self):
        self.print_and_log('---Initial assignments---')

        team_sizes = [0] * len(self.players)
        team_sizes.append(len(self.units))  # all unassigned (team -1)

        for unit in self.units:
            unit.owner = -1

        while team_sizes[-1] > 0:  # unassigned units remain
            max_sat = -99999
            max_sat_unit = Unit('NULL', -1)
            max_sat_player = -1
            for unit in self.units:
                if unit.owner == -1:
                    for p, bid in enumerate(unit.bids):
                        sat = pricing.comp_sat(unit.bids, p)
                        if team_sizes[p] < self.max_team_size and max_sat < sat:
                            max_sat = sat
                            max_sat_unit = unit
                            max_sat_player = p

            team_sizes[max_sat_unit.owner] -= 1
            max_sat_unit.owner = max_sat_player
            team_sizes[max_sat_unit.owner] += 1
            self.print_and_log(f'{max_sat_unit.name:12s} to {max_sat_player} {self.players[max_sat_player]:12s}')

    def teams(self) -> List[List[Unit]]:
        teams = [[] for _ in self.players]

        for unit in self.units:
            teams[unit.owner].append(unit)
        return teams

    def format_teams(self):
        self.print_and_log('---Teams---')
        self.print_and_log(' '.join([f'{player:12s}' for player in self.players]))

        teams = self.teams()
        for i in range(self.max_team_size):
            self.print_and_log(' '.join([f'{(team[i].name[:12]):12s}' for team in teams]))

        self.print_and_log(' '.join([f'{price:5.2f}       ' for price in self.handicaps()]))

    # How player i values player j's team. No adjustments
    def value_matrix(self) -> Matrix:
        v_matrix = [([0] * len(self.players)) for _ in self.players]

        for unit in self.units:
            for valuer_row, bid in zip(v_matrix, unit.bids):
                valuer_row[unit.owner] += bid

        return v_matrix

    # Could avoid recalculating in some circumstances, but these are not common;
    # at minimum, when a unit is reassigned, need to check for synergy relationship with new teammates;
    # also when leaving a team; can't save from that unit's prior swap because other teammates may have changed.
    # Depends on synergy relationship graph density, but on tests with FE8:
    # 54993/55440 calls to synergy_matrix() required a recalculation, implying very few reassignments meet
    # the circumstances of having no former or current teammates as connected to any moving unit.
    # If no synergy relationships, much faster on FE6, but cannot conclude any speedup in general.
    # Could also only update rows/columns of affected players, but most time is all-player rotations
    def synergy_matrix(self) -> Matrix:
        s_matrix = [([0] * len(self.players)) for _ in self.players]

        teams = self.teams()
        for u_i in range(self.max_team_size):
            for u_j in range((u_i+1), self.max_team_size):
                for player_i, synergies in enumerate(self.synergies):
                    for player_j, team in enumerate(teams):
                        s_matrix[player_i][player_j] += synergies[team[u_i].recruit_order][team[u_j].recruit_order]

        return s_matrix

    def v_s_matrix(self) -> Matrix:
        v_matrix = self.value_matrix()
        s_matrix = self.synergy_matrix()
        for v_row, s_row in zip(v_matrix, s_matrix):
            for i in range(len(v_row)):
                v_row[i] += s_row[i]
                v_row[i] = max(0.0, v_row[i])  # team value should never be negative
        return v_matrix

    # Adjusted for synergy and redundancy
    def final_matrix(self) -> Matrix:
        return pricing.apply_redundancy(self.v_s_matrix(), self.bid_sums)

    def handicaps(self) -> List[float]:
        return pricing.pareto_prices(self.final_matrix())

    # Print matrix, comp_sat, handicaps, and matrix+sat after handicapping
    def format_value_matrices(self):
        self.print_and_log('           ' +
                           ' '.join([f'{player:10s}' for player in self.players]) +
                           ' Comparative satisfaction')

        def print_matrix(mat: Matrix, string: str):
            self.print_and_log('')
            self.print_and_log(string)
            for p, row in enumerate(mat):
                self.print_and_log(f'{self.players[p]:10s} ' +
                                   ' '.join([f' {value:6.2f}   ' for value in row]) +
                                   f'  {pricing.comp_sat(row, p):6.2f}')

        print_matrix(self.value_matrix(), 'Unadjusted value matrix')
        print_matrix(self.synergy_matrix(), 'Synergy')
        print_matrix(self.v_s_matrix(), 'Synergy adjusted')
        final_matrix = self.final_matrix()
        print_matrix(final_matrix, 'Redundancy adjusted')

        robustness = 0
        for p, row in enumerate(final_matrix):
            for i, value in enumerate(row):
                if p == i:
                    robustness += value

        self.print_and_log('')
        self.print_and_log(f'Average team robustness: {robustness/len(self.players):6.2f}')

        prices = self.handicaps()

        self.print_and_log('HANDICAPS: ' + ' '.join([f' {price:6.2f}   ' for price in prices]))
        self.print_and_log('')

        self.print_and_log('Handicap adjusted')
        for p, row in enumerate(final_matrix):
            self.print_and_log(f'{self.players[p]:10s} ' +
                               ' '.join([f' {value - price:6.2f}   ' for value, price in zip(row, prices)]) +
                               f'  {pricing.comp_sat(row, p) - pricing.comp_sat(prices, p):6.2f}')

    def get_score(self):
        return pricing.allocation_score(self.final_matrix(), 0.25)

    # try all swaps to improve score
    def improve_allocation_swaps(self) -> bool:
        current_score = self.get_score()
        swapped = False

        for u_i, unit_i in enumerate(self.units):
            for unit_j in self.units[u_i+1:]:
                if unit_i.owner != unit_j.owner:
                    unit_i.owner, unit_j.owner = unit_j.owner, unit_i.owner

                    if current_score < self.get_score():
                        current_score = self.get_score()
                        swapped = True
                        # Use name of owner before swap
                        self.print_and_log(f'Swapping {self.players[unit_j.owner]:12s} '
                                           f'{(unit_i.name[:12]):12s} <-> {(unit_j.name[:12]):12s} '
                                           f'{self.players[unit_i.owner]:12s}, '
                                           f'new score {current_score:7.3f}')
                    else:  # return units to owners
                        unit_i.owner, unit_j.owner = unit_j.owner, unit_i.owner
        return swapped

    # try all rotations (swaps of three or more) to improve score
    # iterate over rotations at the highest level,
    # skip branching tree if player at that level of recursion isn't trading
    # only full p rotations will cost much time

    # If this didn't rotate from rotations[test_until], only need to check until that point:
    # Complete one "lap" without any successful rotation, lap doesn't need to start at rotation[0]
    # Set last_rotation to index r whenever a rotation occurs to pass to next execution.
    def improve_allocation_rotate(self, test_until_i: int, rotations: List[Tuple[int]]) -> int:
        current_score = self.get_score()
        last_rotation_i = -1

        indices = [0]*len(self.players)  # of units being traded from 0~teamsize-1, set during recursive_rotate branch
        teams = self.teams()

        def recursive_rotate(p_i):
            nonlocal teams
            nonlocal current_score
            nonlocal last_rotation_i

            if p_i >= len(self.players):  # base case
                for p in trading_players:
                    teams[p][indices[p]].owner = rotation[p]  # p's unit goes to rotation[p]

                if current_score < self.get_score():
                    current_score = self.get_score()

                    self.print_and_log('')
                    self.print_and_log('Rotating:')
                    for p2 in trading_players:
                        self.print_and_log(f'{self.players[p2]:12s} -> '
                                           f'{(teams[p2][indices[p2]].name[:12]):12s} -> '
                                           f'{self.players[rotation[p2]]:12s}')
                    self.print_and_log(f'New score {current_score:7.3f}')
                    self.print_and_log('')

                    while self.improve_allocation_swaps():
                        pass
                    current_score = self.get_score()

                    teams = self.teams()
                    last_rotation_i = r_i
                else:
                    for p in trading_players:
                        teams[p][indices[p]].owner = p  # unrotate, if teams were updated rotates to new teams

            else:
                if p_i in trading_players:
                    for indices[p_i] in range(self.max_team_size):  # for each unit in the team
                        recursive_rotate(p_i + 1)
                else:  # don't branch, this player isn't trading in this rotation, go to next player
                    recursive_rotate(p_i + 1)

        for r_i, rotation in enumerate(rotations):
            if r_i > test_until_i and last_rotation_i < 0:
                self.print_and_log('Reached latest effected rotation of prior loop. Stopping rotation early.')
                return last_rotation_i

            trading_players = [p for p, r in enumerate(rotation) if p != r]
            self.print_and_log(f'{r_i:3d}/{len(rotations):3d}  '
                               f'Rotation {rotation}  '
                               f'Trading players {trading_players}')
            recursive_rotate(0)

        return last_rotation_i

    def load(self):
        # directories.txt contains paths as first word, subsequent words may be comments
        # 1st line is game directory, 2nd auction dir, subsequent are synergy filenames
        directories = [d[0] for d in misc.read_grid('directories.txt', str)]
        self.game_dir = directories[0]
        self.auct_dir = directories[1]

        self.units = [Unit(row[0], i) for i, row in enumerate(misc.read_grid(f'{self.auct_dir}units.txt', str))]
        self.players = misc.read_grid(f'{self.auct_dir}players.txt', str)[0]
        self.max_team_size = len(self.units) // len(self.players)
        bids = misc.read_grid(f'{self.auct_dir}bids.txt', float)
        misc.extend_array(bids, len(self.units), [0] * len(self.players))
        self.bid_sums = [0] * len(self.players)

        for unit, bid_row in zip(self.units, bids):
            # if fewer than max players, create dummy players from existing bids
            while len(bid_row) < len(self.players):
                bid_row.append(statistics.median(bid_row) * random.triangular(.8, 1.2))
            for i, bid in enumerate(bid_row):
                self.bid_sums[i] += bid
            unit.bids = bid_row

        self.synergies = []
        for player in self.players:
            try:
                next_synergies = misc.read_grid(f'{self.auct_dir}synergy_{player}.txt', float)
            except FileNotFoundError:
                self.set_median_synergy()
            else:
                misc.extend_array(next_synergies, len(self.units), [0] * len(self.units))
                for row in next_synergies:
                    misc.extend_array(row, len(self.units), 0)
                self.synergies.append(next_synergies)

    def run(self):
        self.load()

        if not os.path.exists(f'{self.auct_dir}output'):
            os.makedirs(f'{self.auct_dir}output')

        self.format_bids()
        self.write_logs('bids')

        for i, player in enumerate(self.players):
            self.format_synergy(i)
            self.write_logs(f'synergy_{player}')

        while len(self.units) % len(self.players) != 0:
            self.remove_least_valued_unit()
        self.write_logs('remove_units')

        self.format_initial_assign()
        self.write_logs('initial_assign')

        while self.improve_allocation_swaps():
            pass

        rotations = misc.one_loop_permutations(len(self.players))
        test_until = len(rotations)
        while test_until >= 0:
            test_until = self.improve_allocation_rotate(test_until, rotations)

        self.write_logs('reassignments')

        self.format_value_matrices()
        self.write_logs('matrices')
        self.format_teams()
        self.write_logs('teams')

if __name__ == '__main__':
    test = AuctionState()
    # cProfile.run('test.run()', sort='cumulative')
    test.run()


"""
"""

import phantom.rules as phantom
import json
from datetime import datetime, timedelta
results_dict = {}

# add information from the results_dict to the container
def add_results_to_container(container):
    cef = results_dict
    raw = {}
    success, message, artifact_id = phantom.add_artifact(
        container=container, raw_data=raw, cef_data=cef, label='aws',
        name='AWS SNS Message', severity='medium',
        identifier=None,
        artifact_type='aws')

    phantom.error("=== success/error status message ===")
    phantom.debug(success)
    phantom.error(message)
    return success

# parse and flatten the json to store in results_dict
def parse_json(d):
    for k, v in d.items():
        if isinstance(v, dict):
            parse_json(v)
        else:
            key = "{0}".format(k)
            value = "{0}".format(v)
            results_dict.update({key:value})

def on_start(container):
    import email
    email_body = phantom.collect2(container=container, datapath=['artifact:*.cef.bodyText'])
    phantom.error(email_body)
    phantom.debug('on_start() called')
    raw_email = json.loads(phantom.get_raw_data(container)).get('raw_email')
    b = email.message_from_string(raw_email)
    # parse the email to get the body of the email
    if b.is_multipart():
        email_message = b.get_payload()[0]
        for payload in b.get_payload():
            phantom.debug(payload.get_payload())
        for part in email_message.walk():
            payload = part.get_payload() #returns a bytes object
            payload = json.loads(payload, strict=False)
            phantom.error(payload)
            phantom.error("=== email payload ===")
            phantom.debug(payload)
            parse_json(payload)
    else:
        phantom.debug("=== not multipart ===")
        phantom.error(b.get_payload())
        payload = b.get_payload()
        parse_json(payload)

    phantom.error("=== results dict ===")
    phantom.debug(results_dict)
    add_results_to_container(container)
    return

def on_finish(container, summary):
    phantom.debug('on_finish() called')
    # This function is called after all actions are completed.
    # summary of all the action and/or all detals of actions
    # can be collected here.

    # summary_json = phantom.get_summary()
    # if 'result' in summary_json:
        # for action_result in summary_json['result']:
            # if 'action_run_id' in action_result:
                # action_results = phantom.get_action_results(action_run_id=action_result['action_run_id'], result_data=False, flatten=False)
                # phantom.debug(action_results)

    return


import itertools
import os
import uuid
from abc import ABC, abstractmethod
from typing import Any, List, Optional

import pinecone
from airbyte_cdk.destinations.vector_db_based import Embedder
from airbyte_cdk.models import ConfiguredAirbyteCatalog
from airbyte_cdk.models.airbyte_protocol import AirbyteLogMessage, AirbyteMessage, DestinationSyncMode, Level, Type
from destination_langchain.config import ChromaLocalIndexingModel, DocArrayHnswSearchIndexingModel, PineconeIndexingModel
from destination_langchain.document_processor import METADATA_RECORD_ID_FIELD, METADATA_STREAM_FIELD
from destination_langchain.measure_time import measure_time
from destination_langchain.utils import format_exception
from langchain.document_loaders.base import Document
from langchain.vectorstores import Chroma
from langchain.vectorstores.docarray import DocArrayHnswSearch

class Indexer(ABC):
    def __init__(self, config: Any, embedder: Embedder):
        self.config = config
        self.embedder = embedder
        pass

    def pre_sync(self, catalog: ConfiguredAirbyteCatalog):
        pass

    def post_sync(self) -> List[AirbyteMessage]:
        return []

    @abstractmethod
    def index(self, document_chunks: List[Document], delete_ids: List[str]):
        pass

    @abstractmethod
    def check(self) -> Optional[str]:
        pass

    @property
    def max_metadata_size(self) -> Optional[int]:
        return None

def chunks(iterable, batch_size):
    """A helper function to break an iterable into chunks of size batch_size."""
    it = iter(iterable)
    chunk = tuple(itertools.islice(it, batch_size))
    while chunk:
        yield chunk
        chunk = tuple(itertools.islice(it, batch_size))

# large enough to speed up processing, small enough to not hit pinecone request limits
PINECONE_BATCH_SIZE = 40

class PineconeIndexer(Indexer):
    config: PineconeIndexingModel

    def __init__(self, config: PineconeIndexingModel, embedder: Embedder):
        super().__init__(config, embedder)
        pinecone.init(api_key=config.pinecone_key, environment=config.pinecone_environment, threaded=True)
        self.pinecone_index = pinecone.Index(config.index, pool_threads=10)
        self.embed_fn = measure_time(self.embedder.embeddings.embed_documents)

    def pre_sync(self, catalog: ConfiguredAirbyteCatalog):
        index_description = pinecone.describe_index(self.config.index)
        self._pod_type = index_description.pod_type
        for stream in catalog.streams:
            if stream.destination_sync_mode == DestinationSyncMode.overwrite:
                self._delete_vectors({METADATA_STREAM_FIELD: stream.stream.name})

    def post_sync(self):
        return [AirbyteMessage(type=Type.LOG, log=AirbyteLogMessage(level=Level.WARN, message=self.embed_fn._get_stats()))]

    def _delete_vectors(self, filter):
        if self._pod_type == "starter":
            # Starter pod types have a maximum of 1000000 rows
            top_k = 10000
            self._delete_by_metadata(filter, top_k)
        else:
            self.pinecone_index.delete(filter=filter)

    def _delete_by_metadata(self, filter, top_k):
        zero_vector = [0.0] * self.embedder.embedding_dimensions
        query_result = self.pinecone_index.query(vector=zero_vector, filter=filter, top_k=top_k)
        vector_ids = [doc.id for doc in query_result.matches]
        if len(vector_ids) > 0:
            self.pinecone_index.delete(ids=vector_ids)

    def index(self, document_chunks, delete_ids):
        if len(delete_ids) > 0:
            self._delete_vectors({METADATA_RECORD_ID_FIELD: {"$in": delete_ids}})
        embedding_vectors = self.embed_fn([chunk.page_content for chunk in document_chunks])
        pinecone_docs = []
        for i in range(len(document_chunks)):
            chunk = document_chunks[i]
            metadata = chunk.metadata
            metadata["text"] = chunk.page_content
            pinecone_docs.append((str(uuid.uuid4()), embedding_vectors[i], metadata))
        async_results = [
            self.pinecone_index.upsert(vectors=ids_vectors_chunk, async_req=True, show_progress=False)
            for ids_vectors_chunk in chunks(pinecone_docs, batch_size=PINECONE_BATCH_SIZE)
        ]
        # Wait for and retrieve responses (this raises in case of error)
        [async_result.get() for async_result in async_results]

    def check(self) -> Optional[str]:
        try:
            description = pinecone.describe_index(self.config.index)
            actual_dimension = int(description.dimension)
            if actual_dimension != self.embedder.embedding_dimensions:
                return f"Your embedding configuration will produce vectors with dimension {self.embedder.embedding_dimensions:d}, but your index is configured with dimension {actual_dimension:d}. Make sure embedding and indexing configurations match."
        except Exception as e:
            return format_exception(e)
        return None

    @property
    def max_metadata_size(self) -> int:
        # leave some space for the text field
        return 40_960 - 10_000

class DocArrayHnswSearchIndexer(Indexer):
    config: DocArrayHnswSearchIndexingModel

    def __init__(self, config: DocArrayHnswSearchIndexingModel, embedder: Embedder):
        super().__init__(config, embedder)

    def _init_vectorstore(self):
        self.vectorstore = DocArrayHnswSearch.from_params(
            embedding=self.embedder.embeddings, work_dir=self.config.destination_path, n_dim=self.embedder.embedding_dimensions
        )

    def pre_sync(self, catalog: ConfiguredAirbyteCatalog):
        for stream in catalog.streams:
            if stream.destination_sync_mode != DestinationSyncMode.overwrite:
                raise Exception(
                    f"DocArrayHnswSearchIndexer only supports overwrite mode, got {stream.destination_sync_mode} for stream {stream.stream.name}"
                )
        for file in os.listdir(self.config.destination_path):
            os.remove(os.path.join(self.config.destination_path, file))
        self._init_vectorstore()

    def post_sync(self):
        return [AirbyteMessage(type=Type.LOG, log=AirbyteLogMessage(level=Level.WARN, message=self.index._get_stats()))]

    @measure_time
    def index(self, document_chunks, delete_ids: List[str]):
        # does not support deleting documents, always full refresh sync
        self.vectorstore.add_documents(document_chunks)

    def check(self) -> Optional[str]:
        try:
            self._init_vectorstore()
        except Exception as e:
            return format_exception(e)
        return None

class ChromaLocalIndexer(Indexer):
    config: ChromaLocalIndexingModel

    def __init__(self, config: ChromaLocalIndexingModel, embedder: Embedder):
        super().__init__(config, embedder)

    def _init_vectorstore(self):
        self.vectorstore = Chroma(
            collection_name=self.config.collection_name,
            embedding_function=self.embedder.embeddings,
            persist_directory=self.config.destination_path,
        )

    def pre_sync(self, catalog: ConfiguredAirbyteCatalog):
        self._init_vectorstore()
        for stream in catalog.streams:
            if stream.destination_sync_mode == DestinationSyncMode.overwrite:
                self.vectorstore._collection.delete(where={METADATA_STREAM_FIELD: {"$eq": stream.stream.name}})

    def index(self, document_chunks, delete_ids):
        for delete_in in delete_ids:
            self.vectorstore._collection.delete(where={METADATA_RECORD_ID_FIELD: {"$eq": delete_in}})
        for chunk in document_chunks:
            self._normalize_metadata(chunk)
        self.vectorstore.add_documents(document_chunks)

    def _normalize_metadata(self, document: Document):
        for key, value in document.metadata.items():
            # check bool separately because isinstance(True, int) == True
            if not isinstance(value, (str, float, int)) or isinstance(value, bool):
                document.metadata[key] = str(value)

    def check(self) -> Optional[str]:
        try:
            self._init_vectorstore()
            # try reading collections to make sure it works
            self.vectorstore._client.list_collections()
        except Exception as e:
            return format_exception(e)
        return None


#!/usr/bin/env python
"""
Entry point for stocksim api
"""
from flask import Flask
from flask_cors import CORS
from flask_restful import Api
from flask_jwt_extended import JWTManager
from guppy import hpy

# Local
from api import UserService, StockService
from controllers.UserController import UserController
from settings import JWT_SECRET_KEY

app = Flask(__name__)
cors = CORS(app, resources={r"*": {"origins": "*"}})

app.config["JWT_SECRET_KEY"] = JWT_SECRET_KEY
app.config["JWT_BLACKLIST_ENABLED"] = True
app.config["JWT_BLACKLIST_TOKEN_CHECKS"] = ["access", "refresh"]

blacklist = set()
jwt = JWTManager(app)
api = Api(app)

# guppy
h = hpy()
print(h.heap())

# called every time client tries to access a secure endpoint
@jwt.token_in_blacklist_loader
def check_if_token_in_blacklist(decrypted_token):
    jti = decrypted_token["jti"]
    return UserController.tokenIsBlacklisted(jti)

# api urls
LOCAL_URL = 'http://localhost:5000'
API_LOGIN = '/login/submit'
API_REGISTER = '/registration'
API_WATCHLIST_ADD = "/watch/add"
API_WATCHLIST_REMOVE = "/watch/remove"
API_REFRESH = "/token/refresh"
API_LOGOUT = "/logout/access"
API_LOGOUT_REFRESH = "/logout/refresh"
API_STOCK_PURCHASE_SELL = "/stock/purchase"
API_STOCK = "/stock"
API_USER_INFO = "/user/info"
ACCESS_COOKIE = 'user_access'
REFRESH_COOKIE = 'user_refresh'
USER_COOKIE = 'user_info'

# User Service
api.add_resource(UserService.UserRegistration, API_REGISTER)
api.add_resource(UserService.UserLogin, API_LOGIN)
api.add_resource(UserService.UserLogoutAccess, API_LOGOUT)
api.add_resource(UserService.UserLogoutRefresh, API_LOGOUT_REFRESH)
api.add_resource(UserService.TokenRefresh, API_REFRESH)
api.add_resource(UserService.UserInfo, API_USER_INFO)
# Stock Service
api.add_resource(StockService.GetStock, API_STOCK)
api.add_resource(StockService.PurchaseAsset, API_STOCK_PURCHASE_SELL)
api.add_resource(StockService.WatchAsset, API_WATCHLIST_ADD)
api.add_resource(StockService.RemoveWatchedAsset, API_WATCHLIST_REMOVE)

if __name__ == "__main__":
    # app.run(host='0.0.0.0')    # Dockerized
    app.run(debug=True)    # Debug