from tkinter import ttk
from tkinter import *
from tktooltip import ToolTip
from validate_email import *

import os
import phonenumbers
import sqlite3

class Product:

    db_name = 'database.db'

    def __init__(self, WindowT):
        #Secondary Window Attributes
        self.windTwo = WindowT
        self.windTwo.title('Local Contacts')
        self.windTwo.geometry('800x600')
        self.windTwo.minsize(800, 600)
        self.windTwo.maxsize(1200, 800)
        self.windTwo.configure(bg='#1F1F1F')

        #Variables
        self.my_ctclist_old = []
        self.my_ctclist = []
        self.list_info = []
        self.list_id = []
        self.list_old_id = []
        self.resize_list = [0.12, 0.07, 0.68, 0.15, 15, 17]
        self.name = ''
        self.email = ''
        self.phone = ''
        self.request_name = ''
        self.select_id = ''
        self.title_wind = ''
        self.label_wind = ''
        self.label_btns_text = 'Create a new Contact'
        self.label_email_text = 'Create a new Contact'
        self.resize_val = [True, False]
        self.list_check = False

        """Labels"""

        #Labels Btns One
        self.label_btnf = Label(self.windTwo)
        self.label_btnf.configure(background='#1F1F1F', relief=SOLID, borderwidth=2)
        self.label_btnf.place(relwidth = 0.37, relheight = 0.09, relx = 0.0, rely = 0.0)

        #Label Btns Two
        self.label_btns = Label(self.windTwo, text=self.label_btns_text)
        self.label_btns.configure(background='#1F1F1F', relief=SOLID, borderwidth=2, fg='gray')
        self.label_btns.place(relwidth = 0.63, relheight = 0.09, relx = 0.37, rely = 0.0)

        #Label Stage
        self.label_stage = Label(self.windTwo)
        self.label_stage.configure(background='#1F1F1F', relief=SOLID, borderwidth=2)
        self.label_stage.place(relwidth = 0.63, relheight = 0.91, relx = 0.37, rely = 0.09)

        #Label Search Widgets
        self.label_search = Label(self.windTwo)
        self.label_search.configure(background='#1F1F1F', relief=SOLID, borderwidth=2, fg='gray')
        self.label_search.place(relwidth = 0.37, relheight = 0.91, relx = 0.0, rely = 0.09)

        #Name Label
        self.label_name = Label(self.label_stage, text='Full Name')
        self.label_name.configure(background='#1F1F1F', relief=SOLID, borderwidth=0, font=('Arial bold', 13), fg='gray')

        #Email Label
        self.label_email = Label(self.label_stage, text=self.label_email_text)
        self.label_email.configure(background='#1F1F1F', relief=SOLID, borderwidth=0, font=('Arial bold', 13), fg='gray')
        self.label_email.place(relwidth = 0.45, relheight = 0.06, relx = 0.30, rely = 0.43)

        #Phone Label
        self.label_phone = Label(self.label_stage, text='Number Phone')
        self.label_phone.configure(background='#1F1F1F', relief=SOLID, borderwidth=0, font=('Arial bold', 13), fg='gray')

        #Label list of contacts
        self.label_between = Label(self.label_search, text='List of Contacts')
        self.label_between.configure(background='#1F1F1F', relief=SOLID, borderwidth=0, font=('Arial bold', 13), fg='gray')
        self.label_between.place(relwidth = 0.99, relheight = 0.05, relx = 0, rely = 0.07)

        """Entrys"""

        #Name Entry
        self.CName = Entry(self.label_stage, exportselection=False, bg='#323232', fg='white',
        highlightbackground='gray', border=1, borderwidth=0)

        #Email Entry
        self.CEmail = Entry(self.label_stage, exportselection=False, bg='#323232', fg='white',
        highlightbackground='gray')

        #Phone Entry
        self.CPhone = Entry(self.label_stage, exportselection=False, bg='#323232', fg='white',
        highlightbackground='gray')

        """Buttons"""

        #Add Contacts
        self.img_add_btn = PhotoImage(file='img/img_add_btn.png')
        self.add_btn = Button(self.label_btnf, image=self.img_add_btn, command=self.add_buttonF)
        self.add_btn.configure(borderwidth=0, bg='#1F1F1F', highlightbackground='#1F1F1F')
        self.add_btn.place(relwidth = self.resize_list[0], relheight = self.resize_list[2], relx = 0.05, rely = self.resize_list[3])
        ToolTip(self.add_btn, 'Add Contact', delay=0.2,
        parent_kwargs={"bg": "#1F1F1F", "padx": 5, "pady": 5},
        fg="#ffffff", bg="#1F1F1F", padx=2, pady=2)

        #Delete All Contacts
        self.img_del_all_btn = PhotoImage(file='img/img_del_all_btn.png')
        self.del_all_btn = Button(self.label_btnf, image=self.img_del_all_btn, command=self.del_all_btnF)
        self.del_all_btn.configure(borderwidth=0, bg='#1F1F1F', highlightbackground='#1F1F1F')
        self.del_all_btn.place(relwidth = self.resize_list[0], relheight = self.resize_list[2], relx = 0.87, rely = self.resize_list[3])
        ToolTip(self.del_all_btn, 'Delete All Contacts', delay=0.2,
        parent_kwargs={"bg": "#1F1F1F", "padx": 5, "pady": 5},
        fg="#ffffff", bg="#1F1F1F", padx=2, pady=2)

        #Cancel Button
        self.cancel_btn = Button(self.label_btns, text='Cancel', command=self.cancel_buttonF)
        self.cancel_btn.configure(font=('Arial', 10, 'bold'),
        bg='gray', activebackground='#676767', activeforeground='white', fg='black', highlightbackground='#1F1F1F')

        #Done Button
        self.done_btn = Button(self.label_btns, text='Done', state='disabled')
        self.done_btn.configure(font=('Arial', 10, 'bold'), highlightbackground='#1F1F1F')

        #Edit Button
        self.img_edit_btn = PhotoImage(file='img/img_edit_btn.png')
        self.edit_btn = Button(self.label_btns, image=self.img_edit_btn, command=self.edit_buttonF)
        self.edit_btn.configure(borderwidth=0, bg='#1F1F1F', highlightbackground='#1F1F1F')
        ToolTip(self.edit_btn, 'Edit Contact', delay=0.2,
        parent_kwargs={"bg": "#1F1F1F", "padx": 5, "pady": 5},
        fg="#ffffff", bg="#1F1F1F", padx=2, pady=2)

        #Delete Button
        self.img_delete_btn = PhotoImage(file='img/img_delete_btn.png')
        self.delete_btn = Button(self.label_btns, image=self.img_delete_btn, command=self.delete_buttonF)
        self.delete_btn.configure(borderwidth=0, bg='#1F1F1F', highlightbackground='#1F1F1F')
        ToolTip(self.delete_btn, 'Delete Contact', delay=0.2,
        parent_kwargs={"bg": "#1F1F1F", "padx": 5, "pady": 5},
        fg="#ffffff", bg="#1F1F1F", padx=2, pady=2)

        #Search Bar
        self.searchbar_widget = Entry(self.label_search)
        self.searchbar_widget.configure(font=('Arial', self.resize_list[5]), bg='#323232', fg='gray',
        highlightbackground='gray', border=1, borderwidth=0)
        self.searchbar_widget.place(relwidth = 0.999, relheight = 0.07, relx = 0, rely = 0.0)

        #List of Contacts
        self.listctc_widget = Listbox(self.label_search, selectmode=EXTENDED , exportselection=False)
        self.listctc_widget.configure(bg='#1F1F1F', font=('Arial', self.resize_list[5]), fg='white',
        highlightbackground='gray', borderwidth=1)
        self.listctc_widget.place(relwidth = 0.997, relheight = 0.88, relx = 0, rely = 0.12)

        #Scrollbar Contacts
        self.listctc_scrollbar = Scrollbar(self.listctc_widget, orient='vertical')
        self.listctc_scrollbar.place(relwidth = 0.08, relheight = 0.996, relx = 0.92, rely = 0)
        self.listctc_widget.configure(yscrollcommand=self.listctc_scrollbar.set)
        self.listctc_scrollbar.configure(command=self.listctc_widget.yview, background='#444444', activebackground='gray')

        #Calling the functions
        self.db_exist()
        self.EvnTk()
        self.getctc_list()

    #Functions

    #Function to call the events
    def EvnTk(self):
        #Blocking the tab key
        self.windTwo.unbind_all("<<NextWindow>>")

        #Entry event
        self.control_widgets('insert_search_placeholder', 'search_placeholder')
        self.searchbar_widget.bind('<KeyRelease>', self.check_entryF)

        #Listbox event
        self.listctc_widget.bind('<<ListboxSelect>>', lambda m="": self.show_infoF(0, val_list=True))

        #Check zoomed
        self.windTwo.bind('<Enter>', self.ConfigSizeF)

    #Function to update the listbox
    def update_listboxF(self, data):
        self.listctc_widget.delete(0, END)

        for item in data:
            self.listctc_widget.insert(0, item)

    #Function to check the Entry
    def check_entryF(self, key):
        typed = self.searchbar_widget.get()

        if typed == '':
            data = self.my_ctclist

        else:
            data = []
            for item in self.my_ctclist:
                if typed.lower() in item.lower():
                    data.append(item)

        self.update_listboxF(data)

    #Function to check if the window is zoomed
    def ConfigSizeF(self, key):
        win_height = self.windTwo.winfo_height()
        win_width = self.windTwo.winfo_width()

        #Resize buttons if 800 width
        if win_width >= 800 and win_width <= 899:
            self.resize_list[0] = 0.12
            self.resize_list[1] = 0.07

            #update buttons
            self.control_widgets('update_buttons')

        #Resize buttons if 900 width
        if win_width >= 900 and win_width <= 999:
            self.resize_list[0] = 0.105
            self.resize_list[1] = 0.06

            #Update buttons
            self.control_widgets('update_buttons')

        #Resize buttons if 1000 width
        if win_width >= 1000 and win_width <= 1099:
            self.resize_list[0] = 0.097
            self.resize_list[1] = 0.055

            #Update buttons
            self.control_widgets('update_buttons')

        #Resize buttons if 1100 width
        if win_width >= 1100 and win_width <= 1199:
            self.resize_list[0] = 0.09
            self.resize_list[1] = 0.049

            #Update buttons
            self.control_widgets('update_buttons')

        #Resize buttons if 1200 width
        if win_width > 1199 and win_width == 1200:
            self.resize_list[0] = 0.08
            self.resize_list[1] = 0.046

            #Update buttons
            self.control_widgets('update_buttons')

        #Resize buttons if 600 height
        if win_height >= 600 and win_height <= 699:
            self.resize_list[2] = 0.68
            self.resize_list[3] = 0.15
            self.resize_list[4] = 15
            self.resize_list[5] = 17

            #Update buttons
            self.control_widgets('update_buttons', 'update_search', 'update_entrys')

        #Resize buttons if 700 height
        if win_height >= 700 and win_height <= 799:
            self.resize_list[2] = 0.58
            self.resize_list[3] = 0.16
            self.resize_list[4] = 17
            self.resize_list[5] = 19

            #Update buttons
            self.control_widgets('update_buttons', 'update_search', 'update_entrys')

        #Resize buttons if 800 height
        if win_height > 799 and win_height == 800:
            self.resize_list[2] = 0.51
            self.resize_list[3] = 0.18
            self.resize_list[4] = 19
            self.resize_list[5] = 21

            #Update buttons
            self.control_widgets('update_buttons', 'update_search', 'update_entrys')

        #Check if the window is zoomed
        if win_height > 800 or win_width > 1200:
            self.windTwo.attributes('-zoomed', False)
            self.windTwo.geometry('1200x800')

    #Function to mount the Add Stage
    def add_buttonF(self):
        #Control widgets
        self.control_widgets('del_search', 'del_entry', 'forget_entrys', 'forget_select_stage',
        'disable_search', 'forget_edit_stage', 'place_label_names')
        self.control_widgets('place_add_stage', 'place_entrys', 'reset_entrys',
        'insert_placeholder_entrys', 'entrys_placeholder','validate_add_stage', 'done_add_btn', 'reset_done_btn')

        #Label name
        self.label_btns_text = 'Adding a new Contact'
        self.control_widgets('refresh_label')

        #Change the focus
        self.windTwo.focus()

    #Function to mount the Select Stage
    def cancel_buttonF(self):
        #Control widgets
        self.control_widgets('del_search', 'active_search', 'del_entry', 'forget_add_stage',
        'forget_entrys', 'place_select_stage', 'reset_done_btn', 'forget_label_names', 'insert_search_placeholder')

        #Label name

        if self.list_check != False:
            self.label_btns_text = 'Select a Contact'
            self.label_email_text = 'Select a Contact'
            self.control_widgets('refresh_label')

        else:
            self.label_btns_text = 'Create a new Contact'
            self.label_email_text = 'Create a new Contact'
            self.control_widgets('refresh_label')

        #Change the focus
        self.windTwo.focus()

    #Function to mount the Edit Stage
    def edit_buttonF(self):
        #Control widgets
        self.control_widgets('del_search', 'disable_search', 'forget_edit_stage',
        'forget_select_stage', 'place_add_stage', 'reset_entrys', 'validate_edit_stage',
        'done_edit_btn', 'reset_done_btn', 'place_label_names', 'entrys_placeholder')

        #Between string
        self.convert_thingsF(self.CName.get())

        #Label name
        self.label_btns_text = 'Editing a Contact'
        self.control_widgets('refresh_label')

        #Change the focus
        self.windTwo.focus()

    #Function to mount the Delete Stage
    def delete_buttonF(self):
        #Title name and Label name
        self.title_wind = 'Delete Contact'
        self.label_wind = 'Want to delete this contact?'

        #Create the window and disable all buttons
        self.control_widgets('disable_all_btn', 'disable_search', 'del_search', 'create_wind', 'fill_wind', 'fill_delete')

        #Validation var
        self.email = self.CEmail.get()
        self.phone = self.CPhone.get()

        #Check if the window is closed with the X button
        self.wind.bind("<Destroy>", lambda m="": self.manage_windowsF(event="delete_wind"))

    #Function to mount the Delete All Stage
    def del_all_btnF(self):
        if self.my_ctclist != []:
            #Title name and Label name
            self.title_wind = 'Delete All Contacts'
            self.label_wind = 'Want to delete all the Contacts?'

            #Create the window and disable all buttons
            self.control_widgets('disable_all_btn', 'disable_search', 'del_search', 'create_wind', 'fill_wind', 'fill_delete_all')

            #Validation var
            self.email = self.CEmail.get()
            self.phone = self.CPhone.get()

            #Check if the window is closed with the X button
            self.wind.bind("<Destroy>", lambda m="": self.manage_windowsF(event="delete_all"))

        else:
            pass

    #Function to mount the Wrong stage
    def invalid_entryF(self):
        #Title Name
        self.title_wind = 'Invalid Data'

        #Create the window and disable all buttons
        self.control_widgets('disable_all_btn', 'create_wind')

        #Validate to create the window warn
        if self.phone == False and self.email == False:
            self.label_wind = 'Invalid Phone Number and Email Address'
            self.control_widgets('fill_wind', 'fill_invalid')

        elif self.phone == False:
            self.label_wind = 'Invalid Number Phone'
            self.control_widgets('fill_wind', 'fill_invalid')
            self.CPhone.focus()

        elif self.email == False:
            self.label_wind = 'Invalid Email Address'
            self.control_widgets('fill_wind', 'fill_invalid')
            self.CEmail.focus()

        #Check if the window is closed with the X button
        self.wind.bind("<Destroy>", lambda m="": self.manage_windowsF(event='invalid_wind'))

    #Function to Add Done Button
    def done_addF(self):
        #Extract the data and validate the data
        self.name = self.CName.get()
        self.email = self.validate_emailF(self.CEmail.get())
        self.phone = self.validate_phoneF(self.CPhone.get())

        #Validate the entrys
        if self.phone != False and self.email != False:
            #Control widgets
            self.control_widgets('active_search', 'del_search', 'forget_add_stage',
            'place_select_stage', 'place_edit_stage')

            #Sending the data to show the contact
            self.show_infoF(0, val_button=self.name)

            #Inserting the contact in the database
            self.add_contactF()

            #Change the focus
            self.windTwo.focus()

            #Set True list check
            self.list_check = True

        else:
            self.invalid_entryF()

    #Function to Edit Done Button
    def done_editF(self):
        #Extract the data and validate the data
        self.name = self.CName.get()
        self.email = self.validate_emailF(self.CEmail.get())
        self.phone = self.validate_phoneF(self.CPhone.get())

        #Validate the entrys
        if self.phone != False and self.email != False:
            #Control widgets
            self.control_widgets('active_search', 'del_search', 'forget_add_stage', 'place_select_stage', 'edit_active')

            #Sending the data to show the contact
            self.show_infoF(0, val_button=self.name)

            #Inserting the contact in the database
            self.edit_contactF()

            #Change the focus
            self.windTwo.focus()

        else:
            self.invalid_entryF()

    #Function to show the information of the selected contact
    def show_infoF(self, key, val_button=None, val_list=None):
        #Verifiy method
        if val_button != None:
            #Control widgets
            self.control_widgets('active_search', 'forget_add_stage', 'del_entry', 'place_edit_stage',
            'place_label_names', 'configure_entrys', 'insert_search_placeholder')

            #Adding the information
            self.control_widgets('insert_data_entrys',
            na=val_button,
            em=self.email,
            ph=self.phone)

            self.control_widgets('disable_entrys')

            #Change the focus and the name
            self.windTwo.focus()

            #Label name
            self.label_btns_text = 'Contact Information'
            self.control_widgets('refresh_label')

        elif val_list == True:
            #Request the data
            self.list_info = self.getctc_info(self.convert_thingsF())

            #Validation blank tuple
            if self.list_info != False:
                #Control widget
                self.control_widgets('place_entrys', 'configure_entrys',
                'place_edit_stage', 'del_entry', 'place_label_names',)

                #Adding the data
                self.control_widgets('insert_data_entrys',
                na=self.list_info[0],
                em=self.list_info[1],
                ph=self.list_info[2])

                self.control_widgets('disable_entrys')

                #Change the focus
                #self.windTwo.focus()

                #Label name
                self.label_btns_text = 'Contact Information'
                self.control_widgets('refresh_label')

            else:
                pass

    #Function to clear the placerholder when click
    def placeholderF(self, key, name=None, email=None, phone=None, search=None):
        name_second = self.CName.get()
        email_second = self.CEmail.get()
        phone_second = self.CPhone.get()
        search_second = self.searchbar_widget.get()

        #Validating
        if search == True:
            if search_second == 'Search Contact':
                self.searchbar_widget.delete(0, END)
                self.searchbar_widget.configure(fg='white')

        if name == True:
            if name_second == 'Full Name':
                self.CName.delete(0, END)

        if email == True:
            if email_second == 'E.g. aitsuki@hotmail.com' or email_second == 'No Email Added':
                self.CEmail.delete(0, END)

        if phone == True:
            if phone_second == 'E.g. +571234567890' or phone_second == 'No Number Phone Added':
                self.CPhone.delete(0, END)

    #Function to validate the state of the button and the entry "Name"
    def validate_stageF(self, key, add=None, edit=None):
        #Get the information
        name = self.CName.get()
        email = self.CEmail.get()
        phone = self.CPhone.get()

        #Validate the blank in add stage
        if add == True:
            while name != '' and name.isspace() == False:
                self.control_widgets('color_done_btn')
                break
            else:
                self.control_widgets('reset_done_btn')

        #Validate the blank in edit stage
        if edit == True:
            while phone or email != '':
                if name != '' and name.isspace() == False:
                    self.control_widgets('color_done_btn')
                else:
                    self.control_widgets('reset_done_btn')
                break
            else:
                self.control_widgets('reset_done_btn')

    #Function to validate the phone number entry
    def validate_phoneF(self, new_phone=''):

        if new_phone != '' and new_phone != 'E.g. +571234567890' and new_phone != 'No Number Phone Added':
            #Try because phonenumbers dont return false?
            try:
                phone_string = phonenumbers.parse(new_phone)
                phone = phonenumbers.is_possible_number(phone_string)

                #Validation always true
                if phone:
                    return new_phone

                else:
                    return False

            except Exception as ex:
                return False

        return 'No Number Phone Added'

    #Function to validate the email entry
    def validate_emailF(self, new_email=''):
        if new_email != '' and new_email != 'E.g. aitsuki@hotmail.com' and new_email != 'No Email Added':
            valid_email = validate_email(new_email)

            if valid_email:
                return new_email

            else:
                return False

        return 'No Email Added'

    #Function to add things between two '', get the anchor from lst and the id
    def convert_thingsF(self, name=None):

        if name != None:
            #Inserting the old name between 'name' with aitsuki help
            aitsuki = "'"
            nakuru = "'"
            self.request_name = aitsuki + name + nakuru
            return self.request_name

        else:
            #Convert the lst into a string with aitsuki help
            lst = self.listctc_widget.get(ANCHOR)
            lst_join = "".join(lst)
            nakuru = "'"
            aitsuki = "'"
            self.request_name = aitsuki + lst_join + nakuru

            #Select one id from que list
            tuple_id = self.listctc_widget.curselection()
            if tuple_id != ():
                id = tuple_id[0]
                self.select_id = self.list_id[id]
                return self.request_name, self.select_id
            else:
                return False

    #Function to destroy windows
    def manage_windowsF(self, event=None):
        if event == 'delete_wind':
            #List contact reload
            self.getctc_list()

            self.show_infoF(0, val_button=self.CName.get())

            #Control widget
            self.control_widgets('active_all_btn', 'active_search')

        if event == 'invalid_wind':
            self.control_widgets('active_all_btn', 'active_search')

        if event == 'delete_all':
            self.control_widgets('active_all_btn', 'active_search')

    #Function to control the widgets
    def control_widgets(self, *args, na=None, em=None, ph=None):
        for value in args:

            """Places Stages"""

            #Select Stage
            if value == 'place_select_stage':
                #Add the buttons "Add", "Settings" and "Select"
                self.add_btn.place(relwidth = self.resize_list[0], relheight = self.resize_list[2], relx = 0.05, rely = self.resize_list[3])
                self.del_all_btn.place(relwidth = self.resize_list[0], relheight = self.resize_list[2], relx = 0.87, rely = self.resize_list[3])
                self.resize_val = [True, False]

            #Add Stage
            if value == 'place_add_stage':
                #Add the buttons "Cancel" and "Done"
                self.cancel_btn.place(relwidth = 0.12, relheight = 0.68, relx = 0.05, rely = 0.15)
                self.done_btn.place(relwidth = 0.12, relheight = 0.68, relx = 0.87, rely = 0.15)
                self.resize_val = [False, False]

            #Edit Stage
            if value == 'place_edit_stage':
                #Adding the button to edit
                self.delete_btn.place(relwidth = self.resize_list[1], relheight = self.resize_list[2], relx = 0.87, rely = self.resize_list[3])
                self.edit_btn.place(relwidth = self.resize_list[1], relheight = self.resize_list[2], relx = 0.05, rely = self.resize_list[3])
                self.resize_val = [True, True]

            """Forget Stages"""

            #Select Stage
            if value == 'forget_select_stage':
                #Remove the buttons in the main
                self.add_btn.place_forget()
                self.del_all_btn.place_forget()

            #Add Stage
            if value == 'forget_add_stage':
                #Remove the buttons in the add stage or edit
                self.cancel_btn.place_forget()
                self.done_btn.place_forget()

            #Edit Stage
            if value == 'forget_edit_stage':
                #Removing the edit button
                self.edit_btn.place_forget()
                self.delete_btn.place_forget()

            """Buttons"""

            #Done Button Command Add Stage
            if value == 'done_add_btn':
                #Configure the button to call the function button done in add stage
                self.done_btn.configure(command=self.done_addF)

            #Done Button Command Edit Stage
            if value == 'done_edit_btn':
                #Configure the button to call the function button edit in edit stage
                self.done_btn.configure(command=self.done_editF)

            #Done Button Disable
            if value == 'reset_done_btn':
                self.done_btn.configure(state='disabled', bg='#161616', disabledforeground='white')

            #Done Button Colors
            if value == 'color_done_btn':
                #configuration while mouse is over the button
                self.done_btn.configure(state='normal', bg='#1924FF', fg='black')

                #configuration while mouse is not over the button
                self.done_btn.configure(activebackground='#363FFF', activeforeground='white')

            #Disable All Buttons
            if value == 'disable_all_btn':
                self.delete_btn.configure(state='disabled')
                self.edit_btn.configure(state='disabled')
                self.add_btn.configure(state='disabled')
                self.del_all_btn.configure(state='disabled')
                self.done_btn.configure(state='disabled')
                self.cancel_btn.configure(state='disabled')

            #Active All Buttons
            if value == 'active_all_btn':
                self.delete_btn.configure(state='normal')
                self.edit_btn.configure(state='normal')
                self.add_btn.configure(state='normal')
                self.del_all_btn.configure(state='normal')
                self.done_btn.configure(state='normal')
                self.cancel_btn.configure(state='normal')

            #Update buttons
            if value == 'update_buttons' and self.resize_val[0] == True:
                #Update Add and Del All butons
                self.add_btn.place(relwidth = self.resize_list[0], relheight = self.resize_list[2], relx = 0.05, rely = self.resize_list[3])
                self.del_all_btn.place(relwidth = self.resize_list[0], relheight = self.resize_list[2], relx = 0.87, rely = self.resize_list[3])

                #Update Edit and Delete buttons
                if self.resize_val[1] == True:
                    self.delete_btn.place(relwidth = self.resize_list[1], relheight = self.resize_list[2], relx = 0.87, rely = self.resize_list[3])
                    self.edit_btn.place(relwidth = self.resize_list[1], relheight = self.resize_list[2], relx = 0.05, rely = self.resize_list[3])

            """Search"""

            #Active Search
            if value == 'active_search':
                #Active the search
                self.searchbar_widget.configure(state='normal')
                self.listctc_widget.configure(state='normal')

            #Del Search
            if value == 'del_search':
                #Delete search bar text
                self.searchbar_widget.configure(state='normal')
                self.searchbar_widget.delete(0, END)
                self.searchbar_widget.configure(state='readonly')

            #Disable Search
            if value == 'disable_search':
                #Disable the search
                self.searchbar_widget.configure(state='readonly', readonlybackground='#1F1F1F')
                self.listctc_widget.configure(state='disabled')

            #Search Placeholder
            if value == 'insert_search_placeholder':
                #Delete search bar text
                self.searchbar_widget.delete(0, END)

                self.searchbar_widget.configure(fg='gray')

                #Insert placeholder
                self.searchbar_widget.insert(0, 'Search Contact')

                #List contact reload
                self.getctc_list()

            #Update Search Entry and Listbox
            if value == 'update_search':
                self.searchbar_widget.configure(font=('Arial', self.resize_list[5]))
                self.listctc_widget.configure(font=('Arial', self.resize_list[5]))

            """Labels"""

            #Refresh label stage name
            if value == 'refresh_label':
                self.label_btns.configure(text=self.label_btns_text)
                self.label_email.configure(text=self.label_email_text)

            #Place label names entrys
            if value == 'place_label_names':
                self.label_email_text = 'Email'
                self.label_email.configure(text=self.label_email_text)
                self.label_name.place(relwidth = 0.40, relheight = 0.05, relx = 0.30, rely = 0.19)
                self.label_email.place(relwidth = 0.45, relheight = 0.05, relx = 0.27, rely = 0.41)
                self.label_phone.place(relwidth = 0.40, relheight = 0.05, relx = 0.30, rely = 0.63)

            if value == 'forget_label_names':
                self.label_email_text = 'Select a Contact'
                self.label_email.configure(text=self.label_email_text)
                self.label_name.place_forget()
                self.label_phone.place_forget()

            """Entrys"""

            #Place Entrys
            if value == 'place_entrys':
                #Add the entrys
                self.CName.place(relwidth = 0.70, relheight = 0.07, relx = 0.16, rely = 0.24)
                self.CEmail.place(relwidth = 0.70, relheight = 0.07, relx = 0.16, rely = 0.46)
                self.CPhone.place(relwidth = 0.70, relheight = 0.07, relx = 0.16, rely = 0.68)

            #Configure Entrys
            if value == 'configure_entrys':
                #Configure entrys
                self.CName.configure(state='normal', font=('Arial', self.resize_list[4]), fg='black')
                self.CEmail.configure(state='normal', font=('Arial', self.resize_list[4]), fg='black')
                self.CPhone.configure(state='normal', font=('Arial', self.resize_list[4]), fg='black')

            #Reset Entrys
            if value == 'reset_entrys':
                #Reset entrys
                self.CName.configure(state='normal', font=('Arial', self.resize_list[4]), fg='white')
                self.CEmail.configure(state='normal', font=('Arial', self.resize_list[4]), fg='white')
                self.CPhone.configure(state='normal', font=('Arial', self.resize_list[4]), fg='white')

            #Disable Entrys
            if value == 'disable_entrys':
                #Disabled entrys
                self.CName.configure(state='readonly')
                self.CEmail.configure(state='readonly')
                self.CPhone.configure(state='readonly')

            #Insert Data Entrys
            if value == 'insert_data_entrys':
                #Delete the entrys
                self.CName.delete(0, END)
                self.CEmail.delete(0, END)
                self.CPhone.delete(0, END)

                #Insert the data in the entry
                self.CName.insert(0, na)
                self.CEmail.insert(0, em)
                self.CPhone.insert(0, ph)

            #Del Entrys
            if value == 'del_entry':
                #Delete the entrys
                self.CName.configure(state='normal')
                self.CEmail.configure(state='normal')
                self.CPhone.configure(state='normal')
                self.CName.delete(0, END)
                self.CEmail.delete(0, END)
                self.CPhone.delete(0, END)

            #Insert placeholder
            if value == 'insert_placeholder_entrys':
                #Delete the entrys
                self.CName.delete(0, END)
                self.CEmail.delete(0, END)
                self.CPhone.delete(0, END)

                #Insert in the entry
                self.CName.insert(0, 'Full Name')
                self.CEmail.insert(0, 'E.g. aitsuki@hotmail.com')
                self.CPhone.insert(0, 'E.g. +571234567890')

            #Forget Entrys
            if value == 'forget_entrys':
                #Remove the entrys
                self.CName.place_forget()
                self.CEmail.place_forget()
                self.CPhone.place_forget()

            #Update Entrys
            if value == 'update_entrys':
                self.CName.configure(font=('Arial', self.resize_list[4]))
                self.CEmail.configure(font=('Arial', self.resize_list[4]))
                self.CPhone.configure(font=('Arial', self.resize_list[4]))

            """Validations"""

            #Placeholder Search Validation
            if value == 'search_placeholder':
                self.searchbar_widget.bind("<FocusIn>", lambda m="": self.placeholderF(0, search=True))

            #Placeholder Validation
            if value == 'entrys_placeholder':
                #Deleting the placeholder
                self.CName.bind("<FocusIn>", lambda m="": self.placeholderF(0, name=True))
                self.CEmail.bind("<FocusIn>", lambda m="": self.placeholderF(0, email=True))
                self.CPhone.bind("<FocusIn>", lambda m="": self.placeholderF(0, phone=True))

            #Done Button Add Stage Validation
            if value == 'validate_add_stage':
                #Validating blank
                self.CName.bind("<KeyRelease>", lambda m="": self.validate_stageF(0, add=True))

            #Done Button Edit Stage Validation
            if value == 'validate_edit_stage':
                #Validating edit stage
                self.CName.bind("<KeyRelease>", lambda m="": self.validate_stageF(0, edit=True))
                self.CEmail.bind("<KeyRelease>", lambda m="": self.validate_stageF(0, edit=True))
                self.CPhone.bind("<KeyRelease>", lambda m="": self.validate_stageF(0, edit=True))

            """Window"""

            #Create Window
            if value == 'create_wind':
                self.wind = Toplevel()
                self.wind.title(self.title_wind)
                self.wind.geometry("500x200+700+700")
                self.wind.resizable(False, False)
                self.wind.configure(bg='#1F1F1F')

            #Fill Window
            if value == 'fill_wind':
                #Label
                confirm_lbl = Label(self.wind, text=self.label_wind, width=40, height=2)
                confirm_lbl.configure(background='#1F1F1F', relief=SOLID, borderwidth=0, fg='white', font=('Arial bold', 13))
                confirm_lbl.place(x=250, y=25, anchor=CENTER)

                #Yes Button
                self.img_yes_btn = PhotoImage(file='img/img_yes_btn.png')

                for value in args:
                    #Fill Invalid Window
                    if value == 'fill_invalid':
                        #Ok Button
                        confirm_btnF = Button(self.wind, image=self.img_yes_btn)
                        confirm_btnF.configure(command=lambda m="": self.control_widgets('active_all_btn', 'destroy_wind'))
                        confirm_btnF.configure(height=30, width=30, borderwidth=0, bg='#1F1F1F', highlightbackground='#1F1F1F')
                        confirm_btnF.place(x=250, y=120, anchor=CENTER)

                    #Fill Delete Window
                    if value == 'fill_delete':
                        #Yes Button
                        confirm_btnF = Button(self.wind, image=self.img_yes_btn)
                        confirm_btnF.configure(command=lambda m="": self.delete_contactF(Yes=True))
                        confirm_btnF.configure(height=30, width=30, borderwidth=0, bg='#1F1F1F', highlightbackground='#1F1F1F')
                        confirm_btnF.place(x=150, y=110, anchor=CENTER)

                        #No Button
                        self.img_no_btn = PhotoImage(file='img/img_no_btn.png')
                        confirm_btnS = Button(self.wind, image=self.img_no_btn)
                        confirm_btnS.configure(command=lambda m="": self.delete_contactF(No=True))
                        confirm_btnS.configure(height=30, width=30, borderwidth=0, bg='#1F1F1F', highlightbackground='#1F1F1F')
                        confirm_btnS.place(x=350, y=110, anchor=CENTER)

                    #Fill Delete All Contacts Window
                    if value == 'fill_delete_all':
                        #Yes Button
                        confirm_btnF = Button(self.wind, image=self.img_yes_btn)
                        confirm_btnF.configure(command=lambda m="": self.del_all_contactF(Yes=True))
                        confirm_btnF.configure(height=30, width=30, borderwidth=0, bg='#1F1F1F', highlightbackground='#1F1F1F')
                        confirm_btnF.place(x=150, y=110, anchor=CENTER)

                        #No Button
                        self.img_no_btn = PhotoImage(file='img/img_no_btn.png')
                        confirm_btnS = Button(self.wind, image=self.img_no_btn)
                        confirm_btnS.configure(command=lambda m="": self.del_all_contactF(No=True))
                        confirm_btnS.configure(height=30, width=30, borderwidth=0, bg='#1F1F1F', highlightbackground='#1F1F1F')
                        confirm_btnS.place(x=350, y=110, anchor=CENTER)

            #Destroy Window
            if value == 'destroy_wind':
                self.wind.destroy()

    #SQLITE FUNCTIONS

    #Function to connect the basedata
    def run_query(self, query, parameters = ()):
        with sqlite3.connect(self.db_name) as conn:
            cursor = conn.cursor()
            result = cursor.execute(query, parameters)
            conn.commit()
        return result

    #Function to create a new database if no exist
    def db_exist(self):
        query = """CREATE TABLE IF NOT EXISTS "contacts" (
        "id"	INTEGER NOT NULL,
        "name"	TEXT NOT NULL,
        "email"	TEXT NOT NULL,
        "phone"	TEXT NOT NULL,
        PRIMARY KEY("id" AUTOINCREMENT)
        );"""
        self.run_query(query)

    #Function to get the contacts from database
    def getctc_list(self):
        #Quering the data
        query = 'SELECT name, id FROM contacts ORDER BY name DESC'
        db_rows = self.run_query(query)

        #Reset the list
        self.my_ctclist = []
        self.my_ctclist_old = []

        #Filling the list
        for rows in db_rows:
            self.my_ctclist_old = ''.join(rows[0])
            self.list_old_id = str(rows[1])
            self.list_id.insert(0, self.list_old_id)
            self.my_ctclist.append(self.my_ctclist_old)
        self.update_listboxF(self.my_ctclist)

    #Function to get the last id from the database
    def get_last_id(self):
        #Quering the data
        query = 'SELECT MAX(id) AS LastID FROM contacts'
        db_rows = self.run_query(query)

        #Save the id
        for rows in db_rows:
            self.select_id = ''.join(str(rows[0]))

    #Function to get the data from database with name
    def getctc_info(self, request = []):
        print(request)
        #Validation blank tuple
        if request != False:
            try:
                #Quering the data
                query = f"SELECT name, email, phone FROM contacts WHERE id LIKE {request[1]} AND name LIKE {request[0]}"
                db_rows = self.run_query(query)
                for rows in db_rows:
                    name = rows[0]
                    email = rows[1]
                    phone = rows[2]
                return name, email, phone

            except UnboundLocalError as ex:
                return False
        else:
            return False

    #Function to insert contact in the database
    def add_contactF(self):
        #Queriny the data
        query = 'INSERT INTO contacts VALUES(NULL, ?, ?, ?)'
        parameters = (self.name, self.email, self.phone)
        self.run_query(query, parameters)

        #Get the last id
        self.get_last_id()

        #Update the contact list
        self.getctc_list()

    #Function to edit the contact in database
    def edit_contactF(self):
        #Quering the data
        query = f'UPDATE contacts SET name = ?, email = ?, phone = ? WHERE name = {self.request_name} and id = {self.select_id}'
        parameters = (self.name, self.email, self.phone)
        self.run_query(query, parameters)

        #Update the contact list
        self.getctc_list()

    #Function to delete the contact in the database
    def delete_contactF(self, Yes=None, No=None):

        if Yes == True:
            #Quering the data
            query = f'DELETE FROM contacts WHERE name = {self.convert_thingsF(name=self.CName.get())} AND id = {self.select_id}'
            self.run_query(query)

            #List contact reload
            self.getctc_list()

            #Control widget
            self.control_widgets('destroy_wind', 'forget_entrys', 'place_select_stage', 'forget_add_stage',
            'forget_edit_stage', 'reset_done_btn', 'active_all_btn', 'forget_label_names', 'active_search', 'insert_search_placeholder')

            #Label name
            self.label_btns_text = 'Create a new Contact'
            self.label_email_text = 'Create a new Contact'
            self.control_widgets('refresh_label')

            #Set false list check
            self.list_check = False

        if No == True:
            #List contact reload
            self.getctc_list()

            self.show_infoF(0, val_button=self.CName.get())

            #Control widget
            self.control_widgets('destroy_wind', 'active_all_btn', 'active_search', 'insert_search_placeholder')

    #Function to delete all the contacts, delete the archive database.db
    def del_all_contactF(self, No=None, Yes=None):
        if Yes == True:
            #Delete the database
            path = os.path.join(self.db_name)
            os.remove(path)

            #Create a new database
            self.db_exist()

            #List contact reload
            self.getctc_list()

            #Control widget
            self.control_widgets('destroy_wind', 'forget_entrys', 'place_select_stage', 'forget_add_stage',
            'forget_edit_stage', 'reset_done_btn', 'active_all_btn', 'forget_label_names', 'active_search', 'insert_search_placeholder')

            #Label name
            self.label_btns_text = 'Create a new Contact'
            self.label_email_text = 'Create a new Contact'
            self.control_widgets('refresh_label')

            #Set False list check
            self.list_check = False

        if No == True:
            #List contact reload
            self.getctc_list()

            self.show_infoF(0, val_button=self.CName.get())

            #Control widget
            self.control_widgets('destroy_wind', 'active_all_btn', 'active_search', 'insert_search_placeholder')

