import collections

class Solution:
    def can_form_palindromes(self, ch_cnt_map):
        has_odd = False
        self.single_ch = ''
        for (ch, cnt) in ch_cnt_map.items():
            if cnt % 2 != 0:
                if not has_odd:
                    self.single_ch = ch
                    has_odd = True
                else:
                    return False

        return True

    def generatePalindromes(self, s):
        ch_cnt_map = collections.Counter(s)
        if not self.can_form_palindromes(ch_cnt_map):
            return []

        res = []
        def dfs(ch_cnt_map, acc_str, rest_n):
            if rest_n == 0:
                res.append(acc_str + self.single_ch + acc_str[::-1])
                return

            for (ch, cnt) in ch_cnt_map.items():
                if cnt >= 2:
                    ch_cnt_map[ch] -= 2
                    dfs(ch_cnt_map, acc_str + ch, rest_n - 1)
                    ch_cnt_map[ch] += 2

        dfs(ch_cnt_map, '', len(s) // 2)

        return res


'''
Created on 26 Apr. 2018

@author: christoph
'''

import numpy as np
from scipy.interpolate import UnivariateSpline
from scipy.signal import medfilt
from scipy import ndimage

# xdisp_boxsize = 1
# disp_boxsize = 15
# medfiltered_flat = medfilt(MW,[xdisp_boxsize,disp_boxsize])
# OR
# dum, filtered_flat = make_model_stripes(...) --> see spatial_profiles.py
#
# pix_sens_image = MW / medfiltered_flat   #should be roughly flat & scattering around 1
#
# smoothed_MW = MW / pix_sens_image    #ie for the flat fields that means that smoothed_MW = filtered flat...
# smoothed_img = img / pix_sens_image
#

# maybe the not-fitted offsets in the model_stripes from "make_model_stripes_gausslike" are causing a Fubar in the division here!?!?!?

def onedim_pixtopix_variations(f_flat, filt='gaussian', filter_width=25):
    """
    This routine applies a filter ('gaussian' / 'savgol' / 'median') to an observed flat field in order to determine the pixel-to-pixel sensitivity variations
    as well as the fringing pattern in the red orders. This is done in 1D, ie for the already extracted spectrum.

    INPUT:
    'f_flat'        : dictionary containing the extracted flux from the flat field (master white) (keys = orders)
    'filt'          : method of filtering ('gaussian' / 'savgol' / 'median') - WARNING: ONLY GAUSSIAN FILTER HAS BEEN IMPLEMENTED SO FAR!!!
    'filter_width'  : the width of the kernel for the filtering in pixels; defined differently for the different types of filters (see description of scipy.ndimage....)

    OUTPUT:
    'pix_sens'      : dictionary of the pixel-to-pixel sensitivities (keys = orders)
    'smoothed_flat' : dictionary of the smoothed (ie filtered) whites (keys = orders)

    MODHIST:
    24/05/2018 - CMB create
    """

    pix_sens = {}
    smoothed_flat = {}

    while filt.lower() not in ['g','gaussian','s','savgol','m','median']:
        print("ERROR: filter choice not recognised!")
        filt = raw_input("Please try again: ['(G)aussian','(S)avgol','(M)edian']")

    #loop over all orders
    for ord in sorted(f_flat.keys()):
        if filt.lower() in ['g','gaussian']:
            #Gaussian filter
            smoothed_flat[ord] = ndimage.gaussian_filter(f_flat[ord], filter_width)
            pix_sens[ord] = f_flat[ord] / smoothed_flat[ord]
        elif filt.lower() in ['s','savgol']:
            print('WARNING: SavGol filter not implemented yet!!!')
            break
        elif filt.lower() in ['m','median']:
            print('WARNING: Median filter not implemented yet!!!')
            break
        else:
            #This should never happen!!!
            print("ERROR: filter choice still not recognised!")
            break

    return smoothed_flat, pix_sens

def deblaze_orders(f, wl, smoothed_flat, mask, err=None, degpol=1, gauss_filter_sigma=3., maxfilter_size=100):

    f_dblz = {}
    if err is not None:
        err_dblz = {}

    #if using cross-correlation to get RVs, we need to de-blaze the spectra first
    for o in f.keys():
        #first, divide by the "blaze-function", ie the smoothed flat, which we got from filtering the MASTER WHITE
        f_dblz[o] = f[o] / (smoothed_flat[o]/np.max(smoothed_flat[o]))
        #get rough continuum shape by performing a series of filters
        cont_rough = ndimage.maximum_filter(ndimage.gaussian_filter(f_dblz[o],gauss_filter_sigma), size=maxfilter_size)
        #now fit polynomial to that rough continuum
        p = np.poly1d(np.polyfit(wl[o][mask[o]], cont_rough[mask[o]], degpol))
        #divide by that polynomial
        f_dblz[o] = f_dblz[o] / (p(wl[o]) / np.median(p(wl[o])[mask[o]]))
        #need to treat the error arrays in the same way, as need to keep relative error the same
        if err is not None:
            err_dblz[o] = err[o] / (smoothed_flat[o]/np.max(smoothed_flat[o]))
            err_dblz[o] = err_dblz[o] / (p(wl[o]) / np.median(p(wl[o])[mask[o]]))

    if err is not None:
        return f_dblz,err_dblz
    else:
        return f_dblz


from __future__ import print_function

import datetime
import pprint
import queue
import time

class Backtest(object):
    '''
    Encapsulates the settings and components for carrying out an event-driven backtest.

    :param csv_dir: Hard root to CSV data directory
    :param ticker_list: List of ticker strings
    :param initial_capital: Starting capital for portfolio
    :param heartbeat: Backtest "heartbeat" in seconds
    :param start_date: Start datetime of the strategy
    :param data_handler: (Class) Handles market datafeed
    :param execution_handler: (Class) Handles the orders/fills for trades
    :param portfolio: (Class) Keeps track of portfolio current and prior positions
    :param strategy: (Class) Generates signals based on market data
    '''
    def __init__(self, csv_dir, ticker_list, initial_capital, heartbeat, start_date, data_handler, execution_handler, portfolio, strategy):
        self.csv_dir = csv_dir
        self.ticker_list = ticker_list
        self.initial_capital = initial_capital
        self.heartbeat = heartbeat
        self.start_date = start_date

        self.data_handler_cls = data_handler
        self.execution_handler_cls = execution_handler
        self.portfolio_cls = portfolio
        self.strategy_cls = strategy

        self.events = queue.Queue()

        self.signals = 0
        self.orders = 0
        self.fills = 0
        self.num_strats = 1

        self._generate_trading_instances()

    def _generate_trading_instances(self):
        '''
        Generates trading instance objects from their class types.
        '''
        print('Creating DataHandler, Strategy, Portfolio, and ExecutionHandler')
        self.data_handler = self.data_handler_cls(self.events, self.csv_dir, self.ticker_list) # This is assuming HistoricCSVDataHandler class
        self.strategy = self.strategy_cls(self.data_handler, self.events)
        self.portfolio = self.portfolio_cls(self.data_handler, self.events, self.start_date, self.initial_capital)
        self.execution_handler = self.execution_handler_cls(self.events)

    def _run_backtest(self):
        '''
        Executes the backtest.
        '''
        i = 0
        while True:
            i += 1
            print(i)

            if self.data_handler.continue_backtest == True:
                self.data_handler.update_bars()
            else:
                break

            # Handle events queue
            while True:
                try:
                    event = self.events.get(False)
                except queue.Empty:
                    break
                else:
                    if event is not None:
                        if event.type == 'MARKET':
                            self.strategy.calculate_signals(event)
                            self.portfolio.update_timeindex(event)
                        elif event.type == 'SIGNAL':
                            self.signals += 1
                            self.portfolio.update_signal(event)
                        elif event.type == 'ORDER':
                            self.orders += 1
                            self.execution_handler.execute_order(event)
                        elif event.type == 'FILL':
                            self.fills += 1
                            self.portfolio.update_fill(event)

            time.sleep(self.heartbeat)

    def _output_performance(self):
        '''
        Outputs the strategy performance from the backtest
        '''
        self.portfolio.create_equity_curve_dataframe()

        print('Creating summary stats...')
        stats = self.portfolio.output_summary_stats()

        print('Creating equity curve...')
        print(self.portfolio.equity_curve.tail(10))
        pprint.pprint(stats)

        print('Signals: %s' % self.signals)
        print('Orders: %s' % self.orders)
        print('Fills: %s' % self.fills)

    def simulate_trading(self):
        '''
        Simulates the backtest and outputs portfolio performance.
        '''
        self._run_backtest()
        self._output_performance()


import random
import common

q = 2**255-19 # order of the field---hence the name ed25519

# order of the baseReferencePoint
l = 2**252 + 27742317777372353535851937790883648493

d = (-121665 * pow(121666,q-2,q))%q

# (d+1)^-1 = 121666

def scalar_pack(s):
    s %= l
    result = 32*[0]
    for i in range(32):
        result[i] = s % (2**8)
        s //= (2**8)
    return bytes(result)

def scalar_unpack(data):
    if(len(data)!=32):
        raise Error("invalid encoding of scalar: length is not 32,"
                f" but {len(data)}.")

    s = 0
    for i in range(31):
        s += data[i]*pow(2, 8*i, l)
        s %= l
    # ignore first three bits
    s += (data[31]&0x1f)*pow(2,8*31,l)
    s %= l

    return s

def scalar_random():
    return random.randint(0,l-1)

def scalar_inv(s):
    s %= l
    if s==0:
        raise DivisionByZero()
    return pow(s,l-2,l) # (Fermat's little theorem)

def fe_is_positive(f):
    return (f%q)%2==0

def fe_inv(f):
    f%=q
    if f==0:
        raise DivisionByZero()
    return pow(f,q-2,q) # (Fermat's little theorem)

# returns a positive square root of f
def fe_sqrt(f):
    g = fe_sqrt_any(f)
    if fe_is_positive(g):
        return g
    return q-g

# TODO: add ref to Legendre
def fe_sqrt_any(f):
    f = f % q
    g = pow(f,(q+3)//8,q)
    gg = g**2%q
    if gg==f:
        return g
    elif q-gg==f:
        return (pow(2,(q-1)//4,q)*g)%q
    raise NotASquare()

def fe_is_sqrt(f):
    try:
        fe_sqrt_any(f)
    except NotASquare as e:
        return False
    return True

def fe_random():
    return random.randint(0,q-1)

def fe_pack(f):
    result = 32*[0]
    f %= q
    for i in range(32):
        result[i] = f % (2**8)
        f //= (2**8)
    return bytes(result)

def fe_unpack(data):
    assert(len(data)==32)
    f = 0
    for i in range(31):
        f += data[i]*(2**(8*i))
    # ignore final bit
    f += (0b01111111 & data[31])*(2**(8*31))
    return f

i = fe_sqrt(-1)
magic = fe_inv(-fe_sqrt_any(-d-1))
# magic is the _negative_ square root of -121666

# ReferencePoint on the twisted edwards curve
#   y^2 - x^2 = 1 + dx^2y^2
class ReferencePoint:
    # TODO: correct this method to yield a proper representative
    @staticmethod
    def from_y_and_sign(y,x_is_positive,check=True):
        try:
            x = fe_sqrt((y**2-1)*fe_inv(d*y**2+1))
        except NotASquare:
            raise NotOnCurve()
        if x_is_positive!=fe_is_positive(x):
            x = -x%q
        return ReferencePoint(x,y, check=check)

    @staticmethod
    def from_s(s):
        if not fe_is_positive(s):
            raise SIsNegative()

        try:
            x = fe_sqrt( 4*s**2 * fe_inv(-d*(1-s**2)**2 - (1+s**2)**2) )
        except NotASquare:
            raise Odd()
        y = (1-s**2)*fe_inv(1+s**2)

        if not fe_is_positive(x*y):
            raise InvalidRepresentative("x*y is negative")
        if y%q==0:
            raise InvalidRepresentative("y=0")

        return ReferencePoint(x,y,check=False)

    @staticmethod
    def unpack(data):
        if len(data)!=32:
            raise InvalidEncoding(f"length={len(data)} != 32")
        elif data[31]//128!=0: # the C library ignores this last bit
            raise InvalidEncoding("last bit is not 0")

        return ReferencePoint.from_s(fe_unpack(data))

    @staticmethod
    def hash(data):
        return ReferencePoint.elligator2(fe_unpack(common.sha256(data)))

    @staticmethod
    def random():
        while True:
            try:
                y = fe_random()
                x_is_positive = True #(random.randint(0,1)==1)
                half = ReferencePoint.from_y_and_sign(y,x_is_positive, check=False)
            except InvalidPoint:
                continue
            return half + half

    def __init__(self,x,y, check=True):
        self.x = x % q
        self.y = y % q
        if check:
            self.check()

    def check(self):
        if (self.y**2-self.x**2)%q != (1+d*self.x**2*self.y**2)%q:
            raise NotOnCurve()
        if not (self * (4*l)).is_exactly(ReferencePoint.Zero):
            raise Odd()

    def Copy(self):
        return ReferencePoint(self.x, self.y, check=False)

    def point(self):
        return Point.from_refpoint(self)

    def normalized(self):
        x = self.x
        y = self.y

        if not fe_is_positive(x*y) or y==0:
            x,y = (y*i)%q, (x*i)%q
        if (y+1) % q == 0:  # i.e. y = -1 mod q
            y=1
        if not fe_is_positive(x):
            x,y = q-x,q-y

        return (x,y)

    def normalize(self):
        self.x, self.y = self.normalized()

    def s(self):
        x,y = self.normalized()
        try:
            return fe_sqrt( (1-y)*fe_inv(1+y) )
        except NotASquare:
            assert(False) # should not happen if the ReferencePoint is even

    def pack(self):
        return fe_pack(self.s())

    def __add__(self, other):
        xden = fe_inv(1+d*self.x*other.x*self.y*other.y)
        yden = fe_inv(1-d*self.x*other.x*self.y*other.y)

        return ReferencePoint( (self.x*other.y + other.x*self.y)*xden,
                (self.y*other.y+self.x*other.x)*yden, check=False )

    def __eq__(self, other):
        if not isinstance(other, ReferencePoint):
            return NotImplemented
        return (self.x*other.y - other.x*self.y)%q==0 or \
                (self.x*other.x - self.y*other.y)%q==0

    def equivalence_class(self):
        # doesn't include the odd points
        x,y = self.x,self.y
        yield self
        yield ReferencePoint(-x,-y,check=False)
        yield ReferencePoint(i*y,i*x, check=False)
        yield ReferencePoint(-i*y,-i*x, check=False)

    def is_exactly(self,other):
        if not isinstance(other, ReferencePoint):
            return NotImplemented
        return (self.x==other.x) and (self.y==other.y)

    def __ne__(self, other):
        return not self.__eq__(other)

    def __sub__(self, other):
        if isinstance(other,ReferencePoint):
            return self + -other
        return NotImplemented

    def double(self):
        return self+self

    def double_in_place(self):
        double = self+self
        self.x = double.x
        self.y = double.y

    def __neg__(self):
        return ReferencePoint(-self.x, self.y, check=False)

    def __mul__(self, other):
        return double_and_add_multiplication(self, other, ReferencePoint.Zero)

    def __repr__(self):
        return "ReferencePoint(%s,%s)" % (self.x, self.y)

    # The curve ed25519 is equivalent to the montgomery curve
    #      v**2 + = u**3 + 486662 u**2 + u
    # known as curve25519.  The following methods provide the
    # translation.
    def montgomery(self):
        x,y = self.normalized()
        u = (1-y)*fe_inv(1+y)
        v = u*fe_inv(x)*fe_sqrt(-486664) if x!=0 else 0
        return (u%q,v%q)

    @staticmethod
    def from_montgomery(u, v):
        x = (fe_sqrt(-486664)*u*fe_inv(v))%q if v!=0 else 0
        y = ((1-u)*fe_inv(1+u))%q
        return ReferencePoint(x,y)

    def _jacobi_quartic_slow(self):
        x,y = self.x, self.y
        if x==0:
            # y is now either +1 or -1
            if y==1:
                return JacobiQuartic(0,1,check=False)
            elif y==q-1:
                return JacobiQuartic(1,1,0,check=False)
            else:
                assert(False)
            return JacobiQuartic(0,y,check=False)
        s = fe_sqrt( (1-y)*fe_inv(1+y) ) # y won't be -1 here
        t = (2*s*magic * fe_inv(x))%q
        return JacobiQuartic(s,t, check=False)

    def jacobi_quartic(self):
        x,y = self.x, self.y
        if x==0:
            # y is now either +1 or -1
            if y==1:
                return JacobiQuartic(0,1,check=False)
            elif y==q-1:
                return JacobiQuartic(1,1,0,check=False)
            else:
                assert(False)

        z = ( fe_sqrt(1-pow(y,2,q))*x ) % q
        sz = ( (1-y)*x ) % q
        tz2 = ( 2*z*(1-y)*magic ) % q

        return JacobiQuartic(sz, tz2, z, check=False)

    def t(self):
        x,y = self.normalized()
        return (2*self.s()*magic*fe_inv(x)) % q

    @staticmethod
    def elligator2(x):
        return JacobiQuartic.elligator2(x).refpoint()

    def elligator2_inv(self):
        return self.point().elligator2_inv()

    @staticmethod
    def lizard(payload, N=16):
        return Point.lizard(payload,N).refpoint()

    def lizard_inv(self, N=16):
        return self.point().lizard_inv(N)

# The curve ed25519 is also equivalent to the jacobi quartic
#     s^4 + 2( 1-2d/(d+1) )s^2 + 1 = t^2
# which becomes
#     (sz)^4 + 2( 1-2d/(d+1) )(sz)^2z^2 + z^4 = (tz^2)^2
# in projective coordinates.
a_quartic = ( 1- (2*d)*fe_inv(d+1) ) % q

class JacobiQuartic:
    def __init__(self, sz, tz2, z=1, check=True):
        self._sz = sz % q
        self._tz2 = tz2 % q
        self._z = z % q

        if check: self.check()

    def Copy(self):
        return JacobiQuartic(self._sz, self._tz2, self._z, check=False)

    def check(self):
        sz,tz2,z = self._sz,self._tz2,self._z
        if ( pow(sz,4,q) + 2*a_quartic*pow(sz,2,q)*pow(z,2,q)
                + pow(z,4,q) )%q != pow(tz2,2,q):
            raise InvalidPoint()

    def st(self):
        """Returns (s,t)-coordinates for this point when they exist. """
        """Otherwise throws an Infinite exception."""
        if self._z==0:
            raise Infinite()
        zinv = fe_inv(self._z)
        return ((zinv*self._sz)%q, (zinv**2*self._tz2)%q)

    @staticmethod
    def from_s(s,positive_t=True):
        a = (pow(s,4,q) + 2*a_quartic*pow(s,2,q)+1)%q
        t = fe_sqrt(a)
        if not positive_t:
            t = q - t
        return JacobiQuartic(s,t,check=False)

    @staticmethod
    def random():
        """returns a random non-infinite point on the jacobi quartic"""
        positive_t = (random.getrandbits(1)==0)
        while True:
            try:
                # has 50% chance to succeed
                return JacobiQuartic.from_s(fe_random(),positive_t)
            except NotASquare:
                continue

    def random_infinite():
        """returns a random infinite point on the jacobi quartic"""
        if random.getrandbits(1)==0:
            return JacobiQuartic(1,1,0,check=False)
        else:
            return JacobiQuartic(1,-1,0,check=False)

    def re_z(self):
        """Scales the projective point by a random scalar z """
        """(which doesn't essentially change the point)."""
        w = fe_random()
        return JacobiQuartic(self._sz*w, self._tz2*w*w, self._z*w, check=False)

    def point(self):
        sz,tz2,z = self._sz,self._tz2,self._z
        _2szzmagic = (2*sz*z*magic)%q
        z2 = pow(z,2,q)
        sz_2 = pow(sz,2,q)

        X = _2szzmagic * ( z2 + sz_2 )
        Y = tz2 * ( z2 - sz_2 )
        Z = tz2 * ( z2 + sz_2 )
        T = _2szzmagic * (z2 - sz_2 )

        return Point(X,Y,Z,T)

    def refpoint(self):
        sz,tz2,z = self._sz,self._tz2,self._z
        x = (2*sz*z*magic * fe_inv(tz2)) % q  # tz^2 will never be 0
        y = ((z*z - sz*sz) * fe_inv(z*z + sz*sz)) % q
        #                       \_ z^2 and -(sz)^2 will never be equal
        return ReferencePoint(x, y, check=False)

    def _refpoint_st(self):
        s,t = self.st()
        x = (2*s*magic * fe_inv(t)) % q  # t will never be 0
        y = ((1 - s*s) * fe_inv(1 + s*s)) % q
        #                       \_ 1 and -s^2 will never be equal
        return ReferencePoint(x, y, check=False)

    def is_exactly(self, other):
        if self._z == 0:
            if other._z != 0:
                return False
            return (self._sz**2 * other._tz2
                    - other._sz**2 * self._tz2) % q == 0
        return ( (self._sz * other._z - other._sz * self._z)%q==0 ) \
                and ( (self._tz2 * other._z**2 - other._tz2 * self._z**2)%q==0 )

    def _is_exactly_st(self, other):
        if self._z == 0:
            if other._z != 0:
                return False
            return (self._sz**2 * other._tz2
                    - other._sz**2 * self._tz2) % q == 0
        s1,t1 = self.st()
        s2,t2 = other.st()
        return (s1==s2) and (t1==t2)

    def dual(self):
        return JacobiQuartic(-self._sz, -self._tz2, self._z, check=False)

    def is_exactly_or_dual(self, other):
        return self.is_exactly(other) or self.is_exactly(other.dual())

    def equivalence_class(self):
        for a in self._equivalence_class_part():
            yield a
        for a in (self+JacobiQuartic(1, fe_sqrt(486664), check=False))\
                ._equivalence_class_part():
            yield a

    def _equivalence_class_part(self):
        sz,tz2,z = self._sz,self._tz2,self._z
        yield self.Copy()
        yield JacobiQuartic( -sz, -tz2, z, check=False)
        yield JacobiQuartic( z, -tz2, sz, check=False)
        yield JacobiQuartic( -z, tz2, sz, check=False)

    def __eq__(self, other):
        for a in self.equivalence_class():
            if a.is_exactly(other):
                return True
        return False

    def __repr__(self):
        return f"JacobiQuartic({self._sz}, {self._tz2}, {self._z})"

    def __add__(self, other):
        sz_1, tz2_1, z_1 = self._sz, self._tz2, self._z
        sz_2, tz2_2, z_2 = other._sz, other._tz2, other._z

        z = (pow(z_1,2,q)*pow(z_2,2,q) - pow(sz_1,2,q)*pow(sz_2,2,q) )%q
        s = ( sz_1*z_1*tz2_2 + sz_2*z_2*tz2_1 )%q
        t = ( (tz2_1*tz2_2 + 2*a_quartic*z_1*z_2*sz_1*sz_2)
            * ( pow(z_1,2,q)*pow(z_2,2,q) + pow(sz_1,2,q)*pow(sz_2,2,q) )
            + 2*z_1*z_2*sz_1*sz_2
                * ( pow(sz_1,2,q)*pow(z_2,2,q) + pow(sz_2,2,q)*pow(z_1,2,q) )
            )%q

        return JacobiQuartic(s,t,z,check=False)

    def _add_st(self, other):
        s1,t1 = self.st()
        s2,t2 = other.st()

        den = fe_inv( 1 - pow(s1,2,q)*pow(s2,2,q) )

        s3 = ( (s1*t2 + t1*s2) * den ) % q
        t3 = ( ( (t1*t2+2*a_quartic*s1*s2)*(1+ s1*s1*s2*s2) \
                + 2*s1*s2*(s1*s1+s2*s2) ) * den*den ) % q

        return JacobiQuartic(s3,t3,check=False)

    def __neg__(self):
        return JacobiQuartic(-self._sz,self._tz2,self._z,check=False)

    def __sub__(self,other):
        return self+(-other)

    @staticmethod
    def Zero():
        return JacobiQuartic(0,1,check=False)

    @staticmethod
    def elligator2(x):
        """Provides an injection from the positive scalars below q """
        """to the points of the JacobiQuartic."""
        """Further, elligator(x)=elligator(-x)"""
        r = (i * x * x) % q
        if (d+r)%q==0:
            return JacobiQuartic(0,1,check=False)
        den = fe_inv(((d * r + 1) * (-d - r)) % q)
        n1 = -(r + 1) * (-1 + d) * (d + 1) * den
        n2 = r * n1
        try:
            s, t = fe_sqrt(n1), (-(r-1)*(-1 + d)**2 * den - 1) %q
            # s will be positive
        except NotASquare:
            s, t = -fe_sqrt(n2) % q, (r*(r-1)*(-1 + d)**2 * den - 1) %q
            # s is negative
        return JacobiQuartic(s,t,check=False)

    def _elligator2_inv_slow(self):
        """Returns positive x such that self=elligator2(x)=elligator2(-x)
        if it exists; otherwise throws NoPreimage."""
        try:
            s,t = self.st()
        except Infinite:
            raise NoPreimage()

        if s==0:
            # now either t=1 or t=-1
            if t==1:
                return fe_sqrt(i*d)
            else:
                assert(q-t==1)
                return 0

        # b will be +- (r-1)/(r+1) depending on the sign of s
        b = ( ((t+1)*(d+1)) * fe_inv(s*s*(d-1)) ) % q
        if not fe_is_positive(s):
            b = q - b

        r = ( -(b+1) * fe_inv((b-1)%q) ) % q # b won't be 1

        try:
            return fe_sqrt(-i * r)
        except NotASquare:
            raise NoPreimage()

    def elligator2_inv(self, s_is_positive=None):
        """Returns positive x such that self=elligator2(x)=elligator2(-x)
        if it exists; otherwise throws NoPreimage."""
        sz,tz2,z = self._sz, self._tz2, self._z
        z2 = pow(z,2,q)

        if z==0:
            raise NoPreimage()
        if sz==0:
            if tz2==z2: # that is, t=1
                return fe_sqrt(i*d)
            else:
                assert( (tz2+z2)%q==0 ) # that is, t=-1
                return 0

        sz_2 = pow(sz,2,q)
        a = ( tz2+z2 ) * (d+1)*fe_inv(d-1)
        a2 = pow(a,2,q)
        sz_4 = pow(sz,4,q)
        try:
            y =  fe_inv(fe_sqrt( i* (sz_4 - a2)))
        except NotASquare:
            raise NoPreimage()

        if s_is_positive==None:
            s = ( fe_inv(z)*sz ) % q
            s_is_positive = fe_is_positive(s)

        if s_is_positive:
            x = ( y * (a+sz_2) ) % q
        else:
            x = ( y * (a-sz_2) ) % q

        if fe_is_positive(x):
            return x
        else:
            return q-x

class Error(Exception):
    pass

class NoPreimage(Error):
    pass

class DivisionByZero(Error):
    """raised by fe_inv and scalar_inv"""
    pass

class NotASquare(Error):
    pass

class Invalid(Error):
    pass

class Infinite(Error):
    pass

class InvalidPoint(Invalid):
    pass

class NotOnCurve(InvalidPoint):
    pass

class Odd(InvalidPoint):
    pass

class InvalidEncoding(Invalid):
    pass

class InvalidRepresentative(InvalidEncoding):
    pass

class SIsNegative(InvalidEncoding):
    pass

# the base ReferencePoint
ReferencePoint.Zero = ReferencePoint(0,1, check=False)
ReferencePoint.B = ReferencePoint.from_y_and_sign(
        4*fe_inv(5), True, check=False)
ReferencePoint.B.normalize()

# faster implementation
class Point:
    @staticmethod
    def from_refpoint(a, Z=1):
        return Point(X=a.x*Z, Y=a.y*Z, Z=Z, T=a.x*a.y*Z)

    @staticmethod
    def random():
        return Point.from_refpoint(ReferencePoint.random(),Z=fe_random())

    @staticmethod
    def hash(data):
        return Point.from_refpoint(ReferencePoint.hash(data))

    def __init__(self, X, Y, Z, T):
        # TODO: what should we make of the case that Z=0?
        self.X = X % q
        self.Y = Y % q
        self.Z = Z % q
        self.T = T % q

    def Copy(self):
        return Point(X=self.X, Y=self.Y, Z=self.Z, T=self.T)

    def __repr__(self):
        return f"Point({self.X}, {self.Y}, {self.Z}, {self.T})"

    def __iadd__(self, other):
        if not isinstance(other, Point):
            return NotImplemented

        A = (self.X * other.X)%q
        B = (self.Y * other.Y)%q
        C = (d * (self.T * other.T)%q)%q
        D = (self.Z * other.Z)%q
        E = ( (self.X + self.Y)%q ) * ( (other.X + other.Y)%q )
        E = (E-A-B)%q
        F = (D-C)%q
        G = (D+C)%q
        H = (B+A)%q

        self.X=E*F
        self.Y=G*H
        self.Z=F*G
        self.T=E*H
        return self

    def __add__(self, other):
        result = self.Copy()
        result.__iadd__(other)
        return result

    def __neg__(self):
        return Point(X=-self.X,Y=self.Y,T=-self.T,Z=self.Z)

    def __sub__(self, other):
        return self + -other

    def double_in_place(self):
        A = (self.X * self.X)%q
        B = (self.Y * self.Y)%q
        C = (2 * self.Z * self.Z)%q
        D = -A
        E = (self.X + self.Y)%q
        E = (E*E)%q
        E = (E - A - B)%q
        G = (D+B)%q
        F = (G-C)%q
        H = (D-B)%q

        self.X=E*F
        self.Y=G*H
        self.T=E*H
        self.Z=F*G

        return self

    def double(self):
        result = self.Copy()
        result.double_in_place()
        return result

    def __mul__(self, other):
        return double_and_add_multiplication(self, other, Point.Zero())

    def equivalence_class(self):
        # doesn't include the odd points
        X,Y,Z,T = self.X,self.Y,self.Z,self.T
        yield self.Copy()
        yield Point(X,Y,-Z,T)
        yield Point(Y,X,i*Z,-T)
        yield Point(Y,X,-i*Z,-T)

    def is_exactly(self, other):
        return ( self.X*other.Z - other.X*self.Z )%q==0 and \
                ( self.Y*other.Z - other.Y*self.Z )%q==0

    def __eq__(self, other):
        if not isinstance(other, Point):
            return NotImplemented
        return (self.X*other.Y - other.X*self.Y)%q==0 or \
                (self.X*other.X - self.Y*other.Y)%q==0

    def is_zero(self):
        return self.X==0 or self.Y==0

    def refpoint(self):
        zinv = fe_inv(self.Z)
        return ReferencePoint(self.X * zinv, self.Y * zinv,check=False)

    @staticmethod
    def unpack(data):
        return Point.from_refpoint(ReferencePoint.unpack(data))

    def pack(self):
        return self.refpoint().pack()

    @staticmethod
    def B_times(scalar):
        scalar %= l
        result = Point.Zero()
        i = 0

        while(scalar>0):
            if scalar&1==1:
                result += Point.B_times_two_to_the_power[i]

            scalar >>= 1
            i += 1

        return result

    # since B is passed by-reference, and "+=" is implemented in place,
    # code like
    #
    #   result = self.Point.B
    #   result += result
    #
    # will change the value of B, which is undesirable.
    @staticmethod
    def B():
        return Point._B.Copy()

    @staticmethod
    def Zero():
        return Point._Zero.Copy()

    def jacobi_quartic(self):
        X,Y,Z = self.X, self.Y, self.Z
        if X==0:
            # Y/Z is now either +1 or -1
            if Y==Z:
                return JacobiQuartic(0,1,check=False)
            elif Y==q-Z:
                return JacobiQuartic(1,1,0,check=False)
            else:
                assert(False)

        z = ( fe_sqrt(pow(Z,2,q)-pow(Y,2,q))*X ) % q
        sz = ( (Z-Y)*X ) % q
        tz2 = ( 2*z*Z*(Z-Y)*magic ) % q

        return JacobiQuartic(sz, tz2, z, # check=False
                )

    def four_finite_jacobi_quartics(self):
        """computes the (up to dual) four jacobi quartics associated"""
        """ to this point"""
        X,Y,Z = self.X, self.Y, self.Z
        if X==0 or Y==0:
            yield JacobiQuartic(0,1,check=False)
            yield JacobiQuartic(1,2*magic*i, check=False)
            yield JacobiQuartic(-1,2*magic*i, check=False)
            return

        gamma = fe_inv(fe_sqrt( pow(Y,4,q) * pow(X,2,q) \
                    * (pow(Z,2,q)-pow(Y,2,q))))

        den = gamma*pow(Y,2,q)
        s_X_inv = ( den * (Z-Y) ) % q
        s = (s_X_inv * X) % q
        t = (2*magic*s_X_inv*Z) % q
        sp_Xp_inv = ( den * (Z+Y) ) % q
        sp = (- sp_Xp_inv * X) % q
        tp = (2*magic*sp_Xp_inv*Z) % q

        yield JacobiQuartic(s, t, check=False)
        yield JacobiQuartic(sp, tp, check=False)

        den = fe_inv(fe_sqrt(1+d)) * (pow(Y,2,q)-pow(Z,2,q)) * gamma
        X,Y,Z = Y,X,(i*Z)%q
        s_X_inv = ( den * (Z-Y) ) % q
        s = (s_X_inv * X) % q
        t = (2*magic*s_X_inv*Z) % q
        sp_Xp_inv = ( den * (Z+Y) ) % q
        sp = (- sp_Xp_inv * X) % q
        tp = (2*magic*sp_Xp_inv*Z) % q

        yield JacobiQuartic(s, t, check=False)
        yield JacobiQuartic(sp, tp, check=False)

    @staticmethod
    def elligator2(x):
        return JacobiQuartic.elligator2(x).point()

    def elligator2_inv(self):
        for jc in self.four_finite_jacobi_quartics():
            assert(jc._z==1)
            s_is_positive = fe_is_positive( jc._sz )
            try:
                yield jc.elligator2_inv(s_is_positive)
            except NoPreimage:
                pass
            try:
                yield jc.dual().elligator2_inv(not s_is_positive)
            except NoPreimage:
                pass

    def elligator2_inv_old(self):
        """returns all positive x for which elligator2(x)=elligator2(-x)=self"""
        for b in self.equivalence_class():
            jc = b.jacobi_quartic()
            if jc._z==0: # the result of elligator2 is always finite
                continue
            s_is_positive = fe_is_positive( fe_inv(jc._z)*jc._sz )
            try:
                yield jc.elligator2_inv(s_is_positive)
            except NoPreimage:
                pass
            try:
                yield jc.dual().elligator2_inv(not s_is_positive)
            except NoPreimage:
                pass

    @staticmethod
    def lizard(payload, N=16):
        """provides what is in all probability an injection from """
        """the bytes of length 16 to points on the edwards curve"""
        assert(len(payload)==N)
        assert( N<=30 and N%2==0 )
        return Point.elligator2(fe_unpack(
                lizard_without_elligator(payload, N=N)))

    def lizard_inv(self, N=16):
        assert( N<=30 and N%2==0 )
        for x in self.elligator2_inv():
            data = fe_pack(x)
            payload = data[ 16-N//2 : 16+N//2 ]
            data_hash = bytearray(common.sha256(payload))

            data_hash[0]  &= 0b11111110
            data_hash[31] &= 0b00111111

            if data[:16-N//2]==data_hash[:16-N//2] \
                    and data[16+N//2:]==data_hash[16+N//2:]:
                return payload
        raise NoPreimage()

def lizard_without_elligator(payload, N=16):
    assert( N<=30 and N%2==0 )
    assert(len(payload)==N)
    data = bytearray(common.sha256(payload))
    data[ 16-N//2 : 16+N//2 ] = payload
    data[0] &= 0b11111110
    data[31] &= 0b00111111
    return bytes(data)

Point._Zero = Point.from_refpoint(ReferencePoint.Zero)
Point._B = Point.from_refpoint(ReferencePoint.B)

def double_and_add_multiplication(self, other, zero):
    if not isinstance(other, int):
        return NotImplemented
    other %= 8*l
    result = zero
    power_of_two_times_self = self.Copy()

    while(other>0):
        if other&1==1:
            result += power_of_two_times_self

        power_of_two_times_self.double_in_place()
        other >>= 1

    return result

# TODO: hardcode these values
Point.B_times_two_to_the_power = []
_tmp = Point.B()
for _some_name_not_i in range(253):
    Point.B_times_two_to_the_power.append(_tmp)
    _tmp = _tmp.double()
del _tmp


import dateutil
import dateutil.parser
import yaml
import discord
from discord.ext import commands
from .service import WeatherService

class Weather(commands.Cog):
    """ Weather commands """

    def __init__(self, bot):
        self.bot = bot
        self.weather = WeatherService()

    @commands.command(description='Give me a location, get the weather')
    async def weather(self, ctx, *, location : str):
        channel = ctx.message.channel
        weather_embed = None
        async with channel.typing():
            weather_embed = self.get_weather(location)
        if weather_embed:
            await channel.send(embed=weather_embed)

    def get_weather(self, location):
        weather = self.weather.get_weather(location)

        currently_field = '{} {}.'.format(weather.current_icon, weather.current_summary)
        if weather.hourly_summary:
            currently_field += ' {}'.format(weather.hourly_summary)

        if weather.daily_summary:
            currently_field += ' {}'.format(weather.daily_summary)

        temp_field = '{:,g}°C ({:,g}°F)'.format(weather.current_temp.c, weather.current_temp.f)

        temp_feels_field = '{:,g}°C ({:,g}°F)'.format(weather.feels_like.c, weather.feels_like.f)

        temp_high_low_field = '{:,g}°C ({:,g}°F)/{:,g}°C ({:,g}°F)'.format(
                weather.daily_temp.high.c, weather.daily_temp.high.f,
                weather.daily_temp.low.c, weather.daily_temp.low.f)

        humidity_field = '{:,g}%'.format(weather.humidity)

        precip_field = '{:,g}%'.format(weather.precip)
        wind_field = '{} {:,g} kph ({:,g} freedom units)'.format(
                weather.wind.bearing, weather.wind.kph, weather.wind.mph)

        utc_time = dateutil.parser.parse(weather.utc_time)
        utc_formatted = utc_time.strftime('%Y-%m-%d %H:%M UTC')
        local_time = utc_time.astimezone(dateutil.tz.gettz(weather.local_timezone))
        local_formatted = local_time.strftime('%Y-%m-%d %H:%M {}'.format(weather.local_timezone))

        time_info = '{} \u2022 Local: {}'.format(utc_formatted, local_formatted)
        darksky_attribution = '[Powered by Dark Sky](https://darksky.net/poweredby/)'
        description = '{}\n{}'.format(time_info, darksky_attribution)

        weather_embed = discord.Embed.from_dict({
            "title": weather.location,
            "description": description,
            "timestamp": weather.utc_time,
            "fields": [
                {
                    "name": '**Currently**',
                    "value": currently_field,
                    "inline": True
                },
                {
                    "name": '**Temp**',
                    "value": temp_field,
                    "inline": True
                },
                {
                    "name": '**Feels Like**',
                    "value": temp_feels_field,
                    "inline": True
                },
                {
                    "name": '**High/Low**',
                    "value": temp_high_low_field,
                    "inline": True
                },
                {
                    "name": '**Humidity**',
                    "value": humidity_field,
                    "inline": True
                },
                {
                    "name": '**Precipitation**',
                    "value": precip_field,
                    "inline": True
                },
                {
                    "name": '**Wind**',
                    "value": wind_field,
                    "inline": True
                },
                ],
            })

        alert_text = ''
        for alert in weather.alerts:
            alert_text = alert_text + '__**{}**__: {}: {}\n'.format(
                    alert.severity, alert.title, alert.uri)

        if len(alert_text) > 0:
            weather_embed.add_field(
                name='**Alerts**',
                value=alert_text,
                inline=True
                )

        return weather_embed


import pygame
from LevelParts.Level import *
"""

Do the whole program

"""

# файл запуска программы
pygame.init()
level_screen = pygame.display.set_mode((LevelXSize, LevelYSize))
pygame.display.update()
clock = pygame.time.Clock()
finished = False
flag = False
Test_Level = Level(map_drawer)

while not finished:
    Test_Level.update(level_screen)
    pygame.display.update()
    for event in pygame.event.get():
        Test_Level.game_event(event)
        if event.type == pygame.QUIT:
            finished = True
pygame.quit()

#Test11
#Test1
#Еуые228


# 保存圖片驗證碼的有效期
IMAGR_CODE_REDIS_EXPRIES = 180
# 登陆错误尝试次数
LOGIN_ERROR_MAX_TIMES = 5

# 登入錯誤限制的時間單位 單位:秒
LOGIN_ERROR_FORBID_TIME = 600

# 城區信息的緩存時間, 單位: 秒
AREA_INFO_REDIS_CACHE_EXPIRES =7200

# 分頁顯示
COMMENT_PER_ITEM=20

#  餐廳頁面的緩存時間，單位:秒
RESTAURANT_LIST_PAGE = 3600


from glasswall.content_management import switches
from glasswall.content_management.config_elements.config_element import ConfigElement

class gifConfig(ConfigElement):
    """ A gifConfig ConfigElement.

    Args:
        default (str): The default action: allow, disallow, or sanitise.

    Key word arguments can be specified to change individual switch values:
    gifConfig(default="allow", embedded_images="sanitise")
    """

    def __init__(self, default: str = "sanitise", attributes: dict = {}, **kwargs):
        self.name = self.__class__.__name__
        self.default = default
        self.attributes = attributes
        self.switches_module = switches.gif
        self.default_switches = [
            self.switches_module.metadata(value=default),
        ]

        super().__init__(
            name=self.name,
            default=self.default,
            attributes=self.attributes,
            switches_module=self.switches_module,
            default_switches=self.default_switches,
            config=kwargs
        )


class Member():
    def __init__(self, full_name):
        self.full_name = full_name

    def introduce(self):
        print(f"Hi, my name is {self.full_name.split()[0]}")

class Student(Member):
    def __init__(self, full_name, reason):
        Member.__init__(self, full_name)
        self.reason = reason

class Instructor(Member):

    def __init__(self, full_name, bio, skills=None):
        Member.__init__(self, full_name)
        self.bio = bio
        # self.skills = []
        self.skills = skills
        if self.skills == None:
            self.skills = []

    def add_skill(self, new_skill):
        self.skills.append(new_skill)

class Workshop():
    def __init__(self, date, subject):
        self.date = date
        self.subject = subject
        self.instructors = []
        self.student_roster = []

    def add_participant(self, participant):
        if participant.__class__ == Student:
            self.student_roster.append(participant)
        elif participant.__class__ == Instructor:
            self.instructors.append(participant)

    def print_details(self):
        print('Students')
        for i, s in enumerate(self.student_roster):
            print(f"{i+1}. {s.full_name} - {s.reason}")
        print('Instructors')
        for i, t in enumerate(self.instructors):
            print(f"{i+1}. {t.full_name} - {', '.join(t.skills)}")
            print(f"    {t.bio}")

workshop = Workshop("12/03/2014", "Shutl")

jane = Student(
    "Jane Doe", "I am trying to learn programming and need some help")
lena = Student("Lena Smith", "I am really excited about learning to program!")
vicky = Instructor("Vicky Python", "I want to help people learn coding.")
vicky.add_skill("HTML")
vicky.add_skill("JavaScript")
nicole = Instructor(
    "Nicole McMillan", "I have been programming for 5 years in Python and want to spread the love")
nicole.add_skill("Python")

workshop.add_participant(jane)
workshop.add_participant(lena)
workshop.add_participant(vicky)
workshop.add_participant(nicole)
workshop.print_details()


# Import system modules
import arcpy
from arcpy import env
import numpy as np
from deap import base
from deap import creator
from deap import tools
from deap.tools._hypervolume import pyhv as hv
#import scipy.spatial

from scipy.spatial import cKDTree

import random
import time

def optim(MU, NGEN, path, CXPB, MUTPB, A, B):
   # path = "D:/04_PROJECTS/2001_WIND_OPTIM/WIND_OPTIM_git/intermediate_steps/3_wp/NSGA3_RES/in/B3_FFF+.shp"
    fc = path
    na = arcpy.da.FeatureClassToNumPyArray(fc, ["WT_ID", "ENER_DENS", "prod_MW", "SHAPE@XY"], explode_to_points=True)

    ##here we calculate the expected nearest neighbor distance (in meters) of the scenario
    nBITS = len(na)

    # CXPB  is the probability with which two individuals are crossed
    # MUTPB is the probability for mutating an individual
    #CXPB, MUTPB = 0.8, 0.6
    # MU,NGEN =20, 10
    enertarg = 4300000
    # some parameters to define the random individual

    # total production of energy
    sum_MW = np.sum(na['prod_MW'])

    # the 4.3TWh/y represent the minimal target to reach and app. 4.6Twh is the upper bandwidth
    low_targ = enertarg
    up_targ = enertarg * 1.07

    # the function to determine the initial random population which might reach the energy target bandwidth
    def initial_indi():
        # relative to the total energy production to build the initial vector
        bound_up = (1.0 * up_targ / sum_MW)
        bound_low = (1.0 * low_targ / sum_MW)
        x3 = random.uniform(bound_low, bound_up)
        return np.random.choice([1, 0], size=(nBITS,), p=[x3, 1 - x3])

    def initial_ind2():
        N = np.array(A)
        return N

    def initial_ind3():
        M = np.array(B)
        return M

    # some lists for the evaluation function
    enerd = list(na['ENER_DENS'])
    prod = list(na['prod_MW'])
    id = np.array(na['WT_ID'])
    _xy = list(na['SHAPE@XY'])

    # the evaluation function, taking the individual vector as input

    def evaluate(individual):
        individual = individual[0]
        prod_MWsel = sum(x * y for x, y in zip(prod, individual))
        #check if the total production is witin boundaries, if not return a penalty vector
        if up_targ >= prod_MWsel >= low_targ:
            # goal 1
            mean_enerdsel = sum(x * y for x, y in zip(enerd, individual)) / sum(individual)
            # goal 2
            count_WTsel = sum(individual)
            # goal 3 zip the individual vector to the _xy coordinates
            subset = np.column_stack((_xy,individual))
            #subset the data that only the 1 remains
            subset = subset[subset[:, 2] == 1]
            subset = np.delete(subset, 2, 1)
            tree = cKDTree(subset)
            dists = tree.query(subset, 2)
            nn_dist = dists[0][:, 1]
            rE = 1 / (2 * math.sqrt(1.0 * len(subset) / 41290790000))
            rA= np.mean(nn_dist)
            clus = rA/rE
            res = (clus, count_WTsel, mean_enerdsel)
            ## delete the feature tmp since otherwise it will not work in a loop
            arcpy.Delete_management("tmp")
            arcpy.Delete_management("subset")
        else:
            res = (10e20, 10e20, 0)
        return res

    #def feasible(individual):
        individual = individual[0]
        prod_MWsel = sum(x * y for x, y in zip(prod, individual))
        if (prod_MWsel <= up_targ and prod_MWsel >= low_targ):
            return True
        return False

    ### setup NSGA3 with deap (minimize the first two goals returned by the evaluate function and maximize the third one)
    creator.create("FitnessMulti", base.Fitness, weights=(-1.0, -1.0, 1.0))
    creator.create("Individual", list, fitness=creator.FitnessMulti)
    ref_points = tools.uniform_reference_points(nobj=3, p=12)
    ##setup the optim toolbox I do not understand that totally
    toolbox = base.Toolbox()
    # initial individual and pop
    toolbox.register("initial_indi", initial_indi)
    toolbox.register("individual", tools.initRepeat, creator.Individual, toolbox.initial_indi, n=1)
    toolbox.register("population", tools.initRepeat, list, toolbox.individual)

    ###and the specific individual A
    toolbox.register("initial_indi2", initial_ind2)
    toolbox.register("individual2", tools.initRepeat, creator.Individual, toolbox.initial_indi2, n=1)
    toolbox.register("population2", tools.initRepeat, list, toolbox.individual2)
    pop2 = toolbox.population2(n=1)

    ###and the specific individual B
    toolbox.register("initial_indi3", initial_ind3)
    toolbox.register("individual3", tools.initRepeat, creator.Individual, toolbox.initial_indi3, n=1)
    toolbox.register("population3", tools.initRepeat, list, toolbox.individual2)
    pop3 = toolbox.population3(n=1)

    # evaluation and constraints
    toolbox.register("evaluate", evaluate)
    ##assign the feasibility of solutions and if not feasible a large number for the minimization tasks and a small number for the maximization task
    #toolbox.decorate("evaluate", tools.DeltaPenalty(feasible, (10e20, 10e20, 0)))
    # mate, mutate and select to perform crossover
    toolbox.register("mate", tools.cxTwoPoint)
    toolbox.register("mutate", tools.mutFlipBit, indpb=0.05)
    toolbox.register("select", tools.selNSGA3, ref_points=ref_points)

    ### initialize pareto front
    pareto = tools.ParetoFront(similar=np.array_equal)
    ### initialize population
    pop = toolbox.population(n=MU)
    #pick a random number where to insert the vector containing the best producing WT into the population
    pop[random.randrange(0,MU,1)] = pop2[0]
   #and insert the best energydens accordingly
    pop[random.randrange(0, MU, 1)] = pop3[0]

    first_stats = tools.Statistics(key=lambda ind: ind.fitness.values[0])
    second_stats = tools.Statistics(key=lambda ind: ind.fitness.values[1])
    third_stats = tools.Statistics(key=lambda ind: ind.fitness.values[2])

    first_stats.register("min_clus", np.min, axis=0)
    second_stats.register("min_WT", np.min, axis=0)
    third_stats.register("max_enerd", np.max, axis=0)

    logbook1 = tools.Logbook()
    logbook2 = tools.Logbook()
    logbook3 = tools.Logbook()
    logbook1.header = "gen", "evals", "TIME", "min_clus"
    logbook2.header = "gen", "evals", "min_WT"
    logbook2.header = "gen", "evals", "max_enerd"

    HV = []
    # Evaluate the initial individuals with an invalid fitness
    print("-- fitness of initial population --")
    start_time = time.time()
    invalid_ind = [ind for ind in pop if not ind.fitness.valid]
    fitnesses = list(toolbox.map(toolbox.evaluate, invalid_ind))

    for ind, fit in zip(invalid_ind, fitnesses):
        ind.fitness.values = fit

    ## Hyper volume of initial fitness (scale the n_WT and change the value of the maximization goal with -1
    fitness_trans = np.array(fitnesses)
    fitness_trans[:, 1] *= 1.0 / nBITS
    fitness_trans[:, 2] *= -1
    hyp = hv.hypervolume(fitness_trans, ref=np.array([1, 1, 1]))
    HV.append(hyp)

    end_time = time.time()
    delt_time = end_time - start_time

    record1 = first_stats.compile(pop)
    logbook1.record(gen=0, evals=len(invalid_ind), TIME=delt_time, **record1)

    record2 = second_stats.compile(pop)
    logbook2.record(gen=0, evals=len(invalid_ind), **record2)

    record3 = third_stats.compile(pop)
    logbook3.record(gen=0, evals=len(invalid_ind), **record3)

    # Begin the evolution with NGEN repetitions
    for gen in range(1, NGEN):
        print("-- Generation %i --" % gen)
        start_time = time.time()
        offspring = toolbox.select(pop, len(pop))
        # Clone the selected individuals
        offspring = list(map(toolbox.clone, offspring))

        # Apply crossover and mutation on the offspring
        for child1, child2 in zip(offspring[::2], offspring[1::2]):
            if random.random() < CXPB:
                toolbox.mate(child1[0], child2[0])
                del child1.fitness.values
                del child2.fitness.values

        for mutant in offspring:
            if random.random() < MUTPB:
                toolbox.mutate(mutant[0])
                del mutant.fitness.values

        # Evaluate the individuals with an invalid fitness
        invalid_ind = [ind for ind in offspring if not ind.fitness.valid]

        fitnesses = list(toolbox.map(toolbox.evaluate, invalid_ind))

        for ind, fit in zip(invalid_ind, fitnesses):
            ind.fitness.values = fit

        fitness_trans = np.array(fitnesses)
        fitness_trans[:, 1] *= 1.0 / nBITS
        fitness_trans[:, 2] *= -1
        ## Hyper volume
        hyp = hv.hypervolume(fitness_trans, ref=np.array([1, 1, 1]))
        HV.append(hyp)
        # select the next generation with NSGA3 from pop and offspring of size MU
        pop = toolbox.select(pop + offspring, MU)
        pareto.update(pop)

        record1 = first_stats.compile(invalid_ind)
        logbook1.record(gen=gen, evals=len(invalid_ind), TIME=delt_time, **record1)

        record2 = second_stats.compile(invalid_ind)
        logbook2.record(gen=gen, evals=len(invalid_ind), **record2)

        record3 = third_stats.compile(invalid_ind)
        logbook3.record(gen=gen, evals=len(invalid_ind), **record3)

        end_time = time.time()
        delt_time = end_time - start_time
        print("--- %s seconds ---" % delt_time)

    # fitness pareto
    fitness_pareto = toolbox.map(toolbox.evaluate, pareto)
    fitness_pareto = np.array(fitness_pareto)
    fitness_pareto = {'CLUS': fitness_pareto[:, 0], 'N_WT': fitness_pareto[:, 1], 'ENERDENS': fitness_pareto[:, 2]}
    # pareto items and robustness
    par_items = np.array(pareto.items)
    par_rob = np.array(1.0 * sum(par_items[1:len(par_items)]) / len(par_items))
    par_rob = par_rob.ravel()
    par_rob_mat = np.column_stack((id, par_rob))
    par_rob_mat = {'WT_ID2': par_rob_mat[:, 0], 'par_rob': par_rob_mat[:, 1]}

    # logbook
    gen = np.array(logbook1.select('gen'))
    TIME = np.array(logbook1.select('TIME'))
    WT = np.array(logbook2.select('min_WT'))
    clus = np.array(logbook1.select('min_clus'))
    enerd = np.array(logbook3.select('max_enerd'))
    logbook = np.column_stack((gen, TIME, WT, clus, enerd))
    logbook = {'GENERATION': logbook[:, 0], 'TIME': logbook[:, 1], 'N_WT': logbook[:, 2], 'CLUS': logbook[:, 3],
               'ENERDENS': logbook[:, 4]}

    return HV, par_rob_mat, fitness_pareto, logbook


# for cluster
# default spot instance
is_spot_instance = True
spot_instance_price = 0.2
# default time to wait for instance
instance_time_wait = 15
instance_tag_separator = "-"
cluster_log_file = "cluster.log"
access_id = ""
access_key = ""
cluster_region = ""
identity_file = ""
key_name = ""
security_group = ""
user = ""
zone = ""
security_group_id = ""
cluster_subnet_id = ""
ami_id = ""

spark_service_cmd = "bash /home/ec2-user/spark/sbin/stop-all.sh && bash /home/ec2-user/spark/sbin/start-all.sh"

normal_ssh_template = "ssh -i %s -o ConnectTimeout=3 -o StrictHostKeyChecking=no "\
                      "-o UserKnownHostsFile=/dev/null %s@%s '%s'"

normal_ssh_template_safe = "ssh -i %s -o ConnectTimeout=3 -o StrictHostKeyChecking=no "\
                           "-o UserKnownHostsFile=/dev/null %s@%s"

sudo_ssh_template = "ssh -i %s -tt -o ConnectTimeout=3 -o StrictHostKeyChecking=no "\
                    "-o UserKnownHostsFile=/dev/null %s@%s '%s'"

host_file = "/etc/hosts"
fstab_file = "/etc/fstab"
slave_file = "/home/ec2-user/spark/conf/slaves"
spark_env_file = "/home/ec2-user/spark/conf/spark-env.sh"
spark_default_file = "/home/ec2-user/spark/conf/spark-defaults.conf"
knowhosts_file = "/home/ec2-user/.ssh/known_hosts"

# if we use spot instance, then the fstab is useless
# since we just use the instance once without reboot
# but if we want to persist a cluster, we should add this
# then the cluster can we stop and start for many times without problem.
fstab_template = '"/dev/xvdc   /media/ephemeral1   auto    defaults,nofail,comment=cloudconfig 0   2"'

# for job server and checker
server_port = 0000
interval_to_check_job = 10 * 60
interval_on_error = 60
checker_log_file = "checker.log"

# for mail configuration
sender = ""
receiver = ""
message = """From: spark-cluster-manager <%s>
To: <%s>
Subject: Cluster Error Report

%s""" % (sender, receiver, "%s")

# for log
checker_logger = "checker_logger"
cluster_logger = "clucster_logger"


# -*- coding: utf-8 -*-
sala=[]
q=int(input('Quantidade de salas: '))
for i in range(0,q,1):
    vidasDeCadaSala=int(input('Digite a quantidade de vidas de cada sala: '))
    sala.append(vidasDeCadaSala)
portaDeEntrada=int(input('Digite a porta de entrada do jogo: '))
portaDeSaida=int(input('Digite a porta de saída do jogo: '))
somatório=0
for i in range(portaDeEntrada,portaDeSaida+1,1):
    somatório=somatório+1
print(somatório)


"""
The example to train an object detection model in AutoMM.

An example to finetune an MMDetection model on COCO:
    python detection_train.py \
        --train_path coco17/annotations/instances_train2017.json \
        --test_path coco17/annotations/instances_val2017.json \
        --checkpoint_name yolov3_mobilenetv2_320_300e_coco \
        --num_classes 80 \
        --lr <learning_rate> \
        --wd <weight_decay> \
        --epochs <epochs>

An example to finetune an MMDetection model on VOC:
    First, use this script to convert the VOC dataset to COCO format:
    https://github.com/open-mmlab/mmdetection/blob/9d3e162459590eee4cfc891218dfbb5878378842/tools/dataset_converters/pascal_voc.py
    Then, run:
    python detection_train.py \
        --train_path /media/data/datasets/voc/VOCdevkit/VOCCOCO/voc07_trainval.json \
        --test_path /media/data/datasets/voc/VOCdevkit/VOCCOCO/voc07_test.json \
        --checkpoint_name yolov3_mobilenetv2_320_300e_coco \
        --num_classes 20 \
        --lr <learning_rate> \
        --wd <weight_decay> \
        --epochs <epochs>

Note that for now it's required to install nightly build torchmetrics.
This will be solved in next pr. (MeanAveragePrecision will be moved to AG temporarily.)
"""

import argparse

from autogluon.multimodal import MultiModalPredictor

def detection_train(
    train_path,
    test_path=None,
    checkpoint_name="faster_rcnn_r50_fpn_2x_coco",
    num_classes=80,
    lr=1e-3,
    wd=1e-4,
    epochs=50,
    num_gpus=4,
    val_metric=None,
    per_gpu_batch_size=8,
):

    # TODO: add val_path
    # TODO: remove hardcode for num_classes

    predictor = MultiModalPredictor(
        label="rois_label",
        hyperparameters={
            "model.mmdet_image.checkpoint_name": checkpoint_name,
            "env.num_gpus": num_gpus,
            "env.strategy": "ddp",
        },
        pipeline="object_detection",
        output_shape=num_classes,
        val_metric=val_metric,
    )

    import time

    start = time.time()
    predictor.fit(
        train_path,
        hyperparameters={
            "optimization.learning_rate": lr,
            "optimization.weight_decay": wd,
            "optimization.max_epochs": epochs,
            "optimization.top_k": 1,
            "optimization.top_k_average_method": "best",
            "optimization.warmup_steps": 0.0,
            "optimization.patience": 40,
            "env.per_gpu_batch_size": per_gpu_batch_size,  # decrease it when model is large
        },
    )
    fit_end = time.time()
    print("time usage for fit: %.2f" % (fit_end - start))

    if num_gpus == 1 and test_path is not None:  # TODO: support multigpu inference
        print(predictor.evaluate(test_path))
        print("time usage for eval: %.2f" % (time.time() - fit_end))

if __name__ == "__main__":
    parser = argparse.ArgumentParser()
    parser.add_argument(
        "--train_path", default="/media/data/datasets/voc/VOCdevkit/VOCCOCO/voc07_trainval.json", type=str
    )
    parser.add_argument("--test_path", default="/media/data/datasets/voc/VOCdevkit/VOCCOCO/voc07_test.json", type=str)
    parser.add_argument("--checkpoint_name", default="yolov3_mobilenetv2_320_300e_coco", type=str)
    parser.add_argument("--num_classes", default=20, type=int)
    parser.add_argument("--lr", default=1e-3, type=float)
    parser.add_argument("--wd", default=1e-3, type=float)
    parser.add_argument("--epochs", default=50, type=int)
    parser.add_argument("--num_gpus", default=4, type=int)
    parser.add_argument("--per_gpu_batch_size", default=8, type=int)
    parser.add_argument("--val_metric", default=None, type=str)
    args = parser.parse_args()

    detection_train(
        train_path=args.train_path,
        test_path=args.test_path,
        checkpoint_name=args.checkpoint_name,
        num_classes=args.num_classes,
        lr=args.lr,
        wd=args.wd,
        epochs=args.epochs,
        num_gpus=args.num_gpus,
        val_metric=args.val_metric,  # "mAP" or "direct_loss" or None (use default: "direct_loss")
        per_gpu_batch_size=args.per_gpu_batch_size,
    )


import numpy as np

from ..aggregate_weave import step_indices, step_count

def test_step_indices_length():
    group_idx = np.array([1, 1, 1, 2, 2, 3, 3, 4, 4, 2, 2], dtype=int)
    for _ in xrange(20):
        np.random.shuffle(group_idx)
        step_cnt_ref = np.count_nonzero(np.diff(group_idx))
        assert step_count(group_idx) == step_cnt_ref + 1
        assert len(step_indices(group_idx)) == step_cnt_ref + 2

def test_step_indices_fields():
    group_idx = np.array([1, 1, 1, 2, 2, 3, 3, 4, 5, 2, 2], dtype=int)
    steps = step_indices(group_idx)
    np.testing.assert_array_equal(steps, np.array([ 0, 3, 5, 7, 8, 9, 11]))


from database_worker import InsertData, CreateIndex
import startup
import mappings
from get_ssu_author import get_ssu_author
from best_author import best_author
from best_article import best_article
from quoted_authors import quoted_authors
from co_author import co_author
from article_info import article_info
from diagram import diagram

def main():
    print('Aplication "Abstract base" was started\n')
    while True:
        print('')
        print('Choose one of variant:')
        print('1) Create database')
        print('2) Fill in with data')
        print('3) Get authors who noted sumdu')
        print('4) Get author with the largest number of publications')
        print('5) Get most quoted  publications')
        print('6) Get rating of the most cited authors')
        print('7) Get author who more often co-author (top 5)')
        print('8) Get authors name (authors names through commas), article title, number of citations.')
        print('9) Get for authors, add a histogram: the number of citations of his articles by years.')
        variant = input('Enter number of variant:')
        if variant == '1':
            cretor_author = CreateIndex('author', mappings.author)
            cretor_article = CreateIndex('article', mappings.article)
            cretor_author.create()
            cretor_article.create()
            print('Indexes "article" and "author" were created successfully!!!\n')
        elif variant == '2':
            inserter = InsertData(startup.authors + startup.articles)
            inserter.insert()
            article_info()
            print('Success fillind data!!!\n')
        elif variant == '3':
            print('Authors who use in text SSU:')
            print(get_ssu_author())
        elif variant == '4':
            print(best_author())
        elif variant == '5':
            print(best_article())
        elif variant == '6':
            print(quoted_authors())
        elif variant == '7':
            print(co_author())
        elif variant == '8':
            print(article_info())
        elif variant == '9':
            diagram()

if __name__ == '__main__':
    main()


from collections import deque
import sdl2 as sd2
import sdl2.ext as sdx
import sys

import numpy as np

from qqq.util import Timer

import world
import box_world

class SquareRenderer(sdx.SoftwareSpriteRenderSystem):
    def __init__(self, window):
        super().__init__(window)

    def render(self, components):
        sdx.fill(self.surface, sdx.Color(32, 32, 32))
        super().render(components)

def reset_surface(surface):
    sdx.fill(surface, sdx.Color(0, 0, 0))

def draw_rectangle(surface, q, x, y, w, h):
    l = len(q)
    for ix, item in enumerate(q):
        c = 128*(ix/l)
        sdx.fill(surface, sdx.Color(c, c, c), item)

    sdx.fill(surface, sdx.Color(128, 128, 128), (x, y, w, h))
    q.append((x, y, w, h))

def init_sdl(w, h, name="main"):
    sdx.init()

    w = sdx.Window(name, (500, 500))
    w.show()

    ws = w.get_surface()

    return w, ws

def basic_test_main():
    w, ws = init_sdl(200, 200)
    tim = Timer()

    x0, y0 = 100, 100
    w0, h0 = 10, 10

    tim.set()
    now = tim.now()

    q = deque([], maxlen=100)
    while tim.now() < now + 100:
        t = tim.now()
        reset_surface(ws)
        draw_rectangle(ws, q, x0 + 50*np.sin(8*t)+tim.elapsed(), y0 + 50*np.cos(4*t)+tim.elapsed(), w0, h0)
        w.refresh()
        tim.wait(t + 1/60)

def world_test_main():
    w, h = 500, 500

    win, ws = init_sdl(w, h)
    tim = Timer()
    n = tim.now()

    dt = 1/50
    box = box_world.BoxWorld(w, h)

    while tim.now() < n + 25:
        mark = tim.now()

        box.update()
        box.render()
        sd2.SDL_BlitSurface(box.surface, sd2.SDL_Rect(0, 0, w, h), ws, sd2.SDL_Rect(0, 0, w, h))
        win.refresh()

        tim.sleep(dt)

if __name__ == "__main__":
    basic_test_main()


chStr=''
ch=''
chIndex=0
errflag=0

def error():
    global errflag
    if not errflag:
        print("FAIL")
        errflag=1

def pa():
    global chStr
    global chIndex
    global ch
    if ch=='a':
        ch=chStr[chIndex]
        chIndex+=1
    else:
        error()

def pb():
    global chStr
    global chIndex
    global ch
    if ch=='b':
        ch=chStr[chIndex]
        chIndex+=1
    else:
        error()

def pS():
    global ch
    if ch == 'a':
        pa()
        pA()
        pb()
    else:
        error()

def pA():
    global ch
    def aMethod():
        pa()
        pS()

    def bMethod():
        pb()
    switch={'a':aMethod,'b':bMethod}
    try:
        switch[ch]()
    except KeyError as msg:
        error()

def main():
    global chStr
    global chIndex
    global ch
    global errflag
    chStr=input()
    ch=chStr[chIndex]
    chIndex+=1
    pS()
    if not errflag and ch=='$':
        print("OK")
    else:
        error()

if __name__ == '__main__':
     main()


# -*- coding: utf-8 -*-
"""
Created on Fri May 18 08:29:40 2018
Version: 0.0.01
@author: e10509
"""

# In[1]
import timeit
import matplotlib.pyplot as plt
import numpy as np
#import tkinter
import pandas as pn

from utilities import *

#import xlsxwriter
get_ipython().magic('matplotlib inline')
plt.rcParams['figure.figsize'] = (10.0, 4.0) # set default size of plots
plt.rcParams['image.interpolation'] = 'nearest'
plt.rcParams['image.cmap'] = 'gray'
#plt.style.use('presentation')

get_ipython().magic('load_ext autoreload')
get_ipython().magic('autoreload 2')

trainData = pn.read_excel('sample.xlsx')
testData  = pn.read_excel('sample2.xlsx')
#print the column names
print (trainData.columns)

m = len(trainData['X'])
m1 = len(testData['X'])
numParameters = 24 # number of parameters

trainq_ref  = np.zeros((6,m), dtype = np.float32)
testq_ref   = np.zeros((6,m1), dtype = np.float32)

trainq_ref[0,:] = (trainData['A1'].values)
trainq_ref[1,:] = (trainData['A2'].values)
trainq_ref[2,:] = (trainData['A3'].values)
trainq_ref[3,:] = (trainData['A4'].values)
trainq_ref[4,:] = (trainData['A5'].values)
trainq_ref[5,:] = (trainData['A6'].values)

trainq_ref = trainq_ref*D2R      #(q_ref*PI)/180
#print(q_ref[0,:])
#print(q_ref[:,0])
testq_ref[0,:] = testData['A1'].values
testq_ref[1,:] = testData['A2'].values
testq_ref[2,:] = testData['A3'].values
testq_ref[3,:] = testData['A4'].values
testq_ref[4,:] = testData['A5'].values
testq_ref[5,:] = testData['A6'].values

tQ_ref = D2R*testq_ref
print(testq_ref.shape)

P_n = Matrix([a[0],alp[0],d[1],q[1],a[1],alp[1],d[2],q[2],a[2],alp[2],d[3],q[3],
              a[3],alp[3],d[4],q[4],a[4],alp[4],d[5],q[5],a[5],alp[5],d[6],q[6]])

def measuredX(data):
    l = len(data['X'])
    mX = np.zeros((3*l,1), dtype = np.float32)
    countt = 0
    for j in range(0,l):
        mX[countt,0]   = (data['X'].values)[j]  #val_mX[j]
        mX[countt+1,0] = (data['Y'].values)[j]    #val_mY[j]
        mX[countt+2,0] = (data['Z'].values)[j]     #val_mZ[j]
        countt +=3
    return mX

#Test
#mx = measuredX(trainData)
#print(mx[0:3,:])

def Xr_and_Jacobian(nParam,jointConfig,theta_ref,dq,Tool):
    l      = theta_ref.shape[1]
    count  = 0
    agrX   = np.zeros((1,1), dtype = np.float32)
    agrH   = np.zeros((1,24), dtype = np.float32)
    m      = (l*3) + 1
    for j in range (0,l):

        changeConfiguration(jointConfig,theta_ref[:,j],dq)
#        print("this is qref:" + str(q_ref[:,j]))
        xr,jq = Jacobian(nParam,jointConfig,Tool)  # joint configuration is substittuted

        agrH = np.concatenate((agrH,jq),axis = 0)#np.vstack((agrH,jq))
        agrX = np.concatenate((agrX,xr),axis = 0)#np.vstack((agrX,xr))

#        agrX[count,0]    = xr[0,0]
#        agrX[count+1,0]  = xr[1,0]
#        agrX[count+2,0]  = xr[2,0]
#
##        obIndx.append(observIndex(jq))
#        agrH[count:count+3,:] = jq
#        count +=3
#    print(agrH[-1,:])
    return agrX[1:m],agrH[1:m,:]
# In[7]
#xr,Jr =Xr_and_Jacobian(nTestParam,jointConfig,tQ_ref,jointdq,"Tool_2")
pList,pol = calibConfigSelect(nTestParam,tQ_ref,'Tool_2')
print(pList)
print(pol)

lp = [x for x in range(10)]
print(lp)
#print(Jr[-1,:])
#print(xr.shape)
#plt.plot(np.squeeze(obIn))
#plt.ylabel('ObservIndx')
#plt.xlabel('test Configuration')
#plt.title('observability Index')
#plt.show()

#

def A_and_DJ(nParam,jointConfig,theta_ref,dq,Tool):
    l      = theta_ref.shape[1]
    J_dna = np.zeros((3*l,14), dtype = np.float32)

    Xr,Jr = Xr_and_Jacobian(nParam,jointConfig,theta_ref,dq,Tool)
#    J_dna[:,0:20]  = Jr[:,4:24]

    J_dna[:,0:3]   = Jr[:,4:7]
    J_dna[:,3:5]   = Jr[:,8:10]
    J_dna[:,5:8]   = Jr[:,12:15]
    J_dna[:,8:11]  = Jr[:,16:19]
    J_dna[:,11:14] = Jr[:,20:23]
#    J_dna[:,15:18] = Jr[:,20:23]
#    J_dna[:,21:23] = Jr[:,22:24]
#    J_dna[:,6:19] = Jr[:,11:24]
#    print(J_dna)
#    for k in range(0,12):
#
#        J_dna[:,k] = Jr[:,2*k]

    return Xr,J_dna

#
"""
This fucntion do non-linear leastsquare optimization to calibrate robot kinematic parameter
We plan to try jacobian of position w.r.t kin parameters i.e. J= dP/d(a,alpha,d,theta)
use sysmbolic python for that purpose. In selecting the measured data point for calibiration
Observability measure is considered.

"""
def nLCalibration_NLS(num_iterations,learning_rate,epislon,print_costs=False):

    """
    mX    --- measured cartesian position using laser tracker
    n_P  --  nominal kinemartic parameter
    Xr   --- rference position to calibrate on
    qr   --  joint position corresponding to Xr
    lr --- cosntant learning rate to update the kinematics parameter based on least square error
    epislon --- convergence chrateria

    """
#    m = qr.shape[1]
    numParam = 24#14
    costs = []
    detr = []

    mX  = measuredX(trainData)

    pk  = np.zeros((numParam,1), dtype = np.float32)
#    mP  = np.zeros((3,1), dtype = np.float32)
    err = 0

    mu = 0.01
    muI = mu*(np.identity(numParam))

    prevL_k = 0

#    ro = 0.25
#    gama = 0.75

#######################aggrigate Methods(Levenbrg Marquardt-LM)################
    for i in range(0,num_iterations):
        if (i==0):
            muI = muI/10.0
#        if (i>=100):
#            mu = 0.001
        startTime = timeit.default_timer()
        Xr,idfJ= Xr_and_Jacobian(nTestParam,jointConfig,trainq_ref,jointdq,"Tool_1")

#        Xr,idfJ = A_and_DJ(nTestParam,jointConfig,trainq_ref[:,0:20],jointdq,"Tool_1")
        condNumber = np.linalg.cond(idfJ)
        er    = (mX - Xr)
#        print(idfJ.shape)
        gk    = -2*((idfJ.transpose()).dot(er))  # gradient of loss function evealuated @
#        print(gk.shape)
        G_k   = 2*((idfJ.transpose()).dot(idfJ) + muI)
#        print(G_k.shape)
        pk    = -1*(np.linalg.inv(G_k)).dot(gk)
#        print(pk.shape)

        updateParameters(nTestParam,jointdq,pk,learning_rate,'M1')

#          # compute cost and appened to costs list

        L_k = np.sqrt(compute_cost(Xr,mX))

        if (L_k > prevL_k):
            muI = muI*10
#        else:
#            muI = muI/10

        prevL_k = L_k
        endTime = timeit.default_timer()
#        print(endTime - startTime)
#        if(np.abs(L_k - prevL_k) <= 1e-3):   #ignore the mu value when solution approach convergance
#            mu = 0.0001
#
        if print_costs and i % 10 == 0:

            print("Cost after iteration {}: {}".format(i, np.squeeze(L_k)))
            detr.append(condNumber)

        if print_costs:# and i % 10 == 0:

            costs.append(L_k)

        if(L_k < epislon):
            return

 # Plot result
    print("Improvment in Accuracy is:"+str((costs[0] - costs[-1])*100/costs[0])+"%")
    plt.plot(np.squeeze(costs))
    plt.ylabel('cost')
    plt.xlabel('iterations (per tens)')
    plt.title("Learning rate =" + str(learning_rate))
    plt.show()
    d = {"costs": costs,
         "clibratedParameter": nTestParam,
         "calibratedJoint" : jointdq,
         "learning_rate" : learning_rate,
         "determinant_idfJ": detr}
    return d

# In[11]
#startTime = timeit.default_timer()
#
#rd = nLCalibration_NLS(num_iterations=500,learning_rate=0.1,epislon =1e-3,print_costs=True)
#with open('calibParameters.csv', 'w') as f:
#    [f.write('{0},{1}\n'.format(key, value)) for key, value in rd.items()]
#endTime = timeit.default_timer()
#
#print(endTime - startTime)
#
#print(rd["clibratedParameter"])
#print(rd["calibratedJoint"])

# In[12]

"""
This fucntion do linear leastsquare optimization to calibrate robot kinematic parameter
We plan to try jacobian of position w.r.t kin parameters i.e. J= dP/d(a,alpha,d)
use sysmbolic python for that purpose. In selecting the calibration trajectory Observability is considered.

"""
def nLCalibration_LS(num_iterations,learning_rate,epislon,full_parameters = True,print_costs=False):

    """
    mX    --- measured cartesian position using laser tracker
    n_P  --  nominal kinemartic parameter
    Xr   --- rference position to calibrate on
    qr   --  joint position corresponding to Xr
    lr --- cosntant step size to update the kinematics parameter based on least square error
    epislon --- convergence chrateria

    """
#    m = qr.shape[1]

    costs  = []
    ObIndx = []
#    parameters = nParameters

    mX  = measuredX(trainData)
#    Xr,_ = aggregateJacobian(nTestParam,jointConfig,jointdq) # aggregate pose and jacobian
    pk  = np.zeros((numParameters,1), dtype = np.float32)
#    mP  = np.zeros((3,1), dtype = np.float32)
    err = 0

#######################aggrigate Methods(Levenbrg Marquardt-LM)################
    for i in range(0,num_iterations):
#        if (i==0):
#            muI = muI/10.0
        startTime = timeit.default_timer()
#        if (full_parameters):
        Xr,idfJ = Xr_and_Jacobian(nTestParam,jointConfig,trainq_ref,jointdq,"Tool_1") #aggregateJacobian(nTestParam,jointConfig,jointdq) #idfJ(identification jacobian)

#        Xr,idfJ = A_and_DJ(nTestParam,jointConfig,trainq_ref,jointdq,"Tool_2")

        er    = (mX - Xr)
#        print(er)

        gk    = np.linalg.pinv(idfJ,1e-8)#(np.linalg.inv(G_k)).dot(idfJ)
        pk    = (gk.dot(er))

        condNumber = np.linalg.cond(idfJ)

        updateParameters(nTestParam,jointdq,pk,learning_rate,'M1')
#
###############################################################################
#          # compute cost and appened to costs list

        L_k = np.sqrt(compute_cost(Xr,mX))

#        prevL_k = L_k
        endTime = timeit.default_timer()
#        print(endTime - startTime)

#
        if print_costs and i % 100 == 0:

            print("Cost after iteration {}: {}".format(i, np.squeeze(L_k)))
#            print(pk[6])

        if print_costs:# and i % 10 == 0:

            costs.append(L_k)
            ObIndx.append(condNumber)
        if(L_k < epislon):
            return
    print("Improvment in Accuracy is:"+str((costs[0] - costs[-1])*100/costs[0])+"%")
    plt.plot(np.squeeze(costs))
    plt.ylabel('cost')
    plt.xlabel('iterations (per tens)')
    plt.title("LS_learning rate =" + str(learning_rate))
    plt.show()
    d ={"costs":costs,"learning_rate":learning_rate,"calibratedParameters":nTestParam,"JointOffset":jointdq}
    return d

# In[13]
startTime = timeit.default_timer()

parmd = nLCalibration_LS(num_iterations=2000,learning_rate=0.001,epislon =1e-3,full_parameters = True,print_costs=True)

# write the result to file
with open('calibParametersLS.csv', 'w') as f:
    [f.write('{0},{1}\n'.format(key, value)) for key, value in parmd.items()]

endTime = timeit.default_timer()

print(endTime - startTime)

print(parmd["calibratedParameters"])
print(parmd["JointOffset"])

# In[14]
#startTime = timeit.default_timer()
#learning_rates = [0.1, 0.1, 0.1]
#models = {}
#for i in learning_rates:
#    print ("learning rate is: " + str(i))
#    models[str(i)] = nLCalibration_NLS(num_iterations=300,learning_rate=i,epislon =1e-3,print_costs=True)
#    print ('\n' + "-------------------------------------------------------" + '\n')
#
#for i in learning_rates:
#    plt.plot(np.squeeze(models[str(i)]["costs"]), label= str(models[str(i)]["learning_rate"]))
#
#plt.ylabel('cost')
#plt.xlabel('iterations')
#
#legend = plt.legend(loc='upper center', shadow=True)
#frame = legend.get_frame()
#frame.set_facecolor('0.90')
#plt.show()
#
#endTime = timeit.default_timer()
#
#print(endTime - startTime)

# In[15]
#evalute the performance
cst = []
jConfig = {'q1':9.05880481e-02,
               'q2':-1.37911820e+00,
               'q3':-5.84525391e-02,
               'q4':1.92422551e-04,
               'q5':1.57268214e+00,
               'q6':1.29712690e-02}
qref = {'q1': -0.0019053210949872236, 'q2': -0.0074753436301932463, 'q3': 0.0067879131750221639,
        'q4': 0.0019570135008669587, 'q5': -0.011103828843761083, 'q6': 0.67582795831979081}
#for i in range(0,testq_ref.shape[1]):
#
#    changeConfiguration(jConfig,testq_ref[:,i],qref)
##    print(jConfig)
#    xr,_ =  FKI(nTestParam,jConfig,"Tool_2")
#    print(xr)
#print(cst)
#print(testq_ref.shape[1])
Xr,_ =  Xr_and_Jacobian(nTestParam,jConfig,trainq_ref,jointdq,"Tool_2")
#print(Xr)
xm   = measuredX(trainData)
print(xm.shape)
cost = np.sqrt(compute_cost(xm,Xr))
#print(xr)
##print(jointdq)
cst.append(nTestParam.values())
print(cost)

#with open('aftercalib.csv', 'w') as f:
#    [f.write('{0}\n,{1}\n'.format(xr, xm))]


#!/usr/bin/python3
from odoo import models, fields,api
from odoo.exceptions import Warning
from odoo.addons.ebay_ept.ebaysdk.trading import Connection as trading

class ebay_category(models.Model):
    _name="ebay.category.master.ept"
    _description = "eBay Master Category"

    @api.one
    def _complete_name(self):
        """
            Forms complete name of location from parent location to child location.
        """
        for m in self:
            names = [m.name]
            parent = m.ebay_category_parent_id
            parent = True
            if m.parent_id:
                rec=m.parent_id
            else:
                parent=False
            while parent:
                names.append(rec.name)
                if not rec.parent_id:
                    parent = False
                    continue
                rec=rec.parent_id
                parent = rec.ebay_category_parent_id
            m.ept_complete_name = '/'.join(reversed(names))

    name = fields.Char(size=256, string='Category Name', required=True)
    ept_complete_name = fields.Char(compute=_complete_name, string='Name',store=False)
    ebay_category_id = fields.Char(string='Category ID')
    parent_id=fields.Many2one("ebay.category.master.ept","Parent")
    category_level = fields.Integer(string='Category Level')
    ebay_category_parent_id = fields.Char(string='Parent Category')
    site_id = fields.Many2one('ebay.site.details', string='Site')
    active = fields.Boolean("Active",default=True)
    attribute_ids = fields.One2many('ebay.attribute.master', 'categ_id', 'Attributes')
    instance_id=fields.Many2one("ebay.instance.ept",string="Instance")
    item_specifics = fields.Boolean("Item Specific Enabled",default=False)
    condition_enabled = fields.Boolean("Condition Enabled",default=False)
    variation_enabled=fields.Boolean("VariationsEnabled",default=False)
    leaf_category = fields.Boolean("Leaf Category",default=False)
    ebay_condition_ids = fields.One2many("ebay.condition.ept","category_id","eBay Condition")

    auto_pay_enabled = fields.Boolean("Auto Pay Enable",default=False)
    set_return_policy = fields.Boolean("Return Policy",default=False)
    best_offer_enabled = fields.Boolean("Best Offer Enabled",default=False)
    galary_plus_enabled = fields.Boolean("FreeGalleryPlusEnabled",default=False)
    offer_accept_enabled = fields.Boolean("BestOfferAutoAcceptEnabled",default=False)
    handling_time_enabled=fields.Boolean("HandlingTimeEnabled",default=False)

    paypal_required=fields.Boolean('PayPalRequired',default=False)
    digital_good_delivery_enabled=fields.Boolean("DigitalGoodDeliveryEnabled",default=False)
    is_store_category=fields.Boolean("Is Store Category ?",default=False)
    odoo_product_category = fields.Many2one("product.category",string="Odoo Category",help="Select odoo product category.")

    @api.multi
    def import_store_category(self,instances,level_limit=0,only_leaf_categories=True):
        for instance in instances:
            cat = {}
            site_id = instance.site_id and instance.site_id.site_id or False

            api = instance.get_trading_api_object()
            para = {'DetailLevel': 'ReturnAll'}
            if level_limit>0:
                para.update({'LevelLimit':level_limit})
            if site_id:
                para.update({'CategorySiteID':site_id})
            if only_leaf_categories:
                para.update({'ViewAllNodes':'false'})
            else:
                para.update({'ViewAllNodes':'true'})
            try:
                api.execute('GetStore', para)
                cat = api.response.dict()
            except Exception as e :
                raise Warning(('%s')%(str(e)))

            categories = []
            custom_category=cat.get('Store',{}).get('CustomCategories',{})
            if custom_category and custom_category.get('CustomCategory',[]):
                if isinstance(custom_category.get('CustomCategory',[]),list):
                    categories = custom_category.get('CustomCategory',[])
                else:
                    categories = [custom_category.get('CustomCategory',[])]
            for categ in categories:
                name = categ.get('Name')
                categoryid = categ.get('CategoryID')
                categ_record = self.search([('ebay_category_id','=',categoryid),('instance_id','=',instance.id)],limit=1)
                if categ_record:
                    categ_record.write({'name':name})
                else:
                    categ_record=self.create({
                        'name':name,
                        'ebay_category_id':categoryid,
                        'site_id':instance.site_id and instance.site_id.id or False,
                        'instance_id':instance.id,
                        'is_store_category':True
                    })
                child_categs=categ.get('ChildCategory',[])
                if not isinstance(child_categs,list):
                    child_categs=[child_categs]

                for child in child_categs:
                    name = child.get('Name')
                    categoryid = child.get('CategoryID')

                    child_record = self.search([('ebay_category_id','=',categoryid),('site_id','=',instance.site_id.id),('is_store_category','=',True),('instance_id','=',instance.id)],limit=1)
                    if child_record:
                        child_record.write({'name':name})
                    else:
                        child_record = self.create({
                            'name':name,
                            'ebay_category_id':categoryid,
                            'site_id':instance.site_id and instance.site_id.id or False,
                            'instance_id':instance.id,
                            'is_store_category':True,
                            'ebay_category_parent_id':categ_record.ebay_category_id,
                            'parent_id':categ_record.id
                        })

                    #Added By Dimpal 25/12/2017
                    sub_child_categs = child.get('ChildCategory',[])
                    if not isinstance(sub_child_categs, list):
                        sub_child_categs = [sub_child_categs]
                    for sub_child in sub_child_categs:
                        name = sub_child.get('Name')
                        categoryid = sub_child.get('CategoryID')

                        sub_child_record = self.search([('ebay_category_id','=',categoryid),('site_id','=',instance.site_id.id),('is_store_category','=',True),('instance_id','=',instance.id)],limit=1)
                        if sub_child_record:
                            sub_child_record.write({'name' : name})
                        else:
                            self.create({
                                'name':name,
                                'ebay_category_id':categoryid,
                                'site_id':instance.site_id and instance.site_id.id or False,
                                'instance_id':instance.id,
                                'is_store_category':True,
                                'ebay_category_parent_id':child_record.ebay_category_id,
                                'parent_id':child_record.id
                            })
            self._cr.commit()
        return True

    @api.multi
    def import_category(self,instances,level_limit=0,only_leaf_categories=True,is_import_get_item_condition=False):
        for instance in instances:
            cat = {}
            site_id = instance.site_id and instance.site_id.site_id or False
            api = instance.get_trading_api_object()
            para = {'DetailLevel': 'ReturnAll'}
            if level_limit>0:
                para.update({'LevelLimit':level_limit})
            if site_id:
                para.update({'CategorySiteID':site_id})
            if only_leaf_categories:
                para.update({'ViewAllNodes':'false'})
            else:
                para.update({'ViewAllNodes':'true'})
            try:
                api.execute('GetCategories', para)
                cat = api.response.dict()
            except Exception as e:
                raise Warning(('%s')%(str(e)))
            categories = []
            if cat.get('CategoryArray',{}) and cat['CategoryArray'].get('Category',[]):
                categories = cat['CategoryArray']['Category'] #returns list of dictionary
            if isinstance(categories,dict):
                categories=[categories]

            for categ in categories:
                name = categ.get('CategoryName')
                CategoryID = categ.get('CategoryID')
                AutoPayEnabled = categ.get('AutoPayEnabled')
                CategoryLevel = categ.get('CategoryLevel')
                CategoryParentID = categ.get('CategoryParentID')
                LSD = categ.get('LSD')
                LeafCategory = categ.get('LeafCategory',"false")
                BestOfferEnabled = categ.get('BestOfferEnabled',"false")

                if LeafCategory == 'true':
                    LeafCategory = True
                else:
                    LeafCategory = False
                if LSD == 'true':
                    LSD = True
                else:
                    LSD = False
                if BestOfferEnabled == 'true':
                    BestOfferEnabled = True
                else:
                    BestOfferEnabled = False
                if CategoryID == CategoryParentID:
                        CategoryParentID =False
                categs = self.search([('ebay_category_id','=',CategoryID),('site_id','=',instance.site_id.id)],limit=1)
                parent=self.search([('ebay_category_id','=',CategoryParentID),('site_id','=',instance.site_id.id)],limit=1)
                if not categs:
                    self.create({
                        'name':name,
                        'ebay_category_id':CategoryID,
                        'site_id':instance.site_id and instance.site_id.id or False,
                        'leaf_category':LeafCategory,
                        'ebay_category_parent_id':CategoryParentID,
                        'category_level':CategoryLevel,
                        'auto_pay_enabled':AutoPayEnabled,
                        'best_offer_enabled':BestOfferEnabled,
                        'parent_id':parent and parent.ids[0] or False
                    })
                else:
                    categs.write({
                        'name':name,
                        'ebay_category_id':CategoryID,
                        'site_id':instance.site_id and instance.site_id.id or False,
                        'leaf_category':LeafCategory,
                        'ebay_category_parent_id':CategoryParentID,
                        'category_level':CategoryLevel,
                        'auto_pay_enabled':AutoPayEnabled,
                        'best_offer_enabled':BestOfferEnabled,
                        'parent_id':parent and parent.ids[0] or False
                    })
                if is_import_get_item_condition:
                    """
                        :Function get_item_conditions: This function call to category wise import get item condition.
                    """
                    self.get_item_conditions(import_category_id=CategoryID)

            return True

    @api.multi
    def get_attributes(self, max_name_levels, max_value_per_name):
        attribute_master_obj=self.env['ebay.attribute.master']
        attribute_value_obj=self.env['ebay.attribute.value']
        instance_obj=self.env['ebay.instance.ept']

        results = False
        category = self
        category_code = category.ebay_category_id

        instances = instance_obj.search([('site_id','=',category.site_id.id),('state','=','confirmed')])
        if not instances:
            return True
        instance = instances[0]
        if category_code:
            api = instance.get_trading_api_object()
            para = {'CategoryID':category.ebay_category_id}
            if max_name_levels :
                para.update({'MaxNames' : max_name_levels})
            if max_value_per_name :
                para.update({'MaxValuesPerName' : max_value_per_name})
            results = api.execute('GetCategorySpecifics', para)
            list_of_result=[]
            if isinstance(results.dict().get('Recommendations',{}).get('NameRecommendation',[]),list):
                list_of_result=results.dict().get('Recommendations',{}).get('NameRecommendation',[])
            else:
                list_of_result.append(results.dict().get('Recommendations',{}).get('NameRecommendation',[]))
            for line in list_of_result:
                attribute_name=line.get('Name')
                attribute_record=attribute_master_obj.search([('name','=',attribute_name),('categ_id','=',category.id)])
                if not attribute_record:
                    attribute_record=attribute_master_obj.create({'name':attribute_name,'categ_id':category.id})
                list_of_value=[]
                if isinstance(line.get('ValueRecommendation',[]),list):
                    list_of_value=line.get('ValueRecommendation',[])
                else:
                    list_of_value.append(line.get('ValueRecommendation',{}))
                for value in list_of_value:
                    attribute_value=attribute_value_obj.search([('name','=',value.get('Value')),('attribute_id','=',attribute_record.id)])
                    if not attribute_value:
                        attribute_value_obj.create({'name':value.get('Value'),'attribute_id':attribute_record.id})
            """for line in list_of_result:
                child_categs=self.search([('parent_id','=',category.id)])
                while child_categs:
                    for child in child_categs:
                        child_record=attribute_master_obj.search([('name','=',attribute_name),('categ_id','=',child.id)])
                        if not child_record:
                            child_record=attribute_master_obj.create({'name':attribute_name,'categ_id':child.id})
                        for value in line.get('ValueRecommendation',[]):
                            child_value=attribute_value_obj.search([('name','=',value.get('Value')),('att_master_id','=',child_record.id)])
                            if not child_value:
                                attribute_value_obj.create({'name':value.get('Value'),'att_master_id':child_record.id})

                    child_categs=self.search([('parent_id','in',child_categs.ids)])"""

        return True

    @api.multi
    def get_item_conditions(self, import_category_id=None):
        condition_obj=self.env['ebay.condition.ept']
        instance_obj=self.env['ebay.instance.ept']
        category = None

        if not self and import_category_id:
            category = self.search([('ebay_category_id','=',import_category_id)],limit=1)
        else:
            category = self

        category_code = category.ebay_category_id
        instances = instance_obj.search([('site_id','=',category.site_id.id),('state','=','confirmed')])
        if not instances:
            return True
        instance = instances[0]
        if category_code:
            api = instance.get_trading_api_object()

            para = {'ViewAllNodes': True, 'DetailLevel': 'ReturnAll', 'AllFeaturesForCategory': True, 'CategoryID': category.ebay_category_id}
            api.execute('GetCategoryFeatures', para)

            results1 = api.response.dict()
            if results1:
                category_default = results1.get('SiteDefaults',{})
                category_val = results1.get('Category',{})

                item_sp_en = category_val.get('ItemSpecificsEnabled',False) or category_default.get('ItemSpecificsEnabled',False)
                condition_enabled = category_val.get('ConditionEnabled',False) or category_default.get('ConditionEnabled',False)
                galary_plus_enabled=category_val.get('FreeGalleryPlusEnabled',False) or category_default.get('FreeGalleryPlusEnabled',False)
                offer_accept_enabled=category_val.get('BestOfferAutoAcceptEnabled',False) or category_default.get('BestOfferAutoAcceptEnabled',False)
                set_return_policy=category_val.get("ReturnPolicyEnabled",False) or category_default.get('ReturnPolicyEnabled',False)
                digital_good_delivery_enabled = category_val.get('DigitalGoodDeliveryEnabled',False) or category_default.get('DigitalGoodDeliveryEnabled',False)
                paypal_required=category_val.get("PayPalRequired",False) or category_default.get('PayPalRequired',False)
                variation_enabled=category_val.get("VariationsEnabled",False) or category_default.get('VariationsEnabled',False)
                handling_time_enabled=category_val.get("HandlingTimeEnabled",False) or category_default.get('HandlingTimeEnabled',False)

                offer_accept_enabled=False if offer_accept_enabled=='false' else True
                galary_plus_enabled=False if galary_plus_enabled=='false' else True
                set_return_policy=False if set_return_policy=='false' else True
                item_sp_en = True if item_sp_en == 'Enabled' else False
                digital_good_delivery_enabled=False if digital_good_delivery_enabled== 'false' else True
                condition_enabled =True  if condition_enabled == 'Required' else False

                paypal_required=False if paypal_required=='false' else True
                variation_enabled=True if variation_enabled=='true' else False
                handling_time_enabled=True if handling_time_enabled=='true' else False
                category.write({'item_specifics':item_sp_en,'condition_enabled':condition_enabled,
                                'offer_accept_enabled':offer_accept_enabled,'galary_plus_enabled':galary_plus_enabled,
                                'set_return_policy':set_return_policy,'variation_enabled':variation_enabled,'handling_time_enabled':handling_time_enabled,
                                'digital_good_delivery_enabled':digital_good_delivery_enabled,'paypal_required':paypal_required
                                })

                condition_values = category_val.get('ConditionValues',False)
                if condition_values:
                    if isinstance(condition_values.get('Condition',[]),dict):
                        condition_values=[condition_values.get('Condition',[])]
                    else:
                        condition_values=condition_values.get('Condition',[])

                    for each_val in condition_values:
                        condition_name = each_val.get('DisplayName',False)
                        condition_id = each_val.get('ID',False)
                        if condition_name and condition_id:
                            search_conditions = condition_obj.search([('condition_id','=',condition_id),('category_id','=',category.id),('name','=',condition_name)])
                            if not search_conditions:
                                condition_vals = {'name':condition_name,'condition_id':condition_id,'category_id':category.id}
                                condition_obj.create(condition_vals)

                    if not category.leaf_category and category.ebay_condition_ids:
                        child_categ = self.env['ebay.category.master.ept'].search([('parent_id','=',category.id)])
                        while True:
                            for child in child_categ:
                                for condition in  category.ebay_condition_ids:
                                    search_conditions = condition_obj.search([('condition_id','=',condition.condition_id),('category_id','=',child.id),('name','=',condition.name)])
                                    if not search_conditions:
                                        condition_vals = {'name':condition.name,'condition_id':condition.condition_id,'category_id':child.id}
                            child_categ = self.env['ebay.category.master.ept'].search([('parent_id','in',child_categ.ids)])
                            if not child_categ:
                                break
        return True


from collections import defaultdict

def main():
    with open("puzzleInputs/12.txt") as file:
        inp = file.readlines()
    init_str = to_num(inp[0].split(":")[1].strip())
    init_str_len = len(init_str)

    max_generations = 50000000000
    slice_size = 5
    padding = (slice_size - 1) * "0"
    pot_states = padding + init_str + padding

    rules = defaultdict(lambda: "0")
    for rule_str in inp[1:]:
        rule, result = [s.strip() for s in rule_str.split(" => ")]
        rules[to_index(rule)] = to_num(result)

    # 50bil will never complete, inspected loop and noticed that after
    # 124 generations the sum always increase by 88.
    # Cut the loop short here, and sum up any remaining generations later
    gens_processed = 0
    for gen in range(min(125, max_generations)):
        new_states = []
        for start_index in range(0, len(pot_states) + 1 - slice_size):
            asdf = pot_states[start_index : start_index + slice_size]
            new_states.append(rules[to_index(asdf)])
        pot_states = padding + "".join(new_states) + padding
        gens_processed += 1

        # Part 1
        if (gens_processed == 20):
            print(calc_pot_sum(pot_states, init_str_len))

    # Part 2
    pot_sum = calc_pot_sum(pot_states, init_str_len)
    pot_sum += 88 * max(0, max_generations - gens_processed)
    print(pot_sum)

conversion = str.maketrans({"#":"1", ".":"0"})
def to_num(s):
    return s.translate(conversion)

def to_index(s):
    return int(to_num(s), 2)

def calc_pot_sum(pot_states, init_size):
    offset = (len(pot_states) - init_size) // 2
    return sum([(ind - offset) * int(val) for ind, val in enumerate(pot_states)])

if __name__ == "__main__":
    main()