#import the library used to query a website
from urllib.request import urlopen

#import the Beautiful soup functions to parse the data returned from the website
from bs4 import BeautifulSoup
import pandas as pd

df = pd.DataFrame()
j =0

#specify the url
job_listing1 = "https://losangeles.craigslist.org/d/computer-gigs/search/cpg"
job_listing2 = "https://losangeles.craigslist.org/d/web-html-info-design/search/web"

job_listing3 = "https://newyork.craigslist.org/search/web?search_distance=200&postal=10005"
job_listing4 = "https://newyork.craigslist.org/d/computer-gigs/search/cpg"

job_listing5 = "https://sfbay.craigslist.org/search/sfc/cpg?is_paid=yes"
job_listing6 = "https://sfbay.craigslist.org/search/sfc/web"

job_listing = [job_listing1, job_listing2, job_listing3, job_listing4, job_listing5, job_listing6]

for i in job_listing:

    #Query the website and return the html to the variable 'page'
    page = urlopen(i)
    print("Getting data from",i)
    #Parse the html in the 'page' variable, and store it in Beautiful Soup format
    soup = BeautifulSoup(page)
    #print(soup.prettify())

    right_listing = soup.find('ul', class_='rows')

    #Generate lists
    A=[]
    B=[]
    C=[]

    for row in right_listing.findAll("li"):
        j =  j + 1;
        date = row.find('time', class_='result-date')
        formatted_date = date.get("datetime")
        correct_date = formatted_date[0:10]
        title = row.find('a', class_='result-title hdrlnk')
        link = title.get("href")

        A.append(correct_date)
        B.append(title.find(text=True))
        C.append(link)
        if j == 21:
            break

    j=0

    df1 = pd.DataFrame()
    df1['Time']=A
    df1['Job']=B
    df1['Link']=C
    print("Number of jobs fetched", df1.shape)

    df=df.append(df1)

df=df.sort_values(by='Time', ascending=False)
print("Total number of jobs", df.shape)

#df.set_option('display.html.render_links',)

# send the results into an HTML page which will open in default browser

df.to_html('filename.html', escape=False)
webbrowser.open("/home/maninder/filename.html", new=2)

#df.to_csv('out.csv', index=False)
#df.to_csv('out.csv', encoding='utf-8', index=False)


from enum import Enum

# Colors
GUI_RED_ERROR_BG = '#f86e6c'

# LoadWdiget

# -> Display message for QLineEdit used for file selection
LOAD_WIDGET_FILE_DEFAULT_MESSAGE = 'Select a frame folder to process'
LOAD_WIDGET_FILE_DIALOG_HEADER_TITLE = 'Select a folder to process'
LOAD_WIDGET_LOAD_JSON = 'Load settings from file'

# -> Start button states
class StartStates(Enum):
    LOCKED = 0
    ENABLED = 1
    STOP = 2

LOAD_START_BUTTON_ENABLED_TEXT = 'Start'
LOAD_START_BUTTON_STOP_TEXT = 'Stop'

# VideoPlayer

VIDEO_PLAYER_BG_COLOR = '#303539'
VIDEO_PLAYER_BG_COLOR_BGR = (22, 21, 19)
VIDEO_PLAYER_BG_COLOR_GRAY = 255 # To define
VIDEO_PLAYER_HEIGHT_DEFAULT = 480
VIDEO_PLAYER_WIDTH_DEFAULT = 200

# Type of frames to display
class FrameTypes(Enum):
    FRAME = 0
    GRAY = 1
    CORE = 2
    CONTOUR = 3
    CORE_CC = 4
    CONTOUR_CC = 5

# Mouse event offset
# -> To feel more natural when selecting the area of interest offset
MOUSE_EVENT_PIXEL_OFFSET = 32

# Preprocessing
PREPROCESSING_MAIN_DESCRIPTION = 'Narrow the area of interest to remove redundant frame information. Then select the threshold values for the areas of interest to start the process.'
PREPROCESSING_MINIMUM_WIDTH = 100#
PREPROCESSING_SCROLL_WIDTH_STEP = 10
PREPROCESSING_WINDOW_TITLE = 'Preprocessing'
PREPROCESSING_TITLE_MESSAGE= 'Select the region of interest to cut the frames and save processing time'
PREPROCESSING_DESC_MESSAGE = 'Left click on the approximate center of the flame and adjust the width of the region, scrolling the mouse wheel. You can use the controls to fine tune the area. You can also save/load this presets for future use.'

PREPROCESSING_CUT_WIDGET_TAB_TITLE = 'Cut Frame'
PREPROCESSING_THRESHOLD_WIDGET_TAB_TITLE = 'Threshold controls'
PREPROCESSING_DISPLAY_WIDGET_TAB_TITLE = 'Run settings'
PREPROCESSING_CAMERA_CALIBRATION_WIDGET_TAB_TITLE='Camera Calibration'

# -> Camera calibration
PREPROCESSING_CAMERA_CALIBRATION_LOAD_IMAGE = 'Select a chessboard image'
PREPROCESSING_CAMERA_CALIBRATION_LOAD_DIALOG = 'Select a chessboard image'
PREPROCESSING_CAMERA_CALIBRATION_PLOT_FRAME_TITLE = 'Calibration Image'
PREPROCESSING_CAMERA_CALIBRATION_THRESHOLD_FRAME_TITLE = 'Threshold Image'
PREPROCESSING_CAMERA_CALIBRATION_CONTROLS_TITLE = 'Camera Calibration:'
PREPROCESSING_CAMERA_CALIBRATION_CONTROLS_DESC = 'Allows to get the convertion from pixels to milimiters. This is done by automatically analyzing a chessboard image of the experimental setup.'
PREPROCESSING_CAMERA_CALIBRATION_CONTROLS_SQUARES = 'N° of squares on chessboard:'
PREPROCESSING_CAMERA_CALIBRATION_CONTROLS_SQUARE_SIDE = 'Square side:'
PREPROCESSING_CAMERA_CALIBRATION_CONTROLS_PX_AVG = 'Square side AVG:'
PREPROCESSING_CAMERA_CALIBRATION_CONTROLS_PX_AVG_FIELD = '{:.2f} px'
PREPROCESSING_CAMERA_CALIBRATION_CONTROLS_PX_STD = 'Square side STD:'
PREPROCESSING_CAMERA_CALIBRATION_CONTROLS_PX_STD_FIELD = '{:.2f} px'
PREPROCESSING_CAMERA_CALIBRATION_PX_MM_TITLE = 'Conversion factor:'
PREPROCESSING_CAMERA_CALIBRATION_PX_MM_DESC = 'Val_mm = Val_px * (square_side_mm / square_side_px)'
PREPROCESSING_CAMERA_CALIBRATION_PX_MM_A_LABEL = 'Factor:'
PREPROCESSING_CAMERA_CALIBRATION_CORNER_COLOR = '#F48815'
PREPROCESSING_CAMERA_CALIBRATION_MIN_SQUARES = 5
PREPROCESSING_CAMERA_CALIBRATION_MIN_SQUARE_SIDE = 1 #mm
PREPROCESSING_CAMERA_CALIBRATION_NO_CORNERS_ERROR = 'No squares could be found on the image, try checking the input fields and chessboard image!'
PREPROCESSING_CAMERA_CALIBRATION_SQUARE_SIDE_UNIT = '  mm'
PREPROCESSING_CAMERA_CALIBRATION_FACTOR = '  mm/px'
PREPROCESSING_CAMERA_CALIBRATION_SAVE_TITLE = 'Save the calibration factor to a file'
PREPROCESSING_CAMERA_CALIBRATION_SAVE_DESC = 'Save the current calibration'
PREPROCESSING_CAMERA_CALIBRATION_LOAD_JSON_DIALOG = 'Load a calibration file'
PREPROCESSING_CAMERA_CALIBRATION_DEFAULT_FACTOR = 0.0001
PREPROCESSING_CAMERA_CALIBRATION_N_DECIMALS = 4

# -> For saving/loading jsons
PREPROCESSING_SAVE_CUT = 'Save the current cut profile onto a file'
PREPROCESSING_LOAD_CUT = 'Load cut profile from file'

# -> For auto cut the frame
PREPROCESSING_AUTO_CUT_THRESHOLD_PERCENTAGE = 1
PREPROCESSING_AUTO_CUT_PADDING = 10 # 10 px

# -> For thresholding
PREPROCESSING_THRESHOLD_DESC = 'Adjust the threshold controls to define the core and contour regions. The selected values will be used for the Smoke Point estimation. You can watch the effect of the selected threshols on the previes on the left. You can also save/load this presets for future use.'
PREPROCESSING_THRESHOLD_FRAME_TITLE = '{} preview'
PREPROCESSING_THESHOLD_CONTROLS_TITLE = '{} controls'
PREPROCESSING_THRESHOLD_PERCENTAGE = '{} threshold value: '
PREPROCESSING_THRESHOLD_INFORMATION = 'ROI Statistics'
PREPROCESSSING_ERROR_THRESHOLD_IMAGE = 'The selected threshold results in a null area, please use a lower one.'
PREPROCESSING_START_ERROR = 'Contour threshold cannot be higher than core threshold!'
PREPROCESSING_THRESHOLD_SUFFIX = ' %'
PREPROCESSING_HEIGHT_INFORMATION_PARSER = '{} px'
PREPROCESSING_AREA_INFORMATION_PARSER = '{} px\u00b2'
PREPROCESSING_INFORMATION_TABLE_WIDTH = 200
PREPROCESSING_INFORMATION_TABLE_COLUMN_HEIGHT = 25
PREPROCESSING_TABLE_PADDING = 2 # 1 px per line division
PREPROCESSING_THRESHOLD_SPIN_WIDTH = 75
PREPROCESSING_THRESHOLD_SAVE = 'Save the current threshold values onto a file'
PREPROCESSING_THRESHOLD_LOAD = 'Load threshold values from file'

# -> Derivative threshold
PREPROCESSING_CONSTANTS_DECIMALS = 5
PREPROCESSING_CONSTANTS_STEP = 0.00001
PREPROCESSING_CONSTANTS_TITLE = 'General Settings'
PREPROCESSING_CONSTANTS_DESC = 'Change general settings and constants used during the analysis'
PREPROCESSING_CONSTANTS_DER_THRESHOLD = 'Derivative threshold:'
PREPROCESSING_CONSTANTS_CENTROID_TOLERANCE = 'Centroid tolerance:'
PREPROCESSING_CONSTANTS_CENTROID_TOLERANCE_SUFFIX = '  px'

# -> For display information
PREPROCESSING_DISPLAY_TITLE = 'Run summary'
PREPROCESSING_DISPLAY_DESC = 'This are the settings that will be applied to the Smoke Point run. You can change them going back to the corresponding tabs. You can also save this general settings for future use.'
PREPROCESSING_DISPLAY_CUT = 'Cut - {} coordinate'
PREPROCESSING_DISPLAY_CUT_WIDTH = 'Cut width'
PREPROCESSING_DISPLAY_THRESHOLD = '{} threshold value'
PREPROCESSING_DISPLAY_WIDTH_VALUE = '{} px'
PREPROCESSING_DISPLAY_THRESHOLD_VALUE = '{} %'
PREPROCESSING_DISPLAY_FACTOR = 'Px to mm conversion factor'
PREPROCESSING_DISPLAY_FACTOR_VALUE = '{} mm/px'
PREPROCESSING_DISPLAY_DERIVATIVE_THRESHOLD = 'Derivative threshold'
PREPROCESSING_DISPLAY_DERIVATIVE_THRESHOLD_VALUE = '{:.5f}'
PREPROCESSING_DISPLAY_INFO_WIDTH = 300
PREPROCESSING_DISPLAY_INFO_HEIGHT = 125
PREPROCESSING_DISPLAY_CENTROID_TOL = 'Centroid tolerance'
PREPROCESSING_DISPLAY_CENTROID_TOL_VALUE = '{} px'

# -> Color for lines
PREPROESSING_CENTER_LINE_COLOR = (255,153,51) # '#ff9933'
PREPROCESSING_WIDTH_LINE_COLOR = (51, 153, 255) # '#3399ff'
PREPROCESSING_LINES_WIDTH = 2

# VideoButtons
VIDEO_BUTTONS_WIDGET_WIDTH = 150
VIDEO_BUTTONS_WIDGET_HEIGHT = 200

# PLOT TABS
TABS_WIDGET_WIDTH = 740
TABS_WIDGET_HEIGHT = 500

# PlotWidget
PLOT_WIDGET_DPI = 100
PLOT_WIDGET_WIDTH = 740
PLOT_WIDGET_HEIGHT = 460
PLOT_WIDGET_TRACE_CONTOUR = '#197278'
PLOT_WIDGET_TRACE_CORE = '#6CBEED'
PLOT_WIDGET_TRACE_TIP = '#F46036'

# Centroids Plot
class CentroidTypes(Enum):
    REFERENCE = 0
    VALID = 1
    INVALID = -1

PLOT_CENTROID_REFERENCE_COLOR = '#FFA630'
PLOT_CENTROID_REFERENCE_LINE = '-'
PLOT_CENTROID_SAFE_AREA_LIMITS_COLOR = '#034C3C'
PLOT_CENTROID_SAFE_AREA_LIMITS_LINE = '-.'
PLOT_CENTROID_SAFE_AREA_COLOR = '#3DDC97'
PLOT_CENTROID_SAFE_AREA_ALPHA=0.3
PLOT_CENTROID_VALID_COLOR = '#07004D'
PLOT_CENTROID_VALID_MARKER = 'o'
PLOT_CENTROID_INVALID_COLOR = '#EF2D56'
PLOT_CENTROID_INVALID_MARKER= 'x'

