#Name: Md Raihanul Islam Bhuiyan
#Id: 20101239
#Lab Section: 3

#If the answer shouldn't be -1 but it is still showing -1, run the code few times again. It should give a valid result when it is supposed to.
data=open('input.txt')
data=data.read()
data=data.split('\n')
ld=data[1:]

import random
class genetic:

    #modeling the data and calling other funtions from it
    def model(self):
        transactions=int(data[0])
        chromosomes=[]
        for n in range(0,5):
            s = ''
            for i in range(0,transactions):
                c=str(random.randint(0,1))
                s=s+c
            chromosomes.append(s)
        fit={}
        valid = False
        #iterating the loop 10000 times to check whether we can find a chromosome with fitness value=0
        for i in range(0,10000):
            for c in chromosomes:

                self.fitness(fit,c)

            if 0 in fit:
                #checking if the chromosome with fitness value is not made up of only 0s
                if fit[0]!='0'*int(data[0]):
                    print(fit[0])
                    valid=True
                    break
                else:
                    continue

            #sorting the fit list by fitness values
            sfit=sorted(fit.items())
            fit={}
            best_fit=sfit[0:3]

            chromosomes=self.crossover(best_fit,chromosomes)

            r=random.randint(0,1)
            if r==1:
                chromosomes=self.mutation(chromosomes)

        if valid==False:
            print(-1)

    #checking how much closer to 0 the fitness is and storing it in a dictionary called fit
    def fitness(self,fit,c):

        sum=0
        for i in range(0,len(c)):
            if c[i]=='1':
                detect=ld[i].split(' ')

                if detect[0]=='l':

                    sum=sum-int(detect[1])
                elif detect[0]=='d':
                    #print('f')
                    sum=sum+int(detect[1])
        if sum<0:
            sum=sum*-1
        fit[sum]=c

    #crossing over between the most fit chromosomes randomly
    def crossover(self,best_fit,chromosomes):
        c=random.randint(1,int(data[0])-1)

        if len(best_fit)==3:
            temp1=best_fit[0][1][0:c]
            temp2=best_fit[1][1][0:c]
            temp3=best_fit[2][1][0:c]

            c1=temp1+best_fit[1][1][c:]
            c2=temp1+best_fit[2][1][c:]
            c3=temp2+best_fit[0][1][c:]
            c4=temp2+ best_fit[2][1][c:]
            c5=temp3+best_fit[0][1][c:]
            c6=temp3+best_fit[1][1][c:]

            chromosomes=[c1,c2,c3,c4,c5,c6]
        elif len(best_fit)==2:
            temp1 = best_fit[0][1][0:c]
            temp2 = best_fit[1][1][0:c]
            c1 = temp1 + best_fit[1][1][c:]
            c2=temp2+best_fit[0][1][c:]

            chromosomes=[c1,c2]

        return chromosomes

    #mutating a random index of the chromosomes
    def mutation(self,chromosomes):
        m = random.randint(1, int(data[0]) - 1)
        mchrom=[]

        for c in chromosomes:
            s=''
            if c[m]=='1':
                s=s+c[0:m]+'0'+c[m+1:]
            else:
                s=s+c[0:m]+'1'+c[m+1:]
            mchrom.append(s)

        return(mchrom)

a=genetic()
a.model()


from graph_tool.all import *
import random
import numpy as np

"""
Very basic graph:
n = 4
m = 4
"""

# create graph
g = Graph(directed=False)

# add nodes
v1 = g.add_vertex()
v2 = g.add_vertex()
v3 = g.add_vertex()
v4 = g.add_vertex()

# add edges
e1 = g.add_edge(v1, v2)
e2 = g.add_edge(v2, v3)
e3 = g.add_edge(v1, v3)
e4 = g.add_edge(v3, v4)

# output graph
graph_draw(g)

######################################################################

n = 1000
p_inner = 1/20
p_outer = 1/1000

# Additional example:
# closer values of edge probabilities
#p_outer = 1/160

# create graph
g = Graph(directed=False)

# add nodes
for _ in range(n):
    g.add_vertex()

# add edges
for v1 in g.vertices():
    for v2 in g.vertices():

        if v1 <= v2:
            continue

        # graph-tool automatically indexes nodes from 0 to n-1
        # we draw edges based on node indices:
        #
        # - nodes 0, 4, 8, ...  belong to group 1
        # - nodes 1, 5, 9, ...  belong to group 2
        # - nodes 2, 6, 10, ... belong to group 3
        # - nodes 3, 7, 11, ... belong to group 4

        if (int(v1) % 4) == (int(v2) % 4):
            if random.random() <= p_inner:
                g.add_edge(v1, v2)
        else:
            if random.random() <= p_outer:
                g.add_edge(v1, v2)

# save graph layout for consistent visualizations
pos = sfdp_layout(g)

# output graph
graph_draw(g, pos=pos)

######################################################################

# since sfdp_layout automatically notices group structure
# we also check how the graph looks with a random layout
pos_2 = random_layout(g)
graph_draw(g, pos=pos_2)

# perform classic SBM inference
state = minimize_blockmodel_dl(g, B_min=4, B_max=4, deg_corr=False)
state.draw(pos=pos)

# calculate the percentage of correctly grouped nodes
n_corr = sum([1 if int(v) % 4 == b else 0 for v, b in zip(g.vertices(), state.get_blocks())])
n = g.num_vertices()

print(f"Percentage of correctly grouped vertices: {100 * n_corr / n}% ({n_corr}/{n})")

######################################################################

"""
SBM inference on Zachary karate network
"""

# load graph
g = collection.data["karate"]

# save graph layout for consistent visualizations
pos = sfdp_layout(g)

# draw initial graph
graph_draw(g, pos=pos)

# basic SBM inference:
# captures core-periphery structure

state_1 = minimize_blockmodel_dl(g, B_min=2, B_max=2, deg_corr=False)
state_1.draw(pos=pos)

# degree-corrected SBM inference:
# captures sociological partitioning

seed_rng(2)
np.random.seed(2)

state_2 = minimize_blockmodel_dl(g, B_min=2, B_max=2, deg_corr=True)
state_2.draw(pos=pos)


#WGU Student ID: 010871862
#Student Name: Jeffrey Raymond Tagle

import csv
import datetime
from HashMap import HashMap
from Package import Package
from Truck import Truck

#This function takes a CSV file as a parameter, breaks the data apart into rows at each comma,
#and then iterates through each row adding the row into a list.
#O(n) time complexity
def load_data(filename):
    package_list = []

    with open(filename) as packages:
        package_data = csv.reader(packages, delimiter=',')
        for row in package_data:
            package_list.append(row)
        return package_list

#This function takes a row value, column value, and a CSV file with a distance matrix and returns the distance
#O(1) time complexity
def get_distance(row, column, distances):
    distance = distances[row][column]
    return distance

#This function takes an address string and an address list as parameters, then returns the index value of the address
#O(1) time complexity
def get_address_index(address, address_list):
    address_index = address_list.index(address) + 1
    return address_index

#Nearest neighbor algorithm. This algorithm iterates takes current address, list of package IDs of packages on a truck,
# the package hashmap, the distances CSV file, and the address list CSV file as parameters. The function iterates through
# the list of package IDs, retrieves the Package object of that ID, and then retrieves the delivery address of the package.
# The function then retrieves the distance, compares that distance to the current min distance, and then keeps the min distance.
# Using that min distance, the function identifies the destination address that has that distance and returns the address.
#O(n) time complexity. Later on, the delivery function implements the nearest_neighbor function which leads to an O(n^2) time complexity.
def nearest_neighbor(current_address, truck_packages, package_hash_list, distances, address_list):
    min_distance = float('inf')
    nearest_address_index = 0
    current_address_index = get_address_index(current_address, address_list)
    for i in truck_packages:
        p = package_hash_list.lookup(str(i))
        target_address_index = get_address_index(p.get_delivery_address(), address_list)
        distance = get_distance(current_address_index, target_address_index, distances)
        #if float(distance) == 0:
            #continue
        if float(distance) < float(min_distance):
            min_distance = distance
            nearest_address_index = target_address_index - 1
    nearest_address = address_list[nearest_address_index]
    return nearest_address

#This function just creates a HashMap of Package objects.
#O(n) time complexity
def create_package_hashmap(package_csv_list, package_hash):
    for row in package_csv_list:
        package = Package(row[0], row[1], row[2], row[3], row[4], row[5], row[6], "At the hub")
        package_hash.insert(row[0], package)

distances_list = load_data('distances.csv')
addresses_for_distances_list = load_data('addresses_for_distances.csv')
addresses = []
for a in addresses_for_distances_list:
    addresses.append(a[0])

new_package_list = load_data('Packages.csv')
package_hashmap = HashMap()
create_package_hashmap(new_package_list, package_hashmap)

truck1 = Truck()
truck2 = Truck()
truck3 = Truck()

#Load all 3 trucks
def reset_trucks(truck1, truck2, truck3): #Parameters are truck objects
    truck1.load(1)
    truck1.load(7)
    truck1.load(5)
    truck1.load(8)
    truck1.load(13)
    truck1.load(14)
    truck1.load(15)
    truck1.load(19)
    truck1.load(16)
    truck1.load(20)
    truck1.load(29)
    truck1.load(30)
    truck1.load(34)
    truck1.load(21)
    truck1.load(40)
    truck1.load(37)

    truck2.load(3)
    truck2.load(6)
    truck2.load(18)
    truck2.load(25)
    truck2.load(31)
    truck2.load(26)
    truck2.load(32)
    truck2.load(36)
    truck2.load(38)

    truck3.load(2)
    truck3.load(39)
    truck3.load(22)
    truck3.load(35)
    truck3.load(4)
    truck3.load(10)
    truck3.load(11)
    truck3.load(12)
    truck3.load(17)
    truck3.load(23)
    truck3.load(24)
    truck3.load(33)
    truck3.load(28)
    truck3.load(9)
    truck3.load(27)

def calc_travel_time(distance): #18 mph, can use for individual deliveries or total time
    time_in_seconds = (distance / 18) * 3600
    return time_in_seconds

