from tkinter import *
import math
import pandas
import pandas as pd
from nltk.sentiment.vader import SentimentIntensityAnalyzer
import os.path
from Scripts.filtering import *
from Scripts.webscraper import *
from PIL import ImageTk, Image
from Scripts.review_analysis import *

##########Initialise values############
window = Tk()
HotelCSVData = pd.read_csv("Filtered_Datafiniti_Hotel_Main_Review.csv")
window.geometry("1920x1080")
window.option_add("*Background", "#fff6ec")
window.title("Hotelopolis")
window.iconbitmap("icon/hotelopolis.ico")
senti = SentimentIntensityAnalyzer()
#image = ImageTk.PhotoImage(Image.open("icon/hotelopolis.png"))

Framecolor = "#DAA06D" #color for all frames

#list of hotels on menu (button form)
HotelMenuList=[]
#list of hotels taken from csv
HotelsList =[]
#list of recommended hotels at the side when user clicks hotels
RecommendedHotelsList=[]
#list of bookmarked hotel objects to access class
BookmarkedHotelsObjectsList=[]
#list of bookmarked hotels for dropdown menu
BookmarkedHotelsNameList=[]
#list of review items
ReviewItemsList=[]

#for writing bookmarks
Bookmarkdata=None #if file exists, read from it

#original hotel options
HotelOptions=[]
for name in HotelCSVData["name"]: #add all hotels in csv
    if(pd.isnull(name)): #get rid of any null cells
       continue
    if(name not in HotelOptions):#as the name is repeated multiple times in csv, just take one
        HotelOptions.append(name)

#options for sorting in dropdown menu
MainMenuSortOptions = [
    'Alphabetical A-Z',
    'Alphabetical Z-A',
    'Rating (High to Low)',
    'Rating (Low to High)'
    ]

#options for review filtering
ReviewFilterOptions=[
    'All',
    '1 star',
    '2 stars',
    '3 stars',
    '4 stars',
    '5 stars'
]

def UpdateBookmarkCsv(toggledhotel = None):
    if(toggledhotel == None):
        if(os.path.exists("Bookmarks.csv")):
            Bookmarkdata = pd.read_csv("Bookmarks.csv", index_col=0)
            listofbookmarks = list(Bookmarkdata['name'])
            if(len(HotelOptions) > len(listofbookmarks)):
                NewHotels = [hotel for hotel in HotelOptions if hotel not in listofbookmarks]#check for new hotel and add if neccessary
                BookmarkDataFrame = pd.DataFrame(NewHotels, columns=['name'])
                BookmarkDataFrame["bookmarked"] = False
                Bookmarkdata = pandas.concat([Bookmarkdata, BookmarkDataFrame],axis=0, ignore_index=True)
                Bookmarkdata.to_csv("Bookmarks.csv")

            elif(len(HotelOptions) < len(listofbookmarks)):
                OldHotels = [hotel for hotel in listofbookmarks if hotel not in HotelOptions]  # check for new hotel and add if neccessary
                for hotel in OldHotels:
                    Bookmarkdata.drop(Bookmarkdata[Bookmarkdata['name'] == hotel].index, inplace=True)
                    Bookmarkdata.to_csv("Bookmarks.csv")
        else:
            BookmarkDataFrame = pd.DataFrame(HotelOptions, columns=['name'])  #since bookmarked csv not created, create one and set all hotels to not bookmarked
            BookmarkDataFrame["bookmarked"] = False
            BookmarkDataFrame.to_csv("Bookmarks.csv")

    else:
        Bookmarkdata = pd.read_csv("Bookmarks.csv")
        Bookmarkdata.loc[Bookmarkdata.name == toggledhotel.Name, "bookmarked"] = toggledhotel.Bookmarked
        Bookmarkdata.to_csv("Bookmarks.csv", index=False)  # update csv based on new bookmarks

    Bookmarkdata = pd.read_csv("Bookmarks.csv", index_col=0)
    return Bookmarkdata

class Hotel:
    def __init__(self, name, address, scoreslist, reviewslist, bookmarked): #initialise hotel objects
        self.Name = name
        self.Address = address
        self.ScoresList = scoreslist
        self.ReviewsList = reviewslist
        self.Bookmarked = bookmarked

        #get sentimental anayisis of hotel reviews
        analysis ={}
        analysis["Positive"] = [senti.polarity_scores(i)["pos"] for i in self.ReviewsList]
        analysis["Negative"] = [senti.polarity_scores(i)["neg"] for i in self.ReviewsList]

        TotalScore = 0.00
        if(' ' in self.ScoresList): #detect for hotels without given score and use sentimental analysis score to get review score
            PositiveList = list(analysis["Positive"])
            NegativeList = list(analysis["Negative"])
            for index, values in enumerate(PositiveList):
                totalratingadded = PositiveList[index] + NegativeList[index]
                if(totalratingadded !=0):
                    calculated = round((PositiveList[index]/totalratingadded) * 5) #calculated score by adding positive and negative then divide by total, times 5(out of 5 stars)
                    if(calculated == 0): #to make completely negative reviews have a score of 1
                        calculated=1
                    self.ScoresList[index] = calculated
                    TotalScore += calculated
                else:#if review is completely neutral, give it a score of 3
                    calculated = 3
                    self.ScoresList[index] = calculated
                    TotalScore += calculated
        else:
            for rating in self.ScoresList:
                TotalScore += int(rating)

        self.AverageScore = TotalScore / len(self.ScoresList) #calculate average score by adding all reviews score and divide by number of reviews

        self.Facilities = facility_check(','.join(reviewslist)) #get facilities of hotel from finding keywords from reviews

        GoodReviewsList=[]
        BadReviewsList = []
        for index, score in enumerate(self.ScoresList):
            if(int(score) >=4):
                GoodReviewsList.append(self.ReviewsList[index])
            if (int(score) <= 3):
                BadReviewsList.append(self.ReviewsList[index])

        self.pos_WordCloudReview = ','.join(GoodReviewsList)
        self.neg_WordCloudReview = ','.join(BadReviewsList)

#################functions#####################
def ClearMainMenu(): #clear all widgets on main menu
    MainMenuFrame.grid_forget()
    FilterFrame.grid_forget()

def ClearHotelDetails(): #clear all widgets on hotel details
    RecommendationFrame.grid_forget()
    HotelDetailsFrame.grid_forget()
    MenuButton.grid_forget()
    for Review in ReviewItemsList:
        Review.destroy()

    ReviewItemsList.clear()

def RefreshHotels():
    HotelCSVData = pd.read_csv("Filtered_Datafiniti_Hotel_Main_Review.csv")

    for name in HotelCSVData["name"]:
        if name not in HotelOptions:
            ReviewsList = list(HotelCSVData.loc[HotelCSVData.name == name, 'reviews.text'])
            ReviewsRating = list(HotelCSVData.loc[HotelCSVData.name == name, 'reviews.rating'])
            AddressList = HotelCSVData.loc[HotelCSVData.name == name, 'address']
            Address = AddressList.iat[0]
            Bookmarked = False
            HotelObject = Hotel(name, Address, ReviewsRating, ReviewsList, Bookmarked)
            HotelsList.append(HotelObject)
            HotelOptions.append(name)

    UpdateBookmarkCsv()
    # sort and filter main menu based on default values
    FilterAndSortHotelDetails(SortVariable)

def ToggleBookmark(): #toggle bookmarked status of current hotel
    currenthotelname = HotelNameLabel.cget("text")
    for hotel in HotelsList:
        if(hotel.Name == currenthotelname):
            hotel.Bookmarked = BookmarkedVariable.get()
            if(hotel.Bookmarked):
                BookmarkedHotelsNameList.append(hotel.Name)
                BookmarkedHotelsObjectsList.append(hotel)
                if ("No Bookmarks") in BookmarkedHotelsNameList:
                    BookmarkedHotelsNameList.remove("No Bookmarks")
            else:
                BookmarkedHotelsNameList.remove(hotel.Name)
                BookmarkedHotelsObjectsList.remove(hotel)
                if(len(BookmarkedHotelsNameList)==0):
                    BookmarkedHotelsNameList.append("No Bookmarks")

            UpdateBookmarkCsv(hotel)

    BookmarkDropdown["menu"].delete(0, 'end')
    for hotel in BookmarkedHotelsNameList:
        BookmarkDropdown["menu"].add_command(label= hotel, command=lambda hotel = hotel:SelectFromBookmark(hotel))  #update bookmark dropdown

def FilterAndSortHotelDetails(sortoption = None): #update main menu based on filter and sort options
    for HotelButton in HotelMenuList: #destroy all buttons as we will create them based on all the filter and sort options
        HotelButton.destroy()

    HotelMenuList.clear() #clear list of hotel buttons as they all are destroyed

    #create list to check which ameneties user selected
    amenetiesselectedlist = []
    if(restaurant.get() != "na"):
        amenetiesselectedlist.append(restaurant.get())
    if (pool.get() != "na"):
        amenetiesselectedlist.append(pool.get())
    if (jacuzzi.get() != "na"):
        amenetiesselectedlist.append(jacuzzi.get())
    if(gym.get()!="na"):
        amenetiesselectedlist.append(gym.get())
    if (spa.get() != "na"):
        amenetiesselectedlist.append(spa.get())

    #sort list to be displayed based on user selected sort
    if(SortVariable.get() == 'Alphabetical A-Z'):
        SortedList = sorted(HotelsList, key= lambda x:x.Name)
    elif(SortVariable.get() == 'Alphabetical Z-A'):
        SortedList = sorted(HotelsList, key= lambda x:x.Name, reverse=True)
    elif (SortVariable.get() == 'Rating (High to Low)'):
        SortedList = sorted(HotelsList, key=lambda x: x.AverageScore, reverse=True)
    elif (SortVariable.get() == 'Rating (Low to High)'):
        SortedList = sorted(HotelsList, key=lambda x: x.AverageScore)

    #create buttons based on sorted list, ameneties selected and filtering options
    if(onestar.get() == 0 and twostar.get() == 0 and threestar.get() == 0 and fourstar.get() == 0 and fivestar.get() == 0): #if no star filter selected
        for index, hotel in enumerate(SortedList):
            if (len(amenetiesselectedlist) > 0 and not any(x in hotel.Facilities for x in amenetiesselectedlist)): #if hotel does not have selected ameneites, skip it and dont create a button
                continue
            MenuHotelFrame = Frame(master=MainMenuFrame, highlightthickness=2, highlightbackground=Framecolor)
            MenuHotelFrame.grid(row=index + 1, column=0, sticky=N, pady=10, padx=10)
            facilitieslist = ', '.join(hotel.Facilities)
            HotelPicture =  Label(MenuHotelFrame, text="Insert pic", anchor=CENTER)
            HotelPicture.grid(row=0, column=0, sticky=W, padx=10)
            HotelButton = Button(MenuHotelFrame, text=hotel.Name + "\n"+hotel.Address + "\n Average Score: %0.1f/5" % hotel.AverageScore + "\n Facilities: " + facilitieslist,
                                     command=lambda hotel=hotel: DisplayHotelDetails(hotel), width=60, height=6, font=("Arial", 10), relief=GROOVE)
            HotelButton.grid(row=0, column=1, sticky=W)
            HotelMenuList.append(MenuHotelFrame) #add hotel button back into list
    else:
        for index, hotel in enumerate(SortedList): #else if star filter selected, create buttons based on star filter
            if (len(amenetiesselectedlist) > 0 and not any(x in hotel.Facilities for x in amenetiesselectedlist)): #if hotel does not have selected ameneites, skip it and dont create a button
                continue
            if(int(hotel.AverageScore) == onestar.get() or int(hotel.AverageScore) == twostar.get() or int(hotel.AverageScore) == threestar.get() or int(hotel.AverageScore) == fourstar.get() or int(hotel.AverageScore) == fivestar.get()):
                MenuHotelFrame = Frame(master=MainMenuFrame, highlightthickness=2, highlightbackground=Framecolor)
                MenuHotelFrame.grid(row=index + 1, column=0, sticky=N, pady=10, padx=10)
                facilitieslist = ', '.join(hotel.Facilities)
                HotelPicture = Label(MenuHotelFrame, text="Insert pic", anchor=CENTER)
                HotelPicture.grid(row=0, column=0, sticky=W, padx=10)
                HotelButton = Button(MenuHotelFrame,
                                     text=hotel.Name + "\n" + hotel.Address + "\n Average Score: %0.1f/5" % hotel.AverageScore + "\n Facilities: " + facilitieslist,
                                     command=lambda hotel=hotel: DisplayHotelDetails(hotel), width=60, height=6,
                                     font=("Arial", 10), relief=GROOVE)
                HotelButton.grid(row=0, column=1, sticky=W)
                HotelMenuList.append(MenuHotelFrame)  # add hotel button back into list

    #show no results label if completely empty
    if(len(HotelMenuList) == 0):
        Emptylabel.grid(row= 1, column=0, sticky=N, pady=10)
    else:
        Emptylabel.grid_forget()#clear no result label if there are hotels to display

    UpdateScrollbar()