if __name__ == '__main__':
    WindowT = Tk()
    application = Product(WindowT)
    WindowT.mainloop()


# Bot Main File
import os

# Importing .env infos
from dotenv import load_dotenv
load_dotenv()

# Discord
import discord
client = discord.Client()
## commands
from .commands import (admin,user)

# Challonge Library
import challonge
challonge.set_credentials(os.getenv("CHALLONGE_NICKNAME"), os.getenv("CHALLONGE_TOKEN"))

# Importing database settings
import json
from .database import database
from .database import structure
connection = database.create_connection("./bot/database/database.sqlite")

@client.event
async def on_ready():
	"""
	Sets activity to playing MtG
	Login success informative log
	"""
	game = discord.Game("Magic: the Gathering")
	await client.change_presence(status=discord.Status.online, activity=game)
	print(f"Logged in as {client.user}")
	# Checking tables existence
	if connection is not None:
		database.create_table(connection, structure.sql_create_tournaments_table)
		query = database.execute_request(connection, "SELECT * FROM tournaments")
		if query == []:
			database.create_tournament(connection, structure.sample_tournament)
	else:
		print("Error! cannot create the database connection")

@client.event
async def on_message(message):
	"""
	Main message loop

	Args:
	message (object): a discord.Message
	"""
	# Checking if the bot is sending a message
	if message.author == client.user:
		return

	# Checking if the message is calling the bot
	if message.content.lower().startswith("bot "):
		content = message.content[4:] # ^bot $
		print(f"Received: {content}")

		# Admin Commands
		if content.lower().startswith("admin "):
			await admin.admin_message(message,connection)

		# User Commands
		else:
			await user.user_message(message,connection)

