from tkinter import *
from tkinter import filedialog
from tkinter import messagebox
from tkinter import ttk
from matplotlib.figure import Figure
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from sys import platform
import os
import time
import numpy as np
import uuid
import argparse
import tkinter

parser = argparse.ArgumentParser(description='Visualization args parser')

# Data files
parser.add_argument('--results_folder', type=str, required = True)
parser.add_argument('--monitored_topic_file', type=str, required = True)
parser.add_argument('--visualize_novel_merged', type=str, default = "False")
parser.add_argument('--visualize_monitored_merged', type=str, default = "False")

FLAGS = parser.parse_args()

# Represents a disease cluster; contains basic info and a list to the cases invovled.
class Cluster:
    index = 0
    score = 0
    startdate = ''
    enddate = ''
    words = ''
    locations = ''
    ages = ''
    monitor = 0
    normalized = 0

    words_list = []
    case_list = []

    def __init__(
            self, index, score, startdate, enddate, words,
            locations, ages, monitor=0, normalized=0
    ):
        self.index = int(index)
        self.score = round(float(score), 5)
        self.startdate = startdate
        self.enddate = enddate
        self.words = words
        self.locations = locations
        self.ages = ages
        self.monitor = monitor
        self.normalized = normalized
        self.words_list = []
        self.case_list = []

    def __str__(self):
        return str(self.to_tuple())

    def __repr__(self):
        return str(self)

    def to_tuple(self):
        return self.score, self.startdate, self.enddate, self.words, self.locations, self.ages

# Represents a single case that belongs to a certain cluster. Referenced by Cluster class.
class Case:
    cluster_index = 0
    date = ''
    time = ''
    location = ''
    words = ''
    icd = ''
    sex = ''
    age = ''
    id = ''
    uuid = -1

    def __init__(
            self, cluster_index, date, time, location, words, icd, sex, age, id, uuid
    ):
        self.cluster_index = int(cluster_index)
        self.date = date
        self.time = time
        self.location = location
        self.words = words
        self.icd = icd
        self.sex = sex
        self.age = age
        self.id = id
        self.uuid = uuid

    def __str__(self):
        return str(self.to_tuple())

    def __repr__(self):
        return str(self)

    def to_tuple(self):
        return self.date, self.time, self.location, self.words, self.icd, self.sex, self.age, self.id

# Helper function for determining if a number is float or not

def isfloat(num):
    try:
        a = float(num)
    except:
        return False
    return True

# Helper function for inserting cluster rows into the table
def insert_rows(t, l):
    for cluster in l.values():
        t.insert(
            parent='',
            index='end',
            iid=cluster.index,
            values=cluster.to_tuple())

# Open the file selection GUI and select the corresponding file
# filetype: the file/folder that needs to be selected

def select_file(file_type):
    if file_type == 0 or file_type == 'folder':
        ret = filedialog.askdirectory(
            title='Select Result Folder',
        )
        return ret
    elif file_type == 1 or file_type == 'cluster':
        ret = filedialog.askopenfilename(
            title='Select Static Topic File',
            filetypes=(('CSV File', '*.csv'), ("All Files", "."))
        )
        return ret
    elif file_type == 2 or file_type == 'setting':
        ret = filedialog.askopenfilename(
            title='Select Visualization Setting File',
            filetypes=(('Text File', '*.txt'), ("All Files", "."))
        )
        return ret
    return ''

# Read the settings of the program (the location of the cluster folder and the topic folder)

def read_settings(settings_file_name):
    try:
        settings = open(settings_file_name, 'r')
    except:
        messagebox.showinfo(
            title='Error',
            message='Loading Setting File Failed!')
        return '', ''

    contents = settings.readlines()
    settings.close()

    # Begin processing folders and file

    result_folder_name = ''
    static_topics_file_name = ''
    visualize_novel_merged = ''
    visualize_monitored_merged = ''

    # Create new setting file if necesary
    if len(contents) != 2:
        messagebox.showinfo(
            title='Error',
            message='Visualization setting file not right! \
             Please reselect result folder and cluster file')
        static_topics_file_name = select_file('cluster')
        result_folder_name = select_file('folder')
        return result_folder_name, static_topics_file_name

    try:
        if contents[1][0:19] != 'static_topics_file,':
            raise ValueError
        static_topics_file_name = contents[1][19:]
        if not os.path.exists(static_topics_file_name):
            raise ValueError
    except:
        messagebox.showinfo(
            title='Error',
            message='Cluster/topic file not found! Please reselct the cluster file')
        static_topics_file_name = select_file('cluster')

    try:
        if contents[0][0:15] != 'results_folder,':
            raise ValueError
        result_folder_name = contents[0][15:len(contents[0]) - 1]
        if not os.path.isdir(result_folder_name):
            raise ValueError
    except:
        messagebox.showinfo(
            title='Error',
            message='Result folder not found! Please reselct the result folder')
        result_folder_name = select_file('folder')

    return result_folder_name, static_topics_file_name, visualize_novel_merged, visualize_monitored_merged

# Save the current setting

def save_settings(settings_file_name, result_folder_name, static_topics_file_name):
    try:
        file = open(settings_file_name, 'w')
        line1 = 'results_folder,' + result_folder_name
        line2 = 'static_topics_file,' + static_topics_file_name
        file.write(line1)
        file.write('\n')
        file.write(line2)
        file.close()
    except:
        messagebox.showinfo(
            title='Error',
            message='Saving Settings Failed!')

# Helper function for reading cluster files

def read_file(filename):
    newlines = []
    try:
        f = open(filename)
    except:
        messagebox.showinfo(
            title='Error',
            message='Read ' + filename + " Failed!")
        return newlines
    c = f.readlines()
    for line in c:
        line = line.replace('\n', '')
        newlines.append(line)
    f.close()
    return newlines

# Loading the cluster (cluster stored as global variables)
def load_clusters(result_folder_name, visualize_novel_merged, visualize_monitored_merged):
    clusterlines_file_name =''
    caselines_file_name=''
    topiclines_file_name=''
    mon_clusterlines_file_name=''
    mon_caselines_file_name=''
    mon_topiclines_file_name=''

    if (visualize_novel_merged == False and (platform == "linux" or platform == "linux2" or platform == "darwin")):
        clusterlines_file_name = result_folder_name + "/novel_cluster_summary.txt"
        caselines_file_name = result_folder_name + "/novel_caselines.txt"
        topiclines_file_name = result_folder_name + "/novel_topicwords.txt"
    elif visualize_novel_merged == False and platform == "win32":
        clusterlines_file_name = result_folder_name + "\\novel_cluster_summary.txt"
        caselines_file_name = result_folder_name + "\\novel_caselines.txt"
        topiclines_file_name = result_folder_name + "\\novel_topicwords.txt"
    elif visualize_novel_merged == True and (platform == "linux" or platform == "linux2" or platform == "darwin"):
        clusterlines_file_name = result_folder_name + "/merged_novel_cluster_summary.txt"
        caselines_file_name = result_folder_name + "/merged_novel_caselines.txt"
        topiclines_file_name = result_folder_name + "/merged_novel_topicwords.txt"
    elif visualize_novel_merged == True and platform == "win32":
        clusterlines_file_name = result_folder_name + "\\merged_novel_cluster_summary.txt"
        caselines_file_name = result_folder_name + "\\merged_novel_caselines.txt"
        topiclines_file_name = result_folder_name + "\\merged_novel_topicwords.txt"

    clusterlines = read_file(clusterlines_file_name)
    caselines = read_file(caselines_file_name)
    topiclines = read_file(topiclines_file_name)

    # Reading the cluster first
    for line in clusterlines:
        items = line.split('\t')
        if(len(items) != 7):
            continue
        c = Cluster(
            items[0],
            items[4],
            items[1],
            items[2],
            items[5],
            items[3],
            items[6],
            0,
            0
        )
        novel[c.index] = c

    # Reading the cases and assign them to their clusters
    for case in caselines:
        items = case.split('\t')
        if(len(items) != 9):
            continue
        c = Case(
            items[0],
            items[5],
            items[4],
            items[8],
            items[1],
            items[2],
            items[6],
            items[7],
            items[3],
            str(uuid.uuid4())
        )
        index = c.cluster_index
        if index in novel:
            novel[index].case_list.append(c)

    # Reading the words and assign them to their clusters
    for topic in topiclines:
        items = topic.split('\t')
        if(len(items) != 3):
            continue
        index = int(items[0])
        word = items[2]
        percent = items[1]
        if index in novel:
            novel[index].words_list.append([word, float(percent)])

    if (visualize_monitored_merged == False and (platform == "linux" or platform == "linux2" or platform == "darwin")):
        mon_clusterlines_file_name = result_folder_name + "/monitored_cluster_summary.txt"
        mon_caselines_file_name = result_folder_name + "/monitored_caselines.txt"
        mon_topiclines_file_name = result_folder_name + "/monitored_topicwords.txt"
    elif visualize_monitored_merged == False and platform == "win32":
        mon_clusterlines_file_name = result_folder_name + "\\monitored_cluster_summary.txt"
        mon_caselines_file_name = result_folder_name + "\\monitored_caselines.txt"
        mon_topiclines_file_name = result_folder_name + "\\monitored_topicwords.txt"
    elif visualize_monitored_merged == True and (platform == "linux" or platform == "linux2" or platform == "darwin"):
        mon_clusterlines_file_name = result_folder_name + "/merged_monitored_cluster_summary.txt"
        mon_caselines_file_name = result_folder_name + "/merged_monitored_caselines.txt"
        mon_topiclines_file_name = result_folder_name + "/merged_monitored_topicwords.txt"
    elif visualize_monitored_merged == True and platform == "win32":
        mon_clusterlines_file_name = result_folder_name + "\\merged_monitored_cluster_summary.txt"
        mon_caselines_file_name = result_folder_name + "\\merged_monitored_caselines.txt"
        mon_topiclines_file_name = result_folder_name + "\\merged_monitored_topicwords.txt"

    # Only read the monitored files if they exist
    if (os.path.exists(mon_caselines_file_name) and
            os.path.exists(mon_clusterlines_file_name) and
            os.path.exists(mon_topiclines_file_name)):

        clusterlines = read_file(mon_clusterlines_file_name)
        caselines = read_file(mon_caselines_file_name)
        topiclines = read_file(mon_topiclines_file_name)

        for line in clusterlines:
            items = line.split('\t')
            if(len(items) != 7):
                continue
            c = Cluster(
                items[0],
                items[4],
                items[1],
                items[2],
                items[5],
                items[3],
                items[6],
                1,
                0
            )
            monitored[c.index] = c

        for case in caselines:
            items = case.split('\t')
            if(len(items) != 9):
                continue
            c = Case(
                items[0],
                items[5],
                items[4],
                items[8],
                items[1],
                items[2],
                items[6],
                items[7],
                items[3],
                str(uuid.uuid4())
            )
            index = c.cluster_index
            if index in monitored:
                monitored[index].case_list.append(c)

        for topic in topiclines:
            items = topic.split('\t')
            if(len(items) != 3):
                continue
            index = int(items[0])
            word = items[2]
            percent = items[1]
            if index in monitored:
                monitored[index].words_list.append([word, float(percent)])

# Helper function for sorting columns
# Sorted as string except for score