def SelectFromBookmark(selectedbookmark): #called when u select a hotel from the bookmark dropdown. It will call displayhoteldetails function based on selection
    for hotel in BookmarkedHotelsObjectsList:
        if(hotel.Name == selectedbookmark):
            DisplayHotelDetails(hotel)
            break
    BookmarkNameVariable.set("Bookmarks") #reset bookmark dropdown title

def DisplayWorldCloud():
    currenthotel = None
    currenthotelname = HotelNameLabel.cget("text")
    for hotel in HotelsList:
        if (hotel.Name == currenthotelname):
            currenthotel = hotel

    neg_showWordCloud(currenthotel.neg_WordCloudReview, currenthotelname)
    pos_showWordCloud(currenthotel.pos_WordCloudReview, currenthotelname)

def UpdateRecommendations(hotel): #display recommendations at side of hotel details
    for HotelButton in RecommendedHotelsList: #destroy all buttons recommended before to refresh with new ones
        HotelButton.destroy()

    RecommendedHotelsList.clear()
    for index, otherhotel in enumerate(HotelsList):
        facilitieslist = ', '.join(otherhotel.Facilities)
        if (math.ceil(otherhotel.AverageScore) >= round(hotel.AverageScore) and otherhotel.Name != hotel.Name): #check for hotels with similar of higher star ratings to recommend
            RecoHotelFrame = Frame(master=RecommendationFrame, highlightthickness=2, highlightbackground=Framecolor)
            RecoHotelFrame.grid(row=index + 1, column=0, sticky=N, pady=10, padx=10)
            RecoHotelPicture =  Label(RecoHotelFrame, text="Insert pic", anchor=CENTER)
            RecoHotelPicture.grid(row=0, column=0, sticky=W, padx=10)
            RecoHotelMenuButton = Button(RecoHotelFrame, text=otherhotel.Name + "\n Average Score: %0.1f/5" % otherhotel.AverageScore + "\n Facilities: " + facilitieslist,
                                     command=lambda otherhotel=otherhotel: DisplayHotelDetails(otherhotel), width=26, height=6, font=("Arial", 10), relief=GROOVE, wraplength=200)
            RecoHotelMenuButton.grid(row=0, column=1, sticky=N)
            RecommendedHotelsList.append(RecoHotelFrame)

def FilterReviews(filterby):
    for item in ReviewItemsList:
        item.destroy()
    ReviewItemsList.clear()

    currenthotel = None
    currenthotelname = HotelNameLabel.cget("text")
    for hotel in HotelsList:
        if (hotel.Name == currenthotelname):
            currenthotel = hotel

    filteredvar = 0
    if(filterby == "1 star"):
        filteredvar = 1
    elif(filterby == "2 stars"):
        filteredvar = 2
    elif (filterby == "3 stars"):
        filteredvar = 3
    elif (filterby == "4 stars"):
        filteredvar = 4
    elif (filterby == "5 stars"):
        filteredvar = 5

    # display reviews
    for index, score in enumerate(currenthotel.ScoresList):
        if(filteredvar!= 0 and filteredvar != int(score)):
            continue
        ReviewTextFrame = Frame(master=HotelReviewFrame, highlightbackground=Framecolor, highlightthickness=1)
        ReviewTextFrame.grid(row=index + 2, column=0, sticky=NSEW, pady=5)
        ReviewsScoreText = Label(ReviewTextFrame, text=("Score:", score))
        ReviewsScoreText.grid(row=index, column=0, sticky=NW)
        ReviewsText = Label(ReviewTextFrame, text=currenthotel.ReviewsList[index], justify=LEFT, wraplength=800)
        ReviewsText.grid(row=index + 1, column=0, sticky=NW)
        ReviewItemsList.append(ReviewTextFrame)

# Function to create a bar chart for reviews based on their stars rating
def DisplayBarChart():
    # Getting current hotel
    currenthotel = None
    currenthotelname = HotelNameLabel.cget("text")
    for hotel in HotelsList:
        if (hotel.Name == currenthotelname):
            currenthotel = hotel

    # Categorizing reviews based on their ratings
    one_count, two_count, three_count, four_count, five_count = 0,0,0,0,0
    for score in currenthotel.ScoresList:
        if int(score) == 5:
            five_count += 1
        elif int(score) == 4:
            four_count += 1
        elif int(score) == 3:
            three_count += 1
        elif int(score) == 2:
            two_count += 1
        else:
            one_count += 1

    # Displaying bar chart function from analysis
    showBarChart(one_count, two_count, three_count, four_count, five_count, currenthotelname)

# Function to create and display a pie chart
def DisplayPieChart():
    currenthotel = None
    currenthotelname = HotelNameLabel.cget("text")
    for hotel in HotelsList:
        if (hotel.Name == currenthotelname):
            currenthotel = hotel

    analysis ={}
    analysis["Positive"] = [senti.polarity_scores(i)["pos"] for i in currenthotel.ReviewsList]
    analysis["Negative"] = [senti.polarity_scores(i)["neg"] for i in currenthotel.ReviewsList]
    positive = sum(analysis["Positive"])
    negative = sum(analysis["Negative"])
    showPieChart(positive, negative, currenthotelname)

# Function for Show Analysis Button to display WordCloud, Bar Chart and Pie Chart
def showAnalysis():
    DisplayBarChart()
    DisplayPieChart()

def showEmotions():
    DisplayWorldCloud()

def UpdateScrollbar():
    # scrollbar
    # update size of content for scrollbar
    MainCanvas.update_idletasks()
    MainCanvas.config(scrollregion=MainCanvas.bbox("all"))
    # reset scrollbar position to start
    MainCanvas.xview_moveto(0)
    MainCanvas.yview_moveto(0)

def DisplayMainMenu():
    ClearHotelDetails() #clear hoteldetails gui and show main menu gui
    FilterFrame.grid(row=1, column=0, sticky=N, padx=40)
    MainMenuFrame.grid(row=1, column=1, sticky=NSEW)
    UpdateScrollbar()

#logic for UI display, it clears details and reformats it for the new hotel
def DisplayHotelDetails(hotel):
    ClearHotelDetails() #clear details of old displayed hotel as we will update new one with new widgets
    ClearMainMenu() #clear main menu

    #configure hotel name label
    HotelNameLabel.config(text=hotel.Name)

    # configure hotel address label
    AddressLabel.config(text=("Address: " + hotel.Address))

    facilitieslist = ', '.join(hotel.Facilities)
    FacilitiesLabel.config(text=("Facilities: " + facilitieslist))

    # configure bookmarked status of hotel
    BookmarkedVariable.set(hotel.Bookmarked)

    # configure hotel average score /5
    AverageScoreLabel.config(text= "Star Rating: %0.1f"%hotel.AverageScore+ "/5")

    #configure images
    HotelMainImage.config(text="Main Image")
    HotelSmallImageOne.config(text="Small Image")
    HotelSmallImageTwo.config(text="Small Image")
    HotelSmallImageThree.config(text="Small Image")

    ReviewFilterVariable.set(ReviewFilterOptions[0])

    #display reviews
    for index, score in enumerate(hotel.ScoresList):
        ReviewTextFrame = Frame(master=HotelReviewFrame, highlightbackground=Framecolor, highlightthickness=1)
        ReviewTextFrame.grid(row=index +2, column=0, sticky=NSEW, pady=5)
        ReviewsScoreText = Label(ReviewTextFrame, text=("Score:",score))
        ReviewsScoreText.grid(row=index, column=0, sticky=NW)
        ReviewsText = Label(ReviewTextFrame, text=hotel.ReviewsList[index], justify=LEFT, wraplength=800)
        ReviewsText.grid(row=index+1, column=0, sticky=NW)
        ReviewItemsList.append(ReviewTextFrame)

    UpdateRecommendations(hotel) #call update recommendations to show hotels with similar or better ratings
    #show widgets needed for hotel details
    RecommendationFrame.grid(row=1, column=0, padx=40, sticky=N)
    HotelDetailsFrame.grid(row=1, column=1, sticky=N)
    MenuButton.grid(row=0, column=0, padx=35, pady=20, sticky=NE)
    UpdateScrollbar()

## Create a add hotel pop up
def open_popup():
    global top
    top = Toplevel(MainFrame)
    top.geometry("500x150")
    top.title("Add hotel")
    Label(top, text= "Enter the url of the hotel below! (Tripadvisor.com or booking.com)", font=('Arial')).grid(row=0,column=3)
    global input_text
    input_text = Entry(top, width=40, textvariable="url")
    input_text.focus_set()
    input_text.grid(row=2, column=3)
    #input_text = Text(top, height=3, width=50)
    #input_text.grid(row=2, column=3)
    Ok_button = Button(top, text = "Ok add it!", command= take_input)
    Ok_button.grid(row=3, column=3)

## Take string input and start webscrapping
def take_input(*args):
    url = input_text.get()
    print(url)
    urlchecker(url)
    top.destroy()
    RefreshHotels()

## Click on button
def on_button():
    take_input()