# Height frame plot
PLOT_HEIGHT_TAB_TITLE = 'Height Analysis'
PLOT_HEIGHT_X_AXIS = 'Frames [-]'
PLOT_HEIGHT_Y_AXIS = 'Height [px]'
PLOT_HEIGHT_LABELS = [
    'Flame Height',
    'Core Height',
    'Tip Height'
]

# Heights polyfitted plot
PLOT_HEIGHT_POLY_TITLE_TAB = 'Tip vs Contour'
PLOT_HEIGHT_POLY_DOTS_COLOR = '#4D9DE0'
PLOT_HEIGHT_POLY_LINE_COLOR ='#FF6666'
PLOT_HEIGHT_POLY_DOTS_LABEL = 'Tip height (H) vs Contour height(h)'
PLOT_HEIGHT_POLY_LINE_LABEL = '10th poly fit'
PLOT_HEIGHTS_POLY_XLABEL = 'Contour height (h) px'
PLOT_HEIGHTS_POLY_YLABEL = 'Tip height (H) px'

# Linear region plot
PLOT_LINEAR_TITLE_TAB = 'Linear Analysis'
PLOT_LINEAR_XLABEL = 'Contour height (h) px'
PLOT_LINEAR_YLABEL = ''
PLOT_LINEAR_DER_LABEL = 'Derivative'
PLOT_LINEAR_REGION_LABEL = 'Linear region'

# SP Plot
PLOT_SP_TITLE_TAB = 'SP Analysis'
PLOT_SP_XLABEL = 'Contour height (h) px'
PLOT_SP_YLABEL = 'Tip height (H) px'
PLOT_SP_POLY_COLOR = PLOT_HEIGHT_POLY_LINE_COLOR
PLOT_SP_LINEAR_POLY_COLOR = '#00A676'
PLOT_SP_POLY_LABEL = PLOT_HEIGHT_POLY_LINE_LABEL
PLOT_SP_LINEAR_POLY_LABEL = 'Linear region fit'
PLOT_SP_POINT_COLOR = '#4E4187'
PLOT_SP_POINT_LABEL = 'Smoke Point {:.2f} px'

# Centroid live plot
PLOT_CENTROID_TAB_TITLE = 'Centroid Analysis'
PLOT_CENTROID_XLABEL = 'Frames [-]'
PLOT_CENTROID_YLABEL = 'X coordinate [px]'

# Information bar

class InformationStatus(Enum):
    IDLE = 'IDLE'
    FRAMES = 'Frame Analysis'
    FRAMES_DONE = 'Frames Done'
    POLYNOMIAL = 'SP Analysis'
    DONE = 'Done'

INFORMATION_BAR_OPERATION_LABEL = 'Operation :'
INFORMATION_BAR_ELAPSED_LABEL = 'Elapsed Time :'
INFORMATION_BAR_ELAPSED_FIELD = '{0:02d}:{1:02d}:{2:02d}'

INFORMATION_LABELS_WIDTH = VIDEO_PLAYER_WIDTH_DEFAULT//2 - 2 # 10 for padding

# Information Tabs display

INFORMATION_TAB_DISPLAY_WIDTH = PLOT_WIDGET_WIDTH - 100
INFORMATION_TAB_DISPLAY_HEIGHT = 130

# -> Information tab processed frames
INFORMATION_PROCESSED_FRAMES_PLACEHOLDER = '-'
INFORMATION_PROCESSED_CENTROID_DECIMALS = 2
INFORMATION_PROCESSED_CENTROID_LABEL = '{} px'
INFORMATION_PROCESSED_CORE_LABEL = 'Core threshold value:'
INFORMATION_PROCESSED_CONTOUR_LABEL = 'Contour threshold value:'
INFORMATION_PROCESSED_THRESHOLD_FIELD = '{} %'
INFORMATION_PROCESSED_ROW_NUMBER_FRAMES = 'N° of processed frames:'
INFORMATION_PROCESSED_ROW_INVALID_FRAMES = 'N° of invalid frames:'
INFORMATION_PROCESSED_ROW_H_POINTS = 'N° of contour height points (h):'
INFORMATION_PROCESSED_ROW_TIME = 'Processing time:'
INFORMATION_PROCESSED_ROW_CENTROID = 'Centroid reference x:'
INFORMATION_PROCESSED_ROW_TIP_POINTS = 'N° of tip height points (H):'
INFORMATION_PROCESSED_TAB_TITLE = 'Frame process summary'

# -> Information tab polynomial analysis
INFORMATION_POLYNOMIAL_TAB_TITLE = 'Polynomial analysis summary'
INFORMATION_POLYNOMIAL_PLACEHOLDER = '-'
INFORMATION_POLYNOMIAL_THRESHOLD_VALUE = 'Derivative threshold used:'
INFORMATION_POLYNOMIAL_N_POINT_LINEAR_REGION = 'N° of points found in the linear region:'
INFORMATION_POLYNOMIAL_SP_VALUE_FOUND = 'SP found at:'
INFORMATION_POLYNOMIAL_SP_VALUE_FIELD = '{:.2f} px'
INFORMATION_POLYNOMIAL_PROCESSING_TIME = 'Processing time:'
INFORMATION_POLYNOMIAL_SP_MM_VALUE = 'SP converted:'
INFORMATION_POLYNOMIAL_SP_MM_VALUE_FIELD = '{:.2f} mm'
INFORMATION_POLYNOMIAL_CONV_FACTOR = 'Conversion factor:'

# Main Window
MAIN_WINDOW_TITLE = 'SPD: Smoke Point Detection'


from tkinter import *
from functools import partial
import pygame
from playsound import playsound

pygame.init()
root = Tk()

# First I should make buttons
# Which means I should create categories first lol
root.title("Jeopardy!!")
root["bg"] = "#e8e8e8"
game = LabelFrame(root, padx=10, pady=10, bg="#5ec9ff")
game.grid(row=0, column=0, padx=5, pady=10)

pygame.mixer.music.load("WAVJeopardy_Song (1).wav")
pygame.mixer.music.play()

label_food = Label(game, text="Foods", height=1, width=9, pady=30, borderwidth=5, font=("Comic Sans MS", 25, "normal", "italic"), bg="#5ec9ff")
label_pop_culture = Label(game, text="Pop Culture", height=1, width=9, pady=30, borderwidth=5, font=("Comic Sans MS", 25, "normal", "italic"), bg="#5ec9ff")
label_literature = Label(game, text="Literature", height=1, width=9, pady=30, borderwidth=5, font=("Comic Sans MS", 25, "normal", "italic"), bg="#5ec9ff")
label_capitals = Label(game, text="Capitals", height=1, width=9, pady=30, borderwidth=5, font=("Comic Sans MS", 25, "normal", "italic"), bg="#5ec9ff")
label_fun_facts = Label(game, text="Fun Facts", height=1, width=9, pady=30, borderwidth=5, font=("Comic Sans MS", 25, "normal", "italic"), bg="#5ec9ff")

label_food.grid(row=0, column=0)
label_pop_culture.grid(row=0, column=1)
label_literature.grid(row=0, column=2)
label_capitals.grid(row=0, column=3)
label_fun_facts.grid(row=0, column=4)

#All my methods. rip me
#Also all my python code. Why do I torture myself lol
#Foods
f_questions = ["Fill in the blank: An _____ a day keeps the doctor away", "Zuppa is Italian for this dish",
               "This nut, from the state tree of Texas is a southern pie staple",
               "Orange butter sauce doused in grand marnier and prepared in a chafing dish, it's flame on for this crepe dish!",
               "Which of the following fruits is not technically a berry"]
f_correct_answers = ["Apple", "Soup", "Pecan", "Crepe Suzette", "Strawberries"]
f_answers = [ ["Pomegranate", "Orange", "Apple", "Banana"],
              ["Soup", "Salsa", "Ambrosia", "Guacamole"],
              ["Walnut", "Pecan", "Almond", "Hickory nut"],
              ["Crepe Suzette", "Crepe Louis", "Crepe Marie", "Crepe Antoinette"],
              ["Bananas", "Strawberries", "Cranberries", "Avocados"] ]

#Pop Culture
pc_questions = ["Who originally sings the song \"Say So\"",
                "Which avenger other than Captain America was able to pick up Thor's Mjolnir in the marvel movies",
                "Who is the oldest Kardashian sister?",
                "Which Emmy Award-winning producer was behind Glee, Hollywood, The Politician and American Horror Story?",
                "Which famous american pop band was originally called \"Kara's Flowers'\""]
pc_correct_answers = ["Doja Cat", "Vision", "Kourtney", "Ryan Murphy", "Maroon 5"]
pc_answers = [ ["Saweetie", "Doja Cat", "Cardi B", "Megan Thee Stallion"],
                ["Vision", "Iron Man", "Scarlet Witch", "Black Widow"],
                ["Kim", "Khloe", "Kendall", "Kourtney"],
                ["David E. Kelly", "Ryan Murphy", "James L. Brooks", "Lorne Michaels"],
                ["Maroon 5", "Backstreet Boys", "NSYNC", "Boyz II Men"] ]

#Literature
l_questions = ["Who is the author of \"The Iliad\" and \"The Odyssey\"", "\"Don Quixote\" was written in what language?",
               "Who is the heroine of Nathaniel Hawthorne's \"The Scarlet Letter\"",
               "Put the three cantos of \"The Divine Comedy\" in the correct order.",
               "This poet, who is associated with Romanticism, wrote \"Songs of Innocence and Experience\""]
l_correct_answers = ["Homer", "Spanish", "Hester Prynne", "Inferno, Purgatorio, Paradiso", "William Blake"]
l_answers = [ ["Euripides", "Homer", "Beowulf", "Virgil"],
              ["Old English", "Italian", "Spanish", "Greek"],
              ["Anne Hutchinson", "Hester Prynne", "Scarlett O'Hara", "Elizabeth Bennet"],
              ["Paradiso, Purgatorio, Inferno", "Inferno, Limbo, Paradiso", "Purgatorio, Inferno, Limbo", "Inferno, Purgatorio, Paradiso"],
              ["William Blake", "John Keats", "Percy Bysshe Shelley", "Mary Shelley"] ]

#Capitals
c_questions = ["What is the capital of Mexico?", "What is the capital of the U.S?", "What is the capital of Canada",
               "What is the capital of Australia?", "What is the capital of Morocco?"]
c_correct_answers = ["Mexico City", "Washington DC", "Ottawa", "Canberra", "Rabat"]
c_answers = [ ["Cancun", "Mexico City", "Oaxaca", "Guadalajara"],
              ["Albany", "Washington DC", "Los Angeles", "Las Vegas"],
              ["Ottawa", "Toronto", "Quebec City", "Calgary"],
              ["Canberra", "Brisbane", "Perth", "Melbourne"],
              ["Casablanca", "Marrakesh", "Fes", "Rabat"] ]

#Fun Facts
ff_questions = ["How much is a \"Baker's Dozen\"?", "What is the fear of the number 13 called?",
                "What is the order of the 5 NYC boroughs by smallest to largest population number?",
               "In which state was the first Target opened?", "What is the name of the \"#\" symbol?"]
ff_correct_answers = ["13", "Triskaidekaphobia", "Staten Island, Bronx, Manhattan, Queens, Brooklyn", "Minnesota", "Octothorpe"]
ff_answers = [ ["13", "12", "14", "11"],
              ["Coulrophobia", "Triskaidekaphobia", "Gephyrophobia", "Paraskevidekatriaphobia"],
              ["Staten Island, Queens, Bronx, Manhattan, Brooklyn", "Bronx, Staten Island, Manhattan, Queens, Brooklyn",
               "Staten Island, Bronx, Manhattan, Brooklyn, Queens", "Staten Island, Bronx, Manhattan, Queens, Brooklyn"],
              ["California", "Minnesota", "Colorado", "Texas"],
              ["Lozenge", "Circumflex", "Ampersand", "Octothorpe"] ]

#index1 is the index of the question. index2 is the index of the answer
def setFoodAnswer(index1, index2, answer):
    global packRow
    if index2 == 0:
        a1["state"] = DISABLED
    elif index2 == 1:
        a2["state"] = DISABLED
    elif index2 == 2:
        a3["state"] = DISABLED
    elif index2 == 3:
        a4["state"] = DISABLED
    packRow = 10
    inc = Label(top, text="Incorrect!", font=("Arial", 25, "normal", "italic"), bg="#5ec9ff")
    cor = Label(top, text="Correct!", font=("Arial", 25, "normal", "italic"), bg="#5ec9ff")
    if answer != f_correct_answers[index1]:
        cor.grid_forget()
        inc.grid(row=packRow, column=0)
    else:
        inc.grid_forget()
        cor.grid(row=packRow + 1, column=0)
        a1["state"] = DISABLED
        a2["state"] = DISABLED
        a3["state"] = DISABLED
        a4["state"] = DISABLED

