from unittest import TestCase

import torch

from code2seq.utils.training import cut_encoded_contexts

class TestTrainingUtils(TestCase):
    def test_cut_encoded_contexts(self):
        units = 10
        mask_value = -1
        batch_size = 5
        contexts_per_label = list(range(1, batch_size + 1))
        max_context_len = max(contexts_per_label)

        encoded_contexts = torch.cat([torch.full((i, units), i, dtype=torch.float) for i in contexts_per_label])

        def create_true_batch(fill_value: int, counts: int, size: int) -> torch.tensor:
            return torch.cat(
                [torch.full((1, counts, units), fill_value, dtype=torch.float), torch.zeros((1, size - counts, units))],
                dim=1,
            )

        def create_batch_mask(counts: int, size: int) -> torch.tensor:
            return torch.cat(
                [torch.zeros(1, counts), torch.full((1, size - counts), mask_value, dtype=torch.float)], dim=1
            )

        true_batched_context = torch.cat([create_true_batch(i, i, max_context_len) for i in contexts_per_label])
        true_attention_mask = torch.cat([create_batch_mask(i, max_context_len) for i in contexts_per_label])

        batched_context, attention_mask = cut_encoded_contexts(encoded_contexts, contexts_per_label, mask_value)

        torch.testing.assert_allclose(batched_context, true_batched_context)
        torch.testing.assert_allclose(attention_mask, true_attention_mask)


import numpy as np
from scipy.spatial.distance import pdist, squareform
import scipy.signal as ss
from collections import defaultdict
import warnings

class SceneGraph(object):
    def __init__(self, edge_radius, nodes=None, adj_cube=np.zeros((1, 0, 0)), t=0):
        self.edge_radius = edge_radius
        self.nodes = nodes
        if nodes is None:
            self.nodes = list()
        self.adj_cube = adj_cube
        self.current_t = t
        self.neigbors_via_edge_type_all_t = None

    @property
    def neigbors_via_edge_type(self):
        if self.neigbors_via_edge_type_all_t is None:
            self.neigbors_via_edge_type_all_t = self.get_neigbors_via_edge_type()
        return self.neigbors_via_edge_type_all_t

    def get_neigbors_via_edge_type(self, t=None):
        node_edges_and_neighbors = {node: defaultdict(set) for node in self.nodes}
        edge_types = defaultdict(list)
        if t is None:
            adj_mat = np.max(self.adj_cube, axis=0)
        else:
            adj_mat = self.adj_cube[t]
        for i, curr_node in enumerate(self.nodes):
            for j, curr_neighbor in enumerate(self.nodes):
                if adj_mat[i, j] == 1:
                    edge_type = self.get_edge_type(curr_node, curr_neighbor)
                    edge_types[curr_node].append(edge_type)
                    node_edges_and_neighbors[curr_node][edge_type].add(curr_neighbor)
        return node_edges_and_neighbors

    def get_num_edges(self, t=0):
        return np.sum(self.adj_cube[t]) // 2

    def get_index(self, node):
        return list(self.nodes).index(node)

    @staticmethod
    def get_edge_type(n1, n2):
        return '-'.join(sorted([str(n1), str(n2)]))

    @classmethod
    def create_from_temp_scene_dict(cls, scene_temp_dict, edge_radius, duration=1, t=0):
        """
        Construct a spatiotemporal graph from agent positions in a dataset.

        returns: sg: An aggregate SceneGraph of the dataset.
        """
        nodes = scene_temp_dict.keys()
        N = len(nodes)
        total_timesteps = duration

        position_cube = np.zeros((total_timesteps, N, 2))

        adj_cube = np.zeros((total_timesteps, N, N), dtype=np.int8)

        for node_idx, node in enumerate(nodes):
            position_cube[:, node_idx] = scene_temp_dict[node]

        agg_adj_matrix = np.zeros((N, N), dtype=np.int8)

        for timestep in range(position_cube.shape[0]):
            dists = squareform(pdist(position_cube[timestep], metric='euclidean'))

            # Put a 1 for all agent pairs which are closer than the edge_radius.
            # Can produce a warning as dists can be nan if no data for node is available.
            # This is accepted as nan <= x evaluates to False
            with warnings.catch_warnings():
                warnings.simplefilter("ignore")
                adj_matrix = (dists <= edge_radius).astype(np.int8)

            # Remove self-loops.
            np.fill_diagonal(adj_matrix, 0)

            agg_adj_matrix |= adj_matrix

            adj_cube[timestep] = adj_matrix

        sg = cls(edge_radius, nodes, adj_cube, t)
        return sg

    def get_edge_scaling(self, t, edge_addition_filter, edge_removal_filter, node=None):
        new_edges = np.minimum(ss.fftconvolve(self.adj_cube,
                                              np.reshape(edge_addition_filter, (-1, 1, 1)), 'full'), 1.)[t]
        old_edges = np.minimum(ss.fftconvolve(self.adj_cube,
                                              np.reshape(edge_removal_filter, (-1, 1, 1)), 'full'), 1.)[t]

        adj_mat = np.max(self.adj_cube, axis=0)

        edge_scaling = np.minimum(new_edges + old_edges, 1.)

        if node is None:
            return edge_scaling
        else:
            node_index = self.get_index(node)
            return edge_scaling[
                node_index, adj_mat[node_index] > 0.]  # We only want nodes which were connected at some point

    def get_adj_matrix(self):
        N = len(self.scene_dict)

        if N == 0:
            return None, list()

        active_idxs = list()

        pos_matrix = np.empty((N, 2))
        for idx, node in enumerate(self.scene_dict):
            #     x position   ,     y position
            (pos_matrix[idx][0], pos_matrix[idx][1]) = self.scene_dict[node]

            if np.asarray(self.scene_dict[node]).any():
                active_idxs.append(idx)

        dists = squareform(pdist(pos_matrix, metric='euclidean'))

        # Put a 1 for all agent pairs which are closer than the edge_radius.
        adj_matrix = (dists <= self.edge_radius).astype(int)
        assert len(adj_matrix.shape) == 2 and adj_matrix.shape == (N, N)

        # Remove self-loops.
        np.fill_diagonal(adj_matrix, 0)

        return adj_matrix, active_idxs

    def get_st_graph_info(self):
        """Construct a spatiotemporal graph from N agent positions.

        returns: nodes: An N-length list of ordered nodes.
                 edge_types: An N-size dict containing lists of edge-type string
                             names per node.
                 node_edges_and_neighbors: An N-size dict of edge-types per node,
                                           as well as which nodes are neighboring
                                           along edges of that type.
        """
        N = len(self.scene_dict)

        if N == 0:
            return list(), defaultdict(list), dict()

        nodes = list(self.scene_dict.keys())

        adj_matrix, active_idxs = self.get_adj_matrix()
        assert adj_matrix.shape == (N, N)

        node_edges_and_neighbors = {node: defaultdict(set) for node in nodes}
        edge_types = defaultdict(list)
        for i in active_idxs:
            curr_node = nodes[i]
            for j in active_idxs:
                curr_neighbor = nodes[j]
                if adj_matrix[i, j] == 1:
                    edge_type = self.get_edge_type(curr_node, curr_neighbor)
                    edge_types[curr_node].append(edge_type)

                    node_edges_and_neighbors[curr_node][edge_type].add(curr_neighbor)

        return nodes, edge_types, node_edges_and_neighbors


# In the third version of our hangman game, we allow for words with repeated letters. We accomplish this by
# introducing a new variable, "hidden_hit", that tracks the number of actual alpha characters we have successfully
# filled in

import os	#import os class to allow for clearing of terminal screen
import random

os.system('clear')

words = ["apron","alien","bacon","blade","cabin","curve","drone","ditch","elbow","epoxy","fancy","flyer","gecko","ghost","horse",
		 "human","jumbo","junky","klutz","knife","mango","mouse"]

hang_state = [
	"\t ______\n\t |   |\n\t |\n\t |\n\t |\n\t |\n\t |\n\toooo",
	"\t ______\n\t |   |\n\t |   O\n\t |\n\t |\n\t |\n\t |\n\toooo",
	"\t ______\n\t |   |\n\t |   O\n\t |   |\n\t |\n\t |\n\t |\n\toooo",
	"\t ______\n\t |   |\n\t |   O\n\t |  /|\n\t |\n\t |\n\t |\n\toooo",
	"\t ______\n\t |   |\n\t |   O\n\t |  /|\\\n\t |\n\t |\n\t |\n\toooo",
	"\t ______\n\t |   |\n\t |   O\n\t |  /|\\\n\t |   |\n\t |\n\t |\n\toooo",
	"\t ______\n\t |   |\n\t |   O\n\t |  /|\\\n\t |   |\n\t |  /\n\t |\n\toooo",
	"\t ______\n\t |   |\n\t |   O\n\t |  /|\\\n\t |   |\n\t |  / \\\n\t |\n\toooo"
]

print("Welcome to Hangman!")

hit = 0
hidden_hit = 0
miss = 0

word = list(words[random.randint(0,len(words) - 1)])		# list function converts string into array by character
word_build = []
guess_tracker = []

for x in range(0,len(word)):
	word_build.append("_")

while (hidden_hit < len(word)):
	guess = input("What letter do you guess? ")

	if guess in guess_tracker:
		print("You already guessed that letter. Please try again.")
		continue	# forgoes the remainder of the while loop

	elif guess in word:
		guess_tracker.append(guess)
		for x in range(0,len(word)):
			if(word[x] == guess):
				word_build[x] = guess
				hidden_hit += 1
		hit += 1

	else:
		guess_tracker.append(guess)
		miss += 1

	for x in word_build:
		print(x,end='')
	print("     Hit = " + str(hit) + "    Miss = " + str(miss) + "\n")

print("Congratulations! You win!")


# -*- coding: utf-8 -*-
# _______________________________________________________
# | File Name: sidecar_model.py                         |
# |                                                     |
# | Package Name: Python-Sidecar MODEL API              |
# |                                                     |
# | Version: 2.0                                        |
# |                                                     |
# | Sofatware: Openstack                                |
# |_____________________________________________________|
# | Copyright: 2016@nephoscale.com                      |
# |                                                     |
# | Author:  info@nephoscale.com                        |
# |_____________________________________________________|

#importing the packages
from oslo_config        import cfg
from oslo_log           import log
from oslo_db.sqlalchemy import models
from sqlalchemy.ext     import declarative
from sqlalchemy         import *
from sqlalchemy.sql     import select
from sqlalchemy         import Table, Column, Integer, String, MetaData, ForeignKey, DATETIME, Enum
from sidecar            import exception
from sqlalchemy.orm     import sessionmaker
from sqlalchemy.dialects.postgresql import UUID
try:
    import simplejson as json
except ImportError:
    import json
import sqlalchemy, ConfigParser, enum, uuid, datetime, collections

CONF = cfg.CONF
LOG = log.getLogger(__name__)

# READ THE CONNECTION VARIABLE
try:
    config_file = cfg.CONF.config_file[0]
    config = ConfigParser.ConfigParser()
    config.read(config_file)
    sql_connection = config.get('database', 'connection', '')
    LOG.info("Getting the db configuration and ding the connection.)")