# Starting the bot
def main():
	client.run(os.getenv("DISCORD_TOKEN"))


# encoding: utf-8
from utility import *
import numpy as np
from scipy import stats
from math import *

short_len,long_len=128,128
Ts=20e6

#从stf和ltf里取统计特征
def stat(file_name,phy_frames,n=64*4):
    file_name="after_sync_short"+file_name
    for phy_frame in phy_frames:
        index=phy_frame.modules_index['after_sync_short']
        #鍑洪敊鐨勮瘽灏辫璁鸿瘉涓€涓媠ync_long鍜宖ft涔嬪悗鍑烘潵鐨勯噰鏍蜂釜鏁颁竴涓嶄竴鏍蜂簡
        complex_data=r_complexsamples(file_name,index,n)
        if len(complex_data)==0:
            print('WTF_stats')
            print('read from '+file_name+' index: '+str(index)+' out of range')
            exit()
        print('fuck')

        complex_data_t=[]

        for i,data in enumerate(complex_data):
            data_in_tdom=(data*e**complex(0,2*pi*phy_frame.nomfreq/Ts)).real
            #print(data_in_tdom)
            complex_data_t.append(data_in_tdom)

        print(complex_data_t)
        #complex_data_t=complex_data

        win_size_short=16
        win_size_long=64
        win_num_short=int(short_len/win_size_short)
        win_num_long=int(long_len/win_size_long)
        f_stats=[]

        #sync_short
        for i in range(win_num_short):
            temp=complex_data_t[i*16:(i+1)*16]
            append_awin(f_stats,temp)

        #sync_long
        for i in range(win_num_long):
            temp=complex_data_t[i*64:(i+1)*64]
            append_awin(f_stats,temp)

        phy_frame.feature['stats']=f_stats
    return phy_frames