def foodQ (index):
    #Prints out question (and sets global variables)
    global top
    global a1
    global a2
    global a3
    global a4
    top = Toplevel(bg="#5ec9ff")
    question = Label(top, text=f_questions[index], wraplength=510, pady=80, font=("Comic Sans MS", 15, "normal", "italic"), bg="#5ec9ff")
    question.grid(row=0, column=0)
    #Then the answers
    a1 = Button(top, text=f_answers[index][0], height=4, width=70, command=partial(setFoodAnswer, index, 0, f_answers[index][0]), bg="#82d5ff")
    a2 = Button(top, text=f_answers[index][1], height=4, width=70, command=partial(setFoodAnswer, index, 1, f_answers[index][1]), bg="#82d5ff")
    a3 = Button(top, text=f_answers[index][2], height=4, width=70, command=partial(setFoodAnswer, index, 2, f_answers[index][2]), bg="#82d5ff")
    a4 = Button(top, text=f_answers[index][3], height=4, width=70, command=partial(setFoodAnswer, index, 3, f_answers[index][3]), bg="#82d5ff")
    a1.grid(row=1, column=0)
    a2.grid(row=2, column=0)
    a3.grid(row=3, column=0)
    a4.grid(row=4, column=0)
    #Disables pressed button
    if index == 0:
        f1["state"] = DISABLED
        f1["text"] = ""
        f1["relief"] = "groove"
    elif index == 1:
        f2["state"] = DISABLED
        f2["text"] = ""
        f2["relief"] = "groove"
    elif index == 2:
        f3["state"] = DISABLED
        f3["text"] = ""
        f3["relief"] = "groove"
    elif index == 3:
        f4["state"] = DISABLED
        f4["text"] = ""
        f4["relief"] = "groove"
    elif index == 4:
        f5["state"] = DISABLED
        f5["text"] = ""
        f5["relief"] = "groove"

def setPCAnswer(index1, index2, answer):
    global packRow
    if index2 == 0:
        a1["state"] = DISABLED
    elif index2 == 1:
        a2["state"] = DISABLED
    elif index2 == 2:
        a3["state"] = DISABLED
    elif index2 == 3:
        a4["state"] = DISABLED
    packRow = 10
    inc = Label(top, text="Incorrect!", font=("Arial", 25, "normal", "italic"), bg="#5ec9ff")
    cor = Label(top, text="Correct!", font=("Arial", 25, "normal", "italic"), bg="#5ec9ff")
    if answer != pc_correct_answers[index1]:
        cor.grid_forget()
        inc.grid(row=packRow, column=0)
    else:
        inc.grid_forget()
        cor.grid(row=packRow + 1, column=0)

def pcQ (index):
    #Prints out question (and sets global variables)
    global top
    global a1
    global a2
    global a3
    global a4
    top = Toplevel(bg="#5ec9ff")
    question = Label(top, text=pc_questions[index], wraplength=510, pady=80, font=("Comic Sans MS", 15, "normal", "italic"), bg="#5ec9ff")
    question.grid(row=0, column=0)
    #Then the answers
    a1 = Button(top, text=pc_answers[index][0], height=4, width=70, command=partial(setPCAnswer, index, 0, pc_answers[index][0]), bg="#82d5ff")
    a2 = Button(top, text=pc_answers[index][1], height=4, width=70, command=partial(setPCAnswer, index, 1, pc_answers[index][1]), bg="#82d5ff")
    a3 = Button(top, text=pc_answers[index][2], height=4, width=70, command=partial(setPCAnswer, index, 2, pc_answers[index][2]), bg="#82d5ff")
    a4 = Button(top, text=pc_answers[index][3], height=4, width=70, command=partial(setPCAnswer, index, 3, pc_answers[index][3]), bg="#82d5ff")
    a1.grid(row=1, column=0)
    a2.grid(row=2, column=0)
    a3.grid(row=3, column=0)
    a4.grid(row=4, column=0)
    #Disables pressed button
    if index == 0:
        pc1["state"] = DISABLED
        pc1["text"] = ""
        pc1["relief"] = "groove"
    elif index == 1:
        pc2["state"] = DISABLED
        pc2["text"] = ""
        pc2["relief"] = "groove"
    elif index == 2:
        pc3["state"] = DISABLED
        pc3["text"] = ""
        pc3["relief"] = "groove"
    elif index == 3:
        pc4["state"] = DISABLED
        pc4["text"] = ""
        pc4["relief"] = "groove"
    elif index == 4:
        pc5["state"] = DISABLED
        pc5["text"] = ""
        pc5["relief"] = "groove"

def setLitAnswer(index1, index2, answer):
    global packRow
    if index2 == 0:
        a1["state"] = DISABLED
    elif index2 == 1:
        a2["state"] = DISABLED
    elif index2 == 2:
        a3["state"] = DISABLED
    elif index2 == 3:
        a4["state"] = DISABLED
    packRow = 10
    inc = Label(top, text="Incorrect!", font=("Arial", 25, "normal", "italic"), bg="#5ec9ff")
    cor = Label(top, text="Correct!", font=("Arial", 25, "normal", "italic"), bg="#5ec9ff")
    if answer != l_correct_answers[index1]:
        cor.grid_forget()
        inc.grid(row=packRow, column=0)
    else:
        inc.grid_forget()
        cor.grid(row=packRow + 1, column=0)

def litQ (index):
    #Prints out question (and sets global variables)
    global top
    global a1
    global a2
    global a3
    global a4
    top = Toplevel(bg="#5ec9ff")
    question = Label(top, text=l_questions[index], wraplength=510, pady=80, font=("Comic Sans MS", 15, "normal", "italic"), bg="#5ec9ff")
    question.grid(row=0, column=0)
    #Then the answers
    a1 = Button(top, text=l_answers[index][0], height=4, width=70, command=partial(setLitAnswer, index, 0, l_answers[index][0]), bg="#82d5ff")
    a2 = Button(top, text=l_answers[index][1], height=4, width=70, command=partial(setLitAnswer, index, 1, l_answers[index][1]), bg="#82d5ff")
    a3 = Button(top, text=l_answers[index][2], height=4, width=70, command=partial(setLitAnswer, index, 2, l_answers[index][2]), bg="#82d5ff")
    a4 = Button(top, text=l_answers[index][3], height=4, width=70, command=partial(setLitAnswer, index, 3, l_answers[index][3]), bg="#82d5ff")
    a1.grid(row=1, column=0)
    a2.grid(row=2, column=0)
    a3.grid(row=3, column=0)
    a4.grid(row=4, column=0)
    #Disables pressed button
    if index == 0:
        l1["state"] = DISABLED
        l1["text"] = ""
        l1["relief"] = "groove"
    elif index == 1:
        l2["state"] = DISABLED
        l2["text"] = ""
        l2["relief"] = "groove"
    elif index == 2:
        l3["state"] = DISABLED
        l3["text"] = ""
        l3["relief"] = "groove"
    elif index == 3:
        l4["state"] = DISABLED
        l4["text"] = ""
        l4["relief"] = "groove"
    elif index == 4:
        l5["state"] = DISABLED
        l5["text"] = ""
        l5["relief"] = "groove"

def setCapAnswer(index1, index2, answer):
    global packRow
    if index2 == 0:
        a1["state"] = DISABLED
    elif index2 == 1:
        a2["state"] = DISABLED
    elif index2 == 2:
        a3["state"] = DISABLED
    elif index2 == 3:
        a4["state"] = DISABLED
    packRow = 10
    inc = Label(top, text="Incorrect!", font=("Arial", 25, "normal", "italic"), bg="#5ec9ff")
    cor = Label(top, text="Correct!", font=("Arial", 25, "normal", "italic"), bg="#5ec9ff")
    if answer != c_correct_answers[index1]:
        cor.grid_forget()
        inc.grid(row=packRow, column=0)
    else:
        inc.grid_forget()
        cor.grid(row=packRow + 1, column=0)

def capitalQ (index):
    #Prints out question (and sets global variables)
    global top
    global a1
    global a2
    global a3
    global a4
    top = Toplevel(bg="#5ec9ff")
    question = Label(top, text=c_questions[index], wraplength=510, pady=80, font=("Comic Sans MS", 15, "normal", "italic"), bg="#5ec9ff")
    question.grid(row=0, column=0)
    #Then the answers
    a1 = Button(top, text=c_answers[index][0], height=4, width=70, command=partial(setCapAnswer, index, 0, c_answers[index][0]), bg="#82d5ff")
    a2 = Button(top, text=c_answers[index][1], height=4, width=70, command=partial(setCapAnswer, index, 1, c_answers[index][1]), bg="#82d5ff")
    a3 = Button(top, text=c_answers[index][2], height=4, width=70, command=partial(setCapAnswer, index, 2, c_answers[index][2]), bg="#82d5ff")
    a4 = Button(top, text=c_answers[index][3], height=4, width=70, command=partial(setCapAnswer, index, 3, c_answers[index][3]), bg="#82d5ff")
    a1.grid(row=1, column=0)
    a2.grid(row=2, column=0)
    a3.grid(row=3, column=0)
    a4.grid(row=4, column=0)
    #Disables pressed button
    if index == 0:
        c1["state"] = DISABLED
        c1["text"] = ""
        c1["relief"] = "groove"
    elif index == 1:
        c2["state"] = DISABLED
        c2["text"] = ""
        c2["relief"] = "groove"
    elif index == 2:
        c3["state"] = DISABLED
        c3["text"] = ""
        c3["relief"] = "groove"
    elif index == 3:
        c4["state"] = DISABLED
        c4["text"] = ""
        c4["relief"] = "groove"
    elif index == 4:
        c5["state"] = DISABLED
        c5["text"] = ""
        c5["relief"] = "groove"

def setFFAnswer(index1, index2, answer):
    global packRow
    if index2 == 0:
        a1["state"] = DISABLED
    elif index2 == 1:
        a2["state"] = DISABLED
    elif index2 == 2:
        a3["state"] = DISABLED
    elif index2 == 3:
        a4["state"] = DISABLED
    packRow = 10
    inc = Label(top, text="Incorrect!", font=("Arial", 25, "normal", "italic"), bg="#5ec9ff")
    cor = Label(top, text="Correct!", font=("Arial", 25, "normal", "italic"), bg="#5ec9ff")
    if answer != ff_correct_answers[index1]:
        cor.grid_forget()
        inc.grid(row=packRow, column=0)
    else:
        inc.grid_forget()
        cor.grid(row=packRow + 1, column=0)

def ffQ (index):
    #Prints out question (and sets global variables)
    global top
    global a1
    global a2
    global a3
    global a4
    top = Toplevel(bg="#5ec9ff")
    question = Label(top, text=ff_questions[index], wraplength=510, pady=80, font=("Comic Sans MS", 15, "normal", "italic"), bg="#5ec9ff")
    question.grid(row=0, column=0)
    #Then the answers
    a1 = Button(top, text=ff_answers[index][0], height=4, width=70, command=partial(setFFAnswer, index, 0, ff_answers[index][0]), bg="#82d5ff")
    a2 = Button(top, text=ff_answers[index][1], height=4, width=70, command=partial(setFFAnswer, index, 1, ff_answers[index][1]), bg="#82d5ff")
    a3 = Button(top, text=ff_answers[index][2], height=4, width=70, command=partial(setFFAnswer, index, 2, ff_answers[index][2]), bg="#82d5ff")
    a4 = Button(top, text=ff_answers[index][3], height=4, width=70, command=partial(setFFAnswer, index, 3, ff_answers[index][3]), bg="#82d5ff")
    a1.grid(row=1, column=0)
    a2.grid(row=2, column=0)
    a3.grid(row=3, column=0)
    a4.grid(row=4, column=0)
    #Disables pressed button
    if index == 0:
        ff1["state"] = DISABLED
        ff1["text"] = ""
        ff1["relief"] = "groove"
    elif index == 1:
        ff2["state"] = DISABLED
        ff2["text"] = ""
        ff2["relief"] = "groove"
    elif index == 2:
        ff3["state"] = DISABLED
        ff3["text"] = ""
        ff3["relief"] = "groove"
    elif index == 3:
        ff4["state"] = DISABLED
        ff4["text"] = ""
        ff4["relief"] = "groove"
    elif index == 4:
        ff5["state"] = DISABLED
        ff5["text"] = ""
        ff5["relief"] = "groove"

# My Buttons
# f = food, pc = pop culture, l = literature, c = capitals, ff = fun facts
# They are also numbered: 1 - 100 points, to 5 - 500 points

f1 = Button(game, text="100", height=7, width=30, borderwidth=5, relief="ridge", state=NORMAL, command=partial(foodQ, 0), bg="#82d5ff" )
f2 = Button(game, text="200", height=7, width=30, borderwidth=5, relief="ridge", state=NORMAL, command=partial(foodQ, 1), bg="#82d5ff" )
f3 = Button(game, text="300", height=7, width=30, borderwidth=5, relief="ridge", state=NORMAL, command=partial(foodQ, 2), bg="#82d5ff" )
f4 = Button(game, text="400", height=7, width=30, borderwidth=5, relief="ridge", state=NORMAL, command=partial(foodQ, 3), bg="#82d5ff" )
f5 = Button(game, text="500", height=7, width=30, borderwidth=5, relief="ridge", state=NORMAL, command=partial(foodQ, 4), bg="#82d5ff" )

pc1 = Button(game, text="100", height=7, width=30, borderwidth=5, relief="ridge", state=NORMAL, command=partial(pcQ, 0), bg="#82d5ff" )
pc2 = Button(game, text="200", height=7, width=30, borderwidth=5, relief="ridge", state=NORMAL, command=partial(pcQ, 1), bg="#82d5ff" )
pc3 = Button(game, text="300", height=7, width=30, borderwidth=5, relief="ridge", state=NORMAL, command=partial(pcQ, 2), bg="#82d5ff" )
pc4 = Button(game, text="400", height=7, width=30, borderwidth=5, relief="ridge", state=NORMAL, command=partial(pcQ, 3), bg="#82d5ff" )
pc5 = Button(game, text="500", height=7, width=30, borderwidth=5, relief="ridge", state=NORMAL, command=partial(pcQ, 4), bg="#82d5ff" )