except Exception as e:
    LOG.error(str(e))
    sql_connection = ''

class Evacuate():
    """
    # | Evacuate model
    """
    metadata = MetaData()
    engine   = create_engine(sql_connection, pool_recycle=3600)
    conn     = engine.connect()

    #Creating the tables
    evacuate_events = Table('evacuate_events', metadata,
        Column('id',                  String(100),       primary_key=True,  unique=True, nullable=False),  # Event id column
        Column('name',                String(100),       default='',        nullable=False),
        Column('event_status',        Enum('created', 'completed', 'running', 'failure', 'migrating'), default='created', nullable=True),
        Column('event_create_time',   DATETIME,         default='0000-00-00 00:00:00', nullable=False),
        Column('event_complete_time', DATETIME,         default='0000-00-00 00:00:00', nullable=True),
        Column('node_uuid',           Text),
        Column('vm_uuid_list',        Text),
        Column('extra',               Text)
    )

    #Creating a configuration table
    evacuation_log   = Table('evacuation_log', metadata,
         Column('id',                  Integer(),       primary_key=True,  unique=True, nullable=False),  # Log id column
         Column('hypervisor_name',     String(200),       default='',        unique=True, nullable=False),
         Column('down_since',          Float(),       default='0',        nullable=True),
         Column('evacuated',           Enum('True', 'False'), default='False', nullable=True),
         Column('event_id',            String(100),       default='',        nullable=False),
         Column('prev_time',           DATETIME,          default='0000-00-00 00:00:00', nullable=False),
         Column('event_creation_time', DATETIME,          default='0000-00-00 00:00:00', nullable=False)
    )

    metadata.create_all(engine)
    LOG.info("Created the tables.)")

    def createEvent(self, kw):
        """
        name createEvent
        Params: event data
        Return : Json data
        """

        #Setting the parameters for the event creation
        unique_id = uuid.uuid4().hex
        arg = {
            "id": unique_id,
            "name": kw['name'],
            "event_status": "created",
            "event_create_time": datetime.datetime.now(),
            "node_uuid": kw["node_uuid"],
            "vm_uuid_list": json.dumps(kw["vm_uuid_list"])
        }
        #Inserting the data
        ins = self.evacuate_events.insert().values(arg)
        result = self.conn.execute(ins)
        LOG.info("Event created with id " + str(unique_id))
        return unique_id

    def get_detail(self, uuid):
        """
        # | Function to get the detail of an event
        # |
        # | Arguments:
        # |  <uuid>: Id of the event
        # |
        # | Returns: Json
        """

        #Getting the detail of the event
        get_data_select = select([self.evacuate_events]).where(self.evacuate_events.c.id == uuid)
        get_data = self.conn.execute(get_data_select)
        LOG.info("Getting the event details")

        #Raise exception if no event is present else fetching the one
        if not get_data.rowcount:
            LOG.error("No event with id " + uuid + " found.")
            raise exception.NotFound("No event with id " + uuid + " found.")
        data = get_data.fetchone()
        result = collections.OrderedDict()
        result["id"]                  = uuid
        result["name"]                = data["name"]
        result["event_status"]        = data["event_status"]
        result["event_create_time"]   = data["event_create_time"]
        result["event_complete_time"] = data["event_complete_time"]
        result["node_uuid"]           = data["node_uuid"]
        result["vm_uuid_list"]        = None
        result['extra']               = None
        result['moredata']            = None
        result['predata']             = None

        # If the proper data is there
        # then convert them into json
        if data["vm_uuid_list"]:
            result["vm_uuid_list"] = json.loads(data["vm_uuid_list"])
        if data['extra']:
            result['extra'] = json.loads(data['extra'])

        return result

    def list_events(self, args={}):
        """
        # | Method to list the events
        # |
        # | Arguments: Distionary containg the flter values
        # |
        # | Returns Distionary
        """

        #Setting the allowed args for the serach
        allowed_args = [
            'id',
            'name',
            'event_status',
            'node_uuid',
            'event_create_time',
            'min_event_create_time',
            'max_event_create_time',
            'marker',
            'limit',
            'filter_out'
        ]
        valid_args = {}
        for arg in args:
            # | For each given argument
            # | If it matches with allowed argument
            # | Then treat it as valid arg
            if arg in allowed_args:
                valid_args[arg] = args[arg]

        # Okay Bow lets start our query builder
        get_event_list = select([self.evacuate_events])

        for key in valid_args:
            if type(valid_args[key])==bool:
                val = valid_args[key]
            else:
                val = valid_args[key].strip()

            if not val:
                continue;
            if key == "id":
                get_event_list = get_event_list.where(self.evacuate_events.c.id == val)
            if key == "name":
                get_event_list = get_event_list.where(self.evacuate_events.c.name.like('%' + val + '%'))
            if key == "event_status":
                get_event_list = get_event_list.where(self.evacuate_events.c.event_status.like('%' + val + '%'))
            if key == 'node_uuid':
                get_event_list = get_event_list.where(self.evacuate_events.c.node_uuid == val)
            if key == 'event_create_time':
                get_event_list = get_event_list.where(self.evacuate_events.c.event_create_time == val)
            if key == 'min_event_create_time':
                get_event_list = get_event_list.where(self.evacuate_events.c.event_create_time >= val)
            if key == 'max_event_create_time':
                get_event_list = get_event_list.where(self.evacuate_events.c.event_create_time <= val)
            if key == 'filter_out':
                get_event_list = select([self.evacuate_events]).where(not_(or_(self.evacuate_events.c.event_status == 'failure', self.evacuate_events.c.event_status == 'completed')))

        LOG.info("Created the query with filter options.")
        get_event_list = get_event_list.order_by(desc(self.evacuate_events.c.event_create_time))
        # As per the documentaion in
        # https://specs.openstack.org/openstack/api-wg/guidelines/pagination_filter_sort.html
        # we need to add pagination  only after the filtering. So lets just filter out it.
        #
        # Point to be noted, though it is a bad idea to fetch all the data from db (in worst case when
        # there is no filter option), for time being we have done this way. Later we need to use sqlAlchemy
        try:
            result = self.conn.execute(get_event_list)
        except Exception as e:
            LOG.error(str(e))
            return []

        #Getting the values are setting it in list
        event_list = []
        for row in result:
            event_data = collections.OrderedDict()
            event_data['id']                  = row['id']
            event_data['name']                = row['name']
            event_data['event_status']        = row['event_status']
            event_data['event_create_time']   = row['event_create_time']
            event_data['event_complete_time'] = row['event_complete_time']
            event_data['node_uuid']           = row['node_uuid']
            event_data['moredata']            =  False
            event_data['predata']             = True

            vm_uuid_list = []
            if row['vm_uuid_list']:
                vm_uuid_list = json.loads(row['vm_uuid_list'])
            event_data['vm_uuid_list']        = vm_uuid_list
            event_data['extra']               = row['extra']
            event_list.append(event_data)

        first_index = 0
        if 'marker' in valid_args:
            marker = valid_args['marker']
            if marker is not None:
                for (marker_index, event) in enumerate(event_list):
                    if event['id'] == marker:
                        # we start pagination after the marker
                        first_index = marker_index + 1
                        break
        limit = 10

        # Checking for the limit. If the given
        # Limit is not positive then, return emepty result
        if "limit" in valid_args:
            if not valid_args["limit"].isnumeric():
                return []
            if not valid_args["limit"] > 0:
                return []
            limit = valid_args["limit"].strip()
        limit = int(float(limit))
        catch_limit = int(first_index) + int(limit)

        #Adding the conditions to show previous or next links
        if limit > len(event_list):
            #no need to display the next link and previous link
            next_val = False
            prev_val = False

        elif first_index > limit:
            #need to display the previous link
            prev_val = True

            #Case in each individual page other tahn the first page
            if catch_limit < len(event_list):
                #need to display the next link
                next_val = True
            else:
                next_val = False
        else:
            #need to display the previous link as well as the next link
            next_val = True

            #No need to display the previous link in the first page
            if first_index != 0:
                prev_val = True
            else:
                prev_val = False

        #Getting the event list with limit
        event_list = event_list[first_index: catch_limit]

        #Updating the moredata and predata with values
        for i in range(0, len(event_list)):
            event_list[i]['moredata'] = next_val
            event_list[i]['predata'] = prev_val

        LOG.info("Sending back the result.")
        return event_list

    def update_event(self, event_id, data):
        """
        # | Method to update an events
        # |
        # | Arguments:
        # |     <uuid>: event id
        # |     <data>: Dictionary containg diffrent update sections
        # |
        # | Returns: None
        """

        #Getting the details of event using event id
        event_detail = self.get_detail(event_id)
        if "name" in data:
            # | If name is the parameter check for
            # | the conflict
            name_check = select([self.evacuate_events]).where(
                and_(
                    self.evacuate_events.c.name == data['name'],
                    self.evacuate_events.c.id != event_id
                ))
            name_exist = self.conn.execute(name_check).rowcount
            if name_exist:
                LOG.error("There is already an event named " + data['name'])
                raise exception.Conflict("There is already an event named " + data['name'])

        #Updating the event status
        if 'event_status' in data:
            if data['event_status'] == 'completed':
                data['event_complete_time'] = datetime.datetime.now()
            else:
                data['event_complete_time'] = '0000-00-00 00:00:00'

        if 'vm_uuid_list' in data:
            data['vm_uuid_list'] = json.dumps(data['vm_uuid_list'])

        if 'extra' in data:
            data['extra'] = json.dumps(data['extra'])

        #Updating the data
        update = self.evacuate_events.update().where(self.evacuate_events.c.id == event_id).values(data)
        self.conn.execute(update)
        LOG.info("Event is updated succesfully.")

    def delete_event(self, event_id):
        """
        # | Function to delete an event
        # |
        # | Arguments:
        # |     <event_id>: id of the event
        # |
        # | Returns: None
        """

        # | A vent can be deleted, only if it's status completed
        # | Otherwise by deleting it will make error
        event_detail = self.get_detail(event_id)
        if event_detail['name']:
            self.delete_log(event_detail['name'])
        #if event_detail['event_status'] != 'completed':
        #raise exception.Forbidden("Events with completed status only can be deleted.")
        query = self.evacuate_events.delete().where(self.evacuate_events.c.id == event_id)
        self.conn.execute(query)
        LOG.info("Event is deleted succesfully.")

    def createLog(self, kw):
        """
        # | Function to delete an event
        # |
        # | Arguments:
        # |     <kw>: dictionary with values
        # |
        # | Returns: None
        """

        #Setting the dictionary to insert
        arg = {
            "hypervisor_name": kw['hypervisor_name'],
            "down_since": kw['down_since'],
            "evacuated": "False",
            "event_id": kw['event_id'],
            "prev_time": kw['prev_time'],
            "event_creation_time": datetime.datetime.now()
        }

        #Inserting the data
        ins = self.evacuation_log.insert().values(arg)
        result = self.conn.execute(ins)
        LOG.info("Log is created succesfully.")
        return result

    def get_log_detail(self, name):
        """
        # | Function to get the detail of a log event
        # |
        # | Arguments:
        # |  <hypervisor_name>: Name of the hypervisor
        # |
        # | Returns: Json
        """

        #Searching the database and gettign the details
        get_data_select = select([self.evacuation_log]).where(self.evacuation_log.c.hypervisor_name == name)
        get_data = self.conn.execute(get_data_select)
        LOG.info("Got details of the log")

        #Checking the row count and returning the result
        if not get_data.rowcount:
            result = []
            LOG.error("No log entry with hypervisor name " + name + " found.")
            return result

        #Fecthing the detail from the table.
        data = get_data.fetchone()
        result = collections.OrderedDict()
        result["hypervisor_name"]     = name
        result["down_since"]          = data["down_since"]
        result["evacuated"]           = data["evacuated"]
        result["event_id"]            = data["event_id"]
        result["prev_time"]           = data["prev_time"]
        result["event_creation_time"] = data["event_creation_time"]
        LOG.info("Return back the results.")
        return result

    def list_log(self, args={}):
        """
        # | Method to list the event logs
        # |
        # | Arguments:
        # |   <args>: Dictionary
        # |
        # | Returns
        """

        # Okay Bow lets start our query builder
        get_log_list = select([self.evacuation_log])
        LOG.info("Created the query to get the list of logs.")
        get_log_list = get_log_list.order_by(desc(self.evacuation_log.c.event_creation_time))
        try:
            result = self.conn.execute(get_log_list)
        except Exception as e:
            LOG.error(str(e))
            return []

        #Getting the values are setting it in list
        log_list = []
        for row in result:
            log_data = collections.OrderedDict()
            log_data['id']                  = row['id']
            log_data['hypervisor_name']     = row['hypervisor_name']
            log_data['down_since']          = row['down_since']
            log_data['evacuated']           = row['evacuated']
            log_data['event_id']            = row['event_id']
            log_data['prev_time']           = row['prev_time']
            log_data['event_creation_time'] = row['event_creation_time']
            log_list.append(log_data)
        return log_list

    def update_log(self, hypervisor_name, data):
        """
        # | Method to update a log
        # |
        # | Arguments:
        # |     <uuid>: log id
        # |     <data>: Dictionary containg diffrent update sections
        # |
        # | Returns: None
        """
        #log_detail = self.get_log_detail(hypervisor_name)

        #Checking that hypervisor name is in the data
        if "hypervisor_name" in data:

            # | If hypervisor_name is the parameter check for
            # | the conflict
            name_check = select([self.evacuation_log]).where(self.evacuation_log.c.hypervisor_name == data['hypervisor_name'])
            name_exist = self.conn.execute(name_check).rowcount
            if name_exist:
                #Updating the data
                update = self.evacuation_log.update().where(self.evacuation_log.c.hypervisor_name == hypervisor_name).values(data)
                self.conn.execute(update)
                LOG.info("Log updated succesfully.")

    def delete_log(self, hypervisor_name):
        """
        # | Function to delete a log entry
        # |
        # | Arguments:
        # |     <hypervisor_name>: Name of the hypervisor for which the event is takign place
        # |
        # | Returns: None
        """

        #Setting the delete query
        query = self.evacuation_log.delete().where(self.evacuation_log.c.hypervisor_name == hypervisor_name)
        self.conn.execute(query)
        LOG.info("Log is deleted succesfully.")


