from tkinter import *
import time
import tkinter.messagebox
#from bot import chat
#from chatgui import send
import pyttsx3
import threading
import nltk
from nltk.stem import WordNetLemmatizer
lemmatizer = WordNetLemmatizer()
import pickle
import numpy as np

from keras.models import load_model
model = load_model('chatbot_model.h5')
import json
import random
intents = json.loads(open('intents.json').read()) # loads converts json to python dictionary
words = pickle.load(open('words.pkl','rb'))
classes = pickle.load(open('classes.pkl','rb'))

saved_username = ["You"]
#ans=["jeff"]
window_size="400x400"

def clean_up_sentence(sentence):
    # tokenize the pattern - split words into array
    sentence_words = nltk.word_tokenize(sentence)
    # stem each word - create short form for word example rocks-->rock
    sentence_words = [lemmatizer.lemmatize(word.lower()) for word in sentence_words]
    return sentence_words

# return bag of words array: 0 or 1 for each word in the bag that exists in the sentence

def bow(sentence, words, show_details=True):
    # tokenize the pattern
    #Tokenizing is the process of breaking the whole text into small parts like words.
    sentence_words = clean_up_sentence(sentence)
    # bag of words - matrix of N words, vocabulary matrix
    bag = [0]*len(words)
    for s in sentence_words:
        for i,w in enumerate(words):
            if w == s:
                # assign 1 if current word is in the vocabulary position
                bag[i] = 1
                if show_details:
                    print ("found in bag: %s" % w)
    return(np.array(bag))

def predict_class(sentence, model):
    # filter out predictions below a threshold
    p = bow(sentence, words,show_details=False)
    res = model.predict(np.array([p]))[0]
    ERROR_THRESHOLD = 0.25
    results = [[i,r] for i,r in enumerate(res) if r>ERROR_THRESHOLD]
    # sort by strength of probability
    results.sort(key=lambda x: x[1], reverse=True)
    return_list = []
    for r in results:
        return_list.append({"intent": classes[r[0]], "probability": str(r[1])})
    return return_list

def getResponse(ints, intents_json):
    tag = ints[0]['intent']
    list_of_intents = intents_json['intents']
    for i in list_of_intents:
        if(i['tag']== tag):
            result = random.choice(i['responses'])
            break
    return result

def chatbot_response(msg):
    ints = predict_class(msg, model)
    res = getResponse(ints, intents)
    return res

#Creating GUI with tkinter
def send(msg):
    if msg != '':
        return chatbot_response(msg)
    else:
        return "Sorry, I am afraid I don't Understand."

class ChatInterface(Frame):

    def __init__(self, master=None):
        Frame.__init__(self, master)
        self.master = master

        # sets default bg for top level windows
        self.tl_bg = "#EEEEEE"
        self.tl_bg2 = "#EEEEEE"
        self.tl_fg = "#000000"
        self.font = "Verdana 10"

        menu = Menu(self.master)
        self.master.config(menu=menu, bd=5)