def treeview_sort_column(tv, col, reverse):
    l = [(tv.set(k, col), k) for k in tv.get_children('')]
    if col == 'score':
        l.sort(reverse=reverse, key=lambda x: float(x[0]))
    else:
        l.sort(reverse=reverse)

    # rearrange items in sorted positions
    for index, (val, k) in enumerate(l):
        tv.move(k, '', index)

    # reverse sort next time
    tv.heading(col, command=lambda: \
        treeview_sort_column(tv, col, not reverse))

# Updating the cluster details at the bottom when a new cluster/line is selected

def updating_case_table(event=None):
    cluster_id = table.selection()
    if len(table.selection()) == 0:
        cluster_id = list(novel.keys())
    cluster_id = int(cluster_id[0])
    cluster = novel[cluster_id]
    for chi in case_table.get_children():
        case_table.delete(chi)
    for case in cluster.case_list:
        case_table.insert(
            parent='',
            index='end',
            iid=case.uuid,
            values=case.to_tuple()
        )
    fig = Figure(figsize=(3, 3), dpi=100)
    plot1 = fig.add_subplot(111)
    words = np.array(cluster.words_list)
    weights = words[:, 1]
    weights = weights.astype(float)
    weights = weights / np.sum(weights)
    plot1.pie(weights, labels=words[:, 0])

    canvas = FigureCanvasTkAgg(fig, master=case_canvas)
    canvas.draw()

    canvas.get_tk_widget().grid(column=0, row=0)

# Helper function for opening a new window to add a cluster

def add_cluster():
    cluster_id = table.selection()
    if len(table.selection()) == 0:
        cluster_id = (0, list(novel.keys()))
    cluster_id = int(cluster_id[0])
    cluster = novel[cluster_id]
    add_cluster_helper(cluster)

# A new window that writes a cluster to static topic file
# New window only containing info of a single cluster

def add_cluster_helper(cluster):

    # Window layout
    new_window = Toplevel()
    new_window.config
    title = Label(new_window, text="Syndrome Summary")
    new_window.grid_rowconfigure(0, weight=1)
    new_window.grid_rowconfigure(1, weight=1)
    new_window.grid_rowconfigure(2, weight=3)
    new_window.grid_rowconfigure(3, weight=1)
    new_window.grid_rowconfigure(4, weight=1)
    new_window.grid_columnconfigure(0, weight=1)
    new_window.grid_columnconfigure(1, weight=1)
    new_window.configure(background='white')
    title.grid(row=0, column=0, columnspan=2, sticky='NESW')
    text = Label(
        new_window,
        text='Please review and make any necessary changes before incorporating this syndrome into your Semantic Scan.')
    text.grid(row=1, column=0, columnspan=2, sticky='NESW', )

    # Pie chart
    def update_graph():
        fig = Figure(figsize=(2, 3), dpi=100)
        plot1 = fig.add_subplot(111)
        words = np.array(cluster.words_list)
        weights = words[:, 1]
        weights = weights.astype(float)
        weights = weights / np.sum(weights)
        plot1.pie(weights, labels=words[:, 0])

        canvas = FigureCanvasTkAgg(fig, master=new_window)
        canvas.draw()

        canvas.get_tk_widget().grid(row=2, column=1, sticky='NESW')

    update_graph()

    # Editable word table
    words_table = ttk.Treeview(
        new_window
    )
    words_table.grid(column=0, row=2, sticky='NESW')

    words_table['columns'] = ('word', 'prob')
    words_table.column("#0", width=0, stretch=NO)
    words_table.column('word', anchor=CENTER, width=80)
    words_table.column('prob', anchor=CENTER, width=80)

    words_table.heading("#0", text="", anchor=CENTER)
    words_table.heading('word', text='Word', anchor=CENTER,
                        command=lambda: treeview_sort_column(words_table, "word", False))
    words_table.heading('prob', text='Probability', anchor=CENTER,
                        command=lambda: treeview_sort_column(words_table, "prob", False))

    for i, word in enumerate(cluster.words_list):
        words_table.insert(
            parent='',
            index='end',
            iid=word[0],
            values=word
        )

    # Function for editing words/probabilities
    def edit():
        word = words_table.selection()[0]
        new_new_window = Toplevel()
        e1 = Entry(new_new_window, width=50)
        e1.insert(0, word)
        e1.pack()
        e2 = Entry(new_new_window, width=50)
        prob = [a[1] for a in cluster.words_list if a[0] == word]
        prob = prob[0]
        e2.insert(0, prob)
        e2.pack()

        def edit2():
            new_word = e1.get()
            new_prob = e2.get()
            if not isfloat(new_prob):
                new_new_window.destroy()
                return
            nn = (new_word, new_prob)
            for i, a in enumerate(cluster.words_list):
                if a[0] == word:
                    cluster.words_list[i] = nn
                    break
            words_table.item(word, values=nn)
            update_graph()
            new_new_window.destroy()

        b = Button(new_new_window, text='Edit', command=edit2)
        b.pack()

    def delete():
        word = words_table.selection()[0]
        for i, a in enumerate(cluster.words_list):
            if a[0] == word:
                cluster.words_list.pop(i)
        update_graph()
        words_table.delete(word)

    edit_button = Button(new_window, text='Edit', command=edit)
    edit_button.grid(column=0, row=3)
    delete_button = Button(new_window, text='Delete', command=delete)
    delete_button.grid(column=1, row=3)

    # Whether monitor or not
    var = IntVar()
    include_checkbox = Checkbutton(
        new_window,
        text="Monitor this syndrome in future scans",
        variable=var,
        onvalue=1,
        offvalue=0)
    include_checkbox.deselect()
    include_checkbox.grid(column=0, row=4)

    def incorporate():
        try:
            f = open(static_topics_file_name, 'a')
        except:
            messagebox.showinfo(
                title='Error',
                message='Open ' + static_topics_file_name + ' failed!')
            new_window.destroy()
            return
        ret = ''
        ret = ret + str(int(var.get()))

        words = np.array(cluster.words_list)
        weights = words[:, 1]
        weights = weights.astype(float)
        weights = weights / np.sum(weights)
        words[:, 1] = weights

        for a in words:
            ret = ret + '_' + a[0] + '_' + str(a[1])
        ret = ret + '\n'
        f.write(ret)
        f.close()

        new_window.destroy()

    incorporate_button = Button(
        new_window,
        text='Incorporate Syndrome',
        command=incorporate)
    incorporate_button.grid(column=0, row=5, columnspan=2)

# TODO: Showing a help page
def help_program():
    pass

# TODO: Showing the about info
def about():
    pass

# Showing the time info about the topic and the cluster files
def fileinfo():
    new_window = Toplevel()
    new_window.geometry("300x200")
    if platform == "linux" or platform == "linux2" or platform == "darwin":
        last_modified = time.ctime(os.path.getmtime(result_folder_name + "/novel_cluster_summary.txt"))
    elif platform == "win32":
        last_modified = time.ctime(os.path.getmtime(result_folder_name + "\\novel_cluster_summary.txt"))
    time_label = Label(
        new_window,
        text=(
                "Results files: last modified at " +
                last_modified
        )
    )
    time_label.pack(expand=True, fill='both')

    last_modified2 = time.ctime(os.path.getmtime(static_topics_file_name))
    topic_time_label = Label(
        new_window,
        text=(
                "Static topic file: last modified at " +
                last_modified2
        )
    )
    topic_time_label.pack(expand=True, fill='both')

# Quit the program
def exit_program():
    root.destroy()

