import string
from utils.main_utils import *
from pruners.CHITA import CHITA
from pruners.multi_stage_pruner import MultiStagePruner
from pruners.gradual_pruner import GradualPruner
import json
import sys
import argparse
from itertools import product
import time
import os
from torch.utils.data import DataLoader
import copy
from utils.lr_schedules import cosine_lr_restarts,mfac_lr_schedule
import torch.distributed as dist
import builtins

parser = argparse.ArgumentParser()
parser.add_argument('--arch', type=str, default='mlpnet')
parser.add_argument('--dset', type=str, default='mnist')

parser.add_argument('--num_workers', type=int, default=4)
parser.add_argument('--exp_name', type=str, default='')
parser.add_argument('--exp_id',type=str,default='')

parser.add_argument('--train_batch_size', type=int, default=500)
parser.add_argument('--test_batch_size', type=int, default=500)

parser.add_argument('--fisher_subsample_size', type=int, nargs='+')
parser.add_argument('--fisher_mini_bsz', type=int, nargs='+')

parser.add_argument('--num_iterations', type=int, nargs='+')
parser.add_argument('--num_stages', type=int, nargs='+')
parser.add_argument('--seed', type=int, nargs='+')
parser.add_argument('--first_order_term', type=lambda x: (str(x).lower() == 'true'), nargs='+')
parser.add_argument('--sparsity', type=float, nargs='+')
parser.add_argument('--base_level', type=float, default=0.1) ##In correspondance with sparsity
parser.add_argument('--outer_base_level',type=float,default=0.5)
parser.add_argument('--l2', type=float, nargs='+')
parser.add_argument('--sparsity_schedule', type=str, nargs='+')
parser.add_argument('--algo', type=str, nargs='+')
parser.add_argument('--block_size', type=int, nargs='+') ##Set to -1 if algo does not use this

parser.add_argument('--weight_decay',type=float,default=0.00003751757813)
parser.add_argument('--momentum',type=float,default=0.9)
parser.add_argument('--max_lr',type=float)
parser.add_argument('--min_lr',type=float)
parser.add_argument('--ft_min_lr',type=float,default=-1)
parser.add_argument('--ft_max_lr',type=float,default=-1)
parser.add_argument('--prune_every',type=int)
parser.add_argument('--nprune_epochs',type=int)
parser.add_argument('--nepochs',type=int)
parser.add_argument('--gamma_ft',type=float,default=-1)
parser.add_argument('--warm_up', type=int, default=0)
parser.add_argument('--checkpoint_path', type=str, default='')
parser.add_argument('--first_epoch', type=int, default=0)
parser.add_argument('--schedule', type=str, default='cosine_lr_restarts')
parser.add_argument('--pretrained', type=lambda x: (str(x).lower() == 'true'), default=True)

parser.add_argument('--local_rank', default=-1, type=int,
                        help='local rank for distributed training')

args = parser.parse_args()
arch = args.arch
dset = args.dset
num_workers = args.num_workers
exp_name = args.exp_name
pretrained = args.pretrained
momentum = args.momentum
weight_decay = args.weight_decay

fisher_sizes = [(args.fisher_subsample_size[i], args.fisher_mini_bsz[i]) for i in range(len(args.fisher_mini_bsz)) ] ##Glue the sizes together so we don't take products

if "WORLD_SIZE" in os.environ:
    args.world_size = int(os.environ["WORLD_SIZE"])
else:
    args.world_size = 1
args.distributed = args.world_size > 1

if args.distributed:
    if 'SLURM_PROCID' in os.environ: # for slurm scheduler
        args.rank = int(os.environ['SLURM_PROCID'])
        args.gpu = args.rank % torch.cuda.device_count()
    elif args.local_rank != -1: # for torch.distributed.launch
        args.rank = args.local_rank
        args.gpu = args.local_rank
else:
    args.rank = 0
    args.gpu=0

##Change this to path of imagenet dset
if 'IMAGENET_PATH' in os.environ:
    IMAGENET_PATH = os.environ['IMAGENET_PATH']
else:
    print('****Warning**** No IMAGENET_PATH variable')
    IMAGENET_PATH = ''
CIFAR10_PATH = '../datasets'
MNIST_PATH = '../datasets'

dset_paths = {'imagenet':IMAGENET_PATH,'cifar10':CIFAR10_PATH,
                'mnist':MNIST_PATH}

dset_path = dset_paths[dset]

model,train_dataset,test_dataset,criterion,modules_to_prune = model_factory(arch,dset_path,pretrained=pretrained)

###### Load from checkpoint
if len(args.checkpoint_path) >0:
    checkpoint = torch.load(args.checkpoint_path)
    new_state_trained = OrderedDict()
    for k in checkpoint['model_state_dict']:
        new_state_trained[k[7:]] = checkpoint['model_state_dict'][k]
    model.load_state_dict(new_state_trained)

####
if args.distributed:
    device = args.gpu
else:
    device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
print('Using device ', device)

ngpus_per_node = torch.cuda.device_count()

if args.distributed:
    dist.init_process_group(backend='nccl', init_method='env://',
                            world_size=args.world_size, rank=args.rank)
    torch.backends.cudnn.benchmark = True

    if args.rank!=0:
        def print_pass(*args):
            pass
        #builtins.print = print_pass ##Uncomment to block all other ranks from printing

    torch.cuda.set_device(args.gpu)
    model.cuda(args.gpu)
    model = torch.nn.parallel.DistributedDataParallel(model, device_ids=[args.gpu])
    model_without_ddp = model.module
    #modules_to_prune = ["module." + x for x in modules_to_prune]
    modules_to_prune = [x for x in modules_to_prune]
else:
    model = model.to(device)
    model_without_ddp = model

if args.distributed:
    train_sampler = torch.utils.data.distributed.DistributedSampler(train_dataset, shuffle=True)
else:
    train_sampler = None
train_dataloader = DataLoader(train_dataset, batch_size=args.train_batch_size, shuffle=(train_sampler is None),num_workers=num_workers,pin_memory=True,sampler=train_sampler)
test_dataloader = DataLoader(test_dataset, batch_size=args.test_batch_size, shuffle=True,num_workers=num_workers,pin_memory=True)

alpha_one=False

##########
recompute_bn_stats = (arch == 'resnet20')
if recompute_bn_stats and pretrained:
    #device='cpu'
    model.train()
    original_acc = compute_acc(model,train_dataloader,device=device) #sets up bn stats
    model.eval()
################
#model.to(device)
model.eval()
if (not args.distributed or  args.rank == 0):
    start_test = time.time()
    dense_acc = compute_acc(model_without_ddp,test_dataloader,device=device)
    time_test = time.time() - start_test
    print('Dense test accuracy', dense_acc,' computation time : ', time_test)
###############

acc_different_methods = []
X = None
base_level = args.base_level
ROOT_PATH = '.'

acc_different_methods = []
FOLDER = '{}/results/{}_{}_{}'.format(ROOT_PATH,arch,dset,exp_name)
FILE =  FOLDER+'/data{}_{}.csv'.format(args.exp_id,str(int(time.time())))
os.makedirs(FOLDER,exist_ok=True)

old_fisher_size,old_seed = None,None

torch.backends.cudnn.benchmark = True

for seed,fisher_size, num_stages,num_iterations,first_order_term,sparsity,l2,sparsity_schedule,algo,block_size in product(args.seed, fisher_sizes,args.num_stages,args.num_iterations,args.first_order_term,args.sparsity,args.l2,args.sparsity_schedule,args.algo,args.block_size):

    if (algo == 'Heuristic_LSBlock') and  (block_size == -1):
        continue

    print('seed,fisher_size, num_stages,num_iterations,first_order_term,sparsity,l2,sparsity_schedule,algo,block_size',seed,fisher_size, num_stages,num_iterations,first_order_term,sparsity,l2,sparsity_schedule,algo,block_size)

    X = None
    nepochs = args.nepochs
    nprun_epochs = args.nprune_epochs
    reset_optimizer=True
    sparsities = generate_schedule(nprun_epochs,args.outer_base_level,sparsity,'poly')
    prun_every = args.prune_every
    gamma_ft = args.gamma_ft
    prunepochs = [(i) *prun_every for i in range(len(sparsities))]
    ignore_bias = True

    if args.ft_max_lr == -1:
        args.ft_max_lr = None
    if args.ft_min_lr == -1:
        args.ft_min_lr = None

    if args.schedule == 'mfac':
        lr_schedule = mfac_lr_schedule(nepochs,args.max_lr,args.min_lr,nprun_epochs,args.warm_up)
        print(lr_schedule)
    elif args.schedule == 'cosine_lr_restarts':
        lr_schedule = cosine_lr_restarts(nepochs,args.max_lr,args.min_lr,nprun_epochs,prun_every,gamma_ft,args.warm_up,ft_max_lr=args.ft_max_lr,ft_min_lr=args.ft_min_lr)
        print(args.ft_max_lr,args.ft_min_lr,'----<>')
    else:
        print('Unrecognized schedule')
        break

    fisher_subsample_size, fisher_mini_bsz = fisher_size
    acc_different_methods.append({'algo':algo,'l2':l2,'max_lr':args.max_lr,'min_lr':args.min_lr,'nepochs':args.nepochs,
    'nprun_epochs':nprun_epochs,'prun_every':prun_every,
    'first_order_term':first_order_term,'seed':seed,'fisher_mini_bsz':fisher_mini_bsz,
    'fisher_subsample_size':fisher_subsample_size,
    'num_iterations':num_iterations,'num_stages':num_stages,'recompute_bn_stats' : recompute_bn_stats,
    'ignore_bias':True,'base_level':base_level,
    'sparsity_schedule':sparsity_schedule,
    'block_size':block_size,'train_batch_size':args.train_batch_size,
    'test_batch_size':args.test_batch_size})

    prun_dataloader = DataLoader(train_dataset, batch_size=fisher_mini_bsz, shuffle=True,num_workers=num_workers,pin_memory=True)

    model_pruned = model_without_ddp
    pruner = CHITA(model_pruned,modules_to_prune,prun_dataloader,fisher_subsample_size,fisher_mini_bsz,criterion,block_size,l2,num_iterations,
    first_order_term,alpha_one,device,algo)

    multi_stage_pruner = MultiStagePruner(pruner,test_dataloader,sparsity_schedule,num_stages)
    mask = get_pvec(model_without_ddp,modules_to_prune).cpu() != 0
    gradual_pruner = GradualPruner(multi_stage_pruner,train_dataloader,test_dataloader,criterion,
        modules_to_prune,reset_optimizer,momentum,weight_decay,acc_different_methods,FILE,seed,model=model,device=device,mask=mask,
        first_epoch=args.first_epoch,distributed=args.distributed,rank=args.rank,world_size=args.world_size)

    gradual_pruner.prune(nepochs,lr_schedule,prunepochs,sparsities)

    with open(FILE, "w") as file:
        json.dump(acc_different_methods, file,cls=NpEncoder)

    old_fisher_size,old_seed = fisher_size,seed


from collections import OrderedDict
import numpy as np
import xarray as xr