#####Main code#####
Bookmarkdata = UpdateBookmarkCsv()
#Bookmarkdata = pd.read_csv("Bookmarks.csv", index_col=0)
for i in HotelOptions:
    #create hotels
    ReviewsList = list(HotelCSVData.loc[HotelCSVData.name == i, 'reviews.text'])
    ReviewsRating = list(HotelCSVData.loc[HotelCSVData.name == i, 'reviews.rating'])
    AddressList =  HotelCSVData.loc[HotelCSVData.name == i, 'address']
    Address = AddressList.iat[0]
    Bookmarked = Bookmarkdata.loc[Bookmarkdata.name == i, 'bookmarked'].bool()
    HotelObject = Hotel(i, Address, ReviewsRating, ReviewsList, Bookmarked)
    HotelsList.append(HotelObject)
    if(Bookmarked == True):
        BookmarkedHotelsObjectsList.append(HotelObject)
        BookmarkedHotelsNameList.append(HotelObject.Name)

##########UI LAYOUT##########
#frame for entire window
MainFrame = Frame(master=window)
MainFrame.pack(side=LEFT, fill=BOTH, expand=1)

#canvas for everything
MainCanvas = Canvas(master=MainFrame)
VScrollbar = Scrollbar(master=MainFrame, orient=VERTICAL, command=MainCanvas.yview)
HScrollbar = Scrollbar(master=MainFrame, orient=HORIZONTAL, command=MainCanvas.xview)
#scrollbar
VScrollbar.pack(side=RIGHT, fill=Y)
HScrollbar.pack(side=BOTTOM, fill=X)

#Frame for everything
ContentFrame= Frame(MainCanvas)
MainCanvas.create_window((0,0), window=ContentFrame, anchor=NW)
MainCanvas.configure(xscrollcommand=HScrollbar.set, yscrollcommand=VScrollbar.set)
MainCanvas.pack(side=LEFT, fill=BOTH, expand=1)

#App Title
AppTitleLabel = Label(ContentFrame, text="HOTELOPOLIS", font=("Arial", 40), anchor=CENTER)
AppTitleLabel.grid(row=0, column=1)

#Filter frame for filtering hotels
# Function for scrolling using mouse wheel
def _on_mouse_wheel(event):
    MainCanvas.yview_scroll(-1 * int((event.delta / 120)), "units")

#Mouse Wheel scrolling implementation
MainCanvas.configure(yscrollcommand=VScrollbar.set)
MainCanvas.bind('<Configure>', lambda e: MainCanvas.configure(scrollregion = MainCanvas.bbox("all")))
MainCanvas.bind_all("<MouseWheel>", _on_mouse_wheel)

#Filter Frame
FilterFrame = Frame(master=ContentFrame, highlightbackground=Framecolor, highlightthickness=1, padx=10, pady=5)

#Recommendation frame for recommended hotels
RecommendationFrame = Frame(master=ContentFrame, highlightbackground=Framecolor, highlightthickness=1,padx=10, pady=5)

#Frame for hotel buttons, hotel info
MainMenuFrame = Frame(master=ContentFrame)

#Frame for hotel details
HotelDetailsFrame = Frame(master=ContentFrame, highlightbackground=Framecolor, highlightthickness=1,padx=10, pady=5)

#Frame for display of hotel name, and bookmark and address
HotelDescriptionFrame = Frame(master=HotelDetailsFrame)
HotelDescriptionFrame.grid(row=0, column=0, sticky=NW)

#Frame for display of hotel name, and bookmark
HotelNameFrame = Frame(master=HotelDescriptionFrame)
HotelNameFrame.grid(row=0, column=0, sticky=NW)

#Frame for reviews
HotelPicturesFrame =  Frame(master=HotelDetailsFrame, highlightbackground=Framecolor, highlightthickness=1, padx=10, pady=5)
HotelPicturesFrame.grid(row=1, column=0, sticky=NSEW)

#Frame for main picture
HotelMainPictureFrame =  Frame(master=HotelPicturesFrame, padx=10)
HotelMainPictureFrame.grid(row=0, column=0, sticky=NW)

#Frame for small pictures
HotelSmallPicturesFrame =  Frame(master=HotelPicturesFrame)
HotelSmallPicturesFrame.grid(row=0, column=1, sticky=NW)

#Hotel Main Image Label
HotelMainImage = Label(HotelMainPictureFrame, text="Main pic", width=30, height=20, highlightbackground=Framecolor, highlightthickness=1, padx=10, pady=10)
HotelMainImage.grid(row=0, column=0)

#Hotel Main Image Label
HotelSmallImageOne = Label(HotelSmallPicturesFrame, text="small pic", width=10, height=10, highlightbackground=Framecolor, highlightthickness=1, padx=10, pady=10)
HotelSmallImageOne.grid(row=0, column=0)

#Hotel Main Image Label
HotelSmallImageTwo = Label(HotelSmallPicturesFrame, text="small pic", width=10, height=10, highlightbackground=Framecolor, highlightthickness=1, padx=10, pady=10)
HotelSmallImageTwo.grid(row=1, column=0)

#Hotel Main Image Label
HotelSmallImageThree = Label(HotelSmallPicturesFrame, text="small pic", width=10, height=10, highlightbackground=Framecolor, highlightthickness=1, padx=10, pady=10)
HotelSmallImageThree.grid(row=1, column=1)

#Frame for reviews
HotelReviewFrame =  Frame(master=HotelDetailsFrame)
HotelReviewFrame.grid(row=2, column=0, sticky=NW)

#Recommendation Label
RecommendationLabel = Label(RecommendationFrame, text="You may also like:")
RecommendationLabel.grid(row=0, column=0)

#Back to menu Button
MenuButton = Button(ContentFrame, text="Back To Menu", command=DisplayMainMenu,font=("Arial", 10), relief=GROOVE)

#Hotel name label in display hotel options
HotelNameLabel = Label(HotelNameFrame, font=("Arial", 30))
HotelNameLabel.grid(row=0, column=0, sticky=NW)

#Address label in display hotel options
AddressLabel = Label(HotelDescriptionFrame, text="",font=("Arial", 15))
AddressLabel.grid(row=1, column=0, sticky=NW)

# heading for reviews
ReviewListHeaderText = Label(HotelReviewFrame, text="Reviews", font=("Arial", 15))
ReviewListHeaderText.grid(row=0, column=0, sticky=NW)

#Address label in display hotel options
FacilitiesLabel = Label(HotelDescriptionFrame, text="",font=("Arial", 15))
FacilitiesLabel.grid(row=2, column=0, sticky=NW)

#average star review label in display hotel options
AverageScoreLabel = Label(HotelDescriptionFrame, text="",font=("Arial", 15))
AverageScoreLabel.grid(row=3, column=0, sticky=NW)

#No results label in main menu
Emptylabel = Label(MainMenuFrame,text="No Results", font=("Arial", 20), width=37)

#filter options
FilterLabel = Label(FilterFrame, text="Filters", font=("Arial", 20))
#filter variables
restaurant=StringVar()
jacuzzi=StringVar()
pool=StringVar()
gym=StringVar()
spa=StringVar()

#Label for ameneties and checkboxes for ameneties filter
AmenitiesLabel = Label(FilterFrame, text="Amenities", font=("Arial", 15))
RestaurantFilter = Checkbutton(FilterFrame, text="Restaurant", variable=restaurant, onvalue="restaurant", offvalue= "na", command=FilterAndSortHotelDetails)
JacuzziFilter = Checkbutton(FilterFrame, text="Jacuzzi", variable=jacuzzi, onvalue="jacuzzi", offvalue= "na", command=FilterAndSortHotelDetails)
PoolFilter = Checkbutton(FilterFrame, text="Pool", variable=pool, onvalue="pool", offvalue= "na", command=FilterAndSortHotelDetails)
GymFilter = Checkbutton(FilterFrame, text="Gym", variable=gym, onvalue="gym", offvalue= "na", command=FilterAndSortHotelDetails)
SpaFilter = Checkbutton(FilterFrame, text="Spa", variable=spa, onvalue="spa", offvalue= "na", command=FilterAndSortHotelDetails)
#deselect checkboxes, string var makes it select by default
RestaurantFilter.deselect()
JacuzziFilter.deselect()
PoolFilter.deselect()
GymFilter.deselect()
SpaFilter.deselect()

#Label for ratings and checkboxes for rating filter
RatingLabel = Label(FilterFrame, text="Rating", font=("Arial", 15))
onestar=IntVar()
twostar=IntVar()
threestar=IntVar()
fourstar=IntVar()
fivestar=IntVar()

OneStarFilter = Checkbutton(FilterFrame, text="1 Star", variable=onestar, onvalue=1, offvalue= 0, command=FilterAndSortHotelDetails)
TwoStarFilter = Checkbutton(FilterFrame, text="2 Stars", variable=twostar, onvalue=2, offvalue= 0, command=FilterAndSortHotelDetails)
ThreeStarFilter = Checkbutton(FilterFrame, text="3 Stars", variable=threestar, onvalue=3, offvalue= 0, command=FilterAndSortHotelDetails)
FourStarFilter = Checkbutton(FilterFrame, text="4 Stars", variable=fourstar, onvalue=4, offvalue= 0, command=FilterAndSortHotelDetails)
FiveStarFilter = Checkbutton(FilterFrame, text="5 Stars", variable=fivestar, onvalue=5, offvalue= 0, command=FilterAndSortHotelDetails)

FilterLabel.grid(row=0, column=0, sticky=W)
AmenitiesLabel.grid(row=1, column=0, sticky=W)
RestaurantFilter.grid(row=2, column=0, sticky=W)
JacuzziFilter.grid(row=3, column=0, sticky=W)
PoolFilter.grid(row=4, column=0, sticky=W)
GymFilter.grid(row=5, column=0, sticky=W)
PoolFilter.grid(row=6, column=0, sticky=W)
SpaFilter.grid(row=7, column=0, sticky=W)
RatingLabel.grid(row=8, column=0, sticky=W)
OneStarFilter.grid(row=9, column=0, sticky=W)
TwoStarFilter.grid(row=10, column=0, sticky=W)
ThreeStarFilter.grid(row=11, column=0, sticky=W)
FourStarFilter.grid(row=12, column=0, sticky=W)
FiveStarFilter.grid(row=13, column=0, sticky=W)

# set default value of sort
SortVariable = StringVar()
SortVariable.set(MainMenuSortOptions[0])
#add frame for sort widgets
SortFrame = Frame(master=MainMenuFrame, padx=10, pady=5)
SortFrame.grid(row=0, column=0, sticky=NW)
SortLabel = Label(SortFrame, text="Sort by:", font=("Arial", 14))
SortLabel.grid(row=0, column=0, sticky=NW)
#create sort dropdown
SortDropdown = OptionMenu(SortFrame, SortVariable, *MainMenuSortOptions, command=FilterAndSortHotelDetails)
SortDropdown.grid(row=0, column=1, sticky=NW)
add_hotel = Button(MainMenuFrame, text = "Add Hotel", command= open_popup)
add_hotel.grid(row=0, column=0, sticky=E, padx=10)

#set default value for bookmark widget
BookmarkNameVariable = StringVar()
BookmarkNameVariable.set("Bookmarks")
if (len(BookmarkedHotelsNameList) == 0): #give default list of bookmarks no bookmarks if no bookmarked hotels
    BookmarkedHotelsNameList.append("No Bookmarks")
# create bookmark dropdown
BookmarkDropdown = OptionMenu(ContentFrame, BookmarkNameVariable, *BookmarkedHotelsNameList, command=SelectFromBookmark)
BookmarkDropdown.grid(row=0, column=0, sticky=W, padx=40)

