# encoding:utf-8
import json
from bson import ObjectId
from Godzilla import setting
from Godzilla.setting import REDIS_DB

"""
场景1：u向i发送3条语音消息
u:{}
i:{u:3}

场景2：i读取了u的消息
u:{}
i:{u:0}

场景3：u向i发送3条语音消息,t向i发送了2条语音消息
u:{}
t:{}
i:{u:3,t:2}

场景4：i读取了u的消息
u:{}
t:{}
i:{u:0,t:2}

将未读消息使用字典的形式：
to_user : {from_user1:1,from_user2:3}
存放在Redis中
"""

def set_redis(from_user, to_user):
    """
    设置未读消息
    :param from_user: app
    :param to_user: toy
    :return:
    """
    print(from_user, to_user)  # 5d01fce97a2e4d9c00b61c6d 5d020262969d398f4d5f6126

    to_user_msg = REDIS_DB.get(to_user)
    print("to_user_msg::", to_user_msg)

    if to_user_msg:
        # 存在，即 toy 有值，判断是否有 from_user 的未读消息，若没有，储存值为一，若有，值加一再保存
        to_user_msg = json.loads(to_user_msg)
        if to_user_msg.get(from_user, ""):
            to_user_msg[from_user] += 1
        else:
            to_user_msg[from_user] = 1
        REDIS_DB.set(to_user, json.dumps(to_user_msg))
    else:
        # 不存在，即设置新值
        REDIS_DB.set(to_user, json.dumps({from_user: 1}))

def set_redis_app(from_user, to_user):
    """
    设置未读消息
    :param from_user:  发送者
    :param to_user: 接收者  也是查看者
    :return:
    """

    print(from_user, to_user)  # 5d020262969d398f4d5f6126 5d01fce97a2e4d9c00b61c6d

    to_user_msg = REDIS_DB.get(to_user)

    if to_user_msg:
        # 存在，即 toy 有值，由于无论 以 from_user 为键 是否有值,都设为 0
        to_user_msg = json.loads(to_user_msg)
        to_user_msg[from_user] = 0
        REDIS_DB.set(to_user, json.dumps(to_user_msg))
    else:
        # 不存在，即设置新址
        REDIS_DB.set(to_user, json.dumps({from_user: 0}))

def get_redis(from_user, to_user):
    """
    toy 查询未读消息
    :param from_user:
    :param to_user:
    :return: 未读消息的数量
    """
    print(from_user, to_user)

    to_user_msg = REDIS_DB.get(to_user)

    user_count = 0
    if to_user_msg:
        to_user_msg = json.loads(to_user_msg)

        # toy_id 存在，判断 from_user 是否存在
        from_user_count = to_user_msg.get(from_user)
        if from_user_count:
            user_count = from_user_count  # 该用户的未读数量
        else:
            # 如果这个用户没有未读数量，则去查询其他的是否还有未读消息
            for _from_user,count in to_user_msg.items():
                if count:   # 不为空
                    from_user = _from_user
                    user_count = count

        to_user_msg[from_user] = 0
        REDIS_DB.set(to_user, json.dumps(to_user_msg))
    else:
        REDIS_DB.set(to_user, json.dumps({from_user: 0}))

    print(from_user,user_count)
    return from_user,user_count

def get_redis_all(to_user):
    """
    app 查询 所有的未读消息
    :param to_user:
    :return:    格式:{"u_1":1,"u_2":2,"count":3} 或 {"count":0}
    """
    to_user_msg = REDIS_DB.get(to_user)
    if to_user_msg:
        # 如果有值, 给其 添加一个 count 键值对
        to_user_msg = json.loads(to_user_msg)
        to_user_msg["count"] = sum(to_user_msg.values())
    else:
        to_user_msg = {"count": 0}

    return to_user_msg


import wave, sys, audioop

def u_law_e(i16bit):
    i16bit &= 0x3fff # strips data bigger than 14 bits
    pos = 12        # position is 12 since we are not calculating sign bit and 0 value so 14 - sign == 13; so 13 bits, - 0 value ... 12 bits
    msk = 0x1000    # mask 1 0000 0000 0000 # bitwise mask for singular bits

    sign = 0x80 if i16bit&0x2000 else 0 # generating 8bit sign from 14 bit number

    if sign == 0x80: # if sign is present
        i16bit = twos_compliment(i16bit) # twos_compliment
        i16bit &= 0x3ffe               # strips all bits larger than 14 bits

    i16bit+=0b100001                    # adds 33, 0x21 = 10 0001

    if i16bit > 0x1fff: i16bit = 0x1fff # if number is over maximum ... it becomes maximum

    for x in reversed( range(pos) ):    # this number has least significant bits, not bit... so they have often size of 4 bits, that is why it must be larger than 5
        if (i16bit & msk)!=msk and pos>=5:
            pos = x
            msk >>=1

    LSBTS = ( i16bit >> (pos-4) )&0xf # grabbing mantissa from 16 bit integer

    encoded = sign          # sign
    encoded += (pos-5)<<4    # exponent
    encoded += LSBTS        # mantisa

    return encoded^0xff # inverting all bits

def u_law_d(i8bit):
    i8bit &= 0xff # marginalising data larger than byte
    i8bit ^= 0xff #flipping back bytes
    sign = False

    if i8bit&0x80==0x80: # if it is signed negative 1000 0000
        sign = True # bool option since sign is not really used
        i8bit &= 0x7f # removing the sign of value

    pos = ( (i8bit&0xf0) >> 4 )+5 # grabing initial value for mantisa

    # generating decoded data
    decoded = i8bit&0xf # grabing 1st nibble from 8 bit integer
    decoded <<= pos-4   # shifting by position -4 aka generating mantisa for 16 bit integer
    decoded |= 1 << ( pos-5 ) # OR gate for specific bit
    decoded |= 1<<pos   # OR gate for another specific bit
    decoded -= 0x21 # removing the 10 0001 from value to generate exact value

    if not sign:
        return decoded  # if positive number will be returned as is
    else:
        return -decoded # if negative the number will be returned inverted

file = open('C:\\Users\\sequel2\\AppData\\Roaming\\Fanvil\\recorded\\2018-08-24\\in_3001_2011_0c383e0e709a_2018-08-24_16_11_30.wav', 'rb')
# w = open(r'C:\Users\sequel2\AppData\Roaming\Fanvil\recorded\2018-08-24\in_3001_2011_0c383e0e709a_2018-08-24_16_11_30_2.wav', 'wb')
w = wave.open(r'C:\Users\sequel2\AppData\Roaming\Fanvil\recorded\2018-08-24\in_3001_2011_0c383e0e709a_2018-08-24_16_11_30_2.wav', 'wb')

w.setnchannels(1)
w.setsampwidth(2)
w.setframerate(4000)

# while True:
#     s = file.read(1)
#     if s == '': break
#     print(ord(s))

fdata = file.read()
file.close()

# print(str(fdata))
d_data = audioop.ulaw2lin(fdata, 1)
w.writeframes(d_data)

file.close()
w.close()


highOrderedOperators = ["*","/"]
lowOrderedOperators = ["+","-"]
def grabOperands(array, index):
    operand1 = array[index-1]
    operand2 = array[index+1]

    return (operand1, operand2)

def extractOperation(array, index):
    operands = grabOperands(array,index)
    operator = array[index]

    return (operands[0],operator,operands[1])

def removeOperandsAndOperator(array, index):
    for i in range(3):
        del array[index-1]

    return array

def doOperation(operation):
    operator = operation[1]
    operand1 = float(operation[0])
    operand2 = float(operation[2])
    if operator == "*":
        return operand1 * operand2
    elif operator == "/":
        return operand1 / operand2
    elif operator == "+":
        return operand1 + operand2
    elif operator == "-":
        return operand1 - operand2
    else:
        raise ValueError("Error")

def operationToResult(array, index):
    operation = extractOperation(array, index)
    resultOperation = doOperation(operation)
    array = removeOperandsAndOperator(array, index)
    array.insert(index-1, str(resultOperation))

    return array

def parseOperators(array, operatorsType):
    index = 0
    while index < len(array):
        for operator in operatorsType:
            if array[index] == operator:
                array = operationToResult(array, index)
                index = 0

        index += 1

    return array

def parse(array):
    arrayParsedHighOrder = parseOperators(array, highOrderedOperators)
    arrayFinal = parseOperators(arrayParsedHighOrder, lowOrderedOperators)

    return float(arrayFinal[0])

array = ["12","+","3","*","4","*","3.5","+","2","/","5"]
number = parse(array)
print(number)


#from lib2to3.pytree import _Results
import enum
from operator import truediv
from sre_constants import SUCCESS
import cv2
import mediapipe as mp
import math
import numpy as np
from ctypes import cast, POINTER
from comtypes import CLSCTX_ALL
from pycaw.pycaw import AudioUtilities, IAudioEndpointVolume

devices = AudioUtilities.GetSpeakers()
interface = devices.Activate(
    IAudioEndpointVolume._iid_, CLSCTX_ALL, None)
volume = cast(interface, POINTER(IAudioEndpointVolume))

# print("Volume Level :" , volume.GetMasterVolumeLevel())
# print("Volume Range :" , volume.GetVolumeRange())
# volume.SetMasterVolumeLevel(-10.0, None)

mpDraw = mp.solutions.drawing_utils
#mp_drawing_styles = mp.solutions.drawing_styles
mpHands = mp.solutions.hands
hands = mpHands.Hands()

#THIS IS THE CODE TO CAPTURE THE IMAGE

cap = cv2.VideoCapture(0)

while True:
    success, img = cap.read()
    imgRGB = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
    results = hands.process(imgRGB)
    #print(results.multi_hand_landmarks) #THIS LINE IS TO NOTICE THE POSITION OF THE HAND IN THE IMAGE

    if results.multi_hand_landmarks:
        for handLms in results.multi_hand_landmarks:# HERE WE USED FOR LOOP SO THAT ALL HANDS THAT ARE CAPTURED CAN BE LANDMARKED
            lmList = []
            for id, lm in enumerate(handLms.landmark):#THIS AND THE NEXT LINES ARE CREATED TO PREVENT SCROLLING WHEN NO HANDS ARE SHOWN
                #print(id, lm)
                h , w , c = img.shape
                #IN THE ABOVE LINE ARE HEIGHT WIDTH AND CHANNEL(H,W,C)
                cx, cy = int(lm.x*w) , int(lm.y*h)
                #print(id, cx, cy)
                lmList.append([id, cx, cy])

            #print(lmList)#THIS AND THE ABOVE LINE WERE USED TO GIVE THE HAND POSITIONS IN THE FORM OF AN ARRAY

            # mpDraw.draw_landmarks(img, handLms, mpHands.HAND_CONNECTIONS)
            if lmList:
                x1, y1 = lmList[4][1] , lmList[4][2]
                x2, y2 = lmList[8][1] , lmList[8][2]
            cv2.circle(img, (x1,y1), 10 , (3,6,245) , cv2.FILLED)
            cv2.circle(img, (x2,y2), 10 , (3,6,245) , cv2.FILLED)
            cv2.line(img , (x1,y1) , (x2,y2), (72,46,132), 3)
            length = math.hypot(x2-x1 , y2-y1)
            print(length)

            volRange = volume.GetVolumeRange()
            minVol = volRange[0]
            maxVol = volRange[1]
            vol = np.interp(length , [50,300], [minVol, maxVol])

            volume.SetMasterVolumeLevel(vol, None)

    cv2.imshow("YourImage", img)
    cv2.waitKey(1)

    # length = 50 ==> 300
    # Volume = 0 ==> 100
    # Volume Range = -65.25 ==> 0.0