@xr.register_dataarray_accessor('xevents')
class AidaAccessorStatistics:
    def __init__(self, xarray_obj):
        self._obj = xarray_obj

    def pvi(self, scale):
        """
        Returns the PVI of a timeseries

        .. math:: y = \frac{|x_i - x_{i+s}|^2}{<|x_i - x_{i+s}|^2>}

        where :math:`s` is the scale.

        Parameters
        ----------
        scale : int
            Scale at which to compute the PVI.

        Returns
        -------
        values : ~xarray.DataArray
            An xarray containing the pvi of the original timeseries.

        """
        data = self._obj.values
        if len(data.shape) == 1:
            data = data.reshape((-1, 1))
        result = []
        f = np.abs((data[scale:, :]-data[:-scale, :]))
        f2 = np.sum(f**2, axis=1)
        sigma = np.mean(f2)
        result = np.array(f2/sigma)

        t = self._obj.dims[0]
        time = self._obj.coords[t]
        result = xr.DataArray(result,
                              coords=[time[0:len(f)]],
                              dims=[t],
                              attrs=self._obj.attrs)
        result.attrs['units'] = 'dimensionless'
        return result

    def threshold(self, theta):
        """
        Returns the location of the PVI peaks above the threshold theta
        theta is usually 8 for extreme events, as reported in literature.

        Parameters
        ----------
        theta : int
            Threshold value for PVI.

        Returns
        -------
        result : array
            A numpy array containing the location of the pvi peaks above theta.

        """
        data = self._obj.values
        t = self._obj.dims[0]
        time = self._obj.coords[t]
        if len(data.shape) == 1:
            data = data.reshape((-1, 1))
        result = np.zeros(len(data))
        imax = 0
        kk = 0
        for i in range(0,len(data)):
            if data[i] > theta:
                imax = i
            elif imax != 0:
                result[kk] = np.array(time[imax])
                kk = kk + 1
                imax = 0
        return result

    def increm(self, scale):
        """
        Returns the increments of a timeseries

        .. math:: y = |x_i - x_{i+s}|

        where :math:`s` is the scale.

        Parameters
        ----------
        scale : `int`
            Scale at which to compute the increments.

        Returns
        -------
        kurt : array
            kurtosis of the increments, one per product, using the Fisher's
            definition (0 value for a normal distribution).

        result : `~xarray.DataArray`
            An xarray containing the time series increments, one per
            product in the original timeseries.

        """
        from scipy.stats import kurtosis
        data = self._obj.values
        if len(data.shape) == 1:
             data = data.reshape((-1, 1))
        f = np.abs((data[scale:, :]-data[:-scale, :]))
        result = np.array(f)

        c = self._obj.dims[1]
        t = self._obj.dims[0]
        cols = self._obj.coords[c]
        time = self._obj.coords[t]
        result = xr.DataArray(result,
                              coords=[time[0:len(f)], cols],
                              dims=[t, c],
                              attrs=self._obj.attrs)
        kurt = kurtosis(result, axis=0, fisher=False)
        return kurt, result


#!/usr/bin/env python3

import rospy
from std_msgs.msg import String
from std_msgs.msg import Float64

class  Sub:
    def __init__(self):
        self.steer_angle=0.0
        self.vel_cmd=0.0

    def update_steer(self,data):
        self.steer_angle= data.data

    def update_velocity(self,data):
        self.vel_cmd= data.data

    def subsciber(self):

        pub_right = rospy.Publisher('/toy_car2/joint1_position_controller/command', Float64, queue_size=10)
        pub_left = rospy.Publisher('/toy_car2/joint2_position_controller/command', Float64, queue_size=10)
        pub_move1 = rospy.Publisher('/toy_car2/joint3_position_controller/command', Float64, queue_size=10)
        pub_move2 = rospy.Publisher('/toy_car2/joint4_position_controller/command', Float64, queue_size=10)
        rospy.init_node('subscriber', anonymous=True)
        rate = rospy.Rate(10) # 10hz
        rospy.Subscriber("/toy_car2/steering", Float64, self.update_steer)
        rospy.Subscriber("/toy_car2/velocity", Float64, self.update_velocity)

        while not rospy.is_shutdown():
            data_str = "Velocity %s " % self.vel_cmd +"Steer Angle %s" % self.steer_angle
            rospy.loginfo(data_str)
            pub_right.publish(self.steer_angle)
            pub_left.publish(self.steer_angle)
            pub_move1.publish(self.vel_cmd)
            pub_move2.publish(self.vel_cmd)
            rate.sleep()

if __name__ == '__main__':
    try:
        s=Sub()
        s.subsciber()
    except rospy.ROSInterruptException:
        pass


class Node:
    def __init__(self, val):
        self.val = val
        self.parent = self
        self.rank = 0

class DisjointSet:
    def __init__(self, nums):
        self.map = {}
        self.makeSet(nums)

    def makeSet(self, nums):
        for n in nums:
            self.map[n] = Node(n)

    def union(self, val1, val2):
        parent1 = self.findSet(val1)
        parent2 = self.findSet(val2)

        if parent1 == parent2: return

        if parent1.rank >= parent2.rank:
            if parent1.rank == parent2.rank:
                parent1.rank += 1
            parent2.parent = parent1
        else:
            parent1.parent = parent2

    def findSet(self, val):
        return self.findSetHelper(self.map[val])

    def findSetHelper(self, node):
        if node == node.parent:
            return node
        node.parent = self.findSetHelper(node.parent)
        return node.parent

# test
ds = DisjointSet(range(1,8))

ds.union(1, 2)
ds.union(2, 3)
ds.union(4, 5)
ds.union(6, 7)
ds.union(5, 6)
ds.union(3, 7)

for x in range(1,8):
    print(ds.findSet(x).val)


"""
Bohrium Loop
============
"""

import sys
import copy
from functools import reduce
import numpy_force as numpy
from . import bhary

class Iterator(object):
    """Iterator used for sliding views within loops.

    Notes
    -----
    Supports addition, subtraction and multiplication.
    """

    def __init__(self, max_iter, value, step_delay=1, reset=None):
        """The initial state of the iterator.

        Parameters
        ----------
        max_iter : int
            The maximum amount of iterations the loop can go on for
        value : int
            The beginning offset of the iterator
        step_delay : int
            The amount of iterations needed before a change is made
        reset : int
            The amount of iterations before the changes are reset

        Notes
        -----
        step : int
            The amount the offset is slided when performing a step

        The step can be changed by using multiplication
        """

        self.max_iter = max_iter
        self.offset = value
        self.step_delay = step_delay
        self.reset = reset

        self.step = 1

    def __add__(self, other):
        new_it = copy.copy(self)
        new_it.offset += other
        return new_it

    def __radd__(self, other):
        new_it = copy.copy(self)
        new_it.offset += other
        return new_it

    def __sub__(self, other):
        new_it = copy.copy(self)
        new_it.offset -= other
        return new_it

    def __rsub__(self, other):
        new_it = copy.copy(self)
        new_it.step *= -1
        new_it.offset = other - new_it.offset
        return new_it

    def __mul__(self, other):
        new_it = copy.copy(self)
        new_it.offset *= other
        new_it.step *= other
        return new_it

    def __rmul__(self, other):
        new_it = copy.copy(self)
        new_it.offset *= other
        new_it.step *= other
        return new_it

    def __neg__(self):
        new_it = copy.copy(self)
        new_it.step *= -1
        new_it.offset *= -1
        return new_it

class IteratorOutOfBounds(Exception):
    """Exception thrown when a view goes out of bounds after the maximum
       iterations."""

    def __init__(self, dim, shape, first_index, last_index):
        error_msg = \
            "\n    Iterator out of bounds:\n" \
            "     Dimension %d has length %d, iterator starts from %d and goes to %d." \
            % (dim, shape, first_index, last_index)
        super(IteratorOutOfBounds, self).__init__(error_msg)

class IteratorIllegalDepth(Exception):
    """Exception thrown when a view consists of a mix of iterator depths."""

    def __init__(self):
        error_msg = \
            "\n    Illegal mix of iterators with different depth:\n" \
            "     A view cannot use iterators from different depths of the grid in the same dimension."
        super(IteratorIllegalDepth, self).__init__(error_msg)

class IteratorIllegalBroadcast(Exception):
    """Exception thrown when a view consists of a mix of iterator depths."""

    def __init__(self, dim, a_shape, a_shape_change,
                 bcast_shape, bcast_shape_change):
        error_msg = \
            "Broadcast with dynamic shape:\n" \
            "    View with shape " + str(a_shape) + \
            " changes shape by " + str(a_shape_change) + \
            " in dimension " + str(dim) + \
            ".\n    It is differet from the view it is broadcasted from with shape " + \
            str(bcast_shape) + \
            " which changes shape by " + str(bcast_shape_change) + ".\n"
        super(IteratorIllegalBroadcast, self).__init__(error_msg)

class DynamicViewInfo(object):
    """Object for storing information about dynamic changes to the view"""

    def __init__(self, dynamic_changes, shape, stride, resets={}):
        """The initial state of the dynamic view information.

        Parameters
        ----------
        dynamic_changes : {int : [(int, int, int, int, int)]}
            A dictionary of lists of tuples corresponding to the dynamic
            changes the view.
            The tuple is (slide, shape_change, step_delay, shape, stride)
            and is explained further in the parameters to `add_dynamic_change`.
        shape : int tuple (variable length)
            The shape of the view that the dynamic view is based upon.
            Used when using negative indices to wrap around.
        stride : int tuple (variable length)
            The stride of the view that the dynamic view is based upon.
            Used for making slides to the offset.
        resets : {int : int}
            A dictionary of ints. The key corresponds to the dimension and
            the value to iterations before the changes are reset.
            Used for nested loops.
        """
        self.shape = shape
        self.stride = stride
        self.dynamic_changes = dynamic_changes
        self.resets = resets

    def add_dynamic_change(self, dim, slide, shape_change, step_delay, shape=None, stride=None):
        """Add dynamic changes to the dynamic changes information of the view.

        Parameters
        ----------
        dim : int
            The relevant dimension
        slide : int
            The change to the offset in the given dimension
            (can be both positive and negative)
        shape_change : int
            The amount the shape changes in the given dimension
            (can also be both positive and negative)
        step_delay : int
            If the change is based on an iterator in a grid, it is
            the changes can be delayed until the inner iterators
            have been updated `step_delay` times.
        shape : int
            The shape that the view can slide within. If not given,
            self.shape[dim] is used instead
        stride : int
            The stride that the view can slide within. If not given,
            self.stride[dim] is used instead
        """
        if not shape:
            shape = self.shape[dim]
        if not stride:
            stride = self.stride[dim]

        if self.has_changes_in_dim(dim):
            self.dynamic_changes[dim].append((slide, shape_change, step_delay, shape, stride))
        else:
            self.dynamic_changes[dim] = [(slide, shape_change, step_delay, shape, stride)]

    def has_changes_in_dim(self, dim):
        """Check whether there are any dynamic changes in the given dimension.

        Parameters
        ----------
        dim : int
            The relevant dimension
        """
        return dim in self.dynamic_changes

    def dims_with_changes(self):
        """Returns a list of all dimensions with dynamic changes."""
        return self.dynamic_changes.keys()

    def changes_in_dim(self, dim):
        """Returns a list of all dynamic changes in a dimension.
        If the dimension does not contain any dynamic changes,
        an empty list is returned.

        Parameters
        ----------
        dim : int
            The relevant dimension
        """
        changes = []
        if self.has_changes_in_dim(dim):
            changes += self.dynamic_changes[dim]
        return changes

    def index_into(self, dvi):
        """Modifies the dynamic change such that is reflects
        being indexed into another view with dynamic changes.

        Parameters
        ----------
        dim : DynamicViewInfo
            The infomation about dynamic changes within the
            view which is indexed into
        """
        for dim in dvi.dims_with_changes():
            if (dim in self.resets) or (dim in dvi.resets):
                if not (dim in dvi.resets) or \
                        not (dim in self.resets) or \
                        self.resets[dim] != dvi.resets[dim] or \
                        self.changes_in_dim(dim) != dvi.changes_in_dim(dim):
                    raise IteratorIllegalDepth()
            for change in dvi.changes_in_dim(dim):
                self.add_dynamic_change(dim, *change)

    def dim_shape_change(self, dim):
        """Returns the summed shape change in the given dimension.

        Parameters
        ----------
        dim : int
            The relevant dimension
        """
        shape_change_sum = 0
        if self.has_changes_in_dim(dim):
            for (_, shape_change, _, _, _) in self.dynamic_changes[dim]:
                shape_change_sum += shape_change
        return shape_change_sum

    def get_shape_changes(self):
        """Returns a dictionary of all changes to the shape.
        The dimension is the key and the shape change in the
        dimension is the value.
        """
        shape_changes = {}
        for dim in self.dynamic_changes.keys():
            shape_changes[dim] = 0
            for (_, shape_change, _, _, _) in self.dynamic_changes[dim]:
                shape_changes[dim] += shape_change
        return shape_changes

    def has_changes(self):
        """Returns whether the object contains any dynamic changes."""
        return self.dynamic_changes != {}