#bookmarked checkbutton in display hotel details
BookmarkedVariable = BooleanVar()
BookmarkedButton = Checkbutton(HotelNameFrame, text="Bookmarked", variable=BookmarkedVariable, onvalue=1, offvalue= 0, command=ToggleBookmark)
BookmarkedButton.grid(row=0, column=1, sticky=W)

#Show analysis
ShowAnalysisButton = Button(HotelNameFrame, text = "Show analysis", command=showAnalysis)
ShowAnalysisButton.grid(row=0, column=2)

#Show keywords
ShowEmotionButton = Button(HotelNameFrame, text = "Show keywords", command=showEmotions)
ShowEmotionButton.grid(row=0, column=3)

#add frame for sort widgets
ReviewFilterFrame = Frame(master=HotelReviewFrame, pady=5)
ReviewFilterFrame.grid(row=1, column=0, sticky=NSEW)
ReviewFilterLabel = Label(ReviewFilterFrame, text="Filter by:", font=("Arial", 10))
ReviewFilterLabel.grid(row=0, column=0, sticky=NW)
#create sort dropdown
ReviewFilterVariable = StringVar()
ReviewFilterVariable.set(ReviewFilterOptions[0])
FilterReviewDropdown = OptionMenu(ReviewFilterFrame, ReviewFilterVariable, *ReviewFilterOptions, command=FilterReviews)
FilterReviewDropdown.grid(row=0, column=1, sticky=NW)

#sort and filter main menu based on default values
FilterAndSortHotelDetails(SortVariable)
#show main menu widgets
DisplayMainMenu()
window.mainloop()


import random
import string

from autoslug import AutoSlugField
from django.contrib.auth import get_user_model
from django.core.validators import MinValueValidator
from django.db import models
from django.utils.translation import gettext_lazy as _
from django_countries.fields import CountryField

from apps.common.models import TimeStampedUUIDModel

User = get_user_model()

class PropertyPublishedManager(models.Manager):
    def get_queryset(self):
        return (
            super(PropertyPublishedManager, self)
            .get_queryset()
            .filter(published_status=True)
        )

class Property(TimeStampedUUIDModel):
    class PropertyType(models.TextChoices):
        HOUSE = "House", _("House")
        APARTMENT = "Apartment", _("Apartment")
        OFFICE = "Office", _("Office")
        WAREHOUSE = "Warehouse", _("Warehouse")
        COMMERCIAL = "Commercial", _("Commercial")
        OTHER = "Other", _("Other")

    class AdvertType(models.TextChoices):
        FOR_SALE = "For Sale", _("For Sale")
        FOR_RENT = "For Rent", _("For Rent")
        FOR_AUCTION = "For Auction", _("For Auction")

    user = models.ForeignKey(
        User,
        verbose_name=_("Agent, seller, or Buyer"),
        related_name="agent_or_buyer",
        on_delete=models.DO_NOTHING,
    )
    title = models.CharField(verbose_name=_("Property title"), max_length=250)
    slug = AutoSlugField(populate_from="title", unique=True, always_update=True)
    ref_code = models.CharField(
        verbose_name=_("Property Reference Code"),
        max_length=255,
        unique=True,
        blank=True,
    )
    description = models.TextField(
        verbose_name=_("Description"), default="Default description..."
    )
    country = CountryField(verbose_name=_("Country"), blank_label="Select country")
    city = models.CharField(verbose_name=_("City"), max_length=100)
    postal_code = models.CharField(verbose_name=_("Postal code"), max_length=10)
    street_address = models.CharField(verbose_name=_("Street address"), max_length=150)
    property_number = models.IntegerField(
        verbose_name=_("Property number"), validators=[MinValueValidator(1)]
    )
    price = models.DecimalField(
        verbose_name=_("Price"), max_digits=12, decimal_places=2
    )
    tax = models.DecimalField(
        verbose_name=_("Tax"),
        max_digits=6,
        decimal_places=2,
        default=0.05,
        help_text=_("Tax upon property price"),
    )
    plot_area = models.DecimalField(
        verbose_name=_("Plot area (m^2)"), max_digits=10, decimal_places=2, default=0.0
    )
    number_of_floors = models.IntegerField(
        verbose_name=_("Number of floors"), default=0
    )
    number_of_bedrooms = models.IntegerField(
        verbose_name=_("Number of bedrooms"), default=0
    )
    number_of_bathrooms = models.IntegerField(
        verbose_name=_("Number of bathrooms"), default=0
    )
    property_type = models.CharField(
        verbose_name=_("Property type"),
        max_length=50,
        choices=PropertyType.choices,
        default=PropertyType.OTHER,
    )
    advert_type = models.CharField(
        verbose_name=_("Advert type"),
        max_length=50,
        choices=AdvertType.choices,
        default=AdvertType.FOR_SALE,
    )
    cover_image = models.ImageField(
        verbose_name=_("Cover image"),
        default="/sample_property_cover_image.jpg",
        null=True,
        blank=True,
    )
    image1 = models.ImageField(
        verbose_name=_("Image 1"),
        default="/sample_property_image1.jpg",
        null=True,
        blank=True,
    )
    image2 = models.ImageField(
        verbose_name=_("Image 2"),
        default="/sample_property_image2.jpg",
        null=True,
        blank=True,
    )
    image3 = models.ImageField(
        verbose_name=_("Image 3"),
        default="/sample_property_image3.jpg",
        null=True,
        blank=True,
    )
    image4 = models.ImageField(
        verbose_name=_("Image 4"),
        default="/sample_property_image4.jpg",
        null=True,
        blank=True,
    )
    published_status = models.BooleanField(
        verbose_name=_("Published status"), default=False
    )
    views = models.IntegerField(verbose_name=_("Number of views"), default=0)

    objects = models.Manager()
    published = PropertyPublishedManager()

    class Meta:
        verbose_name = "Property"
        verbose_name_plural = "Properties"

    def __str__(self):
        return self.title

    def save(self, *args, **kwargs):
        self.title = str.title(self.title)
        self.description = str.capitalize(self.description)
        self.ref_code = "".join(
            random.choices(string.ascii_uppercase + string.digits, k=20)
        )
        super(Property, self).save(*args, **kwargs)

    @property
    def final_property_price(self):
        tax_percentage = self.tax
        property_price = self.price
        tax_amount = round(tax_percentage * property_price, 2)
        price_after_tax = float(round(property_price + tax_amount, 2))
        return price_after_tax

class PropertyView(TimeStampedUUIDModel):
    viewer_ip = models.CharField(verbose_name=_("Viewer IP address"), max_length=250)
    property = models.ForeignKey(
        Property, related_name="property_views", on_delete=models.CASCADE
    )

    def __str__(self):
        return f"Total views on {self.property.title} is {self.property.views}"

    class Meta:
        verbose_name = "Total views on Property"
        verbose_name_plural = "Total Property Views"


import hexchat, urllib2, json

__module_name__ = "Currency"
__module_version__ = "1.0"
__module_description__ = "A currency converter plugin for hexchat"

def convert(amt, fro, to):
	p = str(fro+"_"+to)
	f = urllib2.urlopen('http://www.freecurrencyconverterapi.com/api/v2/convert?q='+p+'&compact=y')
	q = json.loads(f.read())
	if(p in q or p.upper() in q):
		a = q[p.upper()]['val']
		b = float(a)*float(amt)
		print(str(amt)+" "+fro+" is "+str(b)+" "+to)
		return hexchat.EAT_ALL
	else:
		print("Usage: /convert <amount> <from> <to>")
		return hexchat.EAT_ALL

def getParam(word, word_eol, userdata):
	del word[0]
	convert(word[0], word[1], word[2])

hexchat.hook_command('convert', getParam, help="Converts currencies")


import multiprocessing as mp
import os
import time

import math
import numpy as np
import pandas as pd

def procesa_totales(diccionario):
    for key, value in diccionario.items():
        if type(value) == str:
            try:
                diccionario[key] = int(value)
            except:
                diccionario[key] = None
        elif math.isnan(value):
            diccionario[key] = None

    return diccionario

def obtener_poblacion(carpeta):
    estados = []
    for subdir, dirs, files in os.walk(carpeta):
        for file in files:
            if file.endswith('.xls'):
                archivo = os.path.join(carpeta, file)
                estados.append(archivo)
    return estados

def cargar_poblacion(archivo):
    start_time = time.time()
    import django
    django.setup()
    from humanitaria.models import Entidad
    dfs = pd.read_excel(archivo,
                        dtype={
                            'ENTIDAD': str,
                            'MUN': str,
                            'LOC': str,
                            'AGEB': str,
                            'MZA': str
                        },
                        sheet_name=None)
    # Combina todos las hojas del excel en un solo dataframe
    df = pd.DataFrame()
    for _, sheet in dfs.items():
        df = df.append(sheet)
    columnas = list(df.columns)[8:]

    df = df.replace('*', np.nan)
    entidad = Entidad.objects.filter(cve_ent=df['ENTIDAD'].iloc[0])
    df_entidad_totales = df[df['NOM_LOC'].str.contains('total de la '
                                                       'entidad',
                                                       regex=False,
                                                       case=False,
                                                       na=False)]
    totales_entidad = df_entidad_totales[columnas].to_dict(
        'records')
    entidad.update(**procesa_totales(totales_entidad[0]))

    df_municipio_totales = df[df['NOM_LOC'].str.contains('total del '
                                                         'municipio',
                                                         regex=False,
                                                         case=False,
                                                         na=False)]
    for i, row in df_municipio_totales.iterrows():
        entidad = Entidad.objects.get(cve_ent=df['ENTIDAD'].iloc[0])
        municipio = entidad.municipio_set.filter(cve_mun=str(row[
                                                                 'MUN'])
                                                 )
        totales_municipio = row[columnas].to_dict()
        municipio.update(**procesa_totales(totales_municipio))

    df_localidades_totales = df[df['NOM_LOC'].str.contains('total de '
                                                           'la '
                                                           'localidad '
                                                           'urbana',
                                                           regex=False,
                                                           case=False,
                                                           na=False)]
    for i, row in df_localidades_totales.iterrows():
        entidad = Entidad.objects.get(cve_ent=df['ENTIDAD'].iloc[0])
        municipio = entidad.municipio_set.get(cve_mun=str(row['MUN']))
        localidad = municipio.localidad_set.filter(cve_loc=str(row[
                                                                   'LOC'])
                                                   )
        totales_localidad = row[columnas].to_dict()
        localidad.update(**procesa_totales(totales_localidad))

    df_agebu_totales = df[df['NOM_LOC'].str.contains('total ageb '
                                                     'urbana',
                                                     regex=False,
                                                     case=False,
                                                     na=False)]
    for i, row in df_agebu_totales.iterrows():
        entidad = Entidad.objects.get(cve_ent=df['ENTIDAD'].iloc[0])
        municipio = entidad.municipio_set.get(cve_mun=str(row['MUN']))
        # No existe San Jose Vieno en BJS 2047
        try:
            localidad = municipio.localidad_set.get(cve_loc=str(
                row['LOC']))
            agebu = localidad.agebu_set.filter(cve_ageb=str(
                row['AGEB']))
            totales_agebu = row[columnas].to_dict()
            agebu.update(**procesa_totales(totales_agebu))
        except:
            pass

    df_manzanas_totales = df[~df['NOM_LOC'].str.contains('total',
                                                         regex=False,
                                                         case=False,
                                                         na=False)]
    for i, row in df_manzanas_totales.iterrows():
        entidad = Entidad.objects.get(cve_ent=df['ENTIDAD'].iloc[0])
        municipio = entidad.municipio_set.get(cve_mun=str(row['MUN']))
        try:
            localidad = municipio.localidad_set.get(cve_loc=str(
                row['LOC']))
            # En aguascalientes no hay ageb 1301 para mun 01 loc 001
            try:
                ageb = localidad.agebu_set.get(cve_ageb=str(
                    row['AGEB']))
            except:
                try:
                    ageb = municipio.agebr_set.get(cve_ageb=str(
                        row['AGEB']))
                except:
                    pass
            manzana = ageb.manzana_set.filter(cve_mza=str(row['MZA']))
            totales_manzana = row[columnas].to_dict()
            manzana.update(**procesa_totales(totales_manzana))
        except:
            pass
        final = time.time() - start_time
        return archivo, final