import os
import numpy as np
np.random.seed(0)
import h5py
import tensorflow as tf
np.random.seed(0)
import matplotlib.pyplot as plt
from pylab import *
from keras.models import Sequential
from keras.optimizers import Adam
from keras.layers import Conv2D, ZeroPadding2D, Activation, Input, concatenate, LeakyReLU, Dropout, Conv2DTranspose
from keras.models import Model
from keras.layers.normalization import BatchNormalization
from keras.engine.topology import Layer
from keras.layers.pooling import MaxPooling2D
from keras.layers.merge import Concatenate
from keras.layers.core import Lambda, Flatten, Dense
from keras.initializers import glorot_uniform,he_uniform
from keras.utils import plot_model,normalize
from keras.regularizers import l2
import random
from keras import backend as K

'''def encoder_layer(num_filters, apply_batchnorm=True,apply_dropout=False, dropout_prob=0.5):
    #initializer = tf.random_normal_initializer(0., 0.02)
    model = Sequential()
    model.add(Conv2D(num_filters,3,strides=1,padding='same',kernel_initializer='he_uniform',use_bias=False))
    model.add(MaxPooling2D(pool_size=(2, 2), strides=None, padding='valid'))

    if apply_batchnorm:
        model.add(BatchNormalization())
    model.add(LeakyReLU())
    if apply_dropout:
        model.add(Dropout(dropout_prob))
    return model

def decoder_layer(num_filters, apply_batchnorm=True,apply_dropout=False, dropout_prob=0.5):
    #initializer = tf.random_normal_initializer(0., 0.02)
    model = Sequential()
    model.add(Conv2DTranspose(num_filters,3,strides=2,padding='same',kernel_initializer='he_uniform',use_bias=False))

    if apply_batchnorm:
        model.add(BatchNormalization())
        model.add(LeakyReLU())
    if apply_dropout:
        model.add(Dropout(dropout_prob))
    return model

def build_EncoderP2E_dep(input_shape):
    inputs = Input(shape=input_shape)
    outputs = inputs
    for i in range(2):
        layer = encoder_layer(256, apply_batchnorm=False, apply_dropout=True, dropout_prob=0.2)
        outputs = layer(outputs)
    for i in range(3):
        layer = encoder_layer(128, apply_dropout=True, dropout_prob=0.2)
        outputs = layer(outputs)
    for i in range(2):
        layer = encoder_layer(64, apply_dropout=True, dropout_prob=0.2)
        outputs = layer(outputs)
    layer = Conv2D(1,3,strides=2,padding='same',kernel_initializer=tf.random_normal_initializer(0., 0.02),
        activation='sigmoid') #Make fully connected
    outputs = layer(outputs)
    return Model(inputs=inputs, outputs=outputs, name = "EncoderP2E")

def build_EncoderD2E_dep(input_shape):
    inputs = Input(shape=input_shape)
    outputs = inputs
    for i in range(2):
        layer = encoder_layer(256, apply_batchnorm=False, apply_dropout=True, dropout_prob=0.2)
        outputs = layer(outputs)
    for i in range(3):
        layer = encoder_layer(128, apply_dropout=True, dropout_prob=0.2)
        outputs = layer(outputs)
    for i in range(2):
        layer = encoder_layer(64, apply_dropout=True, dropout_prob=0.2)
        outputs = layer(outputs)
    layer = Conv2D(1,3,strides=2,padding='same',kernel_initializer=tf.random_normal_initializer(0., 0.02),
        activation='sigmoid') #Make fully connected
    outputs = layer(outputs)
    return Model(inputs=inputs, outputs=outputs,  name = "EncoderD2E")
'''

def build_EncoderD2E(input_shape, embeddingsize=128):
    '''
    Define the neural network to learn image similarity
    Input :
            input_shape : shape of input images
            embeddingsize : vectorsize used to encode our picture
    '''
     # Convolutional Neural Network
    network = Sequential()
    network.add(Conv2D(32, (7,7), activation='relu',
                     input_shape=input_shape,
                     kernel_initializer='he_uniform',
                     kernel_regularizer=l2(2e-4)))
    network.add(MaxPooling2D())
    network.add(Conv2D(64, (3,3), activation='relu', kernel_initializer='he_uniform',
                     kernel_regularizer=l2(2e-4)))
    network.add(MaxPooling2D())
    network.add(Conv2D(128, (3,3), activation='relu', kernel_initializer='he_uniform',
                     kernel_regularizer=l2(2e-4)))
    network.add(Flatten())
    network.add(Dense(128, activation='relu',
                   kernel_regularizer=l2(1e-3),
                   kernel_initializer='he_uniform'))

    network.add(Dense(embeddingsize, activation=None,
                   kernel_regularizer=l2(1e-3),
                   kernel_initializer='he_uniform'))

    #Force the encoding to live on the d-dimentional hypershpere
    network.add(Lambda(lambda x: K.l2_normalize(x,axis=-1)))

    return network

def build_EncoderP2E(input_shape, embeddingsize=128):
    '''
    Define the neural network to learn image similarity
    Input :
            input_shape : shape of input images
            embeddingsize : vectorsize used to encode our picture
    '''
     # Convolutional Neural Network
    network = Sequential()
    network.add(Conv2D(32, (7,7), activation='relu',
                     input_shape=input_shape,
                     kernel_initializer='he_uniform',
                     kernel_regularizer=l2(2e-4)))
    network.add(MaxPooling2D())
    network.add(Conv2D(64, (3,3), activation='relu', kernel_initializer='he_uniform',
                     kernel_regularizer=l2(2e-4)))
    network.add(MaxPooling2D())
    network.add(Conv2D(128, (3,3), activation='relu', kernel_initializer='he_uniform',
                     kernel_regularizer=l2(2e-4)))
    network.add(Flatten())
    network.add(Dense(128, activation='relu',
                   kernel_regularizer=l2(1e-3),
                   kernel_initializer='he_uniform'))

    network.add(Dense(embeddingsize, activation=None,
                   kernel_regularizer=l2(1e-3),
                   kernel_initializer='he_uniform'))

    #Force the encoding to live on the d-dimentional hypershpere
    network.add(Lambda(lambda x: K.l2_normalize(x,axis=-1)))

    return network

def load_minibatch(num=1000, start=-1):
    #Assuming this loads a minibatch of 1000 (picture + doodles + augment pairs) * 3 (examples positive and negative, indicated by y_train)
    # Assumes the in output.hdf5 pairs are already shuffled and randomized. negative examples are created by adding a
    train_dataset = h5py.File('output.hdf5', "r")
    if start < 0:
        start = random.randint(0,18000)
    train_set_P_orig = np.array(train_dataset["image_dataset"][start:start+num],dtype='float32')
    train_set_D_orig = np.array(train_dataset["sketch_dataset"][start:start+num],dtype='float32')

    train_set_P_anchor = train_set_P_orig
    train_set_D_positive = train_set_D_orig
    y_train = np.ones([num,1],dtype='float32')

    #for i in range(1, n):
    train_set_D_negative =  np.array(train_dataset["bad_sketch_dataset"][start:start+num],dtype='float32') # your train set labels
    #train_set_P = tf.concat([train_set_P,train_set_D_positive train_set_P_orig], 0)
    #train_set_D = tf.concat([train_set_D, train_set_D_orig_false], 0)
    #y_train = tf.concat([y_train, np.zeros([num,1],dtype='float32')],axis=0)
    #print("y_train:",y_train.shape)

    triplets = np.zeros((3,train_set_P_orig.shape[0],train_set_P_orig.shape[1],train_set_P_orig.shape[2],train_set_P_orig.shape[3]))
    triplets[0][:,:,:,:] = train_set_P_anchor/255
    triplets[1][:,:,:,:] = train_set_D_positive/255
    triplets[2][:,:,:,:] = train_set_D_negative/255
    #train_set_P_anchor/255, train_set_D_positive/255, train_set_D_negative/255

    return triplets

def load_testset():
    dataset = h5py.File('output.hdf5', 'r')
    test_set_P = np.array(dataset["test_images"],dtype="float32")
    test_set_D = np.array(dataset["test_images"],dtype="float32")
    return test_set_P, test_set_D

class TripletLossLayer(Layer):
    def __init__(self, alpha, **kwargs):
        self.alpha = alpha
        super(TripletLossLayer, self).__init__(**kwargs)

    def triplet_loss(self, inputs):
        anchor, positive, negative = inputs
        p_dist = K.sum(K.square(anchor-positive), axis=-1)
        n_dist = K.sum(K.square(anchor-negative), axis=-1)
        return K.sum(K.maximum(p_dist - n_dist + self.alpha, 0), axis=0)

    def call(self, inputs):
        loss = self.triplet_loss(inputs)
        self.add_loss(loss)
        return loss

def build_model(input_shape,EncoderP2E, EncoderD2E, margin=20):
        anchor_P_input = Input(input_shape, name="anchor_P_input")
        positive_D_input = Input(input_shape, name="positive_D_input")
        negative_D_input = Input(input_shape, name="negative_D_input")

        # Generate the encodings (feature vectors) for the three images
        encoded_P_anchor = EncoderP2E(anchor_P_input)
        encoded_D_pos = EncoderD2E(positive_D_input)
        encoded_D_neg = EncoderD2E(negative_D_input)

        loss_layer = TripletLossLayer(alpha=margin,name='triplet_loss_layer')([encoded_P_anchor,encoded_D_pos,encoded_D_neg])

        # Connect the inputs with the outputs
        network_train = Model(inputs=[anchor_P_input,positive_D_input,negative_D_input],outputs=loss_layer)
        return network_train