#Deliver function. Primary function that allows trucks to deliver packages based on nearest neighbor algorithm.
#Returns total travel distance for the truck.
#O(n^2) time complexity.
def deliver(truck, packages, start_time_h, start_time_m, start_time_s, end_time_h, end_time_m, end_time_s):
    #Parameters are truck object and package hashmap and time to depart, returns total distance traveled

    start_time_in_secs = (start_time_h * 3600) + (start_time_m * 60) + start_time_s
    total_end_time_in_secs = (end_time_h * 3600) + (end_time_m * 60) + end_time_s
    for i in truck.packages:
        p = packages.lookup(str(i))
        p.update_status("In Transit")

    current_address = "4001 South 700 East"
    total_dist = 0

    delivery_time_in_sec = start_time_in_secs # initial value for total delivery time

    while len(truck.packages) > 0:
        #print("***Next while loop iteration***")
        if delivery_time_in_sec >= 37200:
            if 9 in truck.packages:
                p = packages.lookup(str(9))
                p.update_delivery_address("410 S State St")
        #print("Current address: " + current_address)
        dest_address = nearest_neighbor(current_address, truck.packages, packages, distances_list, addresses)
        #print("Destination address: " + dest_address)
        #if current_address == dest_address:
            # = 0
        #else:
        current_travel_dist = float(get_distance(get_address_index(current_address, addresses), get_address_index(dest_address, addresses), distances_list))
        #print("Travel distance from current address to destination address: " + str(current_travel_dist))
        total_dist += current_travel_dist
        #print("Total distance so far: " + str(total_dist))
        travel_time = calc_travel_time(current_travel_dist)
        test_time = datetime.timedelta(seconds=travel_time)
        #print("Time to travel to current dest: " + str(test_time))
        delivery_time_in_sec += travel_time
        delivery_time = datetime.timedelta(seconds=delivery_time_in_sec)
        #print("Time of delivery: " + str(delivery_time))

        if delivery_time_in_sec > total_end_time_in_secs:
            return total_dist

        for i in truck.packages:
            p = packages.lookup(str(i))
            if p.get_delivery_address() == dest_address:

                p.update_status("Delivered at " + str(delivery_time))
                p.update_delivery_time(delivery_time)
                truck.packages.remove(i)
        current_address = dest_address

    return_home_dist = float(get_distance(get_address_index(current_address, addresses), get_address_index("4001 South 700 East", addresses), distances_list))
    #print("Current address: " + current_address)
    #print("Return to hub distance :" + str(return_home_dist))
    total_dist += return_home_dist
    #print("Total distance traveled by truck: " + str(total_dist))

    return total_dist

#Function used to start the program
#O(n^2) time complexity for the overall program.
def start():
    print("Welcome to WGUPS Service! Please choose one of the following options:")

    while True:
        reset_trucks(truck1, truck2, truck3)
        create_package_hashmap(new_package_list, package_hashmap)

        #truck1_total_travel_time = 0
        #truck2_total_travel_time = 0
        #truck3_total_travel_time = 0
        truck1_delivery = 0
        truck2_delivery = 0
        truck3_delivery = 0
        #end_time_in_secs = 0
        print("0 - Exit")
        print("1 - Status of all packages at a given time")
        print("2 - Status of one single package")

        x = input()

        if x == "0":
            return False

        if x == "1":
            print("Give the hours in a 24 hr format")
            time_input_hours = int(input())
            print("Give the amount of minutes")
            time_input_mins = int(input())
            print("Give the amount of seconds")
            time_input_secs = int(input())
            end_time_in_secs = time_input_hours*3600 + time_input_mins*60 + time_input_secs

            if end_time_in_secs >= 28800:
                truck1_delivery = deliver(truck1, package_hashmap, 8, 0, 0, time_input_hours, time_input_mins, time_input_secs)

            if end_time_in_secs >= 32700:
                truck2_delivery = deliver(truck2, package_hashmap, 9, 5, 0, time_input_hours, time_input_mins,
                                          time_input_secs)

            if end_time_in_secs >= 36300:
                truck3_delivery = deliver(truck3, package_hashmap, 10, 5, 00, time_input_hours, time_input_mins,
                                          time_input_secs)

            truck1_total_travel_time_sec = calc_travel_time(truck1_delivery)
            truck1_total_travel_time = datetime.timedelta(seconds=truck1_total_travel_time_sec)
            truck2_total_travel_time_sec = calc_travel_time(truck2_delivery)
            truck2_total_travel_time = datetime.timedelta(seconds=truck2_total_travel_time_sec)
            truck3_total_travel_time_sec = calc_travel_time(truck3_delivery)
            truck3_total_travel_time = datetime.timedelta(seconds=truck3_total_travel_time_sec)

            print("Status for packages as of " + str(datetime.timedelta(seconds=end_time_in_secs)))
            for i in range(1, 41):
                print(package_hashmap.lookup(str(i)))

            print("Total distance traveled for Truck 1 in miles: " + str(truck1_delivery))
            print("Total distance traveled for Truck 2 in miles: " + str(truck2_delivery))
            print("Total distance traveled for Truck 3 in miles: " + str(truck3_delivery))
            print("Total distance traveled for all three trucks: " + str(truck1_delivery + truck2_delivery + truck3_delivery))
            print("Total time traveled for Truck 1: " + str(truck1_total_travel_time))
            print("Total time traveled for Truck 2: " + str(truck2_total_travel_time))
            print("Total time traveled for Truck 3: " + str(truck3_total_travel_time))

        if x == "2":
            print("Give the package ID to search:")
            package_id_input = int(input())
            print("Give the hours in a 24 hr format")
            time_input_hours = int(input())
            print("Give the amount of minutes")
            time_input_mins = int(input())
            print("Give the amount of seconds")
            time_input_secs = int(input())
            end_time_in_secs = time_input_hours * 3600 + time_input_mins * 60 + time_input_secs

            if end_time_in_secs >= 28800:
                deliver(truck1, package_hashmap, 8, 0, 0, time_input_hours, time_input_mins,
                                          time_input_secs)

            if end_time_in_secs >= 32700:
                deliver(truck2, package_hashmap, 9, 5, 0, time_input_hours, time_input_mins,
                                          time_input_secs)

            if end_time_in_secs >= 36340:
                deliver(truck3, package_hashmap, 10, 5, 40, time_input_hours, time_input_mins,
                                          time_input_secs)

            print("Status for package " + str(package_id_input) + " as of " + str(datetime.timedelta(seconds=end_time_in_secs)))
            print(package_hashmap.lookup(str(package_id_input)))

start()


import logging

from django.contrib.auth.models import User

from django.core.exceptions import ObjectDoesNotExist

from rest_framework.parsers import JSONParser
from rest_framework.renderers import JSONRenderer
from io import BytesIO

from .client import BaseClient, MQTTException

from ambulance.models import Ambulance
from ambulance.serializers import AmbulanceSerializer

from hospital.models import Hospital, HospitalEquipment
from hospital.serializers import HospitalSerializer, \
    HospitalEquipmentSerializer

logger = logging.getLogger(__name__)

# SubscribeClient
class SubscribeClient(BaseClient):

    # The callback for when the client receives a CONNACK
    # response from the server.
    def on_connect(self, client, userdata, flags, rc):

        # is connected?
        if not super().on_connect(client, userdata, flags, rc):
            return False

        # Subscribing in on_connect() means that if we lose the
        # connection and reconnect then subscriptions will be renewed.
        # client.subscribe('#', 2)

        # ambulance handler
        self.client.message_callback_add('user/+/ambulance/+/data',
                                         self.on_ambulance)

        # hospital handler
        self.client.message_callback_add('user/+/hospital/+/data',
                                         self.on_hospital)

        # hospital equipment handler
        self.client.message_callback_add('user/+/hospital/+/equipment/+/data',
                                         self.on_hospital_equipment)

        # call handler
        #self.client.message_callback_add('ambulance/+/call',
        #                                 self.on_call)

        # subscribe
        self.subscribe('user/+/ambulance/+/data', 2)
        self.subscribe('user/+/hospital/+/data', 2)
        self.subscribe('user/+/hospital/+/equipment/+/data', 2)

        if self.verbosity > 0:
            self.stdout.write(self.style.SUCCESS(">> Listening to MQTT messages..."))

        return True

    def send_error_message(self, username, topic, payload, error):

        logger.debug("send_error_message: {}, '{}:{}': '{}'".format(username,
                                                                    topic,
                                                                    payload,
                                                                    error))

        if self.verbosity > 0:
            self.stdout.write(self.style.ERROR("*> Error {}, '{}:{}': {}".format(username,
                                                                                topic,
                                                                                payload,
                                                                                error)))

        try:

            message = JSONRenderer().render({
                'topic': topic,
                'payload': payload,
                'error': error
            })
            self.publish('user/{}/error'.format(username), message)

        except Exception as e:

            logger.warning(('mqtt.SubscribeClient: {}, ' +
                            "topic = '{}:{}', " +
                            "error = '{}', " +
                            "exception = {}").format(username,
                                                     topic,
                                                     payload,
                                                     error,
                                                     e))

    def parse_topic(self, msg):

        if not msg.payload:
            # empty payload
            return

        if self.verbosity > 0:
            self.stdout.write(self.style.SUCCESS(" > Parsing message '{}:{}'".format(msg.topic,
                                                                                msg.payload)))

        # parse topic
        values = msg.topic.split('/')

        #print('values = {}'.format(values))

        try:

            # retrieve user
            #print(User.objects.all())
            user = User.objects.get(username=values[1])

        except ObjectDoesNotExist as e:

            # does not know username
            # cannot send error message to user
            logger.warning(('mqtt.SubscribeClient: {}, ' +
                            "topic = '{}:{}', " +
                            "error = '{}', " +
                            "exception = {}").format(username,
                                                     topic,
                                                     payload,
                                                     error,
                                                     e))
            return

        # parse data
        try:

            # Parse data into json dict
            data = JSONParser().parse(BytesIO(msg.payload))

        except Exception as e:

            # send error message to user
            self.send_error_message(user, msg.topic, msg.payload,
                                    "JSON formatted incorrectly")
            return

        if len(values) == 5:

            return (user, data, values[3])

        elif len(values) == 7:

            return (user, data, values[3], values[5])

        else:

            # send error message to user
            # this should never happen because no subscriptions will match
            # topics with different sizes
            self.send_error_message(user, msg.topic, msg.payload,
                                    "Invalid topic")
            return

    # Update ambulance
    def on_ambulance(self, client, userdata, msg):

        logger.debug("on_ambulance: msg = '{}:{}'".format(msg.topic, msg.payload))

        # parse topic
        values = self.parse_topic(msg)
        if not values:
            return

        logger.debug("on_ambulance: values = '{}'".format(values))

        try:

            # retrieve parsed values
            user, data, ambulance_id = values

            logger.debug('ambulance_id = {}'.format(ambulance_id))

            # retrieve ambulance
            ambulance = Ambulance.objects.get(id=ambulance_id)

        except ObjectDoesNotExist:

            # send error message to user
            self.send_error_message(user, msg.topic, msg.payload,
                                    "Ambulance with id '{}' does not exist".format(ambulance_id))
            return

        except Exception as e:

            # send error message to user
            self.send_error_message(user, msg.topic, msg.payload,
                                    "Exception: '{}'".format(e))
            return

        logger.debug('on_ambulance: ambulance = {}'.format(ambulance))

        try:

            # update ambulance
            serializer = AmbulanceSerializer(ambulance,
                                             data=data,
                                             partial=True)
            if serializer.is_valid():

                logger.debug('on_ambulance: valid serializer')

                # save to database
                serializer.save(updated_by=user)

            else:

                logger.debug('on_ambulance: INVALID serializer')

                # send error message to user
                self.send_error_message(user, msg.topic, msg.payload,
                                        serializer.errors)

        except Exception as e:

            logger.debug('on_ambulance: serializer EXCEPTION')

            # send error message to user
            self.send_error_message(user, msg.topic, msg.payload, e)

        logger.debug('on_ambulance: DONE')

    # Update hospital
    def on_hospital(self, client, userdata, msg):

        logger.debug("on_hospital: msg = '{}:{}'".format(msg.topic, msg.payload))

        # parse topic
        values = self.parse_topic(msg)
        if not values:
            return

        logger.debug("on_hospital: values = '{}'".format(values))

        try:

            # retrieve parsed values
            user, data, hospital_id = values

            # retrieve hospital
            hospital = Hospital.objects.get(id=hospital_id)

        except ObjectDoesNotExist:

            # send error message to user
            self.send_error_message(user, msg.topic, msg.payload,
                                    "Hospital with id '{}' does not exist".format(hospital_id))
            return

        except Exception as e:

            # send error message to user
            self.send_error_message(user, msg.topic, msg.payload,
                                    "Exception: '{}'".format(e))
            return

        logger.debug('on_hospital: hospital = {}'.format(hospital))

        try:

            # update hospital
            serializer = HospitalSerializer(hospital,
                                            data=data,
                                            partial=True)
            if serializer.is_valid():

                logger.debug('on_hospital: valid serializer')

                # save to database
                serializer.save(updated_by=user)

            else:

                logger.debug('on_hospital: INVALID serializer')

                # send error message to user
                self.send_error_message(user, msg.topic, msg.payload,
                                        serializer.errors)

        except Exception as e:

            logger.debug('on_hospital: serializer EXCEPTION')

            # send error message to user
            self.send_error_message(user, msg.topic, msg.payload, e)

        logger.debug('on_hospital: DONE')

    # Update hospital equipment
    def on_hospital_equipment(self, client, userdata, msg):

        logger.debug("on_hospital_equipment: msg = '{}:{}'".format(msg.topic, msg.payload))

        # parse topic
        values = self.parse_topic(msg)
        if not values:
            return

        logger.debug("on_hospital_equipment: values = '{}'".format(values))

        try:

            # retrieve parsed values
            user, data, hospital_id, equipment_name = values

            # retrieve hospital equipment
            hospital_equipment = HospitalEquipment.objects.get(hospital=hospital_id,
                                                               equipment__name=equipment_name)

        except ObjectDoesNotExist:

            # send error message to user
            self.send_error_message(user, msg.topic, msg.payload,
                                    "Hospital equipment with hospital id '{}' and name '{}' does not exist".format(hospital_id, equipment_name))
            return

        except Exception as e:

            # send error message to user
            self.send_error_message(user, msg.topic, msg.payload,
                                    "Exception: '{}'".format(e))
            return

        logger.debug('on_hospital_equipment: equipment = {}'.format(hospital_equipment))

        try:

            # update hospital equipment
            serializer = HospitalEquipmentSerializer(hospital_equipment,
                                                     data=data,
                                                     partial=True)
            if serializer.is_valid():

                logger.debug('on_hospital_equipment: valid serializer')

                # save to database
                serializer.save(updated_by=user)

            else:

                logger.debug('on_hospital_equipment: INVALID serializer')

                # send error message to user
                self.send_error_message(user, msg.topic, msg.payload,
                                        serializer.errors)

        except Exception as e:

            logger.debug('on_hospital_equipment: serializer EXCEPTION')

            # send error message to user
            self.send_error_message(user, msg.topic, msg.payload, e)

        logger.debug('on_hospital_equipment: DONE')