import numpy as np
import os, pdb, random, math, cmath, time, datetime
from scipy.interpolate import RegularGridInterpolator, interp2d, griddata, RectBivariateSpline
from scipy.signal import convolve2d
from scipy.stats import multivariate_normal
from .location import Location, Observation, LocDelta
from .utils import dateLinspace, dateRange, getBox, getLatLon
from .roms import getROMSData, reshapeROMS
# from sas_utils/roms import getROMSData, reshapeROMS
import matplotlib.pyplot as plt
import matplotlib.ticker as tick

class World(object):

  """docstring for World"""
  def __init__(self, sci_type, scalar_field, current_u_field, current_v_field, x_ticks, y_ticks, t_ticks, lon_ticks, lat_ticks, cell_x_size, cell_y_size, bounds):
    self.science_variable_type = sci_type
    self.scalar_field = scalar_field
    self.current_u_field = current_u_field
    self.current_v_field = current_v_field

    self.x_ticks = x_ticks # km
    self.y_ticks = y_ticks # km
    self.t_ticks = t_ticks # Time (s) since the world began
    self.lon_ticks  = lon_ticks # Decimal Degrees
    self.lat_ticks = lat_ticks # Decimal Degrees
    self.cell_y_size = cell_y_size
    self.cell_x_size = cell_x_size

    self.bounds = bounds
    self.n_bound = bounds[0]
    self.s_bound = bounds[1]
    self.e_bound = bounds[2]
    self.w_bound = bounds[3]

  def __str__(self):
    return "X-axis: " + str(self.x_ticks) + "\nY-axis: " + str(self.y_ticks) + "\nWorld:\n" + str(self.scalar_field)

  def __repr__(self):
    return "World Class Object"

  def xy2latlon(self, query_xy):
    x2lon_ratio = (self.lon_ticks[1] - self.lon_ticks[0]) / (self.x_ticks[1] - self.x_ticks[0])
    y2lat_ratio = (self.lat_ticks[1] - self.lat_ticks[0]) / (self.y_ticks[1] - self.y_ticks[0])

    xy_reference = Location(xlon=self.x_ticks[0], ylat=self.y_ticks[0])
    latlon_reference = Location(xlon=self.lon_ticks[0], ylat=self.lat_ticks[0])

    dxdy = query_xy - xy_reference

    dlatdlon = LocDelta(d_ylat=dxdy.d_ylat*y2lat_ratio, d_xlon=dxdy.d_xlon*x2lon_ratio)

    return latlon_reference + dlatdlon

  def latlon2xy(self, query_latlon):
    lon2x_ratio = (self.x_ticks[1] - self.x_ticks[0]) / (self.lon_ticks[1] - self.lon_ticks[0])
    lat2y_ratio = (self.y_ticks[1] - self.y_ticks[0]) / (self.lat_ticks[1] - self.lat_ticks[0])

    xy_reference = Location(xlon=self.x_ticks[0], ylat=self.y_ticks[0])
    latlon_reference = Location(xlon=self.lon_ticks[0], ylat=self.lat_ticks[0])

    dlatdlon = query_latlon - latlon_reference

    dxdy = LocDelta(d_ylat=dlatdlon.d_ylat*lat2y_ratio, d_xlon=dlatdlon.d_xlon*lon2x_ratio)

    return xy_reference + dxdy

  def withinBounds(self, query_loc, loc_type='xy'):
    if loc_type == "xy":
      if query_loc.x < np.min(self.x_ticks):
        return False
      if query_loc.x > np.max(self.x_ticks):
        return False
      if query_loc.y < np.min(self.y_ticks):
        return False
      if query_loc.y > np.max(self.y_ticks):
        return False
      return True
    elif loc_type == "latlon":
      if query_loc.lon < np.min(self.lon_ticks):
        return False
      if query_loc.lon > np.max(self.lon_ticks):
        return False
      if query_loc.lat < np.min(self.lat_ticks):
        return False
      if query_loc.lat > np.max(self.lat_ticks):
        return False
      return True

  def makeObservations(self, query_locs, query_times, query_type='sci', loc_type='xy'):
    query_times = [min(time, self.t_ticks[-1]) for time in query_times]

    if loc_type == "xy":
      if query_type == 'sci':
        sci_interp = RegularGridInterpolator((self.x_ticks, self.y_ticks, self.t_ticks), self.scalar_field, fill_value=float('NaN'), bounds_error=False)
        return [Observation(query_loc, float(sci_interp((query_loc.x, query_loc.y, query_time))), query_time) for query_loc, query_time in zip(query_locs, query_times) if self.withinBounds(query_loc, loc_type=loc_type)]

      elif query_type == 'current':
        u_interp = RegularGridInterpolator((self.x_ticks, self.y_ticks, self.t_ticks), self.current_u_field, fill_value=float('NaN'), bounds_error=False)
        v_interp = RegularGridInterpolator((self.x_ticks, self.y_ticks, self.t_ticks), self.current_v_field, fill_value=float('NaN'), bounds_error=False)

        u_obs = [Observation(query_loc, float(u_interp((query_loc.x, query_loc.y, query_time))), query_time) for query_loc, query_time in zip(query_locs, query_times) if self.withinBounds(query_loc, loc_type=loc_type)]
        v_obs = [Observation(query_loc, float(v_interp((query_loc.x, query_loc.y, query_time))), query_time) for query_loc, query_time in zip(query_locs, query_times) if self.withinBounds(query_loc, loc_type=loc_type)]

        return u_obs, v_obs
    elif loc_type == "latlon":
      if query_type == 'sci':
        sci_interp = RegularGridInterpolator((self.lon_ticks, self.lat_ticks, self.t_ticks), self.scalar_field, fill_value=float('NaN'), bounds_error=False)
        return [Observation(query_loc, float(sci_interp((query_loc.lon, query_loc.lat, query_time))), query_time) for query_loc, query_time in zip(query_locs, query_times) if self.withinBounds(query_loc, loc_type=loc_type)]

      elif query_type == 'current':
        u_interp = RegularGridInterpolator((self.lon_ticks, self.lat_ticks, self.t_ticks), self.current_u_field, fill_value=float('NaN'), bounds_error=False)
        v_interp = RegularGridInterpolator((self.lon_ticks, self.lat_ticks, self.t_ticks), self.current_v_field, fill_value=float('NaN'), bounds_error=False)

        u_obs = [Observation(query_loc, float(u_interp((query_loc.lon, query_loc.lat, query_time))), query_time) for query_loc, query_time in zip(query_locs, query_times) if self.withinBounds(query_loc, loc_type=loc_type)]
        v_obs = [Observation(query_loc, float(v_interp((query_loc.lon, query_loc.lat, query_time))), query_time) for query_loc, query_time in zip(query_locs, query_times) if self.withinBounds(query_loc, loc_type=loc_type)]

        return u_obs, v_obs

  def getSnapshot(self, ss_time, snapshot_type='scalar_field'):
    time_dist = [abs(ss_time - x) for x in self.t_ticks]#
    snapshot_time_idx = time_dist.index(min(time_dist))

    if snapshot_type == 'scalar_field':
      return self.scalar_field[:,:,snapshot_time_idx]

    elif snapshot_type == 'current_u_field':
      return self.current_u_field[:,:,snapshot_time_idx]

    elif snapshot_type == 'current_v_field':
      return self.current_v_field[:,:,snapshot_time_idx]

  def getUVcurrent(self, loc, t, loc_type='xy'):
    u_snapshot = self.getSnapshot(t, 'current_u_field')
    v_snapshot = self.getSnapshot(t, 'current_v_field')

    if loc_type == "xy":
      u_interp = RegularGridInterpolator((self.x_ticks, self.y_ticks), u_snapshot, fill_value=0.0, bounds_error=False)
      v_interp = RegularGridInterpolator((self.x_ticks, self.y_ticks), v_snapshot, fill_value=0.0, bounds_error=False)

      current_u_current = u_interp((loc.x, loc.y))
      current_v_current = v_interp((loc.x, loc.y))

    elif loc_type == "latlon":
      u_interp = RegularGridInterpolator((self.lon_ticks, self.lat_ticks), u_snapshot, fill_value=0.0, bounds_error=False)
      v_interp = RegularGridInterpolator((self.lon_ticks, self.lat_ticks), v_snapshot, fill_value=0.0, bounds_error=False)

      current_u_current = u_interp((loc.lon, loc.lat))
      current_v_current = v_interp((loc.lon, loc.lat))

    return LocDelta(d_xlon = float(current_u_current), d_ylat = float(current_v_current))

  def draw(self, ax, block=True, show=False, cbar_max=None, cbar_min=None, quiver_stride=7, snapshot_time=None):

    if snapshot_time is None:
      ss_scalar_field = self.getSnapshot(self.t_ticks[0], 'scalar_field')
      ss_current_u_field = self.getSnapshot(self.t_ticks[0], 'current_u_field')
      ss_current_v_field = self.getSnapshot(self.t_ticks[0], 'current_v_field')
    else:
      ss_scalar_field = self.getSnapshot(snapshot_time, 'scalar_field')
      ss_current_u_field = self.getSnapshot(snapshot_time, 'current_u_field')
      ss_current_v_field = self.getSnapshot(snapshot_time, 'current_v_field')

    if cbar_min is None:
      cbar_min = np.min(ss_scalar_field)
    if cbar_max is None:
      cbar_max = np.max(ss_scalar_field)

    num_format  = '%.0f'
    formatter = tick.FormatStrFormatter(num_format)

    CS = plt.pcolor(self.x_ticks, self.y_ticks, ss_scalar_field.transpose(), cmap='Greys', vmin=cbar_min, vmax=cbar_max)

    quiver = plt.quiver(self.x_ticks[::quiver_stride], self.y_ticks[::quiver_stride], ss_current_u_field.transpose()[::quiver_stride, ::quiver_stride], ss_current_v_field.transpose()[::quiver_stride, ::quiver_stride])
    quiver_key = plt.quiverkey(quiver, 0.95, 1.05, 0.2, "0.2 m/s", labelpos='E', coordinates='axes')

    ax.get_xaxis().set_major_formatter(formatter)
    ax.get_yaxis().set_major_formatter(formatter)
    plt.ylim([np.min(self.x_ticks), np.max(self.x_ticks)])
    plt.xlim([np.min(self.y_ticks), np.max(self.y_ticks)])
    cbar = plt.colorbar(CS, format='%.1f')
    plt.title("Ground Truth World")
    plt.xlabel("X (km)")
    plt.ylabel("Y (km)")
    cbar.set_label(self.science_variable_type)
    ax.axis('scaled')

    if show:
      plt.show(block)

  def getRandomLocationXY(self):
    return Location(xlon=random.choice(self.x_ticks), ylat=random.choice(self.y_ticks))

  def getRandomLocationLatLon(self):
    return Location(xlon=random.choice(self.lon_ticks), ylat=random.choice(self.lat_ticks))

  @classmethod
  def roms(cls, datafile_path, xlen, ylen, center, feature='temperature', resolution=(0.1, 0.1)):

    # World bounds
    bounds = getBox(xlen=xlen, ylen=ylen, center=center)

    n_bound   = bounds[0]
    s_bound   = bounds[1]
    e_bound   = bounds[2]
    w_bound   = bounds[3]

    x_ticks   = np.arange(0.0, xlen+resolution[0], resolution[0])
    y_ticks   = np.arange(0.0, ylen+resolution[1], resolution[1])

    x_ticks = x_ticks - np.max(x_ticks)/2.
    y_ticks = y_ticks - np.max(y_ticks)/2.

    lon_ticks = np.linspace(w_bound, e_bound, len(x_ticks))
    lat_ticks = np.linspace(s_bound, n_bound, len(y_ticks))

    scalar_field, scalar_lat, scalar_lon, roms_t = getROMSData(datafile_path, feature)
    current_u, u_lat, u_lon, _ = getROMSData(datafile_path, 'u')
    current_v, v_lat, v_lon, _ = getROMSData(datafile_path, 'v')

    output_shape = (len(x_ticks), len(y_ticks), len(roms_t))

    scalar_field = reshapeROMS(scalar_field, scalar_lat, scalar_lon, bounds, output_shape)
    current_u = reshapeROMS(current_u, u_lat, u_lon, bounds, output_shape)
    current_v = reshapeROMS(current_v, v_lat, v_lon, bounds, output_shape)
    return cls(feature, scalar_field.data, current_u.data, current_v.data, x_ticks, y_ticks, roms_t, lon_ticks, lat_ticks, resolution[0], resolution[1], bounds)

  @classmethod
  def idealizedFront(cls, start_date, end_date, time_resolution, resolution, xlen, ylen):
    # script to create an undulated temperature front that propagates and changes orientation in time.

    ##################################################
    ### Parameters
    ##################################################

    theta_0 = random.random()*360.0 # initial orientation of front (in degrees)
    dtheta_dt = -45 # rate at which the front is rotating (in degrees per day)
    undulation_wavelength = 7 # wavelength of undulations on the front (in km)
    undulation_amplitude = 2 # undulation_amplitudelitude of the undulations;.
    wave_speed = 2.0 #2.0 # propagation speed of the undulations, in m/s.
    temp_cold = 10 # is the cold side temperature
    temp_warm = 15 # is the warm side temperature;
    noise = 2.
    current_magnitude = 0.2 # Current Magnitude in m/s
    omega = (wave_speed / 1000)

    # World bounds
    bounds = getBox(
      xlen  = xlen,
      ylen  = ylen,
      center  = Location(0.0,0.0),
    )

    width   = 0.5*xlen
    height    = 0.5*ylen
    x_ticks   = np.arange(-width, width+resolution[0], resolution[0])
    y_ticks   = np.arange(-height, height+resolution[1], resolution[1])

    x_ticks = x_ticks - np.max(x_ticks)/2.
    y_ticks = y_ticks - np.max(y_ticks)/2.

    lon_ticks = np.linspace(bounds[3], bounds[2], len(x_ticks))
    lat_ticks = np.linspace(bounds[1], bounds[0], len(y_ticks))

    if isinstance(time_resolution, float) or isinstance(time_resolution, int):
      t_ticks = dateLinspace(start_date, end_date, time_resolution)
    elif isinstance(time_resolution, datetime.timedelta):
      t_ticks = dateRange(start_date, end_date, time_resolution)

    t_ticks = np.array([(x-start_date).total_seconds() for x in t_ticks])

    xx, yy = np.meshgrid(x_ticks, y_ticks)

    theta = theta_0
    noise_kernel = np.ones((5,5)) * (1 / 25.)

    res_scalar_field = np.empty((len(x_ticks), len(y_ticks), len(t_ticks)))
    res_current_u_field = np.empty((len(x_ticks), len(y_ticks), len(t_ticks)))
    res_current_v_field = np.empty((len(x_ticks), len(y_ticks), len(t_ticks)))

    for t_idx, t in enumerate(t_ticks):
      theta = math.radians(theta_0 + dtheta_dt * t/(24*3600))
      theta = theta % (math.pi * 2)
      cos_theta = math.cos(theta)
      sin_theta = math.sin(theta)

      if theta <= 1*math.pi / 4 or theta > 7*math.pi/4: #Mode 0
        zz_final = sin_theta * (cos_theta*xx + sin_theta*yy) + cos_theta * undulation_amplitude * np.sin((cos_theta*xx + sin_theta * yy + omega * t) * (2*math.pi / undulation_wavelength)) - yy
        zz_final = zz_final > 0
      elif theta > 1*math.pi / 4 and theta <= 3*math.pi/4: #Mode 1
        zz_final = cos_theta * (cos_theta*xx + sin_theta*yy) - sin_theta * undulation_amplitude * np.sin((cos_theta*xx + sin_theta * yy + omega * t) * (2*math.pi / undulation_wavelength)) - xx
        zz_final = zz_final < 0
      elif theta > 3*math.pi / 4 and theta <= 5*math.pi/4: #Mode 2
        zz_final = sin_theta * (cos_theta*xx + sin_theta*yy) + cos_theta * undulation_amplitude * np.sin((cos_theta*xx + sin_theta * yy + omega * t) * (2*math.pi / undulation_wavelength)) - yy
        zz_final = zz_final < 0
      elif theta > 5*math.pi / 4 and theta <= 7*math.pi/4: #Mode 3
        zz_final = cos_theta * (cos_theta*xx + sin_theta*yy) - sin_theta * undulation_amplitude * np.sin((cos_theta*xx + sin_theta * yy + omega * t) * (2*math.pi / undulation_wavelength)) - xx
        zz_final = zz_final > 0

      zz_final = zz_final * (temp_warm - temp_cold) + temp_cold

      t_noise = noise * (np.random.random(zz_final.shape) - 0.5)

      scalar_field = convolve2d(zz_final+t_noise, noise_kernel, boundary='symm', mode='same')

      #current_u_field = current_magnitude * cos_theta * np.ones(scalar_field.shape)
      #current_v_field = current_magnitude * sin_theta * np.ones(scalar_field.shape)

      current_u_field = yy
      current_v_field = -1*xx

      current_u_field = current_magnitude * current_u_field / np.max(np.sqrt(current_u_field**2 + current_v_field**2))
      current_v_field = current_magnitude * current_v_field / np.max(np.sqrt(current_u_field**2 + current_v_field**2))

      res_scalar_field[:,:,t_idx] = scalar_field.transpose()
      res_current_u_field[:,:,t_idx] = current_u_field.transpose()
      res_current_v_field[:,:,t_idx] = current_v_field.transpose()

    return cls('temperature', res_scalar_field, res_current_u_field, res_current_v_field, x_ticks, y_ticks, t_ticks, lon_ticks, lat_ticks, resolution[0], resolution[1], bounds)

  def random(cls, start_date, end_date, time_resolution, world_resolution, bounds=None, num_generators=50):

    if bounds is not None:
      x_ticks = np.linspace(bounds[3], bounds[2], world_resolution[0])
      y_ticks = np.linspace(bounds[1], bounds[0], world_resolution[1])

    else:
      x_ticks = np.arange(0,world_resolution[0])
      y_ticks = np.arange(0,world_resolution[1])
      bounds = [world_resolution[1], 0, world_resolution[0], 0]

    if isinstance(time_resolution, float) or isinstance(time_resolution, int):
      t_ticks = dateLinspace(start_date, end_date, time_resolution)
    elif isinstance(time_resolution, datetime.timedelta):
      t_ticks = dateRange(start_date, end_date, time_resolution)

    t_ticks = np.array([(x-start_date).total_seconds() for x in t_ticks])

    # pdb.set_trace()
    yy, xx, tt = np.meshgrid(y_ticks, x_ticks, t_ticks)
    #xx, yy, tt = np.mgrid[x_ticks[0]:x_ticks[-1]:world_resolution[0]*1j, y_ticks[0]:y_ticks[-1]:world_resolution[1]*1j, t_ticks[0]:t_ticks[-1]:time_resolution*1j]

    pos = np.empty(xx.shape + (3,))
    pos[:, :, :, 0] = xx
    pos[:, :, :, 1] = yy
    pos[:, :, :, 2] = tt

    sigma_x = .075*(bounds[0] - bounds[1])
    sigma_y = .075*(bounds[2] - bounds[3])
    sigma_t = .075*(t_ticks[-1] - t_ticks[0])

    cov = np.eye(3) * np.array([sigma_x, sigma_y, sigma_t])

    res = np.zeros((len(x_ticks), len(y_ticks), len(t_ticks)))

    generators = [[random.random()*(bounds[2] - bounds[3]) + bounds[3], random.random()*(bounds[0] - bounds[1]) + bounds[1], random.random()*(t_ticks[-1] - t_ticks[0]) + t_ticks[0]] for ii in range(num_generators)]

    for generator_idx, generator in enumerate(generators):
      x_o = generator[0]
      y_o = generator[1]
      t_o = generator[2]
      generator_res = (1/(2*np.pi*sigma_x*sigma_y*sigma_t) * np.exp(-((xx-x_o)**2/(2*sigma_x**2) + (yy-y_o)**2/(2*sigma_y**2) + (tt-t_o)**2/(2*sigma_t**2))))
      res = res + generator_res

    res = res - np.min(res)
    res = res / np.max(res)

    return cls('temperature', res, x_ticks, y_ticks, t_ticks, resolution[0], resolution[1], bounds)