l1 = Button(game, text="100", height=7, width=30, borderwidth=5, relief="ridge", state=NORMAL, command=partial(litQ, 0), bg="#82d5ff" )
l2 = Button(game, text="200", height=7, width=30, borderwidth=5, relief="ridge", state=NORMAL, command=partial(litQ, 1), bg="#82d5ff" )
l3 = Button(game, text="300", height=7, width=30, borderwidth=5, relief="ridge", state=NORMAL, command=partial(litQ, 2), bg="#82d5ff" )
l4 = Button(game, text="400", height=7, width=30, borderwidth=5, relief="ridge", state=NORMAL, command=partial(litQ, 3), bg="#82d5ff" )
l5 = Button(game, text="500", height=7, width=30, borderwidth=5, relief="ridge", state=NORMAL, command=partial(litQ, 4), bg="#82d5ff" )

c1 = Button(game, text="100", height=7, width=30, borderwidth=5, relief="ridge", state=NORMAL, command=partial(capitalQ, 0), bg="#82d5ff" )
c2 = Button(game, text="200", height=7, width=30, borderwidth=5, relief="ridge", state=NORMAL, command=partial(capitalQ, 1), bg="#82d5ff" )
c3 = Button(game, text="300", height=7, width=30, borderwidth=5, relief="ridge", state=NORMAL, command=partial(capitalQ, 2), bg="#82d5ff" )
c4 = Button(game, text="400", height=7, width=30, borderwidth=5, relief="ridge", state=NORMAL, command=partial(capitalQ, 3), bg="#82d5ff" )
c5 = Button(game, text="500", height=7, width=30, borderwidth=5, relief="ridge", state=NORMAL, command=partial(capitalQ, 4), bg="#82d5ff" )

ff1 = Button(game, text="100", height=7, width=30, borderwidth=5, relief="ridge", state=NORMAL, command=partial(ffQ, 0), bg="#82d5ff" )
ff2 = Button(game, text="200", height=7, width=30, borderwidth=5, relief="ridge", state=NORMAL, command=partial(ffQ, 1), bg="#82d5ff" )
ff3 = Button(game, text="300", height=7, width=30, borderwidth=5, relief="ridge", state=NORMAL, command=partial(ffQ, 2), bg="#82d5ff" )
ff4 = Button(game, text="400", height=7, width=30, borderwidth=5, relief="ridge", state=NORMAL, command=partial(ffQ, 3), bg="#82d5ff" )
ff5 = Button(game, text="500", height=7, width=30, borderwidth=5, relief="ridge", state=NORMAL, command=partial(ffQ, 4), bg="#82d5ff" )

f1.grid(row=1, column=0)
f2.grid(row=2, column=0)
f3.grid(row=3, column=0)
f4.grid(row=4, column=0)
f5.grid(row=5, column=0)

pc1.grid(row=1, column=1)
pc2.grid(row=2, column=1)
pc3.grid(row=3, column=1)
pc4.grid(row=4, column=1)
pc5.grid(row=5, column=1)

l1.grid(row=1, column=2)
l2.grid(row=2, column=2)
l3.grid(row=3, column=2)
l4.grid(row=4, column=2)
l5.grid(row=5, column=2)

c1.grid(row=1, column=3)
c2.grid(row=2, column=3)
c3.grid(row=3, column=3)
c4.grid(row=4, column=3)
c5.grid(row=5, column=3)

ff1.grid(row=1, column=4)
ff2.grid(row=2, column=4)
ff3.grid(row=3, column=4)
ff4.grid(row=4, column=4)
ff5.grid(row=5, column=4)

root.mainloop()


"""
    Module Name:
        System.py

    Abstract:
        This module implements the Python OS main window and args parser.

    Author:
        TheBigEye 2-Jul-2021 - Initial Version written on OS.py
        TheBigEye 31-Jul-2022 - Updated Version moved to System.py
"""

import os
from tkinter import PhotoImage, Tk

from Libs.pyLogger.Logger import Logger
from Libs.pyUtils.pyFetch import Color, get_neofetch

from System.core.boot import boot_check, set_boot, set_desktop_mode
from System.core.kernel import screen_check

OS_NAME = "Python OS"
OS_VERSION = "0.0.2"
OS_AUTHOR = "TheBigEye"
OS_LICENSE = "GPLv3"
OS_COPYRIGHT = "Copyright (C) 2022 TheBigEye"
OS_DESCRIPTION = "A simple OS simulator written in Python"

START_PROCESSES = {
    "SCREEN CHECK": [screen_check],
    "BOOT CHECK": [boot_check]
}

class Display(Tk):
    """ Start the window amd run the procresses """

    def __init__(self, processes: dict) -> None:
        """ Initializes the system """

        super().__init__()

        self.processes = processes
        self.title("Python OS")

        self.WIDTH = 1024
        self.HEIGHT = 600

        self.screen_width = self.winfo_screenwidth()
        self.screen_height = self.winfo_screenheight()
        self.window_x = (self.screen_width /2) - (self.WIDTH /2)
        self.window_y = (self.screen_height /2) - (self.HEIGHT /2)

        self.geometry('%dx%d+%d+%d' % (self.WIDTH, self.HEIGHT, self.window_x, self.window_y))
        self.resizable(False, False)

        self.ICON = PhotoImage(file = "Assets/Icon.png")

        self.configure(background= "#000000")
        self.wm_iconphoto(True, self.ICON)

        # Run the processes
        for process in self.processes:
            for function in self.processes[process]:
                function(self)

        self.update()
        self.mainloop()

class System():
    """ Parse arguments"""

    def run(argv: list[str]) -> None:
        """ Get the arguments and run them """

        arguments = ()
        for arg in argv:
            arguments += (arg,)

        # Check if the user wants to see the help
        if "--help" in arguments:
            print("""
            Command line arguments:
                --help: Shows this help.
                --version: Shows the version.
                --delete-logs: Deletes the logs.
                --set-boot int: Sets the boot.
                --neofetch: Shows the neofetch.
            """)

        # Check if the user wants to see the version
        if "--version" in arguments:
            print("""
            This is the version of the OS.py script.
            """)

        # Check if the user wants to delete the logs
        if "--delete-logs" in arguments:
            Logger.delete_logs()

        # Check if the user wants to set the boot
        if "--set-boot" in arguments:
            # get the value of the boot
            boot = arguments[arguments.index("--set-boot") + 1]
            # set the boot
            set_boot(boot)

        # Check if the user see the neofetch
        if "--neofetch" in arguments:
            print(
                get_neofetch(
                    "Assets/Data/logo.txt",
                    Color.YELLOW,
                    ["*", None, None, "#", None, None, None]
                )
            )

        # Check if the user wants to start the system
        if "--run-clean" in arguments:
            if os.name == "nt":
                os.system("cls")
            else:
                os.system("clear")
            Logger.delete_logs()
            Display(START_PROCESSES)

        if "--wm" in arguments:
            set_desktop_mode("0")

        if "--de" in arguments:
            set_desktop_mode("1")

        # If no arguments are given, run the OS
        if len(arguments) == 1:
            Display(START_PROCESSES)


import numpy as np
import math as mt
from Plot import plot_slam

class SLAM:

    #====================================
    #       Inizialize landmark
    #====================================
    #
    def __init__(self):
        self.mu = np.zeros((3, 1))
        self.sigma = np.zeros((3,3))

        self.errorMovementX = 0.001
        self.errorMovementY = 0.001
        self.errorMovementTeta = 0.0001

        self.errorMeasurementD = 0.1
        self.errorMeasurementTeta = 0.1

        self.R = [self.errorMovementX**2, self.errorMovementY**2, self.errorMovementTeta**2]
        self.Q = np.array([[self.errorMeasurementD**2, 0],
                            [0, self.errorMeasurementTeta**2]])

    #====================================
    #         Prediction landmark
    #====================================
    #
    # motion[0] = velocità lineare
    # motion[1] = velocità angolare
    # motion[2] = tempo
    #
    def predictionMove(self, motion):
        self.mu[0,0] += motion[0] * motion[2] * np.cos(self.mu[2,0])
        self.mu[1,0] += motion[0] * motion[2] * np.sin(self.mu[2,0])
        self.mu[2,0] += motion[1] * motion[2]
        while self.mu[2,0] >  np.pi: self.mu[2,0] -= 2*np.pi
        while self.mu[2,0] < -np.pi: self.mu[2,0] += 2*np.pi

        g = np.array([ [1, 0, -motion[0]*motion[2]*np.sin(self.mu[2,0])], [0, 1, motion[0]*motion[2]*np.cos(self.mu[2,0])], [0, 0, 1] ])
        G = np.vstack(( np.hstack(( g , np.zeros((3,len(self.mu)-3)) )) , np.hstack(( np.zeros((len(self.mu)-3,3)) , np.eye(len(self.mu)-3) )) ))

        self.sigma = np.dot( np.dot( G , self.sigma ) , np.transpose(G) )
        self.sigma[0,0] += self.R[0]
        self.sigma[1,1] += self.R[1]
        self.sigma[2,2] += self.R[2]

    #====================================
    #        Control landmark
    #====================================
    #
    # Lista di vettori contenente
    # le misure dei landmark
    # [[distanza, angolo], ...]
    #
    def controlLandmark(self, measures):
        for measure in measures:
            exist = False

            t = np.array([ [-measure[0,0]*np.sin(measure[1,0]+self.mu[2,0])] , [measure[0,0]*np.cos(measure[1,0]+self.mu[2,0])] ])
            Tmu = np.hstack(( np.eye(2) , t ))
            Tz = np.hstack(( np.array([ [np.cos(measure[1,0]+self.mu[2,0])] , [np.sin(measure[1,0]+self.mu[2,0])] ]) , t ))

            sigmaLL = np.dot( np.dot( Tmu , self.sigma[0:3,0:3] ) , np.transpose( Tmu ) )
            sigmaLL += np.dot( np.dot( Tz , self.Q ) , np.transpose( Tz ) )
            sigmaLL = 3 * np.array([np.sqrt(sigmaLL[0,0]), np.sqrt(sigmaLL[1, 1])])

            landmark = np.array([ self.mu[0] + measure[0,0]*np.cos(measure[1,0]+self.mu[2,0]) , self.mu[1] + measure[0,0]*np.sin(measure[1,0]+self.mu[2,0]) ])

            for i in range(2, int( ((len(self.mu)-1) / 2) + 1)):
                if -sigmaLL[0] <= landmark[0] - self.mu[2*i-1,0] <= sigmaLL[0] and -sigmaLL[1] <= landmark[1] - self.mu[2*i,0] <= sigmaLL[1]:
                    t = [i, measure[0,0], measure[1,0]]
                    self.correctionLandmark(t)
                    exist = True
                    break

            if not exist:
                self.addLandmark(landmark, measure)

    #====================================
    #         Add landmark
    #====================================
    #
    # landmark[0] = x       measure[0] = distanza misurata
    # landmark[1] = y       measure[1] = angolo misurato
    #
    def addLandmark(self, landmark, measure):
        self.mu = np.vstack(( self.mu , landmark ))

        t = np.array([ [-measure[0,0]*np.sin(measure[1,0]+self.mu[2,0])] , [measure[0,0]*np.cos(measure[1,0]+self.mu[2,0])] ])
        Tmu = np.hstack(( np.eye(2) , t ))
        Tz = np.hstack(( np.array([ [np.cos(measure[1,0]+self.mu[2,0])] , [np.sin(measure[1,0]+self.mu[2,0])] ]) , t ))

        sigmaLL = np.dot( np.dot( Tmu , self.sigma[0:3,0:3] ) , np.transpose( Tmu ) )
        sigmaLL += np.dot( np.dot( Tz , self.Q ) , np.transpose( Tz ) )
        sigmaLX = np.dot( Tmu , self.sigma[0:3,:] )

        self.sigma = np.hstack((self.sigma , np.transpose(sigmaLX) ))
        self.sigma = np.vstack((self.sigma , np.hstack(( sigmaLX , sigmaLL ))))

    #====================================
    #         Correction landmark
    #====================================
    #
    # landmark[0] = indice del landmark
    # landmark[1] = distanza del landmark
    # landmark[2] = angolo del landmark
    #
    def correctionLandmark(self, landmark):
        delta = np.array([[ self.mu[2*landmark[0]-1,0] - self.mu[0,0] , self.mu[2*landmark[0],0] - self.mu[1,0] ]]).T
        q = np.sqrt( delta.T.dot(delta) )[0,0]
        h = np.array([[ q , mt.atan2( delta[1,0], delta[0,0] ) - self.mu[2,0] ]]).T
        while h[1,0] >  np.pi: h[1,0] -= 2*np.pi
        while h[1,0] < -np.pi: h[1,0] += 2*np.pi

        H_t1 = np.hstack(( np.array([-q*delta[0,0] , -q*delta[1,0] , 0]) , np.arange(0,2*landmark[0]-4,1)*0 , np.array([q*delta[0,0] , q*delta[1,0]]) , np.arange(0,len(self.mu)-2*landmark[0]-1,1)*0 ))
        H_t2 = np.hstack(( np.array([delta[1,0] , -delta[0,0] , -(q**2)]) , np.arange(0,2*landmark[0]-4,1)*0 , np.array([-delta[1,0] , delta[0,0]]) , np.arange(0,len(self.mu)-2*landmark[0]-1,1)*0 ))
        H  = (1 / (q**2))*np.vstack(( H_t1, H_t2 ))

        K = np.dot( np.dot(self.sigma, H.T) , np.linalg.inv( np.dot( np.dot( H, self.sigma ) , H.T ) + self.Q ))

        T = -np.dot( K , H )
        for i in range(0, len(self.mu)): T[i,i] += 1

        self.mu += np.dot( K , np.array([[landmark[1]], [landmark[2]]]) - h )
        self.sigma = np.dot( T , self.sigma )

    #====================================
    #           Utility
    #====================================

    def plotSlam(self):
        plot_slam(self.mu, self.sigma)

    def getMu(self):
        return self.mu

    def getSigma(self):
        return self.sigma