#!/usr/bin/env python3

from __future__ import annotations

import sys
from dataclasses import dataclass, field
from enum import Enum
from typing import List, Tuple

ROTATION_LOOKUP = {
    'L': -1,
    'R': 1,
}

class Direction(Enum):
    RIGHT = 0
    DOWN = 1
    LEFT = 2
    UP = 3

class Action:
    def perform(self, board: Board):
        raise NotImplementedError

@dataclass()
class Turn(Action):
    rotation: int

    def perform(self, board: Board):
        board.direction = Direction((board.direction.value + self.rotation) % len(Direction))

@dataclass()
class Move(Action):
    count: int

    def perform(self, board: Board):
        for _ in range(self.count):
            if not board.move():
                return

@dataclass
class Board:
    board: List[str]
    x: int = field(default=0)
    y: int = field(default=0)
    face_size: int = field(default=0)
    direction: Direction = field(default=Direction.RIGHT)

    def __post_init__(self):
        first_line = self.board[0]
        self.x = first_line.index('.')
        self.face_size = len(first_line.replace(' ', ''))

    def char_at(self, x, y):
        return self.board[y][x]

    def move(self):
        if self.direction == Direction.LEFT:
            new_x = self.x - 1
            new_y = self.y
            new_direction = self.direction

            if new_x < 0 or self.char_at(new_x, self.y) == ' ':
                if new_y < self.face_size:
                    new_x = self.face_size + self.y
                    new_y = self.face_size
                    new_direction = Direction.DOWN
                elif new_y < self.face_size * 2:
                    new_x = self.face_size * 4 - (self.y - self.face_size + 1)
                    new_y = self.face_size * 3 - 1
                    new_direction = Direction.UP
                else:
                    new_x = self.face_size * 2 - (self.y - self.face_size * 2 + 1)
                    new_y = self.face_size * 2 - 1
                    new_direction = Direction.UP

            if self.char_at(new_x, new_y) == '.':
                self.x = new_x
                self.y = new_y
                self.direction = new_direction
                return True
            return False

        if self.direction == Direction.RIGHT:
            new_x = self.x + 1
            new_y = self.y
            new_direction = self.direction

            if new_x == len(self.board[self.y]) or self.char_at(new_x, self.y) == ' ':
                if new_y < self.face_size:
                    new_x = self.face_size * 4 - 1
                    new_y = self.face_size * 2 + (self.face_size - self.y) - 1
                    new_direction = Direction.LEFT
                elif new_y < self.face_size * 2:
                    new_x = self.face_size * 3 + (self.face_size * 2 - self.y) - 1
                    new_y = self.face_size * 2
                    new_direction = Direction.DOWN
                else:
                    new_x = self.face_size * 2 - (self.y - self.face_size * 2 + 1)
                    new_y = self.face_size * 2 - 1
                    new_direction = Direction.RIGHT

            if self.char_at(new_x, new_y) == '.':
                self.x = new_x
                self.y = new_y
                self.direction = new_direction
                return True
            return False

        if self.direction == Direction.UP:
            new_x = self.x
            new_y = self.y - 1
            new_direction = self.direction

            if new_y < 0 or len(self.board[new_y]) <= self.x or self.char_at(self.x, new_y) == ' ':
                if new_x < self.face_size:
                    new_x = self.face_size * 3 - 1 - self.x
                    new_y = 0
                    new_direction = Direction.DOWN
                elif new_x < self.face_size * 2:
                    new_x = self.face_size * 2
                    new_y = self.x - self.face_size
                    new_direction = Direction.RIGHT
                elif new_x < self.face_size * 3:
                    new_x = self.face_size - (self.x - self.face_size * 2) - 1
                    new_y = self.face_size
                    new_direction = Direction.DOWN
                else:
                    new_x = self.face_size * 3 - 1
                    new_y = self.face_size + (self.face_size * 4 - self.x) - 1
                    new_direction = Direction.RIGHT

            print(self.x, self.y)
            print(new_x, new_y)

            if self.char_at(new_x, new_y) == '.':
                self.x = new_x
                self.y = new_y
                self.direction = new_direction
                return True
            return False

        if self.direction == Direction.DOWN:
            new_x = self.x
            new_y = self.y + 1
            new_direction = self.direction

            if new_y == len(self.board) or len(self.board[new_y]) <= self.x or self.char_at(self.x, new_y) == ' ':
                if new_x < self.face_size:
                    new_x = self.face_size * 3 - 1 - self.x
                    new_y = self.face_size * 3 - 1
                    new_direction = Direction.UP
                elif new_x < self.face_size * 2:
                    new_x = self.face_size * 2
                    new_y = self.face_size * 3 - 1 - (self.face_size * 2 - self.x)
                    new_direction = Direction.RIGHT
                elif new_x < self.face_size * 3:
                    new_x = self.face_size - (self.x - self.face_size * 2) - 1
                    new_y = self.face_size * 2 - 1
                    new_direction = Direction.UP
                else:
                    new_x = 0
                    new_y = self.face_size + (self.face_size * 4 - self.x) - 1
                    new_direction = Direction.RIGHT

            if self.char_at(new_x, new_y) == '.':
                self.x = new_x
                self.y = new_y
                self.direction = new_direction
                return True
            return False

    def display_board(self):
        dir_char = None
        if self.direction == Direction.UP:
            dir_char = '^'
        elif self.direction == Direction.RIGHT:
            dir_char = '>'
        elif self.direction == Direction.DOWN:
            dir_char = 'v'
        elif self.direction == Direction.LEFT:
            dir_char = '<'

        for y in range(len(self.board)):
            if y == self.y:
                print(self.board[y][:self.x] + dir_char + self.board[y][self.x + 1:])
            else:
                print(self.board[y])

def read_board_and_actions() -> Tuple[Board, List[Action]]:
    board = []
    actions_str = None
    face_size = None
    while True:
        line = sys.stdin.readline()
        if not line:
            break
        line = line.strip('\n')
        if not line:
            continue

        print(line)
        chars = set(list(line))
        if chars - {' ', '.', '#', }:
            actions_str = line
            break

        board.append(line)

    print(board)
    print(actions_str)
    print(line)
    actions = []
    number = ''
    for char in actions_str:
        if char in ROTATION_LOOKUP.keys():
            actions.append(Move(count=int(number)))
            actions.append(Turn(rotation=ROTATION_LOOKUP[char]))
            number = ''
        else:
            number += char

    if number:
        actions.append(Move(count=int(number)))

    return Board(board=board), actions

def main():
    board, actions = read_board_and_actions()
    print(board)
    print(actions)
    for action in actions:
        print(board.display_board())
        print()
        action.perform(board=board)

    print(board.display_board())
    print()
    print(1000 * (board.y + 1) + 4 * (board.x + 1) + board.direction.value)

if __name__ == '__main__':
    # import cProfile
    # import re
    #
    # cProfile.run('main()')
    main()


import os, sys

sys.path.insert(0, "srcPython")
import mvn
import util
import numpy as np
import quaternion as quat
import open3d as o3d  # To Do minimal import
import matplotlib.pyplot as plt
import copy

