#to work w Windows, Mac, and Linux:
from pathlib import Path, PurePath
#saving labels
import csv

#audio
import librosa
import librosa.display
import matplotlib.pyplot as plt

#math/data prep
import numpy as np
import pandas as pd
import random
import math
import statistics
from scipy import stats
from sklearn.preprocessing import LabelEncoder
#from keras.utils.np_utils import to_categorical

from errors import FeatureExtractionError, TotalSamplesNotAlignedSpeakerSamples
#from monster_functions import fill_matrix_samples_zero_padded
import prep_noise as prep_data_vad_noise

def collect_labels(data_path):
    p = Path(data_path)
    labels = list(p.glob('*/'))
    labels = [PurePath(labels[i]) for i in range(len(labels))]
    labels = [x.parts[1] for x in labels if '_' not in x.parts[1]]
    labels = check_4_github_files(labels)
    return labels

def get_num_images(data_directory,image_format=None):
    if image_format is None:
        image_format = 'png'
    p = Path(data_directory)
    pics = list(p.glob('**/*.{}'.format(image_format)))
    return len(pics)

def check_4_github_files(labels_list):
    if 'README.md' in labels_list:
        labels_list.remove('README.md')
    if 'LICENSE' in labels_list:
        labels_list.remove('LICENSE')
    return labels_list

def collect_audio_and_labels(data_path):
    '''
    expects wavefiles to be in subdirectory: 'data'
    labels are expected to be the names of each subdirectory in 'data'
    speaker ids are expected to be the first section of each wavefile
    '''
    p = Path(data_path)
    waves = list(p.glob('**/*.wav'))
    #remove directories with "_" at the beginning
    paths = [PurePath(waves[i]) for i in range(len(waves)) if waves[i].parts[1][0]!="_"]
    labels = [j.parts[1] for j in paths ]
    return paths, labels

def get_speaker_id(path_label):
    '''
    A speaker provides input for more than just one word
    this allows the speaker to be put into dictionary without
    causing 'KeyError'
    '''
    speaker_id_info = path_label[-1].split("_")
    speaker_id = speaker_id_info[0]
    speaker_id_label = speaker_id+ "_" + path_label[1]
    if speaker_id_info[-1][0] != str(0):
        print("Problem with {}".format(path_label))
        print("Perhaps the speaker {} has already said the word '{}'.".format(speaker_id,path_label[1]))

        return None
    return speaker_id_label

def organize_data(dictionary, path_labels, features):
    '''
    index corresponds where we are in labels and paths

    expects a path_labels as list of tuples:
    index 0 --> folder "data"
    index 1 --> label for the speaker
    index 3 --> wavefile name of which contains the speaker ID in first section
    '''
    speaker_id_label = get_speaker_id(path_labels)
    if speaker_id_label:
        if speaker_id_label not in dictionary:
            dictionary[speaker_id_label] = features

    return dictionary

def prep_data4sql(dictionary):
    '''
    input:
    expects key to have speaker id and label, separated w "_"
    expects values to be the features used to train model, in numpy array

    returns:
    list of tuples. the tuples correspond to sql columns:
    index 0 --> speaker id
    index ... --> features
    index -1 --> label
    '''
    data_prepped = []
    utterance_count = 0
    for key, value in dictionary.items():
        utterance_count += 1
        speaker_id = key.split("_")[0]
        label = key.split("_")[1]
        #to iterate through all of the samples of each utterance
        #each word contains many feature sets/ samples
        for row in value:
            features = list(row)
            features.insert(0,utterance_count)
            features.insert(0,speaker_id)
            features.append(label)
            data_prepped.append(tuple(features))

    return data_prepped

def get_change_acceleration_rate(spectro_data):
    #first derivative = delta (rate of change)
    delta = librosa.feature.delta(spectro_data)
    #second derivative = delta delta (acceleration changes)
    delta_delta = librosa.feature.delta(spectro_data,order=2)
    return delta, delta_delta

def remove_silences(y):
    yt = librosa.effects.trim(y)
    return yt[0]

def apply_noise(y,sr,wavefile):
    #at random apply varying amounts of environment noise
    rand_scale = random.choice([0.0,0.25,0.5,0.75])
    if rand_scale > 0.0:
        #apply *known* environemt noise to signal
        total_length = len(y)/sr
        y_noise,sr = librosa.load(wavefile,sr=16000)
        envnoise_normalized = prep_data_vad_noise.normalize(y_noise)
        envnoise_scaled = prep_data_vad_noise.scale_noise(envnoise_normalized,rand_scale)
        envnoise_matched = prep_data_vad_noise.match_length(envnoise_scaled,sr,total_length)
        if len(envnoise_matched) != len(y):
            diff = int(len(y) - len(envnoise_matched))
            if diff < 0:
                envnoise_matched = envnoise_matched[:diff]
            else:
                envnoise_matched = np.append(envnoise_matched,np.zeros(diff,))
        y += envnoise_matched
    return y

def save_chroma(wavefile,split,frame_width,time_step,feature_type,num_features,num_feature_columns,noise,path_to_save_png,train=False,noise_wavefile=None,vad = False):

    y, sr = get_samps(wavefile)
    #y = remove_silences(y)
    if vad:
        y = prep_data_vad_noise.get_speech_samples(y,sr)
    if noise_wavefile:
        y = apply_noise(y,sr,noise_wavefile)
    extracted = []
    if "mfcc" in feature_type.lower():
        extracted.append("mfcc")
        features = get_mfcc(y,sr,num_mfcc=num_features)
        features -= (np.mean(features, axis=0) + 1e-8)
        if "delta" in feature_type.lower():
            delta, delta_delta = get_change_acceleration_rate(features)
            features = np.concatenate((features,delta,delta_delta),axis=1)
    elif "fbank" in feature_type.lower():
        extracted.append("fbank")
        features = get_mel_spectrogram(y,sr,num_mels = num_features)
        features -= (np.mean(features, axis=0) + 1e-8)
        if "delta" in feature_type.lower():
            delta, delta_delta = get_change_acceleration_rate(features)
            features = np.concatenate((features,delta,delta_delta),axis=1)
    elif "stft" in feature_type.lower():
        extracted.append("stft")
        features = get_stft(y,sr)
        features -= (np.mean(features, axis=0) + 1e-8)
        if "delta" in feature_type.lower():
            delta, delta_delta = get_change_acceleration_rate(features)
            features = np.concatenate((features,delta,delta_delta),axis=1)
    if features.shape[1] != num_feature_columns:
        raise FeatureExtractionError("The file '{}' results in the incorrect  number of columns (should be {} columns): shape {}".format(wavefile,num_features,features.shape))

    features = np.transpose(features)
    name = Path(wavefile).parts[-1][:-4]

    if split:

        count = 0
        #while count <= time_step:
            #for i in range(0,features.shape[1],frame_width):
        for i in range(0,time_step*frame_width,frame_width):
            if i > features.shape[1]-1:
                features_step = np.zeros((num_feature_columns,frame_width))
            else:
                features_step = features[:,i:i+frame_width]

            if features_step.shape[1] != frame_width:
                diff = frame_width - features_step.shape[1]
                features_step = np.concatenate((features_step,np.zeros((num_feature_columns,diff))),axis=1)

            plt.clf()
            librosa.display.specshow(features_step)

            plt.tight_layout(pad=0)
            plt.savefig("{}{}_{}.png".format(path_to_save_png,name,count),pad_inches=0)
            count+=1
                #if count > time_step:
                    #break
    else:

        plt.clf()
        max_len = frame_width*time_step
        if features.shape[1] < max_len:
            diff = max_len - features.shape[1]
            features = np.concatenate((features,np.zeros((num_feature_columns,diff))),axis=1)
        librosa.display.specshow(features[:,:max_len])
        plt.tight_layout(pad=0)
        plt.savefig("{}{}.png".format(path_to_save_png,name))

    return True

def get_feats(wavefile,feature_type,num_features,delta=False,noise_wavefile = None,vad = False):
    y, sr = get_samps(wavefile)
    if vad:
        y = prep_data_vad_noise.get_speech_samples(y,sr)
    if noise_wavefile:
        y = apply_noise(y,sr,noise_wavefile)
    if delta:
        num_feature_columns = num_features*3
    else:
        num_feature_columns = num_features

    extracted = []
    if "mfcc" in feature_type.lower():
        extracted.append("mfcc")
        features = get_mfcc(y,sr,num_mfcc=num_features)
        features -= (np.mean(features, axis=0) + 1e-8)
        if "delta" in feature_type.lower():
            delta, delta_delta = get_change_acceleration_rate(features)
            features = np.concatenate((features,delta,delta_delta),axis=1)
    elif "fbank" in feature_type.lower():
        extracted.append("fbank")
        features = get_mel_spectrogram(y,sr,num_mels = num_features)
        features -= (np.mean(features, axis=0) + 1e-8)
        if "delta" in feature_type.lower():
            delta, delta_delta = get_change_acceleration_rate(features)
            features = np.concatenate((features,delta,delta_delta),axis=1)
    elif "stft" in feature_type.lower():
        extracted.append("stft")
        features = get_stft(y,sr)
        features -= (np.mean(features, axis=0) + 1e-8)
        if "delta" in feature_type.lower():
            delta, delta_delta = get_change_acceleration_rate(features)
            features = np.concatenate((features,delta,delta_delta),axis=1)
    if features.shape[1] != num_feature_columns:
        raise FeatureExtractionError("The file '{}' results in the incorrect  number of columns (should be {} columns): shape {}".format(wavefile,num_features,features.shape))
    return features

def get_features(wavefile,feature_type,num_features,num_feature_columns,noise):
    if noise:
        '''
        ToDo:
        add option for adding noise to the data
        '''
        pass
    if isinstance(num_features,str):
        num_features = int(num_features)
    y, sr = get_samps(wavefile)
    extracted = []
    if "mfcc" in feature_type.lower():
        extracted.append("mfcc")
        features = get_mfcc(y,sr,num_mfcc=num_features)
        if "delta" in feature_type.lower():
            delta, delta_delta = get_change_acceleration_rate(features)
            features = np.concatenate((features,delta,delta_delta),axis=1)
    elif "fbank" in feature_type.lower():
        extracted.append("fbank")
        features = get_mel_spectrogram(y,sr,num_mels = num_features)
        if "delta" in feature_type.lower():
            delta, delta_delta = get_change_acceleration_rate(features)
            features = np.concatenate((features,delta,delta_delta),axis=1)
    if "pitch" in feature_type.lower():
        extracted.append("pitch")
        freq = np.array(get_domfreq(y,sr))
        #make into dimension matching features to concatenate them
        freq = freq.reshape(len(features),1)
        features = np.concatenate((features,freq),axis=1)

    if features.shape[1] != num_feature_columns:
        raise FeatureExtractionError("The file '{}' results in the incorrect  number of columns (should be {} columns): shape {}".format(wavefile,num_features,features.shape))

    return features, extracted

def get_samps(wavefile,sr=None,high_quality=None):
    if sr is None:
        sr = 16000
    if high_quality:
        quality = "kaiser_high"
    else:
        quality = "kaiser_fast"
    y, sr = librosa.load(wavefile,sr=sr,res_type=quality)

    return y, sr

def get_mfcc(y,sr,num_mfcc=None,window_size=None, window_shift=None):
    '''
    set values: default for MFCCs extraction:
    - 40 MFCCs
    - windows of 25ms
    - window shifts of 10ms
    '''
    if num_mfcc is None:
        num_mfcc = 40
    if window_size is None:
        n_fft = int(0.025*sr)
    else:
        n_fft = int(window_size*0.001*sr)
    if window_shift is None:
        hop_length = int(0.010*sr)
    else:
        hop_length = int(window_shift*0.001*sr)
    mfccs = librosa.feature.mfcc(y,sr,n_mfcc=num_mfcc,hop_length=hop_length,n_fft=n_fft)
    mfccs = np.transpose(mfccs)

    return mfccs