import os
from non_personalised import non_personalised_rc
from CF_personalised import cf_personalised
from bcolour import bcolours

# Function to clear the console
def clearConsole():
    os.system('cls' if os.name == 'nt' else 'clear')

# if not found this will be raised
class MovieIdNotFoundError(Exception):
    pass

# welcome page
def welcomePage():
    clearConsole()
    print(bcolours.HEADER,bcolours.BOLD + "##             Welcome to the MovieMatch              ##" + bcolours.ENDC)
    print(bcolours.OKBLUE + "##                                                     ##" + bcolours.ENDC)
    print(bcolours.OKBLUE + "## This program will help you find a movie to watch    ##" + bcolours.ENDC)
    print(bcolours.OKBLUE + "##                                                     ##" + bcolours.ENDC)
    print(bcolours.OKBLUE + "## based on your" + bcolours.ENDC, bcolours.UNDERLINE,bcolours.FAIL + "past behavior and preferences" + bcolours.ENDC,bcolours.OKBLUE  + "       ##" + bcolours.ENDC)
    print(bcolours.OKBLUE + "##                                                     ##" + bcolours.ENDC)
    print(bcolours.OKBLUE + "## and also with " + bcolours.ENDC, bcolours.UNDERLINE,bcolours.FAIL + "current hot trends!" + bcolours.ENDC,bcolours.OKBLUE+"                ##" + bcolours.ENDC)
    print(bcolours.OKBLUE + "##                                                     ##" + bcolours.ENDC)
    print(bcolours.OKGREEN + "## Ready to explore? Let's begin your movie journey!   ##" + bcolours.ENDC)
    print(bcolours.OKBLUE + "##                                                     ##" + bcolours.ENDC)
    user_input = input(bcolours.WARNING + "Please enter your user id to continue: " + bcolours.ENDC)
    return user_input

# check if user id is valid or active
def checkUser(user_input):
    if int(user_input) in range(1,6041):
        return True
    else:
        return False

# enjoy movie page
def enjoyMovie():
    clearConsole()
    print(bcolours.HEADER + "##  Perfect choice!                                  " + bcolours.ENDC)
    print(bcolours.FAIL + "##  Light is down, stage is set!                 " + bcolours.ENDC)
    print(bcolours.OKGREEN + bcolours.BOLD + "##  Enjoy your movie!                                " + bcolours.ENDC)

# recommend movie page
def recommendMovie(non_personalised_movies, personalised_movies):
    count = 0
    while True:
        clearConsole()
        not_over = True
        if count+5 >= len(non_personalised_movies):
            not_over = False
            print(bcolours.HEADER + "##  Trending Now                                     ##" + bcolours.ENDC)
            for each in non_personalised_movies.iloc[count:].itertuples():
                print( bcolours.OKCYAN + "MovieId: " + bcolours.ENDC, str(each.MovieID) + bcolours.OKCYAN + " :: Movie name: " + bcolours.ENDC + str(each.Title)  +  bcolours.OKCYAN + " :: Movie genres: " + bcolours.ENDC + str(each.Genres))
            print("##                                                   ##")
            print( bcolours.HEADER + "##  Top Picks for you                                ##" + bcolours.ENDC)
            print("##                                                   ##")
            for each in personalised_movies.iloc[count:].itertuples():
                print(bcolours.OKGREEN + "MovieId: " + bcolours.ENDC + str(each.MovieID) + bcolours.OKGREEN + " :: Movie name: " + bcolours.ENDC + str(each.Title)  + bcolours.OKGREEN + " :: Movie genres: " + bcolours.ENDC + str(each.Genres))
            print(bcolours.FAIL + "##  End of the page                                  ##" + bcolours.ENDC)
            count = 0

        if not_over:
            print("##                                                   ##")
            print(bcolours.HEADER + "##  Trending Now                                     ##" + bcolours.ENDC)
            for each in non_personalised_movies.iloc[count:count+5].itertuples():
                print(bcolours.OKCYAN + "MovieId: " + bcolours.ENDC + str(each.MovieID) + bcolours.OKCYAN + " :: Movie name: " + bcolours.ENDC + str(each.Title)  + bcolours.OKCYAN + " :: Movie genres: " + bcolours.ENDC + str(each.Genres))
            print("##                                                   ##")
            print(bcolours.HEADER + "##  Top Picks for you                                ##" + bcolours.ENDC)
            print("##                                                   ##")
            for each in personalised_movies.iloc[count:count+5].itertuples():
                print(bcolours.OKGREEN + "MovieId: " + bcolours.ENDC + str(each.MovieID) + bcolours.OKGREEN + " :: Movie name: " + bcolours.ENDC + str(each.Title)  + bcolours.OKGREEN + " :: Movie genres: " + bcolours.ENDC + str(each.Genres))

        print("##                                                   ##")
        print(bcolours.OKGREEN + "##  Would you like to watch any of these movies?     ##" + bcolours.ENDC)
        if not_over:
            user_input = input(bcolours.WARNING + "Enter movie ID to enjoy the movie, if want to see more options, enter c to continue explore: " + bcolours.ENDC)
        else:
            user_input = input(bcolours.FAIL + "Enter movie ID to enjoy the movie, this is end of the page, enter c to continue explore: " + bcolours.ENDC)

        if user_input == "c":
            if not_over:
                count += 10
        else:
            try:
                user_input = int(user_input)
                if int(user_input) in non_personalised_movies["MovieID"].values or int(user_input) in personalised_movies["MovieID"].values:
                    clearConsole()
                    enjoyMovie()
                    break
                elif int(user_input) not in personalised_movies["MovieID"].values:
                    raise MovieIdNotFoundError("Invalid movie ID. Please enter a valid movie ID or c to continue explore.")
            except ValueError:
                input(bcolours.FAIL + "I am sorry, I didn't get that. Please enter a valid movie ID or c to continue explore." + bcolours.ENDC)
                continue
            except MovieIdNotFoundError:
                input(bcolours.FAIL + "Invalid movie ID. Please enter a valid movie ID or c to continue explore." + bcolours.ENDC)

# wrong user id page
def wrongUser():
    print( bcolours.FAIL +"##  Sorry, we can't find your user id.                ##" + bcolours.ENDC)
    print( bcolours.FAIL +"##  Please try again.                          ##" + bcolours.ENDC)

# main function
def main():
    user_input = welcomePage()
    if checkUser(user_input):
        clearConsole()
        print( bcolours.HEADER,bcolours.BOLD + "##  Welcome back, USER:" + bcolours.ENDC,bcolours.OKBLUE,bcolours.ITALIC + str(user_input) + bcolours.ENDC,bcolours.HEADER,bcolours.BOLD + "                      ##" + bcolours.ENDC)
        print( bcolours.OKGREEN + "##  Let's find a movie for you!                      ##" + bcolours.ENDC)
        print( bcolours.WARNING + "##  Processing...                                    ##" + bcolours.ENDC)
        user_id = int(user_input)
        non_personalised_movies = non_personalised_rc(user_id,100)
        personalised_movies = cf_personalised(user_id,100)
        recommendMovie(non_personalised_movies=non_personalised_movies, personalised_movies=personalised_movies)
    else:
        clearConsole()
        wrongUser()

main()


import numpy as np
import pandas as pd
pd.set_option('max_colwidth',50)
pd.set_option('max_columns',250)
pd.set_option('max_rows',500)

import statsmodels.api as sm
from statsmodels.tsa.stattools import adfuller
from statsmodels.tsa.stattools import adfuller, kpss, acf, grangercausalitytests
from statsmodels.graphics.tsaplots import plot_acf, plot_pacf,month_plot,quarter_plot
from scipy import signal

#visualizations
import folium
from folium import plugins
from folium.plugins import HeatMap
import matplotlib
import matplotlib.pyplot as plt
from mpl_toolkits.axes_grid1 import make_axes_locatable
import seaborn as sns
import cufflinks as cf
import plotly.plotly as py
import plotly.graph_objs as go
import plotly.figure_factory as ff
from plotly import tools as tls
from plotly.offline import download_plotlyjs, init_notebook_mode, plot, iplot
init_notebook_mode(connected=True)
from mpl_toolkits.basemap import Basemap
from pylab import rcParams
cf.go_offline()
cf.set_config_file(world_readable=True,theme='white') # Make all charts public and set a global theme
sns.set_style("whitegrid") #possible choices: white, dark, whitegrid, darkgrid, ticks

### Define function for dataset statistics ###
def get_stats(df, sort_by='Different Values', sort_how=False, exclude=[], include_only=[], target='target'):
        columns = [c for c in df.columns.values if c not in exclude and c in include_only]
        df=df[columns]
        # Total missing values
        mis_val = df.isnull().sum()

        # Percentage of missing values
        mis_val_percent = 100 * df.isnull().sum() / len(df)

        # Data types
        data_types = df.dtypes

        # Different Values
        other_values = pd.DataFrame(columns=['Different Values','Most Common','% of Most Common','Skewness',
                                            'Kurtosis','Mean','Min','25% quantile','Median','75% quantile','Max'])
        for c in columns:
            if (df[c].dtype != 'object'):
                other_values = other_values.append({
                    'Name' : c,
                    'Different Values' : df[c].value_counts().count(),
                    'Most Common' : df[c].value_counts().idxmax(),
                    '% of Most Common' : 100*df[c].value_counts().max() / df[c].value_counts().sum(),
                    'Skewness' : df[c].skew(),
                    'Kurtosis' : df[c].kurt(),
                    'Mean' : df[c].mean(),
                    'Min' : df[c].min(),
                    '25% quantile' : df[c].quantile(0.25),
                    'Median' : df[c].median(),
                    '75% quantile' : df[c].quantile(0.75),
                    'Max' : df[c].max(),
                                                    }, ignore_index=True)
            else:
                other_values = other_values.append({
                    'Name' : c,
                    'Different Values' : df[c].value_counts().count(),
                    'Most Common' : df[c].value_counts().idxmax(),
                    '% of Most Common' : 100*df[c].value_counts().max() / df[c].value_counts().sum()
                                                    }, ignore_index=True)
        other_values = other_values.set_index('Name')

        # Make a table with the results
        mis_val_table = pd.concat([data_types, other_values, mis_val, mis_val_percent], axis=1, sort=False)

        # Rename the columns
        mis_val_table_ren_columns = mis_val_table.rename(
        columns = {0:'Type',
                   'Different Values':'Different Values',
                   'Most Common':'Most Common',
                   '% of Most Common':'% of Most Common',
                   'Skewness':'Skewness',
                   'Kurtosis':'Kurtosis',
                   1:'Missing Values',
                   2:'% of Missing Values',
                   'Mean' : 'Mean',
                   'Min' : 'Min',
                   '25% quantile' : '25% quantile',
                   'Median' : 'Median',
                   '75% quantile' : '75% quantile',
                   'Max' : 'Max',
        })

        # Sort the table
        mis_val_table_ren_columns = mis_val_table_ren_columns.sort_values(sort_by, ascending=sort_how)
        df = mis_val_table_ren_columns

        # Re-arrange columns
        #cols = df.columns.tolist()
        #cols = cols[0:1] + cols[7:8]# + cols[0:1] + cols[2:3] + cols[3:4] + cols[5:6] + cols[4:5] + cols[6:7] +cols[7:8] +cols[8:9] + cols[9:10]
        #df = df[cols]

        # Print some summary information
        print ("Your selected dataframe has " + str(df.shape[0]) + " columns. (" +
        str(df[df['Type']=='object'].shape[0])+" categorical and "+str(df[df['Type']!='object'].shape[0])+" numerical).\n"
        "There are " + str(df[df['Missing Values']>0].shape[0]) +" columns that have missing values, of which " +
        str(df[df['% of Missing Values']>=90].shape[0]) + " have over 90%!\n" +
        str(df[(df['Type']=='object')&(df['Different Values']<5)].shape[0]) +
        " object type columns have less than 5 different values and you can consider one-hot encoding, while " +
        str(df[(df['Type']=='object')&(df['Different Values']>=5)].shape[0]) +
        " have more than 5 colums and you can consider label encoding.\n" +
        str(df[df['Skewness']>1].shape[0]) + " columns are highly positively skewed (skewness>1), while " +
        str(df[df['Skewness']<-1].shape[0]) + " columns are highly negatively skewed (skewness<-1).\n" +
        str(df[(df['Skewness']>-0.5)&(df['Kurtosis']<0.5)].shape[0]) + " columns are symmetrical (-0.5<skewness<0.5).\n" +
        str(df[df['Kurtosis']>3].shape[0]) + " columns have high kurtosis (kurtosis>3) and should be check for outliers, while " +
        str(df[df['Kurtosis']<3].shape[0]) + " columns have low kurtosis (kurtosis<3). "
        )

        # Return the dataframe with missing information
        return mis_val_table_ren_columns

### Define function for Univariate Plots
def plot_univariate(df, plot_title):
    hist_data = []
    hist_data.extend([df])

    group_labels = ['Surface Temperature']
    fig = ff.create_distplot(hist_data, group_labels, show_hist=True)
    distplot1=fig['data']

    trace = go.Box(y=df, name='', pointpos = -1.8, jitter = 0.3, boxpoints = 'all')

    my_fig = tls.make_subplots(rows=1, cols=2, print_grid=False)
    my_fig.layout.update(title=plot_title, barmode = 'overlay', bargap=0.04, height=360, width=940, showlegend=False)

    my_fig.append_trace(distplot1[0], 1, 1)
    my_fig.append_trace(distplot1[1], 1, 1)
    my_fig.append_trace(trace, 1, 2)
    iplot(my_fig)