class Pose:
    """Defines a subjects pose at a given frame:
    :sub: <Subject> subject.
    :frame: <int> frame number of trial to compute.
    """

    def __init__(self, sub, frame):

        self.frame = frame
        self.points = {}
        self.vectors = {}
        self.area = None
        self.volume = None
        self.coordinate_system = "Xsens"  # Xsens, GCS, LCS
        self.__get_points(sub)
        self.__get_xsens_ori()
        self.__to_ground()
        self.__to_lcs()

        self.__get_volume()
        # self.__get_gcs_kin(sub)
        # self.__to_gcs()
        try:
            self.__get_area()
        except:
            print("WARNING: An error occured in estimating area skipping calculation")

    def __str__(self):
        com = self.get_com()
        vel = self.get_com_vel()
        acc = self.get_com_acc()
        origin = self.__get_origin()
        ori = self.__get_ori()

        return """
        Pose at frame {self.frame}:
        \t Coordinate System: {self.coordinate_system}
        \t Area: {self.area} m^2
        \t Volume: {self.volume} m^3
        \t CoM: {com} m
        \t Com Vel: {vel} m/s
        \t Com Acc: {acc} m/s/s
        \t Global Origin: {origin} m
        \t Direction: {ori}
        """.format(
            self=self,
            com=self.get_com(),
            vel=self.get_com_vel(),
            acc=self.get_com_acc(),
            origin=self.__get_point("Origin"),
            ori=self.__get_vector("Ori"),
        )

    def __get_points(self, sub):
        for seg in mvn.SEGMENTS.items():
            if seg[1] == "com":
                # Get CoM accounting for mass of skis/poles
                self.points["CoM"] = (
                    sub.mvnx.get_segment_pos(seg[0], self.frame)
                    # + (
                    #     sub.mvnx.get_segment_pos(mvn.SEGMENT_LEFT_HAND, self.frame)
                    #     / sub.get_pole_mass()
                    # )
                    # + (
                    #     sub.mvnx.get_segment_pos(mvn.SEGMENT_RIGHT_HAND, self.frame)
                    #     / sub.get_pole_mass()
                    # )
                    # + (
                    #     sub.mvnx.get_segment_pos(mvn.SEGMENT_LEFT_TOE, self.frame)
                    #     / sub.get_ski_mass()
                    # )
                    # + (
                    #     / sub.get_ski_mass()
                    # )
                )
            else:
                self.points[seg[1]] = sub.mvnx.get_segment_pos(seg[0], self.frame)
        self.points["Origin"] = sub.mvnx.get_segment_pos(
            mvn.SEGMENT_CENTER_OF_MASS, self.frame
        )

        self.vectors["XsensCoMVel"] = sub.mvnx.get_center_of_mass_vel(self.frame)
        self.vectors["XsensCoMAcc"] = sub.mvnx.get_center_of_mass_acc(self.frame)
        self.vectors["XsensOri"] = np.quaternion(
            *sub.mvnx.get_segment_ori(mvn.SEGMENT_PELVIS, self.frame)
        )

    def __get_point(self, point):
        return copy.deepcopy(self.points[point])

    def __get_vector(self, vector):
        return copy.deepcopy(self.vectors[vector])

    def get_com(self):
        return copy.deepcopy(self.points["CoM"])

    def __get_origin(self):
        return copy.deepcopy(self.points["Origin"])

    def get_com_vel(self):
        com_vel = None
        if self.coordinate_system == "GCS":
            com_vel = copy.deepcopy(self.vectors["XsensCoMVel"]) + copy.deepcopy(
                self.vectors["GCSVel"]
            )
        elif self.coordinate_system == "LCS":
            com_vel = copy.deepcopy(self.vectors["XsensCoMVel"])
        return com_vel

    def get_com_acc(self):
        com_acc = None
        if self.coordinate_system == "GCS":
            com_acc = copy.deepcopy(self.vectors["XsensCoMAcc"]) + copy.deepcopy(
                self.vectors["GCSAcc"]
            )
        elif self.coordinate_system == "LCS":
            com_acc = copy.deepcopy(self.vectors["XsensCoMAcc"])
        return com_acc + [0, 0, -util.GRAVITY]

    def __get_ori(self):
        return copy.deepcopy(self.vectors["Ori"])

    def __to_lcs(self):
        # for i, k in enumerate(self.points.keys()):
        #     self.points[k] = self.points[k] - self.get_com()
        #
        for i, k in enumerate(self.points.keys()):
            self.points[k] = quat.rotate_vectors(
                self.vectors["LCSOri"], self.__get_point(k)
            )
        self.coordinate_system = "LCS"

    def __to_gcs(self):
        if self.coordinate_system == "GCS":
            print("WARNING: pose already in GCS - doing nothing")

        elif self.coordinate_system != "LCS":
            self.__to_lcs()
            ori = self.vectors["Ori"]
            for i, k in enumerate(self.points.keys()):
                if k != "GCSOrigin":
                    self.points[k] = (
                        quat.rotate_vectors(self.vectors["Ori"], self.__get_point(k))
                        + self.points["GCSOrigin"]
                    )
            for i, k in enumerate(self.vectors.keys()):
                if k in ["XsensCoMVel", "XsensCoMAcc"]:
                    self.vectors[k] = quat.rotate_vectors(ori, self.__get_vector(k))
        else:
            ori = self.vectors["Ori"]
            for i, k in enumerate(self.points.keys()):
                if k != "GCSOrigin":
                    self.points[k] = (
                        quat.rotate_vectors(ori, self.__get_point(k))
                        + self.points["GCSOrigin"]
                    )

            for i, k in enumerate(self.vectors.keys()):
                if k in ["XsensCoMVel", "XsensCoMAcc"]:
                    self.vectors[k] = quat.rotate_vectors(ori, self.__get_vector(k))

        self.coordinate_system = "GCS"

    def __to_ground(self):
        min_height = 1e12
        # pts = copy.deepcopy(self.points)
        for i, k in enumerate(self.points.keys()):
            if k not in ["Origin", "CoM"]:
                if self.points[k][2] < min_height:
                    min_height = self.points[k][2]

        if min_height != 0:
            for i, k in enumerate(self.points.keys()):
                if k == "CoM":
                    com = self.get_com()
                    com[2] = com[2] - min_height
                    self.points["CoM"] = copy.deepcopy(com)
                elif k != "CoM":
                    self.points[k][2] = self.points[k][2] - min_height

    def plot_area(self):
        point_vol = []
        for i, k in enumerate(self.points.keys()):
            pt = self.__get_point(k)
            point_vol.append([pt[0], 0, pt[2]])
            point_vol.append([pt[0], 1, pt[2]])
        point_vol = np.array(point_vol)

        pt_cloud = o3d.geometry.PointCloud()
        pt_cloud.points = o3d.utility.Vector3dVector(point_vol)
        tmp_norms = np.zeros((point_vol.shape[0], 3))
        tmp_norms[:, 1] = 1.0
        pt_cloud.normals = o3d.utility.Vector3dVector(tmp_norms)
        hull, _ = pt_cloud.compute_convex_hull()
        # convert to point cloud
        ax = plt.subplot()
        for i in range(point_vol.shape[0]):
            ax.scatter(point_vol[i, 0], point_vol[i, 2], color="grey")
        ax.scatter(point_vol[15, 0], point_vol[15, 2], color="green")
        ax.scatter(point_vol[19, 0], point_vol[19, 2], color="red")

        ax.set_aspect("equal")
        ax.set_title("Frontal Plane area ")
        plt.show()

        return ax, hull

    def __get_area(self, debug=False):
        # Generate point cloud.  Note projection by 1unit in x direction
        # so that area = volume
        point_vol = []
        for i, k in enumerate(self.points.keys()):
            pt = self.__get_point(k)
            point_vol.append([pt[0], 0, pt[2]])
            point_vol.append([pt[0], 1, pt[2]])
        point_vol = np.array(point_vol)

        # convert to point cloud
        if debug:
            ax = plt.subplot()
            for i in range(point_vol.shape[0]):
                ax.scatter(point_vol[i, 0], point_vol[i, 2])
            ax.scatter(point_vol[15, 0], point_vol[15, 2], color="green")
            ax.scatter(point_vol[19, 0], point_vol[19, 2], color="red")

            ax.set_aspect("equal")
            ax.set_title("Frontal Plane area calc")
            plt.show()

        pt_cloud = o3d.geometry.PointCloud()
        pt_cloud.points = o3d.utility.Vector3dVector(point_vol)
        tmp_norms = np.zeros((point_vol.shape[0], 3))
        tmp_norms[:, 1] = 1.0
        pt_cloud.normals = o3d.utility.Vector3dVector(tmp_norms)
        hull, _ = pt_cloud.compute_convex_hull()

        self.area = hull.get_volume() / 1

    def __get_volume(self):
        pts = []
        for i, k in enumerate(self.points.keys()):
            pts.append(self.__get_point(k))

        pts = np.asarray(pts)
        # create convex hull
        pt_cloud = o3d.geometry.PointCloud()
        pt_cloud.points = o3d.utility.Vector3dVector(pts)
        hull, _ = pt_cloud.compute_convex_hull()

        self.volume = hull.get_volume()

    def __parse_coordinate_systems(self, cs):
        if cs not in ["GCS", "LCS", "Xsens"]:
            raise ValueError(
                '{} is not a valid coordinate system.  \nValid coordinate systems are ["GCS", "LCS", "Xsens"]'
            )

    def __get_xsens_ori(self):
        pelvis = self.points["Pelvis"]
        r_hip = self.points["RightUpperLeg"]

        # rotate and project given orientation of pelvis.
        v1 = r_hip - pelvis
        v3 = np.array([0, 0, 1])
        v2 = np.cross(v3, v1)
        v1 = np.cross(v2, v3)
        v1 = v1 / np.linalg.norm(v1)
        v2 = v2 / np.linalg.norm(v2)
        v3 = v3 / np.linalg.norm(v3)

        self.vectors["LCSOri"] = util.rel_quat(
            v1, [1, 0, 0]
        )  # make v1 the new x axis...

    def __get_gcs_kin(self, sub):
        ori = sub.gnss.vel[self.frame, :]

        self.vectors["Ori"] = util.rel_quat(ori, [1, 0, 0])
        self.points["GCSOrigin"] = sub.gnss.pos[self.frame, :]

        self.vectors["GCSVel"] = sub.gnss.vel[self.frame, :]
        self.vectors["GCSAcc"] = sub.gnss.acc[self.frame, :]

    def plot_pose(self, title=""):
        """
        Plot a subjects pose
        """

        if self.coordinate_system == "GCS":
            xlabel = "X"
            ylabel = "Y"
        else:
            xlabel = "X [m]"
            ylabel = "Y [m]"

        zlabel = "Up [m]"

        pts = self.points

        fig = plt.figure(0)
        ax = plt.axes(projection="3d")
        ax.set_xlabel(xlabel)
        ax.set_ylabel(ylabel)
        ax.set_zlabel(zlabel)

        for i, k in enumerate(pts.keys()):
            pt = pts[k]
            if k == "RightShoulder":
                ax.scatter(pt[1], pt[0], pt[2], color=util.CMAP(0))
            elif k == "LeftShoulder":
                ax.scatter(pt[1], pt[0], pt[2], color=util.CMAP(0))
            elif k[:4] == "Righ":
                ax.scatter(pt[1], pt[0], pt[2], color=util.CMAP(2))
            elif k[:4] == "Left":
                ax.scatter(pt[1], pt[0], pt[2], color=util.CMAP(3))
            elif k[:4] == "CoM":
                ax.scatter(pt[1], pt[0], pt[2], color="black")
            elif k[:4] == "Orig":
                break
            else:
                ax.scatter(pt[1], pt[0], pt[2], color=util.CMAP(0))

            print("Point{p}: {pp}".format(p=k, pp=pt))

        ax.add_artist(
            util.Arrow3D(
                [pts["Pelvis"][1], pts["L5"][1]],
                [pts["Pelvis"][0], pts["L5"][0]],
                [pts["Pelvis"][2], pts["L5"][2]],
                **dict(mutation_scale=3, arrowstyle="-", color=util.CMAP(0)),
            )
        )
        ax.add_artist(
            util.Arrow3D(
                [pts["L5"][1], pts["L3"][1]],
                [pts["L5"][0], pts["L3"][0]],
                [pts["L5"][2], pts["L3"][2]],
                **dict(mutation_scale=3, arrowstyle="-", color=util.CMAP(0)),
            )
        )
        ax.add_artist(
            util.Arrow3D(
                [pts["L3"][1], pts["T12"][1]],
                [pts["L3"][0], pts["T12"][0]],
                [pts["L3"][2], pts["T12"][2]],
                **dict(mutation_scale=3, arrowstyle="-", color=util.CMAP(0)),
            )
        )
        ax.add_artist(
            util.Arrow3D(
                [pts["T12"][1], pts["Neck"][1]],
                [pts["T12"][0], pts["Neck"][0]],
                [pts["T12"][2], pts["Neck"][2]],
                **dict(mutation_scale=3, arrowstyle="-", color=util.CMAP(0)),
            )
        )
        ax.add_artist(
            util.Arrow3D(
                [pts["Neck"][1], pts["Head"][1]],
                [pts["Neck"][0], pts["Head"][0]],
                [pts["Neck"][2], pts["Head"][2]],
                **dict(mutation_scale=3, arrowstyle="-", color=util.CMAP(0)),
            )
        )
        ax.add_artist(
            util.Arrow3D(
                [pts["T8"][1], pts["RightShoulder"][1]],
                [pts["T8"][0], pts["RightShoulder"][0]],
                [pts["T8"][2], pts["RightShoulder"][2]],
                **dict(mutation_scale=3, arrowstyle="-", color=util.CMAP(0)),
            )
        )
        ax.add_artist(
            util.Arrow3D(
                [pts["T8"][1], pts["LeftShoulder"][1]],
                [pts["T8"][0], pts["LeftShoulder"][0]],
                [pts["T8"][2], pts["LeftShoulder"][2]],
                **dict(mutation_scale=3, arrowstyle="-", color=util.CMAP(0)),
            )
        )
        ax.add_artist(
            util.Arrow3D(
                [pts["Neck"][1], pts["RightShoulder"][1]],
                [pts["Neck"][0], pts["RightShoulder"][0]],
                [pts["Neck"][2], pts["RightShoulder"][2]],
                **dict(mutation_scale=3, arrowstyle="-", color=util.CMAP(0)),
            )
        )
        ax.add_artist(
            util.Arrow3D(
                [pts["Neck"][1], pts["LeftShoulder"][1]],
                [pts["Neck"][0], pts["LeftShoulder"][0]],
                [pts["Neck"][2], pts["LeftShoulder"][2]],
                **dict(mutation_scale=3, arrowstyle="-", color=util.CMAP(0)),
            )
        )

        ax.add_artist(
            util.Arrow3D(
                [pts["LeftShoulder"][1], pts["LeftUpperArm"][1]],
                [pts["LeftShoulder"][0], pts["LeftUpperArm"][0]],
                [pts["LeftShoulder"][2], pts["LeftUpperArm"][2]],
                **dict(mutation_scale=3, arrowstyle="-", color=util.CMAP(3)),
            )
        )
        ax.add_artist(
            util.Arrow3D(
                [pts["LeftUpperArm"][1], pts["LeftForeArm"][1]],
                [pts["LeftUpperArm"][0], pts["LeftForeArm"][0]],
                [pts["LeftUpperArm"][2], pts["LeftForeArm"][2]],
                **dict(mutation_scale=3, arrowstyle="-", color=util.CMAP(3)),
            )
        )
        ax.add_artist(
            util.Arrow3D(
                [pts["LeftForeArm"][1], pts["LeftHand"][1]],
                [pts["LeftForeArm"][0], pts["LeftHand"][0]],
                [pts["LeftForeArm"][2], pts["LeftHand"][2]],
                **dict(mutation_scale=3, arrowstyle="-", color=util.CMAP(3)),
            )
        )

        ax.add_artist(
            util.Arrow3D(
                [pts["RightShoulder"][1], pts["RightUpperArm"][1]],
                [pts["RightShoulder"][0], pts["RightUpperArm"][0]],
                [pts["RightShoulder"][2], pts["RightUpperArm"][2]],
                **dict(mutation_scale=3, arrowstyle="-", color=util.CMAP(2)),
            )
        )
        ax.add_artist(
            util.Arrow3D(
                [pts["RightUpperArm"][1], pts["RightForeArm"][1]],
                [pts["RightUpperArm"][0], pts["RightForeArm"][0]],
                [pts["RightUpperArm"][2], pts["RightForeArm"][2]],
                **dict(mutation_scale=3, arrowstyle="-", color=util.CMAP(2)),
            )
        )
        ax.add_artist(
            util.Arrow3D(
                [pts["RightForeArm"][1], pts["RightHand"][1]],
                [pts["RightForeArm"][0], pts["RightHand"][0]],
                [pts["RightForeArm"][2], pts["RightHand"][2]],
                **dict(mutation_scale=3, arrowstyle="-", color=util.CMAP(2)),
            )
        )

        ax.add_artist(
            util.Arrow3D(
                [pts["Pelvis"][1], pts["LeftUpperLeg"][1]],
                [pts["Pelvis"][0], pts["LeftUpperLeg"][0]],
                [pts["Pelvis"][2], pts["LeftUpperLeg"][2]],
                **dict(mutation_scale=3, arrowstyle="-", color=util.CMAP(3)),
            )
        )
        ax.add_artist(
            util.Arrow3D(
                [pts["LeftUpperLeg"][1], pts["LeftLowerLeg"][1]],
                [pts["LeftUpperLeg"][0], pts["LeftLowerLeg"][0]],
                [pts["LeftUpperLeg"][2], pts["LeftLowerLeg"][2]],
                **dict(mutation_scale=3, arrowstyle="-", color=util.CMAP(3)),
            )
        )
        ax.add_artist(
            util.Arrow3D(
                [pts["LeftLowerLeg"][1], pts["LeftFoot"][1]],
                [pts["LeftLowerLeg"][0], pts["LeftFoot"][0]],
                [pts["LeftLowerLeg"][2], pts["LeftFoot"][2]],
                **dict(mutation_scale=3, arrowstyle="-", color=util.CMAP(3)),
            )
        )
        ax.add_artist(
            util.Arrow3D(
                [pts["LeftFoot"][1], pts["LeftToe"][1]],
                [pts["LeftFoot"][0], pts["LeftToe"][0]],
                [pts["LeftFoot"][2], pts["LeftToe"][2]],
                **dict(mutation_scale=3, arrowstyle="-", color=util.CMAP(3)),
            )
        )

        ax.add_artist(
            util.Arrow3D(
                [pts["Pelvis"][1], pts["RightUpperLeg"][1]],
                [pts["Pelvis"][0], pts["RightUpperLeg"][0]],
                [pts["Pelvis"][2], pts["RightUpperLeg"][2]],
                **dict(mutation_scale=3, arrowstyle="-", color=util.CMAP(2)),
            )
        )
        ax.add_artist(
            util.Arrow3D(
                [pts["RightUpperLeg"][1], pts["RightLowerLeg"][1]],
                [pts["RightUpperLeg"][0], pts["RightLowerLeg"][0]],
                [pts["RightUpperLeg"][2], pts["RightLowerLeg"][2]],
                **dict(mutation_scale=3, arrowstyle="-", color=util.CMAP(2)),
            )
        )
        ax.add_artist(
            util.Arrow3D(
                [pts["RightLowerLeg"][1], pts["RightFoot"][1]],
                [pts["RightLowerLeg"][0], pts["RightFoot"][0]],
                [pts["RightLowerLeg"][2], pts["RightFoot"][2]],
                **dict(mutation_scale=3, arrowstyle="-", color=util.CMAP(2)),
            )
        )
        ax.add_artist(
            util.Arrow3D(
                [pts["RightFoot"][1], pts["RightToe"][1]],
                [pts["RightFoot"][0], pts["RightToe"][0]],
                [pts["RightFoot"][2], pts["RightToe"][2]],
                **dict(mutation_scale=3, arrowstyle="-", color=util.CMAP(2)),
            )
        )
        # com_vel = self.get_com_vel()
        # com_acc = self.get_com_acc()
        # com = self.get_com()
        # if com_vel is not None:
        #     print("COM = {}".format(com))
        #     print("CoM Velocity = {}".format(com_vel))
        #     ax.add_artist(
        #         util.Arrow3D(
        #             [com[1], com[1] + com_vel[1]],
        #             [com[0], com[0] + com_vel[0]],
        #             [com[2], com[2] + com_vel[2]],
        #             **dict(mutation_scale=3, arrowstyle="-|>", color="green"),
        #         )
        #     )
        # if com_acc is not None:
        #     print("CoM Acceleration = {}".format(com_acc))
        #     ax.add_artist(
        #         util.Arrow3D(
        #             [com[1], com[1] + com_acc[1]],
        #             [com[0], com[0] + com_acc[0]],
        #             [com[2], com[2] + com_acc[2]],
        #             **dict(mutation_scale=3, arrowstyle="-|>", color="red"),
        #         )
        #     )

        limits = np.array([getattr(ax, f"get_{axis}lim")() for axis in "xyz"])
        ax.set_box_aspect(np.ptp(limits, axis=1))
        ax.set_title(title)
        plt.show(block=True)  # show plot
        return fig, ax