def paralelo_carga_poblacion(carpeta):
    start_time = time.time()
    print(f"Inicio : {time.ctime()}\n")
    n = mp.cpu_count()
    print(f"Número de procesadores: {n}\n")
    pool = mp.Pool(n)
    poblacion = obtener_poblacion(carpeta)
    results = [pool.apply_async(cargar_poblacion, args=(i,)) for i in
               poblacion]
    pool.close()
    for ele in results:
        s = ele.get()
        print(f'Archivo: {s[0]}\nFinalizado en: {s[1]} segundos\n')
    print(f"Final: {time.ctime()}\n")
    final = time.time() - start_time
    print(f'Procesamiento en paralelo terminado en: {final} segundos')

def secuencial_carga_poblacion(carpeta):
    start_time = time.time()
    print(f"Inicio : {time.ctime()}\n")
    poblacion = obtener_poblacion(carpeta)
    results = [cargar_poblacion(i) for i in poblacion]
    print(f"Final: {time.ctime()}\n")
    print(results)
    final = time.time() - start_time
    print(f'Procesamiento secuencial terminado en: {final} segundos')

def carga_poblacion(carpeta, paralelo=True):
    if paralelo:
        paralelo_carga_poblacion(carpeta)
    else:
        secuencial_carga_poblacion(carpeta)

if __name__ == "__main__":
    folder = 'data/poblacionales'
    carga_poblacion(folder)


from pygments.token import String
from pygments.lexer import RegexLexer

class RainbowLinesLexer(RegexLexer):
    name = 'Rainbow Lines'
    aliases = ['rainbow-lines']
    filenames = ['*.rainbow-lines']

    tokens = {
        'root': [(r'.*\n', String.Affix, '2')],
        '2': [(r'.*\n', String.Backtick, '3')],
        '3': [(r'.*\n', String.Char, '4')],
        '4': [(r'.*\n', String.Doc, '5')],
        '5': [(r'.*\n', String.Escape, '6')],
        '6': [(r'.*\n', String.Interpol, '7')],
        '7': [(r'.*\n', String.Symbol, 'root')],
    }

class RainbowTwoLinesLexer(RegexLexer):
    name = 'Rainbow Two Lines'
    aliases = ['rainbow-2-lines']
    filenames = ['*.rainbow-2-lines']

    tokens = {
        'root': [(r'.*\n.*\n', String.Affix, '2')],
        '2': [(r'.*\n.*\n', String.Backtick, '3')],
        '3': [(r'.*\n.*\n', String.Char, '4')],
        '4': [(r'.*\n.*\n', String.Doc, '5')],
        '5': [(r'.*\n.*\n', String.Escape, '6')],
        '6': [(r'.*\n.*\n', String.Interpol, '7')],
        '7': [(r'.*\n.*\n', String.Symbol, 'root')],
    }


# -*- coding: utf-8 -*-
"""
Created on Sun Oct 20 01:26:47 2019

@author: LABA
"""

import pandas as pd
from sklearn.preprocessing import LabelEncoder
from sklearn.model_selection import train_test_split
from keras.layers import Input, Embedding, Dense, Flatten, dot, BatchNormalization, Dropout
from keras.models import Model, load_model
import numpy as np

def train_test_split_fuc(data):

    train, tt = train_test_split(data, test_size=0.3)

    vlidation, test = train_test_split(tt, test_size=0.5)

    return train, vlidation, test

ratings = pd.read_csv('ratings.csv')

label  = LabelEncoder()
ratings.userId = pd.DataFrame({'userId':ratings['userId'].values}).apply(label.fit_transform)
ratings.movieId = pd.DataFrame({'movieId':ratings['movieId'].values}).apply(label.fit_transform)

row = list(ratings['userId'].unique())
clo = list(ratings['movieId'].unique())

row = sorted(row)
clo = sorted(clo)

matrix = pd.pivot_table(data = ratings, values='rating', index='userId', columns='movieId')
matrix.fillna(0, inplace=True)

users = ratings.userId.unique()
movies = ratings.movieId.unique()

userid2idx = {o:i for i, o in enumerate(users)}
movieid2idx = {o:i for i, o in enumerate(movies)}

ratings['userId'] = ratings['userId'].apply(lambda x: userid2idx[x])
ratings['movieId'] = ratings['movieId'].apply(lambda x: movieid2idx[x])

train, val , test = train_test_split_fuc(ratings)

user_input = Input(shape=(1,), name='user_input')
user_embedding = Embedding(len(users), 100, name='user_embedding')(user_input)
user_vec = Flatten(name='user_vec')(user_embedding)
user_batch = BatchNormalization(name='user_batch')(user_vec)

movie_input = Input(shape=(1,), name='movies_input')
movie_embedding = Embedding(len(movies), 100, name='movie_embeddubg')(movie_input)
movie_vec = Flatten(name='movie_vec')(movie_embedding)
movie_batch = BatchNormalization(name='movie_batch')(movie_vec)

sim = dot([user_batch, movie_batch], name='sim', axes=1)

dense = Dense(100, activation='relu', name='dense1')(sim)
dense = BatchNormalization(name='bn1')(dense)
dense = Dropout(0.3)(dense)
dense = Dense(1, activation='relu')(dense)

model = Model([user_input, movie_input], dense)

model.compile(optimizer='Adam', loss='mse', metrics=['acc'])
model.summary()

#history = model.fit([train.userId, train.movieId], train.rating,
#                    validation_data=([val.userId, val.movieId], val.rating),
#                    batch_size=32,
#                    epochs=10,
#                    verbose=1)
#
#model.save('LR_CF.h5')

model = load_model('LR_CF.h5')

movie_data = np.array(list(set(ratings.movieId)))[0:4]
user_data = np.array(list(14 for i in range(len(movie_data))))

predictions = model.predict([user_data, movie_data])
predictions = np.array([a[0] for a in predictions])
recommended_movie_ids = (-predictions).argsort()[:]
print(recommended_movie_ids)
print(predictions[recommended_movie_ids])


import json
from itertools import count
from chatterbot.trainers import ListTrainer
from chatterbot.trainers import UbuntuCorpusTrainer

def ToString(s):
    # initialize an empty string
    str1 = " "
    # return string
    return (str1.join(s))

def inputdata(file='intents.json'):
    """Process the input data to a list of statements.

    Parameters
    ----------
    file : str
        The path to the input file.

    Returns
    -------
    list
        A list of statements representing a conversation.
    """
    with open(file, 'r') as f:
        dataset = json.load(f)

    if file == 'english-train.json':
        statements = []
        for conversation in dataset:
            question = conversation['utterances'][0].lower().split('patient:')[1]
            fullstop_questions = question.split('.')

            answer = conversation['utterances'][1].lower().split('doctor:')[1]

            for f_question in fullstop_questions:
                statements.append([f_question, answer])

            statements.append([question, answer])

        return statements

    elif file == 'train_light.json':
        statements = []
        for obj in dataset:
            annotation_dict = obj['annotations'][0]
            question_type = annotation_dict['type']
            if question_type == 'multipleQAs':
                question_objs = annotation_dict['qaPairs']
                for obj in question_objs:
                    question = obj['question'].lower()
                    answer = obj['answer'][0].lower()
                    statements.append([question, answer])
            elif question_type == 'singleAnswer':
                question = obj['question'].lower()
                annotation_dict = obj['annotations'][0]
                answer = annotation_dict['answer'][0].lower()
                statements.append([question, answer])

    elif file == 'intents.json':
        statements = []
        obj = dataset['intents']

        for intent in obj:
            questions = intent['patterns']
            answer = intent['responses']

            for question, answer in zip(questions, answer):
                statements.append([question.lower(), answer.lower()])

        return statements

# hyperparameters
iter = 10

def trainbotbylist(chatbot, dataset='english-train.json'):
    """Train the chatbot using ListTrainer on a specific dataset.

    Parameters
    ----------
    chatbot : ChatBot
        A chatbot instance.
    dataset : str
        The path to the input file.
    """
    trainer = ListTrainer(chatbot)
    data = inputdata(dataset)
    iterator = (count(start=1, step=1))

    for conversation in data:
        trainer.train(conversation)
        statement_count = next(iterator)

    print(f'Successfully trained bot with {statement_count} conversations')

def trainbotbyubuntu(chatbot, iter):
    if(iter == 0):
        return "Sucessfully Trained Chatbot"
    iter -= 1
    trainer = UbuntuCorpusTrainer(chatbot)
    trainer.train()
    print("training the chatbot , iteration No:-" + str(iter))
    trainbotbyubuntu(chatbot, iter)


import os
import pandas as pd
import glob
import SimpleITK as sitk
from sklearn.metrics import f1_score

HOMEDIR = os.path.expanduser('~/')
mediaflux = HOMEDIR + 'mediaflux/'

if not os.path.exists(mediaflux):
    mediaflux = 'Z:/'

directory = mediaflux + 'data_freda/ctp_project/CTP_DL_Data/'
semi_masks = [file for file in glob.glob(directory + 'no_seg/masks_semi/*')
              if ('exclude' not in file and 'funny' not in file)]
masks = [file for file in glob.glob(directory + 'no_seg/masks/*')
         if 'exclude' not in file]
subjects = ['INSP_' + sub.split('.nii')[0].split('_')[-1] for sub in semi_masks]

# # running for cases that james and chrissy did
# masks = [file for file in glob.glob(mediaflux  + 'data_freda/dl_seg_check/*pred*')]
# semi_masks = [file for file in glob.glob(mediaflux  + 'data_freda/dl_seg_check/*seg*')]

# subjects = ['INSP_' + sub.split('.nii')[0].split('_')[-2] for sub in semi_masks]
subjects.sort()

df = pd.DataFrame(columns=["subject",
                           "volume_gt",
                           "volume_pred",
                           "abs_diff",
                           "perc_diff",
                           "dsc",
                           "overcall",
                           "undercall",
                           "blood",
                           ])
df.subject = subjects