# Menu bar

    # File
        file = Menu(menu, tearoff=0)
        menu.add_cascade(label="File", menu=file)
       # file.add_command(label="Save Chat Log", command=self.save_chat)
        file.add_command(label="Clear Chat", command=self.clear_chat)
      #  file.add_separator()
        file.add_command(label="Exit",command=self.chatexit)

    # Options
        options = Menu(menu, tearoff=0)
        menu.add_cascade(label="Options", menu=options)

        # username

        # font
        font = Menu(options, tearoff=0)
        options.add_cascade(label="Font", menu=font)
        font.add_command(label="Default",command=self.font_change_default)
        font.add_command(label="Times",command=self.font_change_times)
        font.add_command(label="System",command=self.font_change_system)
        font.add_command(label="Helvetica",command=self.font_change_helvetica)
        font.add_command(label="Fixedsys",command=self.font_change_fixedsys)

        # color theme
        color_theme = Menu(options, tearoff=0)
        options.add_cascade(label="Color Theme", menu=color_theme)
        color_theme.add_command(label="Default",command=self.color_theme_default)
       # color_theme.add_command(label="Night",command=self.)
        color_theme.add_command(label="Grey",command=self.color_theme_grey)
        color_theme.add_command(label="Blue",command=self.color_theme_dark_blue)

        color_theme.add_command(label="Torque",command=self.color_theme_turquoise)
        color_theme.add_command(label="Hacker",command=self.color_theme_hacker)
       # color_theme.add_command(label='Mkbhd',command=self.MKBHD)

        help_option = Menu(menu, tearoff=0)
        menu.add_cascade(label="Help", menu=help_option)
        #help_option.add_command(label="Features", command=self.features_msg)
        help_option.add_command(label="About jeff", command=self.msg)
        help_option.add_command(label="Developers", command=self.about)

        self.text_frame = Frame(self.master, bd=6)
        self.text_frame.pack(expand=True, fill=BOTH)

        # scrollbar for text box
        self.text_box_scrollbar = Scrollbar(self.text_frame, bd=0)
        self.text_box_scrollbar.pack(fill=Y, side=RIGHT)

        # contains messages
        self.text_box = Text(self.text_frame, yscrollcommand=self.text_box_scrollbar.set, state=DISABLED,
                             bd=1, padx=6, pady=6, spacing3=8, wrap=WORD, bg=None, font="Verdana 10", relief=GROOVE,
                             width=10, height=1)
        self.text_box.pack(expand=True, fill=BOTH)
        self.text_box_scrollbar.config(command=self.text_box.yview)

        # frame containing user entry field
        self.entry_frame = Frame(self.master, bd=1)
        self.entry_frame.pack(side=LEFT, fill=BOTH, expand=True)

        # entry field
        self.entry_field = Entry(self.entry_frame, bd=1, justify=LEFT)
        self.entry_field.pack(fill=X, padx=6, pady=6, ipady=3)
        # self.users_message = self.entry_field.get()

        # frame containing send button and emoji button
        self.send_button_frame = Frame(self.master, bd=0)
        self.send_button_frame.pack(fill=BOTH)

        # send button
        self.send_button = Button(self.send_button_frame, text="Send", relief=GROOVE, bg='white',
                                  bd=1,width=5, command=lambda: self.send_message_insert(None), activebackground="#FFFFFF",
                                  activeforeground="#000000")
        self.send_button.pack(side=LEFT, ipady=8)
        self.master.bind("<Return>", self.send_message_insert)

        self.last_sent_label(date="No messages sent.")
        #t2 = threading.Thread(target=self.send_message_insert(, name='t1')
        #t2.start()

    def playResponce(self,responce):
        x=pyttsx3.init()
        #print(responce)
        li = []
        if len(responce) > 100:
            if responce.find('--') == -1:
                b = responce.split('--')
                #print(b)

        x.setProperty('rate',120)
        x.setProperty('volume',100)
        x.say(responce)
        x.runAndWait()
        #print("Played Successfully......")

    def last_sent_label(self, date):

        try:
            self.sent_label.destroy()
        except AttributeError:
            pass

        self.sent_label = Label(self.entry_frame, font="Verdana 7", text=date, bg=self.tl_bg2, fg=self.tl_fg)
        self.sent_label.pack(side=LEFT, fill=X, padx=3)

    def clear_chat(self):
        self.text_box.config(state=NORMAL)
        self.last_sent_label(date="No messages sent.")
        self.text_box.delete(1.0, END)
        self.text_box.delete(1.0, END)
        self.text_box.config(state=DISABLED)

    def chatexit(self):
        exit()

    def msg(self):
        tkinter.messagebox.showinfo("jeff v1.1",'jeff is a chatbot for Making a general conversation\nIt is based on retrival-based NLP using pythons NLTK tool-kit module\nGUI is based on Tkinter\nIt can answer questions regarding many things')

    def about(self):
        tkinter.messagebox.showinfo("jeff Developers","Affan Murtaza")

    def send_message_insert(self, message):
        user_input = self.entry_field.get()
        pr1 = "Human : " + user_input + "\n"
        self.text_box.configure(state=NORMAL)
        self.text_box.insert(END, pr1)
        self.text_box.configure(state=DISABLED)
        self.text_box.see(END)
        #t1 = threading.Thread(target=self.playResponce, args=(user_input,))
        #t1.start()
        #time.sleep(1)
        ob=send(user_input)
        pr="jeff : " + ob + "\n"
        self.text_box.configure(state=NORMAL)
        self.text_box.insert(END, pr)
        self.text_box.configure(state=DISABLED)
        self.text_box.see(END)
        self.last_sent_label(str(time.strftime( "Last message sent: " + '%B %d, %Y' + ' at ' + '%I:%M %p')))
        self.entry_field.delete(0,END)
        time.sleep(0)
        t2 = threading.Thread(target=self.playResponce, args=(ob,))
        t2.start()
        #return ob

    def font_change_default(self):
        self.text_box.config(font="Verdana 10")
        self.entry_field.config(font="Verdana 10")
        self.font = "Verdana 10"

    def font_change_times(self):
        self.text_box.config(font="Times")
        self.entry_field.config(font="Times")
        self.font = "Times"

    def font_change_system(self):
        self.text_box.config(font="System")
        self.entry_field.config(font="System")
        self.font = "System"

    def font_change_helvetica(self):
        self.text_box.config(font="helvetica 10")
        self.entry_field.config(font="helvetica 10")
        self.font = "helvetica 10"

    def font_change_fixedsys(self):
        self.text_box.config(font="fixedsys")
        self.entry_field.config(font="fixedsys")
        self.font = "fixedsys"

    def color_theme_default(self):
        self.master.config(bg="#EEEEEE")
        self.text_frame.config(bg="#EEEEEE")
        self.entry_frame.config(bg="#EEEEEE")
        self.text_box.config(bg="#FFFFFF", fg="#000000")
        self.entry_field.config(bg="#FFFFFF", fg="#000000", insertbackground="#000000")
        self.send_button_frame.config(bg="#EEEEEE")
        self.send_button.config(bg="#FFFFFF", fg="#000000", activebackground="#FFFFFF", activeforeground="#000000")
        #self.emoji_button.config(bg="#FFFFFF", fg="#000000", activebackground="#FFFFFF", activeforeground="#000000")
        self.sent_label.config(bg="#EEEEEE", fg="#000000")

        self.tl_bg = "#FFFFFF"
        self.tl_bg2 = "#EEEEEE"
        self.tl_fg = "#000000"

    # Dark
    def color_theme_dark(self):
        self.master.config(bg="#2a2b2d")
        self.text_frame.config(bg="#2a2b2d")
        self.text_box.config(bg="#212121", fg="#FFFFFF")
        self.entry_frame.config(bg="#2a2b2d")
        self.entry_field.config(bg="#212121", fg="#FFFFFF", insertbackground="#FFFFFF")
        self.send_button_frame.config(bg="#2a2b2d")
        self.send_button.config(bg="#212121", fg="#FFFFFF", activebackground="#212121", activeforeground="#FFFFFF")
       # self.emoji_button.config(bg="#212121", fg="#FFFFFF", activebackground="#212121", activeforeground="#FFFFFF")
        self.sent_label.config(bg="#2a2b2d", fg="#FFFFFF")

        self.tl_bg = "#212121"
        self.tl_bg2 = "#2a2b2d"
        self.tl_fg = "#FFFFFF"

    # Grey
    def color_theme_grey(self):
        self.master.config(bg="#444444")
        self.text_frame.config(bg="#444444")
        self.text_box.config(bg="#4f4f4f", fg="#ffffff")
        self.entry_frame.config(bg="#444444")
        self.entry_field.config(bg="#4f4f4f", fg="#ffffff", insertbackground="#ffffff")
        self.send_button_frame.config(bg="#444444")
        self.send_button.config(bg="#4f4f4f", fg="#ffffff", activebackground="#4f4f4f", activeforeground="#ffffff")
        #self.emoji_button.config(bg="#4f4f4f", fg="#ffffff", activebackground="#4f4f4f", activeforeground="#ffffff")
        self.sent_label.config(bg="#444444", fg="#ffffff")

        self.tl_bg = "#4f4f4f"
        self.tl_bg2 = "#444444"
        self.tl_fg = "#ffffff"

    def color_theme_turquoise(self):
        self.master.config(bg="#003333")
        self.text_frame.config(bg="#003333")
        self.text_box.config(bg="#669999", fg="#FFFFFF")
        self.entry_frame.config(bg="#003333")
        self.entry_field.config(bg="#669999", fg="#FFFFFF", insertbackground="#FFFFFF")
        self.send_button_frame.config(bg="#003333")
        self.send_button.config(bg="#669999", fg="#FFFFFF", activebackground="#669999", activeforeground="#FFFFFF")
        #self.emoji_button.config(bg="#669999", fg="#FFFFFF", activebackground="#669999", activeforeground="#FFFFFF")
        self.sent_label.config(bg="#003333", fg="#FFFFFF")

        self.tl_bg = "#669999"
        self.tl_bg2 = "#003333"
        self.tl_fg = "#FFFFFF"

    # Blue
    def color_theme_dark_blue(self):
        self.master.config(bg="#263b54")
        self.text_frame.config(bg="#263b54")
        self.text_box.config(bg="#1c2e44", fg="#FFFFFF")
        self.entry_frame.config(bg="#263b54")
        self.entry_field.config(bg="#1c2e44", fg="#FFFFFF", insertbackground="#FFFFFF")
        self.send_button_frame.config(bg="#263b54")
        self.send_button.config(bg="#1c2e44", fg="#FFFFFF", activebackground="#1c2e44", activeforeground="#FFFFFF")
        #self.emoji_button.config(bg="#1c2e44", fg="#FFFFFF", activebackground="#1c2e44", activeforeground="#FFFFFF")
        self.sent_label.config(bg="#263b54", fg="#FFFFFF")

        self.tl_bg = "#1c2e44"
        self.tl_bg2 = "#263b54"
        self.tl_fg = "#FFFFFF"

    # Torque
    def color_theme_turquoise(self):
        self.master.config(bg="#003333")
        self.text_frame.config(bg="#003333")
        self.text_box.config(bg="#669999", fg="#FFFFFF")
        self.entry_frame.config(bg="#003333")
        self.entry_field.config(bg="#669999", fg="#FFFFFF", insertbackground="#FFFFFF")
        self.send_button_frame.config(bg="#003333")
        self.send_button.config(bg="#669999", fg="#FFFFFF", activebackground="#669999", activeforeground="#FFFFFF")
        #self.emoji_button.config(bg="#669999", fg="#FFFFFF", activebackground="#669999", activeforeground="#FFFFFF")
        self.sent_label.config(bg="#003333", fg="#FFFFFF")

        self.tl_bg = "#669999"
        self.tl_bg2 = "#003333"
        self.tl_fg = "#FFFFFF"

    # Hacker
    def color_theme_hacker(self):
        self.master.config(bg="#0F0F0F")
        self.text_frame.config(bg="#0F0F0F")
        self.entry_frame.config(bg="#0F0F0F")
        self.text_box.config(bg="#0F0F0F", fg="#33FF33")
        self.entry_field.config(bg="#0F0F0F", fg="#33FF33", insertbackground="#33FF33")
        self.send_button_frame.config(bg="#0F0F0F")
        self.send_button.config(bg="#0F0F0F", fg="#FFFFFF", activebackground="#0F0F0F", activeforeground="#FFFFFF")
        #self.emoji_button.config(bg="#0F0F0F", fg="#FFFFFF", activebackground="#0F0F0F", activeforeground="#FFFFFF")
        self.sent_label.config(bg="#0F0F0F", fg="#33FF33")

        self.tl_bg = "#0F0F0F"
        self.tl_bg2 = "#0F0F0F"
        self.tl_fg = "#33FF33"

    # Default font and color theme
    def default_format(self):
        self.font_change_default()
        self.color_theme_default()