# A new window where monitored clusters are shown
# The main window only shows the novel ones
# Similar structures/functions
def show_monitored_clusters():
    def exit_this_window():
        root2.destroy()

    default_cluster = list(monitored.keys())

    def updating_case_table_monitored(event=None):
        cluster_id = table_monitored.selection()
        if len(table_monitored.selection()) == 0:
            cluster_id = default_cluster
        cluster_id = int(cluster_id[0])
        cluster = monitored[cluster_id]
        for chi in case_table_monitored.get_children():
            case_table_monitored.delete(chi)
        for case in cluster.case_list:
            case_table_monitored.insert(
                parent='',
                index='end',
                iid='-'+case.uuid,
                values=case.to_tuple()
            )
        fig = Figure(figsize=(3, 3), dpi=100)
        plot1 = fig.add_subplot(111)
        words = np.array(cluster.words_list)
        weights = words[:, 1]
        weights = weights.astype(float)
        weights = weights / np.sum(weights)
        plot1.pie(weights, labels=words[:, 0])

        canvas = FigureCanvasTkAgg(fig, master=case_canvas_monitored)
        canvas.draw()

        canvas.get_tk_widget().grid(column=0, row=0)

    def add_cluster_monitored():
        cluster_id = table_monitored.selection()
        if len(table_monitored.selection()) == 0:
            cluster_id = default_cluster
        cluster_id = int(cluster_id[0])
        cluster = monitored[cluster_id]
        add_cluster_helper(cluster)

    root2 = Toplevel()
    root2.state('zoomed')
    root2.grid_rowconfigure(0, weight=1)
    root2.grid_rowconfigure(1, weight=3)
    root2.grid_rowconfigure(2, weight=3)
    root2.grid_rowconfigure(3, weight=1)
    root2.grid_columnconfigure(0, weight=1)
    root2.grid_columnconfigure(1, weight=1)
    root2.grid_columnconfigure(2, weight=1)
    root2.configure(background='white')

    menubar = Menu(root2)

    filemenu = Menu(menubar, tearoff=0)
    #filemenu.add_command(label="Change Results Folder", command=change_results_folder)
    #filemenu.add_command(label="Change Static Topic File", command=change_static_topic)
    #filemenu.add_separator()
    #filemenu.add_command(label="About", command=about)
    #filemenu.add_separator()
    filemenu.add_command(label="Exit", command=exit_program)
    menubar.add_cascade(label='File', menu=filemenu)

    #helpmenu = Menu(menubar, tearoff=0)
    #helpmenu.add_command(label="Help", command=help_program)
    #helpmenu.add_command(label="Show cluster file info", command=fileinfo)
    #menubar.add_cascade(label="Help", menu=helpmenu)

    #optionmenu = Menu(menubar, tearoff=0)
    #optionmenu.add_command(label="Show statics", command=about)
    #menubar.add_cascade(label="Additional Options", menu=optionmenu)

    root2.config(menu=menubar)

    novel_button = Button(
        root2,
        text="Novel Clusters",
        borderwidth=5,
        relief='ridge',
        command=exit_this_window
    )
    novel_button.grid(row=0, column=0, sticky='NESW')

    monitored_button = Button(
        root2,
        text="Monitored Clusters",
        borderwidth=5,
        relief='ridge',
        state=DISABLED)
    monitored_button.grid(row=0, column=2, sticky='NESW')

    cluster_frame = Frame(root2, borderwidth=5, relief='ridge')
    cluster_frame.grid(
        row=1,
        column=0,
        sticky='NESW',
        columnspan=3,
        rowspan=2
    )

    cluster_scroll = Scrollbar(cluster_frame)
    cluster_scroll.pack(side=RIGHT, fill=Y)

    table_label = Label(cluster_frame, text="Summary of Detected Monitored Clusters")
    table_label.pack()

    table_monitored = ttk.Treeview(
        cluster_frame,
        yscrollcommand=cluster_scroll.set)

    table_monitored.pack(expand=True, fill='both')

    cluster_scroll.config(command=table_monitored.yview)

    table_monitored['columns'] = ('score', 'startdate', 'enddate', 'words', 'location', 'age')

    table_monitored.column("#0", width=0, stretch=NO)
    table_monitored.column('score', anchor=CENTER, width=80)
    table_monitored.column('startdate', anchor=CENTER, width=40)
    table_monitored.column('enddate', anchor=CENTER, width=40)
    table_monitored.column('words', anchor=CENTER, width=160)
    table_monitored.column('location', anchor=CENTER, width=40)
    table_monitored.column('age', anchor=CENTER, width=80)

    table_monitored.heading("#0", text="", anchor=CENTER)
    table_monitored.heading('score', text='Score', anchor=CENTER,
                            command=lambda: treeview_sort_column(table_monitored, "score", False))
    table_monitored.heading('startdate', text='Start Date', anchor=CENTER,
                            command=lambda: treeview_sort_column(table_monitored, "startdate", False))
    table_monitored.heading('enddate', text='End Date', anchor=CENTER,
                            command=lambda: treeview_sort_column(table_monitored, "enddate", False))
    table_monitored.heading('words', text='Words in Learned Syndrome', anchor=CENTER,
                            command=lambda: treeview_sort_column(table_monitored, "words", False))
    table_monitored.heading('location', text='Affected Locations', anchor=CENTER,
                            command=lambda: treeview_sort_column(table_monitored, "location", False))
    table_monitored.heading('age', text='Affected Age Range', anchor=CENTER,
                            command=lambda: treeview_sort_column(table_monitored, "age", False))

    insert_rows(table_monitored, monitored)

    details_frame = Frame(root2, borderwidth=5, relief='ridge')
    details_frame.grid(
        row=3,
        column=0,
        sticky='NESW',
        columnspan=2,
        rowspan=1
    )

    details_label = Label(details_frame, text="Details for Selected Clusters")
    details_label.pack()

    case_table_monitored = ttk.Treeview(
        details_frame
    )

    case_table_monitored.pack(expand=True, fill='both')

    case_table_monitored['columns'] = ('date', 'time', 'location', 'words', 'icd', 'sex', 'age', 'id')

    case_table_monitored.column("#0", width=0, stretch=NO)
    case_table_monitored.column('date', anchor=CENTER, width=40)
    case_table_monitored.column('time', anchor=CENTER, width=40)
    case_table_monitored.column('location', anchor=CENTER, width=40)
    case_table_monitored.column('words', anchor=CENTER, width=80)
    case_table_monitored.column('icd', anchor=CENTER, width=40)
    case_table_monitored.column('sex', anchor=CENTER, width=40)
    case_table_monitored.column('age', anchor=CENTER, width=40)
    case_table_monitored.column('id', anchor=CENTER, width=80)

    case_table_monitored.heading("#0", text="", anchor=CENTER)
    case_table_monitored.heading('date', text='Date', anchor=CENTER,
                                 command=lambda: treeview_sort_column(case_table_monitored, "date", False))
    case_table_monitored.heading('time', text='Time', anchor=CENTER,
                                 command=lambda: treeview_sort_column(case_table_monitored, "time", False))
    case_table_monitored.heading('location', text='Location', anchor=CENTER,
                                 command=lambda: treeview_sort_column(case_table_monitored, "location", False))
    case_table_monitored.heading('words', text='Chief Complaint', anchor=CENTER,
                                 command=lambda: treeview_sort_column(case_table_monitored, "words", False))
    case_table_monitored.heading('icd', text='ICD', anchor=CENTER,
                                 command=lambda: treeview_sort_column(case_table_monitored, "icd", False))
    case_table_monitored.heading('sex', text='Sex', anchor=CENTER,
                                 command=lambda: treeview_sort_column(case_table_monitored, "sex", False))
    case_table_monitored.heading('age', text='Age Group', anchor=CENTER,
                                 command=lambda: treeview_sort_column(case_table_monitored, "age", False))
    case_table_monitored.heading('id', text='VISIT ID', anchor=CENTER,
                                 command=lambda: treeview_sort_column(case_table_monitored, "id", False))

    canvas_frame = Frame(root2, borderwidth=5, relief='ridge')
    canvas_frame.grid(
        row=3,
        column=2,
        sticky='NESW',
        rowspan=1,
        columnspan=1
    )

    canvas_label = Label(canvas_frame, text="Pie Chart for Selected Clusters")
    canvas_label.pack()

    case_canvas_monitored = Frame(canvas_frame)

    case_canvas_monitored.pack()

    monitor_cluster_button = Button(
        canvas_frame,
        text="Include Cluster in Future Runs",
        command=add_cluster_monitored,
        state = DISABLED if len(monitored) == 0 else NORMAL
    )

    monitor_cluster_button.pack(expand=True, fill='x')

    updating_case_table_monitored()

    table_monitored.bind("<<TreeviewSelect>>", updating_case_table_monitored)

def main(args):
    # global info
    global result_folder_name
    global static_topics_file_name
    global novel
    global monitored
    global table
    global case_table
    global case_canvas
    global root

    # Setting up the main window
    root = Tk()
    root.title("Disease Surveillance Visualization")
    root.state('zoomed')
    root.grid_rowconfigure(0, weight=1)
    root.grid_rowconfigure(1, weight=3)
    root.grid_rowconfigure(2, weight=3)
    root.grid_rowconfigure(3, weight=1)
    root.grid_columnconfigure(0, weight=1)
    root.grid_columnconfigure(1, weight=1)
    root.grid_columnconfigure(2, weight=1)
    root.configure(background='white')

    # Setting up the menu
    menubar = Menu(root)

    filemenu = Menu(menubar, tearoff=0)
    #filemenu.add_command(label="Change Results Folder", command=change_results_folder)
    #filemenu.add_command(label="Change Static Topic File", command=change_static_topic)
    #filemenu.add_separator()
    #filemenu.add_command(label="About", command=about)
    #filemenu.add_separator()
    filemenu.add_command(label="Exit", command=exit_program)
    menubar.add_cascade(label='File', menu=filemenu)

    #helpmenu = Menu(menubar, tearoff=0)
    #helpmenu.add_command(label="Help", command=help_program)
    #helpmenu.add_command(label="Show cluster file info", command=fileinfo)
    #menubar.add_cascade(label="Help", menu=helpmenu)

    #optionmenu = Menu(menubar, tearoff=0)
    #optionmenu.add_command(label="Show statics", command=about)
    #menubar.add_cascade(label="Additonal Options", menu=optionmenu)

    root.config(menu=menubar)

    # Setting up the main window frame
    loading_frame = Frame(root,
                      borderwidth=5,
                      relief="ridge")
    loading_frame.grid(
        row=0,
        column=0,
        rowspan=4,
        columnspan=3
    )

    loading_label = Label(loading_frame, text='Loading...')
    loading_label.pack(expand=True, fill='both')

    result_folder_name = args.results_folder
    static_topics_file_name = args.monitored_topic_file
    if args.visualize_novel_merged=="False" or args.visualize_novel_merged=="false" or args.visualize_novel_merged=="FALSE":
        visualize_novel_merged = False
    if args.visualize_novel_merged=="True" or args.visualize_novel_merged=="true" or args.visualize_novel_merged=="TRUE":
        visualize_novel_merged = True
    if args.visualize_monitored_merged=="False" or args.visualize_monitored_merged=="false" or args.visualize_monitored_merged=="FALSE":
        visualize_monitored_merged = False
    if args.visualize_monitored_merged=="True" or args.visualize_monitored_merged=="true" or args.visualize_monitored_merged=="TRUE":
        visualize_monitored_merged = True

    no_file_flag = False
    # Program exiting if no files found
    if result_folder_name == '':
        messagebox.showinfo(
            title='Error',
            message='No file found! Program Exiting')
        no_file_flag = True

    elif static_topics_file_name == '':
        messagebox.showinfo(
            title='Error',
            message='No file found! Program Exiting')
        no_file_flag = True

    novel = {}
    monitored = {}

    # Read and load the clusters onto the main window/frame
    if(no_file_flag):
        root.destroy()
        exit()
    else:
        load_clusters(result_folder_name, visualize_novel_merged, visualize_monitored_merged)

    # Finishing Loading
    loading_label.destroy()

    # Buttons for switching between novel clusters and monitored clusters
    novel_button = Button(
        root,
        text="Novel Clusters",
        borderwidth=5,
        relief='ridge',
        state=DISABLED)
    novel_button.grid(row=0, column=0, sticky='NESW')

    monitored_button = Button(
        root,
        text="Monitored Clusters",
        borderwidth=5,
        relief='ridge',
        command=show_monitored_clusters)
    monitored_button.grid(row=0, column=2, sticky='NESW')

    # A frame to store the cluster table
    cluster_frame = Frame(root, borderwidth=5, relief='ridge')
    cluster_frame.grid(
        row=1,
        column=0,
        sticky='NESW',
        columnspan=3,
        rowspan=2
    )

    cluster_scroll = Scrollbar(cluster_frame)
    cluster_scroll.pack(side=RIGHT, fill=Y)

    table_label = Label(cluster_frame, text="Summary of Detected Novel Clusters")
    table_label.pack()

    # Setting up the cluster table
    table = ttk.Treeview(
        cluster_frame,
        yscrollcommand=cluster_scroll.set)

    table.pack(expand=True, fill='both')

    cluster_scroll.config(command=table.yview)

    table['columns'] = ('score', 'startdate', 'enddate', 'words', 'location', 'age')

    table.column("#0", width=0, stretch=NO)
    table.column('score', anchor=CENTER, width=80)
    table.column('startdate', anchor=CENTER, width=40)
    table.column('enddate', anchor=CENTER, width=40)
    table.column('words', anchor=CENTER, width=160)
    table.column('location', anchor=CENTER, width=40)
    table.column('age', anchor=CENTER, width=80)

    table.heading("#0", text="", anchor=CENTER)
    table.heading('score', text='Score', anchor=CENTER,
              command=lambda: treeview_sort_column(table, "score", False))
    table.heading('startdate', text='Start Date', anchor=CENTER,
              command=lambda: treeview_sort_column(table, "startdate", False))
    table.heading('enddate', text='End Date', anchor=CENTER,
              command=lambda: treeview_sort_column(table, "enddate", False))
    table.heading('words', text='Words in Learned Syndrome', anchor=CENTER,
              command=lambda: treeview_sort_column(table, "words", False))
    table.heading('location', text='Affected Locations', anchor=CENTER,
              command=lambda: treeview_sort_column(table, "location", False))
    table.heading('age', text='Affected Age Range', anchor=CENTER,
              command=lambda: treeview_sort_column(table, "age", False))

    # Inserting the clusters rows to the table
    insert_rows(table, novel)

    # Setting up the lower frame for the cluster detail
    details_frame = Frame(root, borderwidth=5, relief='ridge')
    details_frame.grid(
        row=3,
        column=0,
        sticky='NESW',
        columnspan=2,
        rowspan=1
   )

    details_label = Label(details_frame, text="Details for Selected Clusters")
    details_label.pack()

    # A table for cases in a specfic cluster
    case_table = ttk.Treeview(
        details_frame
    )

    case_table.pack(expand=True, fill='both')

    case_table['columns'] = ('date', 'time', 'location', 'words', 'icd', 'sex', 'age', 'id')

    case_table.column("#0", width=0, stretch=NO)
    case_table.column('date', anchor=CENTER, width=40)
    case_table.column('time', anchor=CENTER, width=40)
    case_table.column('location', anchor=CENTER, width=40)
    case_table.column('words', anchor=CENTER, width=80)
    case_table.column('icd', anchor=CENTER, width=40)
    case_table.column('sex', anchor=CENTER, width=40)
    case_table.column('age', anchor=CENTER, width=40)
    case_table.column('id', anchor=CENTER, width=80)

    case_table.heading("#0", text="", anchor=CENTER)
    case_table.heading('date', text='Date', anchor=CENTER,
                   command=lambda: treeview_sort_column(case_table, "date", False))
    case_table.heading('time', text='Time', anchor=CENTER,
                   command=lambda: treeview_sort_column(case_table, "time", False))
    case_table.heading('location', text='Location', anchor=CENTER,
                   command=lambda: treeview_sort_column(case_table, "location", False))
    case_table.heading('words', text='Chief Complaint', anchor=CENTER,
                   command=lambda: treeview_sort_column(case_table, "words", False))
    case_table.heading('icd', text='ICD', anchor=CENTER,
                   command=lambda: treeview_sort_column(case_table, "icd", False))
    case_table.heading('sex', text='Sex', anchor=CENTER,
                   command=lambda: treeview_sort_column(case_table, "sex", False))
    case_table.heading('age', text='Age Group', anchor=CENTER,
                   command=lambda: treeview_sort_column(case_table, "age", False))
    case_table.heading('id', text='VISIT ID', anchor=CENTER,
                   command=lambda: treeview_sort_column(case_table, "id", False))

    # Setting up the pie chart section
    canvas_frame = Frame(root, borderwidth=5, relief='ridge')
    canvas_frame.grid(
        row=3,
        column=2,
        sticky='NESW',
        rowspan=1,
        columnspan=1
    )

    canvas_label = Label(canvas_frame, text="Pie Chart for Selected Clusters")
    canvas_label.pack()

    case_canvas = Frame(canvas_frame)

    case_canvas.pack()

    monitor_cluster_button = Button(canvas_frame, text="Include Cluster in Future Runs", command=add_cluster)

    monitor_cluster_button.pack(expand=True, fill='x')

    updating_case_table()

    table.bind("<<TreeviewSelect>>", updating_case_table)

    root.mainloop()