def main():
        #noise = tf.random.normal([1,256,256,3])
        batch_size = 1000 #Normally 1000
        batch_num = 1 #Normally 100
        nCP = 10 #Save checkpoint every nCP epochs
        nSM = 100 #Save model every nSM checkpoints
        #n = tf.constant(1.0) #Number of negative examples per positive example
        #CHANGE: Assuing n is always 1train_set_p_orig
        margin = tf.constant(20.0) #triplet margin
        #test_x, test_y = load_minibatch(num=5, start=0)
        img_rows, img_cols, nc = 256, 256, 3
        input_shape = (img_rows, img_cols, nc)

        EncoderD2E = build_EncoderD2E(input_shape)
        EncoderP2E = build_EncoderP2E(input_shape)

        #EncoderD2E.save("./EncoderModel_Saves/EncoderD2E_" + str(5) + ".h5")
        #EncoderP2E.save("./EncoderModel_Saves/EncoderP2E_" + str(5) + ".h5")

        optimizer = Adam(0.0001, beta_1=0.9)

        network_train = build_model(input_shape,EncoderP2E, EncoderD2E, margin)

        network_train.compile(loss=None,optimizer=optimizer)
        network_train.summary()

        network_json = network_train.to_json()
        mode = 'a' if os.path.exists('checkpoints_triplet/model.json') else 'w'
        with open('checkpoints_triplet/model.json', mode) as json_file:
            json_file.write(network_json)

        #checkpoint_dir = "./checkpoints_triplets"
        #checkpoint_prefix = os.path.join(checkpoint_dir, "triplet")
        #checkpoint = tf.train.Checkpoint(optimizer=optimizer, network_train=network_train)
        #manager = tf.train.CheckpointManager(checkpoint, checkpoint_dir, max_to_keep=3)
        #print("checkpoints: ", manager.checkpoints)

        answer = input("Restore from checkpoint? (y/n)")
        if answer == 'y' or answer == 'yes':
            which_epoch = input("which epoch? (int)")
            network_train.load_weights("checkpoints_triplet/weights_" + str(which_epoch) + ".h5")
            print("loaded weights from disk")
            # test_set_P, test_set_D = load_testset()
            test_set_P, test_set_D, test_set_bad_D = load_minibatch(num=100, start=0)

            while True:
                which_image = input("Which test image would you like to see? (int)")
                dist_real = EncoderP2E.predict(test_set_P[int(which_image):int(which_image) + 1]) - EncoderD2E.predict(test_set_D[int(which_image):int(which_image) + 1])
                dist_fake = EncoderP2E.predict(test_set_P[int(which_image):int(which_image) + 1]) - EncoderD2E.predict(test_set_bad_D[int(which_image):int(which_image) + 1])
                print("dist_real: ", np.sum(np.square(dist_real)))
                print("dist_fake: ", np.sum(np.square(dist_fake)))
                plt.imshow(test_set_P[int(which_image)])
                plt.show()
                plt.imshow(test_set_D[int(which_image)])
                plt.show()
                plt.imshow(test_set_bad_D[int(which_image)])
                plt.show()

        elif answer == 'n' or answer == 'no':
            for iteration in range(1000):
                images_per_step = 1000

                #First choose positive and negative examples
                batch = load_minibatch(num=batch_size)
                for i in range(0,batch_size,images_per_step):
                    print("iteration: ", i)
                    print("input shape: ", np.array([batch[0,i:i+images_per_step,:,:,:], batch[1,i:i+images_per_step,:,:,:], batch[2,i:i+images_per_step,:,:,:]]).shape)
                    network_train.fit([batch[0,i:i+images_per_step,:,:,:], batch[1,i:i+images_per_step,:,:,:], batch[2,i:i+images_per_step,:,:,:]], epochs=5)

                    if iteration % nCP == 0:
                        network_train.save_weights("./checkpoints_triplet/weights_" + str(iteration) + ".h5")

                    if iteration % nSM == 0:
                        EncoderD2E.save("./EncoderModel_Saves/EncoderD2E_" + str(iteration) + ".h5")
                        EncoderP2E.save("./EncoderModel_Saves/EncoderP2E_" + str(iteration) + ".h5")

if __name__ == "__main__":
    main()


import bpy
from bpy_extras import view3d_utils
from bpy.props import FloatVectorProperty
import bgl
from math import radians, degrees, pi, cos, sin, copysign
from mathutils import Vector

# TODO
# perspective
# numeric input

persistent_settings = {'active_image': 0,
                       'transform_all': False,
                       'mode': 'TRANSLATE'}

def get_view_orientation_from_quaternion(view_quat):
    """From https://blender.stackexchange.com/a/3428/4979"""
    def r(x):
        return round(x, 3)
    view_rot = view_quat.to_euler()

    orientation_dict = {(0.0, 0.0, 0.0):          'TOP',
                        (r(pi), 0.0, 0.0):        'BOTTOM',
                        (r(pi/2), 0.0, 0.0):      'FRONT',
                        (r(pi/2), 0.0, r(pi)):    'BACK',
                        (r(pi/2), 0.0, r(-pi/2)): 'LEFT',
                        (r(pi/2), 0.0, r(pi/2)):  'RIGHT'}

    return orientation_dict.get(tuple(map(r, view_rot)), 'UNDEFINED')

AXIS_MAP = {
    'TOP':       'xy',
    'BOTTOM':    'xy',
    'FRONT':     'xz',
    'BACK':      'xz',
    'LEFT':      'yz',
    'RIGHT':     'yz',
    'UNDEFINED': 'xy',
}

def space_to_view_vector(view, vector):
    """Transform a 3D world vector to ortho view space."""
    vector = getattr(vector, AXIS_MAP[view])
    if view in {'BACK', 'LEFT'}:
        vector.x *= -1.0
    if view in {'BOTTOM'}:
        vector.y *= -1.0
    return vector

def view_to_region_vector(region, rv3d, view, vector):
    """Transform an ortho view vector to region space."""
    vector_3d = Vector()
    if view in {'BACK', 'LEFT'}:
        vector.x *= -1.0
    if view in {'BOTTOM'}:
        vector.y *= -1.0
    setattr(vector_3d, AXIS_MAP[view], vector)
    vector = view3d_utils.location_3d_to_region_2d(region, rv3d, vector_3d)
    return vector

def draw_callback_px(self, context):
    """From blender's operator_modal_draw.py modal operator template"""
    if self.do_draw:
        bgl.glEnable(bgl.GL_BLEND)
        bgl.glEnable(bgl.GL_LINE_STIPPLE)
        bgl.glColor4f(0.0, 0.0, 0.0, 1.0)
        bgl.glLineWidth(1)

        bgl.glBegin(bgl.GL_LINE_STRIP)
        bgl.glVertex2i(int(self.draw_start.x), int(self.draw_start.y))
        bgl.glVertex2i(int(self.draw_end.x), int(self.draw_end.y))

        bgl.glEnd()

        # restore opengl defaults
        bgl.glLineWidth(1)
        bgl.glDisable(bgl.GL_BLEND)
        bgl.glDisable(bgl.GL_LINE_STIPPLE)
        bgl.glColor4f(0.0, 0.0, 0.0, 1.0)