def append_awin(f_stats,temp):
    f_stats.append(np.var(temp))
    f_stats.append(stats.skew(np.array(temp)))
    f_stats.append(stats.kurtosis(np.array(temp)))
    f_stats.append(np.median(temp))


from urllib.parse import urlparse
import mistletoe
from sqlalchemy import func
from bs4 import BeautifulSoup
import pyotp
import qrcode
import io
import gevent

from ruqqus.helpers.wrappers import *
from ruqqus.helpers.base36 import *
from ruqqus.helpers.sanitize import *
from ruqqus.helpers.filters import *
from ruqqus.helpers.embed import *
from ruqqus.helpers.markdown import *
from ruqqus.helpers.get import *
from ruqqus.classes import *
from ruqqus.mail import *
from flask import *
from ruqqus.__main__ import app, cache, limiter, db_session

BAN_REASONS = ['',
               "URL shorteners are not permitted."
               ]

@app.route("/2faqr/<secret>", methods=["GET"])
@auth_required
def mfa_qr(secret, v):
    x = pyotp.TOTP(secret)
    qr = qrcode.QRCode(
        error_correction=qrcode.constants.ERROR_CORRECT_L
    )
    qr.add_data(x.provisioning_uri(v.username, issuer_name=app.config["SITE_NAME"]))
    img = qr.make_image(fill_color="#"+app.config["SITE_COLOR"], back_color="white")

    mem = io.BytesIO()

    img.save(mem, format="PNG")
    mem.seek(0, 0)
    return send_file(mem, mimetype="image/png", as_attachment=False)