def inherit_dynamic_changes(a, sliced):
    """Creates a view into another view which has dynamic changes.
    The new view inherits the dynamic changes."""
    # Temporary store the dynamic changes
    dvi = a.bhc_dynamic_view_info

    # Perform slicing (removes the dynamic changes to avoid infinite recursion)
    a.bhc_dynamic_view_info = None
    b = a[sliced]

    # Inherit the dynamic changes (and restore dynamic changes to a)
    b.bhc_dynamic_view_info = dvi
    a.bhc_dynamic_view_info = dvi
    return b

def get_iterator(max_iter, val, step_delay=1):
    """Returns an iterator with a given starting value. An iterator behaves like
       an integer, but is used to slide view between loop iterations.

    Parameters
    ----------
    max_iter : int
        The maximum amount of iterations of the loop. Used for checking
        boundaries.
    val : int
        The initial value of the iterator.

    Notes
    -----
    `get_iterator` can only be used within a bohrium loop function. Within the
    loop `max_iter` is set by a lambda function. This is also the case in the
    example.

    Examples
    --------
    >>> def kernel(a):
    ...     i = get_iterator(1)
    ...     a[i] *= a[i-1]
    >>> a = bh.arange(1,6)
    >>> bh.do_while(kernel, 4, a)
    array([1, 2, 6, 24, 120])"""

    it = Iterator(max_iter, val, step_delay)
    return it

def get_grid(max_iter, *args):
    """Returns n iterators in a grid, corresponding to nested loops.

    Parameters
    ----------
    args : pointer to two or more integers
        The first integer is the maximum iterations of the loop, used for checking
        boundaries. The rest are the shape of the grid.

    Notes
    -----
    `get_grid` can only be used within a bohrium loop function. Within the
    loop `max_iter` is set by a lambda function.
    There are no upper bound on the amount of grid values.

    Examples
    --------
    >>> def kernel(a):
    ...     i, j, k = get_grid(3,3,3)
    ...     a[i,j,k] += 1

    correspondes to

    >>> for i in range(3):
    ...     for j in range(3):
    ...         for k in range(3):
    ...             a[i,j,k] += 1"""

    # Remove maximum iterations and reverse the grid to
    # loop over the grid from inner to outer
    grid = args[::-1]

    # Tuple of resulting iterators
    iterators = ()

    # Beginning step delay is always 1
    step_delay = 1

    for dim, iterations in enumerate(grid):
        i = Iterator(max_iter, 0, step_delay, iterations)
        step_delay *= iterations
        iterators = (i,) + iterators
    return iterators

def has_iterator(*s):
    """Checks whether a (multidimensional) slice contains an iterator

    Parameters
    ----------
    s : pointer to an integer, iterator or a tuple of integers/iterators

    Notes
    -----
    Only called from __getitem__ and __setitem__ in bohrium arrays (see _bh.c)."""

    # Helper function for one-dimensional slices
    def check_simple_type(ss):
        if isinstance(ss, slice):
            # Checks whether the view changes shape during iterations
            return isinstance(ss.start, Iterator) or \
                   isinstance(ss.stop, Iterator)
        else:
            return isinstance(ss, Iterator)

    # Checking single or multidimensional slices for iterators
    if isinstance(s, tuple):
        for t in s:
            it = check_simple_type(t)
            if it:
                return it
        return False
    else:
        return check_simple_type(s)

def slide_from_view(a, sliced):
    def check_bounds(shape, dim, s):
        """Checks whether the view is within the bounds of the array,
        given the maximum number of iterations"""

        # If the dimension is reset, then only the range before the reset needs to be checked
        if s.reset and s.max_iter / s.step_delay >= s.reset:
            last_index = s.offset + (s.reset - 1) * s.step
        else:
            last_index = s.offset + s.step / s.step_delay * (s.max_iter - 1)

        # Check that the starting index and the last index is within bounds
        if -shape[dim] <= s.offset < shape[dim] and \
                -shape[dim] <= last_index < shape[dim]:
            return True
        else:
            raise IteratorOutOfBounds(dim, shape[dim], s.offset, last_index)

    def dynamic_shape_change(s):
        """Returns how the shape of a view changes between iterations
        based on a slice possibly containing iterators"""
        if isinstance(s.start, Iterator):
            start_step = s.start.step
        else:
            start_step = 0
        if isinstance(s.stop, Iterator):
            stop_step = s.stop.step
        else:
            stop_step = 0
        return stop_step - start_step

    # Make sure that the indices is within a tuple
    if not isinstance(sliced, tuple):
        sliced = (sliced,)

    # Checks whether the indices contains a slice
    has_slices = reduce((lambda x, y: x or y), [isinstance(s, slice) for s in sliced])

    # The new slices (does not contain iterators)
    new_slices = ()
    # The dynamic changes
    slides = []
    # The resets (used for resetting an iterator in nested loops)
    resets = {}

    for i, s in enumerate(sliced):
        if len(sliced) == 1 or has_iterator(s):
            # A slice with optional step size (eg. a[i:i+2] or a[i:i+2:2])
            if isinstance(s, slice):
                start_is_iterator = isinstance(s.start, Iterator)
                stop_is_iterator = isinstance(s.stop, Iterator)

                # Cannot contain iterators with different reset in same slice
                if start_is_iterator and stop_is_iterator \
                        and (s.start.step_delay != s.stop.step_delay or s.start.reset != s.stop.reset):
                    raise IteratorIllegalDepth()

                # Check whether the start/end iterator stays within the array
                if start_is_iterator:
                    check_bounds(a.shape, i, s.start)
                    start = s.start.offset
                    step = s.start.step
                    step_delay = s.start.step_delay
                    reset = s.start.reset
                else:
                    start = s.start
                    step = 0
                    step_delay = 1

                if stop_is_iterator:
                    if s.stop.offset > 0:
                        check_bounds(a.shape, i, s.stop - 1)
                    else:
                        check_bounds(a.shape, i, s.stop)
                    stop = s.stop.offset
                    reset = s.stop.reset
                else:
                    stop = s.stop

                # Store the new slice
                new_slices += (slice(start, stop, s.step),)
                slides.append((i, step, dynamic_shape_change(s), step_delay))

            # A single iterator (eg. a[i])
            else:
                # Check whether the iterator stays within the array
                check_bounds(a.shape, i, s)

                # If the indices does not contain a slice, the returned value must
                # be a view with shape 1 in each dimension (To avoid a flush)
                if not has_slices:
                    new_slices += (slice(s.offset, s.offset + 1),)
                else:
                    new_slices += (s.offset,)
                slides.append((i, s.step, 0, s.step_delay))
                reset = s.reset

            # Add information about dimension being reset
            if reset:
                resets[i] = reset
        else:
            # Does not contain an iterator, just pass it through
            new_slices += (s,)

    # Use the indices to create a new view
    b = a[new_slices]

    a_dvi = a.bhc_dynamic_view_info

    if a_dvi:
        b_dvi = DynamicViewInfo({}, a_dvi.shape, a.strides, resets)
    else:
        b_dvi = DynamicViewInfo({}, a.shape, a.strides, resets)

    for slide in slides:
        b_dvi.add_dynamic_change(*slide)

    # If the view, which is indexed into, contains dynamic changes,
    # pass them on to the new view

    if a_dvi:
        b_dvi.index_into(a_dvi)

    if b_dvi.has_changes():
        b.bhc_dynamic_view_info = b_dvi
    return b

def add_slide_info(a):
    """Checks whether a view is dynamic and adds the relevant
       information to the view structure within BXX if it is.

    Parameters
    ----------
    a : array view
        A view into an array
    """
    from . import _bh

    # Check whether the view is a dynamic view
    dvi = a.bhc_dynamic_view_info

    if dvi:
        # Set the relevant update conditions for the new view
        for dim in dvi.dynamic_changes.keys():
            for (slide, shape_change, step_delay, shape, stride) in dvi.dynamic_changes[dim]:
                try:
                    stride = int(stride / 8)
                    shape = shape
                except:
                    stride = 0
                    shape = 0

                # Add dynamic information to the view within the cxx bridge
                _bh.slide_view(a, dim, slide, shape_change, shape, stride, step_delay)
        # Add resets to the relevant dimensions within the cxx bridge (used for nested loops)
        for dim in dvi.resets.keys():
            _bh.add_reset(a, dim, dvi.resets[dim])

def do_while(func, niters, *args, **kwargs):
    """Repeatedly calls the `func` with the `*args` and `**kwargs` as argument.

    The `func` is called while `func` returns True or None and the maximum number
    of iterations, `niters`, hasn't been reached.

    Parameters
    ----------
    func : function
        The function to run in each iterations. `func` can take any argument and may return
        a boolean `bharray` with one element.
    niters: int or None
        Maximum number of iterations in the loop (number of times `func` is called). If None, there is no maximum.
    *args, **kwargs : list and dict
        The arguments to `func`

    Notes
    -----
    `func` can only use operations supported natively in Bohrium.

    Examples
    --------
    >>> def loop_body(a):
    ...     a += 1
    >>> a = bh.zeros(4)
    >>> bh.do_while(loop_body, 5, a)
    >>> a
    array([5, 5, 5, 5])

    >>> def loop_body(a):
    ...     a += 1
    ...     return bh.sum(a) < 10
    >>> a = bh.zeros(4)
    >>> bh.do_while(loop_body, None, a)
    >>> a
    array([3, 3, 3, 3])
    """

    from . import _bh
    _bh.flush()
    flush_count = _bh.flush_count()
    func.__globals__['get_iterator'] = lambda x=0: get_iterator(niters, x)
    func.__globals__['get_grid'] = lambda *argz: get_grid(*((niters,) + argz))
    cond = func(*args, **kwargs)
    if flush_count != _bh.flush_count():
        raise TypeError("Invalid `func`: the looped function contains operations not support "
                        "by Bohrium, contain branches, or is simply too big!")
    if niters is None:
        niters = sys.maxsize - 1
    if cond is None:
        _bh.flush_and_repeat(niters, None)
    else:
        if not bhary.check(cond):
            raise TypeError("Invalid `func`: `func` may only return Bohrium arrays or nothing at all")
        if cond.dtype.type is not numpy.bool_:
            raise TypeError("Invalid `func`: `func` returned array of wrong type `%s`. "
                            "It must be of type `bool`." % cond.dtype)
        if len(cond.shape) != 0 and len(cond) > 1:
            raise TypeError("Invalid `func`: `func` returned array of shape `%s`. "
                            "It must be a scalar or an array with one element." % cond.shape)
        if not bhary.is_base(cond):
            raise TypeError("Invalid `func`: `func` returns an array view. It must return a base array.")

        _bh.sync(cond)
        _bh.flush_and_repeat(niters, cond)


from odoo import models, api, fields

class LibraryBook(models.Model):
    _name = 'library.book'
    name = fields.Char('Title')
    isbn = fields.Char('ISBN')
    author_ids = fields.Many2many('res.partner', 'Authors')

    @api.multi
    def name_get(self):
        result = []
        for book in self:
            authors = book.author_ids.mapped('name')
            name = '%s (%s)' % (book.title,
                                ', '.join(authors))
            result.append((book.id, name))
        return result

    @api.model
    def _name_search(self, name='', args=None, operator='ilike',
                     limit=100, name_get_uid=None):
        args = [] if args is None else args.copy()
        if not(name == '' and operator == 'ilike'):
            args += ['|', '|',
                     ('name', operator, name),
                     ('isbn', operator, name),
                     ('author_ids.name', operator, name)
                     ]
        return super(LibraryBook, self)._name_search(
            name='', args=args, operator='ilike',
            limit=limit, name_get_uid=name_get_uid)