def main():

  # n_bound = 29.0
  # s_bound = 28.0
  # e_bound = -94.0
  # w_bound = -95.0

  # bounds = [n_bound, s_bound, e_bound, w_bound]

  # d1 = datetime.datetime(2018, 1, 1)
  # d2 = datetime.datetime(2018, 1, 2)
  # bounds = getBox(xlen = 20, ylen = 20, center = Location(0.0,0.0))

  # wd = World.idealizedFront(
  #   start_date      = d1,
  #   end_date      = d2,
  #   time_resolution   = 24,
  #   resolution      = (0.100, 0.100),
  #   xlen        = 15.,
  #   ylen        = 20.,
  # )
  # wd = World.random(d1, d2, 24, (100, 110), bounds=bounds, num_generators = 50)
  datafile_path = os.path.dirname(os.path.realpath(__file__)) + "/../data/roms_data/"
  datafile_name = "txla_roms/txla_hindcast_jun_1_2015.nc"

  wd = World.roms(datafile_path + datafile_name, 20, 20, Location(xlon=-94.25, ylat=28.25), feature='salt', resolution=(0.1, 0.1))

  print("Generating Figures")

  for t_idx, t in enumerate(wd.t_ticks):
    fig = plt.figure()
    plt.clf()
    plt.title(str(datetime.datetime.fromtimestamp(wd.t_ticks[t_idx])))
    img = plt.pcolor(wd.lon_ticks, wd.lat_ticks, wd.scalar_field[:, :, t_idx].transpose(), vmin=np.min(wd.scalar_field), vmax=np.max(wd.scalar_field))
    cbar = plt.colorbar(img)
    quiver_stride = 10
    plt.xticks(rotation=45)
    plt.quiver(wd.lon_ticks[::quiver_stride], wd.lat_ticks[::quiver_stride], wd.current_u_field[:, :, t_idx].transpose()[::quiver_stride, ::quiver_stride], wd.current_v_field[:, :, t_idx].transpose()[::quiver_stride, ::quiver_stride])
    fig.canvas.draw()
    # plt.show(block=False)
    filename = "../results/plt/world-%03d" % t_idx
    plt.savefig(filename, bbox_inches='tight')
  plt.close('all')