root=Tk()

a = ChatInterface(root)
root.geometry(window_size)
root.title("jeff")
#root.iconbitmap('i.ico')
root.mainloop()


import numpy as np
from sklearn.preprocessing import StandardScaler
from keras.models import Sequential
from keras.layers import LSTM, Dense, Dropout
from keras.callbacks import EarlyStopping
from keras.callbacks import ModelCheckpoint
import itertools
from keras import backend as K
from model_preparation import smape_loss, datasplit, datasplit_3618
# SEED = 666
# os.environ['PYTHONHASHSEED']=str(SEED)
# np.random.seed(SEED)
# tf.random.set_seed(SEED)
# rn.seed(SEED)
# function of LSTM model
def seq2seqModel(X, step):
    K.clear_session()
    model = Sequential()
    model.add(LSTM(50, activation='relu', return_sequences=True, input_shape=(step, X.shape[2])))
    model.add(Dropout(0.2))
    model.add(LSTM(50, activation='relu'))
    model.add(Dropout(0.2))
    model.add(Dense(X.shape[2]))
    model.compile(optimizer='adam', loss=smape_loss)
    return model

# function to create future demand
def predictfuture(dataset, step, model, period):
    for _ in range(period):
        datasetX = dataset[-step:]
        X_train = datasetX.reshape(1, step, datasetX.shape[1])
        next_prediction = model.predict(X_train)
        dataset = np.vstack([dataset, next_prediction])
    return dataset[-period:]