@app.route("/api/is_available/<name>", methods=["GET"])
@app.route("/api/v1/is_available/<name>", methods=["GET"])
@auth_desired
@api("read")
def api_is_available(name, v):

    name=name.lstrip().rstrip()

    if len(name)<3 or len(name)>25:
        return jsonify({name:False})

    x=get_user(name)

    if x:
        return jsonify({name: False})
    else:
        return jsonify({name: True})

@app.route("/uid/<uid>", methods=["GET"])
def user_uid(uid):
    return redirect(get_account(uid).permalink)

# Allow Id of user to be queryied, and then redirect the bot to the
# actual user api endpoint.
# So they get the data and then there will be no need to reinvent
# the wheel.
@app.route("/api/v1/uid/<uid>", methods=["GET"])
@auth_desired
@api("read")
def user_by_uid(uid, v=None):
    user=get_account(uid)

    return redirect(f'/api/v1/user/{user.username}/info')

@app.route("/u/<username>", methods=["GET"])
def redditor_moment_redirect(username):

    return redirect(f"/@{username}")

@app.route("/@<username>", methods=["GET"])
@app.route("/api/v1/user/<username>/listing", methods=["GET"])
@app.get("/api/v2/users/<username>/submissions")
@auth_desired
@api("read")
def u_username(username, v=None):
    """
Get posts created by another user.

URL path parameters:
* `username` - The user whose posts are being fetched.

Optional query parameters:
* `sort` - One of `hot`, `new`, `old`, `top`, `activity`, or `disputed`. Default `new`.
* `t` - One of `day`, `week`, `month`, `year`, `all`. Default `all`.
* `page` - Page of results to return. Default `1`.
"""

    # username is unique so at most this returns one result. Otherwise 404

    # case insensitive search

    u = get_user(username, v=v)

    # check for wrong cases

    #if username != u.username:
        #return redirect(request.path.replace(username, u.username))

    if u.reserved:
        return {'html': lambda: render_template("userpage_reserved.html",
                                                u=u,
                                                v=v),
                'api': lambda: {"error": f"That username is reserved for: {u.reserved}"}
                }

    if u.is_suspended and not (v and (v.admin_level >=3 or v.id==u.id)):
        return {'html': lambda: render_template("userpage_banned.html",
                                                u=u,
                                                v=v),
                'api': lambda: {"error": "That user is banned"}
                }

    if u.is_deleted and not (v and v.admin_level >= 3):
        return {'html': lambda: render_template("userpage_deleted.html",
                                                u=u,
                                                v=v),
                'api': lambda: {"error": "That user deactivated their account."}
                }

    if u.is_private and not (v and (v.admin_level >=3 or v.id==u.id)):
        return {'html': lambda: render_template("userpage_private.html",
                                                u=u,
                                                v=v),
                'api': lambda: {"error": "That userpage is private"}
                }

    if u.is_blocking and not (v and v.admin_level >= 3):
        return {'html': lambda: render_template("userpage_blocking.html",
                                                u=u,
                                                v=v),
                'api': lambda: {"error": f"You are blocking @{u.username}."}
                }

    if u.is_blocked and not (v and v.admin_level >= 3):
        return {'html': lambda: render_template("userpage_blocked.html",
                                                u=u,
                                                v=v),
                'api': lambda: {"error": "This person is blocking you."}
                }

    sort = request.args.get("sort", "new")
    t = request.args.get("t", "all")
    page = int(request.args.get("page", "1"))
    page = max(page, 1)

    ids = u.userpagelisting(v=v, page=page, sort=sort, t=t)

    # we got 26 items just to see if a next page exists
    next_exists = (len(ids) == 26)
    ids = ids[0:25]

    listing = get_posts(ids, v=v)

    return {'html': lambda: render_template("userpage.html",
                                            u=u,
                                            v=v,
                                            listing=listing,
                                            page=page,
                                            next_exists=next_exists,
                                            is_following=(v and u.has_follower(v))),
            'api': lambda: jsonify({"data": [x.json for x in listing]})
            }

@app.route("/@<username>/comments", methods=["GET"])
@app.route("/api/v1/user/<username>/comments", methods=["GET"])
@app.get("/api/v2/users/<username>/comments")
@auth_desired
@api("read")
def u_username_comments(username, v=None):
    """
Get comments created by another user.

URL path parameters:
* `username` - The user whose comments are being fetched.

Optional query parameters:
* `sort` - One of `hot`, `new`, `old`, `top`, or `disputed`. Default `new`.
* `t` - One of `day`, `week`, `month`, `year`, `all`. Default `all`.
* `page` - Page of results to return. Default `1`.
"""

    # username is unique so at most this returns one result. Otherwise 404

    # case insensitive search

    user = get_user(username, v=v)

    # check for wrong cases

    if username != user.username:
        return redirect(f'{user.url}/comments')

    u = user

    if u.reserved:
        return {'html': lambda: render_template("userpage_reserved.html",
                                                u=u,
                                                v=v),
                'api': lambda: {"error": f"That username is reserved for: {u.reserved}"}
                }

    if u.is_suspended and not (v and (v.admin_level >=3 or v.id==u.id)):
        return {'html': lambda: render_template("userpage_banned.html",
                                                u=u,
                                                v=v),
                'api': lambda: {"error": "That user is banned"}
                }

    if u.is_deleted and not (v and v.admin_level >= 3):
        return {'html': lambda: render_template("userpage_deleted.html",
                                                u=u,
                                                v=v),
                'api': lambda: {"error": "That user deactivated their account."}
                }

    if u.is_private and not (v and (v.admin_level >=3 or v.id==u.id)):
        return {'html': lambda: render_template("userpage_private.html",
                                                u=u,
                                                v=v),
                'api': lambda: {"error": "That userpage is private"}
                }

    if u.is_blocking and not (v and v.admin_level >= 3):
        return {'html': lambda: render_template("userpage_blocking.html",
                                                u=u,
                                                v=v),
                'api': lambda: {"error": f"You are blocking @{u.username}."}
                }

    if u.is_blocked and not (v and v.admin_level >= 3):
        return {'html': lambda: render_template("userpage_blocked.html",
                                                u=u,
                                                v=v),
                'api': lambda: {"error": "This person is blocking you."}
                }

    page = int(request.args.get("page", "1"))

    ids = user.commentlisting(
        v=v,
        page=page,
        sort=request.args.get("sort","new"),
        t=request.args.get("t","all")
        )

    # we got 26 items just to see if a next page exists
    next_exists = (len(ids) == 26)
    ids = ids[0:25]

    listing = get_comments(ids, v=v)

    is_following = (v and user.has_follower(v))

    return {"html": lambda: render_template("userpage_comments.html",
                                            u=user,
                                            v=v,
                                            listing=listing,
                                            page=page,
                                            next_exists=next_exists,
                                            is_following=is_following,
                                            standalone=True),
            "api": lambda: jsonify({"data": [c.json for c in listing]})
            }

@app.route("/api/v1/user/<username>/info", methods=["GET"])
@app.get("/api/v2/users/<username>")
@auth_desired
@api("read")
def u_username_info(username, v=None):
    """
Get information about another user.

URL path parameters:
* `username` - A user's name.
"""

    user=get_user(username, v=v)

    if user.is_blocking:
        return jsonify({"error": "You're blocking this user."}), 401
    elif user.is_blocked:
        return jsonify({"error": "This user is blocking you."}), 403

    return jsonify(user.json)

@app.route("/api/follow/<username>", methods=["POST"])
@app.post("/api/v2/users/<username>/follow")
@auth_required
def follow_user(username, v):
    """
Follow another user.

URL path parameters:
* `username` - A user's name.
"""

    target = get_user(username)

    if target.id==v.id:
        return jsonify({"error": "You can't follow yourself!"}), 400

    # check for existing follow
    if g.db.query(Follow).filter_by(user_id=v.id, target_id=target.id).first():
        abort(409)

    new_follow = Follow(user_id=v.id,
                        target_id=target.id)

    g.db.add(new_follow)
    g.db.flush()
    target.stored_subscriber_count=target.follower_count
    g.db.add(target)
    g.db.commit()

    cache.delete_memoized(User.idlist, v, kind="user")

    return "", 204

@app.route("/api/unfollow/<username>", methods=["POST"])
@app.delete("/api/v2/users/<username>/follow")
@auth_required
def unfollow_user(username, v):
    """
Unfollow another user.

URL path parameters:
* `username` - A user's name.
"""

    target = get_user(username)

    # check for existing follow
    follow = g.db.query(Follow).filter_by(
        user_id=v.id, target_id=target.id).first()

    if not follow:
        abort(409)

    g.db.delete(follow)

    cache.delete_memoized(User.idlist, v, kind="user")

    return "", 204

@app.route("/api/agree_tos", methods=["POST"])
@auth_required
def api_agree_tos(v):

    v.tos_agreed_utc = int(time.time())

    g.db.add(v)

    return redirect("/help/terms")

@app.get("/@<username>/pic/profile")
@limiter.exempt
def user_profile(username):
    x = get_user(username)
    return redirect(x.profile_url)

@app.get("/uid/<uid>/pic/profile")
@limiter.exempt
def user_profile_uid(uid):
    x=get_account(uid)
    return redirect(x.profile_url)

@app.route("/saved", methods=["GET"])
@app.route("/api/v1/saved", methods=["GET"])
#@app.get("/api/v2/me/saved")
@auth_required
@api("read")
def saved_listing(v):

    print("saved listing")

    page=int(request.args.get("page",1))

    ids=v.saved_idlist(page=page)

    next_exists=len(ids)==26

    ids=ids[0:25]

    print(ids)

    listing = get_posts(ids, v=v, sort="new")

    return {'html': lambda: render_template("home.html",
                                            v=v,
                                            listing=listing,
                                            page=page,
                                            next_exists=next_exists
                                            ),
            'api': lambda: jsonify({"data": [x.json for x in listing]})
            }

@app.post("/@<username>/toggle_bell")
@app.post("/api/v2/users/<username>/toggle_bell")
@auth_required
@api("update")
def toggle_user_bell(username, v):
    """
Toggle notifications for new posts by a user. You must be following the user.

URL path parameters:
* `username` - Another user's name
"""

    user=get_user(username, v=v, graceful=True)
    if not user:
        return jsonify({"error": f"User '@{username}' not found."}), 404

    follow=g.db.query(Follow).filter_by(user_id=v.id, target_id=user.id).first()
    if not follow:
        return jsonify({"error": f"You aren't following @{user.username}"}), 404

    follow.get_notifs = not follow.get_notifs
    g.db.add(follow)
    g.db.commit()

    return jsonify({"message":f"Notifications {'en' if follow.get_notifs else 'dis'}abled for @{user.username}"})

def convert_file(html):

    if not isinstance(html, str):
        return html

    soup=BeautifulSoup(html, 'html.parser')

    for thing in soup.find_all('link', rel="stylesheet"):

        if not thing['href'].startswith('https'):

            if app.config["FORCE_HTTPS"]:
                thing["href"]=f"https://{app.config['SERVER_NAME']}{thing['href']}"
            else:
                thing["href"]=f"https://{app.config['SERVER_NAME']}{thing['href']}"

    for thing in soup.find_all('a', href=True):

        if thing["href"].startswith('/') and not thing["href"].startswith(("javascript",'//')):
            if app.config["FORCE_HTTPS"]:
                thing["href"]=f"https://{app.config['SERVER_NAME']}{thing['href']}"
            else:
                thing["href"]=f"http://{app.config['SERVER_NAME']}{thing['href']}"

    for thing in soup.find_all('img', src=True):

        if thing["src"].startswith('/') and not thing["src"].startswith('//'):
            if app.config["FORCE_HTTPS"]:
                thing["src"]=f"https://{app.config['SERVER_NAME']}{thing['src']}"
            else:
                thing["src"]=f"http://{app.config['SERVER_NAME']}{thing['src']}"

    return str(soup)