if __name__ == '__main__':
  main()


assignments = []

def assign_value(values, box, value):
    """
    Please use this function to update your values dictionary!
    Assigns a value to a given box. If it updates the board record it.
    """

    # Don't waste memory appending actions that don't actually change any values
    if values[box] == value:
        return values

    values[box] = value
    if len(value) == 1:
        assignments.append(values.copy())
    return values

def remove_value(values, box, remove_value):
    new_value = values[box]

    for char in remove_value:
        new_value = new_value.replace(char, '')

    return assign_value(values, box, new_value)

def cross(A, B):
    "Cross product of elements in A and elements in B."
    return [ a + b for a in A for b in B ]

ROWS  = 'ABCDEFGHI'
COLS  = '123456789'
BOXES = cross(ROWS, COLS)

ROW_UNITS = [ cross(r, COLS) for r in ROWS ]
COL_UNITS = [ cross(ROWS, c) for c in COLS ]
SQUARE_UNITS = [ cross(rs, cs) for rs in ('ABC','DEF','GHI') for cs in ('123','456','789') ]

DIAGONAL_UNIT1 = [ r + c for r, c in zip(ROWS, COLS) ]
DIAGONAL_UNIT2 = [ r + c for r, c in zip(ROWS, reversed(COLS)) ]
DIAGONAL_UNITS = [ DIAGONAL_UNIT1, DIAGONAL_UNIT2 ]

UNIT_LIST = ROW_UNITS + COL_UNITS + SQUARE_UNITS + DIAGONAL_UNITS
UNITS = dict( (box, [ unit for unit in UNIT_LIST if box in unit ]) for box in BOXES)
PEERS = dict( (box, set(sum(UNITS[box],[])) - set([box])) for box in BOXES)

def grid_values(grid):
    """
    Convert grid into a dict of {square: char} with '123456789' for empties.
    Args:
        grid(string) - A grid in string form.
    Returns:
        A grid in dictionary form
            Keys: The boxes, e.g., 'A1'
            Values: The value in each box, e.g., '8'. If the box has no value, then the value will be '123456789'.
    """
    values = [ cell if cell != '.' else '123456789' for cell in grid ]

    return dict(zip(BOXES, values))

def display(values):
    """
    Display the values as a 2-D grid.
    Args:
        values(dict): The sudoku in dictionary form
    """
    width = 1 + max( len(values[box]) for box in BOXES )

    def printable_row(row):
        digits = [ values[ row + col ].center(width) for col in COLS ]
        digits.insert(+3, '|') # Add first separator
        digits.insert(-3, '|') # Add last  separator
        return ''.join(digits)

    def horizontal_separator():
        item   = '-' * width
        group  = item * 3
        groups = [ group ] * 3
        return '+'.join(groups)

    rows = list(map(printable_row, ROWS))
    rows.insert(+3, horizontal_separator()) # Add first separator
    rows.insert(-3, horizontal_separator()) # Add last  separator

    board = "\n".join(rows)
    print(board)

def eliminate(values):
    """Eliminate values from peers of each box with a single value.

    Go through all the boxes, and whenever there is a box with a single value,
    eliminate this value from the set of values of all its peers.

    Args:
        values(dict): a dictionary of the form {'box_name': '123456789', ...}
    Returns:
        the values dictionary with the value eliminated from peers.
    """

    # Get a list of all solved boxes and their values
    solved_boxes = [ (box, value) for box, value in values.items() if len(value) == 1 ]

    # For every solved box
    for box, value in solved_boxes:
        # Remove the box's value from every peer of the box
        for peer in PEERS[box]:
            values = remove_value(values, peer, value)

    return values

def only_choice(values):
    """Finalize all values that are the only choice for a unit.

    Go through all the UNITS, and whenever there is a unit with a value
    that only fits in one box, assign the value to this box.

    Args:
        values(dict): a dictionary of the form {'box_name': '123456789', ...}
    Returns:
        the values dictionary with the values after filling in only choices.
    """

    all_digits = '123456789'

    # For each unit in unit list, check every digit
    for unit in UNIT_LIST:
        for digit in all_digits:
            # Find the boxes that have this digit as part of their value
            digit_occurrences = [ box for box in unit if digit in values[box] ]
            # If there is only one box with this digit as part of their value
            if len(digit_occurrences) == 1:
                # Assign this digit as the whole value of this box
                box = digit_occurrences[0]
                values = assign_value(values, box, digit)

    return values

def naked_twins(values):
    """Eliminate values using the naked twins strategy.
    Args:
        values(dict): a dictionary of the form {'box_name': '123456789', ...}
    Returns:
        the values dictionary with the naked twins eliminated from peers.
    """
    return naked_n_tuple(values, n=2)

def naked_triplets(values):
    """Eliminate values using the naked triplets strategy.
    Args:
        values(dict): a dictionary of the form {'box_name': '123456789', ...}
    Returns:
        the values dictionary with the naked triplets eliminated from peers.
    """
    return naked_n_tuple(values, n=3)

def naked_n_tuple(values, n):
    """Eliminate values using the naked n-tuple strategy.
    Args:
        values(dict): a dictionary of the form {'box_name': '123456789', ...}
    Returns:
        the values dictionary with the naked n-tuple eliminated from peers.
    """

    def find_tuples(unit):
        # Dictionary of the form {'27': ['G8', 'G9'] }
        # The key is the box value
        # The value is a list of boxes that have the same value
        occurrences = {}

        # Get the boxes that should be added to the occurrences dict
        candidate_boxes = [ (box, values[box]) for box in unit if len(values[box]) == n ]

        # For every box, add it to the occurrences dict
        for box, value in candidate_boxes:
            occurrence_list = occurrences.get(value, [])
            occurrence_list = occurrence_list + [ box ]
            occurrences[value] = occurrence_list

        # Return dictionary of the form {'27': ('G8', 'G9') }
        # The key is the box value
        # The value is a tuple of `n` boxes that have the same value
        return dict( (value, tuple(boxes)) for value, boxes in occurrences.items() if len(boxes) == n )

    # Find all instances of naked n-tuples in all units
    for unit in UNIT_LIST:
        for value, n_tuple in find_tuples(unit).items():
            # Eliminate the naked n-tuples as possibilities for their peers
            for box in unit:
                if not box in n_tuple:
                    values = remove_value(values, box, value)

    return values

def reduce_puzzle(values):
    halt = False

    # Function for counting boxes with `value_count` number of values
    def count_boxes(values, value_count=1):
        return len([ box for box, value in values.items() if len(value) == value_count ])

    while not halt:
        # Check how many boxes have a determined value
        solved_values_before = count_boxes(values)

        # Use the Eliminate Strategy
        values = eliminate(values)

        # Use the Only Choice Strategy
        values = only_choice(values)

        # Use the Naked Twins Stategy
        values = naked_twins(values)

        # Use the Naked Triplets Stategy
        values = naked_triplets(values)

        # Check how many boxes have a determined value, to compare
        solved_values_after = count_boxes(values)

        # If no new values were added, stop the loop
        halt = solved_values_before == solved_values_after

        # Sanity check, return False if there is a box with zero available values
        if count_boxes(values, value_count=0):
            return False

    return values