#Calculate the error indicator
def calculate_smape(df_forcalculate, step):
    # calculate the correlation between each feature and demand and choose the first 8 features
    corr_matrix = df_forcalculate.corr()
    demand_corr = corr_matrix.sort_values(by=['demand'], ascending=False)
    index_list = demand_corr.index.tolist()
    df = df_forcalculate[index_list[0:8]]
    real_demand = df['demand']
    # Normalize the data
    scaler = StandardScaler()
    df_sc = scaler.fit_transform(df.reset_index(drop=True))
    dataset = np.array(df_sc)

    X_train, X_test, y_train, y_test = datasplit(dataset, step)
    model = seq2seqModel(X_train, step)
    es = EarlyStopping(monitor='val_loss', mode='min', verbose=1, patience=5)
    model.fit(X_train, y_train, epochs=50, verbose=0, validation_split=0.2, batch_size=64, callbacks=[es])
    y_pred = model.predict(X_test)
    predicted_demand = scaler.inverse_transform(y_pred)
    y_true = scaler.inverse_transform(y_test)
    smape = smape_loss(y_true[:, 0], predicted_demand[:, 0])

    return dataset, model, X_train, X_test, y_train, y_test, predicted_demand, smape, scaler, real_demand

#Function og hyperparameter tunning
def LSTM_HyperParameter_Tuning(config, x_train, y_train, x_test, y_test, sc, accuracy):
    n_neurons, n_batch_size, dropout = config
    possible_combinations = list(itertools.product(n_neurons, n_batch_size, dropout))

    hist = []
    best_accracy = accuracy
    best_smape = 1 - best_accracy
    indicator = False
    for i in range(0, len(possible_combinations)):

        print(f'{i + 1}th combination: \n')
        print('--------------------------------------------------------------------')

        n_neurons, n_batch_size, dropout = possible_combinations[i]

        # instantiating the model in the strategy scope creates the model on the TPU
        # with tpu_strategy.scope():
        K.clear_session()
        regressor = Sequential()
        regressor.add(LSTM(units=n_neurons, activation='relu', return_sequences=True,
                           input_shape=(x_train.shape[1], x_train.shape[2])))
        regressor.add(Dropout(dropout))