if __name__ == '__main__':
    main(FLAGS)

MUSES Open Source Software Code/visualization/visualize.py


from app import note
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware

app = FastAPI()

origins = [
    "http://localhost:3000",
]

app.add_middleware(
    CORSMiddleware,
    allow_origins=origins,
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

app.include_router(note.router, tags=['Notes'], prefix='/api/notes')

@app.get("/api/healthchecker")
def root():
    return {"message": "Welcome to FastAPI with Pymongo"}


count = 0
i = 2

while i <= 1000:
    somme = 2
    divisible = 2

    while divisible <= somme:
        if somme % divisible == 0:
            break

        divisible += 1
        somme += i

    if somme == i * 2:
        count += 1
        print(i)

    i += 1


import sys
sys.stdin = open("tree_subtree.txt")

# 전위
def preorder(start):
    global count
    if start:
        preorder(tree[start][0])
        preorder(tree[start][1])
        count += 1

# 중위
def inorder(start):
    global count
    if start:
        inorder(tree[start][0])
        count += 1
        inorder(tree[start][1])

# 후위
def postorder(start):
    global count
    if start:
        count += 1
        postorder(tree[start][0])
        postorder(tree[start][1])

T = int(input())

for test_case in range(1, T+1):
    E, N = map(int, input().split())

    # 노드 번호는 E+1까지 존재 (간선의 개수 + 1)
    tree = [[0 for _ in range(2)] for _ in range(E+2)]
    data = list(map(int, input().split()))

    for i in range(0, len(data), 2):
        if tree[data[i]][0]:
            tree[data[i]][1] = data[i+1]
        else:
            tree[data[i]][0] = data[i+1]

    count = 0
    preorder(N)
    # inorder(N)
    # postorder(N)

    print('#{} {}'.format(test_case, count))


#!/usr/bin/python
from pymongo import MongoClient
from flask import Flask, jsonify, request
import datetime

#define our mongo connection
client = MongoClient("localhost", 27017)
db = client.oval
races = db.races

app = Flask(__name__)

@app.route('/')
def index():
    return "oval api"

@app.route('/races')
def get_races():
    if 'year' in request.args and not request.args['year'].isdigit():
        return jsonify({'code': 400, 'message': "Invalid year.", 'fields': 'year'}), 400

    json_result = []
    for race in db.races.find({},{"_id": 0}).limit(0):
        json_result.append(race)
    return jsonify({"races": json_result})
@app.route('/categories')
def get_categores():
    if 'year' in request.args and not request.args['year'].isdigit():
        return jsonify({'code': 400, 'message': "Invalid year.", 'fields': 'year'}), 400
    if 'year' in request.args:
        start_date = datetime.datetime(int(request.args['year']),1,1)
        end_date = datetime.datetime(int(request.args['year']),12,31)
        return jsonify({'categories': races.distinct('category',{ "date": {"$gte": start_date, "$lt": end_date }})})
    else:
        return jsonify({'categories': races.distinct('category')})

@app.route('/test')
def test():
    return "Value for year: " + request.args.get('year', 'HELLO!')
if __name__ == '__main__':
    app.run(debug=True)


import numpy as np
from scipy.optimize import minimize
from scipy.io import loadmat
from numpy.linalg import det, inv
from math import sqrt, pi
import scipy.io
import matplotlib.pyplot as plt
import pickle
import sys

def ldaLearn(X,y):
    # Inputs
    # X - a N x d matrix with each row corresponding to a training example
    # y - a N x 1 column vector indicating the labels for each training example
    #
    # Outputs
    # means - A k x d matrix containing learnt means for each of the k classes
    # covmat - A single d x d learnt covariance matrix

    d = X.shape[1]

    numK = []
    #find k
    for x in range(y.shape[0]):
        if int(y[x]) not in numK:
            numK.append(int(y[x]))

    k = len(numK)

    # Pre build the matricies
    Xc = np.ones(X.shape)
    means = np.zeros((k,d))
    total = np.zeros((k,1))

    #find mean
    for index in range(y.shape[0]):
        #increment totals at position
        total[int(y[index])-1]+=1
        #increment for each d
        for dIter in range(d):
            means[int(y[index])-1][dIter] += X[index][dIter]

    #divide by d to find the means
    for row in range(k):
        for column in range(d):
            means[row][column] = means[row][column]/total[row]

    covmat = np.cov(X, rowvar=False)

    return means,covmat

def qdaLearn(X,y):
    # Inputs
    # X - a N x d matrix with each row corresponding to a training example
    # y - a N x 1 column vector indicating the labels for each training example

    d = X.shape[1]

    numK = []
    #find k
    for x in range(y.shape[0]):
        if int(y[x]) not in numK:
            numK.append(int(y[x]))

    k = len(numK)

    # Pre build the matricies
    Xc = np.ones(X.shape)
    means = np.zeros((k,d))
    total = np.zeros((k,1))

    #find mean
    for index in range(y.shape[0]):
        #increment totals at position
        total[int(y[index])-1]+=1
        #increment for each d
        for dIter in range(d):
            means[int(y[index])-1][dIter] += X[index][dIter]

    #divide by d to find the means
    for row in range(k):
        for column in range(d):
            means[row][column] = means[row][column]/total[row]

    #covariance--------------------------

    covmats = []

    classes = []

    #initialize matricies

    for x in range(k):
        classes.append(np.zeros((1,d)))

    for row in range(y.shape[0]):
        classes[int(y[row])-1] = np.vstack([classes[int(y[row])-1],X[row]])

    for i in range(k):
        classes[i] = classes[i][1:]

    for index in range(k):
        #prebuld the matrix to help with covariance
        Xc = np.ones(classes[index].shape)

        #find Xc, an intermediate term for finding covmat
        for cols in range(classes[index].shape[1]):
            temp = classes[index][:,cols]
            colAvg = np.average(temp)
            Xc[:,cols] = temp - colAvg
        covmats.append((1/classes[index].shape[0])*(np.transpose(Xc)).dot(Xc))

    # Outputs
    # means - A k x d matrix containing learnt means for each of the k classes
    # covmats - A list of k d x d learnt covariance matrices for each of the k classes

    # IMPLEMENT THIS METHOD
    return means,covmats

def ldaTest(means,covmat,Xtest,ytest):
    # Inputs
    # means, covmat - parameters of the LDA model
    # Xtest - a N x d matrix with each row corresponding to a test example
    # ytest - a N x 1 column vector indicating the labels for each test example
    # Outputs
    # acc - A scalar accuracy value
    # ypred - N x 1 column vector indicating the predicted labels
    N = Xtest.shape[0]

    ypred = 0

    acc = 0.0

    N = Xtest.shape[0]
    k = means.shape[0]
    findMax = np.zeros((N,k))

    covmat = 1/np.linalg.det(np.linalg.inv(covmat))

    for i,x in enumerate(Xtest):
        for j in range(k):
            top = x - means[j]
            top = np.dot(top, np.transpose(top))
            theTop = -.5*(top*covmat)
            exp = np.exp(theTop)
            prob = covmat*exp
            findMax[i][j] = prob

    maxes = np.argmax(findMax,axis=1)
    maxes = np.add(maxes,1)

    for i,x in enumerate(ytest):
        if x == maxes[i]:
            acc+=1

    acc = acc/N

    return acc,ytest

def qdaTest(means,covmats,Xtest,ytest):
    # Inputs
    # means, covmats - parameters of the QDA model
    # Xtest - a N x d matrix with each row corresponding to a test example
    # ytest - a N x 1 column vector indicating the labels for each test example
    # Outputs
    # acc - A scalar accuracy value
    # ypred - N x 1 column vector indicating the predicted labels

    ypred = 0

    acc = 0.0

    N = Xtest.shape[0]
    k = len(covmats)
    covmat = np.zeros((k))
    findMax = np.zeros((N,k))

    cov = covmats
    #get the determinate of each covariance matrix
    for x in range(len(covmats)):
        covmat[x] = 1/np.linalg.det(covmats[x])

    for i,x in enumerate(Xtest):
        for y in range(k):
            top = (x-means[y])*covmat[y]
            top = np.dot(np.transpose(top),top)
            theTop = -.5*(top)
            exp = np.exp(theTop)
            prob = covmat[y]*exp
            findMax[i][y] = prob

    maxes = np.argmax(findMax,axis=1)
    maxes = np.add(maxes,1)
    for i,x in enumerate(ytest):
        if x == maxes[i]:
            acc+=1

    ypred = np.array(maxes)
    ypred = ypred.reshape(ypred.shape[0],1)
    acc = acc/N
    # IMPLEMENT THIS METHOD
    return acc,ypred

def learnOLERegression(X,y):
    # Inputs:
    # X = N x d
    # y = N x 1
    # Output:
    # w = d x 1

    #formula w = (x^T x)^-1 (x^T Y)
    s = np.dot(np.transpose(X),X)

    inverse = np.linalg.inv(s)
    w = np.dot(inverse,np.dot(np.transpose(X),y))

    # IMPLEMENT THIS METHOD
    return w

def learnRidgeRegression(X,y,lambd):
    # Inputs:
    # X = N x d
    # y = N x 1
    # lambd = ridge parameter (scalar)
    # Output:
    # w = d x 1

    left = np.linalg.inv(lambd*np.identity(X.shape[1]) + np.dot(np.transpose(X),X))
    right = np.dot(np.transpose(X),y)
    w = np.dot(left,right)

    # IMPLEMENT THIS METHOD
    return w

def testOLERegression(w,Xtest,ytest):
    # Inputs:
    # w = d x 1
    # Xtest = N x d
    # ytest = X x 1
    # Output:
    # mse

    #total = np.sum(np.square(np.transpose(ytest-np.dot(Xtest,w))))
    N = Xtest.shape[0]

    total = 0
    for i,x in enumerate(Xtest):
        right = np.dot(np.transpose(w),x)
        j = ytest[i]-right
        total+= np.dot(np.transpose(j),j)

    mse = total/N
    # IMPLEMENT THIS METHOD
    return mse

def regressionObjVal(w, X, y, lambd):

    # compute squared error (scalar) and gradient of squared error with respect
    # to w (vector) for the given data X and y and the regularization parameter
    # lambda

    #changes y from (252,1) to (252,)
    y = y.transpose()
    y = y[0]
    y.tolist()

    N = X.shape[0]

    #calculate squared error
    preSum = y - np.dot(X,w)
    postSum = np.sum(np.dot(np.transpose(preSum),preSum))/(2*N)
    regression = (lambd/2)*(np.dot(np.transpose(w),w))
    error = postSum+regression

    #calculate squared error gradient
    postW = (lambd*w)
    left = np.dot(np.transpose(w),np.dot(np.transpose(X),X))
    right = np.dot(np.transpose(X),y)

    s = (left-right)/N

    error_grad = s+postW

    # IMPLEMENT THIS METHOD
    return error, error_grad

def mapNonLinear(x,p):
    # Inputs:
    # x - a single column vector (N x 1)
    # p - integer (>= 0)
    # Outputs:
    # Xp - (N x (p+1))

    N = x.shape[0]

    Xp = np.zeros((N,p+1))

    for i in range(N):
        for j in range(p+1):
            Xp[i][j] = x[i]**j

    return Xp

# Main script

# Problem 1
# load the sample data
if sys.version_info.major == 2:
    X,y,Xtest,ytest = pickle.load(open('sample.pickle','rb'))
else:
    X,y,Xtest,ytest = pickle.load(open('sample.pickle','rb'),encoding = 'latin1')

# LDA
means,covmat = ldaLearn(X,y)
ldaacc,ldares = ldaTest(means,covmat,Xtest,ytest)
print('LDA Accuracy = '+str(ldaacc))
# QDA
means,covmats = qdaLearn(X,y)
qdaacc,qdares = qdaTest(means,covmats,Xtest,ytest)
print('QDA Accuracy = '+str(qdaacc))

# plotting boundaries
x1 = np.linspace(-5,20,100)
x2 = np.linspace(-5,20,100)
xx1,xx2 = np.meshgrid(x1,x2)
xx = np.zeros((x1.shape[0]*x2.shape[0],2))
xx[:,0] = xx1.ravel()
xx[:,1] = xx2.ravel()

fig = plt.figure(figsize=[12,6])
plt.subplot(1, 2, 1)

zacc,zldares = ldaTest(means,covmat,xx,np.zeros((xx.shape[0],1)))
plt.contourf(x1,x2,zldares.reshape((x1.shape[0],x2.shape[0])),alpha=0.3)
plt.scatter(Xtest[:,0],Xtest[:,1],c=ytest.flatten())
plt.title('LDA')

plt.subplot(1, 2, 2)

zacc,zqdares = qdaTest(means,covmats,xx,np.zeros((xx.shape[0],1)))
plt.contourf(x1,x2,zqdares.reshape((x1.shape[0],x2.shape[0])),alpha=0.3)
plt.scatter(Xtest[:,0],Xtest[:,1],c=ytest.flatten())
plt.title('QDA')

plt.show()

# Problem 2
if sys.version_info.major == 2:
    X,y,Xtest,ytest = pickle.load(open('diabetes.pickle','rb'))
else:
    X,y,Xtest,ytest = pickle.load(open('diabetes.pickle','rb'),encoding = 'latin1')

# add intercept
X_i = np.concatenate((np.ones((X.shape[0],1)), X), axis=1)
Xtest_i = np.concatenate((np.ones((Xtest.shape[0],1)), Xtest), axis=1)

w = learnOLERegression(X,y)
mle = testOLERegression(w,Xtest,ytest)

w_i = learnOLERegression(X_i,y)
mle_i = testOLERegression(w_i,Xtest_i,ytest)

print('MSE without intercept '+str(mle))
print('MSE with intercept '+str(mle_i))

# Problem 3
k = 101
lambdas = np.linspace(0, 1, num=k)
i = 0
mses3_train = np.zeros((k,1))
mses3 = np.zeros((k,1))
for lambd in lambdas:
    w_l = learnRidgeRegression(X_i,y,lambd)
    mses3_train[i] = testOLERegression(w_l,X_i,y)
    mses3[i] = testOLERegression(w_l,Xtest_i,ytest)
    i = i + 1
print(mses3)
fig = plt.figure(figsize=[12,6])
plt.subplot(1, 2, 1)
plt.plot(lambdas,mses3_train)
plt.title('MSE for Train Data')
plt.subplot(1, 2, 2)
plt.plot(lambdas,mses3)
plt.title('MSE for Test Data')

plt.show()

# Problem 4
k = 101
lambdas = np.linspace(0, 1, num=k)
i = 0
mses4_train = np.zeros((k,1))
mses4 = np.zeros((k,1))
opts = {'maxiter' : 20}    # Preferred value.
w_init = np.ones((X_i.shape[1],1))
for lambd in lambdas:
    args = (X_i, y, lambd)
    w_l = minimize(regressionObjVal, w_init, jac=True, args=args,method='CG', options=opts)
    w_l = np.transpose(np.array(w_l.x))
    w_l = np.reshape(w_l,[len(w_l),1])
    mses4_train[i] = testOLERegression(w_l,X_i,y)
    mses4[i] = testOLERegression(w_l,Xtest_i,ytest)
    i = i + 1
fig = plt.figure(figsize=[12,6])
plt.subplot(1, 2, 1)
plt.plot(lambdas,mses4_train)
plt.plot(lambdas,mses3_train)
plt.title('MSE for Train Data')
plt.legend(['Using scipy.minimize','Direct minimization'])

plt.subplot(1, 2, 2)
plt.plot(lambdas,mses4)
plt.plot(lambdas,mses3)
plt.title('MSE for Test Data')
plt.legend(['Using scipy.minimize','Direct minimization'])
plt.show()

# Problem 5
pmax = 7
lambda_opt = 0.06 # REPLACE THIS WITH lambda_opt estimated from Problem 3
mses5_train = np.zeros((pmax,2))
mses5 = np.zeros((pmax,2))
for p in range(pmax):
    Xd = mapNonLinear(X[:,2],p)
    Xdtest = mapNonLinear(Xtest[:,2],p)
    w_d1 = learnRidgeRegression(Xd,y,0)
    mses5_train[p,0] = testOLERegression(w_d1,Xd,y)
    mses5[p,0] = testOLERegression(w_d1,Xdtest,ytest)
    w_d2 = learnRidgeRegression(Xd,y,lambda_opt)
    mses5_train[p,1] = testOLERegression(w_d2,Xd,y)
    mses5[p,1] = testOLERegression(w_d2,Xdtest,ytest)

fig = plt.figure(figsize=[12,6])
plt.subplot(1, 2, 1)
plt.plot(range(pmax),mses5_train)
plt.title('MSE for Train Data')
plt.legend(('No Regularization','Regularization'))
plt.subplot(1, 2, 2)
plt.plot(range(pmax),mses5)
plt.title('MSE for Test Data')
plt.legend(('No Regularization','Regularization'))
plt.show()


# -*- coding: utf-8 -*-

import babel.dates
import re
import werkzeug

from ast import literal_eval
from werkzeug.datastructures import OrderedMultiDict
from werkzeug.exceptions import NotFound

from odoo import fields, http, _
from odoo.addons.website.controllers.main import QueryURL
from odoo.http import request
from odoo.osv import expression
from odoo.tools.misc import get_lang
from odoo.tools import lazy
from odoo.exceptions import UserError

class WebsiteEventController(http.Controller):

    def sitemap_event(env, rule, qs):
        if not qs or qs.lower() in '/events':
            yield {'loc': '/events'}

    # ------------------------------------------------------------
    # EVENT LIST
    # ------------------------------------------------------------

    def _get_events_search_options(self, **post):
        return {
            'displayDescription': False,
            'displayDetail': False,
            'displayExtraDetail': False,
            'displayExtraLink': False,
            'displayImage': False,
            'allowFuzzy': not post.get('noFuzzy'),
            'date': post.get('date'),
            'tags': post.get('tags'),
            'type': post.get('type'),
            'country': post.get('country'),
        }

    @http.route(['/event', '/event/page/<int:page>', '/events', '/events/page/<int:page>'], type='http', auth="public", website=True, sitemap=sitemap_event)
    def events(self, page=1, **searches):
        Event = request.env['event.event']
        SudoEventType = request.env['event.type'].sudo()

        searches.setdefault('search', '')
        searches.setdefault('date', 'upcoming')
        searches.setdefault('tags', '')
        searches.setdefault('type', 'all')
        searches.setdefault('country', 'all')

        website = request.website

        step = 12  # Number of events per page

        options = self._get_events_search_options(**searches)
        order = 'date_begin'
        if searches.get('date', 'upcoming') == 'old':
            order = 'date_begin desc'
        order = 'is_published desc, ' + order
        search = searches.get('search')
        event_count, details, fuzzy_search_term = website._search_with_fuzzy("events", search,
            limit=page * step, order=order, options=options)
        event_details = details[0]
        events = event_details.get('results', Event)
        events = events[(page - 1) * step:page * step]

        # count by domains without self search
        domain_search = [('name', 'ilike', fuzzy_search_term or searches['search'])] if searches['search'] else []

        no_date_domain = event_details['no_date_domain']
        dates = event_details['dates']
        for date in dates:
            if date[0] not in ['all', 'old']:
                date[3] = Event.search_count(expression.AND(no_date_domain) + domain_search + date[2])

        no_country_domain = event_details['no_country_domain']
        countries = Event.read_group(expression.AND(no_country_domain) + domain_search, ["id", "country_id"],
            groupby="country_id", orderby="country_id")
        countries.insert(0, {
            'country_id_count': sum([int(country['country_id_count']) for country in countries]),
            'country_id': ("all", _("All Countries"))
        })

        search_tags = event_details['search_tags']
        current_date = event_details['current_date']
        current_type = None
        current_country = None

        if searches["type"] != 'all':
            current_type = SudoEventType.browse(int(searches['type']))

        if searches["country"] != 'all' and searches["country"] != 'online':
            current_country = request.env['res.country'].browse(int(searches['country']))

        pager = website.pager(
            url="/event",
            url_args=searches,
            total=event_count,
            page=page,
            step=step,
            scope=5)

        keep = QueryURL('/event', **{
            key: value for key, value in searches.items() if (
                key == 'search' or
                (value != 'upcoming' if key == 'date' else value != 'all'))
            })

        searches['search'] = fuzzy_search_term or search

        values = {
            'current_date': current_date,
            'current_country': current_country,
            'current_type': current_type,
            'event_ids': events,  # event_ids used in website_event_track so we keep name as it is
            'dates': dates,
            'categories': request.env['event.tag.category'].search([
                ('is_published', '=', True), '|', ('website_id', '=', website.id), ('website_id', '=', False)
            ]),
            'countries': countries,
            'pager': pager,
            'searches': searches,
            'search_tags': search_tags,
            'keep': keep,
            'search_count': event_count,
            'original_search': fuzzy_search_term and search,
            'website': website
        }

        if searches['date'] == 'old':
            # the only way to display this content is to set date=old so it must be canonical
            values['canonical_params'] = OrderedMultiDict([('date', 'old')])

        return request.render("website_event.index", values)

    # ------------------------------------------------------------
    # EVENT PAGE
    # ------------------------------------------------------------

    @http.route(['''/event/<model("event.event"):event>/page/<path:page>'''], type='http', auth="public", website=True, sitemap=False)
    def event_page(self, event, page, **post):
        values = {
            'event': event,
        }

        if '.' not in page:
            page = 'website_event.%s' % page

        try:
            # Every event page view should have its own SEO.
            values['seo_object'] = request.website.get_template(page)
            values['main_object'] = event
        except ValueError:
            # page not found
            values['path'] = re.sub(r"^website_event\.", '', page)
            values['from_template'] = 'website_event.default_page'  # .strip('website_event.')
            page = request.env.user.has_group('website.group_website_designer') and 'website.page_404' or 'http_routing.404'

        return request.render(page, values)

    @http.route(['''/event/<model("event.event"):event>'''], type='http', auth="public", website=True, sitemap=True)
    def event(self, event, **post):
        if event.menu_id and event.menu_id.child_id:
            target_url = event.menu_id.child_id[0].url
        else:
            target_url = '/event/%s/register' % str(event.id)
        if post.get('enable_editor') == '1':
            target_url += '?enable_editor=1'
        return request.redirect(target_url)

    @http.route(['''/event/<model("event.event"):event>/register'''], type='http', auth="public", website=True, sitemap=False)
    def event_register(self, event, **post):
        values = self._prepare_event_register_values(event, **post)
        return request.render("website_event.event_description_full", values)

    def _prepare_event_register_values(self, event, **post):
        """Return the require values to render the template."""
        urls = lazy(event._get_event_resource_urls)
        return {
            'event': event,
            'main_object': event,
            'range': range,
            'google_url': lazy(lambda: urls.get('google_url')),
            'iCal_url': lazy(lambda: urls.get('iCal_url')),
            'registration_error_code': post.get('registration_error_code'),
        }

    def _process_tickets_form(self, event, form_details):
        """ Process posted data about ticket order. Generic ticket are supported
        for event without tickets (generic registration).

        :return: list of order per ticket: [{
            'id': if of ticket if any (0 if no ticket),
            'ticket': browse record of ticket if any (None if no ticket),
            'name': ticket name (or generic 'Registration' name if no ticket),
            'quantity': number of registrations for that ticket,
        }, {...}]
        """
        ticket_order = {}
        for key, value in form_details.items():
            registration_items = key.split('nb_register-')
            if len(registration_items) != 2:
                continue
            ticket_order[int(registration_items[1])] = int(value)

        ticket_dict = dict((ticket.id, ticket) for ticket in request.env['event.event.ticket'].sudo().search([
            ('id', 'in', [tid for tid in ticket_order.keys() if tid]),
            ('event_id', '=', event.id)
        ]))

        return [{
            'id': tid if ticket_dict.get(tid) else 0,
            'ticket': ticket_dict.get(tid),
            'name': ticket_dict[tid]['name'] if ticket_dict.get(tid) else _('Registration'),
            'quantity': count,
        } for tid, count in ticket_order.items() if count]

    @http.route(['/event/<model("event.event"):event>/registration/new'], type='json', auth="public", methods=['POST'], website=True)
    def registration_new(self, event, **post):
        tickets = self._process_tickets_form(event, post)
        availability_check = True
        if event.seats_limited:
            ordered_seats = 0
            for ticket in tickets:
                ordered_seats += ticket['quantity']
            if event.seats_available < ordered_seats:
                availability_check = False
        if not tickets:
            return False
        default_first_attendee = {}
        if not request.env.user._is_public():
            default_first_attendee = {
                "name": request.env.user.name,
                "email": request.env.user.email,
                "phone": request.env.user.mobile or request.env.user.phone,
            }
        else:
            visitor = request.env['website.visitor']._get_visitor_from_request()
            if visitor.email:
                default_first_attendee = {
                    "name": visitor.display_name,
                    "email": visitor.email,
                    "phone": visitor.mobile,
                }
        return request.env['ir.ui.view']._render_template("website_event.registration_attendee_details", {
            'tickets': tickets,
            'event': event,
            'availability_check': availability_check,
            'default_first_attendee': default_first_attendee,
        })

    def _process_attendees_form(self, event, form_details):
        """ Process data posted from the attendee details form.
        Extracts question answers:
        - For both questions asked 'once_per_order' and questions asked to every attendee
        - For questions of type 'simple_choice', extracting the suggested answer id
        - For questions of type 'text_box', extracting the text answer of the attendee.

        :param form_details: posted data from frontend registration form, like
            {'1-name': 'r', '1-email': 'r@r.com', '1-phone': '', '1-event_ticket_id': '1'}
        """
        allowed_fields = request.env['event.registration']._get_website_registration_allowed_fields()
        registration_fields = {key: v for key, v in request.env['event.registration']._fields.items() if key in allowed_fields}
        for ticket_id in list(filter(lambda x: x is not None, [form_details[field] if 'event_ticket_id' in field else None for field in form_details.keys()])):
            if int(ticket_id) not in event.event_ticket_ids.ids and len(event.event_ticket_ids.ids) > 0:
                raise UserError(_("This ticket is not available for sale for this event"))
        registrations = {}
        general_answer_ids = []
        general_identification_answers = {}
        # as we may have several questions populating the same field (e.g: the phone)
        # we use this to hold the fields that have already been handled
        # goal is to use the answer to the first question of every 'type' (aka name / phone / email / company name)
        already_handled_fields_data = {}
        for key, value in form_details.items():
            if not value:
                continue

            key_values = key.split('-')
            # Special case for handling event_ticket_id data that holds only 2 values
            if len(key_values) == 2:
                registration_index, field_name = key_values
                if field_name not in registration_fields:
                    continue
                registrations.setdefault(registration_index, dict())[field_name] = int(value) or False
                continue

            registration_index, question_type, question_id = key_values
            answer_values = None
            if question_type == 'simple_choice':
                answer_values = {
                    'question_id': int(question_id),
                    'value_answer_id': int(value)
                }
            else:
                answer_values = {
                    'question_id': int(question_id),
                    'value_text_box': value
                }

            if answer_values and not int(registration_index):
                general_answer_ids.append((0, 0, answer_values))
            elif answer_values:
                registrations.setdefault(registration_index, dict())\
                    .setdefault('registration_answer_ids', list()).append((0, 0, answer_values))

            if question_type in ('name', 'email', 'phone', 'company_name')\
                and question_type not in already_handled_fields_data.get(registration_index, []):
                if question_type not in registration_fields:
                    continue

                field_name = question_type
                already_handled_fields_data.setdefault(registration_index, list()).append(field_name)

                if not int(registration_index):
                    general_identification_answers[field_name] = value
                else:
                    registrations.setdefault(registration_index, dict())[field_name] = value

        if general_answer_ids:
            for registration in registrations.values():
                registration.setdefault('registration_answer_ids', list()).extend(general_answer_ids)

        if general_identification_answers:
            for registration in registrations.values():
                registration.update(general_identification_answers)

        return list(registrations.values())

    def _create_attendees_from_registration_post(self, event, registration_data):
        """ Also try to set a visitor (from request) and
        a partner (if visitor linked to a user for example). Purpose is to gather
        as much informations as possible, notably to ease future communications.
        Also try to update visitor informations based on registration info. """
        visitor_sudo = request.env['website.visitor']._get_visitor_from_request(force_create=True)

        registrations_to_create = []
        for registration_values in registration_data:
            registration_values['event_id'] = event.id
            if not registration_values.get('partner_id') and visitor_sudo.partner_id:
                registration_values['partner_id'] = visitor_sudo.partner_id.id
            elif not registration_values.get('partner_id'):
                registration_values['partner_id'] = False if request.env.user._is_public() else request.env.user.partner_id.id

            # update registration based on visitor
            registration_values['visitor_id'] = visitor_sudo.id

            registrations_to_create.append(registration_values)

        return request.env['event.registration'].sudo().create(registrations_to_create)

    @http.route(['''/event/<model("event.event"):event>/registration/confirm'''], type='http', auth="public", methods=['POST'], website=True)
    def registration_confirm(self, event, **post):
        """ Check before creating and finalize the creation of the registrations
            that we have enough seats for all selected tickets.
            If we don't, the user is instead redirected to page to register with a
            formatted error message. """
        registrations_data = self._process_attendees_form(event, post)
        event_ticket_ids = {registration['event_ticket_id'] for registration in registrations_data}
        event_tickets = request.env['event.event.ticket'].browse(event_ticket_ids)
        if any(event_ticket.seats_limited and event_ticket.seats_available < len(registrations_data) for event_ticket in event_tickets):
            return request.redirect('/event/%s/register?registration_error_code=insufficient_seats' % event.id)
        attendees_sudo = self._create_attendees_from_registration_post(event, registrations_data)

        return request.redirect(('/event/%s/registration/success?' % event.id) + werkzeug.urls.url_encode({'registration_ids': ",".join([str(id) for id in attendees_sudo.ids])}))

    @http.route(['/event/<model("event.event"):event>/registration/success'], type='http', auth="public", methods=['GET'], website=True, sitemap=False)
    def event_registration_success(self, event, registration_ids):
        # fetch the related registrations, make sure they belong to the correct visitor / event pair
        visitor = request.env['website.visitor']._get_visitor_from_request()
        if not visitor:
            raise NotFound()
        attendees_sudo = request.env['event.registration'].sudo().search([
            ('id', 'in', [str(registration_id) for registration_id in registration_ids.split(',')]),
            ('event_id', '=', event.id),
            ('visitor_id', '=', visitor.id),
        ])
        return request.render("website_event.registration_complete",
            self._get_registration_confirm_values(event, attendees_sudo))

    def _get_registration_confirm_values(self, event, attendees_sudo):
        urls = event._get_event_resource_urls()
        return {
            'attendees': attendees_sudo,
            'event': event,
            'google_url': urls.get('google_url'),
            'iCal_url': urls.get('iCal_url')
        }

    # ------------------------------------------------------------
    # TOOLS (HELPERS)
    # ------------------------------------------------------------

    def get_formated_date(self, event):
        start_date = fields.Datetime.from_string(event.date_begin).date()
        end_date = fields.Datetime.from_string(event.date_end).date()
        month = babel.dates.get_month_names('abbreviated', locale=get_lang(event.env).code)[start_date.month]
        return ('%s %s%s') % (month, start_date.strftime("%e"), (end_date != start_date and ("-" + end_date.strftime("%e")) or ""))

    def _extract_searched_event_tags(self, searches):
        tags = request.env['event.tag']
        if searches.get('tags'):
            try:
                tag_ids = literal_eval(searches['tags'])
            except:
                pass
            else:
                # perform a search to filter on existing / valid tags implicitely + apply rules on color
                tags = request.env['event.tag'].search([('id', 'in', tag_ids)])
        return tags


#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import random
import string
from .AbstractNoiseGen import AbstractNoiseGen
from .Edit import Edit
from pyspark.sql.types import *
from pyspark.sql import functions as F

class EditGen(AbstractNoiseGen):
    """
    This class introduces edits (according to the edit distance) into the data.
    """

    def __init__(self, df, columns, edits=3):
        super().__init__(df, columns)
        self.edits = edits

    @staticmethod
    def description(**kwargs):
        return '{} edits the given value with some changes' \
            .format(EditGen.name())

    @staticmethod
    def name(**kwargs):
        return 'EDIT'

    @staticmethod
    def create_edit(elem, edits, only_numbers):
        for n in range(edits):
            choice = random.choice(list(Edit))
            if choice is Edit.INSERTION:
                elem = EditGen.create_insertion(elem, only_numbers)
            elif choice is Edit.SUBSTITUTION:
                elem = EditGen.create_substitution(elem, only_numbers)
            elif choice is Edit.DELETION:
                elem = EditGen.create_deletion(elem)
            else:
                raise IndexError(
                    'The value {} is not a supported value'.format(choice))
        return elem

    @staticmethod
    def create_insertion(elem, only_numbers):
        if only_numbers:
            char = random.choice(string.digits)
        else:
            char = random.choice(string.ascii_letters)
        if not elem:
            return elem + char
        position = random.randint(0, len(elem))
        return elem[:position] + char + elem[position:]

    @staticmethod
    def create_substitution(elem, only_numbers):
        if not elem:
            return elem
        position = random.randint(0, len(elem) - 1)
        char = elem[position]
        while char == elem[position]:
            if only_numbers:
                char = random.choice(string.digits)
            else:
                char = random.choice(string.ascii_letters)
        return elem[:max(0, position)] + char + elem[
                                                min(position + 1, len(elem)):]

    @staticmethod
    def create_deletion(elem):
        if not elem:
            return elem
        position = random.randint(0, len(elem) - 1)
        return elem[:position] + elem[position + 1:]

    @staticmethod
    def edit_generation(elem, distribution, edits, only_numbers=False):
        if not distribution.generate(elem):
            return elem
        if elem is None or not elem:
            return elem
        if isinstance(elem, int) or isinstance(elem, float) or isinstance(elem, str):
            ret = EditGen.create_edit(str(elem), edits, only_numbers)
        else:
            raise IndexError('Type {} not supported'.format(type(elem)))
        if isinstance(elem, int):
            if not ret:
                ret = 0
            return int(ret)
        elif isinstance(elem, float):
            if not ret:
                ret = 0
            return float(ret)
        return ret

    def string_udf(self, distribution):
        edits = self.edits
        return F.udf(lambda elem: EditGen.edit_generation(elem, distribution,
                                                          edits,
                                                          only_numbers=False),
                     StringType())

    def int_udf(self, distribution):
        edits = self.edits
        return F.udf(lambda elem: EditGen.edit_generation(elem, distribution,
                                                          edits,
                                                          only_numbers=True),
                     IntegerType())

    def double_udf(self, distribution):
        edits = self.edits
        return F.udf(lambda elem: EditGen.edit_generation(elem, distribution,
                                                          edits,
                                                          only_numbers=True),
                     DoubleType())

    def bigint_udf(self, distribution):
        edits = self.edits
        return F.udf(lambda elem: EditGen.edit_generation(elem, distribution,
                                                          edits,
                                                          only_numbers=True),
                     LongType())

    def tinyint_udf(self, distribution):
        edits = self.edits
        return F.udf(lambda elem: EditGen.edit_generation(elem, distribution,
                                                          edits,
                                                          only_numbers=True),
                     IntegerType())

    def decimal_udf(self, distribution):
        edits = self.edits
        return F.udf(lambda elem: EditGen.edit_generation(elem, distribution,
                                                          edits,
                                                          only_numbers=True),
                     IntegerType())

    def smallint_udf(self, distribution):
        edits = self.edits
        return F.udf(lambda elem: EditGen.edit_generation(elem, distribution,
                                                          edits,
                                                          only_numbers=True),
                     IntegerType())

    def date_udf(self, distribution):
        pass

    def timestamp_udf(self, distribution):
        pass

    def __str__(self):
        return '{} - {}'.format(EditGen.name(), self.columns)


from __future__ import print_function,unicode_literals
import gdb

"""
psp (from r0)
exc_return (from lr)

???

...
s1
s0
[optional reserved aligner]
F: xPSR
E: pc
D: lr
C: r12
B: r3
A: r2
9: r1
8: r0: sp points to this position before exception return
7: r4
6: r5
5: r6
4: r7
3: r8
2: r9
1: r10
0: r11 : sp points to this position in the stack after context save

lowest address at bottom, highest at top.
can treat SP as an array
"""

class Rtx(object):
    def __init__(self):
        pass

    def version(self):
       pass

class RtxVersion(gdb.Command):
    def __init__(self):
        super(RtxVersion, self).__init__("rtx-version", gdb.COMMAND_RUNNING)

class Context(object):
    def __init__(self, *argv):
        if len(argv) == 0:
            self.pc = None
            self.lr = None
            self.sp = None
        elif len(argv) == 3:
            self.pc = argv[0]
            self.lr = argv[1]
            self.sp = argv[2]
        else:
            raise "invalid number of context args"

    def save(self):
        self.pc = gdb.parse_and_eval('$pc')
        self.sp = gdb.parse_and_eval('$sp')
        self.lr = gdb.parse_and_eval('$lr')

    def restore(self):
        try:
            gdb.parse_and_eval("$pc=%d" % (self.pc))
        except Exception as e:
            raise gdb.GdbError("Could not set `pc`: {}".format(e))
        try:
            gdb.parse_and_eval("$sp=%d" % (self.sp))
        except Exception as e:
            raise gdb.GdbError("Could not set `sp`: {}".format(e))
        try:
            gdb.parse_and_eval("$lr=%d" % (self.lr))
        except Exception as e:
            raise gdb.GdbError("Could not set `lr`: {}".format(e))

def rtx_bt(thread_arg):
    thread_t = gdb.lookup_type("osRtxThread_t").pointer()
    u32_t = gdb.lookup_type("uint32_t")
    tthread_t = thread_arg.type.target().unqualified().pointer()
    if tthread_t != thread_t:
        raise gdb.GdbError("rtx-bt argument is not a osRtxThread_t: '{}' != "
                           "'{}'".format(tthread_t, thread_t))
    if thread_arg == 0:
        raise gdb.GdbError("thread is NULL")

    thread = thread_arg.cast(thread_t).dereference()
    stack = thread['sp'].cast(u32_t.pointer())
    pc = stack[0xE]
    lr = stack[0xD]
    sp = stack + 0
    new_ctx = Context(pc, lr, sp)
    old_ctx = Context()
    old_ctx.save()

    new_ctx.restore()
    gdb.execute("bt")
    old_ctx.restore()

class RtxBt(gdb.Command):
    def __init__(self):
        super(RtxBt, self).__init__("rtx-bt", gdb.COMMAND_RUNNING,
                                    gdb.COMPLETE_EXPRESSION)

    def invoke(self, arg, from_tty):
        args = gdb.string_to_argv(arg)
        if len(args) != 1:
            raise gdb.GdbError("rtx-bt takes 1 osRtxThread_t argument")
        thread_arg = gdb.parse_and_eval(args[0])
        rtx_bt(thread_arg)

RtxBt()

def thread_state(value):
    status = ['inactive', 'ready', 'running', 'blocked', 'terminated' ]

    if value == -1:
        return 'error'

    vl = value & 0xf
    vh = (value & 0xf0) >> 4
    try:
        s1 = status[vl]
    except IndexError:
        s1 = "unknown({})".format(vl)

    wait = ['', 'delay', 'join', 'thread_flags', 'event_flags', 'mutex',
            'semaphore', 'memory_pool', 'message_get', 'message_put']
    if vh == 0:
        return s1

    try:
        s2 = wait[vh]
    except IndexError:
        s2 = "unknown({})".format(vh)

    return "{}|{}".format(s1, s2)

class RtxThreads(gdb.Command):
    """List all RTX threads"""
    def __init__(self):
        super(RtxThreads, self).__init__("info rtx-threads", gdb.COMMAND_STACK,
                                         gdb.COMPLETE_NONE)
        self.u32_t = gdb.lookup_type("uint32_t")

    def _pone(self, thread):
        vp = gdb.lookup_type('void').pointer()
        u32_t = self.u32_t
        stack = thread['sp'].cast(u32_t.pointer())
        pc = stack[0xE]

        try:
            pc = int(pc)
        except gdb.error:
            pc = int(str(pc).split(None, 1)[0], 16)

        thread_id = thread['id']
        tname = thread['name']
        if tname == 0:
            name = "(NULL)"
        else:
            name = str(thread['name']).split(None, 1)[1]
        x = gdb.execute("x/i {}".format(pc), False, True)[:-1]
        print("{:#x} {} {}: {}".format(
            int(thread), name, thread_state(thread['state']), x))

    def _plist(self, tlist, next_field):
        while tlist != 0:
            self._pone(tlist)
            tlist = tlist[next_field]

    def invoke(self, _arg, _from_tty):

        tctx = gdb.parse_and_eval('osRtxInfo.thread');
        print("# Curr: ")
        self._pone(tctx['run']['curr'])
        print("# Next: ")
        self._pone(tctx['run']['next'])
        print("# Delay:")
        self._plist(tctx['delay_list'], 'delay_next')
        print("# Wait:")
        self._plist(tctx['wait_list'], 'delay_next')
        print("# Idle:")
        self._pone(tctx['idle'])

RtxThreads()

def find_thread(thread_id):
    thread_p = gdb.lookup_type('osRtxThread_t').pointer()
    thread = thread_id.cast(thread_p)

    u32_t = gdb.lookup_type("uint32_t")
    stack = thread['sp'].cast(u32_t.pointer())
    return (stack[0xE], stack + 0x8)

class RtxThread(gdb.Command):
    """Run a gdb command in the context of a Rtx thread"""
    def __init__(self):
        super(RtxThread, self).__init__("rtx-thread", gdb.COMMAND_STACK,
                                         gdb.COMPLETE_NONE)
        self.u32_t = gdb.lookup_type("uint32_t")

    def invoke(self, arg, _from_tty):
        thread_id, cmd = arg.split(None, 1)
        thread_id = gdb.parse_and_eval(thread_id)

        pc, sp = find_thread(thread_id)
        if not pc:
            print("No such thread: ", thread_id)
            return

        try:
            pc = int(pc)
        except gdb.error:
            pc = int(str(pc).split(None, 1)[0], 16)

        save_frame = gdb.selected_frame()
        gdb.parse_and_eval('$save_sp = $sp')
        gdb.parse_and_eval('$save_pc = $pc')
        gdb.parse_and_eval('$sp = {}'.format(str(sp)))
        gdb.parse_and_eval('tbreak {}'.format(str(pc)))
        gdb.parse_and_eval('jump *{}'.format(str(pc)))

        try:
            gdb.execute(cmd)
        finally:
            gdb.parse_and_eval('$sp = $save_sp')
            gdb.parse_and_eval('tbreak $save_pc')
            gdb.parse_and_eval('jump $save_pc')
            save_frame.select()

RtxThread()


# -*- coding: utf-8 -*-
from PyQt5.QtCore import *
from PyQt5.QtWebKitWidgets import *
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
import resources
from widgets.buttons import ToolButton

class SearchBar(QLineEdit):
    searchClicked = pyqtSignal()

    def __init__(self, parent=None):
        QWidget.__init__(self, parent)
        self.searchButton = ToolButton('test', QIcon('images/search.png'), self)
        self.searchButton.setCursor(Qt.PointingHandCursor)
        self.searchButton.clicked.connect(self.searchClicked)
        self.setStyleSheet('QLineEdit{background-color: #FFF; color: #000; '
                           'border: 1px solid #D6D6D6; padding: 2px}')

    def resizeEvent(self, e):
        size = self.searchButton.sizeHint()
        self.searchButton.move(self.rect().right() - size.width() - 5,
                               (self.height() - size.height())/2)

class GMap(QWidget):
    locationSet = pyqtSignal(str, str, str)
    mapLoaded = pyqtSignal()

    def __init__(self, parent=None):
        QWidget.__init__(self, parent)
        self.webView = QWebView()
        self.webView.setUrl(QUrl('file:///home/lg/PycharmProjects/ivy-webchat-chat-advance/widgets/gmap.html'))
        self.api = GMapApi()
        self.mapLoadComplete = False
        self.attachWindowObject()
        self.webView.page().mainFrame().javaScriptWindowObjectCleared.connect(self.attachWindowObject)
        self.webView.page().mainFrame().loadFinished.connect(self.mapLoadOk)
        self.api.locationSet.connect(self.locationSet)

        self.searchInput = SearchBar()
        hLayout = QHBoxLayout()
        hLayout.addWidget(self.searchInput)
        self.searchInput.returnPressed.connect(self.searchPressed)

        mainLayout = QVBoxLayout()
        mainLayout.addLayout(hLayout)
        mainLayout.addWidget(self.webView)
        mainLayout.setContentsMargins(0, 0, 0, 0)
        mainLayout.setSpacing(0)
        self.setLayout(mainLayout)
        self.api.mapLoaded.connect(self.mapLoaded)
        self.searchInput.searchClicked.connect(self.searchPressed)
        self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)

    @pyqtSlot()
    def attachWindowObject(self):
        frame = self.webView.page().mainFrame()
        frame.addToJavaScriptWindowObject('api', self.api)

    @pyqtSlot(bool)
    def mapLoadOk(self, ok):
        if ok:
            self.mapLoadComplete = True

    @pyqtSlot()
    def searchPressed(self):
        if not self.mapLoadComplete:
            return
        text = self.searchInput.text()
        if len(text) < 1:
            return
        self.api.searchPressed.emit(text)

    def loadLocation(self, *args):
        if len(args) == 1 and isinstance(args[0], dict):
            self.api.loadLocation.emit(str(args[0]['lng']), str(args[0]['lat']))
        elif len(args) == 2:
            self.api.loadLocation.emit(args[0], args[1])

    def sizeHint(self):
        return QSize(800, 600)

    def minimumSizeHint(self):
        return QSize(0, 0)