def search(values):
    """Using depth-first search and propagation, create a search tree and solve the sudoku.
    Args:
        values(dict): a dictionary of the form {'box_name': '123456789', ...}
    Returns:
        the values dictionary with the naked twins eliminated from PEERS.
    """

    # Reduce the puzzle the search space by enforcing constraints
    values = reduce_puzzle(values)

    # If the solution is invalid, return False
    if values is False:
        return False

    # If all boxes are solved, return the values
    if all(len(values[box]) == 1 for box in BOXES):
        return values

    # Choose one of the unfilled squares with the fewest possibilities
    unsolved_values = [ item for item in values.items() if len(item[1]) > 1 ]
    box, choices = min(unsolved_values, key=lambda item: len(item[1]))

    # For every possibile value of box
    for value in choices:
        # Create a new sudoku game by picking that value for the box
        new_values = values.copy()
        new_values[box] = value

        # Recursively search the game with picked value
        solution = search(new_values)

        # If picked value yelds a solution
        # Return that solution
        if solution:
            return solution

def solve(grid):
    """
    Find the solution to a Sudoku grid.
    Args:
        grid(string): a string representing a sudoku grid.
            Example: '2.............62....1....7...6..8...3...9...7...6..4...4....8....52.............3'
    Returns:
        The dictionary representation of the final sudoku grid. False if no solution exists.
    """

    # Parse grind string into a sudoku grid dictionary representation
    sudoku = grid_values(grid)

    # Solve the sudoku by searching for a solution
    solution = search(sudoku)

    return solution

if __name__ == '__main__':
    diag_sudoku_grid = '2.............62....1....7...6..8...3...9...7...6..4...4....8....52.............3'
    display(solve(diag_sudoku_grid))

    try:
        from visualize import visualize_assignments
        visualize_assignments(assignments)

    except SystemExit:
        pass
    except:
        print('We could not visualize your board due to a pygame issue. Not a problem! It is not a requirement.')


#Declare a main method
def main():
     #Declare an empty string for file name
     fileName = " "

     while True:
          try:
               #prompt the user to enter a file name
               fileName = input("\nInput a file name:  ")
               #open the file
               inFile = open(fileName , "r+")
               break

          #block will run if the user enters an invalid file name
          except IOError:
               print("File could not be found.")

     #function call to retrieve the number of times each word occurs in text file
     print("Here is the number of times each word occurs in the text file",
           "\n",countWords(fileName))

#declare a count words method to return a dictionary of the
#number of word occurences
def countWords(fileName):
     output_dictionary = {}
     #open the inputFile
     inputFile = open (fileName , "r+")

     #use a for loop to traverse each single line
     for line in inputFile:
          #split the line into a list of words
          words = line.split()
          #by default, each word count will start at 1
          default_count = 1

          #use a for loop to traverse each single word in a line of words
          for single_word in words:
               #convert the case of all words to lower case
               single_word = ConvCase(single_word)

               #if the single word is in the dictionary
               if single_word in output_dictionary:
                    #then increment its word count by 1
                    output_dictionary[single_word] +=1
               #otherwise, set it to the default word count
               else:
                  output_dictionary[single_word] = default_count

     #close the inputFile and return the dictionary
     inputFile.close()
     return output_dictionary

#funtion call to convert the case of all words to lower case
def ConvCase(single_word):
     output_word = ""
     #use a for loop to traverse each word
     for char in single_word:
          #if the character is an alpha character, then append it to the word
          if char.isalpha():
               output_word+=char
     #return the word in lower case
     return output_word.lower()

main()


from django.urls import path
from . import views
app_name = 'polls'
urlpatterns = [
    path('', views.index, name='index'),
    path('<int:question_id>/', views.detail, name='detail'),
    path('<int:question_id>/results/', views.results, name='results'),
    path('<int:question_id>/vote/', views.vote, name='vote'),
    path('create_form', views.create_form, name='create_form'),
    path('create', views.create, name='create'),
    path('success_saved', views.success_saved, name='success_saved'),
    path('<int:question_id>/update', views.Update.as_view(), name='update'),
    path('<int:question_id>/delete', views.Delete.as_view(), name='delete'),
    path('<int:choice_id>/update_choice', views.ChoiceUpdateView.as_view(), name='update_choice'),
    path('create_choice', views.ChoiceCreateView, name='create_choice'),
    path('<int:choice_id>/delete_choice', views.ChoiceDeleteView.as_view(), name='delete_choice'),
]


lang_list = [
('af','Afrikaans'),
('ar','Arabic'),
('bg','Bulgarian'),
('bn','Bangla'),
('bs','Bosnian'),
('ca','Catalan'),
('cs','Czech'),
('cy','Welsh'),
('da','Danish'),
('de','German'),
('el','Greek'),
('en','English'),
('es','Spanish'),
('et','Estonian'),
('fa','Persian'),
('fi','Finnish'),
('fil','Filipino'),
('fj','Fijian'),
('fr','French'),
('he','Hebrew'),
('hi','Hindi'),
('hr','Croatian'),
('ht','Haitian Creole'),
('hu','Hungarian'),
('id','Indonesian'),
('is','Icelandic'),
('it','Italian'),
('ja','Japanese'),
('ko','Korean'),
('lt','Lithuanian'),
('lv','Latvian'),
('mg','Malagasy'),
('ms','Malay'),
('mt','Maltese'),
('mww','Hmong Daw'),
('nb','Norwegian'),
('nl','Dutch'),
('otq','Querétaro Otomi'),
('pl','Polish'),
('pt','Portuguese'),
('ro','Romanian'),
('ru','Russian'),
('sk','Slovak'),
('sl','Slovenian'),
('sm','Samoan'),
('sr-Cyrl','Serbian (Cyrillic)'),
('sr-Latn','Serbian (Latin)'),
('sv','Swedish'),
('sw','Kiswahili'),
('ta','Tamil'),
('th','Thai'),
('tlh','Klingon'),
('to','Tongan'),
('tr','Turkish'),
('ty','Tahitian'),
('uk','Ukrainian'),
('ur','Urdu'),
('vi','Vietnamese'),
('yua','Yucatec Maya'),
('yue','Cantonese (Traditional)'),
('zh-Hans','Chinese Simplified'),
('zh-Hant','Chinese Traditional')
]

ocr_lang_list = [
('ar','Arabic'),
('cs','Czech'),
('da','Danish'),
('de','German'),
('el','Greek'),
('en','English'),
('es','Spanish'),
('fi','Finnish'),
('fr','French'),
('hu','Hungarian'),
('it','Italian'),
('ja','Japanese'),
('ko','Korean'),
('nb','Norwegian'),
('nl','Dutch'),
('pl','Polish'),
('pt','Portuguese,'),
('ro','Romanian'),
('ru','Russian'),
('sk','Slovak'),
('sr-Cyrl','SerbianCyrillic'),
('sr-Latn','SerbianLatin'),
('sv','Swedish'),
('tr','Turkish'),
('zh-Hans','ChineseSimplified'),
('zh-Hant','ChineseTraditional')
]


import json
import keras
import numpy as np
from keras.layers import Layer
from keras import backend as K

class VariableConnections(Layer):
    def __init__(self,drop_prob=0.25, **kwargs):
        self.drop_prob = drop_prob
        super(VariableConnections, self).__init__(**kwargs)

    def build(self, input_shape):
        # Create a trainable weight variable for this layer.
        x = np.random.choice([1,0], size=input_shape[1:], p=[1-self.drop_prob, self.drop_prob])
        self.kernel = K.cast(x,dtype='float32')
        super(VariableConnections, self).build(input_shape)

    def call(self, x):
        return x * self.kernel

    def compute_output_shape(self, input_shape):
        return input_shape

class DropWeights(keras.callbacks.Callback):
    def __init__(self,rate=.05):
        super(DropWeights,self).__init__()
        self.masks = {}
        self.rate = rate
        self.before = None

    def on_train_begin(self, logs={}):
        count = 0
        for layer in self.model.layers:
            params = layer.get_weights()
            if 'locally' in layer.name:
                name = 'layer_'+str(count)

                weights = params[0]
                bias = params[1]

                mask = np.random.uniform(size=weights.shape)
                mask = mask > self.rate
                self.masks[name] = mask

                weights = weights * self.masks[name]
                self.model.layers[count].set_weights([weights,bias])
            count += 1
        return

    def on_train_end(self, logs={}):
        count = 0
        for layer in self.model.layers:
            params = layer.get_weights()
            if 'locally' in layer.name:
                name = 'layer_' + str(count)

                bias = params[1]
                weights = params[0]

                weights = weights * self.masks[name]
                self.model.layers[count].set_weights([weights,bias])
            count += 1
        return

    def on_batch_begin(self, batch, logs={}):
        count = 0
        for layer in self.model.layers:
            params = layer.get_weights()
            if 'locally' in layer.name:
                name = 'layer_' + str(count)

                bias = params[1]
                weights = params[0]

                weights = weights * self.masks[name]
                self.model.layers[count].set_weights([weights,bias])
            count += 1
        return

    def on_batch_end(self, batch, logs={}):
        '''
        count = 0
        after = None
        for layer in self.model.layers:
            params = layer.get_weights()
            if params != []:
                if count == 0:
                    print "after",params[0][0][0]
                    after = params[0][0][0]
            count += 1
        '''
        return


Category = input('Category: ')
product_url = 'https://www.supremenewyork.com/shop/all/%s'%(Category)
product_title = input('Name of product (must be official name): ')
name = input('Full Name: ')
email = input('E-mail: ')
phone_number = input('Phone number: ')
adress = input('Adress: ')
city = input('City: ')
zip_code = input("Zip code: ")
ccinfo = input('CC number: ')
ccmonth = input('CC month: ')
ccyear = input('CC year(1 is 2019, 2 is 2020 etc): ')
cvv = input('CVV: ')

keys = {
    "product_title": product_title,
    "product_url": product_url,
    "name": name,
    "email": email,
    "phone_number": phone_number,
    "adress": adress,
    "city": city,
    "zip": zip_code,
    "ccinfo": ccinfo,
    "ccmonth": ccmonth,
    "ccyear": ccyear,
    "CVV": cvv
}


#!/usr/bin/env python
# coding: utf-8

import sys
import numpy as np
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt

df = pd.read_csv("UserExpenses.csv")
sex_dummy = pd.get_dummies(df['Sex'])
df = pd.concat([df, sex_dummy], axis=1)
df = df.drop(['Sex'], axis=1)
student_dummy = pd.get_dummies(df['Student'])
df = pd.concat([df, student_dummy], axis=1)

df.rename(columns={'No': 'Professional',
             'Yes': 'Students'}, inplace=True)

df = df.drop(['Student'], axis=1)

country_dummy = pd.get_dummies(df['Country'])

df = pd.concat([df, country_dummy], axis=1)

df = df.drop(['Country'], axis=1)

month_dummy = pd.get_dummies(df['Month'])

df = pd.concat([df, month_dummy], axis=1)

df = df.drop(['Month'], axis=1)

from sklearn.model_selection import train_test_split

X = df[['primaryIncome', 'Age', 'female', 'male',
   'Professional','Students','Canada',
   'England','India','United States',
   'April', 'February', 'January', 'June', 'March', 'May']]

y = df['Total_Expenses']

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.4)

from sklearn.linear_model import LinearRegression
lm = LinearRegression()
lm = lm.fit(X_train,y_train)