#         if first_additional_layer:
#             regressor.add(LSTM(units=n_neurons, activation='relu', return_sequences=True,
#                                input_shape=(x_train.shape[1], x_train.shape[2])))
#             regressor.add(Dropout(dropout))

        # if second_additional_layer:
        #     regressor.add(LSTM(units=n_neurons))
        #     regressor.add(Dropout(dropout))
        #
        # if third_additional_layer:
        #     regressor.add(GRU(units=n_neurons))
        #     regressor.add(Dropout(dropout))

        regressor.add(LSTM(units=n_neurons, activation='relu'))
        regressor.add(Dropout(dropout))
        regressor.add(Dense(units=x_train.shape[2]))
        regressor.compile(optimizer='adam', loss=smape_loss)

        es = EarlyStopping(monitor='val_loss', mode='min', verbose=1, patience=5)
        '''''
        From the mentioned article above --> If a validation dataset is specified to the fit() function via the validation_data or v
        alidation_split arguments,then the loss on the validation dataset will be made available via the name “val_loss.”
        '''''

        file_path = 'temp/best_model.h5'

        mc = ModelCheckpoint(file_path, monitor='val_loss', mode='min', verbose=1, save_best_only=True)

        '''''
        cb = Callback(...)  # First, callbacks must be instantiated.
        cb_list = [cb, ...]  # Then, one or more callbacks that you intend to use must be added to a Python list.
        model.fit(..., callbacks=cb_list)  # Finally, the list of callbacks is provided to the callback argument when fitting the model.
        '''''

        regressor.fit(x_train, y_train, validation_split=0.2, epochs=50, batch_size=n_batch_size, callbacks=[es, mc],
                      verbose=0)

        # load the best model
        # regressor = load_model('best_model.h5')

        y_pred = regressor.predict(x_test)
        predicted_demand = sc.inverse_transform(y_pred)
        y_true = sc.inverse_transform(y_test)
        smape = smape_loss(y_true[:, 0], predicted_demand[:, 0])
        if 0.00 < smape < 1.00:
            new_accuracy = 1.00 - smape
            if new_accuracy > best_accracy:
                indicator = True
                best_accracy = new_accuracy
                best_smape = smape
                best_regressor = regressor
                best_predicted_demand = predicted_demand
                hist.append(list(
                    (n_neurons, n_batch_size,
                     dropout,
                     best_accracy)))
                if best_accracy > 0.7999999:
                    break
            else:
                if indicator:
                    pass
                else:
                    best_regressor, best_predicted_demand = [], []
                hist.append(list((n_neurons, n_batch_size, dropout, 'not working')))
        else:
            if indicator:
                pass
            else:
                best_regressor, best_predicted_demand = [], []
            hist.append(list((n_neurons, n_batch_size, dropout, 'not working')))
    return best_accracy, best_smape, best_regressor, best_predicted_demand, hist

# function to create future demand for 18 months validation
def predictfuture_3618(dataset, step, model, period):
    dataset = dataset[0:len(dataset)-18]
    for _ in range(period):
        datasetX = dataset[-step:]
        X_train = datasetX.reshape(1, step, datasetX.shape[1])
        if isinstance(model, list):
            pass
        next_prediction = model.predict(X_train)
        dataset = np.vstack([dataset, next_prediction])
    return dataset[-period:]