### Define function for Map Plot
def plot_map(df,variable,title,saveFig=False):
    # How much to zoom from coordinates (in degrees)
    zoom_scale = 0
    lats = df['Center Lat'].tolist()
    lons = df['Center Long'].tolist()
    prob = df[variable].tolist()

    # Setup the bounding box for the zoom and bounds of the map
    bbox = [np.min(lats)-zoom_scale,np.max(lats)+zoom_scale,\
            np.min(lons)-zoom_scale,np.max(lons)+zoom_scale]

    fig, ax = plt.subplots(figsize=(20,10))
    ax.set_title(title, fontsize = 24, loc='center')
    matplotlib.rcParams.update({'font.size': 14})
    # Define the projection, scale, the corners of the map, and the resolution.
    m = Basemap(projection='cyl',llcrnrlat=29.75,urcrnrlat=46.25, llcrnrlon=-6,urcrnrlon=36.5,lat_ts=10,resolution='h')
    m.bluemarble()

    # Draw coastlines and fill continents and water with color
    m.drawcoastlines()
    #m.fillcontinents(color='#CCCCCC',lake_color='lightblue')

    # draw parallels, meridians, and color boundaries
    m.drawparallels(np.arange(29.75,46.25,(46.25-30)/5),labels=[1,0,0,0])
    m.drawmeridians(np.arange(-6,36.5,(36.5+6)/5),labels=[0,0,0,1],rotation=15)
    m.drawmapboundary(fill_color='lightblue')

    # format colors for elevation range
    alt_min = np.min(prob)
    alt_max = np.max(prob)
    cmap = plt.get_cmap('jet') #jet,nipy_spectral,YlOrRd,hot_r
    normalize = matplotlib.colors.Normalize(vmin=alt_min, vmax=alt_max)

    from matplotlib.patches import Rectangle
    from matplotlib.patches import FancyBboxPatch

    # the range [50,250] can be changed to create different colors and ranges
    for ii in range(0,len(prob)):
        x,y = m(lons[ii],lats[ii])
        color_interp = np.interp(prob[ii],[alt_min,alt_max],[50,250])
        rect=plt.Rectangle(xy=(x-0.25,y-0.25),linewidth=0.6, width=0.5,height=0.5,fill=True, alpha=0.8,color=cmap(int(color_interp)))
        border=plt.Rectangle(xy=(x-0.25,y-0.25),linewidth=0.2, width=0.5,height=0.5,fill=False, alpha=0.7,color="#000088")
        ax.add_patch(rect);ax.add_patch(border)

    # format the colorbar
    divider = make_axes_locatable(ax)
    cax = divider.append_axes("right", size="3%", pad=0.05)
    cbar = matplotlib.colorbar.ColorbarBase(cax, cmap=cmap,norm=normalize)

    # save the figure and show it
    if (saveFig == True):
        plt.savefig(title+'.png', format='png', dpi=500,transparent=True)
    plt.show()

### Define Function for Time Series Line Plot
def time_plot(df,variable,title,y_axis_title):
    fig, ax = plt.subplots(figsize=(15, 6))
    sns.lineplot(df.index, df[variable] )

    ax.set_title(title, fontsize = 20, loc='center', fontdict=dict(weight='bold'))
    ax.set_xlabel('Year', fontsize = 16, fontdict=dict(weight='bold'))
    ax.set_ylabel(y_axis_title, fontsize = 16, fontdict=dict(weight='bold'))
    plt.tick_params(axis='y', which='major', labelsize=16)
    plt.tick_params(axis='x', which='major', labelsize=16)
    ax.yaxis.tick_left()

### Define Function for Time Series Seasonality Plots
def seasonality_plot(df,variable,title,y_axis_title=''):
    #variable = 'salinitySurface'
    fig, ax = plt.subplots(figsize=(15, 6))

    palette = sns.color_palette("ch:2.5,-.2,dark=.3", 10)
    sns.lineplot(df['month'], df[variable], hue=df['year'], palette=palette)
    ax.set_title(title, fontsize = 20, loc='center', fontdict=dict(weight='bold'))
    ax.set_xlabel('Month', fontsize = 16, fontdict=dict(weight='bold'))
    ax.set_ylabel(y_axis_title, fontsize = 16, fontdict=dict(weight='bold'))

    fig, ax = plt.subplots(nrows=1, ncols=2, figsize=(15, 6))

    sns.boxplot(df['year'], df[variable], ax=ax[0])
    ax[0].set_title('Year-wise Box Plot\n(The Trend)', fontsize = 20, loc='center', fontdict=dict(weight='bold'))
    ax[0].set_xlabel('Year', fontsize = 16, fontdict=dict(weight='bold'))
    ax[0].set_ylabel(y_axis_title, fontsize = 16, fontdict=dict(weight='bold'))

    sns.boxplot(df['month'], df[variable], ax=ax[1])
    ax[1].set_title('Month-wise Box Plot\n(The Seasonality)', fontsize = 20, loc='center', fontdict=dict(weight='bold'))
    ax[1].set_xlabel('Month', fontsize = 16, fontdict=dict(weight='bold'))
    ax[1].set_ylabel(y_axis_title, fontsize = 16, fontdict=dict(weight='bold'))

### Decomposition and strength of trend and seasonality###
def decomposition(df,variable):

    y = df[[variable]]
    rcParams['figure.figsize'] = 15, 12
    rcParams['axes.labelsize'] = 20
    rcParams['ytick.labelsize'] = 16
    rcParams['xtick.labelsize'] = 16
    decomposition = sm.tsa.seasonal_decompose(y, model='additive')
    decomp = decomposition.plot()
    decomp.suptitle('', fontsize=22)

    trend_strength = max(0,(1-decomposition.resid.var()/(decomposition.resid+decomposition.trend).var())[0])
    seasonality_strength = max(0,(1-decomposition.resid.var()/(decomposition.resid+decomposition.seasonal).var())[0])
    print("Trend strength:",trend_strength)
    print("Seasonality strength:",seasonality_strength)

### Augmented Dickey-Fuller Test to check for Stationarity
def adf_test(series,title=''):
    """
    Pass in a time series and an optional title, returns an ADF report
    """
    print('Augmented Dickey-Fuller Test: {}'.format(title))
    result = adfuller(series.dropna(),autolag='AIC') # .dropna() handles differenced data

    labels = ['ADF test statistic','p-value','# lags used','# observations']
    out = pd.Series(result[0:4],index=labels)

    for key,val in result[4].items():
        out['critical value ({})'.format(key)]=val

    print(out.to_string())          # .to_string() removes the line "dtype: float64"

    if result[1] <= 0.05:
        print("Strong evidence against the null hypothesis")
        print("Reject the null hypothesis")
        print("Data has no unit root and is stationary")
    else:
        print("Weak evidence against the null hypothesis")
        print("Fail to reject the null hypothesis")
        print("Data has a unit root and is non-stationary")


'''
display date time on Live video
also display frame size
'''

import cv2 as cv
import datetime as dt

# intialize default camera
cap = cv.VideoCapture(0)

print(" Camera available : ", cap.isOpened())

# properties of captured device can be taken using get()
framewidth  = cap.get( cv.CAP_PROP_FRAME_WIDTH )
frameheight = cap.get( cv.CAP_PROP_FRAME_HEIGHT )

print(" Frame width  : ", framewidth)
print(" Frame height : ", frameheight)

while(True):
    # read return isReadable, frame(image)
    retain, frame = cap.read()

    if retain == True:

        fontface = cv.FONT_HERSHEY_SIMPLEX
        # form text
        text = ' W: ' + str(framewidth) + '  ' + 'H: ' + str(frameheight) + ' Date: ' + str(dt.datetime.now())
        # put on display
        frame = cv.putText( frame, text, (0,20), fontface, 0.4, (100,220,36), 1, cv.LINE_AA)
        # display captured frame
        cv.imshow("Frame", frame)

        # break loop on press q
        if cv.waitKey( 1 ) & 0xFF == ord('q'):
            break
    else:
        break
# release captured device
cap.release()
cv.destroyAllWindows()


from rest_framework import serializers

from api.models import Agendas, Consultas, Especialidades, Medicos
from api.validators import Validators
from datetime import date

class EspecialidadesSerializer(serializers.ModelSerializer):
    class Meta:
        model = Especialidades
        fields = ["id", "nome"]

class MedicosSerializer(serializers.ModelSerializer):

    especialidade = EspecialidadesSerializer(many=False)

    class Meta:
        model = Medicos
        fields = ["id", "crm", "nome", "especialidade"]

class AgendaSerializer(serializers.ModelSerializer):

    medico = MedicosSerializer()
    horarios = serializers.StringRelatedField(
        many=True, source='horarios_disponiveis')

    class Meta:
        model = Agendas
        fields = ['id', 'medico', 'dia', 'horarios']

class CurrentUserDefault:
    requires_context = True

    def __call__(self, serializer_field):
        return serializer_field.context['request'].user

class ConsultaSerializer(serializers.ModelSerializer):

    agenda_id = serializers.PrimaryKeyRelatedField(
        queryset=Agendas.objects.filter(dia__gte=date.today()),
        write_only=True,
        label='agenda'
    )

    dia = serializers.DateField(source="agenda.dia", read_only=True)

    medico = MedicosSerializer(source="agenda.medico", read_only=True)

    user = serializers.HiddenField(default=CurrentUserDefault())

    class Meta:
        model = Consultas
        fields = ['id', 'dia', 'horario', 'data_agendamento',
                  'medico', 'user', 'agenda_id']

    def validate(self, data):

        agenda = data['agenda_id']
        horario = data['horario']

        if Validators().data_expirada(agenda.dia, horario):
            raise serializers.ValidationError(
                "Data e hora informados são menores do que a data atual"
            )

        if Validators().mesmo_dia_para_usuario(agenda.dia, horario, data['user']):
            raise serializers.ValidationError(
                'Paciente já possui uma consulta marcada para esse dia e horário'
            )

        if Validators().agenda_em_uso(agenda.pk, horario):

            raise serializers.ValidationError('Agenda em uso')

        if not agenda.horarios.filter(disponivel=True, hora=horario).exists():
            raise serializers.ValidationError('Horário indisponível')

        return data

    def create(self, data):

        agenda = data.pop('agenda_id')

        return Consultas.objects.create(
            dia=agenda.dia,
            agenda=agenda,
            user=data['user'],
            horario=data['horario']
        )


#!/usr/bin/python

import fnmatch
import os
import glob
import re

class StaticPhpScanner:

    def __init__(self, folder=None, recursive=False):
        """ Constructor

        """
        self.folder = folder
        self.recursive = recursive
        self.patterns = ['\$_(?P<method>(GET|POST|COOKIE))\[(\'|")(?P<var>[a-z0-9-_:]+)(\'|")\]',
                         '\$_(?P<method>SERVER)\[(\'|")(?P<var>(HTTP_REFERER|HTTP_USER_AGENT))(\'|")\]']

    def searchFiles(self, folder, recursive):
        """ Search php files in folder

        """
        files = []
        if recursive:
            for root, dirnames, filenames in os.walk(folder):
                for filename in fnmatch.filter(filenames, '*.php'):
                    files.append(os.path.join(root, filename))
        else:
            files = glob.glob("%s/*.php" % folder)

        return files

    def parsePages(self, files):
        """ Find entrypoint in files

        """
        result = {}
        compiledPatterns = []

        for pattern in self.patterns:
            regexp = re.compile(pattern, re.IGNORECASE)
            compiledPatterns.append(regexp)

        for file in files:
            result[file] = []
            with open(file, 'r') as lines:
                line_number = 0
                for line in lines:
                    line_number = line_number + 1
                    for pattern in compiledPatterns:
                        for m in pattern.finditer(line):
                            found = m.groupdict()
                            result[file].append({'line': line_number,
                                                 'method': found['method'],
                                                 'var': found['var']})
            if len(result[file]) == 0:
                result.pop(file, None)
        return result

    def scan(self, output):
        """ Begin file scanning

        """
        files = self.searchFiles(self.folder, self.recursive)
        return self.parsePages(files)


class Solution:
    def getSkyline(self, buildings: List[List[int]]) -> List[List[int]]:
        heap = []
        points = set([x[0] for x in buildings] + [x[1] for x in buildings])
        ans = [[-1, 0]]

        def addToSkyline(P):
            if ans[-1][1] != P[1]:
                ans.append(P)

        i = 0
        for p in sorted(points):

            while i < len(buildings) and buildings[i][0] <= p:
                heapq.heappush(heap, (-buildings[i][2], buildings[i][1]))
                i += 1

            while heap and heap[0][1] <= p:
                heapq.heappop(heap)

            height = -heap[0][0] if heap else 0
            addToSkyline((p, height))

        return ans[1:]


# coding=gbk
# 中文模型
from transformers import AutoModelForQuestionAnswering, BertTokenizer, BertForQuestionAnswering
import torch
# if torch.cuda.is_available():
#     device = torch.device("cuda")
#     print('there are %d GPU(s) available.'% torch.cuda.device_count())
#     print('we will use the GPU: ', torch.cuda.get_device_name(0))
# else:
#     print('No GPU availabel, using the CPU instead.')
#     device = torch.device('cpu')
device = torch.device('cpu')
# model = BertForQuestionAnswering.from_pretrained('E:\\Dataset\\pytorch-Bert\\bert-base-chinese')
# tokenizer = BertTokenizer.from_pretrained('E:\\Dataset\\pytorch-Bert\\bert-base-chinese')
model = BertForQuestionAnswering.from_pretrained('../Model/chinese-roberta-wwm-ext-finetuned-cmrc2018')
tokenizer = BertTokenizer.from_pretrained('../Model/chinese-roberta-wwm-ext-finetuned-cmrc2018')