if __name__ == "__main__":
    from subject import Subject

    sub = Subject(3)
    sub.load_trial("hard", "xsens")

    frame = 32301
    frame = 43500
    p = Pose(sub, frame)

    vel = p.get_com_vel()
    com = p.get_com()
    ax = plt.subplot()
    ax.plot(sub.gnss.pos[:, 1], sub.gnss.pos[:, 0])
    ax.scatter(sub.gnss.pos[frame, 1], sub.gnss.pos[frame, 0])
    ax.scatter(com[1], com[0], color="green")
    ax.arrow(com[1], com[0], 5 * vel[1], 5 * vel[0], color="green")
    plt.show()

    p = Pose(sub, 43550)
    p = Pose(sub, 43600)
    p = Pose(sub, 43650)

    p2 = Pose(sub, 28000)

    frames = list(range(0, sub.mvnx.frame_count, 2000))
    poses = []
    for f in frames:
        poses.append(Pose(sub, f))

    fig, (ax1, ax2) = plt.subplots(1, 2)
    ax1.plot(sub.gnss.pos[:, 0], sub.gnss.pos[:, 1])
    scale = 1
    for p in poses:
        com = p.get_com()
        com_vel = p.get_com_vel()
        com_acc = p.get_com_acc() / util.GRAVITY  # convert to gs
        print(p.get_com())
        print(p.get_com_vel())
        ax1.arrow(com[0], com[1], scale * com_vel[0], scale * com_vel[1], color="green")
        ax1.arrow(com[0], com[1], com_acc[0], com_acc[1], color="red")

        ax2.arrow(com[1], com[2], scale * com_vel[1], scale * com_vel[2], color="green")
        ax2.arrow(com[1], com[2], com_acc[1], com_acc[2], color="red")
    fig.show()

    p = Pose(sub, 0)
    p.plot_pose()


import timeit
from tkinter import *
from tkinter import messagebox

from AI import ChessAI
from GUI.GUI import GUI
from Helper import Helper
from Move import Move, CantMoveError