#Calculate the error indicator for 18 months validation
def calculate_smape_3618(df_forcalculate, step):
    # calculate the correlation between each feature and demand and choose the first 8 features
    corr_matrix = df_forcalculate.corr()
    demand_corr = corr_matrix.sort_values(by=['demand'], ascending=False)
    index_list = demand_corr.index.tolist()
    df = df_forcalculate[index_list[0:8]]
    real_demand = df['demand']
    # Normalize the data
    scaler = StandardScaler()
    df_sc = scaler.fit_transform(df.reset_index(drop=True))
    dataset = np.array(df_sc)

    X_train, X_test, y_train, y_test, future_y = datasplit_3618(dataset, step)
    model = seq2seqModel(X_train, step)
    es = EarlyStopping(monitor='val_loss', mode='min', verbose=1, patience=5)
    model.fit(X_train, y_train, epochs=50, verbose=0, validation_split=0.2, batch_size=64, callbacks=[es])
    y_pred = model.predict(X_test)
    predicted_demand = scaler.inverse_transform(y_pred)
    y_true = scaler.inverse_transform(y_test)
    smape = smape_loss(y_true[:, 0], predicted_demand[:, 0])

    return dataset, model, X_train, X_test, y_train, y_test, predicted_demand, smape, scaler, real_demand, future_y


"""
This program analyses (spelling is hard) text files.
It has a function to find any word with sl
It has a function that finds words with triple vowel
It has a function that counts distinct words in a file
It has a markhov chain generator, and a frequency generator
"""
import re
import urllib2
import codeskulptor
from collections import defaultdict
from collections import Counter

def findall_sl(text):
    """
    Finds words that begin with sl
    """
    return re.findall(r"\b[sS]l\S+\b", text)

def findall_triple_vowel(text):
    """
    Finds words with triple vowels
    """
    return re.findall(r"\b\S*(?:aaa+|eee+|iii+|ooo+|uuu+)\S*\b", text, re.IGNORECASE)

def findall_80s(text):
    """
    Finds words that reference the eighties
    """
    return re.findall(r"\b(?:eighties|198\d|(?:19|)80s)\b", text, re.IGNORECASE)

def count_distinct_words(filename):
    """
    Counts the number of words in a file
    """
    list_of_words = get_word_list(filename, False, False)
    temp_set = set()
    for word in list_of_words:
        temp_set.add(word.lower())
    return len(temp_set)

def get_word_list(filename, include_punc, case_sensitive):
    """
    Helper function I wrote, returns a list of words out of a file
    Options to include_punctuation or return words case sensitive
    """
    url_file = urllib2.urlopen(codeskulptor.file2url(filename))
    list_of_words = []
    for line in url_file.readlines():
        for word in re.findall(r"[?!]+|-+|\.+|[,:;\"'`()/&#]|-?[A-Za-z0-9]+(?:['\-.@/][A-Za-z0-9]+)*|-?\$?\d{1,3}(?:,?\d{3})*(?:\.\d+)?", line):
            if(case_sensitive):
                list_of_words.append(word)
            else:
                list_of_words.append(word.lower())
    if(not include_punc):
        temp_list = []
        for word in list_of_words:
            if re.match("[a-zA-Z]", word):
                temp_list.append(word)
        return temp_list
    return list_of_words

def median_word(filename):
    """
    Returns the word that is mentioned a median amount of times in a file
    """
    list_of_words = get_word_list(filename, False, False)
    # Yes I know this should be a Counter. Oh well
    temp_dict = {}
    for word in list_of_words:
        if word in temp_dict:
            temp_dict[word] += 1
        else:
            temp_dict[word] = 1
    value_list = []
    for key in temp_dict:
        value_list.append((key, temp_dict[key]))
    value_list.sort(key=lambda x: x[1])
    return value_list[(len(value_list) / 2) - 1][0]

def wordseq_successor_counts(
    filename_list,
     seq_size,
     include_punc,
     is_case_sensitive):
    """
    Creates a markhov chain using a list of files.
    The chain consists of a dictionary mapping tuples to counters
    The counter matches single word strings to
    the amount of times that word has been mentioned after the tuple
    """
    list_of_word_lists = []
    return_dict = defaultdict(Counter)
    for single_file in filename_list:
        list_of_word_lists.append(
            get_word_list(single_file, include_punc, is_case_sensitive))
    for word_list in list_of_word_lists:
        for index in range(0, len(word_list) - seq_size):
            temp_list = []
            for second_index in range(0, seq_size):
                temp_list.append(word_list[index + second_index])
            return_dict[tuple(temp_list)][word_list[index + seq_size]] += 1
    return return_dict

# print(wordseq_successor_counts(['comp130_AmericanPie.txt'], 1, False, False))