for sub in subjects:
    print(f"Running for {sub}")
    semi_mask = sitk.ReadImage([file for file in semi_masks if sub in file][0])
    spacing = semi_mask.GetSpacing()
    voxel_ml = spacing[0] * spacing[1] * spacing[2] / 1000
    labelStats = sitk.LabelShapeStatisticsImageFilter()

    labelStats.SetBackgroundValue(0)
    labelStats.Execute(semi_mask)
    try:
        size_lesion = len(labelStats.GetIndexes(1)) * voxel_ml
    except RuntimeError:
        size_lesion = 0.
    df.loc[df.subject == sub, 'volume_gt'] = round(size_lesion, 1)

    mask = sitk.Cast(
        sitk.ReadImage([file for file in masks if sub in file][0]), sitk.sitkUInt8)
    labelStats.Execute(mask)
    try:
        size_prediction = len(labelStats.GetIndexes(1)) * voxel_ml
    except RuntimeError:
        size_prediction = 0.
    df.loc[df.subject == sub, 'volume_pred'] = round(size_prediction, 1)

    diff = size_prediction - size_lesion
    if diff < 0:
        df.loc[df.subject == sub, 'undercall'] = 1
        df.loc[df.subject == sub, 'overcall'] = 0
    elif diff > 0:
        df.loc[df.subject == sub, 'undercall'] = 0
        df.loc[df.subject == sub, 'overcall'] = 1
    else:
        df.loc[df.subject == sub, 'undercall'] = 0
        df.loc[df.subject == sub, 'overcall'] = 0

    if not size_lesion == 0:
        perc = abs(diff)/size_lesion * 100
    else:
        perc = 0

    df.loc[df.subject == sub, 'abs_diff'] = round(abs(diff), 1)
    df.loc[df.subject == sub, 'perc_diff'] = round(perc, 1)

    # dice
    array_semi = sitk.GetArrayFromImage(semi_mask).flatten()
    array_mask = sitk.GetArrayFromImage(mask).flatten()
    f1 = f1_score(array_mask, array_semi)
    df.loc[df.subject == sub, 'dsc'] = round(f1, 3)

df.sort_values(by='subject', inplace=True)

# df.to_csv('../study_design/study_lists/no_seg_stats.csv', index=False)
df.to_csv('../study_design/study_lists/no_seg_stats_densenet.csv', index=False)

keys = ["volume_gt", "volume_pred", "abs_diff", "perc_diff", "dsc"]

for key in keys:
    df[key] = df[key].apply(pd.to_numeric, errors='coerce')

df_blood = pd.read_csv('../study_design/study_lists/no_seg_stats_with_blood.csv')

import seaborn as sns

import matplotlib.pyplot as plt

fig = plt.figure()
ax = sns.scatterplot(
    x=df_blood.subject.to_list(),
    y=df_blood.abs_diff.to_list(),
    hue=df_blood.blood.to_list())
plt.legend(["any blood", "no blood"])

ax.set(ylabel="volume diff", ylim=(0, 100), xticks='')
plt.show()


#encoding=utf-8
import numpy as np
import operator
import matplotlib.pyplot as plt
from matplotlib.font_manager import FontProperties#解决显示中文问题
import matplotlib.lines as mlines
def create():
    group = np.array([[1.0,1.1],[1.0,1.0],[0,0],[0,0.1]])
    labels = ['A','A','B','B']
    return  group,labels

#文件数据转化为矩阵
def file2matric(filename):
    f = open(filename,'r')
    arr = f.readlines()
    num_row = len(arr)
    returnMatric  = np.zeros((num_row,3))
    labelVictor = []
    index = 0
    for line in arr:
        line = line.strip()
        lineFromline = line.split('\t')
        returnMatric[index,:] = lineFromline[0:3]#index 只是表示第index+1行
        labelVictor.append(int(lineFromline[-1]))#将标签量转化为数字向量
        index +=1
    return returnMatric,labelVictor#返回矩阵和标签向量

#matplotlib绘制数据图
def showdata(returnMatric,returnVictor):
    font_set = FontProperties(fname=r"c:\windows\fonts\simsun.ttc", size=15)  # 找到中文字体
    fig,axs = plt.subplots(2,2,sharey=False,sharex=False,figsize = (12,8))
    numlabel = len(returnVictor)
    colors = []
    for i in returnVictor:
        if i==1:
            colors.append('red')
        elif i==2:
            colors.append('orange')
        elif i==3:
            colors.append('black')
    #绘制图例，由于带有不同的标签，总会一次性绘制出图形，不同类别的图例标签无法表示，通过自己添加空数据类型，分类出实例
    #玩游戏、每周消费的冰激凌数目占比
    axs[0][0].scatter(returnMatric[:, 1], returnMatric[:, 2],c=colors)
    type1 = axs[0][0].scatter([],[],c='red',label = 'didntLike')
    type2 = axs[0][0].scatter([],[], c='orange',label = 'smallDoses')
    type3 = axs[0][0].scatter([],[], c='black',label = 'smallDoses')
    axs[0][0].set_title(u'玩游戏、每周消费的冰激凌数目占比',fontproperties = font_set,color = 'r')
    axs[0][0].set_xlabel(u'玩游戏', fontproperties=font_set,color = 'k')
    axs[0][0].set_ylabel(u'冰激凌数目', fontproperties=font_set,color = 'k')
    # 设置图例
    axs[0][0].legend(handles=[type1, type2, type3], labels=['didntLike', 'smallDoses', 'smallDoses'], loc='upper right')
    #飞行常客里程数与玩游戏
    axs[0][1].scatter(returnMatric[:, 0], returnMatric[:, 1], c=colors)
    axs[0][1].set_title(u'飞行常客里程数与玩游戏占比', fontproperties=font_set, color='r')
    axs[0][1].set_xlabel(u'飞行常客里程数', fontproperties=font_set, color='k')
    axs[0][1].set_ylabel(u'玩游戏', fontproperties=font_set, color='k')
    # 设置图例
    axs[0][1].legend(handles=[type1, type2, type3], labels=['didntLike', 'smallDoses', 'smallDoses'], loc='upper right')
    #飞行常客里程数与冰激凌
    axs[1][0].scatter(returnMatric[:, 0], returnMatric[:, 2], c=colors)
    axs[1][0].set_title(u'飞行常客里程数与冰激凌占比', fontproperties=font_set, color='r')
    axs[1][0].set_xlabel(u'飞行常客里程数', fontproperties=font_set, color='k')
    axs[1][0].set_ylabel(u'冰激凌', fontproperties=font_set, color='k')
    # 设置图例
    axs[1][0].legend(handles=[type1, type2, type3], labels=['didntLike', 'smallDoses', 'smallDoses'], loc='upper right')
    plt.tight_layout()
    plt.show()

#归一化数据
def autoNormal(dataset):
    min = dataset.min(0)
    max = dataset.max(0)
    range = max-min
    m = dataset.shape[0]
    normal = np.zeros(np.shape(dataset))
    #tile(A,reps)参数A是一个数组（多维或一维）
    # rep参数是一个元组，里面有几个数，最右边的数代表A的最深的维度的元素应该重复的次数，往左边一点的数代表A的次深的维度应该重复的次数。
    normal_1 = dataset - np.tile(min,(m,1))
    normal_fin = normal_1/np.tile(range,(m,1))
    return normal_fin,min,range

#分类
def classify(A,dateSet,labels,k):
    dateSize = dateSet.shape[0]
    relation  = np.tile(A,(dateSize,1))-dateSet
    squar = relation**2
    result = (squar.sum(axis=1))**0.5
    sort_re= result.argsort()
    Count = {}
    #只需要统计结果
    for i in range(k):
        vote = labels[sort_re[i]]
        Count[vote] = Count.get(vote,0)+1
    #将统计结果排序,items函数，将一个字典以列表的形式返回，因为字典是无序的，所以返回的列表也是无序的。
    final = sorted(Count.items(),key=operator.itemgetter(1),reverse=True)
    return final[0][0]#获取具体的某个分类

#对于输入数据进行分类测试，得到错误率
def data_classify_test():
    ratio = 0.1
    returnmatric,returnvictor = file2matric('datingTestSet2.txt')
    normal,min,range = autoNormal(returnmatric)
    m = normal.shape[0]
    errorCount = 0
    num = int(m*ratio)
    for i in np.arange(num):#int数据不能迭代
        classify_result = classify(normal[i,:],normal[num:m,:],returnvictor[num:m],3)#调用分类器
        # print('classifier get\'s result is: %d,And real character is %d\n'\
        #       % (classify_result,returnvictor[i]))
        if (classify_result != returnvictor[i]):
            errorCount +=1
    print('classifier error ratio is:%f' %(errorCount/float(num)))#错误率表示错误数除以总数

#用户具体输入某一个人，从而判断出这个人属于的类别
def classify_person():
    result = ['hate','just soso','fatastic']
    plane = float(input('plan spend on distance：'))
    ice_cream = float(input('ice cream eat number ：'))
    game = float(input('video&game spend on time:'))
    returnmatric, returnvictor = file2matric('datingTestSet2.txt')
    normal, min, range = autoNormal(returnmatric)
    person = [plane,game,ice_cream]
    result_number = classify((person-min)/range,normal,returnvictor,3)
    if result_number==3:
        result = 'fatastic'
    elif result_number==2:
        result='just soso'
    elif result_number==1:
        result='hate'
    print('System judge the person belong: %s'%result)


#!/usr/bin/env python3
import pika
import socket

'''
  Usage:
    Receives all messages transmitted from "c_emit_log_fanout.py"
    1) start up a couple of c_receive_logs_fanout.py sessions
    2) send a message

    > python3 c_emit_log_fanout.py <some message>

    Both receivers should see the emitted messages

  Demonstrates:
    * Publish Subscribe
    * Fanout exchange

  Monitoring:
    * to view the results with the RabbitMQ manager:
    <hostname>:15672 in browser

    where <hostname> is the results of your hostname command

'''

# Taken from Jamieson Becker
def get_ip():
  s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
  try:
    # doesn't have to be reachable
    s.connect(('10.255.255.255', 1))
    IP = s.getsockname()[0]
  except:
    IP = '127.0.0.1'
  finally:
    s.close()
  return IP

# create a connection and a channel
credentials = pika.PlainCredentials('bob', 'dobbs')
parameters = pika.ConnectionParameters(get_ip(), 5672, '/', credentials)
connection = pika.BlockingConnection(parameters=parameters)
channel = connection.channel()

# create an exchange and bind it to an exclusive queue
channel.exchange_declare(exchange='logs', exchange_type='fanout')
result = channel.queue_declare(exclusive=True)
queue_name = result.method.queue
channel.queue_bind(exchange='logs', queue=queue_name)

print(' [*] Waiting for logs. To exit press CTRL-C')

def callback(ch, method, properties, body):
  print(" [x] {!s}".format(body.decode('utf8')))

channel.basic_consume(callback,
    queue=queue_name,
    no_ack=True)
channel.start_consuming()


from flask import Flask, render_template, request
import jsonify
import requests
import pickle
import numpy as np
import sklearn
from sklearn.preprocessing import StandardScaler
app = Flask(__name__)
model = pickle.load(open('heart_disease_random_forest_model.pkl', 'rb'))
@app.route('/',methods=['GET'])
def Home():
    return render_template('index.html')