import torch
import torch.nn as nn
import torch.nn.functional as F

class Simple_CNN(nn.Module):
    def __init__(self, num_labels):
        super(Simple_CNN, self).__init__()

        self.pool = nn.MaxPool2d(2, 2)

        self.conv1 = nn.Conv2d(3, 6, 5)
        self.conv2 = nn.Conv2d(6, 16, 5)

        self.fc1 = nn.Linear(13456, 120)
        self.fc2 = nn.Linear(120, 84)
        self.fc3 = nn.Linear(84, num_labels)

        self.apply(self.init_weights_xavier)

    def init_weights_xavier(self, m):
        if isinstance(m, nn.Linear):
            torch.nn.init.xavier_uniform_(m.weight)
            m.bias.data.fill_(0.01)

    def forward(self, x):
        x = self.pool(F.relu(self.conv1(x)))
        x = self.pool(F.relu(self.conv2(x)))
        x = torch.flatten(x, 1) # flatten all dimensions except batch
        x = F.relu(self.fc1(x))
        x = F.relu(self.fc2(x))
        x = self.fc3(x)

        return x


import json
from time import perf_counter
from datetime import timedelta
from contextlib import AbstractContextManager
from functools import wraps, partial
from collections import defaultdict

from typing import DefaultDict, List

class profiler(AbstractContextManager):
  timings: DefaultDict[str, List[timedelta]] = defaultdict(list)

  def __init__(self, name: str, printer=None, store=True, **printer_kwargs):
    self.name = name
    self.store = store
    self.delta = None

    if printer is None:
      self.printer = None
    else:
      self.printer = partial(printer, **printer_kwargs)

  @classmethod
  def clear(cls):
    cls.timings = defaultdict(list)

  @classmethod
  def _json_default(cls, obj):
    if isinstance(obj, timedelta):
      return str(obj)
    raise TypeError

  @classmethod
  def dump(cls, output_path, indent=4):
    with open(output_path, 'w') as f:
      json.dump(cls.timings, f, indent=indent, default=cls._json_default)

  @classmethod
  def profile(cls, printer=print, **printer_kwargs):
    def wrapper(func):
      prf = cls(func.__name__, printer=printer, **printer_kwargs)

      @wraps(func)
      def profiled_func(*args, **kwargs):
        with prf:
          return func(*args, **kwargs)

      return profiled_func
    return wrapper

  def __enter__(self):
    self.begin = perf_counter()
    return self

  def __exit__(self, *exc_info):
    if any(e is not None for e in exc_info):
      self.delta = None
      return

    self.delta = delta = timedelta(seconds=perf_counter() - self.begin)
    if self.store:
      self.timings[self.name].append(delta)
    if self.printer is not None:
      self.printer(f"Time for {self.name}:\t{delta}")


# Publisher
from __future__ import unicode_literals
import zmq
import time
import sys

class Publisher:
    # instantiate variables and connect to broker
    def __init__(self, ip_add):
        self.topic = "Default"
        self.full_add = "tcp://" + str(ip_add) + ":1234"
        ctx = zmq.Context()
        self.sock_pub = ctx.socket(zmq.PUB)
        self.sock_pub.connect(self.full_add)
        print("Publisher connected to the broker")

    # register a topic for this publisher
    def register_pub(self, topic):
        self.topic = topic
        msg = "REGISTER||" + str(self.topic)
        time.sleep(1)
        self.sock_pub.send_string(msg)
        return True

    # publish the given information for pre-registered topic
    def publish(self, info):
        # format for published string is "topic||info"
        msg = str(self.topic) + "||" + str(info)
        self.sock_pub.send_string(msg)
        return True

if __name__ == '__main__':
    # handle input
    if len(sys.argv) != 3:
        print("Please provide 2 arguments as specified in the readme")
    elif "||" in sys.argv[1]:
        print("Please re-run and remove any '||' found in the topic name")
    else:
        # process input arguments
        topic = sys.argv[1]
        ip_add = sys.argv[2]

        # create Publisher object
        pub = Publisher(ip_add)
        pub.register_pub(topic)

        # wait for inputted information to publish
        while True:
            info = input("Input information about your topic and press enter to publish!\n")
            pub.publish(info)
            print("Success!")


from threading import Lock
import sys
import rospy
from control_msgs.msg import JointTrajectoryControllerState
from moveit_msgs.srv import SaveRobotStateToWarehouse as SaveState
from moveit_msgs.msg import RobotState
from sensor_msgs.msg import JointState
from sr_robot_commander.sr_arm_commander import SrArmCommander
from sr_robot_commander.sr_hand_commander import SrHandCommander
from sr_robot_commander.sr_robot_commander import SrRobotCommander

class SrStateSaverUnsafe:
    def __init__(self, name, hand_or_arm="both", side="right", save_target=False):

        self._save = rospy.ServiceProxy(
            'save_robot_state', SaveState)

        self._name = name
        self._save_target = save_target

        if name is None or name == '':
            raise ValueError("Cannot save with empty name.")

        prefix = ""
        double_error = []
        if hand_or_arm == "arm":
            if side != "bimanual":
                prefix = "ra" if side == "right" else "la"
                self._commander = SrArmCommander(side + '_arm')
                if not self._commander.arm_found():
                    double_error.append("Group " + side + "_arm not found.")
            else:
                self._commander = SrRobotCommander('two_arms')
        elif hand_or_arm == 'hand':
            if side != "bimanual":
                prefix = "rh" if side == "right" else "lh"
                self._commander = SrHandCommander(side + '_hand')
            else:
                self._commander = SrRobotCommander('two_hands')
        elif hand_or_arm == 'both':
            if side != "bimanual":
                self._commander = SrRobotCommander(side + '_arm_and_hand')
            else:
                self._commander = SrRobotCommander('two_arms_and_hands')

        if len(double_error) != 0:
            raise ValueError(" ".join(double_error))

        self._save_hand = (hand_or_arm in ("hand", "both"))
        self._save_arm = (hand_or_arm in ("arm", "both"))
        self._save_bimanual = (side == 'bimanual')

        if save_target:
            rospy.loginfo("Saving targets instead of current values")
            self._mutex = Lock()
            self._target_values = {}
            if self._save_hand:
                self._hand_subscriber = rospy.Subscriber("/" + prefix + "_trajectory_controller/state",
                                                         JointTrajectoryControllerState, self._target_cb)
            if self._save_arm:
                self._arm_subscriber = rospy.Subscriber("/" + prefix + "_trajectory_controller/state",
                                                        JointTrajectoryControllerState, self._target_cb)
            if self._save_bimanual:
                if self._save_hand:
                    self.r_hand_subscriber = rospy.Subscriber("/ra_trajectory_controller/state",
                                                              JointTrajectoryControllerState, self._target_cb)
                    self.l_hand_subscriber = rospy.Subscriber("/la_trajectory_controller/state",
                                                              JointTrajectoryControllerState, self._target_cb)
                if self._save_arm:
                    self.r_arm_subscriber = rospy.Subscriber("/ra_trajectory_controller/state",
                                                             JointTrajectoryControllerState, self._target_cb)
                    self.l_arm_subscriber = rospy.Subscriber("/la_trajectory_controller/state",
                                                             JointTrajectoryControllerState, self._target_cb)

        current_dict = {}
        rospy.loginfo("Getting current")
        current_dict = self._commander.get_current_state()
        robot_name = self._commander.get_robot_name()

        if self._save_target:
            rospy.loginfo("Getting targets")
            waiting_for_targets = True
            while waiting_for_targets and not rospy.is_shutdown():
                self._mutex.acquire()  # pylint: disable=R1732
                waiting_for_targets = False
                for joint in current_dict:
                    if joint in self._target_values:
                        current_dict[joint] = self._target_values[joint]
                    else:
                        waiting_for_targets = True
                        rospy.loginfo(f"Still waiting for {joint} target")
                if waiting_for_targets:
                    rospy.loginfo(self._target_values)
                    rospy.sleep(1)
        if rospy.is_shutdown():
            sys.exit()

        self.save_state(current_dict, robot_name)

    def _target_cb(self, data):
        self._mutex.acquire()  # pylint: disable=R1732
        for joint_index, joint in enumerate(data.joint_names):
            self._target_values[joint] = data.desired.positions[joint_index]

    def save_state(self, current_dict, robot_name):
        robot_state = RobotState()
        rospy.loginfo(current_dict)
        robot_state.joint_state = JointState()
        robot_state.joint_state.name = current_dict.keys()
        robot_state.joint_state.position = current_dict.values()
        rospy.logwarn(robot_state)
        self._save(self._name, robot_name, robot_state)


from guillotina import configure
from guillotina.db.interfaces import ICockroachStorage
from guillotina.db.interfaces import IPostgresStorage
from guillotina.interfaces import IDatabaseInitializedEvent

statements = [
    'CREATE SEQUENCE IF NOT EXISTS order_sequence',
    """CREATE INDEX IF NOT EXISTS objects_pos_in_parent
ON {} (((json->>'position_in_parent')::int) DESC)""",
    """CREATE INDEX IF NOT EXISTS objects_pos_in_parent_asc
ON {} (((json->>'position_in_parent')::int) ASC)"""
]

@configure.subscriber(for_=IDatabaseInitializedEvent)
async def db_initialized(event):
    '''
    Initialize additional pg indexes
    '''
    storage = event.database.storage
    if not IPostgresStorage.providedBy(storage) or ICockroachStorage.providedBy(storage):
        return

    # create json data indexes
    async with storage.lock:
        for statement in statements:
            await storage.read_conn.execute(
                statement.format(storage._objects_table_name))


import random

class CityNode:
    def __init__(self, direction, weight):
        self.status = direction
        self.value = weight

city_list = {0: 'Podgorica,\n Montenegro',
             1: 'Vatican City,\n Vatican City',
             2: 'Addis Ababa,\n Ethiopia',
             3: 'Gaborone,\n Botswana',
             4: 'Vaduz,\n Liechtenstein'}
city_list2 = {0: 'Podgorica, Montenegro',
              1: 'Vatican City, Vatican City',
              2: 'Addis Ababa, Ethiopia',
              3: 'Gaborone, Botswana',
              4: 'Vaduz, Liechtenstein'}

city_num = len(city_list)

distance_list = [564,  # Podgorica & Vatican City
                 4173,  # Podgorica & Addis Ababa
                 7493,  # Podgorica & Gaborone
                 929,  # Podgorica & Vaduz
                 4469,  # Vatican City & Addis Ababa
                 7530,  # Vatican City & Gaborone
                 627,  # Vatican City & Vaduz
                 3997,  # Addis Ababa & Gaborone
                 5056,  # Addis Ababa & Vaduz
                 8152  # Gaborone & Vaduz
                 ]

adjacency_matrix = [
    [0, 1, 1, 1, -1],
    [-1, 0, 1, 1, -1],
    [-1, -1, 0, 1, 1],
    [-1, -1, -1, 0, 1],
    [1, 1, 0, 0, -1]
]  # default graph of your choice

# set up the graph
city_matrix = [[CityNode(0, -1) for j in range(city_num)] for i in range(city_num)]
for i in range(city_num):
    for j in range(i, city_num):
        if i != j:
            distance = distance_list.pop(0)
            city_matrix[i][j] = CityNode(adjacency_matrix[i][j], distance)
            city_matrix[j][i] = CityNode(adjacency_matrix[j][i], distance)
            distance_list.append(distance)

path = []

def reset():
    for i in range(city_num):
        for j in range(i, city_num):
            if i == j:
                city_matrix[i][j].status = 0
                city_matrix[i][j].value = -1
            else:
                city_matrix[i][j].status = adjacency_matrix[i][j]
                city_matrix[j][i].status = adjacency_matrix[j][i]
    path.clear()

def add_edge(departure, arrival):
    if city_matrix[departure][arrival].status == 0:
        city_matrix[departure][arrival].status = 1
        city_matrix[arrival][departure].status = -1

    else:
        print("The edge between " + city_list2[departure] + " and " + city_list2[arrival] + " already exists!")