class StartGUI(GUI):
    w_queens = 0
    b_queens = 0

    def __init__(self, root: Tk, move: Move, chess_ai: ChessAI):
        super().__init__(move)
        self.__root = root
        self.__chess_ai = chess_ai
        self.__active_images = dict()
        self.__is_piece_selected = False
        self.__old_square_drag_release = None
        self.__old_square_click = None

    @property
    def root(self) -> Tk:
        return self.__root

    def create_img(self, square_name: str, coordinate: tuple) -> None:
        piece_type, piece_color, piece_number = self._square_type_color_number[square_name]
        self._all_images[(piece_type, piece_color, piece_number)] = PhotoImage(file=Helper.get_image_path_by_piece_type_color_number(piece_type, piece_color, piece_number))
        self.__active_images[square_name] = self.widgets["game_canvas"].create_image(coordinate[0], coordinate[1], image=self._all_images[piece_type, piece_color, piece_number])

    def drag_image(self, mouse) -> None:
        square_name = Helper.get_square_name_by_gui_coordinate((mouse.x, mouse.y))

        if self.__active_images[square_name] is not None and not self.__is_piece_selected:
            self.__is_piece_selected = True
            self.__old_square_drag_release = square_name
            self.__old_square_click = None
        elif self.__is_piece_selected:
            self.create_img(self.__old_square_drag_release, (mouse.x, mouse.y))

    def click(self, mouse) -> None:
        square_name = Helper.get_square_name_by_gui_coordinate((mouse.x, mouse.y))
        coordinate = Helper.square_name_to_coordinate(square_name)
        available_moves = self._move.available_move_options(coordinate)

        if len(self._grey_dot_images.keys()) and self.__old_square_click:
            self.main_move_function_gui(mouse, self.__old_square_click, self.unselect_piece_click)
        elif self.__active_images[square_name]:
            piece_type, piece_color, piece_number = self._square_type_color_number[square_name]
            if piece_color == self._move.color_turn:
                self.__old_square_click = square_name

        self.delete_grey_dots()
        if self._move.check():
            available_moves = self._move.check_options(coordinate)
        if len(self._move.moves_that_place_king_in_check(coordinate)):
            available_moves = list((set(available_moves)).difference(set(self._move.moves_that_place_king_in_check(coordinate))))
        for move in available_moves:
            square = Helper.square_coordinate_to_name(move)
            gui_coordinate = Helper.get_gui_coordinate_by_square_name(square)
            self._grey_dot_images[square] = self.widgets["game_canvas"].create_image(gui_coordinate[0], gui_coordinate[1], image=self._grey_dot_image)

    def main_move_function_gui(self, mouse, square, unselect_piece) -> None:
        if square is None:
            return
        old_coordinate = Helper.square_name_to_coordinate(square)
        new_coordinate = Helper.square_name_to_coordinate(Helper.get_square_name_by_gui_coordinate((mouse.x, mouse.y)))
        try:
            moves = self._move.move(old_coordinate, new_coordinate)
        except CantMoveError:
            gui_coordinate = Helper.get_gui_coordinate_by_square_name(Helper.square_coordinate_to_name(old_coordinate))
            self.create_img(square, gui_coordinate)
            unselect_piece()
            return
        self.update_square(moves)
        self.delete_grey_dots()
        self.remove_check()
        self.check()
        unselect_piece()
        self.stalemate()
        self.checkmate()
        self.draw()
        self.three_fold_repetition()
        self.main_move_function_ai()

    def main_move_function_ai(self):
        t1 = timeit.default_timer()
        move = self.__chess_ai.minimax_root(1, True)
        t2 = timeit.default_timer()
        print(t2 - t1)
        try:
            self._move.move(list(move.keys())[0], list(move.values())[0])
        except AttributeError:
            return
        self.update_square(move)
        self.remove_check()
        self.check()
        self.stalemate()
        self.checkmate()
        self.draw()
        self.three_fold_repetition()

    def release(self, mouse) -> None:
        self.main_move_function_gui(mouse, self.__old_square_drag_release, self.unselect_piece_drag_release)

    def check(self) -> None:
        color = self._move.check()
        if color is not None:
            for square in Helper.get_all_square_names():
                piece_type, piece_color, piece_number = self._square_type_color_number[square]
                if piece_type == 'K' and piece_color == color:
                    gui_coordinate = Helper.get_gui_coordinate_by_square_name(square)
                    self._red_dot_images[square] = self.widgets["game_canvas"].create_image(gui_coordinate[0], gui_coordinate[1], image=self._red_dot_image)

    def remove_check(self) -> None:
        for square in self._red_dot_images.keys():
            self.widgets["game_canvas"].delete(self._red_dot_images[square])

    def unselect_piece_drag_release(self) -> None:
        self.__is_piece_selected = False
        self.__old_square_drag_release = None

    def unselect_piece_click(self) -> None:
        self.__old_square_click = None

    def delete_grey_dots(self) -> None:
        try:
            for square in self._grey_dot_images.keys():
                self.widgets["game_canvas"].delete(self._grey_dot_images[square])
        except TclError:
            pass

    def update_square(self, moves: dict) -> None:
        for move in moves.keys():
            old_square = Helper.square_coordinate_to_name(move)
            new_square = Helper.square_coordinate_to_name(moves[move])
            self.update_image(old_square, new_square)

    def update_image(self, old_square: str, new_square: str) -> None:
        piece_type, piece_color, piece_number = self._square_type_color_number[old_square]
        piece_type, piece_number = self.check_promotion(new_square, piece_type, piece_color, piece_number)
        new_coordinate = Helper.get_gui_coordinate_by_square_name(new_square)

        if self._move.last_move_was_en_passant:
            passant_square = Helper.square_coordinate_to_name(self._move.en_passant_coordinate_temp_1)
            self.widgets["game_canvas"].delete(self.__active_images[passant_square])
            self.__active_images[passant_square] = None
            self._square_type_color_number[passant_square] = None, None, None
            self._move.last_move_was_en_passant = False
            self._move.en_passant_coordinate_temp_1 = None

        self.widgets["game_canvas"].delete(self.__active_images[old_square])
        self.widgets["game_canvas"].delete(self.__active_images[new_square])
        self.__active_images[old_square] = None
        self.__active_images[new_square] = None

        self._all_images[(piece_type, piece_color, piece_number)] = PhotoImage(file=Helper.get_image_path_by_piece_type_color_number(piece_type, piece_color, piece_number))
        self.__active_images[new_square] = self.widgets["game_canvas"].create_image(new_coordinate[0], new_coordinate[1], image=self._all_images[piece_type, piece_color, piece_number])
        self._square_type_color_number[old_square] = None, None, None
        self._square_type_color_number[new_square] = piece_type, piece_color, piece_number

    def draw(self) -> None:
        if not self._move.is_draw:
            self._move.draw_the_game()
            if self._move.is_draw:
                draw_messagebox = messagebox.showinfo("Draw", "Draw by insufficient material!")
                Label(self.root, text=draw_messagebox).grid(row=0, column=0)
                self.root.destroy()

    def checkmate(self) -> None:
        if self._move.is_checkmate():
            checkmate_messagebox = messagebox.showinfo("Checkmate", "Checkmate!")
            Label(self.root, text=checkmate_messagebox).grid(row=0, column=0)
            self.root.destroy()

    def stalemate(self) -> None:
        if self._move.is_stalemate():
            stalemate_messagebox = messagebox.showinfo("Stalemate", "Stalemate!")
            Label(self.root, text=stalemate_messagebox).grid(row=0, column=0)
            self.root.destroy()

    def three_fold_repetition(self) -> None:
        if self._move.three_fold_repetition():
            three_fold_repetition_messagebox = messagebox.showinfo("Draw", "Draw by repetition!")
            Label(self.root, text=three_fold_repetition_messagebox).grid(row=0, column=0)
            self.root.destroy()

    @staticmethod
    def check_promotion(new_square: str, piece_type: str, piece_color: str, piece_number: str) -> tuple:
        if new_square[1] in ['1', '8'] and piece_type == 'p':
            if piece_color == "white":
                StartGUI.w_queens += 1
                return 'q', "R{}".format(StartGUI.w_queens)
            else:
                StartGUI.b_queens += 1
                return 'q', "R{}".format(StartGUI.b_queens)
        return piece_type, piece_number

    def position_pieces(self) -> None:
        for square_name in Helper.get_all_square_names():
            piece_type, piece_color, piece_number = Helper.get_piece_type_color_number_by_square_name(square_name)
            coordinate = Helper.get_gui_coordinate_by_square_name(square_name)
            try:
                self.__active_images[square_name] = self.widgets["game_canvas"].create_image(coordinate[0], coordinate[1], image=self._all_images[piece_type, piece_color, piece_number])
            except KeyError:
                self.__active_images[square_name] = None

    def play(self) -> None:
        self.destroyer()
        self.generator(self.root)

        game_canvas = self.widgets["game_canvas"]
        game_canvas.grid(row=0, column=0)
        game_canvas.create_image(0, 0, image=self._chess_board_image, anchor=NW)
        self.position_pieces()
        game_canvas.bind('<Button-1>', self.click)
        game_canvas.bind('<B1-Motion>', self.drag_image)
        game_canvas.bind('<ButtonRelease-1>', self.release)


import cv2
import numpy as np

# Importing the Libraries
image_file = r"F:\Fall 2021 NTNU\Computer Vision NTU\Chapter-7\HomeWork-10\lena.bmp"
gray_image = cv2.imread(image_file, 0)  # Read Image in Grayscale

def convolve(img, kernel):
    row_img, col_img = img.shape
    row_k, col_k = kernel.shape
    res = 0
    for h_row in range(row_img):
        for w_col in range(col_img):
            if 0 <= row_img - h_row - 1 < row_k and 0 <= col_img - w_col - 1 < col_k:
                res += img[h_row, w_col] * kernel[row_img - h_row - 1, col_img - w_col - 1]
    return res

def convolution_image(gray_image, kernel, threshold):
    # To avoid index out of bounds Error
    mask_img = np.zeros((gray_image.shape[0] - kernel.shape[0] + 1, gray_image.shape[1] - kernel.shape[1] + 1))
    for h_row in range(mask_img.shape[0]):
        for w_col in range(mask_img.shape[1]):
            value = convolve(gray_image[h_row:h_row + kernel.shape[0], w_col:w_col + kernel.shape[1]], kernel)
            if value >= threshold:
                mask_img[h_row, w_col] = 1
            elif value <= -threshold:
                mask_img[h_row, w_col] = -1
            else:
                mask_img[h_row, w_col] = 255

    return mask_img

def zero_crossing(masked_image):
    # 8 neighborhood zero crossing
    zero_cross_image = np.copy(masked_image)
    for h_row in range(0, masked_image.shape[0] - 1):
        for w_col in range(0, masked_image.shape[1] - 1):
            if masked_image[h_row, w_col] <= 0:
                zero_cross_image[h_row, w_col] = 255
            elif masked_image[h_row, w_col] == 1:
                if masked_image[h_row - 1, w_col - 1] == -1 or masked_image[h_row, w_col - 1] == -1 or masked_image[
                    h_row + 1, w_col - 1] == -1 \
                        or masked_image[h_row - 1, w_col] == -1 or masked_image[h_row + 1, w_col] == -1 or masked_image[
                    h_row - 1, w_col + 1] == -1 \
                        or masked_image[h_row, w_col + 1] == -1 or masked_image[h_row + 1, w_col + 1] == -1:
                    zero_cross_image[h_row, w_col] = 0
                else:
                    zero_cross_image[h_row,w_col] = 255
    return zero_cross_image