# model = BertForQuestionAnswering.from_pretrained('E:\\Dataset\\pytorch-Bert\\albert-chinese-large-qa')
# tokenizer = BertTokenizer.from_pretrained('E:\\Dataset\\pytorch-Bert\\albert-chinese-large-qa')
# model = BertForQuestionAnswering.from_pretrained('E:\\Dataset\\pytorch-Bert\\chinese-roberta-wwm-ext\\finetune')
# tokenizer = BertTokenizer.from_pretrained('E:\\Dataset\\pytorch-Bert\\chinese-roberta-wwm-ext\\finetune')
model.to(device)

def read_text(text):
    text_name = "../Data/data_512.txt"
    file = open(text_name, mode='r', encoding="gbk")
    for line in file:
        text += line.strip('\n')
    file.close()
    print(text)
    return text

text = ""
text = read_text(text)
# text = "关于支持“双招双引”的十条意见。为落实市委、市政府“突出开放招商 强化项目带动”的部署，完善“壶兰计划”人才政策，促进招商引资和招才引智实效,为莆田落实高质量赶超提供人才保障，结合莆田实际，现提出以下意见。1.对来莆田创新创业和成果转化的国内外高层次创新创业团队，经认定，在“壶兰计划”补助的基础上，再给予 100 万元用于科学研究；对诺贝尔奖获得者、“两院”院士、国家最高科学技术奖获得者等顶尖人才或携带具有国际先进水平技术成果产业化项目来莆落户的创业团队，通过“一事一议”方式报请市委、市政府研究同意，最高给予 5000 万元资助。责任单位：市委组织部、市科技局。2.对实际投资 2 亿元或年纳税总额 5000 万元以上的招商项目(包括现有企业增加投资、企业并购增加投资)，世界 500 强企业的外商直接投资项目(投资额不设下限)，当年度投资（使用自有资金，下同）到位 5000 万元，给予自主认定四类人才指标 1名，每增加实际到位投资额 5000 万元增加 1 名指标，同一企业当年度最多不超过 10 名。责任单位：市发改委、市财政局、市工信局、市商务局。"

questions = [
    "壶兰计划是哪个市的？",
    "诺贝尔奖获得者可以获得多少补助？",
    "同一企业当年度最多不超过多少名人才指标？",
    "“双招双引”给出哪些意见？",
    "在“壶兰计划”补助的基础上，再给予多少万元用于科学研究？"
]

# text = "萤火虫工作室是一家总部设在英国伦敦和康涅狄格州坎顿，并在苏格兰阿伯丁设有质量部门的电子游戏开发商。" \
#        "1999年8月，西蒙·布雷德伯里，埃里克·乌列特和大卫·莱斯特成立萤火虫工作室，一起开发了很多游戏，" \
#        "包括非常成功的“凯撒” 和“王国霸主”系列。公司成立后，萤火虫工作室发布了一个未来前景规划：" \
#        "“萤火虫工作室要创造一个人们游戏其中的引人瞩目的新世界。我们要提供一个丰富多彩的游戏环境，" \
#        "令玩家在我们的图像和编码技术不断提升的游戏世界中感到愉快。我们的专长是在游戏中开发战略，" \
#        "而我们今后要继续发展，与我们精彩的视觉效果，引人瞩目的人物和易于上手的特点相结合。" \
#        "如果我们能这样完成工作，玩家将会发现一个自己创造的，加进自己个性的世界”。" \
#        "该公司将市场定位于PC(Windows)和苹果电脑上的即时战略游戏领域，特别是公司成功的“要塞”系列。" \
#        "目前，他们正在开发PC和Xbox360上的次时代游戏。"
# questions = [
#     "萤火虫工作室的总部设在哪里？",
#     "该公司将市场定位于什么？",
#     "谁成立了萤火虫公司？"
#     ]

# text = "《神盾局特工》（英语：Agents of S.H.I.E.L.D.）是一部美国广播公司于2013年制作并播出的电视剧，" \
#        "由乔斯·温登根据漫威漫画中的同名组织神盾局为蓝本创作，属于漫威电影宇宙的系列作品之一，" \
#        "从电影系列的第二阶段开始。“神盾局”（S.H.I.E.L.D.）是“国土战略防御攻击与后勤保障局”" \
#        "（Strategic Homeland Intervention，Enforcement and Logistics Division）的简称，" \
#        "前身为“战略科学军团”（Strategic Scientific Reserve, S.S.R.），在第二次世界大战期间，" \
#        "为了对抗“九头蛇”（HYDRA）而由同盟国联合组成。"
#
# questions = [
#     "《神盾局特工》是哪个公司制作的？",
#     "“神盾局”是什么的简称？",
#     "“神盾局”是为了对抗哪个组织而由同盟国联合组成的？",
#     "神盾局是什么时候成立的？"
# ]

# text = "株洲北站全称广州铁路（集团）公司株洲北火车站。除站场主体，另外管辖湘潭站、湘潭东站和三个卫星站，田心站、白马垅站、十里冲站，以及原株洲车站货房。车站办理编组、客运、货运业务。车站机关地址：湖南省株洲市石峰区北站路236号，邮编412001。株洲北站位于湖南省株洲市区东北部，地处中南路网，是京广铁路、沪昆铁路两大铁路干线的交汇处，属双向纵列式三级七场路网性编组站。车站等级为特等站，按技术作业性质为编组站，按业务性质为客货运站，是株洲铁路枢纽的主要组成部分，主要办理京广、沪昆两大干线四个方向货物列车的到发、解编作业以及各方向旅客列车的通过作业。每天办理大量的中转车流作业，并有大量的本地车流产生和集散，在路网车流的组织中占有十分重要的地位，是沟通华东、华南、西南和北方的交通要道，任务艰巨，作业繁忙。此外，株洲北站还有连接石峰区喻家坪工业站的专用线。株洲北站的前身是田心车站。"
# questions = [
#     "株洲北站的机关地址是什么",
#     "株洲北站管辖哪些站？"
#     ]

for question in questions:
    # inputs = tokenizer(question, text, add_special_tokens=False, return_tensors="pt")
    inputs = tokenizer(question, text, add_special_tokens=False, return_tensors="pt")
    # input_ids = inputs["input_ids"].tolist()[0]
    input_ids = inputs["input_ids"][0]
    text_tokens = tokenizer.convert_ids_to_tokens(input_ids)
    answer_start_scores, answer_end_scores = model(**inputs)
    answer_start = torch.argmax(
        answer_start_scores
    )  # Get the most likely beginning of answer with the argmax of the score
    answer_end = torch.argmax(answer_end_scores) + 1  # Get the most likely end of answer with the argmax of the score
    answer = tokenizer.convert_tokens_to_string(tokenizer.convert_ids_to_tokens(input_ids[answer_start:answer_end]))
    # answer_end = torch.argmax(answer_end_scores)+1  # Get the most likely end of answer with the argmax of the score
    # answer = text_tokens[answer_start:answer_end]
    # answer = "".join(answer)
    print(f"Question: {question}")
    print(f"Answer: {answer}")
    # inputs = tokenizer(question, text, return_tensors="pt").to(device)
    # tokens = tokenizer.convert_ids_to_tokens(inputs["input_ids"][0])
    # start_scores, end_scores = model(**inputs)
    # answer_start = torch.argmax(start_scores)
    # answer_end = torch.argmax(end_scores)+1
    # answer = tokens[answer_start:answer_end]
    # str = ""
    # print(str.join(answer))
    # print("标准答案：湖南省株洲市石峰区北站路236号，邮编412001。")


from paste import httpserver

from u1db.remote import (
    http_app,
    server_state,
    )

def make_server(host, port, working_dir):
    """Make a server on host and port exposing dbs living in working_dir."""
    state = server_state.ServerState()
    state.set_workingdir(working_dir)
    application = http_app.HTTPApp(state)
    server = httpserver.WSGIServer(application, (host, port),
                                   httpserver.WSGIHandler)
    return server


import cmath
from opender.auxiliary_funcs import sym_component

class DEROutputs:
    """
    DER model outputs, in terms of active and reactive power, currents, or voltage behind impedance
    EPRI Report Reference: Section 3.11 in Report #3002026631: IEEE 1547-2018 OpenDER Model
    """

    def __init__(self, der_obj):

        self.der_file = der_obj.der_file
        self.exec_delay = der_obj.exec_delay
        self.der_input = der_obj.der_input

        self.p_out_pu = 0    # DER output active power in per unit based on the DER nameplate apparent power rating
        self.q_out_pu = 0    # DER output reactive power in per unit based on the DER nameplate apparent power rating
        self.p_out_w = 0     # DER output active power in Watts
        self.q_out_var = 0   # DER output reactive power in vars
        self.p_out_kw = 0    # DER output active power in kilowatts
        self.q_out_kvar = 0  # DER output reactive power in kilovars

        self.i_a_pu = 0     # DER output phase a current in per unit
        self.i_b_pu = 0     # DER output phase b current in per unit
        self.i_c_pu = 0     # DER output phase c current in per unit
        self.i_mag_pu = [0, 0, 0]   # For single phase DER: an array of a single floating number of DER output current magnitude in per unit
                                    # For three phase DER: an array of three floating numbers of DER three phase output current magnitude in per unit
        self.i_mag_amp = [0, 0, 0]  # DER output current magnitude in ampere
        self.i_theta = [0, 0, 0]    # DER output current phase angle

        self.v_pos_out_cmd_pu = 0   # DER output positive sequence voltage magnitude before limitation in per unit
        self.v_neg_out_cmd_pu = 0   # DER output negative sequence voltage magnitude before limitation in per unit

        self.v_pos_out_pu = 0       # DER output positive sequence voltage magnitude in per unit
        self.v_neg_out_pu = 0       # DER output negative sequence voltage magnitude in per unit
        self.v_a_out_pu, self.v_b_out_pu, self.v_c_out_pu = 0, 0, 0  # DER output phase voltage in per unit
        self.v_out_mag_pu = [0, 0, 0]   # For single phase DER: an array of a single floating number of DER output voltage magnitude in per unit
                                        # For three phase DER: an array of three floating numbers of DER three phase output voltage magnitude in per unit
        self.v_out_mag_v = [0, 0, 0]    # DER output voltage magnitude in volts
        self.v_out_theta = [0, 0, 0]    # DER output voltage phase angle

    def calculate_p_q_output(self, i_pos_pu):
        """
        Calculate DER output active and reactive power

        Used variables as inputs:
        :param i_pos_pu:	DER output positive sequence current in per unit
        :param v_pos_pu:	Positive sequence voltage at RPA
        :param NP_VA_MAX:	DER nameplate apparent power rating
        """
        # Eq 3.11.1-1 Calculate DER output active and reactive power based on current and voltage
        self.p_out_pu = (i_pos_pu * self.der_input.v_pos_pu.conjugate()).real
        self.q_out_pu = -(i_pos_pu * self.der_input.v_pos_pu.conjugate()).imag

        # Eq 3.11.1-2 Calculate DER output P and Q in watts, vars
        self.p_out_w = self.p_out_pu * self.der_file.NP_VA_MAX
        self.q_out_var = self.q_out_pu * self.der_file.NP_VA_MAX

        # Eq 3.11.1-3 Calculate DER output P and Q in kW and kvar
        self.p_out_kw = self.p_out_w * 1e-3
        self.q_out_kvar = self.q_out_var * 1e-3

        return self.p_out_w, self.q_out_var

    def calculate_i_output(self, i_pos_pu, i_neg_pu):
        """
        Calculate DER output currents

        Used variables as inputs:
        :param i_pos_pu:	DER output positive sequence current in per unit
        :param i_neg_pu	DER output negative sequence current in per unit
        :param v_pos_pu:	Positive sequence voltage at RPA
        :param v_neg_pu:	Negative sequence voltage at RPA
        :param v_angle:	Voltage angle at RPA in radian
        :param NP_VA_MAX:	DER nameplate apparent power rating
        :param NP_AC_V_NOM:	AC voltage base—nominal voltage rating
        :param NP_PHASE:	Single- or Three-phase DER
        """

        if self.der_file.NP_PHASE == "THREE":
            # Eq 3.11.2-1, calculate three phase current
            self.i_a_pu, self.i_b_pu, self.i_c_pu = sym_component.convert_symm_to_abc(i_pos_pu, i_neg_pu)

            self.i_mag_pu = [abs(self.i_a_pu), abs(self.i_b_pu), abs(self.i_c_pu)]

            # Eq 3.11.2-2, calculate three phase current in ampere
            self.i_mag_amp = [i * self.der_file.NP_VA_MAX / self.der_file.NP_AC_V_NOM * 0.5773502691896258 for i in
                              self.i_mag_pu]

            # Eq 3.11.2-3, Calculate current phase angles
            self.i_theta = [cmath.phase(self.i_a_pu), cmath.phase(self.i_b_pu), cmath.phase(self.i_c_pu)]
        else:
            # Eq 3.11.2-4, calculate current amplitude and angles for single phase DER
            self.i_mag_pu = [abs(i_pos_pu)]
            self.i_mag_amp = [self.i_mag_pu * self.der_file.NP_VA_MAX / self.der_file.NP_AC_V_NOM]
            self.i_theta = [cmath.phase(i_pos_pu)]

    def calculate_v_output(self, i_pos_pu, i_neg_pu):
        """
        Calculate DER output currents

        Used variables as inputs:
        :param i_pos_pu:	DER output positive sequence current in per unit
        :param i_neg_pu	DER output negative sequence current in per unit
        :param v_pos_pu:	Positive sequence voltage at RPA
        :param v_neg_pu:	Negative sequence voltage at RPA
        :param v_angle:	Voltage angle at RPA in radian
        :param NP_VA_MAX:	DER nameplate apparent power rating
        :param NP_AC_V_NOM:	AC voltage base—nominal voltage rating
        :param NP_PHASE:	Single- or Three-phase DER
        :param NP_RESISTANCE:	DER source resistance for voltage output
        :param NP_REACTANCE:	DER source reactance for voltage output
        """

        # Eq 3.11.3-1, calculate DER output voltage based on measured voltage, calculated current and impedance
        self.v_pos_out_cmd_pu = self.der_input.v_pos_pu + i_pos_pu * (self.der_file.NP_RESISTANCE + 1j * self.der_file.NP_REACTANCE)
        self.v_neg_out_cmd_pu = self.der_input.v_neg_pu + i_neg_pu * (self.der_file.NP_RESISTANCE + 1j * self.der_file.NP_REACTANCE)

        # Limit output voltage based on DER inverter DC voltage
        self.v_pos_out_pu, self.v_neg_out_pu = self.v_limit(self.v_pos_out_cmd_pu, self.v_neg_out_cmd_pu)

        if self.der_file.NP_PHASE == "THREE":
            # Eq 3.11.3-4, Calculate three phase voltages in per unit based on limited positive and negative voltage
            self.v_a_out_pu, self.v_b_out_pu, self.v_c_out_pu = sym_component.convert_symm_to_abc(self.v_pos_out_pu, self.v_neg_out_pu, self.der_input.v_zero_pu)
            self.v_out_mag_pu = [abs(self.v_a_out_pu), abs(self.v_b_out_pu), abs(self.v_c_out_pu)]

            # Eq 3.11.3-5, Calculate three phase voltage in volts
            self.v_out_mag_v = [i * self.der_file.NP_AC_V_NOM * 0.5773502691896258 for i in self.v_out_mag_pu]

            # Eq 3.11.3-6, Calculate three phase voltage angles
            self.v_out_theta = [cmath.phase(self.v_a_out_pu), cmath.phase(self.v_b_out_pu), cmath.phase(self.v_c_out_pu)]
        else:

            # Eq 3.11.3-7~9, Calculate three phase voltage angles
            self.v_out_mag_pu = [abs(self.v_pos_out_pu)]
            self.v_out_mag_v = [self.v_out_mag_pu * self.der_file.NP_AC_V_NOM]
            self.v_out_theta = [cmath.phase(self.v_pos_out_pu)]

    def v_limit(self, pos_pu, neg_pu):
        v_limit = self.der_file.NP_V_DC / self.der_file.NP_AC_V_NOM

        # Eq 3.11.3-2, calculate maximum phase voltage
        v_max_pu = max([abs(x) for x in sym_component.convert_symm_to_abc(pos_pu, neg_pu)])
        if v_max_pu > v_limit:
            # Eq 3.11.3-3 reduce voltage output to the voltage limited by the DER inverter DC voltage
            pos_out_pu = pos_pu * v_limit / v_max_pu
            neg_out_pu = neg_pu * v_limit / v_max_pu
        else:
            pos_out_pu = pos_pu
            neg_out_pu = neg_pu

        return pos_out_pu, neg_out_pu