def remove_edge(departure, arrival):
    if city_matrix[departure][arrival].status != 0:
        city_matrix[departure][arrival].status = 0
        city_matrix[arrival][departure].status = 0
    else:
        print("The edge between " + city_list2[departure] + " and " + city_list2[arrival] + " does not exists!")

def generate_random_edge():
    while True:
        random_edge = random.sample(range(city_num), 2)
        if city_matrix[random_edge[0]][random_edge[1]].status == 0:
            print(city_list2[random_edge[0]] + ' to ' + city_list2[random_edge[1]] + ' is added')
            break
    add_edge(random_edge[0], random_edge[1])
    return random_edge

def function():
    cycle = []
    vertex = 0
    starting_vertex = 0
    while not path:
        if vertex > 0:
            starting_vertex = generate_random_edge()[0]
            # Start from the outgoing vertex of the random edge instead of from the beginning to save time
        for vertex in range(starting_vertex, city_num):
            if city_matrix[vertex][vertex].status == 0 and city_matrix[vertex][vertex].value == -1:
                cycle_detection(vertex, vertex, cycle)
            city_matrix[vertex][vertex].status = 0
            city_matrix[vertex][vertex].value = -1
    print("Cycle detected: ")
    for each_cycle in path:
        print(each_cycle)

def cycle_detection(predecessor, vertex, cycle):
    city_matrix[vertex][vertex].status = 1  # Mark the current vertex as visited
    for adjacent in range(city_num):  # for every adjacent vertex
        if vertex != adjacent and city_matrix[vertex][adjacent].status == 1:  # Check if it is adjacent
            city_matrix[vertex][vertex].value = adjacent
            if city_matrix[adjacent][adjacent].status == 0:
                cycle_detection(predecessor, adjacent, cycle)
            elif city_matrix[adjacent][adjacent].status == 1:  # The adjacent vertex has been visited, cycle detected
                form_cycle(adjacent, cycle)
    if city_matrix[vertex][vertex].value == -1 or city_matrix[predecessor][predecessor].value == vertex:
        city_matrix[vertex][vertex].status = -1
    else:
        city_matrix[vertex][vertex].status = 0

def form_cycle(vertex, cycle):
    stop = vertex
    while not cycle.__contains__(vertex):
        cycle.append(vertex)
        vertex = city_matrix[vertex][vertex].value
    if vertex == stop:
        cycle.append(vertex)
        path.append(cycle.copy())
        cycle.clear()
    else:
        print("Hehe, weird right?")

function()


# -*- coding: utf-8 -*-
import terrariumLogging
logger = terrariumLogging.logging.getLogger(__name__)

from terrariumSwitch import terrariumPowerSwitchSource
from terrariumUtils import terrariumUtils

from hashlib import md5

import asyncio
from kasa import Discover, SmartStrip, SmartPlug

class terrariumPowerSwitchTPLinkKasa(terrariumPowerSwitchSource):
  TYPE = 'tplinkkasa'
  URL = '^\d{1,3}\.\d{1,3}\.\d{1,3}(,\d{1,3})?$'

  def __get_address(self):
    data = self.get_address().strip().split(',')
    if len(data) == 2 and '' == data[1]:
      del(data[1])

    return data

  def load_hardware(self):
    address = self.__get_address()
    if len(address) == 2:
      self._device = SmartStrip(address[0])
    else:
      self._device = SmartPlug(address[0])

  def set_hardware_state(self, state, force = False):

    async def __set_hardware_state(device,address,state):
      await device.update()
      strip = len(address) == 2
      plug = (device if not strip else device.plugs[int(address[1])-1])
      if state is True:
        await plug.turn_on()
      else:
        await plug.turn_off()

      return True

    address = self.__get_address()
    try:
      asyncio.run(__set_hardware_state(self._device,address,state))
      return True
    except RuntimeError as err:
      return True

  def get_hardware_state(self):
    data = []

    async def __get_hardware_state(device,address):
      await device.update()
      strip = len(address) == 2
      if strip:
        data.append(device.plugs[int(address[1])-1].is_on)
      else:
        data.append(device.is_on)

    address = self.__get_address()
    try:
      asyncio.run(__get_hardware_state(self._device,address))
    except RuntimeError as err:
      return None

    return len(data) == 1 and terrariumUtils.is_true(data[0])

  @staticmethod
  def scan_power_switches(callback=None, **kwargs):
    found_devices = []

    async def scan():
      devices = await Discover.discover()
      for ip_address in devices:
        device = devices[ip_address]
        await device.update()
        if device.is_strip:
          for counter in range(1,len(device.plugs)+1):
            found_devices.append(terrariumPowerSwitchTPLinkKasa(
                                    md5(('{}{}{}'.format(terrariumPowerSwitchTPLinkKasa.TYPE,device.device_id,counter)).encode()).hexdigest(),
                                    '{},{}'.format(device.host,counter),
                                    device.plugs[counter-1].alias,
                                    None,
                                    callback))

        else:
          found_devices.append(terrariumPowerSwitchTPLinkKasa(
                                  md5(('{}{}'.format(terrariumPowerSwitchTPLinkKasa.TYPE,device.device_id)).encode()).hexdigest(),
                                  '{}'.format(device.host),
                                  device.alias,
                                  None,
                                  callback))
    try:
      asyncio.run(scan())
    except RuntimeError as err:
      pass

    for device in found_devices:
       yield device


"""
Read file into texts and calls.
It's ok if you don't understand how to read files.
"""
from collections import Counter
import csv

with open('texts.csv', 'r') as f:
    reader = csv.reader(f)
    texts = list(reader)

with open('calls.csv', 'r') as f:
    reader = csv.reader(f)
    calls = list(reader)

"""
TASK 3:
(080) is the area code for fixed line telephones in Bangalore.
Fixed line numbers include parentheses, so Bangalore numbers
have the form (080)xxxxxxx.)

Part A: Find all of the area codes and mobile prefixes called by people
in Bangalore.
 - Fixed lines start with an area code enclosed in brackets. The area
   codes vary in length but always begin with 0.
 - Mobile numbers have no parentheses, but have a space in the middle
   of the number to help readability. The prefix of a mobile number
   is its first four digits, and they always start with 7, 8 or 9.
 - Telemarketers' numbers have no parentheses or space, but they start
   with the area code 140.

Print the answer as part of a message:
"The numbers called by people in Bangalore have codes:"
 <list of codes>
The list of codes should be print out one per line in lexicographic order with no duplicates.

Part B: What percentage of calls from fixed lines in Bangalore are made
to fixed lines also in Bangalore? In other words, of all the calls made
from a number starting with "(080)", what percentage of these calls
were made to a number also starting with "(080)"?

Print the answer as a part of a message::
"<percentage> percent of calls from fixed lines in Bangalore are calls
to other fixed lines in Bangalore."
The percentage should have 2 decimal digits
"""

def show_codes_called_in_bangalore(calls):
    codes = get_area_codes(calls)  # Time O(n) Space O(n)
    unique_codes = sorted(set(codes))  # Type casting to set O(n) + Sort O(n log n). Space O(n)
    print("The numbers called by people in Bangalore have codes:")
    for record in unique_codes:  # O(n) for the worst case
        print(record)

    print_percentage_from_to_bangalore(codes)  # Time O(n) Space O(n)

def print_percentage_from_to_bangalore(codes):
    # Counter is a subclass of Dict and requires order of O(n) to traverse all elements of iterable input. Space used O(n)
    counted_codes_per_area = Counter(codes)  # O(n)
    total_codes = len(codes)  # O(1)
    total_codes_bangalore = counted_codes_per_area['(080)']  # Dict get Time complexity O(1), Space (1)
    percent = total_codes_bangalore * 100 / total_codes  # float of max 4 bytes Space O(1)
    print(f"{percent:.2f} percent of calls from fixed lines in Bangalore are calls to other fixed lines in Bangalore.")

def get_area_codes(calls):
    codes = []  # Space complexity O(n)
    for record in calls:  # List loop O(n)
        if record[0].startswith("(080)"):
            code = extract_code(record[1])  # extract_code: O(1)
            codes.append(code)  # List append O(1)
    return codes

def extract_code(record):
    if record.startswith("("):
        ind = record.index(")")
        return record[:ind+1]
    return record[:4]

show_codes_called_in_bangalore(calls)


import torch
import torch.nn as nn
from glasses.models.classification.fishnet import FishNet, FishNetBottleNeck
from glasses.nn.att import SpatialSE
from torchinfo import summary

def test_fishnet():
    device = torch.device("cpu")
    x = torch.rand(1, 3, 224, 224)

    model = FishNet().eval()
    pred = model(x)
    assert pred.shape[-1] == 1000
    # test fishnet99
    model = FishNet.fishnet99().eval()
    pred = model(x)
    assert pred.shape[-1] == 1000

    # n_params, _ = summary(model.to(device), (3, 224, 224), device=device)
    # # we know the correct number of paramters of fishnet
    # assert n_params.item() == 16628904

    # test fishnet150
    model = FishNet.fishnet150().eval()
    pred = model(x)
    assert pred.shape[-1] == 1000

    # n_params, _ = summary(model.to(device), (3, 224, 224), device=device)
    # # we know the correct number of paramters of fishnet
    # assert n_params.item() == 24959400

    block = lambda in_ch, out_ch, **kwargs: nn.Sequential(
        FishNetBottleNeck(in_ch, out_ch), SpatialSE(out_ch)
    )
    model = FishNet.fishnet99(block=block)
    pred = model(x)
    assert pred.shape[-1] == 1000
    # summary(model.to(device), (3, 224, 224))


from selenium import webdriver
import time
import math

try:
    actual_result = "abrakadabra"
    print("Wrong text, got " + actual_result + ", something wrong")

    print("Let's count together: {}, then goes {}, and then {}".format("one", "two", "three"))

    actual_result = "abrakadabra"
    print(f"Wrong text, got '{actual_result}', something wrong")

    str1 = "one"
    str2 = "two"
    str3 = "three"
    print(f"Let's count together: {str1}, then goes {str2}, and then {str3}")

    print(f"Simple 2 x 2 = {2*2}")

except Exception as error:
    print(f'ОШИБКА: {error}')

finally:
    time.sleep(1)

# не забываем оставить пустую строку в конце файла


# coding=utf-8
import time

import numpy as np
import pgmath as pm
import pgutils as pu

def single_point_algorithm(songs, transition_matrix, params):
    # assignment a random position at each song in the target space
    position = np.random.rand(songs, params.dimension)
    position_new = np.empty_like(position)

    # error for stopping criteria mean square error
    squared_error = 200

    tic = time.perf_counter()
    batch = pu.initialize_landmarks(songs, params, transition_matrix)
    toc = time.perf_counter()
    print('init landmarks', toc - tic)

    # calculus of the distance matrix (distance matrix for norm and vector, partition function )
    distances = pm.Distances(position, batch)

    # try 100, 200 iterations
    for i in range(params.n_iter):

        print('Iteration', i)

        if i % 10 == 0:
            tic = time.perf_counter()
            pu.update_landmarks(songs, batch, position, params)
            toc = time.perf_counter()
            print('Updated landmarks:', toc - tic, " seconds")

        # update the position of the songs
        tic = time.perf_counter()
        pu.update_songs(position_new, transition_matrix, position, params, distances)
        toc = time.perf_counter()

        print("Time to update songs:", toc - tic, " seconds")

        squared_error_new = (np.square(position_new - position)).mean(axis=None)
        # stop criteria
        if np.abs(squared_error_new - squared_error) < 1E-8 * squared_error:
            return position
        else:
            position_new, position = position, position_new
            squared_error = squared_error_new

        tic = time.perf_counter()
        distances.update(position, batch)
        toc = time.perf_counter()

        print("Time to update distances:", toc - tic, " seconds")

    return position_new


'''
Created on 6. juli 2012

@author: Joakim
'''
from google.appengine.ext import db