def wordseq_successor_frequencies(
    filename_list,
     seq_size,
     include_punc,
     is_case_sensitive):
    """
    calls wordseq_successor_counts and converts the counts into frequencies
    """
    counts_dict = wordseq_successor_counts(
        filename_list,
        seq_size,
     include_punc,
     is_case_sensitive)
    return_dict = defaultdict(dict)
    for key in counts_dict:
        total_count = 0.0
        for inner_key in counts_dict[key]:
            total_count += float(counts_dict[key][inner_key])
        for inner_key in counts_dict[key]:
            return_dict[key][inner_key] = float(
                counts_dict[key][inner_key]) / float(total_count)
    return return_dict


import datetime, traceback
import ElmcityEventParser

class HelloWorldParser(ElmcityEventParser.EventParser):

  def Parse(self):
    try:
      self.ParsePage()
    except:
      self.LogMsg('exception', 'HelloWorldParser.Parse', traceback.format_exc())
    self.BuildICS()

  def ParsePage(self):
    evt = ElmcityEventParser.Event()
    evt.title = "Hello World"
    evt.start = datetime.datetime.now()
    evt.url = ''
    self.events.append(evt)

def test():
  parser = HelloWorldParser(url=None)
  parser.Parse()


# -*- coding: utf-8 -*-
"""
consistency_check_starter.py

A time queue action to periodically start a new consistency check
"""
import datetime
import logging
import os
import random
import time

from anti_entropy_server.audit_result_database import \
    AuditResultDatabase

_polling_interval = float(os.environ.get(
    "NIMBUSIO_ANTI_ENTROPY_POLLING_INTERVAL", "1800.0")
)
_audit_cutoff_days = int(os.environ.get("NIMBUSIO_AUDIT_CUTOFF_DAYS", "14"))
_max_active_checks = int(os.environ.get(
    "NIMBUSIO_ANTI_ENTROPY_MAX_ACTIVE_CHECKS", "1")
)

class ConsistencyCheckStarter(object):
    """
    A time queue action to periodically start a new consistency check
    """
    def __init__(self, state, start_consistency_check):
        self._log = logging.getLogger("ConsistencyCheckStarter")
        self._state = state
        self._start_consistency_check = start_consistency_check

    @classmethod
    def next_run(cls):
        return time.time() + _polling_interval

    def run(self, halt_event):
        """pick a collection and start a new consistency check"""
        if halt_event.is_set():
            self._log.info("halt-event is set: exiting")
            return

        cutoff_timestamp = \
            datetime.datetime.now() - \
            datetime.timedelta(days=_audit_cutoff_days)
        database = AuditResultDatabase(
            self._state["central-database-connection"]
        )
        ineligible_collection_ids = set(
            database.ineligible_collection_ids(cutoff_timestamp)
        )
        eligible_collection_ids = self._state["collection-ids"] \
                            - ineligible_collection_ids

        self._log.info(
            "found %s collections eligible for consistency check" % (
                len(eligible_collection_ids),
            )
        )

        eligible_collection_id_list = list(eligible_collection_ids)
        while len(eligible_collection_id_list) > 0 \
        and len(self._state["active-requests"]) < _max_active_checks:
            collection_id = random.choice(eligible_collection_id_list)
            eligible_collection_id_list.remove(collection_id)
            self._start_consistency_check(self._state, collection_id)

        return [(self.run, self.next_run(), )]


from Grille import *
from Agent import *
from Message import *

import random
import time

def randomAgentsGenerator(grid, nb_agents):

	random_start_positions = []
	random_end_positions = []
	agents = []
	c = 1
	obj = [[0 for i in range(grid.__size__)] for j in range(grid.__size__)]
	while len(random_start_positions)<nb_agents:
		[x,y] = [random.randint(0,grid.__size__-1),random.randint(0,grid.__size__-1)]
		if [x,y] not in random_start_positions:
			random_start_positions.append([x,y])
	while len(random_end_positions)<nb_agents:
		[x,y] = [random.randint(0,grid.__size__-1),random.randint(0,grid.__size__-1)]
		if [x,y] not in random_end_positions:
			random_end_positions.append([x,y])
			obj[x][y] = c
			c += 1
	mail_box = [[] for i in range(nb_agents+1)]
	for i in range(nb_agents):
		agents.append(Agent(random_start_positions[i][0],random_start_positions[i][1],random_end_positions[i][0],random_end_positions[i][1],grid,mail_box))
	print("Agents generated")
	return mail_box, agents, obj