def info_packet(username, method="html"):

    print(f"starting {username}")

    packet={}

    with app.test_request_context("/my_info"):

        db=db_session()
        g.timestamp=int(time.time())
        g.db=db

        user=get_user(username)

        #submissions
        post_ids=db.query(Submission.id).filter_by(author_id=user.id).order_by(Submission.created_utc.desc()).all()
        post_ids=[i[0] for i in post_ids]
        posts=get_posts(post_ids, v=user)
        packet["posts"]={
            'html':lambda:render_template("userpage.html", v=None, u=user, listing=posts, page=1, next_exists=False),
            'json':lambda:[x.self_download_json for x in posts]
        }

        #comments
        comment_ids=db.query(Comment.id).filter_by(author_id=user.id).order_by(Comment.created_utc.desc()).all()
        comment_ids=[x[0] for x in comment_ids]
        comments=get_comments(comment_ids, v=user)
        packet["comments"]={
            'html':lambda:render_template("userpage_comments.html", v=None, u=user, listing=comments, page=1, next_exists=False),
            'json':lambda:[x.self_download_json for x in comments]
        }

        #upvoted posts
        upvote_query=db.query(Vote.submission_id).filter_by(user_id=user.id, vote_type=1).order_by(Vote.id.desc()).all()
        upvote_posts=get_posts([i[0] for i in upvote_query], v=user)
        upvote_posts=[i for i in upvote_posts]
        for post in upvote_posts:
            post.__dict__['voted']=1
        packet['upvoted_posts']={
            'html':lambda:render_template("userpage.html", v=None, listing=posts, page=1, next_exists=False),
            'json':lambda:[x.json_core for x in upvote_posts]
        }

        print('post_downvotes')
        downvote_query=db.query(Vote.submission_id).filter_by(user_id=user.id, vote_type=-1).order_by(Vote.id.desc()).all()
        downvote_posts=get_posts([i[0] for i in downvote_query], v=user)
        packet['downvoted_posts']={
            'html':lambda:render_template("userpage.html", v=None, listing=posts, page=1, next_exists=False),
            'json':lambda:[x.json_core for x in downvote_posts]
        }

        print('comment_upvotes')
        upvote_query=db.query(CommentVote.comment_id).filter_by(user_id=user.id, vote_type=1).order_by(CommentVote.id.desc()).all()
        upvote_comments=get_comments([i[0] for i in upvote_query], v=user)
        packet["upvoted_comments"]={
            'html':lambda:render_template("userpage_comments.html", v=None, listing=upvote_comments, page=1, next_exists=False),
            'json':lambda:[x.json_core for x in upvote_comments]
        }

        print('comment_downvotes')
        downvote_query=db.query(CommentVote.comment_id).filter_by(user_id=user.id, vote_type=-1).order_by(CommentVote.id.desc()).all()
        downvote_comments=get_comments([i[0] for i in downvote_query], v=user)
        packet["downvoted_comments"]={
            'html':lambda:render_template("userpage_comments.html", v=None, listing=downvote_comments, page=1, next_exists=False),
            'json':lambda:[x.json_core for x in downvote_comments]
        }

        print('blocked users')
        blocked_users=db.query(UserBlock.target_id).filter_by(user_id=user.id).order_by(UserBlock.id.desc()).all()
        users=[get_account(base36encode(x[0])) for x in blocked_users]
        packet["blocked_users"]={
            "html":lambda:render_template("admin/new_users.html", users=users, v=None, page=1, next_exists=False),
            "json":lambda:[x.json_core for x in users]
        }

        send_mail(
            user.email,
            "Your Ruqqus Data",
            "Your Ruqqus data is attached.",
            "Your Ruqqus data is attached.",
            files={f"{user.username}_{entry}.{method}": io.StringIO(convert_file(str(packet[entry][method]()))) for entry in packet}
        )

    print("finished")

#@app.route("/my_info", methods=["POST"])
#@limiter.limit("2/day")
@auth_required
@validate_formkey
def my_info_post(v):

    if not v.is_activated:
        return redirect("/settings/security")

    method=request.values.get("method","html")
    if method not in ['html','json']:
        abort(400)

    gevent.spawn_later(5, info_packet, v.username, method=method)

    return "started"


import pandas as pd
from kafka import KafkaProducer
import json
import time

df = pd.read_csv("../datasets/BTS_1_benign.csv")

column_names = df.columns

df_jsons_list = df.to_json(orient='records', lines=True).splitlines()

producer = KafkaProducer(
    bootstrap_servers=['localhost:29092'],
)
for item in df_jsons_list:
    print("yeee")
    print(item)
    print(type(item))
    producer.send("flows-infoo", value=item.encode('utf-8'))


import constructs
from aws_cdk import RemovalPolicy, aws_apigateway, aws_lambda, aws_logs, aws_iam
import cdk_nag

class AppProjectApi(constructs.Construct):
    def __init__(
        self,
        scope: constructs.Construct,
        id: str,
        handler: aws_lambda.IFunction,
    ) -> None:
        super().__init__(scope, id)

        # Access logs group
        access_log_group = aws_logs.LogGroup(
            self,
            "SimpleCrudAppRestApiAccessLogGroup",
            log_group_name="simple-crud-api-access-log-group",
            removal_policy=RemovalPolicy.RETAIN,
            retention=aws_logs.RetentionDays.TWO_MONTHS,
        )

        # Stage options
        stage_options = aws_apigateway.StageOptions(
            stage_name="dev",
            access_log_destination=aws_apigateway.LogGroupLogDestination(
                access_log_group
            ),
            access_log_format=aws_apigateway.AccessLogFormat.json_with_standard_fields(
                caller=True,
                http_method=True,
                ip=True,
                protocol=True,
                request_time=True,
                resource_path=True,
                response_length=True,
                status=True,
                user=True,
            ),
            logging_level=aws_apigateway.MethodLoggingLevel.INFO,
            data_trace_enabled=True,
            metrics_enabled=True,
            tracing_enabled=True,
        )

        # Api Gateway
        self._api = aws_apigateway.LambdaRestApi(
            self,
            "SimpleCrudAppRestApi",
            handler=handler,
            proxy=False,
            description="Products API proxy to the Lambda",
            deploy_options=stage_options,
            rest_api_name="simple-crud-app-rest-api",
        )

        cw_role = [p for p in self._api.node.children if isinstance(p, aws_iam.Role)][0]
        cdk_nag.NagSuppressions.add_resource_suppressions(
            construct=cw_role,
            suppressions=[
                cdk_nag.NagPackSuppression(
                    id="AwsSolutions-IAM4",
                    reason="CloudWatch role is configured by CDK itself.",
                    applies_to=["Policy::arn:<AWS::Partition>:iam::aws:policy/service-role/AmazonAPIGatewayPushToCloudWatchLogs"]
                ),
            ],
        )

        self._api.add_gateway_response(
            "client-error-response",
            type=aws_apigateway.ResponseType.DEFAULT_4_XX,
            response_headers={
                "Access-Control-Allow-Origin": "'*'",
                "Access-Control-Allow-Headers": "'Content-Type,X-Amz-Date,Authorization,\
                    X-Api-Key,x-amz-security-token'",
                "Access-Control-Allow-Methods": "'OPTIONS,GET,POST,PUT,DELETE'",
            },
            templates={
                "application/json": '{ "message": $context.error.messageString }'
            },
        )

        self._api.add_gateway_response(
            "server-error-response",
            type=aws_apigateway.ResponseType.DEFAULT_5_XX,
            response_headers={
                "Access-Control-Allow-Origin": "'*'",
                "Access-Control-Allow-Headers": "'Content-Type,X-Amz-Date,Authorization,\
                    X-Api-Key,x-amz-security-token'",
                "Access-Control-Allow-Methods": "'OPTIONS,GET,POST,PUT,DELETE'",
            },
            templates={
                "application/json": '{ "message": $context.error.messageString }'
            },
        )

        aws_apigateway.RequestValidator(self, "api-gw-request-validator",
            rest_api=self._api,
        )

    @property
    def api(self) -> aws_apigateway.SpecRestApi:
        return self._api


from typing import Optional, Tuple
from mergedMain import mergeGame
import math

class maxVsRand():
    def get_action(self, game_state: mergeGame, depth):
        _, action = self.maxMove(game_state, depth)
        return action

    def maxMove(self, state: mergeGame, depth) -> Tuple[float, Optional[Tuple]]:
        if depth <= 0:
            return state.score
        moves = state.findLegalMoves()
        if len(moves) == 0:
            return state.score
        else:
            bestVal = -math.inf
            bestMove = None
            for move in moves:
                val = self.averageMove(state.generateSuccessorBoard(move), depth-1)
                if val > bestVal:
                    bestVal = val
                    bestMove = move
        return (bestVal, bestMove)

    def averageMove(self, state: mergeGame, depth):
        pieces = state.allPossibleNextPieces()
        sum = 0
        for piece in pieces:
            val = self.maxMove(state.generateBoardNextPiece(piece), depth-1)
            if type(val) is tuple:
                val , _ = val
            sum += val
        return sum / len(pieces)


import telebot
import config

from telebot import types

bot = telebot.TeleBot(config.TOKEN)

@bot.message_handler(commands=['start'])
def welcome(message):
	sti = open('sticks/welcome.tgs ', 'rb')
	bot.send_sticker(message.chat.id, sti)

	# keyboard
	markup = types.ReplyKeyboardMarkup(resize_keyboard=True)
	item1 = types.KeyboardButton("О компании")
	item2 = types.KeyboardButton("Наши услуги")
	item3 = types.KeyboardButton("Примеры")

	markup.add(item1, item2, item3)

	bot.send_message(message.chat.id, "Добро пожаловать, {0.first_name}!\nЯ - <b>{1.first_name}</b>, бот созданный чтобы быть подопытным кроликом.".format(message.from_user, bot.get_me()),
		parse_mode='html', reply_markup=markup)

@bot.message_handler(content_types=['text'])
def lalala(message):
	if message.chat.type == 'private':
		if message.text == 'О компании':

			markup = types.InlineKeyboardMarkup(row_width=2)
			item1 = types.InlineKeyboardButton("Контакты", callback_data='contacts')
			item2 = types.InlineKeyboardButton("Сайт", url='https://habrahabr.ru')
			item3 = types.InlineKeyboardButton("Инстаграм", url='https://instagram.com/cube_online_russia')

			markup.add(item1, item2, item3)

			bot.send_message(message.chat.id, 'Компания является экспертом..', reply_markup=markup)
		elif message.text == 'Наши услуги':
			bot.send_message(message.chat.id, 'Тут должны быть фотки')
		elif message.text == 'Примеры':
			bot.send_message(message.chat.id, 'Здесь вы можете посмотреть примеры наших работ\n[Рестораны 🍕🍷]\n@BigBuddaVLBot'.format(message.from_user, bot.get_me()),
		parse_mode='html')
		else:
			bot.send_message(message.chat.id, 'Я не знаю что ответить 😢')