if __name__ == "__main__":
    # Laplace mask 1
    laplace_mask1_kernel = np.array([
        [0, 1, 0],
        [1, -4, 1],
        [0, 1, 0]
    ])
    laplace_mask1_image = convolution_image(gray_image, laplace_mask1_kernel, 15)
    zero_crossing_laplace_mask_image = zero_crossing(laplace_mask1_image)
    cv2.imshow('Zero Crossing Image', zero_crossing_laplace_mask_image)
    cv2.waitKey(0)
    # Laplace Mask 2
    laplace_mask2_kernel = np.array([
        [1, 1, 1],
        [1, -8, 1],
        [1, 1, 1]
    ]) / 3
    laplace_mask2_image = convolution_image(gray_image, laplace_mask2_kernel, 15)
    zero_crossing_laplace_mask2_image = zero_crossing(laplace_mask2_image)
    cv2.imshow('Zero Crossing laplace mask 2 Image', zero_crossing_laplace_mask2_image)
    cv2.waitKey(0)
    # Minimum Variance Laplacian
    minimum_variance_laplacian_kernel = np.array([
        [2., -1, 2],
        [-1, -4, -1],
        [2, -1, 2]
    ]) / 3
    minimum_variance_laplacian_image = convolution_image(gray_image, minimum_variance_laplacian_kernel, 15)
    zero_crossing_mvl_image = zero_crossing(minimum_variance_laplacian_image)
    cv2.imshow('Zero Crossing Minimum Variance Laplacian Image', zero_crossing_mvl_image)
    cv2.waitKey(0)
    # Laplace of Gaussian
    laplace_of_gaussian_kernel = np.array([
        [0, 0, 0, -1, -1, -2, -1, -1, 0, 0, 0],
        [0, 0, -2, -4, -8, -9, -8, -4, -2, 0, 0],
        [0, -2, -7, -15, -22, -23, -22, -15, -7, -2, 0],
        [-1, -4, -15, -24, -14, -1, -14, -24, -15, -4, -1],
        [-1, -8, -22, -14, 52, 103, 52, -14, -22, -8, -1],
        [-2, -9, -23, -1, 103, 178, 103, -1, -23, -9, -2],
        [-1, -8, -22, -14, 52, 103, 52, -14, -22, -8, -1],
        [-1, -4, -15, -24, -14, -1, -14, -24, -15, -4, -1],
        [0, -2, -7, -15, -22, -23, -22, -15, -7, -2, 0],
        [0, 0, -2, -4, -8, -9, -8, -4, -2, 0, 0],
        [0, 0, 0, -1, -1, -2, -1, -1, 0, 0, 0]
    ])
    laplace_of_gaussian_image = convolution_image(gray_image, laplace_of_gaussian_kernel, 3000)
    zero_crossing_log_image = zero_crossing(laplace_of_gaussian_image)
    cv2.imshow('Zero Crossing Laplace of Gaussian Image', zero_crossing_log_image)
    cv2.waitKey(0)
    # Difference of Gaussian
    difference_of_gaussian_kernel = np.array([
        [-1, -3, -4, -6, -7, -8, -7, -6, -4, -3, -1],
        [-3, -5, -8, -11, -13, -13, -13, -11, -8, -5, -3],
        [-4, -8, -12, -16, -17, -17, -17, -16, -12, -8, -4],
        [-6, -11, -16, -16, 0, 15, 0, -16, -16, -11, -6],
        [-7, -13, -17, 0, 85, 160, 85, 0, -17, -13, -7],
        [-8, -13, -17, 15, 160, 283, 160, 15, -17, -13, -8],
        [-7, -13, -17, 0, 85, 160, 85, 0, -17, -13, -7],
        [-6, -11, -16, -16, 0, 15, 0, -16, -16, -11, -6],
        [-4, -8, -12, -16, -17, -17, -17, -16, -12, -8, -4],
        [-3, -5, -8, -11, -13, -13, -13, -11, -8, -5, -3],
        [-1, -3, -4, -6, -7, -8, -7, -6, -4, -3, -1],
    ])
    difference_of_gaussian_image = convolution_image(gray_image, difference_of_gaussian_kernel, 1)
    zero_crossing_dog_image = zero_crossing(difference_of_gaussian_image)
    cv2.imshow('Zero Crossing Difference of Gaussian Image', zero_crossing_dog_image)
    cv2.waitKey(0)


__author__ = 'Georgios Rizos (georgerizos@iti.gr)'

from reveal_user_classification.preprocess.insight.insight_curation_util import make_folder_paths,\
    get_number_of_nodes, preprocess_graph_data, preprocess_feature_data, make_implicit_graphs, make_labelling

def preprocess_insight_curation_dataset(insight_curation_source_folder,
                                        dataset,
                                        graph_raw_data_files,
                                        feature_raw_data_files):
    # Calculate folder paths.
    raw_data_folder,\
    preprocessed_data_folder,\
    implicit_graph_folder,\
    simple_undirected_implicit_graph_folder = make_folder_paths(insight_curation_source_folder, dataset)

    # Get number of nodes.
    number_of_nodes = get_number_of_nodes(raw_data_folder, dataset)

    # Preprocess all graph data.
    for graph_raw_data_file in graph_raw_data_files:
        preprocess_graph_data(dataset,
                              raw_data_folder,
                              preprocessed_data_folder,
                              graph_raw_data_file,
                              number_of_nodes)

    # Preprocess all feature data.
    for feature_raw_data_file in feature_raw_data_files:
        preprocess_feature_data(dataset,
                                raw_data_folder,
                                preprocessed_data_folder,
                                feature_raw_data_file,
                                number_of_nodes)

    # Make all implicit graphs.
    make_implicit_graphs(preprocessed_data_folder, simple_undirected_implicit_graph_folder)

    # Make labelling.
    make_labelling(dataset, raw_data_folder, preprocessed_data_folder)

########################################################################################################################
# Configure preprocessing.
########################################################################################################################
SOURCE_FOLDER = "/home/georgerizos/Documents/LocalStorage/raw_data/Insight/Curation"

CURATION_DATASETS = ["alaska", "georgia", "idaho", "massachusetts", "northdakota", "ohio", "oklahoma", "tennessee",
                     "vermont", "virginia"]

GRAPH_RAW_DATA_FILES = ["followedby", "mentionedby", "retweetedby"]

FEATURE_RAW_DATA_FILES = ["colisted", "listdesc", "listmerged", "listnames", "tweets50", "tweets100", "tweets200"]

########################################################################################################################
# Preprocess all datasets.
########################################################################################################################
for DATASET in CURATION_DATASETS:
    preprocess_insight_curation_dataset(SOURCE_FOLDER,
                                        DATASET,
                                        GRAPH_RAW_DATA_FILES,
                                        FEATURE_RAW_DATA_FILES)


import math

from config_wrapper import global_config
from lease_pb2 import CapacityLease
from utils import clock, logger

# Default values for the lease duration, decay factor and refresh
# interval.
_kDefaultLeaseDuration = 60
_kDefaultDecayFactor = 0.5
_kDefaultRefreshInterval = 16

# Abstract base class for algorithm classes.
class AlgorithmImpl(object):

  # Factory method. Creates a specifica algorithm object
  # for a resource (based on its template). The algorithm
  # needs to know the server_level to calculate the refresh
  # intervals correctly.

  @classmethod
  def create(self, template, server_level):
    # If the template specifies the algorithm, that's the one
    # we will use. If not there might be a default algorithm
    # specified in the configuration. If that is not available
    # we default to the "None" algorithm.
    if template.HasField('algorithm'):
      algo = template.algorithm
    else:
      algo = global_config.get_default_algorithm()

    if algo.name == 'Static':
      from algo_static import StaticAlgorithm
      a = StaticAlgorithm(algo, server_level)
    elif algo.name == 'None':
      from algo_none import NoneAlgorithm
      a = NoneAlgorithm(algo, server_level)
    elif algo.name == 'ProportionalShare':
      from algo_proportional import ProportionalShareAlgorithm
      a = ProportionalShareAlgorithm(algo, server_level)
    else:
      logger.warning('Unknown algorithm: %s' % algo.name)
      a = NoneAlgorithm(algo, server_level)

    a.server_level = server_level

    return a

  # Gets a named algorithm parameter from the configuration. The
  # algorithm objects use this to get their configuration data.
  # Note: The returned value is always a string.
  def get_named_parameter(self, algo, name, default=None):
    for p in algo.param:
      if p.name == name:
        return p.value

    return default

  # Gets the standard parameters that many (well, at least
  # more than one) algorithms need, and stores them into the
  # algorithm object.
  def _get_default_parameters(self, algo):
    self.lease_duration_secs = int(
        self.get_named_parameter(
            algo, 'lease_duration_secs',
            _kDefaultLeaseDuration))
    self.decay_factor = float(
        self.get_named_parameter(
            algo, 'decay_factor',
            _kDefaultDecayFactor))
    self.refresh_interval = int(
        self.get_named_parameter(
            algo, 'refresh_interval',
            _kDefaultRefreshInterval))

  # Returns the refresh interval for this server, based on the
  # refresh_interval and the level of the server. The
  # refresh interval stored in the configuration is the interval
  # that the root server gives out, and then every level above
  # that halves that interval.
  def get_refresh_interval(self):
    return int(
        math.pow(self.decay_factor, self.server_level) *
        self.refresh_interval)

  # Returns the maximum lease duration this algorithm will ever
  # give out. The server needs to know that to determine the
  # time that a resources will be in learning mode.
  def get_max_lease_duration(self):
    return self.lease_duration_secs

  # Creates a new lease for a certain capacity for a given resource.
  def create_lease(self, resource, capacity):
    now = clock.get_time()

    # Creates the lease object and sets the essential properties.
    lease = CapacityLease()
    lease.capacity = capacity
    lease.refresh_interval = self.get_refresh_interval()

    # The server cannot give out a lease that lasts longer than
    # it itself has capacity for from a lower level.
    if resource.HasField('has'):
      lease.expiry_time = min(
          resource.has.expiry_time, now + self.lease_duration_secs)
    else:
      lease.expiry_time = now + self.lease_duration_secs

    # Edge case: If we are near the end of the lease we must make sure
    # that the refresh interval does not tell the client to do a refresh
    # after the resource has expired. If that happens, adjust the
    # refresh interval to just before the end of the lease expiration.
    if now + lease.refresh_interval >= lease.expiry_time:
      lease.refresh_interval = lease.expiry_time - now - 1

    assert lease.IsInitialized()

    return lease


"""Default settings for tests."""

import os
from pathlib import Path

import numpy as np

###################################################################################################
###################################################################################################

# Define general settings for test simulations
FS = 100
N_SECONDS = 10.0

FS_ODD = 123
N_SECONDS_ODD = 1/7

N_SECONDS_CYCLE = 1.0

# Define parameter options for test simulations
FREQ1 = 10
FREQ2 = 25
FREQ_SINE = 1
FREQS_LST = [8, 12, 1]
FREQS_ARR = np.array([5, 10, 15])
EXP1 = -1
EXP2 = -2
KNEE = 100

# Define settings for testing analyses
F_RANGE = (FREQ1-2, FREQ1+2)

# Define error tolerance levels for test comparisons
EPS = 10**(-10)
EPS_FILT = 10**(-3)

# Set paths for test files
TESTS_PATH = Path(os.path.abspath(os.path.dirname(__file__)))
BASE_TEST_FILE_PATH = TESTS_PATH / 'test_files'
TEST_PLOTS_PATH = os.path.join(BASE_TEST_FILE_PATH, 'plots')


import os

from bgcore import tsv
from bgcore.labelfilter import LabelFilter

from wok.logger import get_logger