def get_mel_spectrogram(y,sr,num_mels = None,window_size=None, window_shift=None):
    '''
    set values: default for mel spectrogram calculation (FBANK)
    - windows of 25ms
    - window shifts of 10ms
    '''
    if num_mels is None:
        num_mels = 40
    if window_size is None:
        n_fft = int(0.025*sr)
    else:
        n_fft = int(window_size*0.001*sr)
    if window_shift is None:
        hop_length = int(0.010*sr)
    else:
        hop_length = int(window_shift*0.001*sr)

    fbank = librosa.feature.melspectrogram(y,sr,n_fft=n_fft,hop_length=hop_length,n_mels=num_mels)
    fbank = np.transpose(fbank)

    return fbank

def get_stft(y,sr,window_size=None, window_shift=None):
    if window_size is None:
        n_fft = int(0.025*sr)
    else:
        n_fft = int(window_size*0.001*sr)
    if window_shift is None:
        hop_length = int(0.010*sr)
    else:
        hop_length = int(window_shift*0.001*sr)
    stft = np.abs(librosa.feature.stft(y,sr,n_fft=n_fft,hop_length=hop_length)) #comes in complex numbers.. have to take absolute value
    stft = np.transpose(stft)

    return stft

def get_domfreq(y,sr):
    frequencies, magnitudes = get_freq_mag(y,sr)
    #select only frequencies with largest magnitude, i.e. dominant frequency
    dom_freq_index = [np.argmax(item) for item in magnitudes]
    dom_freq = [frequencies[i][item] for i,item in enumerate(dom_freq_index)]

    return dom_freq

def get_freq_mag(y,sr,window_size=None, window_shift=None):
    '''
    default values:
    - windows of 25ms
    - window shifts of 10ms
    '''
    if window_size is None:
        n_fft = int(0.025*sr)
    else:
        n_fft = int(window_size*0.001*sr)
    if window_shift is None:
        hop_length = int(0.010*sr)
    else:
        hop_length = int(window_shift*0.001*sr)
    #collect frequencies present and their magnitudes
    frequencies,magnitudes = librosa.piptrack(y,sr,hop_length=hop_length,n_fft=n_fft)
    frequencies = np.transpose(frequencies)
    magnitudes = np.transpose(magnitudes)

    return frequencies, magnitudes

def get_data_matrix(data,features_start_stop,many=True):
    if len(features_start_stop) > 1:
        data = data.iloc[:,features_start_stop[0]:features_start_stop[1]].values
    else:
        if many:
            data = data.iloc[:,features_start_stop[0]::].values
        else:
            data = data.iloc[:,features_start_stop[0]].values

    return data

def get_unique(pandas_series,limit):
    '''
    expects a pandas series and an integer
    '''
    if len(pandas_series) > limit:
        print("Iterating through data to save memory..")
        unique = []
        for item in pandas_series:
            if item not in unique:
                unique.append(item)
    else:
        print("Getting labels via pandas.Series.unique()")
        unique = pandas_series.unique()

    return unique

def get_col_id_name(data,col_id):
    cols = data.columns
    col_id_name = cols[col_id]

    return col_id_name

def get_ids(data,col_id):
    col_id_name = get_col_id_name(data,col_id)
    ids = data[col_id_name]
    ids_unique = get_unique(ids,1000000)

    return ids_unique, ids

def get_num_samples_per_id(ids,data,col_id):
    col_id_name = get_col_id_name(data,col_id)
    samples_list = []
    for id_num in ids:
        samples_list.append(sum(data[col_id_name]==id_num))

    return samples_list