class Wikipage(db.Model):
    content = db.TextProperty(required = True)
    created = db.DateTimeProperty(auto_now_add = True)

    @classmethod
    def update(cls, content, page):
        key = db.Key.from_path('wiki', page)
        return cls(content=content, parent=key)

    @classmethod
    def getPage(cls, page, version):
        q = cls.all()
        key = db.Key.from_path('wiki', page)
        if q.ancestor(key) is None:
            return None
        list = q.ancestor(key).order('-created').fetch(20)
        if not list:
            return None
        if not version.isdigit():
            return list[0]
        version = int(version)
        return list[version-1]

    @classmethod
    def getHistory(cls, page):
        q = cls.all()
        key = db.Key.from_path('wiki', page)
        if q.ancestor(key) is None:
            return None
        return q.ancestor(key).order('-created').fetch(20)


import requests
import configparser
import json
import sys
import pytz
from pytz import timezone
from datetime import datetime, timedelta

# Import config file and create config section
config = configparser.ConfigParser()
config.read("/opt/config/vision.cfg")
cfg_weather = config["weather"]

# Default timezone and date format
utc = pytz.utc
fmt = "%d.%m %H:%M"

# Return the json response data for a specific forecast location
def getForecast(location):
    if location == "default":
        url = (
            "https://api.openweathermap.org/data/2.5/forecast?q="
            + cfg_weather["location"]
            + "&mode=json&units=metric&lang=de&APPID="
            + cfg_weather["apikey"]
        )
    else:
        url = (
            "https://api.openweathermap.org/data/2.5/forecast?q="
            + location
            + "&mode=json&units=metric&lang=de&APPID="
            + cfg_weather["apikey"]
        )

    json_data = json.loads(requests.request("GET", url, data="", headers="").text)
    return json_data

# Create the string to return if request was either 200 or 400
def createString(json_data, location):
    if json_data["cod"] == "404":
        return "Die gesuchte Stadt wurde nicht gefunden."
    forecast_list = json_data["list"]
    if location == "default":
        string = "Wetter in: " + cfg_weather["location"] + """\n"""
    else:
        string = "Wetter in: " + location + """\n"""
    i = 0
    while i < 3:
        utc_dt = utc.localize(datetime.utcfromtimestamp(forecast_list[i]["dt"]))
        de_tz = timezone("Europe/Berlin")
        de_dt = utc_dt.astimezone(de_tz)
        string = (
            string
            + str(de_dt.strftime(fmt))
            + " / "
            + str(forecast_list[i]["main"]["temp"])
            + "°C / "
            + forecast_list[i]["weather"][0]["description"]
            + """\n"""
        )
        i += 1
    return string

print(createString(getForecast(sys.argv[1]), sys.argv[1]))


# =============================================================================
# IMPORTS
# =============================================================================
# Python
from datetime import timedelta
from random import randint
from unittest import mock

# Django
from django.core.exceptions import ValidationError
from django.db import models
from django.test import TestCase
from django.urls import reverse
from django.utils.timezone import now

# App
from games.models import Game
from project_manager.constants import (
    FORUM_THREAD_URL,
    LOGO_MAX_HEIGHT,
    LOGO_MAX_WIDTH,
    PROJECT_BASENAME_MAX_LENGTH,
    PROJECT_SLUG_MAX_LENGTH,
)
from project_manager.models.abstract import Project
from project_manager.validators import basename_validator
from project_manager.plugins.models import Plugin
from project_manager.sub_plugins.constants import SUB_PLUGIN_LOGO_URL
from project_manager.sub_plugins.helpers import handle_sub_plugin_logo_upload
from project_manager.sub_plugins.models import (
    SubPlugin,
    SubPluginContributor,
    SubPluginGame,
    SubPluginTag,
)
from tags.models import Tag
from test_utils.factories.sub_plugins import (
    SubPluginFactory,
    SubPluginReleaseFactory,
)
from users.models import ForumUser

# =============================================================================
# TEST CASES
# =============================================================================
class SubPluginTestCase(TestCase):
    def test_model_inheritance(self):
        self.assertTrue(
            expr=issubclass(SubPlugin, Project)
        )

    def test_basename_field(self):
        field = SubPlugin._meta.get_field('basename')
        self.assertIsInstance(
            obj=field,
            cls=models.CharField,
        )
        self.assertEqual(
            first=field.max_length,
            second=PROJECT_BASENAME_MAX_LENGTH,
        )
        self.assertIn(
            member=basename_validator,
            container=field.validators,
        )
        self.assertFalse(expr=field.unique)
        self.assertTrue(expr=field.blank)
        self.assertFalse(expr=field.null)

    def test_owner_field(self):
        field = SubPlugin._meta.get_field('owner')
        self.assertIsInstance(
            obj=field,
            cls=models.ForeignKey,
        )
        self.assertEqual(
            first=field.remote_field.model,
            second=ForumUser,
        )
        self.assertEqual(
            first=field.remote_field.on_delete,
            second=models.SET_NULL,
        )
        self.assertEqual(
            first=field.remote_field.related_name,
            second='sub_plugins',
        )
        self.assertFalse(expr=field.blank)
        self.assertTrue(expr=field.null)

    def test_contributors_field(self):
        field = SubPlugin._meta.get_field('contributors')
        self.assertIsInstance(
            obj=field,
            cls=models.ManyToManyField,
        )
        self.assertEqual(
            first=field.remote_field.model,
            second=ForumUser,
        )
        self.assertEqual(
            first=field.remote_field.related_name,
            second='sub_plugin_contributions',
        )
        self.assertEqual(
            first=field.remote_field.through,
            second=SubPluginContributor,
        )

    def test_slug_field(self):
        field = SubPlugin._meta.get_field('slug')
        self.assertIsInstance(
            obj=field,
            cls=models.SlugField,
        )
        self.assertEqual(
            first=field.max_length,
            second=PROJECT_SLUG_MAX_LENGTH,
        )
        self.assertFalse(expr=field.unique)
        self.assertFalse(expr=field.primary_key)
        self.assertTrue(expr=field.blank)
        self.assertFalse(expr=field.null)

    def test_plugin_field(self):
        field = SubPlugin._meta.get_field('plugin')
        self.assertIsInstance(
            obj=field,
            cls=models.ForeignKey,
        )
        self.assertEqual(
            first=field.remote_field.model,
            second=Plugin,
        )
        self.assertEqual(
            first=field.remote_field.related_name,
            second='sub_plugins',
        )
        self.assertEqual(
            first=field.remote_field.on_delete,
            second=models.CASCADE,
        )

    def test_supported_games_field(self):
        field = SubPlugin._meta.get_field('supported_games')
        self.assertIsInstance(
            obj=field,
            cls=models.ManyToManyField,
        )
        self.assertEqual(
            first=field.remote_field.model,
            second=Game,
        )
        self.assertEqual(
            first=field.remote_field.related_name,
            second='sub_plugins',
        )
        self.assertEqual(
            first=field.remote_field.through,
            second=SubPluginGame,
        )

    def test_tags_field(self):
        field = SubPlugin._meta.get_field('tags')
        self.assertIsInstance(
            obj=field,
            cls=models.ManyToManyField,
        )
        self.assertEqual(
            first=field.remote_field.model,
            second=Tag,
        )
        self.assertEqual(
            first=field.remote_field.related_name,
            second='sub_plugins',
        )
        self.assertEqual(
            first=field.remote_field.through,
            second=SubPluginTag,
        )

    def test_primary_attributes(self):
        self.assertEqual(
            first=SubPlugin.handle_logo_upload,
            second=handle_sub_plugin_logo_upload
        )
        self.assertEqual(
            first=SubPlugin.logo_path,
            second=SUB_PLUGIN_LOGO_URL,
        )

    def test__str__(self):
        sub_plugin = SubPluginFactory()
        self.assertEqual(
            first=str(sub_plugin),
            second=f'{sub_plugin.plugin.name}: {sub_plugin.name}',
        )

    def test_current_version(self):
        sub_plugin = SubPluginFactory()
        created = now()
        for offset, version in enumerate([
            '1.0.0',
            '1.0.1',
            '1.1.0',
            '1.0.9',
        ]):
            release = SubPluginReleaseFactory(
                sub_plugin=sub_plugin,
                version=version,
                created=created + timedelta(minutes=offset),
            )
            self.assertEqual(
                first=sub_plugin.current_version,
                second=release.version,
            )

    def test_total_downloads(self):
        sub_plugin = SubPluginFactory()
        total_downloads = 0
        for _ in range(randint(3, 7)):
            download_count = randint(1, 20)
            total_downloads += download_count
            SubPluginReleaseFactory(
                sub_plugin=sub_plugin,
                download_count=download_count,
            )

        self.assertEqual(
            first=sub_plugin.total_downloads,
            second=total_downloads,
        )

    @mock.patch(
        target='project_manager.models.abstract.Image.open',
    )
    def test_clean_logo(self, mock_image_open):
        SubPlugin().clean()
        mock_image_open.return_value.size = (
            LOGO_MAX_WIDTH,
            LOGO_MAX_HEIGHT,
        )
        SubPlugin(logo='test.jpg').clean()

        mock_image_open.return_value.size = (
            LOGO_MAX_WIDTH + 1,
            LOGO_MAX_HEIGHT + 1,
        )
        with self.assertRaises(ValidationError) as context:
            SubPlugin(logo='test.jpg').clean()

        self.assertEqual(
            first=len(context.exception.messages),
            second=2,
        )
        self.assertIn(
            member=f'Logo width must be no more than {LOGO_MAX_WIDTH}.',
            container=context.exception.messages,
        )
        self.assertIn(
            member=f'Logo height must be no more than {LOGO_MAX_HEIGHT}.',
            container=context.exception.messages,
        )

    @mock.patch(
        target='project_manager.models.abstract.settings.MEDIA_ROOT',
    )
    def test_save(self, mock_media_root):
        basename = 'test'
        mock_obj = mock.Mock(
            stem=basename,
        )
        mock_media_root.__truediv__.return_value.files.return_value = [mock_obj]
        SubPluginFactory(
            basename=basename,
            logo='test.jpg',
        )
        mock_obj.remove.assert_called_once_with()

    def test_get_forum_url(self):
        sub_plugin = SubPluginFactory()
        self.assertIsNone(obj=sub_plugin.get_forum_url())

        topic = randint(1, 40)
        sub_plugin = SubPluginFactory(
            topic=topic,
        )
        self.assertEqual(
            first=sub_plugin.get_forum_url(),
            second=FORUM_THREAD_URL.format(topic=topic),
        )

    def test_get_absolute_url(self):
        sub_plugin = SubPluginFactory()
        self.assertEqual(
            first=sub_plugin.get_absolute_url(),
            second=reverse(
                viewname='plugins:sub-plugins:detail',
                kwargs={
                    'slug': sub_plugin.plugin_id,
                    'sub_plugin_slug': sub_plugin.slug,
                }
            )
        )

    def test_meta_class(self):
        self.assertTrue(issubclass(SubPlugin.Meta, Project.Meta))
        self.assertTupleEqual(
            tuple1=SubPlugin._meta.unique_together,
            tuple2=(
                ('plugin', 'basename'),
                ('plugin', 'name'),
                ('plugin', 'slug'),
            )
        )
        self.assertEqual(
            first=SubPlugin._meta.verbose_name,
            second='SubPlugin',
        )
        self.assertEqual(
            first=SubPlugin._meta.verbose_name_plural,
            second='SubPlugins',
        )


import os
import sys
import pandas as pd
import warnings
import re

warnings.simplefilter(action='ignore', category=FutureWarning)

os.chdir(os.path.dirname(sys.argv[0]))