class GMapApi(QObject):
    searchPressed = pyqtSignal(str)
    locationSet = pyqtSignal(str, str, str)
    loadLocation = pyqtSignal(str, str)
    mapLoaded = pyqtSignal()

    def __init__(self, parent=None):
        QObject.__init__(self, parent)

    @pyqtSlot(float, float, str)
    def setLocation(self, lat, lng, readable):
        self.locationSet.emit(str(round(lng, 6)), str(round(lat, 6)), readable)

    @pyqtSlot()
    def mapLoadOk(self):
        self.mapLoaded.emit()


from outta.parser import Parser
from outta.elements import SetIconName, SetTitle, SetTitleAndIconName
import pyte.control as ctrl
import pytest

OSC_TERMINATORS = set([ctrl.ST_C0, ctrl.ST_C1, ctrl.BEL])

@pytest.fixture(params=OSC_TERMINATORS)
def osc_terminator(request):
    return request.param

def test_set_icon_name(osc_terminator):
    icon_name = "icon name"
    text = ctrl.OSC_C1 + f"1;{icon_name}" + osc_terminator
    actual = list(Parser().feed(text))
    expected = [SetIconName((), {"name": icon_name}, text)]
    assert actual == expected

def test_set_title(osc_terminator):
    title = "title"
    text = ctrl.OSC_C1 + f"2;{title}" + osc_terminator
    actual = list(Parser().feed(text))
    expected = [SetTitle((), {"title": title}, text)]
    assert actual == expected