#standard_to = StandardScaler()
@app.route("/predict", methods=['POST'])
def predict():
    #Fuel_Type_Diesel=0
    if request.method == 'POST':
        Age = int(request.form['Age'])
        Gender=request.form['sex']
        if(Gender=='Male'):
            Gender=1
        else:
            Gender=0
        cp = int(request.form['cp'])
        trestbps = int(request.form['trestbps'])
        chol = int(request.form['chol'])
        fbs = int(request.form['fbs'])
        restecg = int(request.form['restecg'])
        thalach = int(request.form['thalach'])
        exang = int(request.form['exang'])

        oldpeak=float(request.form['oldpeak'])

        slope=int(request.form['slope'])
        ca=int(request.form['slope'])
        thal=int(request.form['slope'])

        #Kms_Driven2=np.log(Kms_Driven)
        #Owner=int(request.form['Owner'])
        #Fuel_Type_Petrol=request.form['Fuel_Type_Petrol']
        #if(Fuel_Type_Petrol=='Petrol'):
        #        Fuel_Type_Petrol=1
        #        Fuel_Type_Diesel=0
        #else:
        #    Fuel_Type_Petrol=0
        #    Fuel_Type_Diesel=1
        #Year=2020-Year
        #Gender=request.form['Gender']
        #if(Gender=='Male'):
        #    Gender=1
        #else:
        #    Gender=0

        #Transmission_Mannual=request.form['Transmission_Mannual']
        #if(Transmission_Mannual=='Mannual'):
        #    Transmission_Mannual=1
        #else:
        #    Transmission_Mannual=0
        prediction=model.predict([[Age,sex,cp,tresttbps,chol,fbs,restecg,thalach,exang,oldspeak,slope,ca,thal]])
        output=round(prediction[0],2)
        if output==0:
            return render_template('index.html',prediction_texts="Patient does not have heart disease")
        elif output==1:
            return render_template('index.html',prediction_text="Patient has heart disease")
    else:
        return render_template('index.html')

if __name__=="__main__":
    app.run(debug=True)


import cv2
import mediapipe as mp
import pafy
import numpy as np
mp_drawing = mp.solutions.drawing_utils
mp_pose = mp.solutions.pose
import matplotlib.pyplot as plt
from mpl_toolkits import mplot3d
from time import time, sleep
from gtts import gTTS
from playsound import playsound
import os
import subprocess

def calculate_2Dangle(a,b,c):
    a = np.array(a) # First
    b = np.array(b) # Mid
    c = np.array(c) # End
    radians = np.arctan2(c[1]-b[1], c[0]-b[0]) - np.arctan2(a[1]-b[1], a[0]-b[0])
    angle = np.abs(radians*180.0/np.pi)
    if angle >180.0: angle = 360-angle
    return angle

def norm(v):
    v = np.array(v)
    norm_v = np.sqrt(v[0]**2+v[1]**2+v[2]**2)
    return norm_v

def calculate_3Dangle(a,b,c):
    a = np.array(a) # First
    b = np.array(b) # Mid
    c = np.array(c) # End
    radians = np.arctan2(c[1]-b[1], c[0]-b[0]) - np.arctan2(a[1]-b[1], a[0]-b[0])
    angle = np.abs(radians*180.0/np.pi)
    if angle > 180.0: angle = 360-angle
    return angle

class RealTime_Coaching_Voice:
    """
    Class implements Pose Estimation model to make inferences on a youtube video using Opencv2.
    """

    def __init__(self, url, out_file="src_landmarks.mov"):
        """
        Initializes the class with youtube url and output file.
        :param url: Has to be as youtube URL,on which prediction is made.
        :param out_file: A valid output file name.
        """
        self._URL = url
        self.out_file = out_file
        self.tmp = np.zeros(2)

    def get_video_from_url(self):
        """
        Creates a new video streaming object to extract video frame by frame to make prediction on.
        :return: opencv2 video capture object, with lowest quality frame available for video.
        """
        play = pafy.new(self._URL).streams[0]
        assert play is not None
        return cv2.VideoCapture(play.url)

    def __call__(self):
        """
        This function is called when class is executed, it runs the loop to read the video frame by frame,
        and write the output into a new file.
        :return: void
        """

        player1 = self.get_video_from_url()
        player2 = cv2.VideoCapture(0)
        assert player1.isOpened()
        assert player2.isOpened()
        with mp_pose.Pose(min_detection_confidence=0.5, min_tracking_confidence=0.5) as pose1:
            with mp_pose.Pose(min_detection_confidence=0.5, min_tracking_confidence=0.5) as pose2:
                self.tmp[0] = time() # store time for optimized list printing
                while True:

                    ### 1. Pose Estimation of Contents ###

                    start_time1 = time()
                    ret1, frame1 = player1.read()
                    assert ret1

                    # To improve performance, optionally mark the image as not writeable to
                    # pass by reference.
                    frame1.flags.writeable = False
                    image1 = cv2.cvtColor(frame1, cv2.COLOR_BGR2RGB)

                    try:

                        results1 = pose1.process(image1)

                        if results1 is None:
                            continue

                        # Draw the pose annotation on the image.
                        image1.flags.writeable = True
                        image1 = cv2.cvtColor(image1, cv2.COLOR_RGB2BGR)
                        mp_drawing.draw_landmarks(image1,
                                                  results1.pose_landmarks,
                                                  mp_pose.POSE_CONNECTIONS
                                                 )
                        # Check Performance
                        end_time1 = time()
                        fps1 = 1/np.round(end_time1 - start_time1, 3)
                        print(f"Youtube _ Frames Per Second : {fps1}")

                        ### 2. Pose Estimation of User ###

                        start_time2 = time()
                        ret2, frame2 = player2.read()
                        assert ret2

                        # To improve performance, optionally mark the image as not writeable to
                        # pass by reference.
                        frame2.flags.writeable = False
                        image2 = cv2.cvtColor(frame2, cv2.COLOR_BGR2RGB)
                        results2 = pose2.process(image2)

                        if results2 is None:
                            continue

                        # Draw the pose annotation on the image.
                        image2.flags.writeable = True
                        image2 = cv2.cvtColor(image2, cv2.COLOR_RGB2BGR)
                        mp_drawing.draw_landmarks(image2,
                                                  results2.pose_landmarks,
                                                  mp_pose.POSE_CONNECTIONS
                                                 )
                        # Check Performance
                        end_time2 = time()
                        self.tmp[1] = end_time2
                        fps2 = 1/np.round(end_time2 - start_time2, 3)
                        print(f"USER _ Frames Per Second : {fps2}")

                        ### 3. Plot in Concatentaed Fashion
                        image1_rev = cv2.resize(image1, (400, 200))
                        image2_rev = cv2.resize(image2, (400, 200))

                        imstack = np.vstack([image1_rev,image2_rev])

                        cv2.namedWindow("Comparison")
                        cv2.imshow('Comparison',imstack)

                        ### 4. Logic ###

                        if self.tmp[1]-self.tmp[0] > 10: # ~ 1 operation per about 5 frames
                            self.tmp[0] = self.tmp[1]; self.tmp[1] = 0 # renewal time
                            landmarks1 = results1.pose_landmarks.landmark
                            landmarks2 = results2.pose_landmarks.landmark
                            ldmk1 = np.array(landmarks1)
                            ldmk2 = np.array(landmarks2)
                            for i in range(33):
                                ldmk1[i] = np.array([ldmk1[i].x, ldmk1[i].y, ldmk1[i].z, ldmk1[i].visibility])
                                ldmk2[i] = np.array([ldmk2[i].x, ldmk2[i].y, ldmk2[i].z, ldmk2[i].visibility])

                            dist = np.zeros(4) # list of distance
                            dist[0] = abs(calculate_2Dangle(ldmk1[13][0:2], ldmk1[11][0:2], ldmk1[23][0:2]) - calculate_2Dangle(ldmk2[13][0:2], ldmk2[11][0:2], ldmk2[23][0:2]))
                            dist[1] = abs(calculate_2Dangle(ldmk1[14][0:2], ldmk1[12][0:2], ldmk1[24][0:2]) - calculate_2Dangle(ldmk2[14][0:2], ldmk2[12][0:2], ldmk2[24][0:2]))
                            dist[2] = abs(calculate_2Dangle(ldmk1[11][0:2], ldmk1[13][0:2], ldmk1[15][0:2]) - calculate_2Dangle(ldmk2[11][0:2], ldmk2[13][0:2], ldmk2[15][0:2]))
                            dist[3] = abs(calculate_2Dangle(ldmk1[12][0:2], ldmk1[14][0:2], ldmk1[16][0:2]) - calculate_2Dangle(ldmk2[12][0:2], ldmk2[14][0:2], ldmk2[16][0:2]))

                            tmp = dist[0]
                            k = 0
                            for i in [1,2,3]:
                                if dist[i] > dist[0]:
                                    dist[0] = dist[i]
                                    k = i
                            if dist[0] < 30:
                                continue

                            else:
                                if k == 0:
                                    text = '왼팔의 위치가 잘못되었습니다.'
                                    tts = gTTS(text = text, lang = 'ko', slow = False)
                                elif k == 1:
                                    text = '오른팔의 위치가 잘못되었습니다.'
                                    tts = gTTS(text = text, lang = 'ko', slow = False)
                                elif k == 2:
                                    text = '왼쪽 팔꿈치의 위치가 잘못되었습니다.'
                                    tts = gTTS(text = text, lang = 'ko', slow = False)
                                elif k == 3:
                                    text = '오른쪽 팔꿈치의 위치가 잘못되었습니다.'
                                    tts = gTTS(text = text, lang = 'ko', slow = False)

                                os.makedirs("./audios_cache/", exist_ok=True)
                                audio_file_name = './audios_cache/guide_{0}.mp3'.format(str(int(time())))
                                tts.save(audio_file_name)
                                subprocess.call(["python", "play_audio_cache.py", "-p", audio_file_name])

                                '''
                                audio_file_name = './audios_cache/guide_{0}.mp3'.format(str(int(time())))
                                tts.save(audio_file_name)
                                print("Audio File Write: {0}".format(audio_file_name))
                                exec("from playsound import playsound\nplaysound(audio_file_name)", globals())
                                if os.path.isfile(audio_file_name):
                                    os.remove(audio_file_name)
                                '''
                                '''
                                file = "./audios_cache/guide_{0}.mp3".format(str(int(time())))
                                tts.save(file)
                                playsound(file)
                                if os.path.isfile(file):
                                    os.remove(file)
                                '''

                    except:
                        pass

                    if cv2.waitKey(5) & 0xFF == 27:
                        break

if __name__ == "__main__":
    application = RealTime_Coaching_Voice('https://www.youtube.com/watch?v=goT7St7V9Xk')
    application()


import asyncio
import json
import os
import random
import re

import discord
import requests
from discord.ext import commands
from discord.utils import get
from airtable import Airtable

print(discord.__version__)

intents = discord.Intents().all()
bot = commands.Bot(command_prefix='.', intents=intents)

activity = True

fgm = r"https?://(www.)?groupme"  # fuck groupme

at = Airtable(os.environ['AT'], api_key=os.environ['ATKEY'], table_name='Table 1')
at.get_all()
print(at)

bot.remove_command("help")

@bot.event
async def on_ready():
    await bot.change_presence(status=discord.Status.online,
                              activity=discord.Activity(name="your bank accounts drain.", type=3))
    print(f'{bot.user.name} is running...')

@bot.command()
async def ping(ctx):
    await ctx.send(f"Pong! {bot.latency * 1000:.03f}ms")