def prep_data(data,id_col_index,features_start_stop_index,label_col_index,num_features,frame_width,session):
    data_df = pd.DataFrame(data)

    #find max num samples --> don't lose data, zero pad those that are fewer
    utterance_ids_unique, utterance_ids_repeated = get_ids(data_df,id_col_index)
    num_utterances = len(utterance_ids_unique)
    num_samps_per_utterance = get_num_samples_per_id(utterance_ids_unique,data_df,id_col_index)
    max_samps = max(num_samps_per_utterance)

    #need the samples to be fully divisible by the frame size: no partial frames
    samples_per_utterance_zero_padded = (max_samps//frame_width)*frame_width
    numrows_zeropadded_data = samples_per_utterance_zero_padded * num_utterances
    data_zeropadded = np.zeros((numrows_zeropadded_data,num_features+1))#+1 for labels column

    features = get_data_matrix(data_df,features_start_stop_index,many=True)
    labels = get_data_matrix(data_df,label_col_index,many=False)
    #change categorical labels to integers
    #save the label-integer pairings to .csv (session --> unique filename)
    y, labels_present = prep_categorical_labels(labels,session)

    # initialize row_id as 0, and it will get updated in the function
    # this helps me know that the right data is getting inserted in the right row of the new matrix
    row_id = 0
    try:
        if np.modf(numrows_zeropadded_data/samples_per_utterance_zero_padded)[0] != 0.0:
            raise TotalSamplesNotAlignedSpeakerSamples("Length of matrix does not align with total samples for each speaker")

        for i, id_num in enumerate(utterance_ids_unique):
            #PROBLEM
            #
            equal_utterance = utterance_ids_repeated == id_num
            indices = np.where(equal_utterance)[0]

            #get label for utterance
            label = y[indices[0]]

            data_zeropadded, row_id = fill_matrix_samples_zero_padded(data_zeropadded,row_id,features,indices,label,samples_per_utterance_zero_padded,frame_width)

    except TotalSamplesNotAlignedSpeakerSamples as e:
        print(e)
        data_zeropadded = None

    return data_zeropadded, samples_per_utterance_zero_padded, num_utterances, labels_present

def shape_data_dimensions_CNN_LSTM(data_zeropadded,samples_per_utterance_zero_padded, frame_width):
    '''
    prep data shape for ConvNet+LSTM:
    *assumes last column is label column

    shape = (num_speakers, num_sets_per_speaker; num_frames_per_set; num_features_per_frame; grayscale)

    If ConvNet and LSTM put together --> (66,32,19,120,1) if 66 speakers
    - ConvNet needs grayscale
    - LSTM needs num_sets_per_speaker

    If separate:
    - Convent needs grayscale (19,120,1)
    - LSTM needs number features in a series, i.e. 19 (19,120)
    '''

    #separate features from labels:
    features = data_zeropadded[:,:-1]
    print("Shape of features: {}".format(features.shape))
    labels = data_zeropadded[:,-1]
    print("Label index 0: {}".format(labels[0]))

    #number of frames within each set of utterance samples...
    num_frame_sets = samples_per_utterance_zero_padded//frame_width

    #number of sets (of utterance samples) in the data
    num_sets_samples = len(features)//num_frame_sets

    num_utterances = len(data_zeropadded)//samples_per_utterance_zero_padded

    #make sure only number of samples are included to make up complete context window frames of e.g. 19 frames (if context window frame == 9, 9 before and 9 after a central frame, so 9 * 2 + 1)
    check = len(data_zeropadded)//num_frame_sets
    if math.modf(check)[0] != 0.0:
        print("Extra Samples not properly removed")
    else:
        print("No extra samples found")

    #reshaping data to suit ConvNet + LSTM model training.
    #see notes at top of function definition
    X = features.reshape(len(data_zeropadded)//samples_per_utterance_zero_padded,samples_per_utterance_zero_padded//frame_width,frame_width,features.shape[1],1)
    #collect labels only **once** per utterance
    y_indices = list(range(0,len(labels),samples_per_utterance_zero_padded))
    y = labels[y_indices]
    #y = to_categorical(y)

    return X, y

def prep_categorical_labels(labels,session):
    #expects a numpy array
    y = pd.Series(labels)
    classes = get_unique(y,1000000)
    # encode class values as integers
    print("Fitting the encoder on the data..")
    encoder = LabelEncoder()
    encoder.fit(y)
    print("Encoding the labels..")
    classes_encoded = list(encoder.transform(classes))
    print("Saving labels..")
    save_class_labels(classes,classes_encoded,session)
    print("Encoding the data")
    y = encoder.transform(labels)

    return y, classes

def save_class_labels(class_labels,class_labels_encoded,session):
    dict_labels = {}
    for i, item in enumerate(class_labels_encoded):
        dict_labels[item] = class_labels[i]
    filename = 'dict_labels_{}.csv'.format(session)
    with open(filename,'w') as f:
        w = csv.writer(f)
        w.writerows(dict_labels.items())

    return None

def get_class_distribution(class_labels,labels_list):
    dict_class_distribution = {}
    for label in class_labels:
        count = 0
        for label_item in labels_list:
            if label == label_item:
                count+=1
            dict_class_distribution[label] = count
    return dict_class_distribution

def get_min_samples_per_class(class_labels, labels_list):
    dict_class_distribution = get_class_distribution(class_labels,labels_list)
    min_val = (1000000, None)
    for key, value in dict_class_distribution.items():
        if value < min_val[0]:
            min_val = (value, key)
    return min_val

def get_max_nums_train_val_test(max_num_per_class):
    max_train = int(max_num_per_class*.8)
    max_val = int(max_num_per_class*.1)
    max_test = int(max_num_per_class*.1)
    sum_max_nums = max_train + max_val + max_test
    if max_num_per_class > sum_max_nums:
        diff = max_num_per_class - sum_max_nums
        max_train += diff
    return max_train, max_val, max_test

def get_train_val_test_indices(list_length):
    indices_ran = list(range(list_length))
    random.shuffle(indices_ran)
    train_len = int(list_length*.8)
    val_len = int(list_length*.1)
    test_len = int(list_length*.1)
    sum_indices = train_len + val_len + test_len
    if sum_indices != list_length:
        diff = list_length - sum_indices
        train_len += diff
    train_indices = []
    val_indices = []
    test_indices = []
    for i, item in enumerate(indices_ran):
        if i < train_len:
            train_indices.append(item)
        elif i >= train_len and i < train_len+val_len:
            val_indices.append(item)
        elif i >= train_len + val_len and i < list_length:
            test_indices.append(item)
    return train_indices, val_indices, test_indices

def make_dict_class_index(class_labels,labels_list):
    dict_class_index_list = {}
    for label in class_labels:
        dict_class_index_list[label] = []
        for i, label_item in enumerate(labels_list):
            if label == label_item:
                dict_class_index_list[label].append(i)
    return dict_class_index_list

def assign_indices_train_val_test(class_labels,dict_class_index,max_nums_train_val_test):
    dict_class_dataset_index_list = {}
    for label in class_labels:
        tot_indices = dict_class_index[label]
        tot_indices_copy = tot_indices.copy()
        random.shuffle(tot_indices_copy)
        train_indices = tot_indices_copy[:max_nums_train_val_test[0]]
        val_indices = tot_indices_copy[max_nums_train_val_test[0]:max_nums_train_val_test[0]+max_nums_train_val_test[1]]
        test_indices = tot_indices_copy[max_nums_train_val_test[0]+max_nums_train_val_test[1]:max_nums_train_val_test[0]+max_nums_train_val_test[1]+max_nums_train_val_test[2]]
        dict_class_dataset_index_list[label] = [train_indices,val_indices,test_indices]
    return dict_class_dataset_index_list

def get_feats4pickle(class_labels,dict_labels_encoded,data_filename4saving,max_num_samples,dict_class_dataset_index_list,paths_list,labels_list,feature_type,num_filters,time_step,frame_width,limit=None,delta=False,noise_wavefile=None,vad=False,dataset_index=0):
    msg = "\nExtracting features from {} samples. \nFeatures will be saved in the file {}".format(max_num_samples,data_filename4saving)
    print(msg)

    for label in class_labels:
        paths_list_dataset = []
        labels_list_dataset = []
        train_val_test_index_list = dict_class_dataset_index_list[label]
        #print(train_val_test_index_list[dataset_index])
        for k in train_val_test_index_list[dataset_index]:
            paths_list_dataset.append(paths_list[k])
            labels_list_dataset.append(labels_list[k])

        print("Extracting features from class: {}".format(label))

    #train_feats = Parallel(n_jobs=num_cores)(
        #delayed(all_feats)('./data/audio_train_trim/' + x + '.npy')
        #for x in tqdm(train.fname.values))

    #train_feats_df = pd.DataFrame(np.vstack(train_feats))

        for j, wav in enumerate(paths_list_dataset):
            if limit and j > limit:
                break
            else:
                feats = coll_feats_manage_timestep(time_step,frame_width,wav,feature_type,num_filters,delta=False, noise_wavefile=noise_wavefile,vad = True)
                np.save(data_filename4saving+"_"+label+"_.npy",feats)

    return True

def coll_feats_manage_timestep(time_step,frame_width,wav,feature_type,num_filters,delta=False,noise_wavefile=None,vad = True):
    feats = get_feats(wav,feature_type,num_filters,delta=False,noise_wavefile=noise_wavefile,vad = True)
    max_len = frame_width*time_step
    print(feats.shape)
    if feats.shape[0] < max_len:
        diff = max_len - feats.shape[0]
        feats = np.concatenate((feats,np.zeros((diff,feats.shape[1]))),axis=0)
    else:
        feats = feats[:max_len,:]
    print(feats.shape)
    return feats


import numpy as np
import random

def calculator(input1, cal, input2=0):

    a, num1 = load_a(input1, cal)
    if cal == 3:  # 乘法
        b_max = 99 // a
        b = random.randint(1, b_max)
        c = a * b
        num2 = b

    if cal == 4:  # 除法
        b = factorization(a)
        c = a / b
        num2 = b

    if cal == 1:  # 加法
        if input1 == 0:
            if input2 == 0:
                b_max = 100 - a
                b = random.randint(1, b_max+1)
                num2 = b
            else:
                b = ans[step-1]
                a_max = 99 - int(b)
                a = random.randint(1, a_max+1)
                num1 = a
                num2 = input2
        else:
            if input2 == 0:
                b_max = 100 - a
                b = random.randint(1, b_max+1)  # 加1，防止b_max = 0,
                num2 = b
            else:
                b = ans[step-1]
                a = ans[step - 2]
                num1 = input1
                num2 = input2
        c = a + b

    if cal == 2:  # 减法
        if input1 == 0:
            if input2 == 0:
                b_max = a
                b = random.randint(1, b_max)
                num2 = b
            else:
                b = ans[step-1]
                a = random.randint(b, 100)
                num1 = a
                num2 = input2
        else:
            if input2 == 0:
                b = random.randint(1, a)
                num2 = b
            else:
                b = ans[step-1]
                a = ans[step-2]
                num1 = input1
                num2 = input2
        c = a - b
    return num1, num2, c

def load_a(input1, cal):
    if input1 == 0:
        if cal == 3:
            a = random.randint(1, 49)
        else:
            a = random.randint(1, 99)
        num1 = a
    else:
        a = ans[step-1]
        num1 = input1
    return a, num1

def factorization(num):
    factor = []
    for i in range(2, num):
        while i != num:
            if num % i == 0:
                factor.append(i)
                num = num / i
            else:
                break
    long = len(factor)
    random.shuffle(factor)
    aa = random.randint(0, long)
    out = int(np.prod(factor[:aa]))
    return out

calc_trans = {1: '+',
              2: '-',
              3: '*',
              4: '/'}

num_formula = 20
results = []
for i in range(num_formula):
    num_cal = random.randint(2, 3)
    calculators_num = np.random.randint(1, 4.1, size=num_cal)
    result = [0] * (2 * num_cal + 1)
    ans = [0]*num_cal
    step = 0

    for index, cal in enumerate(calculators_num):
        if cal > 2.5:  # 先算乘除
            result[index * 2 + 1] = calc_trans[cal]
            result[index * 2], result[index * 2 + 2], ans[step] = calculator(result[index * 2], cal)  # 乘除运算符后面的数一定没有生成呢
            step += 1

    for index, cal in enumerate(calculators_num):
        if cal < 2.5:  # 再算加减
            result[index * 2 + 1] = calc_trans[cal]
            result[index * 2], result[index * 2 + 2], ans[step] = calculator(result[index * 2], cal, result[index * 2 + 2])  # 加减运算符前后的数可能都生成过了
            step += 1
    result.append('=')
#    result.append(ans[-1])
    results.append(result)

t=''
with open ('subject.txt','w') as q:
    for result in results:
        for i in result:
            t += str(i)+' '
        q.write(t.strip(' '))
        q.write('\n')
        t=''

print(results[:])


import species, jobs, items, story

from random import randint
from time import sleep
import sys, os

def log(message):
    '''Game log'''
    message = str(message).replace('_', ' ').title()
    print(message)

def read_sentence(text, seconds = 0.2, clear_time = 3):
    print('')
    for character in text:
        print(character, end = '')
        sys.stdout.flush()
        sleep(seconds)
    if text in list(story.questions):
        print('')
        answers = story.questions[text]
        n = 0
        for answer in answers:
            n += 0
            print(n, ' -> ', answer)
        number = input('\nEnter a number: ')
        return answers[number - 1]
    sleep(clear_time)
    os.system('cls')

class Dice():
    def __init__(self, faces):
        '''Generate a x faces dice'''
        self.faces = int(faces)
        log('dice D{} created'.format(faces))
    def roll(self) -> int:
        face = randint(1, self.faces)
        log('dice rolled (Face: {}/{})'.format(face, self.faces))
        return face

class Character():
    def __init__(self, specie, gender, name):
        '''Generate a character with: specie, gender, name'''
        self.specie = specie
        self.gender = gender
        self.name = name
        self.job = None
        self.stats = species.superiors.species[specie]
        self.gold = 0
        self.bag = []
        self.equipped = {
            'weapon' : None,
            'shield' : None,
            'helmet' : None,
            'armor' : None,
            'gloves' : None,
            'pants' : None,
            'boots' : None,
        }
        log('{} character {} created'.format(specie, self.name))
    def add_stats(self, stats):
        pass
    def remove_stats(self, stats):
        pass
    def set_job(self, job):
        '''Set Job'''
        pass
    def get_item(self, item_name):
        '''Get item'''
        item = items.items[item_name]
        if self.stats['max_cap'] - self.stats['cap'] > item['cap']:
            self.bag.append(item_name)
            self.stats['cap'] += item['cap']
            log('{} get {} (Cap: {}/{})'.format(self.name, item_name, self.stats['cap'], self.stats['max_cap']))
        else:
            log('{} is full'.format(self.name))
    def equip_item(self, item_name):
        pass
    def unequip_item(self, item_name):
        pass
    def damaged(self, damage):
        '''Lost damage'''
        if self.stats['life'] > damage:
            self.stats['life'] -= damage
            log('{} lost {} damage (Life: {}/{})'.format(self.name, damage, self.stats['life'], self.stats['max_life']))
        else:
            self.stats['life'] = 0
            log('{} died'.format(self.name))

class Story():
    def __init__(self):
        self.chapter = 1
        self.choices = []
        self.story = story.chapters

# Tests:
def test_combat():
    dice = Dice(20)
    sleep(1)
    player1 = Character('elf', 'm', 'legolas')
    sleep(1)

    while player1.stats['life'] > 0:
        damage = dice.roll()
        player1.damaged(damage)
        sleep(1)

def test_get_items():
    player1 = Character('elf', 'm', 'legolas')
    sleep(1)
    item1 = 'leather_armor'
    item1_stats = items.items[item1]

    while player1.stats['max_cap'] - player1.stats['cap'] > item1_stats['cap']:
        player1.get_item(item1)
        sleep(1)
    player1.get_item(item1)

def test_story():
    tale = Story()
    text_title = list(tale.story)[0]
    text = tale.story[text_title]
    read_sentence(text[0])
    read_sentence(text[1])
    read_sentence(text[2])
    print(read_sentence(text[3]))

#test_combat()
#test_get_items()
test_story()


import os
import pandas as pd
import string
import re
from cleaning import *
# Config
ORIGIN = "/home/iiraven/ASRI/raw_files/"
LM_ORIGIN = "/home/iiraven/ASRI/lm/"
DEV_SET = {'path':ORIGIN+"dev.tsv",'name':'dev'}
TEST_SET =  {'path':ORIGIN+"test.tsv",'name':'test'}
TRAIN_SET = {'path':ORIGIN+"train.tsv",'name':'train'}
OTHER_SET = {'path':ORIGIN+"other.tsv",'name':'other'}
INVALIDATED_SET = {'path':ORIGIN+"invalidated.tsv",'name':'invalidated'}
VALIDATED_SET = {'path':ORIGIN+"validated.tsv",'name':'validated'}
SETS = [DEV_SET,TEST_SET,TRAIN_SET,OTHER_SET,INVALIDATED_SET,VALIDATED_SET]

# Helpes
def load_files(path):
    df = pd.read_csv(path,delimiter="\t")
    return df

def create_text_file():
    with open(LM_ORIGIN+'lm_text.txt','w',encoding='utf-8') as f:
        pass

def save_text(text):
    with open(LM_ORIGIN+'lm_text.txt','a',encoding='utf-8') as f:
        f.write(text+" ")

# Generate text
create_text_file()
for path in SETS:
    print("** Start generating corpus from : "+path['name']+' dataset')
    df = load_files(path['path'])
    for index,row in df.iterrows():
        save_text(row.sentence+'\n')

print("Your copurs is ready in "+LM_ORIGIN+"lm_text.txt")


from django.urls import path

from .mlfunctions import detect_cont, capture_face
from .views import index, add_class, add_student, dirss, filess, csv_data, login_request, logout_request, stu_list

urlpatterns = [
    path('', index, name='home'),
    # path('cap', capture_face, name='capture'),
    path('stlist',stu_list,name='stu-list'),
    path('add', add_class, name='add_class'),
    path('adds', add_student, name='add-student'),
    path('detect', detect_cont, name='detect'),
    path('files/<date_input>', filess, name='files'),
    path('data/<file_name>/<path>', csv_data, name='data'),
    path('dirs', dirss, name='dirss'),
    path('login/', login_request, name='login'),
    path("logout", logout_request, name="logout"),
    # path('logout', django.contrib.auth.views.LogoutView, {'next_page': '/'}, name='logout'),
]


#!/usr/bin/env python3

import speech_recognition as sr
import os
import re

p = re.compile('^(.*)[\\\-]', re.IGNORECASE)

while True:

	soundboard_dir = os.environ['SOUNDBOARD']
	for file in os.listdir(soundboard_dir):

		name_match = p.match(file)
		name = ""
		if name_match:
			name = name_match.group(1)
			name = name.replace("-", "+")
			name = name.replace("_", "/")

			# Record Audio
			r = sr.Recognizer()
			try:
				with sr.AudioFile(soundboard_dir + "/" + file) as source:
					audio = audio = r.record(source)

				# Speech recognition using Google Speech Recognition
				# for testing purposes, we're just using the default API key
				# to use another API key, use `r.recognize_google(audio, key="GOOGLE_SPEECH_RECOGNITION_API_KEY")`
				# instead of `r.recognize_google(audio)`
				print(name + " said: " + r.recognize_google(audio))
			except sr.UnknownValueError:
				pass
				#print("Google Speech Recognition could not understand audio")
			except sr.RequestError as e:
				print("Could not request results from Google Speech Recognition service; {0}".format(e))
			except EOFError:
				continue

		os.remove(soundboard_dir + "/" + file)


import cv2
import numpy as np
import constants
import mouse

class EyeDetector:
    """
    Eye detection, gaze detection, and mouse pointer movement.
    """

    def __init__(self):

        # The landmarks from face landmark predictor.
        self.landmarks = None

    ###################################################################
    # Eye image processing section
    ###################################################################

    def __get_region(self, landmark_index):
        """
        Get the landmarks based on the index.
        :param landmark_index: find landmarks from 'constants.' like constants.LEFT_PUPIL_LANDMARK.
        :return: an array of [x, y] points of landmarks
        """

        # initialze with zeros and replace them with xy coords
        region = np.zeros(shape=(len(landmark_index), 2), dtype=np.int32)

        for i, point in enumerate(landmark_index):
            region[i] = self.landmarks[point]

        return region

    ###################################################################
    # Gaze detection section
    ###################################################################

    def __get_horizontal_pupil_direction(self):
        """
        Calculate the horizontal gaze direction based on certain horizontal thresholds.
        :return: constants.LEFT, RIGHT, or CENTER
        """

        # get center x between pupils
        left_pupil = self.__get_region(constants.LEFT_PUPIL_LANDMARK)[0]
        right_pupil = self.__get_region(constants.RIGHT_PUPIL_LANDMARK)[0]
        center_x = int((left_pupil[0] + right_pupil[0]) / 2)

        # get the x direction threshold
        # I needed landmarks that will act as x-thresholds to determine left and right.
        # Nose is the part in the body the moves the least, do it will be a good reference point.
        nose_left_x, nose_left_y = self.__get_region(constants.NOSE_TIP_LANDMARK_LEFT)[0]
        nose_right_x, nose_right_y = self.__get_region(constants.NOSE_TIP_LANDMARK_RIGHT)[0]

        # check direction
        if center_x < nose_left_x:
            return constants.LEFT
        elif center_x > nose_right_x:
            return constants.RIGHT
        else:
            return constants.CENTER

    def __get_vertical_pupil_direction(self):
        """
        Calculate the vertical gaze direction based on certain vertical thresholds.
        :return: constants.UP, DOWN, or CENTER
        """
        # get average y between pupils
        left_pupil = self.__get_region(constants.LEFT_EYELID_TOP_LANDMARK)[0]
        right_pupil = self.__get_region(constants.RIGHT_EYELID_TOP_LANDMARK)[0]
        average_y = int((left_pupil[1] + right_pupil[1]) / 2)

        nose_lower_x, nose_lower_y = self.__get_region(constants.NOSE_TIP_LANDMARK_LOW)[0]
        nose_higher_x, nose_higher_y = self.__get_region(constants.NOSE_TIP_LANDMARK_HIGH)[0]

        # Vertical gaze detection is a bit less intuitive than horizontal gaze detection.
        # I cannot use the pupil's relative position against the eye to determine
        # its vertical position. It's due to the limitation of MediaPipe face mesh:
        # the iris landmarks always stay within the eye fissure landmarks.
        # In other words, if the person looks up and the iris moves up,
        # the entire eye landmarks will follow the iris instead of just the iris moving up.
        # So, instead of using the pupil's relative position against the eye fissure as
        # the measure to determine its vertical motion,
        # I measured its distance to the tip of the nose.
        nose2nose = nose_lower_y - nose_higher_y + 1
        nose2iris = nose_lower_y - average_y
        ratio = nose2iris / nose2nose

        # check direction
        if ratio > constants.NOSE2EYE_RATIO_UP_THRESH:
            return constants.UP
        elif ratio < constants.NOSE2EYE_RATIO_DOWN_THRESH:
            return constants.DOWN
        else:
            return constants.CENTER

    def __move_mouse_with_gaze(self):
        """
        Move the mouse pointer based on the gaze.
        :return:
        """
        hor_dir = self.__get_horizontal_pupil_direction()
        ver_dir = self.__get_vertical_pupil_direction()

        mouse.move_mouse_pointer_4dir(hor_dir, ver_dir)

        return hor_dir, ver_dir

    def apply_face_center_mask(self, image):
        """
        Highlight the human outline on the webcam image to
        help the user center their body for better tracking.
        :param image:
        :return:
        """

        head_center_coordinates = (320, 260)
        head_axesLength = (125, 150)

        body_center_coordinates = (320, 500)
        body_axesLength = (225, 100)

        angle = 0
        startAngle = 0
        endAngle = 360
        color = (255, 255, 255)
        thickness = -1

        mask = np.zeros(shape=(480, 640), dtype=np.uint8)

        mask = cv2.ellipse(mask, head_center_coordinates, head_axesLength,
                           angle, startAngle, endAngle, color, thickness)

        mask = cv2.ellipse(mask, body_center_coordinates, body_axesLength,
                           angle, startAngle, endAngle, color, thickness)

        return cv2.bitwise_and(image, image, mask=mask)

    def __show_info_window(self, image, head_rotation, hor_dir, ver_dir):
        """
        Display the window that describes the status of gaze detection.

        :param image:
        :param head_rotation:
        :param hor_dir:
        :param ver_dir:
        :return:
        """

        # blur the rest of face for privacy
        blurred_image = cv2.blur(image, (21, 21))
        blurred_image = cv2.cvtColor(blurred_image, cv2.COLOR_BGR2GRAY)
        blurred_image = cv2.cvtColor(blurred_image, cv2.COLOR_GRAY2BGR)

        # draw iris
        iris_region_l = self.__get_region(constants.LEFT_IRIS_LANDMARKS)
        iris_region_r = self.__get_region(constants.RIGHT_IRIS_LANDMARKS)

        # only reveal the area near eyes
        minx = np.min(iris_region_l[:, 0]) - 15
        maxx = np.max(iris_region_r[:, 0]) + 15
        miny = np.min(iris_region_l[:, 1]) - 5
        maxy = np.max(iris_region_r[:, 1]) + 5

        blur_mask = np.zeros(shape=image.shape, dtype=np.uint8)
        blur_mask = cv2.rectangle(blur_mask, (minx, miny), (maxx, maxy), (255, 255, 255), -1)
        image = np.where(blur_mask == (255, 255, 255), image, blurred_image)

        # apply another mask
        image = self.apply_face_center_mask(image)

        (lx, ly), lr = cv2.minEnclosingCircle(iris_region_l)
        lr = int(lr)
        lx = int(lx)
        ly = int(ly)

        (rx, ry), rr = cv2.minEnclosingCircle(iris_region_r)
        rr = int(rr)
        rx = int(rx)
        ry = int(ry)

        cv2.circle(image, (lx, ly), lr, (0, 0, 255), 2)
        cv2.circle(image, (rx, ry), rr, (0, 0, 255), 2)

        head_rot_color = (255, 255, 255)

        if head_rotation != constants.CENTER:
            head_rot_color = (0, 0, 255)

            cv2.putText(image, 'Align yourself to the outline and', (20, 110),
                        cv2.FONT_HERSHEY_SIMPLEX, 0.8, head_rot_color, 2)
            cv2.putText(image, 'face the camera for better result.', (20, 140),
                        cv2.FONT_HERSHEY_SIMPLEX, 0.8, head_rot_color, 2)

        cv2.putText(image, f'Head rotation: {head_rotation}', (20, 80), cv2.FONT_HERSHEY_SIMPLEX, 1, head_rot_color, 2)

        return image

    def update(self, landmarks, bgr_img, eye_closed, head_rotation):
        """
        Update the gaze detection and control the mouse.
        """
        self.landmarks = landmarks

        hor_dir = None
        ver_dir = None

        if not eye_closed and head_rotation == constants.CENTER:
            hor_dir, ver_dir = self.__move_mouse_with_gaze()
            bgr_img = self.__show_info_window(bgr_img, head_rotation, hor_dir, ver_dir)
            bgr_img = draw_arrow(bgr_img, hor_dir, ver_dir)
            return bgr_img

        return self.__show_info_window(bgr_img, head_rotation, hor_dir, ver_dir)

def draw_arrow(image, hor_dir, ver_dir):
    """
    Draw the directional arrow on the image

    :param image:
    :param hor_dir:
    :param ver_dir:
    :return:
    """
    radius = 80

    start_point = (270, radius + 20)

    # End coordinate
    end_x = start_point[0]
    end_y = start_point[1]

    if ver_dir == constants.UP:
        end_y -= radius
    elif ver_dir == constants.DOWN:
        end_y += radius

    if hor_dir == constants.LEFT:
        end_x -= radius
    elif hor_dir == constants.RIGHT:
        end_x += radius

    # Red color in BGR
    color = (0, 255, 0)

    # Line thickness
    thickness = 5

    image = cv2.arrowedLine(image, start_point, (end_x, end_y),
                            color, thickness, tipLength=0.2)
    return image


from matplotlib import pyplot as plt
import cv2

#In open cv the color of the image is in BGR format
#in matplotlib the color of the image is in RGB format
img = cv2.imread('lena.jpg')
cv2.imshow('image',img)
img = cv2.cvtColor(img,cv2.COLOR_BGR2RGB)
plt.xticks([]),plt.yticks([]) #this will remove the x and y coordinates marker
plt.imshow(img) #this will store the images into the matplotlib eindow
plt.show()   #this will show the matplotlib window
cv2.waitKey(0)
cv2.destroyAllWindows()


#swea 2056. 연월일 달력 D1
#얘가 D1 중에 젤 까다로운 듯
# 이 문제 풀어서 D1 클리어!!
# https://swexpertacademy.com/main/code/problem/problemDetail.do?problemLevel=1&contestProbId=AV5QLkdKAz4DFAUq&categoryId=AV5QLkdKAz4DFAUq&categoryType=CODE&problemTitle=&orderBy=FIRST_REG_DATETIME&selectCodeLang=PYTHON&select-1=1&pageSize=10&pageIndex=1
# https://haerang94.tistory.com/167

num = int(input())
daylist=[0,31,28,31,30,31,30,31,31,30,31,30,31]

for j in range(1,num+1):
    print(f'#{j}', end=' ' )

    #연월일 나누기
    date=input()
    year=int(date[:4])
    month=int(date[4:6])
    day=int(date[6:])

    #달: 0 초과 12 이하
    if (month <1 or month >12):
        print('-1')
        continue
    #일: range(0 초과 해당일) 사이에 있는지?
    if day not in range(1,daylist[month]+1):
        print('-1')
        continue
    else:
        print(f'{date[:4]}/{date[4:6]}/{date[6:]}')


from __future__ import unicode_literals

from django.db import models, migrations

class Migration(migrations.Migration):

    dependencies = [
        ('kerb_auth', '0001_initial'),
    ]

    operations = [
        migrations.AddField(
            model_name='user',
            name='last_connected',
            field=models.DateTimeField(null=True, verbose_name='date last connected to service', blank=True),
        ),
    ]


# Sorting01 [10989]_py  Not Work by Memory exceeded
# Memory limit = 8MB  <---- This is the challenge part
import sys
n = int(sys.stdin.readline())
arr=[0]*10001 # use one array and update
for _ in range(n):
    # index is the number
    # count it if its more
    arr[(int(sys.stdin.readline()))] +=1;
for i in range(10001):
    # print index (count)times when avaiable
    if arr[i] !=0 :
        for _ in range(arr[i]):
            print(i)


from django.db import models
from django.contrib.auth.models import User

class Base(models.Model):
    created = models.DateTimeField(auto_now_add=True)
    updated = models.DateTimeField(auto_now=True)

    class Meta:
        abstract = True

class Employee(Base):
    user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='employees')
    cpf = models.CharField('CPF', max_length=14, unique=True)

    def __str__(self):
        return f'{self.user}'


"""
En base a las instrucciones dadas por la docente usted debe generar un modelo matemático para
programar la suma de n número usando python. Recuerde que el programa debe ser genérico es decir
puede sumar la cantidad de números que el usuario desee.

Autor: Ednan Josué Merino Calderón

Versión:1.0
"""

def suma_consecutiva():
    """
    Suma consecutivamente los números desde 1 hasta el que decida el usuario
    ------------
    Retorna:
    ------------
    La suma de 1 hasta n
    """
    #Mientras sea verdadero
    while True:
        #Manejo de excepciones
        try:
            #Se le pide al usuario que ingrese un número entero para sumar
            n = int(input("Ingrese cuántos números desea sumar: "))
            #Sentencia que permite para un bucle
            break
        #Si se produce una excepción/error
        except ValueError:
            #Se le notifica al usuario que no ingreso correctamente lo solicitado
            print("El valor introducido no es un número. Intenta de nuevo")
    #Se inicializa la variable m en 0
    m=0
    #Para un valor i, dentro del rango 1 y el número ingresado
    for i in range (1,n+1):
        #Se imprimen los números
        print(i)
        #La suma es la variable m
        m=m+i
    #Se imprime la solución
    print("La suma de los primeros",n,"números naturales es:",m)

def suma_n_numeros():
    """
    Se le pide al usuario que ingrese cierta cantidad de números para sumar
    ------------
    Retorna:
    ------------
    La suma de los números ingresados por teclado
    """
    #Mientras sea verdadero
    while True:
        #Manejo de excepciones
        try:
            #Se le pide al usuario que ingrese una cantidad de número para sumar
            n=int(input("Ingrese cuántos números va a sumar: "))
            #Sentencia que permite parar un bucle
            break
        #Si se produce una excepción o error
        except ValueError:
            #Se le notifica al usuario que su valor no es un número
            print("El valor introducido no es un número. Intenta de nuevo")
    #Inicializamos la variable m con 0
    m=0
    #Bucle mientras n sea mayor que 0
    while n>0:
        #Mientras sea verdadero
        while True:
            #Manejo de excepciones
            try:
                #Se le pide al usuario que ingrese un número
                numero=int(input("Ingrese un Número: "))
                #Sentencia que permite parar un bucle
                break
            #Si se produce una excepción/error
            except ValueError:
                #Se le notifica al usuario que no ingresó un número correctamente
                print("El valor introducido no es un número. Intenta de nuevo")
        #La variable m es igual a m+suma de dígitos
        m=m+numero
        #Se finaliza el ciclo
        n=n-1
    #Se imprime la suma
    print("La suma es:",m)

def menu():
    """
    Llama a la función menú para elegir un conjunto de opciones
    ------------
    El parámetro es la opción a elegir

    Retorna:
    ------------
    Retorna la opción elegida
    """
    opcion = ""
    #mientras la opcion sea diferente de 3
    while opcion != "3":
        #menu se ejcutara
        menu = """
        SUMA GENÉRICA POR JOSUÉ MERINO
        ------------------------
        1. Suma Consecutiva
        2. Suma de n números
        3. Salir
        ------------------------
        Elija su opción: """
        #opcion es igual a la entrada que debemos a menu
        opcion = input(menu)
        #si la opcion es 1
        if opcion == "1":
            #llamammos a la funcion suma consecutiva
            suma_consecutiva()
            break
        if opcion == "2":
            #Llamamos a la función suma de n números
            suma_n_numeros()
            break
#Es el main del aplicativo
if __name__=="__main__":
    #Llama a la función menú.
    menu()


# -*- coding: utf-8 -*-
#
from wechat.wrapper import WeChatHandler
from wechat.models import Activity, Ticket, User
import datetime
import json

__author__ = "Epsirom"

class ErrorHandler(WeChatHandler):

    def check(self):
        return True

    def handle(self):
        return self.reply_text('对不起，您输入的信息不规范，请重试')

class DefaultHandler(WeChatHandler):

    def check(self):
        return True

    def handle(self):
        return self.reply_text('对不起，没有找到您需要的信息:(')

class HelpOrSubscribeHandler(WeChatHandler):

    def check(self):
        return self.is_text('帮助', 'help') or self.is_event('scan', 'subscribe') or \
               self.is_event_click(self.view.event_keys['help'])

    def handle(self):
        return self.reply_single_news({
            'Title': self.get_message('help_title'),
            'Description': self.get_message('help_description'),
            'Url': self.url_help(),
        })

class UnbindOrUnsubscribeHandler(WeChatHandler):

    def check(self):
        return self.is_text('解绑') or self.is_event('unsubscribe')

    def handle(self):
        self.user.student_id = ''
        self.user.save()
        return self.reply_text(self.get_message('unbind_account'))

class BindAccountHandler(WeChatHandler):

    def check(self):
        return self.is_text('绑定') or self.is_event_click(self.view.event_keys['account_bind'])

    def handle(self):
        return self.reply_text(self.get_message('bind_account'))

class BookEmptyHandler(WeChatHandler):

    def check(self):
        return self.is_event_click(self.view.event_keys['book_empty'])

    def handle(self):
        return self.reply_text(self.get_message('book_empty'))

class BookWhatHandler(WeChatHandler):

    def check(self):
        return self.is_event_click(self.view.event_keys['book_what'])

    def handle(self):
        acts = Activity.objects.filter(book_end__gte=datetime.datetime.now()).order_by('start_time')
        answer = []
        for index in range(0, len(acts)):
            if index >= 5:
                break
            answer.append({
                'Title': acts[index].name,
                'Description': acts[index].description,
                'Url': self.url_act(acts[index].id),
            })
        return self.reply_news(answer)

class GetTicketHandler(WeChatHandler):

    def check(self):
        return self.is_event_click(self.view.event_keys['get_ticket'])

    def handle(self):
        tic_flag  = False

        tic = []

        for i in Ticket.objects.all():
            if i.student_id == self.user.student_id and i.status == 1:
                    tic_flag = True
                    tic.append(i)
        answer = []
        if len(tic) == 0:
            return self.reply_text("Sorry, you have no tickets now!")
        for index in range(0, len(tic)):
            if index >= 5:
                break
            answer.append({
                'Title': tic[index].activity.name,
                'Description': tic[index].activity.description,
                'Url': self.url_tic(self.user.open_id, tic[index].unique_id),
            })
        return self.reply_news(answer)

class ClickHeaderHandler(WeChatHandler):
    actid = 0
    def check(self):
        for act in Activity.objects.all():
            if self.is_event_click(self.view.event_keys['book_header'] + str(act.id)):
                ClickHeaderHandler.actid = act.id
                return self.is_event_click(self.view.event_keys['book_header']+str(act.id))
    def handle(self):
        act = Activity.objects.get(id = ClickHeaderHandler.actid)
        currentTime = datetime.datetime.now().timestamp()
        if self.user.student_id:
            if act:
                if act.book_start.timestamp() <= currentTime:
                    if act.book_end.timestamp() > currentTime:
                        if act.remain_tickets > 0:
                            tic = Ticket.objects.filter(student_id= User.objects.get(open_id=self.user.open_id).student_id).filter(activity = act).filter(status = 1)
                            if tic:
                                return self.reply_text("您已经拥有该活动的票了。")
                            tic_id = self.get_ticket_id(act, act.total_tickets - act.remain_tickets)
                            temp = Ticket.objects.create(student_id = User.objects.get(open_id=self.user.open_id).student_id, unique_id = tic_id, activity = act, status = 1)
                            temp.save()
                            act.remain_tickets -= 1
                            act.save()
                            return self.reply_single_news({
                                    'Title':act.name,
                                    'Description':act.description,
                                    'Url':self.url_activity(tic_id),
                            })
                        else:
                            return self.reply_text("抱歉，该活动的票已被抢光。")
                    else:
                        return self.reply_text("抱歉，该活动抢票已结束。")
                else:
                    return self.reply_text("抱歉，该活动尚未开始抢票。")
            else:
                return self.reply_text("对不起，您选择的活动不存在。")
        else:
            return self.reply_text("对不起，您还未绑定学号。")

class BookHeaderHandler(WeChatHandler):

    def check(self):
        return self.is_text_command('抢票')

    def handle(self):
        str = self.input['Content'][3:]
        activity = Activity.objects.filter(key = str)
        currentTime = datetime.datetime.now().timestamp()
        if self.user.student_id:
            if activity:
                for act in activity:
                    if act.book_start.timestamp() <= currentTime:
                        if act.book_end.timestamp() > currentTime:
                            if act.remain_tickets > 0:
                                tic = Ticket.objects.filter(student_id= User.objects.get(open_id=self.user.open_id).student_id).filter(activity = act).filter(status = 1)
                                if tic:
                                    return self.reply_text("您已经拥有该活动的票了。")
                                tic_id = self.get_ticket_id(act, act.total_tickets - act.remain_tickets)
                                temp = Ticket.objects.create(student_id = User.objects.get(open_id=self.user.open_id).student_id, unique_id = tic_id, activity = act, status = 1)
                                temp.save()
                                act.remain_tickets -= 1
                                act.save()
                                return self.reply_single_news({
                                    'Title':act.name,
                                    'Description':act.description,
                                    'Url':self.url_activity(tic_id),
                            })
                            else:
                                return self.reply_text("抱歉，该活动的票已被抢光。")
                        else:
                            return self.reply_text("抱歉，该活动抢票已结束。")
                    else:
                        return self.reply_text("抱歉，该活动尚未开始抢票。")
            else:
                return self.reply_text("对不起，您输入的活动不存在。")
        else:
            return self.reply_text("对不起，您还未绑定学号。")

class CancellHeaderHandler(WeChatHandler):

    def check(self):
        return self.is_text_command('退票')

    def handle(self):
        str = self.input['Content'][3:]
        activity = Activity.objects.filter(key = str)
        currentTime = datetime.datetime.now().timestamp()
        if activity:
            for act in activity:
                if act.book_start.timestamp() <= currentTime:
                    tic = Ticket.objects.get(student_id= User.objects.get(open_id=self.user.open_id).student_id, activity = act, status = 1)
                    if tic:
                        tic.delete()
                        act.remain_tickets += 1
                        act.save()
                        return self.reply_text("退票成功。")
                    else:
                        return self.reply_text("您还尚未拥有该活动的票。")
                else:
                    return self.reply_text("抱歉，该活动尚未开始抢票。")
        else:
            return self.reply_text("对不起，您输入的活动不存在。")

class CalHandler(WeChatHandler):

    def check(self):
        return True

    def handle(self):
        return self.reply_text(eval(self.input['Content']))


# 1.1.1 Disable unused filesystems

import subprocess
import os

file = open("temp.txt","a+")
FS = ["cramfs", "freevxfs", "jffs2", "hfs", "hfsplus", "udf"]
#fixed = subprocess.getoutput("/usr/sbin/modprobe -n -v cramfs | grep 'install /bin/true'")
for g in FS:
    print(g)
    status, output = subprocess.getstatusoutput("/usr/sbin/modprobe -n -v {} | grep 'install /bin/true'".format(g, g))
    print(output)
    #print(status)

    if status == 0:
        print("No Change")
        print("---------------------")
    else:
        file.write("{}\n".format(g))
        print("---------------------")

file.close()

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

#Remediation

file = open("temp.txt", "r")
f = open("/etc/modprobe.d/disablefs.conf", "a+")

for g in file.readlines():
    x = g.strip('\n')
    print(x)
    f.write("install {} /bin/true \n".format(x))
    os.system("rmmod {}".format(x))

f.close()
file.close()


import json

for i in range(1, 7):
    with open("hsk-"+str(i)+"-including-metadata-update.json", "w", encoding="UTF8") as out_file:
        myjson = json.load(open("hsk-"+str(i)+"-including-metadata.json", encoding="UTF8"))
        for word in myjson['words']:
            try:
                word['translation-data'] = {
                    'english': word['english'],
                    'pinyin-numbered': word['pinyin-numbered'],
                    'pinyin': word['pinyin'],
                    'simplified': word['simplified'],
                    'traditional': word['traditional']
                }
                del word['english']
                del word['pinyin-numbered']
                del word['pinyin']
                del word['simplified']
                del word['traditional']
            except KeyError as exc:
                print('did not have that key')
        out_file.write(
            json.dumps(
                myjson,
                indent=4,
                ensure_ascii=False,
                separators=(',', ': ')))


#!/usr/bin/python3
# -*- coding: utf-8 -*-
# @author : liuhefei
# @Time : 2019/8/14 22:21
# @desc: 求出符合要求的素数

# 判断素数
def isPrime(n):
    for i in range(2, n):
        if n % i == 0:
            return False  # n不是素数
    return True  # n是素数

# 求出紧靠n的k个素数
def num(n, k, array):
    i, n = 0, n + 1
    while k > 0:
        if isPrime(n):  # 调用函数isPrime判断n是否是素数
            array[i] = n  # 若n是素数，则将n存入数组array中
            i += 1
            k -= 1
        n += 1

# 文件操作
def filedata():
    array = [0] * 1000
    rf = open('infile.txt', 'r')  # 读infile.txt文件
    wf = open('outfile.txt', 'w')  # 写outfile.txt文件
    # 从infile.txt文件中读取10对(n,k)值
    for i in range(10):
        [n, k] = rf.readline().split()
        n = int(n)
        k = int(k)
        num(n, k, array)  # 调用num函数
        for n in range(k):
            print('%d ' % array[n], file=wf, end='')  # 写文件
        print(file=wf)

    rf.close()  # 关闭infile.txt文件
    wf.close()  # 关闭outfile.txt文件

if __name__ == '__main__':
    array = [0] * 1000
    print('输入整数n和k：')
    n, k = map(int, input().split())
    num(n, k, array)  # 调用num函数
    for n in range(k):
        print(array[n], end=' ')  # 打印出array数组中的每个值
    print('\n')
    filedata()  # 调用filedata函数


from aiogram.types import Message

from loader import dp
from utils import MessageBox
from utils.states import States

@dp.message_handler(commands=["start", "help"])
async def start_and_help(message: Message):
    print(f"{message.from_user.first_name}: {message.text}")
    await message.answer(
        "Приветствую!\nДанный бот создан для поиска самых дешевых железнодорожных билетов. 🔍\n"
        "Чтобы воспользоваться поиском, введите команду /find"
    )

@dp.message_handler(commands=["find"], state="*")
async def find_ticket(message: Message):
    print(f"{message.from_user.first_name}: {message.text}")
    message_ = await message.answer(text="Приступим к поиску! 🔍\nВведите название пункта отправления:")
    MessageBox.put(message=message_, user_id=message.from_user.id)
    await States.waiting_for_departure_station.set()


from collections import defaultdict
from enum import IntEnum
from typing import DefaultDict, Dict, List, NamedTuple, Optional, Set, Tuple

import numpy as np
import torch
from torch.utils.data.dataloader import default_collate
from tqdm.auto import tqdm

from l5kit.data import AGENT_DTYPE, PERCEPTION_LABEL_TO_INDEX
from l5kit.dataset import EgoDataset
from l5kit.dataset.utils import move_to_device, move_to_numpy
from l5kit.geometry import rotation33_as_yaw, transform_points
from l5kit.simulation.dataset import SimulationConfig, SimulationDataset

class TrajectoryStateIndices(IntEnum):
    """Defines indices for accessing trajectory states from LocalSceneBatch.
    example: all_speeds = local_scene_batch.recorded_ego_states[:, TrajectoryStateIndices.SPEED]

    :param X: the index for x position
    :param Y: the index for y position
    :param THETA: the index for the angle in radians
    :param SPEED: the index for speed in mps
    :param ACCELERATION: the index for acceleration in mps^2
    :param CURVATURE: the index for curvature (1pm)
    :param TIME: the index for time (seconds)
    """
    X = 0
    Y = 1
    THETA = 2
    SPEED = 3
    ACCELERATION = 4
    CURVATURE = 5
    TIME = 6

class UnrollInputOutput(NamedTuple):
    """ A single input output dict for an agent/ego in a given frame

    :param track_id: the agent track id
    :param inputs: input dict
    :param outputs: output dict
    """
    track_id: int
    inputs: Dict[str, np.ndarray]
    outputs: Dict[str, np.ndarray]

class ClosedLoopSimulatorModes(IntEnum):
    """Defines the different modes for which the closed loop simulator can be used.

    :param L5KIT: the index for using closed loop simulator for L5Kit environment
    :param GYM: the index for using closed loop simulator for Gym environment
    """
    L5KIT = 0
    GYM = 1

class SimulationOutputCLE:
    def __init__(self, scene_id: int, sim_dataset: SimulationDataset,
                 ego_ins_outs: DefaultDict[int, List[UnrollInputOutput]],
                 agents_ins_outs: DefaultDict[int, List[List[UnrollInputOutput]]]):
        """This object holds information about the result of the simulation loop
        for a given scene dataset for close loop evaluation.

        :param scene_id: the scene indices
        :param sim_dataset: the simulation dataset
        :param ego_ins_outs: all inputs and outputs for ego (each frame of each scene has only one)
        :param agents_ins_outs: all inputs and outputs for agents (multiple per frame in a scene)
        """
        if scene_id not in sim_dataset.scene_dataset_batch:
            raise ValueError(f"scene: {scene_id} not in sim datasets: {sim_dataset.scene_dataset_batch}")

        self.scene_id = scene_id
        recorded_dataset = sim_dataset.recorded_scene_dataset_batch[scene_id]
        simulated_dataset = sim_dataset.scene_dataset_batch[scene_id]

        self.simulated_agents = simulated_dataset.dataset.agents
        self.recorded_agents = recorded_dataset.dataset.agents
        self.recorded_ego = recorded_dataset.dataset.frames
        self.simulated_ego = simulated_dataset.dataset.frames

        self.simulated_ego_states = self.build_trajectory_states(self.simulated_ego)
        self.recorded_ego_states = self.build_trajectory_states(self.recorded_ego)

        self.ego_ins_outs = ego_ins_outs[scene_id]
        self.agents_ins_outs = agents_ins_outs[scene_id]

    def get_scene_id(self) -> int:
        """
        Get the scene index for this SimulationOutput

        :return: the scene index
        """
        return self.scene_id

    @staticmethod
    def build_trajectory_states(frames: np.ndarray) -> torch.Tensor:
        """
        Convert frames into a torch trajectory
        :param frames: the scene frames
        :return: the trajectory
        """
        trajectory_states = torch.zeros(len(frames), len(TrajectoryStateIndices), dtype=torch.float)
        translations = frames["ego_translation"]
        rotations = frames["ego_rotation"]

        for idx_frame in range(len(frames)):
            # TODO: there is a conversion from float64 to float32 here
            trajectory_states[idx_frame, TrajectoryStateIndices.X] = translations[idx_frame, 0]
            trajectory_states[idx_frame, TrajectoryStateIndices.Y] = translations[idx_frame, 1]
            trajectory_states[idx_frame, TrajectoryStateIndices.THETA] = rotation33_as_yaw(rotations[idx_frame])
            # TODO: Replace 0.1 by step_time
            trajectory_states[idx_frame, TrajectoryStateIndices.TIME] = 0.1 * idx_frame
            # TODO: we may need to fill other fields

        return trajectory_states

class SimulationOutput(SimulationOutputCLE):
    def __init__(self, scene_id: int, sim_dataset: SimulationDataset,
                 ego_ins_outs: DefaultDict[int, List[UnrollInputOutput]],
                 agents_ins_outs: DefaultDict[int, List[List[UnrollInputOutput]]]):
        """This object holds information about the result of the simulation loop
        for a given scene dataset for close loop evaluation and visualization

        :param scene_id: the scene indices
        :param sim_dataset: the simulation dataset
        :param ego_ins_outs: all inputs and outputs for ego (each frame of each scene has only one)
        :param agents_ins_outs: all inputs and outputs for agents (multiple per frame in a scene)
        """

        super(SimulationOutput, self).__init__(scene_id, sim_dataset, ego_ins_outs, agents_ins_outs)

        # Useful for visualization
        self.recorded_dataset = sim_dataset.recorded_scene_dataset_batch[scene_id]
        self.simulated_dataset = sim_dataset.scene_dataset_batch[scene_id]

class ClosedLoopSimulator:
    def __init__(self, sim_cfg: SimulationConfig, dataset: EgoDataset,
                 device: torch.device,
                 model_ego: Optional[torch.nn.Module] = None,
                 model_agents: Optional[torch.nn.Module] = None,
                 keys_to_exclude: Tuple[str] = ("image",),
                 mode: int = ClosedLoopSimulatorModes.L5KIT):
        """
        Create a simulation loop object capable of unrolling ego and agents
        :param sim_cfg: configuration for unroll
        :param dataset: EgoDataset used while unrolling
        :param device: a torch device. Inference will be performed here
        :param model_ego: the model to be used for ego
        :param model_agents: the model to be used for agents
        :param keys_to_exclude: keys to exclude from input/output (e.g. huge blobs)
        :param mode: the framework that uses the closed loop simulator
        """
        self.sim_cfg = sim_cfg
        if not sim_cfg.use_ego_gt and model_ego is None and mode == ClosedLoopSimulatorModes.L5KIT:
            raise ValueError("ego model should not be None when simulating ego")
        if not sim_cfg.use_agents_gt and model_agents is None and mode == ClosedLoopSimulatorModes.L5KIT:
            raise ValueError("agents model should not be None when simulating agent")
        if sim_cfg.use_ego_gt and mode == ClosedLoopSimulatorModes.GYM:
            raise ValueError("ego has to be simulated when using gym environment")

        self.model_ego = torch.nn.Sequential().to(device) if model_ego is None else model_ego.to(device)
        self.model_agents = torch.nn.Sequential().to(device) if model_agents is None else model_agents.to(device)

        self.device = device
        self.dataset = dataset

        self.keys_to_exclude = set(keys_to_exclude)

    def unroll(self, scene_indices: List[int]) -> List[SimulationOutput]:
        """
        Simulate the dataset for the given scene indices
        :param scene_indices: the scene indices we want to simulate
        :return: the simulated dataset
        """
        sim_dataset = SimulationDataset.from_dataset_indices(self.dataset, scene_indices, self.sim_cfg)

        agents_ins_outs: DefaultDict[int, List[List[UnrollInputOutput]]] = defaultdict(list)
        ego_ins_outs: DefaultDict[int, List[UnrollInputOutput]] = defaultdict(list)

        for frame_index in tqdm(range(len(sim_dataset)), disable=not self.sim_cfg.show_info):
            next_frame_index = frame_index + 1
            should_update = next_frame_index != len(sim_dataset)

            # AGENTS
            if not self.sim_cfg.use_agents_gt:
                agents_input = sim_dataset.rasterise_agents_frame_batch(frame_index)
                if len(agents_input):  # agents may not be available
                    agents_input_dict = default_collate(list(agents_input.values()))
                    agents_output_dict = self.model_agents(move_to_device(agents_input_dict, self.device))

                    # for update we need everything as numpy
                    agents_input_dict = move_to_numpy(agents_input_dict)
                    agents_output_dict = move_to_numpy(agents_output_dict)

                    if should_update:
                        self.update_agents(sim_dataset, next_frame_index, agents_input_dict, agents_output_dict)

                    # update input and output buffers
                    agents_frame_in_out = self.get_agents_in_out(agents_input_dict, agents_output_dict,
                                                                 self.keys_to_exclude)
                    for scene_idx in scene_indices:
                        agents_ins_outs[scene_idx].append(agents_frame_in_out.get(scene_idx, []))

            # EGO
            if not self.sim_cfg.use_ego_gt:
                ego_input = sim_dataset.rasterise_frame_batch(frame_index)
                ego_input_dict = default_collate(ego_input)
                ego_output_dict = self.model_ego(move_to_device(ego_input_dict, self.device))

                ego_input_dict = move_to_numpy(ego_input_dict)
                ego_output_dict = move_to_numpy(ego_output_dict)

                if should_update:
                    self.update_ego(sim_dataset, next_frame_index, ego_input_dict, ego_output_dict)

                ego_frame_in_out = self.get_ego_in_out(ego_input_dict, ego_output_dict, self.keys_to_exclude)
                for scene_idx in scene_indices:
                    ego_ins_outs[scene_idx].append(ego_frame_in_out[scene_idx])

        simulated_outputs: List[SimulationOutput] = []
        for scene_idx in scene_indices:
            simulated_outputs.append(SimulationOutput(scene_idx, sim_dataset, ego_ins_outs, agents_ins_outs))
        return simulated_outputs

    @staticmethod
    def update_agents(dataset: SimulationDataset, frame_idx: int, input_dict: Dict[str, np.ndarray],
                      output_dict: Dict[str, np.ndarray]) -> None:
        """Update the agents in frame_idx (across scenes) using agents_output_dict

        :param dataset: the simulation dataset
        :param frame_idx: index of the frame to modify
        :param input_dict: the input to the agent model
        :param output_dict: the output of the agent model
        :return:
        """

        agents_update_dict: Dict[Tuple[int, int], np.ndarray] = {}

        world_from_agent = input_dict["world_from_agent"]
        yaw = input_dict["yaw"]
        pred_trs = transform_points(output_dict["positions"][:, :1], world_from_agent)[:, 0]
        pred_yaws = yaw + output_dict["yaws"][:, 0, 0]

        next_agents = np.zeros(len(yaw), dtype=AGENT_DTYPE)
        next_agents["centroid"] = pred_trs
        next_agents["yaw"] = pred_yaws
        next_agents["track_id"] = input_dict["track_id"]
        next_agents["extent"] = input_dict["extent"]

        next_agents["label_probabilities"][:, PERCEPTION_LABEL_TO_INDEX["PERCEPTION_LABEL_CAR"]] = 1

        for scene_idx, next_agent in zip(input_dict["scene_index"], next_agents):
            agents_update_dict[(scene_idx, next_agent["track_id"])] = np.expand_dims(next_agent, 0)
        dataset.set_agents(frame_idx, agents_update_dict)

    @staticmethod
    def get_agents_in_out(input_dict: Dict[str, np.ndarray],
                          output_dict: Dict[str, np.ndarray],
                          keys_to_exclude: Optional[Set[str]] = None) -> Dict[int, List[UnrollInputOutput]]:
        """Get all agents inputs and outputs as a dict mapping scene index to a list of UnrollInputOutput

        :param input_dict: all agent model inputs (across scenes)
        :param output_dict: all agent model outputs (across scenes)
        :param keys_to_exclude: if to drop keys from input/output (e.g. huge blobs)
        :return: the dict mapping scene index to a list UnrollInputOutput. Some scenes may be missing
        """
        key_required = {"track_id", "scene_index"}
        if len(key_required.intersection(input_dict.keys())) != len(key_required):
            raise ValueError(f"track_id and scene_index not found in keys {input_dict.keys()}")

        keys_to_exclude = keys_to_exclude if keys_to_exclude is not None else set()
        if len(key_required.intersection(keys_to_exclude)) != 0:
            raise ValueError(f"can't drop required keys: {keys_to_exclude}")

        ret_dict = defaultdict(list)
        for idx_agent in range(len(input_dict["track_id"])):
            agent_in = {k: v[idx_agent] for k, v in input_dict.items() if k not in keys_to_exclude}
            agent_out = {k: v[idx_agent] for k, v in output_dict.items() if k not in keys_to_exclude}
            ret_dict[agent_in["scene_index"]].append(UnrollInputOutput(track_id=agent_in["track_id"],
                                                                       inputs=agent_in,
                                                                       outputs=agent_out))
        return dict(ret_dict)

    @staticmethod
    def get_ego_in_out(input_dict: Dict[str, np.ndarray],
                       output_dict: Dict[str, np.ndarray],
                       keys_to_exclude: Optional[Set[str]] = None) -> Dict[int, UnrollInputOutput]:
        """Get all ego inputs and outputs as a dict mapping scene index to a single UnrollInputOutput

        :param input_dict: all ego model inputs (across scenes)
        :param output_dict: all ego model outputs (across scenes)
        :param keys_to_exclude: if to drop keys from input/output (e.g. huge blobs)
        :return: the dict mapping scene index to a single UnrollInputOutput.
        """
        key_required = {"track_id", "scene_index"}
        if len(key_required.intersection(input_dict.keys())) != len(key_required):
            raise ValueError(f"track_id and scene_index not found in keys {input_dict.keys()}")

        keys_to_exclude = keys_to_exclude if keys_to_exclude is not None else set()
        if len(key_required.intersection(keys_to_exclude)) != 0:
            raise ValueError(f"can't drop required keys: {keys_to_exclude}")

        ret_dict = {}
        scene_indices = input_dict["scene_index"]
        if len(np.unique(scene_indices)) != len(scene_indices):
            raise ValueError(f"repeated scene_index for ego! {scene_indices}")

        for idx_ego in range(len(scene_indices)):
            ego_in = {k: v[idx_ego] for k, v in input_dict.items() if k not in keys_to_exclude}
            ego_out = {k: v[idx_ego] for k, v in output_dict.items() if k not in keys_to_exclude}
            ret_dict[ego_in["scene_index"]] = UnrollInputOutput(track_id=ego_in["track_id"],
                                                                inputs=ego_in,
                                                                outputs=ego_out)
        return ret_dict

    @staticmethod
    def update_ego(dataset: SimulationDataset, frame_idx: int, input_dict: Dict[str, np.ndarray],
                   output_dict: Dict[str, np.ndarray]) -> None:
        """Update ego across scenes for the given frame index.

        :param dataset: The simulation dataset
        :param frame_idx: index of the frame to modify
        :param input_dict: the input to the ego model
        :param output_dict: the output of the ego model
        :return:
        """
        world_from_agent = input_dict["world_from_agent"]
        yaw = input_dict["yaw"]
        pred_trs = transform_points(output_dict["positions"][:, :1], world_from_agent)
        pred_yaws = np.expand_dims(yaw, -1) + output_dict["yaws"][:, :1, 0]

        dataset.set_ego(frame_idx, 0, pred_trs, pred_yaws)


import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import keras

# Abrir csv
covid_df = pd.read_csv('COVID-19_Daily_Testing_-_By_Person.csv')

# Borrar filas NaN
covid_df = covid_df.dropna()

# Ordenar el dataframe según la columna 'Date'
covid_df.sort_values(by=['Date'], inplace=True)

# Borrar columna 'Day'
covid_df = covid_df.drop(['Day', 'Date'], axis=1)

# Insertar columna incremental 'Tiempo'
covid_df.insert(0, 'Tiempo', range(len(covid_df)))

# Creación del modelo
x = covid_df[["People Positive - Age 30-30"]]
x = (x-x.min())/(x.max()-x.min())

y = covid_df[['People Positive - Total']]

model = keras.Sequential([
    keras.layers.Dense(
        1,
        input_shape=(x.shape[1],),
        activation=None
    )
])

# Compilar el modelo
model.compile(
    optimizer=keras.optimizers.SGD(lr=0.001),
    loss='mse',
    metrics=[]
)

# Entrenar el modelo
model.fit(x, y, epochs=100, batch_size=16)

# Predecir
y_predictions = model.predict(x)

# Graficar el resultado en azul vs los datos en rojo
plt.plot(covid_df['Tiempo'], covid_df['People Positive - Total'], 'ro')
plt.plot(covid_df['Tiempo'], y_predictions, 'bo')

plt.xlabel('Tiempo')
plt.ylabel('People Positive - Total')

plt.show()


from ast import Str
from tkinter import *
from tkinter import messagebox

'''
===========================================================
                    FUNCIONALIDAD
===========================================================
'''
#Menu
#Menu BBDD
#mMenú Limpiar
#Menú Ayuda
# Licencia
def licencia():
    # CREATIVE COMMONS GNU GPL https://www.gnu.org/licenses/gpl-3.0.txt
    gnuglp = '''
    Demo de un sistema CRUD en Python para gestión
    de alumnos
    Copyright (C) 2022 - Lisandro "El crack" Suvercase
    Email: lisandro@suvercase.com\n=======================================
    This program is free software: you can redistribute it
    and/or modify it under the terms of the GNU General Public
    License as published by the Free Software Foundation,
    either version 3 of the License, or (at your option) any
    later version.
    This program is distributed in the hope that it will be
    useful, but WITHOUT ANY WARRANTY; without even the
    implied warranty of MERCHANTABILITY or FITNESS FOR A
    PARTICULAR PURPOSE.  See the GNU General Public License
    for more details.
    You should have received a copy of the GNU General Public
    License along with this program.
    If not, see <https://www.gnu.org/licenses/>.'''
    messagebox.showinfo("LICENCIA", gnuglp)

# ACERCA DE

def acerca():
    messagebox.showinfo("ACERCA DE....", "Creado por Lisandro Suvercase \npara Codo a Codo 4.0 - Big Data\n Mayo 2022\nEmail: blabla@hola.com")
'''
===========================================================
                    INTERFAZ GRÁFICA
===========================================================
'''

raiz = Tk()
raiz.title('GUI - Com 22040')

#Barra Menú
barramenu = Menu(raiz) #Menu pertenece a la libreria de Tkinter, dentro le informo donde va a estar, le digo qu eva a estar en mi raiz. #Creo la barra menu
raiz.config(menu=barramenu) #agrega el menú a la ventana principal

bbddmenu = Menu(barramenu, tearoff=0) #Crea submenú BBDD
bbddmenu.add_command(label='Conectar') #Agrega un botón al submenú BBDD
bbddmenu.add_command(label='Salir') #Agrega un botón al submenú BBDD

limpiarmenu = Menu(barramenu,tearoff=0)
limpiarmenu.add_command(label='Limpiar campos')

ayudamenu = Menu(barramenu,tearoff=0)
ayudamenu.add_command(label="Licencia", command=licencia)
ayudamenu.add_command(label="Acerca de...", command=acerca)

barramenu.add_cascade(label='BBDD', menu=bbddmenu)# Crea el botón BBDD y le asigna el submenú
barramenu.add_cascade(label='Limpiar', menu=limpiarmenu)
barramenu.add_cascade(label='Acerca de', menu=ayudamenu)

# FRAMECAMPOS

framecampos = Frame(raiz) #framecampos es el nombre que yo le puse, le puedo poner cualquier nombre, le asigno un objeto (importado de Tkinter) llamado Frame y le digo que va a estar situado en la raiz
framecampos.pack() #el método pack es una forma de acomodar las cosas en una ventana

legajo = StringVar()
alumno = StringVar()
email = StringVar()
calificacion = DoubleVar()
escuela = StringVar()
localidad = StringVar()
provincia = StringVar()

'''
entero = IntVar() #Declara variable de tipo entero
flotante = DoubleVar() #Declara variable de tipo float
cadena = StringVar() #Declara variable del tipo cadena
booleano = BooleanVar() #Declara variable del tipo booleano
'''

legajo_input = Entry(framecampos, textvariable=legajo)
legajo_input.grid(row=0, column=2, padx=10, pady= 10)

alumno_input = Entry(framecampos, textvariable=alumno)
alumno_input.grid(row=1, column=2, padx=10, pady= 10)

email_input = Entry(framecampos, textvariable=email)
email_input.grid(row=2, column=2, padx=10, pady= 10)

calificacion_input =Entry(framecampos, textvariable="Calificacion")
calificacion_input.grid(row=3, column=2, padx=10, pady= 10)

escuela_input = Entry(framecampos, textvariable="Escuela")
escuela_input.grid(row=4, column=2, padx=10, pady= 10)

localidad_input = Entry(framecampos, textvariable="Localidad")
localidad_input.grid(row=5, column=2, padx=10, pady= 10)

provincia_input = Entry(framecampos, textvariable="Provincia")
provincia_input.grid(row=6, column=2, padx=10, pady= 10)

# labels

legajo_label = Label(framecampos,text='Legajo')
legajo_label.grid(row=0, column=1, padx=10, pady=10, sticky='e')

alumno_label = Label(framecampos,text='Alumno')
alumno_label.grid(row=1, column=1, padx=10, pady=10, sticky='e')

email_label = Label(framecampos, text="Email")
email_label.grid(row=2, column=1, padx=10, pady=10, sticky='e')

calificacion_label = Label(framecampos, text="Calificación")
calificacion_label.grid(row=3, column=1, padx=10, pady=10, sticky='e')

escuela_label = Label(framecampos, text="Escuela")
escuela_label.grid(row=4, column=1, padx=10, pady=10, sticky='e')

localidad_label = Label(framecampos, text="Localidad")
localidad_label.grid(row=5, column=1, padx=10, pady=10, sticky='e')

provincia_label = Label(framecampos, text="Provincia")
provincia_label.grid(row=6, column=1, padx=10, pady=10, sticky='e')

#FRAME BOTONERA ----> CRUD(Create, Read, Update, Delete)

framebotones = Frame(raiz)
framebotones.pack()

#CREAR
boton_crear = Button(framebotones, text="Crear")
boton_crear.grid(row=0, column=0, padx=5, pady=10)
#LEER (buscar x nro de legajo)
boton_leer = Button(framebotones, text="Leer")
boton_leer.grid(row=0, column=1, padx=5, pady=10)
#ACTUALIZAR
boton_actualizar = Button(framebotones, text="Actualizar")
boton_actualizar.grid(row=0, column=2, padx=5, pady=10)
#BORRAR
boton_borrar = Button(framebotones, text="Borrar")
boton_borrar.grid(row=0, column=3, padx=5, pady=10)

#FRAME DEL PIE
framecopy = Frame(raiz)
framecopy.pack()

copy_label = Label(framecopy, text='(2022) por Lisandro Suvercase para CaC 4.0 - Big Data')
copy_label.grid(row=0, column=0, padx=10, pady=10)

raiz.mainloop() #nuestra ultima linea tiene que ser el mainloop, mantiene abierta nuestra interfaz gráfica hasta que alguien la cierre.


import os
import datetime
#Os Modülü Nedir?
"""
---İşletim sistemleri hakkında bilgiler, klasör işlemleri, dosya işlemleri os modülü ile yapılabilir
---
"""

result = os.name#Hangi işletim sistemi kullandığımızı çıktı olarak veriri
result = os.getcwd()#Dosya hakkında bilgi verir.Bulunduğu konumu çıktı olarak yazdırır -- Etkin dizini gösterme
#os.mkdir("yenidosya")#Aynı dizin altında yeni dosya oluşturur
#os.chdir()#Change the current working directory to the specified path. --Dizin değiştirme
result = os.listdir()
result = os.listdir('C:\\')
result = os.stat("basic_module.py")#Parametreye girilen dosya hakkında bilgileri verir --Boyut --Değiştirme tarihi -- Açma tarihi...
print(datetime.datetime.fromtimestamp(result.st_atime))#Son erişim tarihi
print(datetime.datetime.fromtimestamp(result.st_ctime))#Oluşturma tarihi
print(datetime.datetime.fromtimestamp(result.st_mtime))#Değiştirme tarihi
"""
Klasor Adı değiştirme
os.rename("klasör adı","yeni isim")
"""
"""
os.rmdir()
os.rmdirs()
--Belirtilen dosya içeriklerini veya dosyaları siler
"""
yol = os.path.abspath("basic_module.py")#Dosyanın tam konumunu çıktı olarak verir
yol = os.path.dirname('C:/Users/fb-du\Desktop\python\module/basic_module.py')#Dosya yolu girilen dosyanın dizin ismini verir
result = os.path.dirname(os.path.abspath('basic_module.py'))
result = os.path.exists('C:/Users/fb-du\Desktop\python\module/basic_module.py')#Dosya var mı yok mu ?
result = os.path.isdir('C:/Users/fb-du\Desktop\python\module/basic_module.py')#Dosya mı?
result = os.path.isfile('C:/Users/fb-du\Desktop\python\module/basic_module.py')

print(yol)
print(result)


# Uses python3
import sys

def optimal_sequence(n):
    dp = [0] * (n + 1)
    dp[1] = 1
    for i in range(1, n + 1):
        dp[i] = dp[i - 1] + 1
        if i % 3 == 0:
            dp[i] = min(dp[i // 3] + 1, dp[i])

        if i % 2 == 0:
            dp[i] = min(dp[i // 2] + 1, dp[i])

    solution = []
    while n > 1:
        solution.append(n)
        if n % 2 == 0 and dp[n // 2] == dp[n] - 1:
            n = n // 2
        elif n % 3 == 0 and dp[n // 3] == dp[n] - 1:
            n = n // 3
        else:
            n -= 1
    solution.append(1)
    return reversed(solution)

input = sys.stdin.read()
n = int(input)
sequence = list(optimal_sequence(n))
print(len(sequence) - 1)
for x in sequence:
    print(x, end=" ")


def splitsum(l):
    AnswerList = []
    pos = 0
    neg = 0
    for i in l:
        if i > 0:
            pos = pos + (i*i)
        elif i < 0:
            neg = neg + (i*i*i)
    AnswerList.append(pos)
    AnswerList.append(neg)
    return AnswerList


import os
from common import (
    DECIMALS,
    ROUNDINGS,
    ROUNDING_TO_ZERO,
    FLAG_INEXACT,
    FLAG_INVALID_OPERATION,
    Context,
    Decimal,
    FlagType,
    write_line,
)

DECIMAL_COUNT = 80_000

# Round is important, so it will have multiple files.
# This will also make tests more 'parallel'.
SEEDS: tuple[int, ...] = (
    1191299818,
    68198198,
)

def write(dir: str):
    for ctx in DECIMALS:
        for index, seed in enumerate(SEEDS):
            decimals = ctx.generate(DECIMAL_COUNT, seed=seed)
            _write_round_file(dir, ctx, index, decimals)
            _write_round_exact_file(dir, ctx, index, decimals)

def _write_round_file(
    dir: str,
    ctx: Context,
    file_index: int,
    decimals: list[Decimal],
):
    operation = "round"
    ctx_python = ctx._python_context

    for rounding in ROUNDINGS:
        file_name = (
            f"{operation}_{ctx.file_header}_{rounding.swift_name}_{file_index}.txt"
        )
        path = os.path.join(dir, file_name)
        print(file_name)

        # The most important line:
        ctx_python.rounding = rounding.python

        with open(path, "w") as f:
            for d in decimals:
                ctx.flags.clear_all()
                result = ctx_python.to_integral_exact(d.value)

                excluded_flags: list[FlagType] = [FLAG_INEXACT]

                if ctx_python.is_snan(d.value):
                    excluded_flags.append(FLAG_INVALID_OPERATION)

                ctx.flags.assert_empty(excluding=excluded_flags)

                write_line(
                    f,
                    context=ctx,
                    operation=operation,
                    rounding=rounding,
                    arguments=[d],
                    expected=Decimal(result),
                )

def _write_round_exact_file(
    dir: str,
    ctx: Context,
    file_index: int,
    decimals: list[Decimal],
):
    operation = "round_exact"

    file_name = f"{operation}_{ctx.file_header}_{file_index}.txt"
    path = os.path.join(dir, file_name)
    print(file_name)

    # Rounding does not matter
    rounding = ROUNDING_TO_ZERO
    ctx_python = ctx._python_context
    ctx_python.rounding = rounding.python

    with open(path, "w") as f:
        for d in decimals:
            ctx.flags.clear_all()
            result = ctx_python.to_integral_exact(d.value)

            excluded_flags: list[FlagType] = [FLAG_INEXACT]

            if ctx_python.is_snan(d.value):
                excluded_flags.append(FLAG_INVALID_OPERATION)

            ctx.flags.assert_empty(excluding=excluded_flags)

            compare = ctx_python.compare(d.value, result)
            is_exact = ctx_python.is_zero(compare)

            if not ctx.flags.is_set(FLAG_INEXACT):
                write_line(
                    f,
                    context=ctx,
                    operation=operation,
                    rounding=rounding,
                    arguments=[d],
                    expected=Decimal(result),
                )


import matplotlib.pyplot as plt
import numpy as np

def create_fig(slots, system, fig_name, title):
    fig = plt.figure(fig_name)
    left, right = fig.subplots(nrows=1, ncols=2)
    fig.suptitle(title)

    left.plot(range(0,slots), system.backlogged_by_slot, color='orange')
    left.set_xlabel('Slot')
    left.set_ylabel('Backlogged nodes')
    left.set_xlim(left=0, right=slots)
    left.set_ylim(bottom=0)

    right.plot(range(0,slots), np.cumsum(system.arrivals_by_slot),\
            color='red', label='Total packet arrivals')
    right.plot(range(0,slots), np.cumsum(system.entering_by_slot), \
            color='blue', label='Total packets entering')
    right.plot(range(0,slots), np.cumsum(system.success_in_slot), \
            color='green', label='Total packets leaving')

    right.legend(loc="lower right")
    right.set_xlabel('Slot')
    right.set_ylabel('Packets')
    right.set_xlim(left=0, right=slots)
    right.set_ylim(bottom=0)

    plt.gcf().set_size_inches(16, 8)

def plot_Q3(slots, system):
    fig_name = 'Q3'
    title = 'Plots for Q3, lambda=1/e and qr=0.01'
    create_fig(slots, system, fig_name, title)

def plot_Q5(slots, system):
    fig_name = 'Q5'
    title = 'Plots for Q5, lambda=1/2 and qr=0.01'
    create_fig(slots, system, fig_name, title)

def plot_Q6(slots, system):
    fig_name = 'Q6'
    title = 'Plots for Q6, lambda=1/e and qr=0.1'
    create_fig(slots, system, fig_name, title)

def plot_Q4(m, backlogged_by_slot, mean_ps_empirical, mean_ps_theoretical):
    max_backed = max(backlogged_by_slot)

    fig = plt.figure('Q4_1')
    plot1, plot2 = fig.subplots(2,1)

    plot1.set_title('Frequency of each backlog value for system in Q3')
    freq1 = np.histogram(backlogged_by_slot, range(m+2))[0].tolist()
    plot1.bar(range(m+1), freq1)
    plot1.set_xlim(-1,max_backed+1)

    plot2.set_title('Normalized frequency of each backlog value for system in Q3')
    freq2 = np.histogram(backlogged_by_slot, range(m+2), density=True)[0].tolist()
    plot2.bar(range(m+1), freq2)
    plot2.set_xlim(-1,max_backed+1)
    plt.gcf().set_size_inches(16, 8)

    plt.figure('Q4_2')
    plt.title('Probability of success comparison')
    plt.plot([mean_ps_empirical]*(max_backed+1), linestyle='dashed',\
         label=('Empirical mean: '+ str(mean_ps_empirical)))
    plt.plot([mean_ps_theoretical]*(max_backed+1), linestyle='dashed', \
        label=('Theoretical mean: '+ str(mean_ps_theoretical)))
    plt.xlim(-1,max_backed + 1)
    plt.ylim(0,1)

    plt.legend()
    plt.gcf().set_size_inches(16, 8)

def plot_Q7(slots, system):
    plt.figure('Q7_1')
    plt.title('True vs estimated backlog using Pseudo-Bayesian stabilization')
    plt.plot(system.n_hat_by_slot, label='Estimated n')
    plt.plot(system.backlogged_by_slot, label='True n')

    plt.xlabel('Slot')
    plt.ylabel('n backlogged nodes')
    plt.xlim(0,slots)
    plt.ylim(bottom=0)
    plt.legend()
    plt.gcf().set_size_inches(16, 8)

    plt.figure('Q7_2')
    plt.plot(range(0,slots), np.cumsum(system.arrivals_by_slot),\
            color='red', label='Total packet arrivals')
    plt.plot(range(0,slots), np.cumsum(system.entering_by_slot), \
            color='blue', label='Total packets entering')
    plt.plot(range(0,slots), np.cumsum(system.success_in_slot), \
            color='green', label='Total packets leaving')

    plt.legend(loc="lower right")
    plt.xlabel('Slot')
    plt.ylabel('Packets')
    plt.xlim(left=0, right=slots)
    plt.ylim(bottom=0)

    plt.gcf().set_size_inches(16, 8)

def plot_Q8(arrival_rates, simulated_avg_delay, theoretical_avg_delay):
    plt.figure('Q8')
    plt.title('Average delay for a successful packet transmission')

    plt.plot(arrival_rates, simulated_avg_delay, linestyle='None', marker='o', \
        label='Empirical')
    plt.plot(arrival_rates, theoretical_avg_delay, linestyle='None', marker='x', \
        label='Theoretical')

    plt.xlabel('Arrival rate')
    plt.ylabel('Average delay')
    plt.legend()
    plt.gcf().set_size_inches(16, 8)


"""
https://leetcode.com/explore/interview/card/top-interview-questions-easy/92/array/559/

Plus One

Given a non-empty array of digits representing a non-negative integer, plus
one to the integer.

The digits are stored such that the most significant digit is at the head of
the list, and each element in the array contain a single digit.

You may assume the integer does not contain any leading zero, except the
number 0 itself.

Example 1:

Input: [1,2,3]
Output: [1,2,4]
Explanation: The array represents the integer 123.
Example 2:

Input: [4,3,2,1]
Output: [4,3,2,2]
Explanation: The array represents the integer 4321.
"""
from typing import List

class Solution:
    def plus_one(self, digits: List[int], j: int = None) -> List[int]:
        """
        modifies the list in place
        """
        if j is None:
            j = len(digits)-1
        digits[j] = (digits[j]+1) % 10
        if digits[j] == 0:
            if j == 0:
                digits.insert(0, 1)
            else:
                return self.plus_one(digits, j-1)

    def plusOne(self, digits: List[int]) -> List[int]:
        digits = digits[:]
        self.plus_one(digits)
        return digits