'''
Factorials
Write two methods to calculate Factorials for an input number.
In the first method calculate it iteratively.

In the second method calculate it recursively.
The results can be output to standard output, returned from the function as an array/list, etc.
'''
import math

def factorial(number):
    if number == 0:
        return 1
    else:
        return number * factorial(number-1)

def factorial_itr(number):
    num = 1
    while number >= 1:
        num = num * number
        number = number - 1
    return num


"""
Optimizers for skip-thoughts
"""
import theano
import theano.tensor as tensor
import numpy

def adam(lr, tparams, grads, inp, cost):
    gshared = [theano.shared(p.get_value() * 0., name='%s_grad'%k) for k, p in tparams.items()]
    gsup = [(gs, g) for gs, g in zip(gshared, grads)]

    f_grad_shared = theano.function(inp, cost, updates=gsup, profile=False)

    lr0 = 0.0002
    b1 = 0.1
    b2 = 0.001
    e = 1e-8

    updates = []

    i = theano.shared(numpy.float32(0.))
    i_t = i + 1.
    fix1 = 1. - b1**(i_t)
    fix2 = 1. - b2**(i_t)
    lr_t = lr0 * (tensor.sqrt(fix2) / fix1)

    for p, g in zip(tparams.values(), gshared):
        m = theano.shared(p.get_value() * 0.)
        v = theano.shared(p.get_value() * 0.)
        m_t = (b1 * g) + ((1. - b1) * m)
        v_t = (b2 * tensor.sqr(g)) + ((1. - b2) * v)
        g_t = m_t / (tensor.sqrt(v_t) + e)
        p_t = p - (lr_t * g_t)
        updates.append((m, m_t))
        updates.append((v, v_t))
        updates.append((p, p_t))
    updates.append((i, i_t))

    f_update = theano.function([lr], [], updates=updates, on_unused_input='ignore', profile=False)

    return f_grad_shared, f_update


from PIL import Image
import cv2
from pathlib import Path
import numpy as np
airship_graphic=Path("RenderedRedFortune.png")
Original_Image = cv2.imread(airship_graphic.as_posix(),cv2.IMREAD_UNCHANGED)
print(Original_Image.shape)
def rotate_image(img, angle,size):
    size_reverse = np.array(img.shape[1::-1]) # swap x with y
    M = cv2.getRotationMatrix2D(tuple(size_reverse / 2.), angle, 1.)
    MM = np.absolute(M[:,:2])
    #size_new = MM @ size_reverse

    M[:,-1] += (size - size_reverse) / 2.
    return cv2.warpAffine(img, M, tuple(size))

#create new headings
headings=np.linspace(0,360,361)
for angle in headings:
    rotated_image1 = rotate_image(Original_Image,angle,size=[4000,4000])
    cv2.imwrite("Airship Assets/Airship Headings/RenderedRedFortune{:02d}deg.png".format(int(angle)),rotated_image1)


from collections import OrderedDict
import json
import os
from utils.widgets import InfoButton

from django.utils.translation import gettext_lazy as _

from stemp_abw.forms import LayerGroupForm, ComponentGroupForm, AreaGroupForm

# do not execute when on RTD (reqd for API docs):
if 'READTHEDOCS' not in os.environ:
    from stemp_abw.forms import ScenarioDropdownForm

from stemp_abw.app_settings import layer_areas_metadata, layer_region_metadata,\
    layer_result_metadata, LAYER_DEFAULT_STYLES, ESYS_COMPONENTS_METADATA,\
    ESYS_AREAS_METADATA, labels, text_files_dir

def prepare_layer_data():

    def _config2layer(cat_name, layer_cfg_metadata):
        layer_data = {}
        _labels = labels()

        # create layer list for AJAX data urls,
        # include show (initial showup) and title (for spinner)
        layer_list = {l: {'show': d['show'],
                          'model': d['model'],
                          'cat': cat_name}
                      for ls in layer_cfg_metadata.values()
                      for l, d in ls.items()}
        for l, v in layer_list.items():
            layer_list[l]['title'] = _labels['layers'][l]['title']

        # create JSON for layer styles
        layer_style = {l: a['style']
                       for v in layer_cfg_metadata.values()
                       for l, a in v.items()}
        layer_style.update(LAYER_DEFAULT_STYLES)

        # create dict choropleth layers
        choropleth_data = {l: a['choropleth']
                           for v in layer_cfg_metadata.values()
                           for l, a in v.items() if 'choropleth' in a}

        # update layer and layer group _labels using _labels config
        layer_metadata = OrderedDict()
        for (grp, layers) in layer_cfg_metadata.items():
            layer_metadata.update({grp: {'layers': layers}})
            layer_metadata[grp]['title'] = _labels['layer_groups'][grp]['title']
            layer_metadata[grp]['text'] = _labels['layer_groups'][grp]['text']
            for l, v in layers.items():
                layer_metadata[grp]['layers'][l]['title'] = _labels['layers'][l]['title']
                layer_metadata[grp]['layers'][l]['text'] = _labels['layers'][l]['text']

        # create layer groups for layer menu using layers config
        layer_groups = layer_metadata.copy()
        for grp, layers in layer_metadata.items():
            layer_groups[grp]['layers'] = LayerGroupForm(layers=layers['layers'],
                                                         cat_name=cat_name)
        layer_data['layer_groups'] = layer_groups

        return layer_data, layer_list, layer_style, choropleth_data

    # categories are different lists of layers, e.g.
    # 'region' is for the info layers of the status quo (region panel)
    # 'areas' is for areas that put restrictions on use for e.g. wind turbines
    layer_categories = {'areas': layer_areas_metadata(),
                        'region': layer_region_metadata(),
                        'results': layer_result_metadata()}

    # init data dict
    layer_data = {'layer_list': {},
                  'layer_style': {},
                  'choropleth_data': {}
                  }

    # prepare and fill
    for cat, metadata in layer_categories.items():
        ld, ll, ls, cd = _config2layer(cat, metadata)
        layer_data.update({'layer_{cat}'.format(cat=cat): ld})
        layer_data['layer_list'].update(ll)
        layer_data['layer_style'].update(ls)
        layer_data['choropleth_data'].update(cd)

    # serialize style data
    layer_data['layer_style'] = json.dumps(layer_data['layer_style'])
    layer_data['choropleth_data'] = json.dumps(layer_data['choropleth_data'])

    return layer_data

def component_data():
    component_data_store = {}
    _labels = labels()

    # update component/area and group _labels using _labels config
    comp_metadata = OrderedDict()
    area_metadata = OrderedDict()
    for (grp, comps) in ESYS_COMPONENTS_METADATA.items():
        comp_metadata.update({grp: {'comps': comps}})
        comp_metadata[grp]['title'] = _labels['component_groups'][grp]['title']
        comp_metadata[grp]['text'] = _labels['component_groups'][grp]['text']
        for l, v in comps.items():
            comp_metadata[grp]['comps'][l]['title'] = _labels['components'][l]['title']
            comp_metadata[grp]['comps'][l]['text'] = _labels['components'][l]['text']

            # additional text
            if _labels['components'][l].get('text2') is not None:
                comp_metadata[grp]['comps'][l]['text2'] =\
                    _labels['components'][l]['text2']

            # reveal window
            reveal_id = _labels['components'][l].get('reveal_id')
            reveal_icon = _labels['components'][l].get('reveal_icon')
            if (reveal_id is not None) and (reveal_icon is not None):
                comp_metadata[grp]['comps'][l]['popup'] =\
                    create_panel_reveal_info_button(reveal_id, reveal_icon)
            else:
                comp_metadata[grp]['comps'][l]['popup'] = None

            # icon
            if _labels['components'][l].get('icon') is not None:
                comp_metadata[grp]['comps'][l]['icon'] =\
                    _labels['components'][l]['icon']
            else:
                comp_metadata[grp]['comps'][l]['icon'] = None

    for (grp, comps) in ESYS_AREAS_METADATA.items():
        area_metadata.update({grp: {'comps': comps}})
        area_metadata[grp]['title'] = _labels['component_groups'][grp]['title']
        area_metadata[grp]['text'] = _labels['component_groups'][grp]['text']
        for l, v in comps.items():
            area_metadata[grp]['comps'][l]['title'] = _labels['components'][l]['title']
            area_metadata[grp]['comps'][l]['text'] = _labels['components'][l]['text']

            # reveal window
            reveal_id = _labels['components'][l].get('reveal_id')
            reveal_icon = _labels['components'][l].get('reveal_icon')
            if (reveal_id is not None) and (reveal_icon is not None):
                area_metadata[grp]['comps'][l]['popup'] =\
                    create_panel_reveal_info_button(reveal_id, reveal_icon)
            else:
                area_metadata[grp]['comps'][l]['popup'] = None

            # icon
            if _labels['components'][l].get('icon') is not None:
                area_metadata[grp]['comps'][l]['icon'] =\
                    _labels['components'][l]['icon']
            else:
                area_metadata[grp]['comps'][l]['icon'] = None

    # create component groups for esys panel using components config
    comp_groups = comp_metadata.copy()
    for grp, comps in comp_groups.items():
        comp_groups[grp]['comps'] = ComponentGroupForm(components=comps['comps'])
    component_data_store['comp_groups'] = comp_groups

    # create area groups for areas panel (variable areas) using components config
    area_groups = area_metadata.copy()
    for grp, comps in area_groups.items():
        area_groups[grp]['comps'] = AreaGroupForm(components=comps['comps'])
    component_data_store['area_groups'] = area_groups

    return component_data_store

def prepare_scenario_data():
    """Create scenarios for scenario dropdown menu (tool initialization only)"""
    return {'scenarios': ScenarioDropdownForm()}

def create_panel_reveal_info_button(reveal_id, reveal_icon):
    """Creates reveal window with trigger button with content from markdown file
    (panel info button, e.g. in wind slider)
    """
    f = open(os.path.join(text_files_dir(), f'{reveal_id}.md'), 'r', encoding='utf-8')
    popup = InfoButton(text=f.read(),
                       tooltip=str(_('Bitte klicken!')),
                       is_markdown=True,
                       ionicon_type=reveal_icon,
                       ionicon_size='small',
                       ionicon_color='#F2994A',
                       info_id=reveal_id)
    f.close()
    return popup

# do not execute when on RTD (reqd for API docs):
if 'READTHEDOCS' not in os.environ:
    SCENARIO_DATA = prepare_scenario_data()