coeff_df = pd.DataFrame(lm.coef_,X.columns,columns=['Coefficient'])

predictions = lm.predict(X_test)

df["Total_Expenses"]=np.log(df['Total_Expenses'])

coeff_df = pd.DataFrame(lm.coef_,X.columns,columns=['Coefficient'])

y = df['Total_Expenses']

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.4)

from sklearn.linear_model import LinearRegression
lm = LinearRegression()
lm = lm.fit(X_train,y_train)
coeff_df = pd.DataFrame(lm.coef_,X.columns,columns=['Coefficient'])

predictions = lm.predict(X_test)

dfnew = pd.read_csv(sys.argv[1])
#print(sys.argv[1])
TotalExp = lm.predict(dfnew)*100
print(TotalExp)


#!/usr/bin/env python
"""QuTiP: The Quantum Toolbox in Python

QuTiP is open-source software for simulating the dynamics of closed and open
quantum systems. The QuTiP library depends on the excellent Numpy, Scipy, and
Cython numerical packages. In addition, graphical output is provided by
Matplotlib.  QuTiP aims to provide user-friendly and efficient numerical
simulations of a wide variety of quantum mechanical problems, including those
with Hamiltonians and/or collapse operators with arbitrary time-dependence,
commonly found in a wide range of physics applications. QuTiP is freely
available for use and/or modification on all common platforms. Being free of
any licensing fees, QuTiP is ideal for exploring quantum mechanics in research
as well as in the classroom.
"""

DOCLINES = __doc__.split('\n')

CLASSIFIERS = """\
Development Status :: 4 - Beta
Intended Audience :: Science/Research
License :: OSI Approved :: BSD License
Programming Language :: Python
Programming Language :: Python :: 3
Topic :: Scientific/Engineering
Operating System :: MacOS
Operating System :: POSIX
Operating System :: Unix
Operating System :: Microsoft :: Windows
"""

# import statements
import os
import sys
# The following is required to get unit tests up and running.
# If the user doesn't have, then that's OK, we'll just skip unit tests.
try:
    from setuptools import setup, Extension
    TEST_SUITE = 'nose.collector'
    TESTS_REQUIRE = ['nose']
    EXTRA_KWARGS = {
        'test_suite': TEST_SUITE,
        'tests_require': TESTS_REQUIRE
    }
except:
    from distutils.core import setup
    from distutils.extension import Extension
    EXTRA_KWARGS = {}

try:
    import numpy as np
except:
    np = None

from Cython.Build import cythonize
from Cython.Distutils import build_ext

# all information about QuTiP goes here
MAJOR = 4
MINOR = 2
MICRO = 0
ISRELEASED = False
VERSION = '%d.%d.%d' % (MAJOR, MINOR, MICRO)
REQUIRES = ['numpy (>=1.8)', 'scipy (>=0.15)', 'cython (>=0.21)']
INSTALL_REQUIRES = ['numpy>=1.8', 'scipy>=0.15', 'cython>=0.21']
PACKAGES = ['qutip', 'qutip/ui', 'qutip/cy', 'qutip/cy/src',
            'qutip/qip', 'qutip/qip/models',
            'qutip/qip/algorithms', 'qutip/control', 'qutip/nonmarkov',
            'qutip/_mkl', 'qutip/tests', 'qutip/legacy',
            'qutip/cy/openmp', 'qutip/cy/openmp/src']
PACKAGE_DATA = {
    '.': ['README.md', 'LICENSE.txt'],
    'qutip': ['configspec.ini'],
    'qutip/tests': ['*.ini'],
    'qutip/cy': ['*.pxi', '*.pxd', '*.pyx'],
    'qutip/cy/src': ['*.cpp', '*.hpp'],
    'qutip/control': ['*.pyx'],
    'qutip/cy/openmp': ['*.pxd', '*.pyx'],
    'qutip/cy/openmp/src': ['*.cpp', '*.hpp']
}
# If we're missing numpy, exclude import directories until we can
# figure them out properly.
INCLUDE_DIRS = [np.get_include()] if np is not None else []
# ajgpitch Mar 2017:
# This HEADERS did not work, but I will leave it in anyway, as it is supposed to.
# I had to do the nasty thing with PACKAGES and PACKAGE_DATA above.
HEADERS = ['qutip/cy/src/zspmv.hpp', 'qutip/cy/openmp/src/zspmv_openmp.hpp']
NAME = "qutip"
AUTHOR = ("Alexander Pitchford, Paul D. Nation, Robert J. Johansson, "
          "Chris Granade, Arne Grimsmo")
AUTHOR_EMAIL = ("alex.pitchford@gmail.com, nonhermitian@gmail.com, "
                "jrjohansson@gmail.com, cgranade@cgranade.com, "
                "arne.grimsmo@gmail.com")
LICENSE = "BSD"
DESCRIPTION = DOCLINES[0]
LONG_DESCRIPTION = "\n".join(DOCLINES[2:])
KEYWORDS = "quantum physics dynamics"
URL = "http://qutip.org"
CLASSIFIERS = [_f for _f in CLASSIFIERS.split('\n') if _f]
PLATFORMS = ["Linux", "Mac OSX", "Unix", "Windows"]

def git_short_hash():
    try:
        git_str = "+" + os.popen('git log -1 --format="%h"').read().strip()
    except:
        git_str = ""
    else:
        if git_str == '+': #fixes setuptools PEP issues with versioning
            git_str = ''
    return git_str

FULLVERSION = VERSION
if not ISRELEASED:
    FULLVERSION += '.dev'+str(MICRO)+git_short_hash()

# NumPy's distutils reads in versions differently than
# our fallback. To make sure that versions are added to
# egg-info correctly, we need to add FULLVERSION to
# EXTRA_KWARGS if NumPy wasn't imported correctly.
if np is None:
    EXTRA_KWARGS['version'] = FULLVERSION

def write_version_py(filename='qutip/version.py'):
    cnt = """\
# THIS FILE IS GENERATED FROM QUTIP SETUP.PY
short_version = '%(version)s'
version = '%(fullversion)s'
release = %(isrelease)s
"""
    a = open(filename, 'w')
    try:
        a.write(cnt % {'version': VERSION, 'fullversion':
                FULLVERSION, 'isrelease': str(ISRELEASED)})
    finally:
        a.close()

local_path = os.path.dirname(os.path.abspath(sys.argv[0]))
os.chdir(local_path)
sys.path.insert(0, local_path)
sys.path.insert(0, os.path.join(local_path, 'qutip'))  # to retrive _version

# always rewrite _version
if os.path.exists('qutip/version.py'):
    os.remove('qutip/version.py')

write_version_py()

# Add Cython extensions here
cy_exts = ['spmatfuncs', 'stochastic', 'sparse_utils', 'graph_utils', 'interpolate',
        'spmath', 'heom', 'math', 'spconvert', 'ptrace', 'testing']

# If on Win and Python version >= 3.5 (i.e. Visual studio compile)
if sys.platform == 'win32' and int(str(sys.version_info[0])+str(sys.version_info[1])) >= 35:
    _compiler_flags = ['/w', '/Ox']
# Everything else
else:
    _compiler_flags = ['-w', '-O3', '-march=native', '-funroll-loops']

EXT_MODULES =[]
# Add Cython files from qutip/cy
for ext in cy_exts:
    _mod = Extension('qutip.cy.'+ext,
            sources = ['qutip/cy/'+ext+'.pyx', 'qutip/cy/src/zspmv.cpp'],
            include_dirs = [np.get_include()],
            extra_compile_args=_compiler_flags,
            extra_link_args=[],
            language='c++')
    EXT_MODULES.append(_mod)

# Add Cython files from qutip/control
_mod = Extension('qutip.control.cy_grape',
            sources = ['qutip/control/cy_grape.pyx'],
            include_dirs = [np.get_include()],
            extra_compile_args=_compiler_flags,
            extra_link_args=[],
            language='c++')
EXT_MODULES.append(_mod)

# Add optional ext modules here
if "--with-openmp" in sys.argv:
    sys.argv.remove("--with-openmp")
    if (sys.platform == 'win32'
            and int(str(sys.version_info[0])+str(sys.version_info[1])) >= 35):
        omp_flags = ['/openmp']
        omp_args = []
    else:
        omp_flags = ['-fopenmp']
        omp_args = omp_flags
    _mod = Extension('qutip.cy.openmp.parfuncs',
            sources = ['qutip/cy/openmp/parfuncs.pyx',
                       'qutip/cy/openmp/src/zspmv_openmp.cpp'],
            include_dirs = [np.get_include()],
            extra_compile_args=_compiler_flags+omp_flags,
            extra_link_args=omp_args,
            language='c++')
    EXT_MODULES.append(_mod)
    # Add benchmark pyx
    _mod = Extension('qutip.cy.openmp.benchmark',
            sources = ['qutip/cy/openmp/benchmark.pyx'],
            include_dirs = [np.get_include()],
            extra_compile_args=_compiler_flags,
            extra_link_args=[],
            language='c++')
    EXT_MODULES.append(_mod)

# Setup commands go here
setup(
    name = NAME,
    version = FULLVERSION,
    packages = PACKAGES,
    include_dirs = INCLUDE_DIRS,
    headers = HEADERS,
    ext_modules = cythonize(EXT_MODULES),
    cmdclass = {'build_ext': build_ext},
    author = AUTHOR,
    author_email = AUTHOR_EMAIL,
    license = LICENSE,
    description = DESCRIPTION,
    long_description = LONG_DESCRIPTION,
    keywords = KEYWORDS,
    url = URL,
    classifiers = CLASSIFIERS,
    platforms = PLATFORMS,
    requires = REQUIRES,
    package_data = PACKAGE_DATA,
    zip_safe = False,
    install_requires=INSTALL_REQUIRES,
    **EXTRA_KWARGS
)


from pike.manager import PikeManager

def load_plugins(plugin_type, plugin_dir, plugin_classes):
    loaded_plugins = []
    plugin_classes = plugin_classes.split(',')
    print("Searching dir '{0}' for {1} plugins...".format(plugin_dir, plugin_type), flush=True)
    with PikeManager([plugin_dir]) as mgr:
        found_classes = mgr.get_classes()
        class_names = [c.__name__ for c in found_classes]
        print("Found classes: {0}".format(class_names), flush=True)
        for p in plugin_classes:
            print("Loading plugin class '{0}'".format(p), flush=True)
            if p not in class_names:
                print("Plugin class {0} not found! skipping...".format(p))
            else:
                loaded_plugins.append(found_classes[class_names.index(p)]())
    return loaded_plugins


################################################################################
#  Licensed to the Apache Software Foundation (ASF) under one
#  or more contributor license agreements.  See the NOTICE file
#  distributed with this work for additional information
#  regarding copyright ownership.  The ASF licenses this file
#  to you under the Apache License, Version 2.0 (the
#  "License"); you may not use this file except in compliance
#  with the License.  You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
#  Unless required by applicable law or agreed to in writing, software
#  distributed under the License is distributed on an "AS IS" BASIS,
#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#  See the License for the specific language governing permissions and
# limitations under the License.
################################################################################
import asyncio
import unittest
from datetime import timedelta