@bot.callback_query_handler(func=lambda call: True)
def callback_inline(call):
	try:
		if call.message:
			if call.data == 'contacts':
				bot.send_message(call.message.chat.id, 'Мы находимся по адресу: г.Москва, Варшавское шоссе д.1 ст 1, офис В605')

	except Exception as e:
		print(repr(e))

# RUN
bot.polling(none_stop=True)


# Import modules

import numpy as np
from scipy import misc
from sklearn.cluster import KMeans
from matplotlib import pyplot as plt

def read_scene():
	data_x = misc.imread('../../Data/Scene/times_square.jpg')

	return (data_x)

title = ["Original",
		"KMeans Clustering (n=2)",
		"KMeans Clustering (n=5)",
		"KMeans Clustering (n=10)",
		"KMeans Clustering (n=25)",
		"KMeans Clustering (n=50)",
		"KMeans Clustering (n=75)",
		"KMeans Clustering (n=100)",
		"KMeans Clustering (n=200)"]

def plot_image(data,title):
	# pass in an array of plot data + array of labels
	print("I am in plotting")
	fig = plt.figure()

	cluster_size = [0, 2, 5, 10, 25, 50, 75, 100, 200]

	ax1 = fig.add_subplot(331)
	ax2 = fig.add_subplot(332)
	ax3 = fig.add_subplot(333)
	ax4 = fig.add_subplot(334)
	ax5 = fig.add_subplot(335)
	ax6 = fig.add_subplot(336)
	ax7 = fig.add_subplot(337)
	ax8 = fig.add_subplot(338)
	ax9 = fig.add_subplot(339)

	axis = [ax1,ax2,ax3,ax4,ax5,ax6,ax7,ax8,ax9]

	for i,d in enumerate(data):
		print("I am plotting for ", i)
		axis[i].imshow(d)
		axis[i].set_title(title[i])
		axis[i].set_xlabel("k_value"+str(cluster_size[i]))
	plt.tight_layout()
	plt.show()

def plot_the_error(error,title,ylabel):
	cluster_size = [ 2, 5, 10, 25, 50, 75, 100, 200]
	plt.plot(cluster_size , error,'-o')
	plt.title(title)
	plt.xlabel("Number of Clusters")
	plt.ylabel(ylabel)
	plt.show()

if __name__ == '__main__':

	################################################
	# K-Means
	cluster_size = [2, 5, 10, 25, 50, 75, 100, 200]
	# cluster_size = [2]

	data_x = read_scene()
	print('X = ', data_x.shape)

	flattened_image = data_x.ravel().reshape(data_x.shape[0] * data_x.shape[1], data_x.shape[2])
	# print('Flattened image = ', flattened_image.shape)
	# print("X val ", data_x[0], data_x[0].shape)
	print('Implement k-means here ...')

	plots_array = []
	sse_errors =[]
	plots_array.append(data_x)
	x = flattened_image
	totalpixels = x.shape[0]
	compressions_array = []
	for c in cluster_size:
		print("Running for cluster size", c)

		temp_image = np.zeros(flattened_image.shape)
		clf = KMeans(n_clusters= c, n_jobs= -1)
		clf.fit(flattened_image)
		cluster_centers = clf.cluster_centers_
		for i in range(flattened_image.shape[0]):
			temp_image[i] = cluster_centers[clf.labels_[i]]

		sse_errors.append(np.log(np.sum(np.square(temp_image-x))))
		temp_image = temp_image.ravel().reshape(data_x.shape[0], data_x.shape[1], data_x.shape[2])
		plots_array.append(temp_image/255)

		compression_rate = (np.ceil(np.log2(c))*totalpixels + c * 3 * 32) / (24*totalpixels)
		compressions_array.append([c,compression_rate])
	plot_image(plots_array,title)
	print("I am onto plotting")
	plot_the_error(sse_errors,"Error vs k-Clusters","Squared Error in log space")
	print("The Compression Rate is",compressions_array)

	# reconstructed_image = flattened_image.ravel().reshape(data_x.shape[0], data_x.shape[1], data_x.shape[2])
	# print('Reconstructed image = ', reconstructed_image.shape)


import csv
import matplotlib.pyplot as plt
import os
import jieba
import jieba.analyse
from wordcloud import WordCloud, STOPWORDS
import numpy    #numpy计算包
from datetime import datetime
import re

#时间与电影数量折线图
def movie_date_amount(fileName):
    #获取每列
    with open(fileName, encoding='utf-8', errors='ignore') as f:
        reader = csv.reader(f)
        header_row = next(reader)
        header_row[0] = header_row[0][2:-1]
        #print(header_row)
        '''
        for index, column_header in enumerate(header_row):
             print(index, column_header)
        '''
        #对数据进行筛选生成对应坐标数组
        dict1 = {}
        keys,data = [],[]
        for row in reader:
            if row[18] in dict1.keys():
                dict1[row[18]] = dict1[row[18]]+1
            else:
                dict1.setdefault(row[18],1)
        dict1.pop('0')
        for key in dict1.keys():
            keys.append(key)
            data.append(dict1[key])
    #创建画板
    plt.rcParams['font.sans-serif'] = ['SimHei']
    plt.rcParams['axes.unicode_minus'] = False
    fig1 = plt.figure(figsize=(30,5))
    plt.xticks(size='small', rotation=90, fontsize=5)
    #plt.plot(横坐标数组，纵坐标数组，颜色)
    plt.plot(keys,data,'red')
    plt.title("年份与电影数量图")
    #plt.show()
    pic_path = "D:/Python_Programs/Lab/result/movie_date_amount.png"
    plt.savefig(pic_path)

#个别国家的时间与电影数量折线图
def area_date_amount(filename):
    with open(fileName, encoding='utf-8', errors='ignore') as f:
        reader = csv.reader(f)
        header_row = next(reader)
        header_row[0] = header_row[0][2:-1]
        list_Chian = []
        list_USA = []
        list_India = []
        for row in reader:
            if '中国大陆' in row[13]:
                list_Chian.append(row)
            elif '美国' in row[13]:
                list_USA.append(row)
            elif '印度' in row[13]:
                list_India.append(row)
        dict1,dict2,dict3 = {},{},{}
        for list in list_Chian:
            if list[18] in dict1.keys():
                dict1[list[18]] = dict1[list[18]]+1
            else:
                dict1.setdefault(list[18],1)
        for list in list_USA:
            if list[18] in dict2.keys():
                dict2[list[18]] = dict2[list[18]]+1
            else:
                dict2.setdefault(list[18],1)
        for list in list_India:
            if list[18] in dict3.keys():
                dict3[list[18]] = dict3[list[18]]+1
            else:
                dict3.setdefault(list[18],1)
        time,amount1,amount2,amount3 = [],[],[],[]
        for key in dict1.keys():
            time.append(key)
            amount1.append(dict1[key])
        set_index = []
        for index,year in enumerate(time):
            if year in dict2.keys():
                amount2.append(dict2[year])
            else:
                set_index.append(index)
        for it in set_index:
            time.pop(it)
            amount1.pop(it)
            for i in range(len(set_index)):
                set_index[i] -= 1
        set_index2 = []
        for index, year in enumerate(time):
            if year in dict3.keys():
                amount3.append(dict3[year])
            else:
                set_index2.append(index)
        for it in set_index2:
            time.pop(it)
            amount2.pop(it)
            amount1.pop(it)
            for i in range(len(set_index2)):
                set_index2[i] -= 1
        time.pop()
        amount1.pop()
        amount2.pop()
        amount3.pop()
        # 创建画板
        plt.rcParams['font.sans-serif'] = ['SimHei']
        plt.rcParams['axes.unicode_minus'] = False
        fig1 = plt.figure(figsize=(15, 5))
        plt.xticks(size='small', rotation=90, fontsize=10)
        # plt.plot(横坐标数组，纵坐标数组，颜色)
        plt.plot(time, amount1, '-',label='中国')
        plt.plot(time, amount2, '-',label='美国')
        plt.plot(time, amount3, '-',label='印度')
        plt.xticks(time)
        plt.xlabel('年份')
        plt.title("各地区年份与电影数量图")
        #显示每条线的label
        plt.legend()
        #plt.show()
        pic_path = "D:/Python_Programs/Lab/result/area_date_amount.png"
        plt.savefig(pic_path)

#语言与电影数量柱状图
def lan_amount(filename):
    with open(fileName, encoding='utf-8', errors='ignore') as f:
        reader = csv.reader(f)
        header_row = next(reader)
        header_row[0] = header_row[0][2:-1]
        dict1 = {}
        list_lans_amount = [0,0,0,0,0,0,0,0,0,0,0,0,0,0]
        list_lans = ['汉语','英语','法语','德语','韩语','意大利语','日语','葡萄牙语','泰语','罗马尼亚语','阿拉伯语','尼泊尔语','丹麦语','捷克语']
        for row in reader:
            if '汉语' in row[10] or '粤语' in row[10] or '闽南' in row[10] or '藏语' in row[10]:
                list_lans_amount[0] += 1
            elif '英语' in row[10]:
                list_lans_amount[1] += 1
            elif '法语' in row[10]:
                list_lans_amount[2] += 1
            elif '德语' in row[10]:
                list_lans_amount[3] += 1
            elif '韩语' in row[10]:
                list_lans_amount[4] += 1
            elif '意大利语' in row[10]:
                list_lans_amount[5] += 1
            elif '日语' in row[10]:
                list_lans_amount[6] += 1
            elif '葡萄牙语' in row[10]:
                list_lans_amount[7] += 1
            elif '泰语' in row[10]:
                list_lans_amount[8] += 1
            elif '罗马尼亚语' in row[10]:
                list_lans_amount[9] += 1
            elif '阿拉伯语' in row[10]:
                list_lans_amount[10] += 1
            elif '尼泊尔语' in row[10]:
                list_lans_amount[11] += 1
            elif '丹麦语' in row[10]:
                list_lans_amount[12] += 1
            elif '捷克语' in row[10]:
                list_lans_amount[13] += 1
        # 创建画板
        plt.rcParams['font.sans-serif'] = ['SimHei']
        plt.rcParams['axes.unicode_minus'] = False
        fig1 = plt.figure(figsize=(15, 6))
        plt.xticks(size='small', rotation=90, fontsize=8)
        # plt.bar(横坐标数组，纵坐标数组)
        plt.bar(list_lans, list_lans_amount,alpha=0.5, width=0.3, color='yellow', edgecolor='red', label='语言与电影数量图', lw=1)
        plt.title("语言与电影数量图")
        plt.legend()
        #plt.show()
        pic_path = "D:/Python_Programs/Lab/result/lan_amount.png"
        plt.savefig(pic_path)