@bot.command(pass_context=True)
async def mergerole(ctx):
    print('running')
    r = get(ctx.message.guild.roles, name="Accepted")
    print(r)
    newrole = get(ctx.message.guild.roles, name="Committed")
    print(newrole)
    for member in ctx.message.guild.members:
        print(member)
        if r in member.roles:
            print('to add')
            await member.add_roles(newrole)
            print('adding')
    print('done')

@bot.command()
async def help(ctx):
    embed = discord.Embed(
        title='Emperor Palpatine',
        description='A bot to serve Vanderbilt discord servers!',
        colour=discord.Colour.dark_gold()
    )

    embed.set_footer(text='Created July 2020 by thecolellis#6969.')
    embed.set_thumbnail(
        url='https://cdn.discordapp.com/attachments/733788698277052438/733792565798764684/1200px-Vanderbilt_Commodores_logo.svg.png')
    embed.set_author(name='Emperor Palpatine#6411',
                     icon_url='https://images-ext-2.discordapp.net/external/runjMvzmXx2Q7dRXkr7r48j6VQTBOiu-agSsMDySZdY/%3Fsize%3D1024/https/cdn.discordapp.com/avatars/735266441204334663/b55eabc51240ca749f1f5d73a0e78463.png?width=681&height=681')
    embed.add_field(name='My prefix:', value='\"`.`\"', inline=True)
    embed.add_field(name='Need help?', value='Type `.help` for assistance!', inline=True)
    embed.add_field(name='List of Commands', value='help \n newprofile \n ping \n profile', inline=False)

    await ctx.send(embed=embed)

@bot.command()
async def newprofile(ctx):
    embed = discord.Embed(
        title='New Profile:',
        description='Click this link to set up your profile: https://vandyinfo.tech/links/discordprofile',
        colour=discord.Colour.dark_gold()
    )
    await ctx.send(embed=embed)

@bot.command()
async def profile(ctx, *, arg=None):
    await bot.wait_until_ready()
    if not arg:
        records = at.search('Discord username with Discriminator', str(ctx.message.author))
    else:
        records = at.search('Name', arg.lower())
    user = ctx.message.author
    pfp = user.avatar_url
    if not records:
        await ctx.send("User not found! Reminder that the bot only updates once daily.")
    else:
        info = (records[0]['fields'])

        embed = discord.Embed(
            title=info['First Name'] + ' ' + info['Last Name'] + ' (' + info[
                'Discord username with Discriminator'] + ')',
            colour=discord.Colour.dark_gold()
        )

        embed.set_footer(
            text='Information is updated daily.  Please message `thecoleellis#6969` if any errors are found.')
        embed.set_thumbnail(url=info['Portrait'])
        embed.set_author(name=user, icon_url=pfp)
        embed.add_field(name='Graduating Year', value=info['Graduating Year'], inline=True)
        embed.add_field(name='(Intended) Major', value=info['(Intended) Major'], inline=True)
        embed.add_field(name='College of Enrollment', value=info['College of Enrollment'], inline=True)
        embed.add_field(name='Dorm House', value=info['Dorm House'], inline=True)
        embed.add_field(name='Room Number', value=info['Room Number'], inline=True)
        embed.add_field(name='VU Visions Group', value=info['VU Visions Group'], inline=True)
        embed.add_field(name='Introduction', value=info['Introduction'], inline=False)
        snap = False
        insta = False
        if 'None Provided' not in info['Socials: Snapchat']:
            snap = True
        if 'None Provided' not in info['Socials: Instagram']:
            insta = True
        if snap and insta:
            embed.add_field(name='Socials', value='Snapchat: http://snapchat.com/add/' + info[
                'Socials: Snapchat'] + ' \n Instagram: http://instagram.com/' + info[
                                                      'Socials: Instagram'] + ' \n Linkedin: ' + info[
                                                      'Socials: LinkedIn'], inline=False)
        elif snap:
            embed.add_field(name='Socials',
                            value='Snapchat: http://snapchat.com/add/' + info['Socials: Snapchat'] + ' \n Instagram: ' +
                                  info['Socials: Instagram'] + ' \n Linkedin: ' + info['Socials: LinkedIn'],
                            inline=False)
        elif insta:
            embed.add_field(name='Socials',
                            value='Snapchat: ' + info['Socials: Snapchat'] + ' \n Instagram: http://instagram.com/' +
                                  info['Socials: Instagram'] + ' \n Linkedin: ' + info['Socials: LinkedIn'],
                            inline=False)

        await ctx.send(embed=embed)

@bot.event
async def on_message(message):
    if not message.author.bot:
        if message.author.id == 700233926085443645:
            user = bot.get_user(214508201624862731)
            vrand = random.randint(0,16)
            print(f"vrand: {vrand}")
            if vrand == 8:
                await message.channel.send('no :hearts:')
            await bot.get_channel(712069333257420821).send("another one <@!214508201624862731>")

        if 'he is always watching' in message.content.lower():
            await message.channel.send(
                'https://media.discordapp.net/attachments/699763540361478145/734157709770752131/image0.jpg')
            await message.channel.send('The Emperor is always watching...')
        if 'floor plan' in message.content.lower():
            if 'commons' in message.content.lower():
                await message.channel.send(
                    'Commons Floor Plans: https://discordapp.com/channels/678041940901625865/678067983376973845/735639699435159612')
            elif 'towers' in message.content.lower():
                await message.channel.send(
                    'Towers Floor Plans: https://discordapp.com/channels/678041940901625865/678067983376973845/735613872098246768')
            elif 'branscomb' in message.content.lower():
                await message.channel.send(
                    'Branscomb Floor Plans: https://discordapp.com/channels/678041940901625865/678067983376973845/725169006113325197')
            elif 'cole' in message.content.lower():
                await message.channel.send(
                'Cole Floor Plans: https://discord.com/channels/678041940901625865/678067983376973845/795025289142468668')
            elif 'mayfield' in message.content.lower():
                await message.channel.send(
                'Mayfield Floor Plans: https://discord.com/channels/678041940901625865/678067983376973845/795025614439579648')
            elif 'mcgill' in message.content.lower():
                await message.channel.send(
                'McGill Floor Plans: https://discord.com/channels/678041940901625865/678067983376973845/795025696556056596')
            elif 'mctyeire' in message.content.lower():
                await message.channel.send(
                'McTyeire Floor Plans: https://discord.com/channels/678041940901625865/678067983376973845/795025735365427200')
            elif 'morgan' in message.content.lower() or 'lewis' in message.content.lower():
                await message.channel.send(
                'Morgan and Lewis Floor Plans: https://discord.com/channels/678041940901625865/678067983376973845/795025783772676127')
            elif 'tolman' in message.content.lower():
                await message.channel.send(
                'Tolman Floor Plans: https://discord.com/channels/678041940901625865/678067983376973845/795025842953912330')
            elif 'warren' in message.content.lower() or 'moore' in message.content.lower() or 'kissam' in message.content.lower():
                await message.channel.send(
                'Warren and Moore (Kissam) Floor Plans: https://discord.com/channels/678041940901625865/678067983376973845/795027155074416701')
            elif 'ebi' in message.content.lower():
                await message.channel.send(
                'EBI Floor Plans: https://discord.com/channels/678041940901625865/678067983376973845/795039142743900181')
            elif 'zeppos' in message.content.lower():
                await message.channel.send(
                'Zeppos Floor Plans: https://discord.com/channels/678041940901625865/678067983376973845/795038705073127455')
            elif 'highland' in message.content.lower():
                await message.channel.send(
                '''Highland Floor Plans (Mayfield): https://discord.com/channels/678041940901625865/678067983376973845/795025614439579648
                   Highland Floor Plans (Morgan and Lewis): https://discord.com/channels/678041940901625865/678067983376973845/795025783772676127''')
        if re.search(fgm, message.content.lower()) and message.channel.id != 747890842819231815:  # match groupme link and check not wrong channel
            await message.author.send(
                'We do not allow the posting of GroupMe links outside of the <#747890842819231815> channel, please repost your link there.')
            await message.delete()
        if 'vandy' in message.content.lower():
            rand = random.randint(0, 20)
            arand = random.randint(0, 29)
            print(f"rand: {rand}")
            print(f"arand: {arand}")
            if rand == 7 and message.author.id != 472229397085290506:
                await message.channel.send('fuck vandy')
                await message.channel.send('all my homies hate vandy')
            if arand == 15 and message.author.id == 472229397085290506:
                await message.channel.send('fuck vandy')
                await message.channel.send('all my homies hate vandy')
            if rand == 7 and arand != 15 and message.author.id == 472229397085290506:
                await message.channel.send('i would\'ve said it if it wasnt alissa smh')
        if 'emperor' in message.content.lower() or 'palpatine' in message.content.lower() or 'diermeier' in message.content.lower() or 'chancellor' in message.content.lower():
            rand = random.randint(0, 14)
            print(rand)
            if rand == 7:
                await message.channel.send(
                    'https://media.discordapp.net/attachments/699763540361478145/734157709770752131/image0.jpg')
                await message.channel.send('The Emperor is always watching...')
        if bot.user in message.mentions:
            await message.channel.send('no :)')
        if message.channel.id == 692841868777750638:
            await message.add_reaction('\N{THUMBS UP SIGN}')
            await message.add_reaction('\N{THUMBS DOWN SIGN}')
        if 'sam' in message.content.lower() and 'admin' in message.content.lower():
            await message.delete()
        if 'admin' in message.content.lower() and 'abuse' in message.content.lower():
            await message.delete()
    await bot.process_commands(message)

bot.run(os.environ['TOKEN'])


import os.path
import structlog

my_path = os.path.abspath(os.path.dirname(__file__))
path = os.path.join(my_path, "exercise.log")
print(path)

# Do not use a with construction in production code to pass the file to the logging.
# Here is it used to ensure the log file is properly closed without boilerplate
with open(path, "a+") as logfile:
    structlog.configure(
        logger_factory=structlog.PrintLoggerFactory(file=logfile),
    )

    # # create logger
    logger = structlog.getLogger("simpleLogger")

    # 'application' code
    logger.debug("debug message")
    logger.info("info message")
    logger.warning("warn message")
    logger.error("error message")
    logger.critical("critical message", action="create incident")


# 1021 회전하는 큐

import collections

N, M = map(int, input().split())

deque = collections.deque()
for i in range(1, N+1):
    deque.append(i)

lst = list(map(int, input().split()))
ans = 0

for x in lst:
    if deque[0] == x:
        deque.popleft()
    else:
        idx = deque.index(x)
        if idx < len(deque)-idx:
            for i in range(idx):
                deque.append(deque.popleft())
            ans += idx
        else:
            for i in range(len(deque)-idx):
                deque.appendleft(deque.pop())
            ans += (len(deque) - idx)
        deque.popleft()

print(ans)


from firebase_admin import firestore
from google.cloud.firestore_v1.base_query import FieldFilter

def get_churches(church_name="none"):
    db = firestore.client()
    churches = []
    if church_name == "none":
        docs = db.collection("churches").stream()
    else:
        docs = db.collection("churches").where(filter=FieldFilter("name", "==", church_name)).stream()
    for doc in docs:
        church = doc.to_dict()
        church["id"] = doc.id
        churches.append(church)

    return churches