if __name__ == '__main__':
	n = 5
	grid = Grille(n)

	nb_agents = 15

	mail_box, agents, obj = randomAgentsGenerator(grid, nb_agents)

	grid.__show__()

	print("Objective : \n")

	for x in range(len(obj)):
		print("|\t", end="")
		for y in range(len(obj)):
			print(str(obj[x][y])+"\t",end="")
		print("|")
	print("")

	time.sleep(5)
	start_time = time.time()
	for i in range(len(agents)):
		agents[i].start()

	"""
	mail_box = [[],[],[],[],[],[],[],[]]
	# agent_1 = Agent(1,1,4,4,grid, mail_box)
	# agent_2 = Agent(0,0,3,4,grid, mail_box)
	agent_1 = Agent(4,1,1,2,grid, mail_box)
	agent_2 = Agent(3,1,2,3,grid, mail_box)
	agent_3 = Agent(2,0,0,2,grid, mail_box)
	agent_4 = Agent(1,2,4,0,grid, mail_box)
	agent_5 = Agent(3,3,0,0,grid, mail_box)
	agent_6 = Agent(2,2,2,4,grid, mail_box)
	agent_7 = Agent(1,1,4,4,grid, mail_box)
	agent_1.start()
	agent_2.start()
	agent_3.start()
	agent_4.start()
	agent_5.start()
	agent_6.start()
	agent_7.start()
	"""

	while not grid.isTerminal():
		time.sleep(3)
		for box in mail_box:
			for mail in box:
				print(mail.toString())
		grid.__show__()
	print("--- %s seconds ---" % (time.time() - start_time))


# prints a string
print("Mary had a little lamb")
# prints a string which has a formatted string in it
print("Its fleece was white as {}".format('snow'))
# prints a string
print("And everywhere that Mary went.")
# prints the point ten times(repeat)
print("." * 10)
# what would that do

# strings are assigned to variables
end1 = "C"
end2 = "h"
end3 = "e"
end4 = "e"
end5 = "s"
end6 = "e"
end7 = "B"
end8 = "u"
end9 = "r"
end10 = "g"
end11 = "e"
end12 = "r"

# watch end = ' ' at the end. try removing it to see what happens
# concatenation is taking place in both prints
print(end1 + end2 + end3 + end4 + end5 + end6, end=' ')
print(end7 + end8 + end9 + end10 + end11 + end12)


from typing import Literal, Optional

from aries_cloudcontroller import AcaPyClient
from fastapi import HTTPException
from pydantic import BaseModel, Field

from app.services import acapy_wallet
from app.services.acapy_ledger import accept_taa_if_required
from shared import LEDGER_REGISTRATION_URL, LEDGER_TYPE
from shared.log_config import get_logger
from shared.util.rich_async_client import RichAsyncClient

logger = get_logger(__name__)

class LedgerRequestSovrin(BaseModel):
    network: str = Field(None)
    did: str = Field(None)
    verkey: str = Field(None)
    payment_address: str = Field(None, alias="paymentaddr")

class LedgerRequestVon(BaseModel):
    did: str = Field(None)
    seed: str = Field(None)
    verkey: str = Field(None)
    role: str = Field(None)

async def post_to_ledger(
    did: str, verkey: str, role: Optional[Literal["ENDORSER"]] = "ENDORSER"
):
    if LEDGER_TYPE == "sovrin":
        payload = LedgerRequestSovrin(
            network="stagingnet",
            did=did,
            verkey=verkey,
        )
    elif LEDGER_TYPE == "von":
        payload = LedgerRequestVon(did=did, seed="null", verkey=verkey, role=role)
    else:
        raise HTTPException(
            status_code=501,
            detail="Cannot resolve ledger type. Should be either von or sovrin",
        )

    logger.info(f"Try post to ledger: {payload}")
    async with RichAsyncClient(raise_status_error=False) as client:
        response = await client.post(
            LEDGER_REGISTRATION_URL, json=payload.model_dump(), timeout=300
        )

    if response.is_error:
        raise HTTPException(
            status_code=response.status_code,
            detail=f"Something went wrong.\nCould not write to Ledger.\n{response.text}",
        )
    logger.info("Successfully posted to ledger.")

async def has_public_did(aries_controller: AcaPyClient):
    try:
        await acapy_wallet.get_public_did(aries_controller)
        return True
    except Exception:
        return False

async def create_public_did(
    aries_controller: AcaPyClient, set_public: bool = True
) -> acapy_wallet.Did:
    logger.info("Handling create public did request")
    did_object = await acapy_wallet.create_did(aries_controller)

    if not did_object.did or not did_object.verkey:
        raise Exception("Cannot register did without did and/or verkey")

    await post_to_ledger(did=did_object.did, verkey=did_object.verkey)
    await accept_taa_if_required(aries_controller)

    if set_public:
        await acapy_wallet.set_public_did(aries_controller, did_object.did)

    logger.info("Successfully handled create public did request.")
    return did_object