def gather():
    # Load the data
    df = pd.read_csv('saves/MH3U_user.csv')
    df.set_index('Name', inplace=True)

    # Create dataframes
    df2 = pd.DataFrame(data={'ID':0,'Name':0,'Total Quantity':0,'Quantity in box':0,'Quantity on hunter':0,'Rarity':0},index=(0,1))
    df3 = pd.DataFrame(data={'ID':0,'Type':0,'Name':0,'Level':0,'Quantity':0,'Rarity':0,'Category':0,'Subcategory':0},index=(0,1))

    # Locate items and equipment
    index_inv = df.index.get_loc('struct inventory i[1]')
    df_inv = df.iloc[index_inv:index_inv+74]
    index_pouch = df.index.get_loc('struct pouch i[2]')
    df_pouch = df.iloc[index_pouch:index_pouch+98]
    index_chest = df.index.get_loc('struct chest i[3]')
    df_chest = df.iloc[index_chest:index_chest+3002]
    index_box = df.index.get_loc('struct box i[4]')
    df_box = df.iloc[index_box:index_box+12002]
    df_inv.reset_index(inplace=True)
    df_pouch.reset_index(inplace=True)
    df_chest.reset_index(inplace=True)
    df_box.reset_index(inplace=True)

    # Gather inventory items
    for i in range(0,74):
        if 'ID' in df_inv.iloc[i,0]:
            id = df_inv.iloc[i,1]
        if 'count' in df_inv.iloc[i,0]:
            count = df_inv.iloc[i,1]
            s = {'ID':id,'Name':0,'Total Quantity':0,'Quantity in box':0,'Quantity on hunter':int(count),'Rarity':0}
            df2 = df2.append(s,ignore_index=True)

    # Gather item pouch items
    for i in range(0,98):
        if 'ID' in df_pouch.iloc[i,0]:
            id = df_pouch.iloc[i,1]
        if 'count' in df_pouch.iloc[i,0]:
            count = df_pouch.iloc[i,1]
            s = {'ID':id,'Name':0,'Total Quantity':0,'Quantity in box':0,'Quantity on hunter':int(count),'Rarity':0}
            df2 = df2.append(s,ignore_index=True)

    # Gather chest items
    for i in range(0,3002):
        if 'ID' in df_chest.iloc[i,0]:
            id = df_chest.iloc[i,1]
        if 'count' in df_chest.iloc[i,0]:
            count = df_chest.iloc[i,1]
            s = {'ID':id,'Name':0,'Total Quantity':0,'Quantity in box':int(count),'Quantity on hunter':0,'Rarity':0}
            df2 = df2.append(s,ignore_index=True)

    # Gather equipment
    for i in range(0,12002):
        if 'type' in df_box.iloc[i,0]:
            type = df_box.iloc[i,1]
        if 'level_or_slot_count' in df_box.iloc[i,0]:
            level = df_box.iloc[i,1]
        if 'ID' in df_box.iloc[i,0]:
            id = df_box.iloc[i,1]
            s = {'ID':id,'Type':type,'Name':0,'Level':level,'Quantity':1,'Rarity':0,'Category':0,'Subcategory':0}
            df3 = df3.append(s,ignore_index=True)

    # Clean dataframes
    df2['Total Quantity'] = df2['Quantity in box'] + df2['Quantity on hunter']

    # Adding dictionaries
    df_dict_items = pd.read_csv('dictionaries/MH3U_dictionary_items.csv')
    df_dict_items.set_index('ID', inplace=True)
    df_dict_equipment = pd.read_csv('dictionaries/MH3U_dictionary_equipment.csv')

    # Add item information
    for i in range(len(df2)):
        id = df2.iloc[i,0]
        try:
            s = {'ID':id,'Name':df_dict_items.loc[int(float(id)),'Name'],'Total Quantity':0,'Quantity in box':0,'Quantity on hunter':0,'Rarity':df_dict_items.loc[int(float(id)),'Rarity']}
            df2 = df2.append(s,ignore_index=True)
        except KeyError:
            continue

    # Adding equipment information
    for i in range(len(df3)):
        id = df3.iloc[i,0]
        type = df3.iloc[i,1]
        df_temp = df_dict_equipment[(df_dict_equipment['ID'] == int(float(id))) & (df_dict_equipment['Type'] == int(float(type)))]
        try:
            df_temp.reset_index(inplace=True)
            s = {'ID':id,'Type':type,'Name':df_temp.loc[0,'Name'],'Level':0,'Quantity':0,'Rarity':df_temp.loc[0,'Rarity'],'Category':df_temp.loc[0,'Category'],'Subcategory':df_temp.loc[0,'Subcategory']}
            df3 = df3.append(s,ignore_index=True)
        except KeyError:
            continue

    # Cleaning
    df2 = df2.groupby(df2['ID'],sort=False).aggregate({'Name':'last','Total Quantity':'sum','Quantity in box':'sum','Quantity on hunter':'sum','Rarity':'last'})
    df3 = df3.groupby([df3['ID'],df3['Type']],sort=False).aggregate({'Name':'last','Level':'first','Quantity':'sum','Rarity':'last','Category':'last','Subcategory':'last'})

    # Outputting dataframes
    df2.to_csv(r'outputs/MH3U_output_items.csv',encoding='utf-8')
    df3.to_csv(r'outputs/MH3U_output_equipment.csv',encoding='utf-8')


from random import choice

def run_game():
    word=choice(["hello","name","Tharun"])

    name=input("Enter your name:")
    print(f"welcome to the game Hangman: {name}")

    guessed_chars=""
    tries=3
    cheat=1

    while tries>0:
        blanks=0
        print("Word: ",end="")
        for char in word:
            if char in guessed_chars:
                print(char,end="")
            else:
                print("_",end="")
                blanks+=1
        print()
        if(blanks==0):
            print("You got it")
            break
        guess_the_letter=input("Enter a letter: ")
        if(len(guess_the_letter)>1):
            if(cheat==1):
                print("U r trying cheat...Final Warning")
                cheat-=1
                continue
            else:
                print("You have cheated more than once..You are out od the game")
                break
        if(guess_the_letter in guessed_chars):
            print("You have used the letter....dont waste your time")
            continue
        #adding the letter to the previous guessed letter
        guessed_chars+=guess_the_letter
        if guess_the_letter not in word:
            tries-=1
            print("You have guessed wrong letter...{tries} tries remaining")

            if tries==0:
                print("Sorry...You have Lost!")
                break

if __name__=="__main__" :
    run_game()


from .transforms              import build_transform
from torchvision              import datasets
from torch.utils.data         import DataLoader, Dataset
from torch.utils.data.sampler import SubsetRandomSampler
from pandas                   import Series, DataFrame
from PIL                      import Image

import numpy  as np
import pandas as pd
import os

np.random.seed(11)

def make_train_loader(cfg):

    num_workers = cfg.DATA.NUM_WORKERS
    batch_size  = cfg.DATA.TRAIN_BATCH_SIZE
    valid_size  = cfg.DATA.VALIDATION_SIZE
    train_path  = cfg.PATH.TRAIN_SET
    csv_path    = cfg.PATH.CSV_PATH

    train_df = pd.read_csv(csv_path + 'train.csv')

    labels = train_df['label']
    label_np = Series.to_numpy(labels)

    #看一下一共多少不同种类
    label_set = set(label_np)

    #构建一个编号与名称对应的字典，以后输出的数字要变成名字的时候用：
    label_list = list(label_set)
    dic = {}
    for i in range(3):
        dic[  label_list[i]   ] = i

    train_file =  Series.to_numpy(train_df["image_id"])
    file_train = [os.path.join(train_path, i) for i in train_file ]
    # np.save( "file_train.npy" ,file_train )

    train_labels = Series.to_numpy(train_df["label"])

    number_train = []

    for i in range(train_labels.shape[0]):
        number_train.append(  dic[ train_labels[i] ]  )

    number_train = np.array(number_train)

    # np.save( "number_train.npy" ,number_train )

    transforms = build_transform(cfg)

    def default_loader(path):
        img_pil =  Image.open(path)
        img_pil = img_pil.resize((224,224))
        img_tensor = transforms(img_pil)
        return img_tensor

    class train_set(Dataset):
        def __init__(self, loader=default_loader):
            #定义好 image 的路径
            self.images = file_train
            self.target = number_train
            self.loader = loader

        def __getitem__(self, index):
            fn = self.images[index]
            img = self.loader(fn)
            target = self.target[index]
            return img,target

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

    trainset  = train_set()

    num_train = len(trainset)
    indices = list(range(num_train))
    split = int(np.floor(valid_size * num_train))

    np.random.shuffle(indices)

    train_idx, valid_idx = indices[split:], indices[:split]
    train_sampler = SubsetRandomSampler(train_idx)
    valid_sampler = SubsetRandomSampler(valid_idx)

    train_loader = DataLoader(trainset, batch_size=batch_size, num_workers=num_workers, sampler=train_sampler)
    valid_loader = DataLoader(trainset, batch_size=batch_size, num_workers=num_workers, sampler=valid_sampler)

    return train_loader, valid_loader

def make_test_loader(cfg):

    num_workers = cfg.DATA.NUM_WORKERS
    batch_size  = cfg.DATA.TEST_BATCH_SIZE
    test_path   = cfg.PATH.TEST_SET
    csv_path    = cfg.PATH.CSV_PATH

    dev_df = pd.read_csv(csv_path + 'dev.csv')

    labels = dev_df['label']
    label_np = Series.to_numpy(labels)

    #看一下一共多少不同种类
    label_set = set(label_np)

    #构建一个编号与名称对应的字典，以后输出的数字要变成名字的时候用：
    label_list = list(label_set)
    dic = {}
    for i in range(3):
        dic[  label_list[i]   ] = i

    dev_file =  Series.to_numpy(dev_df["image_id"])
    file_dev = [os.path.join(test_path, i) for i in dev_file ]
    np.save( "file_dev.npy" ,file_dev )

    dev_labels = Series.to_numpy(dev_df["label"])

    number_dev = []

    for i in range(dev_labels.shape[0]):
        number_dev.append(  dic[ dev_labels[i] ]  )

    number_dev = np.array(number_dev)

    # np.save( "number_dev.npy" ,number_dev )

    transforms = build_transform(cfg)

    def default_loader(path):
        img_pil =  Image.open(path)
        img_pil = img_pil.resize((224,224))
        img_tensor = transforms(img_pil)
        return img_tensor

    class train_set(Dataset):
        def __init__(self, loader=default_loader):
            #定义好 image 的路径
            self.images = file_dev
            self.target = number_dev
            self.loader = loader

        def __getitem__(self, index):
            fn = self.images[index]
            img = self.loader(fn)
            target = self.target[index]
            return img,target

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

    devset  = train_set()

    test_loader = DataLoader(devset, batch_size=batch_size, num_workers=num_workers)

    return test_loader


# Bom dia 0 - 11, Boa tarde 12-17 e Boa noite 18-23.

horario = input('Qual o horário atual? ')

if horario.isnumeric():
    horario = int(horario)
    if horario <= 11:
        print('Bom dia!')
    elif horario <= 17:
        print('Boa tarde!')
    elif horario <= 23:
        print('Boa noite!')
    elif horario < 0 or horario > 23:
        print('Por favor, insira um horário válido')
else:
    print('Por favor, insira um horário válido')


from fastapi import FastAPI, Body
from pydantic import BaseModel, Field

app = FastAPI()

class Item(BaseModel):
    name: str
    description: str | None = None
    price: float
    tax: float | None = None

    class Config:
        schema_extra = {
            "example":{
                "name": "Book",
                "description": "Book is written by Yubraj Upadhaya.",
                "price": 45.3,
                "tax": 12.3
            }
        }

@app.post('/config-items/')
async def create_items(item: Item):
    return item.dict()

@app.post('/single-example-items')
async def single_example_item(item: Item = Body(example={
                "name": "Book",
                "description": "Book is written by Yubraj Upadhaya.",
                "price": 45.3,
                "tax": 12.3
            })):
            return item.dict()