class BackgroundImageTransform(bpy.types.Operator):
    """Transform background image. Press G to move, R to rotate, S to scale. Mousewheel to select image"""
    bl_idname = "view3d.background_image_transform"
    bl_label = "Transform Background Image"
    bl_options = {'REGISTER', 'UNDO', 'GRAB_CURSOR', 'BLOCKING'}

    @classmethod
    def poll(self, context):
        return (context.space_data.type == 'VIEW_3D'
                and len(context.space_data.background_images))

    def reset(self):
        """Set background images' data to stored values"""
        for i_d in self.background_images:
            image = i_d['image']
            image.offset_x, image.offset_y = i_d['initial_location']
            image.rotation = i_d['initial_rotation']
            image.size = i_d['initial_size']

            image.use_flip_x = i_d['initial_flip_x']
            image.use_flip_y = i_d['initial_flip_y']

    def get_pivot_point(self, context, images):
        """ Get pivot type from space properties"""
        if context.space_data.pivot_point == 'CURSOR':
            pivot_point = (
                space_to_view_vector(
                    self.camera_orientation,
                    context.space_data.cursor_location))
        elif context.space_data.pivot_point in ('BOUNDING_BOX_CENTER',
                                                'MEDIAN_POINT',
                                                'INDIVIDUAL_ORIGINS'):
            pivot_point = Vector((0.0, 0.0))
            for i_d in images:
                pivot_point += i_d['initial_location_view']
            pivot_point /= len(images)
        elif context.space_data.pivot_point == 'ACTIVE_ELEMENT':
            pivot_point = self.background_images[self.active_image]['initial_location_view'].copy()
        return pivot_point

    def update(self, context, event):
        """Update transforms on each call"""
        region = context.region
        rv3d = context.region_data

        mouse_location_3d = (
            view3d_utils.region_2d_to_location_3d(
                region,
                rv3d,
                (event.mouse_region_x, event.mouse_region_y),
                Vector()))
        initial_mouse_location_2d = (
            space_to_view_vector(
                self.camera_orientation,
                self.initial_mouse_location_3d))

        if self.transform_all:
            images = self.background_images
        else:
            images = (self.background_images[self.active_image],)

        pivot_point = self.get_pivot_point(context, images)

        for i_i, i_d in enumerate(images):
            pivot_point_image = pivot_point.copy()
            pivot_point_image.y *= i_d['width'] / i_d['height']

            help_string  = ', Confirm: (Enter/LMB)'
            help_string += ', Cancel: (Esc/RMB)'
            help_string += ', Choose Image: (Mousewheel)'
            help_string += ', Transform All: (A)'
            help_string += ', Move: (G)'
            help_string += ', Rotate: (R)'
            if self.view_perspective == 'ORTHO':
                help_string += ', Scale: (S)'
            help_string += ', Constrain to axis: (X/Y)'

            initial_mouse_vector = initial_mouse_location_2d - pivot_point
            current_mouse_vector = space_to_view_vector(
                self.camera_orientation,
                mouse_location_3d) - pivot_point

            if self.mode == 'TRANSLATE':
                # Get mouse differential in view space
                offset = space_to_view_vector(
                    self.camera_orientation,
                    (mouse_location_3d - self.initial_mouse_location_3d))

                # Offset is based a factor of width or height
                offset.y *= i_d['width'] / i_d['height']

                # Snap mode
                if event.ctrl:
                    offset.x //= 1
                    offset.y //= 1
                # Precision mode
                if event.shift:
                    offset *= 0.1

                # Axis constraint
                if self.constrain_x:
                    offset.y = 0.0
                if self.constrain_y:
                    offset.x = 0.0

                # Apply translation to background image
                i_d['image'].offset_x, i_d['image'].offset_y = (
                    i_d['initial_location'] + offset)
                context.area.header_text_set(
                    "Dx: %.4f Dy: %.4f" % tuple(offset) + help_string)

            elif self.mode == 'ROTATE':
                # Get angles in view space
                rotation_offset = initial_mouse_vector.angle_signed(
                    current_mouse_vector)

                # Add whole turns to avoid precision mode popping
                if (self.previous_rotation_offset < 0
                        and rotation_offset > 0
                        and abs(rotation_offset) > pi/2):
                    self.revolutions -= 1
                elif (self.previous_rotation_offset > 0
                        and rotation_offset < 0
                        and abs(rotation_offset) > pi/2):
                    self.revolutions += 1

                self.previous_rotation_offset = rotation_offset
                rotation_offset += self.revolutions * 2*pi

                # Snap mode
                if event.ctrl:
                    rotation_offset = (
                        radians((degrees(rotation_offset) // 5) * 5))
                # Precision mode
                if event.shift:
                    rotation_offset *= 0.1

                # Translate image in a circular path around 3D cursor
                if ((context.space_data.pivot_point in (
                        'CURSOR', 'BOUNDING_BOX_CENTER',
                        'MEDIAN_POINT', 'ACTIVE_ELEMENT')
                        or (context.space_data.pivot_point == 'ACTIVE_ELEMENT'
                            and i_i != self.active_image))
                        and (i_d['initial_location_view']
                             - pivot_point).length_squared != 0):
                    initial_angle = (
                        i_d['initial_location_view']
                        - pivot_point).angle_signed(Vector((1.0, 0.0)))
                    rotation_distance = (
                        i_d['initial_location_view']
                        - pivot_point).length
                    offset = pivot_point_image
                    offset.x += (
                        cos(initial_angle - rotation_offset)
                        * rotation_distance)
                    offset.y += (
                        sin(initial_angle - rotation_offset)
                        * rotation_distance
                        * i_d['width']
                        / i_d['height'])
                    i_d['image'].offset_x, i_d['image'].offset_y = offset

                # Apply rotation to background image
                i_d['image'].rotation = (
                    i_d['initial_rotation'] + rotation_offset)
                context.area.header_text_set(
                    "Rot: %.2f°" % degrees(rotation_offset) + help_string)

            elif self.mode == 'SCALE':
                scale_offset = ((
                    space_to_view_vector(
                        self.camera_orientation, mouse_location_3d)
                    - pivot_point).length
                    / (initial_mouse_location_2d - pivot_point).length)

                # Snap mode
                if event.ctrl:
                    scale_offset = ((scale_offset * 10) // 1) / 10
                # Precision mode
                if event.shift:
                    scale_offset = scale_offset * 0.5 + 0.5

                # Detect flip (mouse has crossed line perpendicular
                # to the pivot-initial mouse line)
                mouse_cross_product = (
                    initial_mouse_vector * current_mouse_vector)
                # Cross products have the different signs
                # From https://stackoverflow.com/a/1986776/4561348
                if (copysign(1, mouse_cross_product)
                        != copysign(1, self.previous_mouse_cp)):
                    i_d['image'].use_flip_x = not i_d['image'].use_flip_x
                    i_d['image'].use_flip_y = not i_d['image'].use_flip_y
                    self.previous_mouse_cp = mouse_cross_product

                flip = -1.0 if mouse_cross_product < 0 else 1.0

                # Translate image along a line
                # between 3D cursor and original location
                if (context.space_data.pivot_point in ('CURSOR',
                                                       'BOUNDING_BOX_CENTER',
                                                       'MEDIAN_POINT')
                        or (context.space_data.pivot_point == 'ACTIVE_ELEMENT'
                            and i_i != self.active_image)):
                    offset = (
                        i_d['initial_location_view']
                        + (pivot_point - i_d['initial_location_view'])
                        * (1-scale_offset * flip))
                    offset.y *= i_d['width'] / i_d['height']
                    i_d['image'].offset_x, i_d['image'].offset_y = offset

                # Apply scale to background image
                i_d['image'].size = i_d['initial_size'] * scale_offset
                context.area.header_text_set(
                    "Scale: %.4f" % scale_offset + help_string)

        # Draw line from the mouse cursor
        pivot_point_region = view_to_region_vector(
            region, rv3d, self.camera_orientation, pivot_point)
        self.draw_start = Vector((event.mouse_region_x, event.mouse_region_y))
        # ...to the pivot point (image center or 3D cursor)...
        self.draw_end = pivot_point_region

    def modal(self, context, event):
        context.area.tag_redraw()
        if event.type in (
                'MOUSEMOVE',
                'LEFT_CTRL', 'RIGHT_CTRL',
                'LEFT_SHIFT', 'RIGHT_SHIFT'):
            self.update(context, event)

        # Axis constraint events
        elif event.type == 'X' and event.value == 'PRESS':
            self.constrain_y = False
            self.constrain_x = not self.constrain_x
            self.update(context, event)
        elif event.type == 'Y' and event.value == 'PRESS':
            self.constrain_x = False
            self.constrain_y = not self.constrain_y
            self.update(context, event)

        # Mode switch events
        elif event.type == 'R' and event.value == 'PRESS':
            self.mode = 'ROTATE'
            self.reset()
            self.update(context, event)
            self.do_draw = True
        elif event.type == 'G' and event.value == 'PRESS':
            self.mode = 'TRANSLATE'
            self.reset()
            self.update(context, event)
            # Do not draw stitched line in translation mode
            self.do_draw = False
        elif (
                event.type == 'S'
                and event.value == 'PRESS'
                and self.view_perspective == 'ORTHO'):
            self.mode = 'SCALE'
            self.reset()
            self.update(context, event)
            self.do_draw = True

        # Image selection events : iterate through image list
        elif event.type == 'WHEELUPMOUSE':
            self.reset()
            self.active_image += 1
            if self.active_image > len(self.valid_images) - 1:
                self.active_image = 0
            self.update(context, event)
        elif event.type == 'WHEELDOWNMOUSE':
            self.reset()
            previous = self.active_image
            self.active_image -= 1
            if previous == 0:
                self.active_image = len(self.valid_images) - 1
            self.update(context, event)
        # Toggle transforming all images
        elif event.type == 'A' and event.value == 'PRESS':
            self.transform_all = not self.transform_all
            self.reset()
            self.update(context, event)

        # Confirm and apply
        elif event.type in {'LEFTMOUSE', 'RET'}:
            context.area.header_text_set()
            bpy.types.SpaceView3D.draw_handler_remove(self._handle, 'WINDOW')
            persistent_settings['active_image'] = self.active_image
            persistent_settings['transform_all'] = self.transform_all
            persistent_settings['mode'] = self.mode
            return {'FINISHED'}

        # Cancel and reset
        elif event.type in {'RIGHTMOUSE', 'ESC'}:
            self.reset()
            context.area.header_text_set()
            bpy.types.SpaceView3D.draw_handler_remove(self._handle, 'WINDOW')
            return {'CANCELLED'}

        return {'RUNNING_MODAL'}

    def init_images(self, background_images):
        self.background_images = []
        for bgi in background_images:
            i_d = {}
            i_d['image'] = bgi
            i_d['image_orientation'] = bgi.view_axis
            i_d['width'], i_d['height'] = bgi.image.size
            i_d['initial_flip_x'] = bgi.use_flip_x
            i_d['initial_flip_y'] = bgi.use_flip_y
            i_d['initial_location'] = Vector((bgi.offset_x, bgi.offset_y))
            i_d['initial_location_view'] = Vector((bgi.offset_x, bgi.offset_y))
            i_d['initial_location_view'].y *= i_d['height'] / i_d['width']
            i_d['initial_rotation'] = bgi.rotation
            i_d['initial_size'] = bgi.size
            self.background_images.append(i_d)

    def invoke(self, context, event):
        rv3d = context.region_data
        region = context.region

        self.mode = persistent_settings['mode']
        self.transform_all = persistent_settings['transform_all']
        self.constrain_x = False
        self.constrain_y = False

        if rv3d.view_perspective == 'PERSP':
            self.report({'WARNING'}, 'Perspective camera unsupported.')
            return {'CANCELLED'}

        self.view_perspective = rv3d.view_perspective
        self.camera_orientation = (
            get_view_orientation_from_quaternion(rv3d.view_rotation))
        self.region_offset_x = 0
        self.region_offset_y = 0

        self.initial_mouse = Vector((
            event.mouse_region_x,
            event.mouse_region_y))
        self.initial_mouse_location_3d = (
            view3d_utils.region_2d_to_location_3d(
                region, rv3d, self.initial_mouse, Vector()))

        self.valid_images = []
        self.previous_rotation_offset = 0.0
        self.revolutions = 0

        self.previous_mouse_cp = 1.0

        # Get currently visible images
        for background_image in context.space_data.background_images:
            image_orientation = background_image.view_axis
            if (background_image.show_background_image
                and background_image.image is not None
                and (rv3d.view_perspective == 'CAMERA'
                     and image_orientation in {'CAMERA', 'ALL'}
                     or rv3d.view_perspective == 'ORTHO'
                     and self.camera_orientation != 'UNDEFINED'
                     and image_orientation in {self.camera_orientation, 'ALL'}
                     )):
                self.valid_images.append(background_image)

        if len(self.valid_images):
            self.active_image = min(
                persistent_settings['active_image'],
                len(self.valid_images)-1)
            self.init_images(self.valid_images)
            context.window_manager.modal_handler_add(self)
            args = (self, context)
            self.do_draw = self.mode in ('ROTATE', 'SCALE')
            self._handle = bpy.types.SpaceView3D.draw_handler_add(
                draw_callback_px, args, 'WINDOW', 'POST_PIXEL')
            return {'RUNNING_MODAL'}
        else:
            self.report({'WARNING'}, 'No background image found.')
            return {'CANCELLED'}

# REGISTRY #
def register():
    bpy.utils.register_module(__name__)

def unregister():
    bpy.utils.unregister_module(__name__)

if __name__ == "__main__":
    register()


def datosenlista():
    archivoreto = open("agenda.txt", "r")
    lineas = archivoreto.readlines()
    listaordenada = []
    salida = []
    for linea in lineas:
        salida.append(linea.replace("\n", ""))
        listaordenada = [salida[i:i + 3] for i in range(0, len(salida), 3)]
    return listaordenada

archivoreto = open("agenda.txt")
archivoreto.close()

while True:
    print("menu princial")
    print("1. Ver listado")
    print("2. Ver listado filtrado")
    print("3. Agregar beneficiario ")
    print("4. Buscar beneficiario")
    print("5. Borrar beneficiario")
    print("6. Salir)")
    entrada = int(input())
    if entrada==1:
        datoss=datosenlista()
        for i  in datoss:
            for k in i:
                print(k)
        continue

    elif entrada==2:

        letra=input()
        nueva=datosenlista()
        resultados = []
        for i in nueva:
            for k in i:
                if k[0].lower().startswith(letra):
                    resultados+=i

        for g in resultados:
            print(g)

        continue

    elif entrada == 3:
        orden=datosenlista()
        # despues de que tenga la lista ordenada, se realiza la comparacion de las cedula
        # si estan repetidas, no se puede escribir el nuevo usiario

        print("ingrese un nuevo usuario")

        cuenta = 0
        archivoreto = open("agenda.txt", "a")
        while True:
            nombre = input().lower()
            cedula = input()
            numero = input()
            for i in datosenlista():
                for k in i:

                    if k == cedula:
                        cuenta = 1
                        break

                if cuenta == 1:
                    break

            if cuenta == 1:
                continue
            else:
                break

        archivoreto.writelines(nombre + "\n")
        archivoreto.writelines(cedula + "\n")
        archivoreto.writelines(numero + "\n")
        print("usuario ingresado con exito")
        archivoreto.close()

    elif entrada == 4:
        buscar=input().lower()
        #buscar usuario con su nombre
        for i in datosenlista() :
            for k in i:
                if k==buscar:
                    print(i[1])
                    print(i[2])
        archivoreto.close()

    elif entrada == 5:

        aaa=datosenlista()

        cel = input()

        for i in aaa:
            for k in i:
                if k==cel:
                    aaa.remove(i)

        archivoreto=open("agenda.txt","w")

        for i in aaa:
            for k in i:
                archivoreto.write(str(k)+"\n")
        archivoreto.close()

    elif entrada == 6:

        break

    else:

        continue


import math
# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next

# Better
class Solution:
    def middleNode(self, head):
        temp_node = head
        count = 0
        while temp_node != None:
            count += 1
            temp_node = temp_node.next
        count = (count/2)+1 if count % 2 == 0 else count / 2
        count = math.ceil(count)
        i = 0
        while head != None:
            i += 1
            if i == count:
                return head
            head = head.next

class SolutionOptimal:
    def middleNode(self, head):
        slow_tortoise = fast_tortoise = head
        while fast_tortoise.next != None and fast_tortoise != None:
            fast_tortoise.next = fast_tortoise.next.next
            slow_tortoise = slow_tortoise.next

sol = Solution()
sol.middleNode(head)


# Bind address of the server
# HOST = "127.0.0.1"
# PORT = 3000

# Extended log output, but slower
DEBUG = False
VERBOSE = DEBUG
AUTO_RELOAD = DEBUG

# Required to encrypt or sign sessions, cookies, tokens, etc.
# SECRET = "!!!<<<CHANGEME>>>!!!"

# Connection to the database
# POSTGRES_URL = "postgresql+asyncpg://user:pass@host/dbname"
# POSTGRES_POOL_SIZE = 20
# POSTGRES_MAX_OVERFLOW = 2 * POSTGRES_POOL_SIZE

# URL to the keycloak realm, as reachable by the API service. This is not
# necessarily its publicly reachable URL, keycloak advertises that iself.
# KEYCLOAK_URL = "http://localhost:1234/auth/realms/obs/"

# Auth client credentials
# KEYCLOAK_CLIENT_ID = "portal"
# KEYCLOAK_CLIENT_SECRET = "00000000-0000-0000-0000-000000000000"

# Whether the API should run the worker loop, or a dedicated worker is used
# DEDICATED_WORKER = True

# The root of the frontend. Needed for redirecting after login, and for CORS.
# Set to None if frontend is served by the API.
FRONTEND_URL = None
FRONTEND_HTTPS = True

# Where to find the compiled frontend assets (must include index.html), or None
# to disable serving the frontend.
FRONTEND_DIR = "../frontend/build/"

# Can be an object or a JSON string
FRONTEND_CONFIG = {
    "imprintUrl": "https://example.com/imprint",
    "privacyPolicyUrl": "https://example.com/privacy",
    "mapHome": {"zoom": 6, "longitude": 10.2, "latitude": 51.3},
    "banner": {"text": "This is a test installation.", "style": "warning"},
}

# If the API should serve generated tiles, this is the path where the tiles are
# built. This is an experimental option and probably very inefficient, a proper
# tileserver should be prefered. Set to None to disable.
TILES_FILE = None

# Path overrides:
# API_ROOT_DIR = "??" # default: api/ inside repository
# DATA_DIR = "??" # default: $API_ROOT_DIR/..
# PROCESSING_DIR = "??" # default: DATA_DIR/processing
# PROCESSING_OUTPUT_DIR = "??"  # default: DATA_DIR/processing-output
# TRACKS_DIR = "??" # default: DATA_DIR/tracks
# OBS_FACE_CACHE_DIR = "??" # default: DATA_DIR/obs-face-cache

# Additional allowed origins for CORS headers. The FRONTEND_URL is included by
# default. Python list, or whitespace separated string.
ADDITIONAL_CORS_ORIGINS = None

# vim: set ft=python :


from openerp import models, api, _
from openerp.exceptions import Warning

class account_analytic_account_amendment(models.TransientModel):
    _name = "account.analytic.account.amendment"
    _description = "Amendment for many contracts"

    @api.multi
    def make_amendment(self):
        """
        Action performed after a selection of many contracts.
        """
        contract_obj = self.env['account.analytic.account']
        contract_ids = self._context.get('active_ids')
        contracts = contract_obj.search([
                                         ('state', '=', 'open'),
                                         ('id', 'in', contract_ids),
                                         ])
        if contracts:
            contracts.make_amendment()
        else:
            raise Warning(_("There's no 'open' contract contract "
                            "in this selection. Please select 'open' "
                            "contracts to be able to set them to 'amendment'"))

# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:


# alsRepeaterLauncher

from alsRepeater import AlsRepeater
from als import ALS
import json

from input.heart.heart_import import get_heart_data
from input.ads.ads_import import get_ads_data
from input.voice.voice_import import get_voice_data

def initialize_record():
    default_values = ALS.__init__.__defaults__
    argument_names = ALS.__init__.__code__.co_varnames[1:]  # [1:] to remove 'self' as input argument

    non_default_values = [None] * (len(argument_names) - len(default_values))

    values = non_default_values.copy()
    values.extend(default_values)

    record = {}

    record['data_str'] = None
    record['input_dict'] = dict(zip(argument_names, values))
    record['reps'] = 5
    record['n_jobs'] = 5
    record['argument_value_dict'] = {}
    record['results'] = []

    return record

def validate_record(record):
    try:
        argument_value_dict = record['argument_value_dict']

        if len(argument_value_dict) != 3:
            print(
                'ERROR: self.argument_value_dict must have 3 keys. To only vary along 1 or 2 axis, include a key with value as a list with only one value')
            return False

        return True
    except:
        return False

class AlsRepeaterLauncher:

    def __init__(self, record):
        if validate_record(record):
            self.record = record
            data_str = self.record['data_str']
            self.record['input_dict']['data_str'] = data_str

            if data_str == 'heart':
                self.record['input_dict']['unsplit_data'] = get_heart_data()
                self.record['input_dict']['n_classes'] = 2  # n classes used to calculate entropy correctly
            elif data_str == 'ads':
                self.record['input_dict']['unsplit_data'] = get_ads_data(n_components=1000)
                self.record['input_dict']['n_classes'] = 2
            elif data_str == 'voice':
                self.record['input_dict']['unsplit_data'] = get_voice_data()
                self.record['input_dict']['n_classes'] = 26
            else:
                print('ERROR data_str NOT VALID')
        else:
            print('RECORD NOT VALID')

    def run_3_dimensional_varied_reps(self):
        """
        :return: 4 dimensional dict,
            first key = first argument to vary on + argument value
                second key = second argument to very on + argument value
                    third key = third argument to very on + argument value
                        fourth key = performance metric (e.g. accuracy)
                            value = average of performance metric per learning step across reps
        """
        argument_value_dict = self.record['argument_value_dict']
        input_dict = self.record['input_dict']
        reps = self.record['reps']
        n_jobs = self.record['n_jobs']

        argument_strs = list(argument_value_dict.keys())

        results = {} # initiate output 3D dict
        repeater_number = 0

        # To print progress percentages later:
        n_als_to_perform = reps
        for key in argument_value_dict:
            n_als_to_perform = n_als_to_perform * len(argument_value_dict[key])
        n_als_performed = 0

        for i in argument_value_dict[argument_strs[0]]:  # iterate over argument values of first argument string
            input_dict_altered = input_dict.copy()
            input_dict_altered[argument_strs[0]] = i  # alter argument1 to have value i

            result_key1 = argument_strs[0] + '_' + str(i)
            results[result_key1] = {}  # initiate sub dictionary
            for j in argument_value_dict[argument_strs[1]]:  # iterate over argument values of second argument string
                input_dict_altered[argument_strs[1]] = j  # alter argument2 to have value j

                result_key2 = argument_strs[1] + '_' + str(j)
                results[result_key1][result_key2] = {}  # initiate sub sub dictionary
                for k in argument_value_dict[argument_strs[2]]:
                    input_dict_altered[argument_strs[2]] = k  # alter argument3 to have value k

                    # run reps with the two arguments having value i and j
                    alsr = AlsRepeater(input_dict_altered, id = repeater_number)
                    repeater_number += 1

                    alsr.run(n_reps=reps, n_jobs=n_jobs,  n_als_to_perform=n_als_to_perform, n_als_performed=n_als_performed)
                    n_als_performed = n_als_performed + reps

                    result_key3 = argument_strs[2] + '_' + str(k)
                    results[result_key1][result_key2][result_key3] = alsr.get_mean_results()

                    print('#### COMPLETED REPS: ' + result_key1 + ' | ' + result_key2 + ' | ' + result_key3 + '####')

        self.record['results'] = results

        # delete unsplit data from record that will be saved
        del self.record['input_dict']['unsplit_data']
        return self.record

    # NOT IN USE:
    # def __run_varied_reps(self, argument_str, argument_value_range):
    #    """
    #    :param argument_str: str of argument which value to vary
    #    :param argument_value_range: list of values to run experiments with
    #    :return: dict with keys as argument_value and value as mean_result dict
    #    """
    #    results = {}
    #    for argument_value in argument_value_range:
    #        alsr = AlsRepeater(self.input_dict)
    #        alsr.input_dict[argument_str] = argument_value
    #        alsr.run(n_reps=self.reps)
    #        result = alsr.get_mean_results()
    #
    #        results[argument_value] = result
    #    return results


"""
Code for linting modules and subworkflows in the nf-core/modules repository and
in nf-core pipelines
"""

from __future__ import print_function

import logging
import operator
import os
from pathlib import Path

import rich
from rich.markdown import Markdown
from rich.table import Table

import nf_core.modules.modules_utils
import nf_core.utils
from nf_core.components.components_command import ComponentCommand
from nf_core.components.nfcore_component import NFCoreComponent
from nf_core.lint_utils import console
from nf_core.modules.modules_json import ModulesJson
from nf_core.utils import plural_s as _s

log = logging.getLogger(__name__)

class LintException(Exception):
    """Exception raised when there was an error with module or subworkflow linting"""

    pass

class LintResult:
    """An object to hold the results of a lint test"""

    def __init__(self, component, lint_test, message, file_path):
        self.component = component
        self.lint_test = lint_test
        self.message = message
        self.file_path = file_path
        self.component_name = component.component_name

class ComponentLint(ComponentCommand):
    """
    An object for linting modules and subworkflows either in a clone of the 'nf-core/modules'
    repository or in any nf-core pipeline directory
    """

    def __init__(
        self,
        component_type,
        dir,
        fail_warned=False,
        remote_url=None,
        branch=None,
        no_pull=False,
        registry=None,
        hide_progress=False,
    ):
        super().__init__(
            component_type,
            dir=dir,
            remote_url=remote_url,
            branch=branch,
            no_pull=no_pull,
            hide_progress=hide_progress,
        )

        self.fail_warned = fail_warned
        self.passed = []
        self.warned = []
        self.failed = []
        if self.component_type == "modules":
            self.lint_tests = self.get_all_module_lint_tests(self.repo_type == "pipeline")
        else:
            self.lint_tests = self.get_all_subworkflow_lint_tests(self.repo_type == "pipeline")

        if self.repo_type == "pipeline":
            modules_json = ModulesJson(self.dir)
            modules_json.check_up_to_date()
            self.all_remote_components = []
            for repo_url, components in modules_json.get_all_components(self.component_type).items():
                if remote_url is not None and remote_url != repo_url:
                    continue
                for org, comp in components:
                    self.all_remote_components.append(
                        NFCoreComponent(
                            comp,
                            repo_url,
                            Path(self.dir, self.component_type, org, comp),
                            self.repo_type,
                            Path(self.dir),
                            self.component_type,
                        )
                    )
            if not self.all_remote_components:
                raise LookupError(
                    f"No {self.component_type} from {self.modules_repo.remote_url} installed in pipeline."
                )
            local_component_dir = Path(self.dir, self.component_type, "local")
            self.all_local_components = []
            if local_component_dir.exists():
                self.all_local_components = [
                    NFCoreComponent(
                        comp,
                        None,
                        Path(local_component_dir, comp),
                        self.repo_type,
                        Path(self.dir),
                        self.component_type,
                        remote_component=False,
                    )
                    for comp in self.get_local_components()
                ]
            self.config = nf_core.utils.fetch_wf_config(self.dir, cache_config=True)
        else:
            component_dir = Path(
                self.dir,
                self.default_modules_path if self.component_type == "modules" else self.default_subworkflows_path,
            )
            self.all_remote_components = [
                NFCoreComponent(m, None, component_dir / m, self.repo_type, Path(self.dir), self.component_type)
                for m in self.get_components_clone_modules()
            ]
            self.all_local_components = []
            if not self.all_remote_components:
                raise LookupError(f"No {self.component_type} in '{self.component_type}' directory")

            # This could be better, perhaps glob for all nextflow.config files in?
            self.config = nf_core.utils.fetch_wf_config(Path(self.dir).joinpath("tests", "config"), cache_config=True)

        if registry is None:
            self.registry = self.config.get("docker.registry", "quay.io")
        else:
            self.registry = registry
        log.debug(f"Registry set to {self.registry}")

        self.lint_config = None
        self.modules_json = None

    @staticmethod
    def get_all_module_lint_tests(is_pipeline):
        if is_pipeline:
            return [
                "module_patch",
                "module_version",
                "main_nf",
                "meta_yml",
                "module_todos",
                "module_deprecations",
                "module_changes",
            ]
        else:
            return ["main_nf", "meta_yml", "module_todos", "module_deprecations", "module_tests"]

    @staticmethod
    def get_all_subworkflow_lint_tests(is_pipeline):
        if is_pipeline:
            return ["main_nf", "meta_yml", "subworkflow_changes", "subworkflow_todos", "subworkflow_version"]
        else:
            return ["main_nf", "meta_yml", "subworkflow_todos", "subworkflow_tests"]

    def set_up_pipeline_files(self):
        self.load_lint_config()
        self.modules_json = ModulesJson(self.dir)
        self.modules_json.load()

        # Only continue if a lint config has been loaded
        if self.lint_config:
            for test_name in self.lint_tests:
                if self.lint_config.get(test_name, {}) is False:
                    log.info(f"Ignoring lint test: {test_name}")
                    self.lint_tests.remove(test_name)

    def filter_tests_by_key(self, key):
        """Filters the tests by the supplied key"""
        # Check that supplied test keys exist
        bad_keys = [k for k in key if k not in self.lint_tests]
        if len(bad_keys) > 0:
            raise AssertionError(
                "Test name{} not recognised: '{}'".format(
                    _s(bad_keys),
                    "', '".join(bad_keys),
                )
            )

        # If -k supplied, only run these tests
        self.lint_tests = [k for k in self.lint_tests if k in key]

    def _print_results(self, show_passed=False, sort_by="test"):
        """Print linting results to the command line.

        Uses the ``rich`` library to print a set of formatted tables to the command line
        summarising the linting results.
        """

        log.debug("Printing final results")

        sort_order = ["lint_test", "component_name", "message"]
        if sort_by == "module" or sort_by == "subworkflow":
            sort_order = ["component_name", "lint_test", "message"]

        # Sort the results
        self.passed.sort(key=operator.attrgetter(*sort_order))
        self.warned.sort(key=operator.attrgetter(*sort_order))
        self.failed.sort(key=operator.attrgetter(*sort_order))

        # Find maximum module name length
        max_name_len = 40
        for tests in [self.passed, self.warned, self.failed]:
            try:
                for lint_result in tests:
                    max_name_len = max(len(lint_result.component_name), max_name_len)
            except:
                pass

        # Helper function to format test links nicely
        def format_result(test_results, table):
            """
            Given an list of error message IDs and the message texts, return a nicely formatted
            string for the terminal with appropriate ASCII colours.
            """
            # TODO: Row styles don't work current as table-level style overrides.
            # Leaving it here in case there is a future fix
            last_modname = False
            even_row = False
            for lint_result in test_results:
                if last_modname and lint_result.component_name != last_modname:
                    even_row = not even_row
                last_modname = lint_result.component_name
                table.add_row(
                    Markdown(f"{lint_result.component_name}"),
                    os.path.relpath(lint_result.file_path, self.dir),
                    Markdown(f"{lint_result.message}"),
                    style="dim" if even_row else None,
                )
            return table

        # Print blank line for spacing
        console.print("")

        # Table of passed tests
        if len(self.passed) > 0 and show_passed:
            table = Table(style="green", box=rich.box.MINIMAL, pad_edge=False, border_style="dim")
            table.add_column(f"{self.component_type[:-1].title()} name", width=max_name_len)
            table.add_column("File path")
            table.add_column("Test message")
            table = format_result(self.passed, table)
            console.print(
                rich.panel.Panel(
                    table,
                    title=rf"[bold][✔] {len(self.passed)} {self.component_type[:-1].title()} Test{_s(self.passed)} Passed",
                    title_align="left",
                    style="green",
                    padding=0,
                )
            )

        # Table of warning tests
        if len(self.warned) > 0:
            table = Table(style="yellow", box=rich.box.MINIMAL, pad_edge=False, border_style="dim")
            table.add_column(f"{self.component_type[:-1].title()} name", width=max_name_len)
            table.add_column("File path")
            table.add_column("Test message")
            table = format_result(self.warned, table)
            console.print(
                rich.panel.Panel(
                    table,
                    title=rf"[bold][!] {len(self.warned)} {self.component_type[:-1].title()} Test Warning{_s(self.warned)}",
                    title_align="left",
                    style="yellow",
                    padding=0,
                )
            )

        # Table of failing tests
        if len(self.failed) > 0:
            table = Table(style="red", box=rich.box.MINIMAL, pad_edge=False, border_style="dim")
            table.add_column(f"{self.component_type[:-1].title()} name", width=max_name_len)
            table.add_column("File path")
            table.add_column("Test message")
            table = format_result(self.failed, table)
            console.print(
                rich.panel.Panel(
                    table,
                    title=rf"[bold][✗] {len(self.failed)} {self.component_type[:-1].title()} Test{_s(self.failed)} Failed",
                    title_align="left",
                    style="red",
                    padding=0,
                )
            )

    def print_summary(self):
        """Print a summary table to the console."""
        table = Table(box=rich.box.ROUNDED)
        table.add_column("[bold green]LINT RESULTS SUMMARY", no_wrap=True)
        table.add_row(
            rf"[✔] {len(self.passed):>3} Test{_s(self.passed)} Passed",
            style="green",
        )
        table.add_row(rf"[!] {len(self.warned):>3} Test Warning{_s(self.warned)}", style="yellow")
        table.add_row(rf"[✗] {len(self.failed):>3} Test{_s(self.failed)} Failed", style="red")
        console.print(table)


from odoo import models
from odoo.addons.component.core import Component
import logging

_logger = logging.getLogger(__name__)

class VersionKeyModel(models.TransientModel):
    # In actual connector version is mandatory use a model
    _name = '_prestashop.version.key'

class VersionKey(Component):
    _name = '_prestashop.version.key'
    _apply_on = '_prestashop.version.key'
    _usage = 'prestashop.version.key'

    keys = {
        'messages': 'customer_messages',
    }

    def get_key(self, key):
        output_key = self.keys.get(key) or key
        _logger.info("Output key changed from %s to %s" % (key, output_key))
        return output_key

class VersionKey1609(Component):
    _name = '_prestashop.version.key.1.6.0.9'
    _inherit = '_prestashop.version.key'
    _usage = 'prestashop.version.key.1.6.0.9'

    keys = {
        'product_option_value': 'product_option_values',
        'category': 'categories',
        'order_slip': 'order_slips',
        'order_slip_detail': 'order_slip_details',
        'group': 'groups',
        'order_row': 'order_rows',
        'tax': 'taxes',
        'image': 'images',
        'combinations': 'combinations',
        'tag': 'tags',
        'manufacturers': 'manufacturers',
    }

class VersionKey1612(Component):
    _name = '_prestashop.version.key.1.6.1.2'
    _inherit = '_prestashop.version.key'
    _usage = 'prestashop.version.key.1.6.1.2'

    # keys checked in 1.6.1.9:
    # * customer_messages
    # * order_slip
    # * order_slip_detail

    keys = {
        'product_option_value': 'product_option_value',
        'category': 'category',
        'image': 'image',
        'order_slip': 'order_slip',
        'order_slip_detail': 'order_slip_detail',
        'group': 'group',
        'order_row': 'order_row',
        'tax': 'taxes',
        'combinations': 'combination',
        'product_features': 'product_feature',
        'tag': 'tag',
        'messages': 'customer_messages',
        'manufacturers': 'manufacturers',
    }

class VersionKey1619(Component):
    _name = '_prestashop.version.key.1.6.1.9'
    _inherit = '_prestashop.version.key'
    _usage = 'prestashop.version.key.1.6.1.9'

    # keys checked in 1.6.1.9:
    # * customer_messages
    # * order_slip
    # * order_slip_detail

    keys = {
        'product_option_value': 'product_option_value',
        'category': 'category',
        'image': 'image',
        'order_slip': 'order_slip',
        'order_slip_detail': 'order_slip_detail',
        'group': 'group',
        'order_row': 'order_row',
        'tax': 'tax',
        'combinations': 'combination',
        'product_features': 'product_feature',
        'tag': 'tag',
        'messages': 'customer_messages',
        'manufacturers': 'manufacturers',
    }

class VersionKey1750(Component):
    _name = '_prestashop.version.key.1.7.5.0'
    _inherit = '_prestashop.version.key'
    _usage = 'prestashop.version.key.1.7.5.0'

    # TODO: Don't forget to adpt your PS server due to this regression :
    # https://www.prestashop.com/forums/topic/890277-r%C3%A9cup%C3%A9rer-le-d%C3%A9tail-des-r%C3%A9ductions-sur-commande-via-lapi/?tab=comments#comment-2955986
    keys = {
        'product_option_value': 'product_option_value',
        'category': 'categories',
        'image': 'image',
        'order_slip': 'order_slip',
        'order_slip_detail': 'order_slip_details',
        'order_row': 'order_row',
        'group': 'groups',
        'tax': 'tax',
        'product_features': 'product_features',
        'combinations': 'combination',
        'tag': 'tags',
        'messages': 'customer_messages',
        'manufacturers': 'manufacturers',
    }


from typing import List

import numpy as np

from Clustering.Centroid import Point, Centroid

def smart_centroids(points: List[Point], n_centroids: int):
    centroids = []

    rand = np.random.randint(0, np.shape(points)[0])
    next_point = points[rand]

    for i in range(n_centroids):
        new_centroid = Centroid.from_point(next_point)
        centroids.append(new_centroid)

        current_distance = next_point.distance(new_centroid)

        for point in points:
            distance = new_centroid.distance(point)
            if distance > current_distance:
                next_point = point
                current_distance = distance

    return centroids


from math import sqrt
from vector import VectorObject2D, obj as v

class Transform():
  def __init__(
    self,
    position: VectorObject2D,
    scale: VectorObject2D
  ) -> None:
    self.position: VectorObject2D = position
    self.scale: VectorObject2D = scale
    pass

  def distance_to(self, other: 'Transform') -> float:
    dx: float = float(abs(other.position.x - self.position.x))
    dy: float = float(abs(other.position.y - self.position.y))

    sum_squares = dx**2 + dy**2

    return sqrt(sum_squares)

  def is_overalpping(self, other: 'Transform') -> bool:
    parent_scale: VectorObject2D = self.scale
    other_scale: VectorObject2D = other.scale

    distance_x: float = float(abs(self.position.x - other.position.x))
    distance_y: float = float(abs(self.position.y - other.position.y))

    is_overlapping_x: bool = distance_x <= float(parent_scale.x / 2) + float(other_scale.x / 2)
    is_overlapping_y: bool = distance_y <= float(parent_scale.y / 2) + float(other_scale.y / 2)

    return is_overlapping_x and is_overlapping_y

  def move(self, direction: str, amount: float) -> None:
    if direction == "up":
      self.position.y += amount
    elif direction == "down":
      self.position.y -= amount
    elif direction == "left":
      self.position.x -= amount
    elif direction == "right":
      self.position.x += amount

  def relocate(self, x: float, y: float) -> None:
    self.position.x = x
    self.position.y = y

  def rescale(self, x: float, y: float) -> None:
    self.scale.x = x
    self.scale.y = y


import re

from configparser import ConfigParser
from uuid import uuid4

from fantastic.exercises.fill.fill import Fill
from fantastic.exercises.utils import text_to_html

class RemplirClavierCadre(Fill):
    """exercises consisting of finding verbes between parenthesis
    and adding a frame above the sentence with the verb"""

    def __init__(self, json_path: str, config: ConfigParser) -> None:
        Fill.__init__(
            self,
            json_path,
            config,
            template_name="fill",
            output_folder_name="remplir_clavier_cadre",
        )

    def adapt_guideline(self):
        """should adapt the guideline for some exercises"""

        guideline = super().find_guideline()
        guideline = guideline = guideline.replace("entre parenthèses ", "")
        guideline = guideline.replace(" entre parenthèses", "")

        return guideline

    def convert_to_html(self):
        """get the raw text and output an html version of it readty to be adapted"""

        # we get the data from json
        guideline = self.adapt_guideline()
        # find additional guideline returns a tuple
        additional_guideline = "".join(super().find_additional_guideline())
        # list of sentences from exercise_text
        sentences = super().find_sentences()

        # text to html convert each word, but we need to manke changes before text to html
        # so we need to encapsulate what we want to give to the fill box in only one word : hex hash
        # replacement dict contains all change to be made after the conversion to html
        replacement, sentences_with_hash = ({}, [])
        for sentence in sentences:
            # we initialize sentence_id in case of bad extracted xml
            sentence_id = 0
            # getting the verbs
            verbs = re.findall(r"\(.+?\)", sentence)
            sentence_with_hash = ""
            sentence_without_verb = sentence

            for verb in verbs:
                # verb contains parenthesis
                sentence_without_verb = sentence_without_verb.replace(f"{verb}", "…")

                # we generate an unique id for the sentence, that we will not found in the text
                # because after the conversion to html, we'll replace the unique id by html code
                sentence_id = uuid4().hex
                replacement[
                    str(sentence_id)
                ] = f"{verb[1:-1]}"
                sentence_with_hash += str(sentence_id) + " "

            if sentence_id == 0:
                # no verb found
                sentences_with_hash.append(sentence)
            else:
                # verb found
                sentences_with_hash.append(
                    sentence_with_hash + "
 " + sentence_without_verb
                )

        # we conver to html the text of guideline, additional guideline and exercise_text
        guideline = text_to_html([guideline])
        # we want it to be empty if there are no additional guideline
        additional_guideline = (
            text_to_html([additional_guideline]) if additional_guideline != "" else ""
        )
        exercise_text = text_to_html(sentences_with_hash, True)

        return guideline, additional_guideline, exercise_text, replacement

    def adapt(self):
        """specific adaptation for this type of exercise"""
        super().adapt_html()
        return self


from dataclasses import dataclass
from datetime import datetime
import re
from os import path
from typing import Any, cast, Type, TypeVar

from jsons import (
    dump,
    dumps,
    NoneType,
    load,
    loads,
    JsonsError,
    set_deserializer,
    set_serializer,
    set_validator,
    suppress_warnings,
    default_nonetype_deserializer,
)

S = TypeVar("S", bound="Serializable")
_T = TypeVar("_T")

JSON_FILE_EXTENSION: str = ".json"
WRITE: str = "w"
READ: str = "r"
JSON_PARSE_ERROR = '{"error": "Object could not be parsed due to json issue"}'
# TODO Issue #??: Jsons library incorrectly dumps class method
KEYS_TO_REMOVE = ["from_json", "from_json_file", "from_json_object"]

@dataclass
class Serializable:
    """
    Serializable class with methods to convert to json
    """

    def to_json(self, strip_privates: bool = True) -> str:
        """
        Serialize to json string
        :param strip_privates: strip private variables
        :return: the json string representation of this object
        """
        return write_json(self, strip_privates)

    def to_json_object(self, strip_privates: bool = True) -> Any:
        """
        Serialize to json object
        :param strip_privates: strip private variables
        :return: the json representation of this object
        """
        return write_json_object(self, strip_privates)

    def to_json_file(
        self, file_name: str, file_path: str = "", strip_privates: bool = True
    ) -> None:
        """
        Serialize an object to a json file
        :param file_name: File name
        :param file_path: File path
        :param strip_privates: Strip private variables
        """
        write_json_file(self, file_name, file_path, strip_privates)

    @classmethod
    def from_json(cls: Type[S], data: str) -> S:
        """
        Deserialize the provided data string into the specified instance
        :param data: JSON string
        """
        return read_json(data, cls)

    @classmethod
    def from_json_object(cls: Type[S], data: object) -> S:
        """
        Deserialize the provided data object into the specified instance
        :param data: JSON object
        """
        return read_json_object(data, cls)

    @classmethod
    def from_json_file(cls: Type[S], file_name: str, file_path: str = "") -> S:
        """
        Deserialize the provided file into the specified instance
        :param file_name: File name
        :param file_path: File path
        """
        return read_json_file(cls, file_name, file_path)

def _remove_key(obj: Any, key_to_remove: str) -> Any:
    """
    Remove key from object recursively
    :param obj: Any object
    :param key_to_remove: key to remove
    """
    if isinstance(obj, dict):
        for key in list(obj.keys()):
            if key == key_to_remove:
                del obj[key]
            else:
                _remove_key(obj[key], key_to_remove)
    elif isinstance(obj, list):
        for i in reversed(range(len(obj))):
            if obj[i] == key_to_remove:
                del obj[i]
            else:
                _remove_key(obj[i], key_to_remove)

def write_json(object_to_write: object, strip_privates: bool = True) -> str:
    """
    Serialize to json string
    :param object_to_write: object to write to json
    :param strip_privates: strip private variables
    :return: the json string representation of this object
    """
    set_serializers()
    suppress_warnings()
    try:
        json_object = write_json_object(object_to_write, strip_privates)
        json_string = cast(
            str, dumps(json_object, strip_privates=strip_privates, strip_nulls=True)
        )
        return json_string
    except JsonsError:
        return JSON_PARSE_ERROR

def write_json_object(object_to_write: object, strip_privates: bool = True) -> object:
    """
    Serialize to json object
    :param object_to_write: object to write to json
    :param strip_privates: strip private variables
    :return: the json representation of this object
    """
    set_serializers()
    suppress_warnings()
    try:
        json_object = dump(
            object_to_write, strip_privates=strip_privates, strip_nulls=True
        )
        for key in KEYS_TO_REMOVE:
            _remove_key(json_object, key)
        return json_object
    except JsonsError:
        return JSON_PARSE_ERROR

def write_json_file(
    object_to_write: object,
    file_name: str,
    file_path: str = "",
    strip_privates: bool = True,
) -> None:
    """
    Serialize json data string to json file
    :param object_to_write: object to write to json
    :param file_name: File name
    :param file_path: File path
    :param strip_privates: strip private variables
    """
    json_file_path: str = path.join(file_path, file_name + JSON_FILE_EXTENSION)
    with open(json_file_path, WRITE) as json_file:
        json_file.write(write_json(object_to_write, strip_privates))

def read_json(data: Any, class_out: Type[_T]) -> _T:
    """
    Deserialize json file to object
    :param data: Json file data
    :param class_out: Object type
    :return: Deserialized object
    """
    set_deserializers()
    return cast(_T, loads(data, class_out))

def read_json_object(data: Any, class_out: Type[_T]) -> _T:
    """
    Deserialize json file to object
    :param data: Json file data
    :param class_out: Object type
    :return: Deserialized object
    """
    set_deserializers()
    return cast(_T, load(data, class_out))

def read_json_file(class_out: Type[_T], file_name: str, file_path: str = "") -> _T:
    """
    Deserialize json file to object
    :param class_out: Object type
    :param file_name: File name
    :param file_path: File path
    :return: Deserialized object
    """
    set_deserializers()
    json_file_path: str = path.join(file_path, file_name + JSON_FILE_EXTENSION)
    with open(json_file_path, READ) as json_file:
        data = json_file.read()
        target: _T = read_json(data, class_out)
    return target

def set_serializers() -> None:
    """Set serializers for jsons to use to cast specific classes"""

    # Local import to minimize jsons usage across files
    from .group import ElementModP, ElementModQ

    set_serializer(lambda p, **_: str(p), ElementModP)
    set_serializer(lambda q, **_: str(q), ElementModQ)
    set_serializer(lambda dt, **_: dt.isoformat(), datetime)

def set_deserializers() -> None:
    """Set deserializers and validators for json to use to cast specific classes"""

    # Local import to minimize jsons usage across files
    from .group import ElementModP, ElementModQ, int_to_p_unchecked, int_to_q_unchecked

    set_deserializer(
        lambda p_as_int, cls, **_: int_to_p_unchecked(p_as_int), ElementModP
    )
    set_validator(lambda p: p.is_in_bounds(), ElementModP)

    set_deserializer(
        lambda q_as_int, cls, **_: int_to_q_unchecked(q_as_int), ElementModQ
    )
    set_validator(lambda q: q.is_in_bounds(), ElementModQ)

    set_deserializer(
        lambda none, cls, **_: None
        if none == "None"
        else default_nonetype_deserializer(none),
        NoneType,
    )

    set_deserializer(lambda dt, cls, **_: _deserialize_datetime(dt), datetime)

def _deserialize_datetime(value: str) -> datetime:
    """
    The `fromisoformat` function doesn't recognize the Z (Zulu) suffix
    to indicate UTC.  For compatibility with more external clients, we
    should allow it.
    """
    tz_corrected = re.sub("Z$", "+00:00", value)
    return datetime.fromisoformat(tz_corrected)


"""
Modificações na base de dados de extratos
- reformata mes de referenência
- cria a data corrigida (data real da transação
- cria o mês da data corrigida
- cria algumas variáveis sempre fixas
"""

import datetime as dt
from dateutil.relativedelta import relativedelta

def cria_variaveis(dados):
    """
    cria novas variáveis
    @dados: base pd.DataFrame que quero transformar.
    """
    data_base = dados.copy()

    # PARCELA ATUAL E TOTAL
    # procura no memo 2 o número de parcelas

    df1 = data_base[['data', 'memo2', 'mes_ref']].loc[
        data_base['tipo_conta'].isin(['Cartão'])
        & data_base['memo2'].str.contains('^PARC [0-9]{2}/[0-9]{2}$')
    ]
    df1['parc_atual'] = df1['memo2'].str.replace('PARC ', '')
    df1['parc_atual'] = df1['parc_atual'].str.split('/', 1)
    df1['parc_total'] = [int(x[1]) for x in df1['parc_atual']]
    df1['parc_atual'] = [int(x[0]) for x in df1['parc_atual']]

    # DataN
    # data da transação corrigida pelo número de parcelas
    # em trans. parcelada, a data é o momento que a transação foi realizada originalmente

    temp = []
    for index, value in enumerate(df1['data']):
        desloca = value + relativedelta(months=+df1['parc_atual'].iloc[index] - 1)
        if desloca > df1['mes_ref'].iloc[index]:
            temp.append(value)
        else:
            temp.append(desloca)

    df1['dataN'] = temp
    data_base['dataN'] = data_base['data']
    data_base['dataN'].update(df1['dataN'])

    # MES DA DATA DA TRANSAÇÃO
    data_base['mesN'] = [x + relativedelta(day=1) for x in data_base['dataN']]

    # OUTRAS VARIÁVEIS (fixas)
    data_base['moeda'] = 'BRL'
    data_base['tipo_entrada'] = 'OFX'
    data_base['valorN'] = data_base['valor']
    data_base['data_import'] = dt.date.today()

    return data_base


num=int(input())
temp=num
order=len(str(num))
sum=0
while num > 0:
    digit=num %10
    sum=sum+digit ** order
    num=num//10
if sum==temp:
    print("armstrong")
else:
    print("not armstrng")


from __future__ import print_function, division, absolute_import

import copy
from astropy import units as u
from marvin.utils.datamodel.maskbit import get_maskbits
from .base import DAPDataModel, Template, spaxel as spaxel_unit
from .base import Model, Channel, MultiChannelProperty
from .MPL6 import SPX, HYB10, VOR10, MPL6_maps, binid_properties
from .MPL6 import MPL6_emline_channels, oii_channel, oiid_channel

# update Template for MPL-8
MILESHC_MILESHC = Template('MILESHC-MILESHC',
                           description=('Set of templates derived from the MILES library, '
                                        'used for both the stellar kinematics and emission lines.'))

# new figure of merit channels
fom_channels = [
    Channel('rms', formats={'string': 'RMS of residuals for fitted pixels',
                            'latex': r'RMS of residuals'},
            description='RMS of the residuals for all fitted pixels in the stellar continuum.',
            unit=u.erg / u.s / (u.cm ** 2) / u.Angstrom / spaxel_unit, scale=1e-17, idx=0),
    Channel('frms', formats={'string': 'RMS of the fractional residuals',
                             'latex': r'RMS of the fractional residuals'},
            description='Fractional residuals for the stellar continuum fit.', idx=1),
    Channel('rchi2', formats={'string': 'Stellar continuum reduced chi-square',
                              'latex': r'Stellar\ continuum\ reduced\ \chi^2'},
            description='Reduced chi-square of the stellar continuum fit.', idx=2),
    Channel('fresid_68th_percentile', db_name='68th_perc_frac_resid',
            formats={'string': '68th percentile',
                     'latex': r'68^{th} percentile'},
            description='68%% growth of the fractional residuals between the model and data.', idx=3),
    Channel('fresid_99th_percentile', db_name='99th_perc_frac_resid',
            formats={'string': '99th percentile Frac. Residuals',
                     'latex': r'99^{th} percentile Frac. Residuals'},
            description='99%% growth of the fractional residuals between the model and data.', idx=4),
    Channel('fresid_max', db_name='max_frac_resid',
            formats={'string': 'Max Fractional Residual',
                     'latex': r'Max Fractional Residual'},
            description='Maximum growth of the fractional residuals between the model and data.', idx=5),
    Channel('per_pix_chi_68th_percentile', db_name='68th_perc_per_pix_chi',
            formats={'string': '68th percentile',
                     'latex': r'68^{th} percentile'},
            description='68%% growth of the error-normalized residuals', idx=6),
    Channel('per_pix_chi_99th_percentile', db_name='99th_perc_per_pix_chi',
            formats={'string': '99th percentile',
                     'latex': r'99^{th} percentile'},
            description='99%% growth of the error-normalized residuals', idx=7),
    Channel('per_pix_chi_max', db_name='max_per_pix_chi',
            formats={'string': 'Max Error-Normalized Residuals',
                     'latex': r'Max Error-Normalized Residuals'},
            description='Maximum growth of the error-normalized residuals', idx=8),
]

# new emission line channels
new_channels = [
    Channel('hei_3889', formats={'string': 'HeI 3889',
                                 'latex': r'$\forb{He\,I}\;\lambda 3889$'}, idx=22),
    Channel('ni_5199', formats={'string': 'NI 5199',
                                'latex': r'$\forb{N\,I}\;\lambda 5199$'}, idx=23),
    Channel('ni_5201', formats={'string': 'NI 5201',
                                'latex': r'$\forb{N\,I}\;\lambda 5201$'}, idx=24),
]

MPL8_emline_channels = copy.deepcopy(MPL6_emline_channels) + new_channels

new_properties = [
    # New Emission Line extensions
    MultiChannelProperty('emline_ga', ivar=False, mask=False,
                         channels=[oii_channel] + MPL8_emline_channels,
                         formats={'string': 'Amplitude of Fitted Gaussians'},
                         unit=u.erg / u.s / (u.cm ** 2) / u.Angstrom / spaxel_unit, scale=1e-17,
                         binid=binid_properties[3],
                         description='Amplitude of the fitted Gaussian emission lines.'),
    MultiChannelProperty('emline_ganr', ivar=False, mask=False,
                         channels=[oii_channel] + MPL8_emline_channels,
                         formats={'string': 'Amplitude Over Noise of Fitted Gaussians'},
                         binid=binid_properties[3],
                         description='Amplitude Over Noise of the fitted Gaussian emission lines.'),
    MultiChannelProperty('emline_lfom', ivar=False, mask=False,
                         channels=[oii_channel] + MPL8_emline_channels,
                         formats={'string': 'Emission Line Reduced Chi-Square'},
                         binid=binid_properties[3],
                         description='Reduced chi-square in 15 pixel windows around each fitted emission line'),
    # Figure of Merit Extensions in MAPS
    MultiChannelProperty('emline_fom', ivar=False, mask=False,
                         channels=fom_channels,
                         formats={'string': 'Emission Line FOM'},
                         unit=u.dimensionless_unscaled,
                         description='Full spectrum figures-of-merit for emission line fitting'),
    MultiChannelProperty('stellar_fom', ivar=False, mask=False,
                         channels=fom_channels, formats={
                             'string': 'Stellar FOM'},
                         unit=u.dimensionless_unscaled,
                         description='Full spectrum figures-of-merit for stellar continuum fitting'),
    # New Stellar SigmaCorr
    MultiChannelProperty('stellar_sigmacorr', ivar=False, mask=False,
                         channels=[Channel('resolution_difference',
                                           formats={'string': 'Resolution Difference'}, idx=0),
                                   Channel('fit',
                                           formats={'string': 'Fit'}, idx=1)],
                         unit=u.km / u.s,
                         formats={'string': 'Stellar sigma correction',
                                  'latex': r'Stellar $\sigma$ correction'},
                         description='Quadrature correction for STELLAR_SIGMA to obtain the '
                                     'astrophysical velocity dispersion.'),
]

emline_props = [
    MultiChannelProperty('emline_sflux', ivar=True, mask=True,
                         channels=[oiid_channel] + MPL8_emline_channels,
                         formats={'string': 'Emission line summed flux'},
                         unit=u.erg / u.s / (u.cm ** 2) / spaxel_unit, scale=1e-17,
                         binid=binid_properties[3],
                         description='Non-parametric summed flux for emission lines.'),
    MultiChannelProperty('emline_sew', ivar=True, mask=True,
                         channels=[oiid_channel] + MPL8_emline_channels,
                         formats={'string': 'Emission line EW'},
                         unit=u.Angstrom,
                         binid=binid_properties[3],
                         description='Emission line non-parametric equivalent '
                                     'widths measurements.'),
    MultiChannelProperty('emline_gflux', ivar=True, mask=True,
                         channels=[oii_channel] + MPL8_emline_channels,
                         formats={'string': 'Emission line Gaussian flux'},
                         unit=u.erg / u.s / (u.cm ** 2) / spaxel_unit, scale=1e-17,
                         binid=binid_properties[3],
                         description='Gaussian profile integrated flux for emission lines.'),
    MultiChannelProperty('emline_gvel', ivar=True, mask=True,
                         channels=[oii_channel] + MPL8_emline_channels,
                         formats={'string': 'Emission line Gaussian velocity'},
                         unit=u.km / u.s,
                         binid=binid_properties[3],
                         description='Gaussian profile velocity for emission lines.'),
    MultiChannelProperty('emline_gew', ivar=True, mask=True,
                         channels=[oii_channel] + MPL8_emline_channels,
                         formats={'string': 'Emission line Gaussian EW'},
                         unit=u.Angstrom,
                         binid=binid_properties[3],
                         description='Gaussian-fitted equivalent widths measurements '
                                     '(based on EMLINE_GFLUX).'),
    MultiChannelProperty('emline_gsigma', ivar=True, mask=True,
                         channels=[oii_channel] + MPL8_emline_channels,
                         formats={'string': 'Emission line Gaussian sigma',
                                  'latex': r'Emission line Gaussian $\sigma$'},
                         unit=u.km / u.s,
                         binid=binid_properties[3],
                         description='Gaussian profile velocity dispersion for emission lines; '
                                     'must be corrected using EMLINE_INSTSIGMA.'),
    MultiChannelProperty('emline_instsigma', ivar=False, mask=False,
                         channels=[oii_channel] + MPL8_emline_channels,
                         formats={'string': 'Emission line instrumental sigma',
                                  'latex': r'Emission line instrumental $\sigma$'},
                         unit=u.km / u.s,
                         binid=binid_properties[3],
                         description='Instrumental dispersion at the fitted line center.'),
    MultiChannelProperty('emline_tplsigma', ivar=False, mask=False,
                         channels=[oii_channel] + MPL8_emline_channels,
                         formats={'string': 'Emission line template instrumental sigma',
                                  'latex': r'Emission line template instrumental $\sigma$'},
                         unit=u.km / u.s,
                         binid=binid_properties[3],
                         description='The dispersion of each emission line used in '
                                     'the template spectra'),
]

# Update Maps Properties
remove = ['stellar_cont_rchi2', 'stellar_sigmacorr', 'stellar_cont_fresid']
MPL8_maps = [m for m in MPL6_maps if m.name not in remove and 'emline' not in m.name]
MPL8_maps += emline_props + new_properties

# Update Model Properties
MPL8_models = [
    Model('binned_flux', 'FLUX', 'WAVE', extension_ivar='IVAR',
          extension_mask='MASK', unit=u.erg / u.s / (u.cm ** 2) / u.Angstrom / spaxel_unit,
          scale=1e-17, formats={'string': 'Binned flux'},
          description='Flux of the binned spectra',
          binid=binid_properties[0]),
    Model('full_fit', 'MODEL', 'WAVE', extension_ivar=None,
          extension_mask='MODEL_MASK', unit=u.erg / u.s / (u.cm ** 2) / u.Angstrom / spaxel_unit,
          scale=1e-17, formats={'string': 'Best fitting model'},
          description='The best fitting model spectra (sum of the fitted '
                      'continuum and emission-line models)',
          binid=binid_properties[0]),
    Model('emline_fit', 'EMLINE', 'WAVE', extension_ivar=None,
          extension_mask=None,
          unit=u.erg / u.s / (u.cm ** 2) / u.Angstrom / spaxel_unit,
          scale=1e-17, formats={'string': 'Emission line model spectrum'},
          description='The model spectrum with only the emission lines.',
          binid=binid_properties[3]),
    Model('stellar_fit', 'STELLAR', 'WAVE', extension_ivar=None,
          extension_mask='STELLAR_MASK',
          unit=u.erg / u.s / (u.cm ** 2) / u.Angstrom / spaxel_unit,
          scale=1e-17, formats={'string': 'Stellar continuum model spectrum'},
          description='The model spectrum with only the stellar continuum',
          binid=binid_properties[1])
]

# MPL-8 DapDataModel goes here
MPL8 = DAPDataModel('2.3.0', aliases=['MPL-8', 'MPL8'],
                    bintypes=[SPX, HYB10, VOR10],
                    db_only=[HYB10],
                    templates=[MILESHC_MILESHC],
                    properties=MPL8_maps,
                    models=MPL8_models,
                    bitmasks=get_maskbits('MPL-8'),
                    default_bintype='HYB10',
                    default_template='MILESHC-MILESHC',
                    property_table='SpaxelProp8',
                    default_binid=copy.deepcopy(binid_properties[0]),
                    default_mapmask=['NOCOV', 'UNRELIABLE', 'DONOTUSE'],
                    qual_flag='DAPQUAL')


class Solution:
    def canBeTypedWords(self, text: str, brokenLetters: str) -> int:
        texts = text.split(" ")
        ans = len(texts)
        if brokenLetters == "":
            return ans

        for t in texts:
            for b in brokenLetters:
                if b in t:
                    ans -= 1
                    break

        return ans