#语言与电影数量饼状图
def lan_amount_pie(filename):
    with open(fileName, encoding='utf-8', errors='ignore') as f:
        reader = csv.reader(f)
        header_row = next(reader)
        header_row[0] = header_row[0][2:-1]
        dict1 = {}
        list_lans_amount = [0,0,0,0,0,0,0,0,0,0]
        list_lans = ['汉语','英语','法语','德语','韩语','意大利语','西班牙语','日语','瑞典语','其他']
        for row in reader:
            if ('汉语' in row[10]) or ('普通话' in row[10]) or ('粤语' in row[10]) or ('闽南' in row[10])or('上海' in row[10]) or ('藏语' in row[10]) or ('方言' in row[10]) or ('彝语' in row[10]) or ('客家话' in row[10]) or ('武汉话' in row[10]):
                list_lans_amount[0] += 1
            elif '英语' in row[10]:
                list_lans_amount[1] += 1
            elif '法语' in row[10]:
                list_lans_amount[2] += 1
            elif '德语' in row[10]:
                list_lans_amount[3] += 1
            elif '韩语' in row[10]:
                list_lans_amount[4] += 1
            elif '意大利语' in row[10]:
                list_lans_amount[5] += 1
            elif '葡萄牙语' in row[10]:
                list_lans_amount[6] += 1
            elif '日语' in row[10]:
                list_lans_amount[7] += 1
            elif '瑞典语' in row[10]:
                list_lans_amount[8] += 1
            elif row[10] != '':
                list_lans_amount[9] += 1
                if row[10] in dict1.keys():
                    dict1[row[10]] = dict1[row[10]] + 1
                else:
                    dict1.setdefault(row[10], 1)
        # 创建画板
        plt.rcParams['font.sans-serif'] = ['SimHei']
        plt.rcParams['axes.unicode_minus'] = False
        fig1 = plt.figure(figsize=(8, 6))
        #plt.xticks(size='small', rotation=90, fontsize=7)
        explode = (0,0,0,0,0,0,0,0,0,0)
        plt.pie(list_lans_amount,explode=explode,labels=list_lans,autopct='%1.1f%%',shadow=False,startangle=150,
                textprops={'fontsize':10,'color':'black'})
        plt.title("语言与电影数量饼状图")
        #plt.show()
        pic_path = "D:/Python_Programs/Lab/result/lan_amount_pie.png"
        plt.savefig(pic_path)

#国家与电影数量柱状图
def area_amount(filename):
    with open(fileName, encoding='utf-8', errors='ignore') as f:
        reader = csv.reader(f)
        header_row = next(reader)
        header_row[0] = header_row[0][2:-1]
        list_area_amount = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
        list_areas = ['中国','美国','日本','韩国','印度','意大利','加拿大','西班牙','巴西','英国','德国','法国','俄罗斯','瑞典','澳大利亚']
        for row in reader:
            if '中国' in row[13] :
                list_area_amount[0] += 1
            elif '美国' in row[13]:
                list_area_amount[1] += 1
            elif '日本' in row[13]:
                list_area_amount[2] += 1
            elif '韩国' in row[13]:
                list_area_amount[3] += 1
            elif '印度' in row[13]:
                list_area_amount[4] += 1
            elif '意大利' in row[13]:
                list_area_amount[5] += 1
            elif '加拿大' in row[13]:
                list_area_amount[6] += 1
            elif '西班牙' in row[13]:
                list_area_amount[7] += 1
            elif '巴西' in row[13]:
                list_area_amount[8] += 1
            elif ('英国' in row[13]) or ('爱尔兰' in row[13]):
                list_area_amount[9] += 1
            elif '德国' in row[13]:
                list_area_amount[10] += 1
            elif '法国' in row[13]:
                list_area_amount[11] += 1
            elif '俄罗斯' in row[13]:
                list_area_amount[12] += 1
            elif '瑞典' in row[13]:
                list_area_amount[13] += 1
            elif '澳大利亚' in row[13]:
                list_area_amount[14] += 1

        # 创建画板
        plt.rcParams['font.sans-serif'] = ['SimHei']
        plt.rcParams['axes.unicode_minus'] = False
        fig1 = plt.figure(figsize=(15, 6))
        plt.xticks(size='small', rotation=90, fontsize=8)
        # plt.bar(横坐标数组，纵坐标数组)
        plt.bar(list_areas, list_area_amount,alpha=0.5, width=0.3, color='yellow', edgecolor='red', label='国家与电影数量图', lw=1)
        plt.title("国家与电影数量柱状图")
        plt.legend()
        #plt.show()
        pic_path = "D:/Python_Programs/Lab/result/area_amount.png"
        plt.savefig(pic_path)

#评分和电影数柱状图
def score_count(fileName):
    dict1={}
    score,amount = [],[]
    with open(fileName, encoding='utf-8', errors='ignore') as f:
        reader = csv.reader(f)
        header_row = next(reader)
        header_row[0] = header_row[0][2:-1]
        print(header_row)
        for row in reader:
            if row[6] in dict1.keys():
                dict1[row[6]] += 1;
            elif row[6] != '0.0':
                dict1.setdefault(row[6],1)
        for key in dict1.keys():
            score.append(key)
            amount.append(dict1[key])
    # 创建画板
    plt.rcParams['font.sans-serif'] = ['SimHei']
    plt.rcParams['axes.unicode_minus'] = False
    fig1 = plt.figure(figsize=(15, 6))
    plt.xticks(size='small', rotation=90, fontsize=8)
    # plt.bar(横坐标数组，纵坐标数组)
    plt.bar(score, amount, alpha=0.5, width=0.3, color='yellow', edgecolor='red',
             label='评分与电影数量柱状图', lw=1)
    plt.title("评分与电影数量柱状图")
    plt.legend()
    #plt.show()
    pic_path = "D:/Python_Programs/Lab/result/score_count.png"
    plt.savefig(pic_path)

#不同国家每年发行电影的平均评分
def date_averageScover(filename):
    country = ['中国','美国','日本','韩国']
    date = []
    for i in range(1948,2020):
        date.append(i)
    list_Chian = []
    list_USA = []
    list_Japan = []
    with open(fileName, encoding='utf-8', errors='ignore') as f:
        reader = csv.reader(f)
        header_row = next(reader)
        header_row[0] = header_row[0][2:-1]
        for row in reader:
            if '中国' in row[13]:
                list_Chian.append(row)
            elif '美国' in row[13]:
                list_USA.append(row)
            elif '日本' in row[13]:
                list_Japan.append(row);
    Ave_China = []
    Ave_USA = []
    Ave_Japan = []
    for year in date:
        sum,count = 0,0
        average = 0
        for row in list_Chian:
            if (str(year) in row[18]) and (row[6] != '0.0'):
                count += 1
                sum += float(row[6])
        if(count > 0):
            average = sum / count
        Ave_China.append(average)
    for year in date:
        sum,count = 0,0
        average = 0
        for row in list_USA:
            if (str(year) in row[18]) and (row[6] != '0.0'):
                count += 1
                sum += float(row[6])
        if (count > 0):
            average = sum / count
        Ave_USA.append(average)
    for year in date:
        sum,count = 0,0
        average = 0
        for row in list_Japan:
            if (str(year) in row[18]) and (row[6] != '0.0'):
                count += 1
                sum += float(row[6])
        if (count > 0):
            average = sum / count
        Ave_Japan.append(average)
    # 创建画板
    plt.rcParams['font.sans-serif'] = ['SimHei']
    plt.rcParams['axes.unicode_minus'] = False
    fig1 = plt.figure(figsize=(15, 5))
    plt.xticks(size='small', rotation=90, fontsize=10)
    # plt.plot(横坐标数组，纵坐标数组，颜色)
    plt.plot(date, Ave_China, '-', label='中国')
    plt.plot(date, Ave_USA, '-', label='美国')
    plt.plot(date, Ave_Japan, '-', label='日本')
    plt.xticks(date)
    plt.xlabel('年份')
    plt.title("部分国家年份与平均评分折线图")
    # 显示每条线的label
    plt.legend()
    #plt.show()
    pic_path = "D:/Python_Programs/Lab/result/date_averageScover.png"
    plt.savefig(pic_path)

#生成豆瓣评分top20的电影csv文件
def createtop20(filename):
    data = csv.reader(open(filename,encoding='utf-8'), delimiter=',')
    sortedlist = sorted(data, key=lambda x: x[6], reverse=True)
    #按评分排列所有影片，取评分前20生成score_top20.csv
    with open("score_top20.csv", "w",encoding='utf-8-sig', newline='') as f:
        fileWriter = csv.writer(f, delimiter=',')
        for i in range (1,21):
            #print(row)
            fileWriter.writerow(sortedlist[i])
    f.close()

#评分top20生成词云
def createwordcloud(filename1,filename2):
    data = csv.reader(open(filename1, encoding='utf-8'), delimiter=',')
    movie_id = []
    for row in data:
        #print(row[0])
        movie_id.append(row[0])
    #根据id对每个top20电影生成词云

    #获取评论
    for id in movie_id:
        data = csv.reader(open(filename2, encoding='utf-8'), delimiter=',')
        txtname = "tmp"+id.encode('utf-8').decode('utf-8-sig')+".txt"
        flag = os.path.exists(txtname)
        if flag != True:
            for row in data:
                if row[2] == id:
                    f = open(txtname, "a", encoding='utf-8-sig')
                    f.write(row[3])

    #生成词云
    for id in movie_id:
        txtname = 'tmp'+id.encode('utf-8').decode('utf-8-sig')+'.txt'
        flag = os.path.exists(txtname)
        if flag:
            data = open(txtname.encode('utf-8').decode('utf-8-sig'), encoding='utf-8-sig').read()
            #print(type(data))
            pattern = re.compile(r'[\u4e00-\u9fa5]+')
            filterdata = re.findall(pattern, data)
            cleaned_comments = ''.join(filterdata)
            # 使用jieba分词进行中文分词,topK为返回关键词个数,withWeight为是否一并返回关键词权重值,默认值为 False
            result=jieba.analyse.textrank(cleaned_comments,topK=80,withWeight=True)
            keywords = dict()
            for i in result:
                keywords[i[0]] = i[1]
            print("删除停用词前", keywords)  # {'演员': 0.18290354231824632, '大片': 0.2876433001472282}
            # 停用词集合
            stopwords = set(STOPWORDS)
            f = open('./StopWords.txt', encoding="utf8")
            while True:
                word = f.readline()
                if word == "":
                    break
                stopwords.add(word[:-1])

            keywords = {x: keywords[x] for x in keywords if x not in stopwords}
            print("\n删除停用词后", keywords)
            # 用词云进行显示,font_path字体路径
            wordcloud = WordCloud(font_path="simhei.ttf", background_color="white",
                                  max_font_size=80, stopwords=stopwords)
            word_frequence = keywords
            myword = wordcloud.fit_words(word_frequence)
            plt.imshow(myword)  # 展示词云图
            plt.axis("off")
            #plt.show()
            pic_path = "D:/Python_Programs/Lab/result/wordcloud"+id.encode('utf-8').decode('utf-8-sig')+'.png'
            plt.savefig(pic_path)

fileName = 'moviedata\movies.csv'
fileName1= 'moviedata\comments.csv'
fileName2 = 'score_top20.csv'
'''
movie_date_amount(fileName)
area_date_amount(fileName)
lan_amount(fileName)
lan_amount_pie(fileName)
area_amount(fileName)
score_count(fileName)
date_averageScover(fileName)
createtop20(fileName)
'''
createwordcloud(fileName2,fileName1)

项目/23组_豆瓣电影数据的爬取、分析与建模/23组_豆瓣电影数据的爬取、分析与建模/数据分析/Data_visualization.py