from intogensm import so
from intogensm.config import GlobalConfig, PathsConfig
from intogensm.projects.db import ProjectDb

NON_SYN = 0
SYN = 1

class OncodriveClust(object):
	"OncodriveCLUST helper"

	def __init__(self, config, paths, logger=None):
		"""
		:param config: intogensm.config.OncodriveClustConfig
		:param paths: PathsConfig
		:param logger: Optional logger
		"""

		self.config = config
		self.paths = paths
		self.logger = logger or get_logger("oncodriveclust")

		self._load_config()

	def _load_config(self):
		self.logger.info("OncodriveCLUST configuration:")

		self.samples_threshold = self.config.samples_threshold

		default_filter = self.paths.data_gene_filter_path()
		self.filter_enabled = self.config.filter_enabled
		self.filter_path = self.config.filter_path or default_filter
		if self.filter_path is None: # user can assign a null
			self.filter_enabled = False
			self.filter_path = default_filter

		self.logger.info("  samples_threshold = {0}".format(self.samples_threshold))
		self.logger.info("  genes_filter_enabled = {0}".format(self.filter_enabled))
		self.logger.info("  genes_filter_path = {0}".format(os.path.basename(self.filter_path)))

		self.filter = LabelFilter()

		if self.filter_enabled:
			self.logger.info("Loading expression filter ...")
			self.logger.debug("> {0}".format(self.filter_path))
			self.filter.load(self.filter_path)

		return self

	def load_cds_len(self, path):

		self.logger.info("Loading transcripts CDS length ...")
		self.logger.debug("> {}".format(path))

		cds_len = {}
		with tsv.open(path, "r") as f:
			for gene, transcript, transcript_len in tsv.lines(f, (str, str, int), header=True):
				cds_len[transcript] = transcript_len
		return cds_len

	def retrieve_data(self, projdb):

		cds_len = self.load_cds_len(self.paths.data_ensembl_gene_transcripts_path())
		data = {}

		self.logger.info("Retrieving gene alterations for OncodriveCLUST ...")

		for csq in projdb.consequences(join_samples=True,
									   filters={ProjectDb.CSQ_CTYPES : so.ONCODRIVECLUST | so.SYNONYMOUS}):

			if csq.transcript not in cds_len:
				continue

			transcript_len = cds_len[csq.transcript]

			if so.match(csq.ctypes, so.ONCODRIVECLUST):
				cls = NON_SYN
			elif so.match(csq.ctypes, so.SYNONYMOUS):
				cls = SYN
			else:
				continue

			for sample in csq.var.samples:
				key = (cls, csq.gene, sample.name)
				if key not in data:
					data[key] = (csq.transcript, transcript_len, csq.protein_pos)
				else:
					transcript, tlen, protein_pos = data[key]
					if transcript_len > tlen:
						data[key] = (csq.transcript, transcript_len, csq.protein_pos)

		return data


#url = "https://bytebank.com/cambio?moedaOrigem=real&moedaDestino=dolar&quantidade=100"
#url = "bytebank.com/cambio?moedaOrigem=real"
url =" "

#Sanitização da URL
#url = url.replace(" ","") ||||||| um boa forma de tirar algo da string
url = url.strip()

#validação da URL
if url =="":
    raise ValueError("A URL está vazia")

#Separa base e parametro
indice_interrogacao = url.find('?')
url_base = url[0:indice_interrogacao]   #busca até o primeiro parametro de busca separedo por interrogação
url_parametros = url[indice_interrogacao+1:]  #indice do busca separeda, iniciando da interrogação até o fim da sting
print(url_parametros)

#Busca O valor de um parametro
parametro_busca = 'moedaOrigem'
indice_parametros = url_parametros.find(parametro_busca)
indice_valor = indice_parametros + len(parametro_busca)+1
indice_e_comercial = url_parametros.find('&')
if indice_e_comercial ==-1:
    valor = url_parametros[indice_valor:]
else:
    valor= url_parametros[indice_valor:indice_e_comercial]

print(valor)


import argparse
import pickle

from pythomata.impl.symbolic import SymbolicDFA

if __name__ == '__main__':
    parser = argparse.ArgumentParser("fix-automaton")
    parser.add_argument("-i", type=str, help="Path to automaton pickle file.", default="inputs/automaton.pickle")
    parser.add_argument("-o", type=str, help="Path to output file.", default="output.pickle")
    parser.add_argument("--render", type=str, help="Path to dot file.", default=None)

    arguments = parser.parse_args()
    with open(arguments.i, "rb") as fin:
        automaton: SymbolicDFA = pickle.load(fin)

    # States numbers
    to_explore = [automaton.initial_state]
    new2old = []
    while len(to_explore) > 0:
        state = to_explore.pop(0)
        new2old.append(state)
        for successor in sorted(automaton._transition_function[state].keys()):
            if successor not in new2old and successor not in to_explore:
                to_explore.append(successor)
    old2new = {old: new for new, old in enumerate(new2old)}

    # New automaton and states
    new_automaton = SymbolicDFA()
    for new_state, old_state in enumerate(new2old):
        if automaton.initial_state == old_state:
            assert old_state == 0
        else:
            new_assigned_state = new_automaton.create_state()
            assert new_assigned_state == new_state

        new_automaton.set_accepting_state(
            new_state, automaton.is_accepting(old_state))

    # Transitions
    for old_state in automaton.states:
        for old_next, guard in automaton._transition_function[old_state].items():
            new_automaton.add_transition((
                old2new[old_state], guard, old2new[old_next]
            ))

    # Save
    if arguments.render is not None:
        new_automaton.to_graphviz().render(arguments.render)
    with open(arguments.o, "wb") as fout:
        pickle.dump(new_automaton, fout, protocol=4)


class Solution:
    def groupAnagrams(self, strs) :
        prime = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103]
        dic = {}
        for s in strs:
            key = 1
            for c in s:
                key *= prime[ord(c) - 97]
            if key in dic:
                dic[key].append(s)
            else:
                dic[key] = [s]

        return list(dic.values())

a = Solution()
ans = a.groupAnagrams(["eat", "tea", "tan", "ate", "nat", "bat"])


import time
import os
import subprocess
import platform
from cv2 import *
#import fswebcam

def Capture(ID):
    cam = VideoCapture(0)   # 0 -> index of camera
    s, img = cam.read()
    if s:    # frame captured without any errors
        namedWindow("cam-test")
        imshow("cam-test",img)
        waitKey(0)
        destroyWindow("cam-test")
        imwrite("Subject%s.jpg" %ID,img) #save image

#Program Header

print("------------------------")
print("Kristan's Webcam Capture")
print("------------------------")

#Init Testing

dir_path = os.path.dirname(os.path.realpath(__file__))
print(dir_path)

#Get Varibales

Name = input("Please enter subject's name: ")
PhotoMax = int(input("How Many Photo's Would you like to take? \n"))
PhotoFreq = int(input("How long do you want photo preperation time to be?      (Seconds) \n"))

savepath = (dir_path + "/" + Name)
#print(savepath)

try:
    os.mkdir(savepath)
except OSError:
    print ("Creation of the directory %s failed" % savepath)
    os.chdir(savepath)
   # print(os.getcwd())
else:
    print ("Successfully created the directory %s " % savepath)
    os.chdir(savepath)
   # print(os.getcwd())

print("Starting Process")

print("Starting Process in 3 Seconds Please Prepare")
time.sleep(1)
print("Starting Process in 2 Seconds Please Prepare")
time.sleep(1)
print("Starting Process in 1 Seconds Please Prepare")
time.sleep(1)

print("Please Press Space To Continue To Next Image")

count = 0
while (count < PhotoMax):
 # os("fswebcam -r 1280x720 --no-banner Right1.jpg")
 print(count + 1)
 Capture(count + 1)
 time.sleep(PhotoFreq)
 count = count + 1
 #print(count + 1)
print ("Good bye!")


# https://www.acmicpc.net/problem/16973
# 부분합을 이용

n, m = map(int, input().split())
data = [[0] * (m + 1) for _ in range(n + 1)]
s = [[0] * (m + 1) for _ in range(n + 1)]
for i in range(1, n + 1):
    data[i][1:] = list(map(int, input().split()))
h, w, sr, sc, fr, fc = map(int, input().split())

from  collections import deque

# (부분합이용) 해당 직사각형을 움직였을 때, 1을 침범했는지 확인
def check(r, c, er, ec):
    return s[er][ec] - s[er - 1][ec] + s[er][ec - 1] + s[er][ec]

for i in range(1, n + 1):
    for j in range(1, m + 1):
        s[i][j] = s[i - 1][j] + s[i][j - 1] - s[i - 1][j - 1] + data[i][j]

q = deque()
q.append((sr, sc)) # 시작위치

dist = [[-1] * (m + 1) for _ in range(n + 1)]
dist[sr][sc] = 0

moves = [(0,1),(0,-1),(1,0),(-1,0)]

while q:
    r, c = q.popleft()
    for move in moves:
        nr = r + move[0]
        nc = c + move[1]
        if 1 <= nr \
            and 1 <= nc \
            and nr + h - 1 <= n \
            and nc + w - 1 <= m \
            and check(nr, nc, nr + h - 1, nr + w - 1) == 0 \
            and dist[nr][nc] == -1:
            dist[nr][nc] += dist[r][c] + 1
            q.append((nr, nc))

print(dist[fr][fc])

06_직사각형탈출.py


import numpy as np
from .Poly import Poly

class LLS(Poly):
    """Linear least-squares function approximation

    This class inherits our Poly class to approximate a given function as a linear function.
    """

    def __init__(self, func, interval=[-1,1]):
        """Inits LLS with a function to approximate and an interval on which to approximate"""
        self.func = func
        self.interval = np.array(interval)

        # Sample the given function at m points and evaluate
        m = 1000
        x = np.linspace(interval[0], interval[1], m)
        y = func(x)

        # Create the linear least-squares fit c0+c1*x**2
        c0 = (np.sum(x**2)*np.sum(y)-np.sum(x*y)*np.sum(x))/(m*np.sum(x**2)-np.sum(x)**2)
        c1 = (m*np.sum(x*y)-np.sum(x)*np.sum(y))/(m*np.sum(x**2)-np.sum(x)**2)

        self.coeffs = np.array([c0, c1])


import networkx

from extractors import ExtractorInterface

class BotTrackExtractor(ExtractorInterface):

    def extract(self, dataset, hits_max_iter=100):

        graph = networkx.DiGraph()

        n_lines = dataset.netflow.shape[0]
        i = 0

        for current_source_ip, current_destination_ip in zip(dataset.netflow[:, dataset.Field.SourceIPAddress], dataset.netflow[:, dataset.Field.DestinationIPAddress]):
            graph.add_node(current_source_ip)
            graph.add_node(current_destination_ip)
            graph.add_edge(current_source_ip, current_destination_ip)

            if n_lines > 100:
                i += 1
                if i % int(n_lines/100) == 0:
                    print('\r' + str(int(i/int(n_lines/100))) + ' %', end='')

        if n_lines > 100:
            print('\r')

        (hubs, authorities) = networkx.hits(graph, max_iter=hits_max_iter, tol=1e-06)
        features = {ip: {'label': dataset.labeled_ips[ip], 'authority': authorities[ip], 'hub': hubs[ip]} for ip in graph.nodes()}

        return features