def test_set_icon_name_and_title(osc_terminator):
    name = "name"
    text = ctrl.OSC_C1 + f"0;{name}" + osc_terminator
    actual = list(Parser().feed(text))
    expected = [SetTitleAndIconName((), {"title": name, "name": name}, text)]
    assert actual == expected


from django.db.models import Count
from django.http import HttpResponse
from django.shortcuts import get_object_or_404
from django.views.generic import DetailView, ListView
from taggit.models import Tag

from blog.models import Post

from .forms import CommentForm

# Create your views here.

class PostListView(ListView):
    queryset = Post.published.all()
    context_object_name = "posts"
    paginate_by = 3

    def get(self, request, tag_slug=None):
        tag = None
        if tag_slug:
            tag = get_object_or_404(Tag, slug=tag_slug)
            self.queryset = self.queryset.filter(tags__in=[tag])
        return HttpResponse(self.queryset)

class PostDetailView(DetailView):
    def get(self, request, year, month, day, post):
        post = Post.published.get(
            slug=post,
            publish__year=year,
            publish__month=month,
            publish__day=day,
        )
        post_tags_ids = post.tags.values_list("id", flat=True)
        similar_posts = Post.published.filter(tags__in=post_tags_ids).exclude(
            id=post.id
        )
        similar_posts = similar_posts.annotate(same_tags=Count("tags")).order_by(
            "-same_tags", "-publish"
        )[:4]
        return HttpResponse({"post": post, "similar_posts": similar_posts})