from google.protobuf.json_format import MessageToDict
from google.protobuf.any_pb2 import Any

from tests.examples_pb2 import LoginEvent, SeenCount
from statefun.request_reply_pb2 import ToFunction, FromFunction
from statefun import RequestReplyHandler, AsyncRequestReplyHandler
from statefun.core import StatefulFunctions, kafka_egress_record
from statefun.core import StatefulFunctions, kinesis_egress_record

class InvocationBuilder(object):
    """builder for the ToFunction message"""

    def __init__(self):
        self.to_function = ToFunction()

    def with_target(self, ns, type, id):
        InvocationBuilder.set_address(ns, type, id, self.to_function.invocation.target)
        return self

    def with_state(self, name, value=None):
        state = self.to_function.invocation.state.add()
        state.state_name = name
        if value:
            any = Any()
            any.Pack(value)
            state.state_value = any.SerializeToString()
        return self

    def with_invocation(self, arg, caller=None):
        invocation = self.to_function.invocation.invocations.add()
        if caller:
            (ns, type, id) = caller
            InvocationBuilder.set_address(ns, type, id, invocation.caller)
        invocation.argument.Pack(arg)
        return self

    def SerializeToString(self):
        return self.to_function.SerializeToString()

    @staticmethod
    def set_address(namespace, type, id, address):
        address.namespace = namespace
        address.type = type
        address.id = id

def round_trip(typename, fn, to: InvocationBuilder) -> dict:
    functions = StatefulFunctions()
    functions.register(typename, fn)
    handler = RequestReplyHandler(functions)
    f = FromFunction()
    f.ParseFromString(handler(to.SerializeToString()))
    return MessageToDict(f, preserving_proto_field_name=True)

def async_round_trip(typename, fn, to: InvocationBuilder) -> dict:
    functions = StatefulFunctions()
    functions.register(typename, fn)
    handler = AsyncRequestReplyHandler(functions)

    in_bytes = to.SerializeToString()
    future = handler(in_bytes)
    out_bytes = asyncio.get_event_loop().run_until_complete(future)

    f = FromFunction()
    f.ParseFromString(out_bytes)
    return MessageToDict(f, preserving_proto_field_name=True)

def json_at(nested_structure: dict, path):
    try:
        for next in path:
            nested_structure = next(nested_structure)
        return nested_structure
    except KeyError:
        return None

def key(s: str):
    return lambda dict: dict[s]

def nth(n):
    return lambda list: list[n]

NTH_OUTGOING_MESSAGE = lambda n: [key("invocation_result"), key("outgoing_messages"), nth(n)]
NTH_STATE_MUTATION = lambda n: [key("invocation_result"), key("state_mutations"), nth(n)]
NTH_DELAYED_MESSAGE = lambda n: [key("invocation_result"), key("delayed_invocations"), nth(n)]
NTH_EGRESS = lambda n: [key("invocation_result"), key("outgoing_egresses"), nth(n)]

class RequestReplyTestCase(unittest.TestCase):

    def test_integration(self):
        def fun(context, message):
            # state access
            seen = context.state('seen').unpack(SeenCount)
            seen.seen += 1
            context.state('seen').pack(seen)

            # regular state access
            seenAny = context['seen']
            seenAny.Unpack(seen)

            # sending and replying
            context.pack_and_reply(seen)

            any = Any()
            any.type_url = 'type.googleapis.com/k8s.demo.SeenCount'
            context.send("bar.baz/foo", "12345", any)

            # delayed messages
            context.send_after(timedelta(hours=1), "night/owl", "1", any)

            # egresses
            context.send_egress("foo.bar.baz/my-egress", any)
            context.pack_and_send_egress("foo.bar.baz/my-egress", seen)

            # kafka egress
            context.pack_and_send_egress("sdk/kafka",
                                         kafka_egress_record(topic="hello", key=u"hello world", value=seen))
            context.pack_and_send_egress("sdk/kafka",
                                         kafka_egress_record(topic="hello", value=seen))

            # AWS Kinesis generic egress
            context.pack_and_send_egress("sdk/kinesis",
                                         kinesis_egress_record(
                                             stream="hello",
                                             partition_key=u"hello world",
                                             value=seen,
                                             explicit_hash_key=u"1234"))
            context.pack_and_send_egress("sdk/kinesis",
                                         kinesis_egress_record(
                                             stream="hello",
                                             partition_key=u"hello world",
                                             value=seen))

        #
        # build the invocation
        #
        builder = InvocationBuilder()
        builder.with_target("org.foo", "greeter", "0")

        seen = SeenCount()
        seen.seen = 100
        builder.with_state("seen", seen)

        arg = LoginEvent()
        arg.user_name = "user-1"
        builder.with_invocation(arg, ("org.foo", "greeter-java", "0"))

        #
        # invoke
        #
        result_json = round_trip("org.foo/greeter", fun, builder)

        # assert first outgoing message
        first_out_message = json_at(result_json, NTH_OUTGOING_MESSAGE(0))
        self.assertEqual(first_out_message['target']['namespace'], 'org.foo')
        self.assertEqual(first_out_message['target']['type'], 'greeter-java')
        self.assertEqual(first_out_message['target']['id'], '0')
        self.assertEqual(first_out_message['argument']['@type'], 'type.googleapis.com/k8s.demo.SeenCount')

        # assert second outgoing message
        second_out_message = json_at(result_json, NTH_OUTGOING_MESSAGE(1))
        self.assertEqual(second_out_message['target']['namespace'], 'bar.baz')
        self.assertEqual(second_out_message['target']['type'], 'foo')
        self.assertEqual(second_out_message['target']['id'], '12345')
        self.assertEqual(second_out_message['argument']['@type'], 'type.googleapis.com/k8s.demo.SeenCount')

        # assert state mutations
        first_mutation = json_at(result_json, NTH_STATE_MUTATION(0))
        self.assertEqual(first_mutation['mutation_type'], 'MODIFY')
        self.assertEqual(first_mutation['state_name'], 'seen')
        self.assertIsNotNone(first_mutation['state_value'])

        # assert delayed
        first_delayed = json_at(result_json, NTH_DELAYED_MESSAGE(0))
        self.assertEqual(int(first_delayed['delay_in_ms']), 1000 * 60 * 60)

        # assert egresses
        first_egress = json_at(result_json, NTH_EGRESS(0))
        self.assertEqual(first_egress['egress_namespace'], 'foo.bar.baz')
        self.assertEqual(first_egress['egress_type'], 'my-egress')
        self.assertEqual(first_egress['argument']['@type'], 'type.googleapis.com/k8s.demo.SeenCount')

class AsyncRequestReplyTestCase(unittest.TestCase):

    def test_integration(self):
        async def fun(context, message):
            any = Any()
            any.type_url = 'type.googleapis.com/k8s.demo.SeenCount'
            context.send("bar.baz/foo", "12345", any)

        #
        # build the invocation
        #
        builder = InvocationBuilder()
        builder.with_target("org.foo", "greeter", "0")

        seen = SeenCount()
        seen.seen = 100
        builder.with_state("seen", seen)

        arg = LoginEvent()
        arg.user_name = "user-1"
        builder.with_invocation(arg, ("org.foo", "greeter-java", "0"))

        #
        # invoke
        #
        result_json = async_round_trip("org.foo/greeter", fun, builder)

        # assert outgoing message
        second_out_message = json_at(result_json, NTH_OUTGOING_MESSAGE(0))
        self.assertEqual(second_out_message['target']['namespace'], 'bar.baz')
        self.assertEqual(second_out_message['target']['type'], 'foo')
        self.assertEqual(second_out_message['target']['id'], '12345')
        self.assertEqual(second_out_message['argument']['@type'], 'type.googleapis.com/k8s.demo.SeenCount')


# -*- coding: utf-8 -*-
#
# Copyright © Spyder Project Contributors
# Licensed under the terms of the MIT License
# (see spyder/__init__.py for details)

"""
Status bar container.
"""

# Third-party imports
from qtpy.QtCore import Signal

# Local imports
from spyder.api.widgets import PluginMainContainer
from spyder.plugins.statusbar.widgets.status import (
    ClockStatus, CPUStatus, MemoryStatus
)

class StatusBarContainer(PluginMainContainer):
    DEFAULT_OPTIONS = {
        'show_status_bar': True,
        'memory_usage/enable': True,
        'memory_usage/timeout': 2000,
        'cpu_usage/enable': False,
        'cpu_usage/timeout': 2000,
        'clock/enable': False,
        'clock/timeout': 1000,
    }

    sig_show_status_bar_requested = Signal(bool)
    """
    This signal is emmitted when the user wants to show/hide the
    status bar.
    """

    def setup(self, options):
        # Basic status widgets
        self.mem_status = MemoryStatus(parent=self)
        self.cpu_status = CPUStatus(parent=self)
        self.clock_status = ClockStatus(parent=self)

    def on_option_update(self, option, value):
        if option == 'memory_usage/enable':
            self.mem_status.setVisible(value)
        elif option == 'memory_usage/timeout':
            self.mem_status.set_interval(value)
        elif option == 'cpu_usage/enable':
            self.cpu_status.setVisible(value)
        elif option == 'cpu_usage/timeout':
            self.cpu_status.set_interval(value)
        elif option == 'clock/enable':
            self.clock_status.setVisible(value)
        elif option == 'clock/timeout':
            self.clock_status.set_interval(value)
        elif option == 'show_status_bar':
            self.sig_show_status_bar_requested.emit(value)

    def update_actions(self):
        pass


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

from . import views

router = DefaultRouter()
router.register(r'groups', views.GroupViewSet)
router.register(r'users', views.UserViewSet)

urlpatterns = [
    path('', include(router.urls)),
    path(r'groups/<int:pk>/users/', views.GroupMembers.as_view()),
]


"""
1 2
3 0 1 2
2 1 3
"""

k, rows = map(int, input().strip().split())
#输入rows行
tree = []
for i in range(rows):
    tree.append(list(map(int, input().strip().split())))

#先找到根节点
def find(root):
    for index, t in enumerate(tree):
        if t[1] == root:
            return index
    #没有，则不存在叶子结点 返回-1
    return -1

#宽度遍历
def bfs(root, time):
    #根据k在进行宽度遍历
    #对根节点的子节点个数进行排序，选择子节点个数最多的k个进行宽度遍历
    index = find(root)
    if index == -1:
        result.append(time)
        return
    else:
        for i in tree[index][2:2+k-1]:
            bfs(i, time + 1)

result = []
root = find(0)
bfs(0, 0)
print(max(result))


def list_manipulator(ll, command, where, *numbers):
    if not numbers:
        numbers = []
        numbers.append(1)

    if command == "add":
        if where == "beginning":
            for i in range(len(numbers)):
                ll.insert(i, numbers[i])
        if where == "end":
            for i in range(len(numbers)):
                ll.append(numbers[i])
    elif command == "remove":
        if where == "beginning":
            for _ in range(numbers[0]):
                ll.pop(0)
        if where == "end":
            for _ in range(numbers[0]):
                ll.pop()
    return ll