@app.post('/multiple-example-items/')
async def multiple_example_items(item: Item = Body(examples={
                "normal":{
                    "summary": "A normal example.",
                    "description": "Just Test",
                    "value":{
                        "name": "Book",
                        "description": "Book is written by Yubraj Upadhaya.",
                        "price": 45.3,
                        "tax": 12.3
                    },
                },
                "converted":{
                    "summary": "A converted example.",
                    "description": "Just Test",
                    "value":{
                        "name": "Book",
                        "description": "Book is written by Yubraj Upadhaya.",
                        "price": 45.3,
                        "tax": 12.3
                    },
                },
            })):
    return item.dict()


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

# In[3]:

import os
import csv
import math
import pandas as pd
import PySimpleGUI as sg
import logging

logging.basicConfig(filename='example.log', level=logging.DEBUG, format='%(message)s')
#ask for user input
sg.theme('SandyBeach')
layout = [
    [sg.Text('Which sheet and column would you like to work with?')],
    [sg.Text('Column Name', size =(15, 1)), sg.InputText()],
    #[sg.Text('Sheet Number', size =(15, 1)), sg.InputText()],
    [sg.Submit(), sg.Cancel()]
]
window = sg.Window('Simple data entry window', layout)
event, values = window.read()
window.close()

#sheetNumber=values[1]
columnName=values[0]

for folderName in os.scandir():
    if folderName.is_dir():
        print(folderName)
        logging.info(folderName)
        for filename in os.scandir(folderName):
            try:
                if filename.path.endswith(".csv"):
                    overWriteColumn=[]
                    df = pd.read_csv(filename.path)
                    toOverwrite= df[columnName]
                    for unrounded in toOverwrite:
                        print(str(unrounded) + " rounded to "+ str(round(float(unrounded),6)))
                        logging.info(str(unrounded) + " rounded to "+ str(round(float(unrounded),6)))
                        overWriteColumn.append(round(float(unrounded),6))
                    df[columnName]=overWriteColumn
                    df.drop(df.columns[df.columns.str.contains('unnamed',case = False)],axis = 1, inplace = True)
                    df.to_csv(filename.path, index=False)
                    print("Done: "+ filename.name)
                    logging.info("Done: "+ filename.name)
            except Exception as e:
                print(str(e)+ " : " +filename.name)
                logging.info(str(e)+ " : " +filename.name)
                pass

input("Press any key to exit")

# In[ ]:


"""
Hello World example

Author: Alexander Hentschel, alex.hentschel@axiomzen.co
"""

import numpy as np

# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ #
# Change matplotlib backend from "MacOSX" (default) to "TKAgg"
# This should fix a variety of issues under MacOS.
# IMPORTANT: execute in a newly opend Python Console.
# ............................................................................ #
import matplotlib as mpl
mpl.use("TKAgg", warn=False, force=True)

# For making this change permanent, modify your `~/.matplotlib/matplotlibrc`
# as described in the 01_setup_python.md.
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ #

import matplotlib.pyplot as plt

def sample_sin(start=0, stop=10, points=10000):
    x = np.linspace(start, stop, num=points)
    y = np.sin(x)
    return x,y

x, y =  sample_sin()

fig = plt.figure()
plt.plot(x,y)
plt.draw()


# coding: utf-8

import sys
import requests

month=sys.argv[1]
start=sys.argv[2]
end=sys.argv[3]

users = set()
messages = 0

for day in range(int(start), int(end)):
    if len(str(day)) < 2:
        day = '0%s' % day
    if len(str(month)) < 2:
        month = '0%s' % month

    day = str(day)
    month = str(month)

    log = requests.get('http://irclogs.ubuntu.com/2015/{1}/{0}/%23juju.txt'.format(day, month))
    data = log.text.split('\n')
    for line in data:
        if not line.startswith('['):
            continue
        time, user, _ = line.split(' ', 2)
        messages += 1
        users.add(user)

print(len(users))
print(messages)


# -*- coding: utf-8 -*-
"""
Created on Thu Jun 20 13:31:27 2019

@author: daryl
"""

import csv
import os
from functools import partial
import json

import geopandas as gpd
import matplotlib
#matplotlib.use('Agg')
import matplotlib.pyplot as plt

from gerrychain import (
    Election,
    Graph,
    MarkovChain,
    Partition,
    accept,
    constraints,
    updaters,
)
from gerrychain.metrics import efficiency_gap, mean_median
from gerrychain.proposals import recom, propose_random_flip
from gerrychain.updaters import cut_edges
from gerrychain.tree import recursive_tree_part, bipartition_tree_random

state_abbr = "MA"
housen = "SEN"
state_fip = "25"
num_districts = 40

newdir = "./Outputs/"+state_abbr+housen+"_Precincts/"
os.makedirs(os.path.dirname(newdir + "init.txt"), exist_ok=True)
with open(newdir + "init.txt", "w") as f:
    f.write("Created Folder")

graph = Graph.from_json("./Data/MA2010.json")

df = gpd.read_file("./Data/MA_precincts_12_16.shp")
print("built graph")

unique_label = "GEOID10"
pop_col = "TOTPOP"

#df["nWHITE"] = df["TOTPOP"] - df["WHITE"]
import pandas as pd

num_elections = 6

election_names = [
    "BVAP",
    "SEN12",
    "PRES12",
    "SEN13",
    "SEN14",
    "PRES16"]

election_columns = [
    ["BVAP", "nBVAP"],
    ["SEN12D","SEN12R"],
    ["PRES12D","PRES12R"],
    ["SEN13D","SEN13R"],
    ["SEN14D","SEN14R"],
    ["PRES16D", "PRES16R"]
    ]

totpop = 0
for n in graph.nodes():
    graph.node[n]["TOTPOP"] = int(graph.node[n]["TOTPOP"])
    graph.node[n]["VAP"] = int(graph.node[n]["VAP"])
    graph.node[n]["BVAP"] = int(graph.node[n]["BVAP"])
    for i in range(1,num_elections):
        for j in election_columns[i]:
            graph.node[n][j] = int(graph.node[n][j].replace(',', ''))

    graph.node[n]["nBVAP"] = graph.node[n]["VAP"] - graph.node[n]["BVAP"]
    totpop+= graph.node[n]["TOTPOP"]

for i in range(1):
    cddict =  recursive_tree_part(graph,range(num_districts),totpop/num_districts,"TOTPOP", .01,1)

    df["initial"]=df.index.map(cddict)

    df.plot(column="initial",cmap="jet")
    plt.savefig(newdir+"initial.png")
    plt.close()

with open(newdir+"init.json", 'w') as jf1:
	    json.dump(cddict, jf1)

print("saved Initial")
updater = {
        "population": updaters.Tally("TOTPOP", alias="population"),
    "cut_edges": cut_edges,
            }

elections = [
    Election(
        election_names[i],
        {"First": election_columns[i][0], "Second": election_columns[i][1]},
    )
    for i in range(num_elections)
]

election_updaters = {election.name: election for election in elections}

updater.update(election_updaters)

initial_partition = Partition(graph, cddict, updater)
print("built initial partition")

ideal_population = sum(initial_partition["population"].values()) / len(
    initial_partition
)

proposal = partial(
    recom, pop_col="TOTPOP", pop_target=ideal_population, epsilon=0.05, node_repeats=1, method = bipartition_tree_random
)

#compactness_bound = constraints.UpperBound(
#    lambda p: len(p["cut_edges"]), 2 * len(initial_partition["cut_edges"])
#)

chain = MarkovChain(
    proposal=proposal,
    constraints=[
        constraints.within_percent_of_ideal_population(initial_partition, 0.05),
          #constraints.single_flip_contiguous#no_more_discontiguous
    ],
    accept=accept.always_accept,
    initial_state=initial_partition,
    total_steps=100000
)

print("initialized chain")

with open(newdir + "Start_Values.txt", "w") as f:
    f.write("Values for Starting Plan: Tree Recursive\n \n ")
    f.write("Initial Cut: " + str(len(initial_partition["cut_edges"])))
    f.write("\n")
    f.write("\n")

    for elect in range(num_elections):
        f.write(
            election_names[elect]
            + "District Percentages"
            + str(
                sorted(initial_partition[election_names[elect]].percents("First"))
            )
        )
        f.write("\n")
        f.write("\n")

        f.write(
            election_names[elect]
            + "Mean-Median :"
            + str(mean_median(initial_partition[election_names[elect]]))
        )

        f.write("\n")
        f.write("\n")

        f.write(
            election_names[elect]
            + "Efficiency Gap :"
            + str(efficiency_gap(initial_partition[election_names[elect]]))
        )

        f.write("\n")
        f.write("\n")

        f.write(
            election_names[elect]
            + "How Many Seats :"
            + str(initial_partition[election_names[elect]].wins("First"))
        )

        f.write("\n")
        f.write("\n")

print("wrote starting values")

pop_vec = []
cut_vec = []
votes = [[], [], [], [],[],[]]
mms = []
egs = []
hmss = []

t = 0
for part in chain:

    pop_vec.append(sorted(list(part["population"].values())))
    cut_vec.append(len(part["cut_edges"]))
    mms.append([])
    egs.append([])
    hmss.append([])

    for elect in range(num_elections):
        votes[elect].append(sorted(part[election_names[elect]].percents("First")))
        mms[-1].append(mean_median(part[election_names[elect]]))
        egs[-1].append(efficiency_gap(part[election_names[elect]]))
        hmss[-1].append(part[election_names[elect]].wins("First"))

    t += 1
    if t%100 ==0:
        print(t)
    if t % 2000 == 0:
        print(t)
        with open(newdir + "mms" + str(t) + ".csv", "w") as tf1:
            writer = csv.writer(tf1, lineterminator="\n")
            writer.writerows(mms)

        with open(newdir + "egs" + str(t) + ".csv", "w") as tf1:
            writer = csv.writer(tf1, lineterminator="\n")
            writer.writerows(egs)

        with open(newdir + "hmss" + str(t) + ".csv", "w") as tf1:
            writer = csv.writer(tf1, lineterminator="\n")
            writer.writerows(hmss)

        with open(newdir + "pop" + str(t) + ".csv", "w") as tf1:
            writer = csv.writer(tf1, lineterminator="\n")
            writer.writerows(pop_vec)

        with open(newdir + "cuts" + str(t) + ".csv", "w") as tf1:
            writer = csv.writer(tf1, lineterminator="\n")
            writer.writerows([cut_vec])

        with open(newdir + "assignment" + str(t) + ".json", "w") as jf1:
            json.dump(dict(part.assignment), jf1)

        for elect in range(num_elections):
            with open(
                newdir + election_names[elect] + "_" + str(t) + ".csv", "w"
            ) as tf1:
                writer = csv.writer(tf1, lineterminator="\n")
                writer.writerows(votes[elect])

        df["plot" + str(t)] = df.index.map(dict(part.assignment))
        df.plot(column="plot" + str(t), cmap="tab20")
        plt.savefig(newdir + "plot" + str(t) + ".png")
        plt.close()

        votes = [[], [], [], [],[],[]]
        mms = []
        egs = []
        hmss = []
        pop_vec = []
        cut_vec = []


import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D

point1 = np.array([0,0,0])
normal1 = np.array([1,-2,1])

point2 = np.array([0,-4,0])
normal2 = np.array([0,2,-8])

point3 = np.array([0,0,1])
normal3 = np.array([-4,5,9])

# the constant of a plane equation is the dot product of
# a point on the plane with the normal vector to the plane
d1 = -np.sum(point1*normal1)
d2 = -np.sum(point2*normal2)
d3 = -np.sum(point3*normal3)

xx, yy = np.meshgrid(range(30), range(30))

z1 = (-normal1[0]*xx - normal1[1]*yy - d1)*1./normal1[2]
z2 = (-normal2[0]*xx - normal2[1]*yy - d2)*1./normal2[2]
z3 = (-normal3[0]*xx - normal3[1]*yy - d3)*1./normal3[2]

plt3d = plt.figure().gca(projection='3d')
plt3d.plot_surface(xx, yy, z1, color='blue')
plt3d.plot_surface(xx, yy, z2, color='yellow')
plt3d.plot_surface(xx, yy, z3, color='cyan')
plt.show()