class CommentCreateView(DetailView):
    def get(self, request, year, month, day, post):
        post = Post.published.get(
            slug=post,
            publish__year=year,
            publish__month=month,
            publish__day=day,
        )
        form = CommentForm()
        return HttpResponse(form)

    def post(self, request, year, month, day, post):
        post = Post.published.get(
            slug=post,
            publish__year=year,
            publish__month=month,
            publish__day=day,
        )
        form = CommentForm(request.POST)
        if form.is_valid():
            new_comment = form.save(commit=False)
            new_comment.post = post
            new_comment.user = request.user
            new_comment.save()
            return HttpResponse("Comment Added")
        else:
            return HttpResponse("Comment Not Added")


from db.run_sql import run_sql
from models.animal import Animal
import repositories.owner_repository as owner_repository
import repositories.vet_repository as vet_repository

def save(animal):
    sql = "INSERT INTO animals (name, type, dob, owner_id, vet_id) VALUES (%s, %s, %s, %s, %s) RETURNING *"
    values = [animal.name, animal.type, animal.dob, animal.owner.id, animal.vet.id]
    results = run_sql(sql, values)
    id = results[0]['id']
    animal.id = id
    return animal

def select_all():
    animals = []
    sql = "SELECT * FROM animals"
    results = run_sql(sql)
    for row in results:
        owner = owner_repository.select(row['owner_id'])
        vet = vet_repository.select(row['vet_id'])
        animal = Animal(row['name'], row['type'], row['dob'], owner, vet, row['id'])
        animals.append(animal)
    return animals

def select(id):
    animal = None
    sql = "SELECT * FROM animals WHERE id = %s"
    values = [id]
    result = run_sql(sql, values)[0]
    if result is not None:
        owner = owner_repository.select(result['owner_id'])
        vet = vet_repository.select(result['vet_id'])
        animal = Animal(result['name'], result['type'], result['dob'], owner, vet, result['id'])
    return animal

def select_id(id):
    animals = []
    sql = "SELECT * FROM animals WHERE vet_id = %s"
    values = [id]
    results = run_sql(sql, values)
    for row in results:
        owner = owner_repository.select(row['owner_id'])
        vet = vet_repository.select(row['vet_id'])
        animal = Animal(row['name'], row['type'], row['dob'], owner, vet, row['id'])
        animals.append(animal)
    return animals

def select_id_owner(id):
    animals = []
    sql = "SELECT * FROM animals WHERE owner_id = %s"
    values = [id]
    results = run_sql(sql, values)
    for row in results:
        owner = owner_repository.select(row['owner_id'])
        vet = vet_repository.select(row['vet_id'])
        animal = Animal(row['name'], row['type'], row['dob'], owner, vet, row['id'])
        animals.append(animal)
    return animals

def delete(id):
    sql = "DELETE FROM animals WHERE id = %s"
    values = [id]
    run_sql(sql, values)

def delete_all():
    sql = "DELETE FROM animals"
    run_sql(sql)

def update(animal):
    sql = "UPDATE animals SET (name, type, dob, owner_id, vet_id) = (%s, %s, %s, %s, %s) WHERE id = %s"
    values = [animal.name, animal.type, animal.dob, animal.owner.id, animal.vet.id, animal.id]
    run_sql(sql, values)


from flask import Flask, jsonify, request, render_template, url_for,redirect
import pymysql
import os
from PIL import Image
import glob
import base64
import requests as reqs
from io import BytesIO

app = Flask(__name__)
conn = pymysql.connect('localhost', 'cars99', 'admin99', 'car_detection')

@app.route("/", methods=['GET', 'POST'])
def index():
    if (request.method == 'POST'):
        some_json = request.get_json()
        return jsonify({'you send' : some_json['name']}), 201
    else:
        return jsonify({"name": "Dark"})

@app.route('/add/<int:num>',methods=['GET'])
def add(num):
    return jsonify({'result' : num + 100})

@app.route('/inserts', methods=['POST'])
def insert_data():
    if request.method == 'POST':
        data_json = request.get_json()
        with conn:
            speed = data_json['project_speed']
            color = data_json['project_colors']
            category = data_json['project_category']
            brand = data_json['project_brand']
            path = data_json['project_image']
            cur = conn.cursor()
            sql = "INSERT INTO project2 (project_speed, project_colors, project_category, project_brand, project_image) VALUES (%s ,%s ,%s, %s, %s)"
            val = [(speed, color, category, brand, path)]
            cur.executemany(sql, val)
            conn.commit()
            print(cur.rowcount, "record was inserted")
            # return render_template('insert.html')
            return jsonify(data_json), 200

@app.route('/moon/<string:data>', methods=['GET'])
def moon(data):
    return jsonify({'data' : data})

@app.route('/img', methods=['POST'])
def images():
    image64 = request.get_json()
    data = image64['image']
    name = image64['name']
    im = Image.open(BytesIO(base64.b64decode(data)))
    # im.save('img//accept.png', 'PNG')
    im.save('cross/img//'+name, 'PNG')
    return jsonify({'data' : image64}), 201

@app.route('/del', methods=['GET'])
def delete_():
    with conn:
        cursor= conn.cursor()
        cursor.execute("TRUNCATE TABLE project2")
        return jsonify({'info' : 'Drop table complete.'})

if __name__ == '__main__':
    app.run(host='206.189.46.191',port=443,debug=True)