import tkinter as tk
from tkinter import ttk

# globals
option1 = False
option2 = False
option3 = False
option4 = False
option5 = False
option6 = False
option7 = False
option8 = False
race = ''

class ToggledFrame(tk.Frame):

    def __init__(self, parent, text="", *args, **options):
        tk.Frame.__init__(self, parent, *args, **options)

        self.show = tk.IntVar()
        self.show.set(0)

        self.title_frame = ttk.Frame(self)
        self.title_frame.pack(fill="x", expand=1)

        ttk.Label(self.title_frame, text=text).pack(side="left", fill="x", expand=1)

        self.toggle_button = ttk.Checkbutton(self.title_frame, width=2, text='+', command=self.toggle,
                                            variable=self.show, style='Toolbutton')
        self.toggle_button.pack(side="left")

        self.sub_frame = tk.Frame(self, relief="sunken", borderwidth=1)

    def toggle(self):
        if bool(self.show.get()):
            self.sub_frame.pack(fill="x", expand=1)
            self.toggle_button.configure(text='-')
        else:
            self.sub_frame.forget()
            self.toggle_button.configure(text='+')

def create_dashboard():
    root = tk.Tk()
    root.title("I know, I'm amazing")
    root.minsize(width=600, height=100)
    # root.maxsize(width=600, height=500)
    # scrollbar = tk.Scrollbar(root)
    # scrollbar.pack(side='right', fill='y')

    root_label1 = tk.Label(root, text="Jules's Path", font=20)
    root_label1.pack()
    root_label2 = tk.Label(root, text="A Choose-Your-Own Adventure Story")
    root_label2.pack()

    #################################
    # Introduction
    #################################
    intro = ToggledFrame(root, text='Introduction', relief="raised", borderwidth=1)
    intro.pack(fill="x", expand=1, pady=2, padx=2, anchor="n")

    ttk.Label(intro.sub_frame, text="Once upon a time, in a galaxy far, far away... There lived a brave adventurer named Jules."
                                  "\nShe loved exploring and helping people, so she set out through the woods with one goal: "
                                  "\none day, she would save the world.").pack()
    ttk.Label(intro.sub_frame, text='\nChoose a race').pack()
    message = ''
    racepick = ttk.Label(intro.sub_frame, text=message)
    def pick_race(value):
        global race
        race = value
        if value == 'infp':
            message = "You gain a bonus to diplomacy and have a giant bunny companion\n"
        elif value == 'elf':
            message = "You've lived in the forest for hundreds of years and own a magical sword.\n"
        else:
            message = "LOTR races are overrated! You have a long neck and are fluent in GSL (Giraffe Sign Language).\n"
        racepick.config(text=message)
    innerintro = ttk.Frame(intro.sub_frame)
    ttk.Button(innerintro, text='INFP', command=lambda: pick_race('infp')).grid(row=0, column=1)
    ttk.Button(innerintro, text='Elf', command=lambda: pick_race('elf')).grid(row=0, column=2)
    ttk.Button(innerintro, text='Giraffe', command=lambda: pick_race('giraffe')).grid(row=0, column=3)

    # add empty columns before and after to center
    innerintro.grid_columnconfigure(0, weight=1)
    innerintro.grid_columnconfigure(4, weight=1)
    innerintro.pack()

    racepick.pack()

    #################################
    # Chapter 1
    #################################
    # troll bridge - infp option = empathize
    #   - RIGHT UNDERSTANDING - see the world as it really is
    ch1 = ToggledFrame(root, text='Chapter 1', relief="raised", borderwidth=1)
    ch1.pack(fill="x", expand=1, pady=2, padx=2, anchor="n")

    ttk.Label(ch1.sub_frame, text="\nWhile traveling through the forest, Jules approached a bridge over a small creek. There "
                                  "\nwas a troll blocking the way. She noticed that the troll looked weak and hungry. He "
                                  "\nwouldn't pose much of a challenge if things got messy. When the troll demanded that she "
                                  "\npay a toll to cross, Jules heard childlike giggling from beneath the bridge.").pack()
    message = ''
    ch1pick = ttk.Label(ch1.sub_frame, text=message)
    def pick_ch1(value):
        global race
        global option1
        if value == 'choice1':
            option1 = False
            message = "You easily defeat the weak troll! Two emaciated troll children come out from under the bridge and " \
                      "\nrun away sobbing. They get lost. One starves to death alone in the forest and the other ends up being" \
                      "\nadopted by an angry and abusive drunk in town. He grows up never remembering what it was like to " \
                      "\nbe loved."
        elif value == 'choice2':
            option1 = True
            message = "The troll looks relieved, thanks you, and lets you pass. Later that day, you spot the troll in town " \
                      "\nbuying food for his starving children. They all look happy."
        else:
            if race == 'infp':
                option1 = True
                message = "You ask the troll if everything is alright. He looks surprised. Nobody has ever asked him that" \
                          "\nbefore. He lets his guard down and says it's been a rough year. You begin to understand that he's" \
                          "\nacting out of desperation. He tells you that he just lost his wife and is having a hard time " \
                          "\nraising the kids alone. He just wants money to help feed them. You give him some money for food, " \
                          "\nbut also tell him about a friend in your hometown who's hiring and owes you a favor. You tell " \
                          "\nthe troll to head there and mention your name. You've befriended the troll and set him up with a " \
                          "\nsteady job. He thanks you profusely for understanding and caring. His children come out from" \
                          "\nhiding and hug you. They all head off toward town with hope in their hearts."
            else:
                option1 = False
                message = "You're not an INFP! Pick again."
        ch1pick.config(text=message)
    innerch1 = ttk.Frame(ch1.sub_frame)
    ttk.Button(innerch1, text='Slay the troll', command=lambda: pick_ch1('choice1')).grid(row=0, column=1)
    ttk.Button(innerch1, text='Pay the toll', command=lambda: pick_ch1('choice2')).grid(row=0, column=2)
    ttk.Button(innerch1, text='Empathize and listen (INFP only)', command=lambda: pick_ch1('choice3')).grid(row=0, column=3)

    # add empty columns before and after to center
    innerch1.grid_columnconfigure(0, weight=1)
    innerch1.grid_columnconfigure(4, weight=1)
    innerch1.pack()

    ch1pick.pack()

    #################################
    # Chapter 2
    #################################
    # lost - giraffe option = get directions from nearby deaf giraffes
    #   - RIGHT INTENT - passion for the journey, commitment to the path
    ch2 = ToggledFrame(root, text='Chapter 2', relief="raised", borderwidth=1)
    ch2.pack(fill="x", expand=1, pady=2, padx=2, anchor="n")

    ttk.Label(ch2.sub_frame,
              text="Jules set out toward the jungles far to the south. It was rumored that there was a long-forgotten "
                   "\ncivilization hidden under all the foliage there. After several days of travel through a foggy valley, "
                   "\nover a pink glacier, and past a prairie of tall grass and passionflowers, Jules finally reached the "
                   "\nedge of the jungle. She ventured in without a map, and it wasn't long before she got lost.").pack()
    message = ''
    ch2pick = ttk.Label(ch2.sub_frame, text=message)

    def pick_ch2(value):
        global race
        global option2
        if value == 'choice1':
            option2 = False
            message = "You give up searching and turn back. Had you continued on, you would have scared off a warthog, which " \
                      "\nlater ended up walking into a family of leopards. You didn't though, so the leopards kept hunting and " \
                      "\neventually found a young troll cultist nearby. He managed to escape them, but not before they ate his " \
                      "\nfoot. The troll boy would now walk with a peg leg and a painful limp for rest of his life."
        elif value == 'choice2':
            option2 = True
            message = "You continue searching and eventually find some stones with beautiful carvings. You bring them to the" \
                      "\nnext town you get to and donate them to the local museum. The curator insists on a small reward. You " \
                      "\ncontinue on your journey knowing you've preserved a small part of history."
        else:
            if race == 'giraffe':
                option2 = True
                message = "You break out your GSL and ask some giraffes in the nearby prairie where to find the ruins. They " \
                          "\ngive you directions to a waterfall and say the entrance is hidden behind it. You look behind " \
                          "\nthe waterfall and discover an entire lost city of immeasurable beauty. When you get to the next" \
                          "\ntown, you find the curator of the local museum and he organizes an expedition based on your " \
                          "\ndirections. The city is able to be studied in great depth and generations of historians benefit " \
                          "\nfrom what is discovered about the lost civilization."
            else:
                option2 = False
                message = "You're not a Giraffe! Pick again."
        ch2pick.config(text=message)

    innerch2 = ttk.Frame(ch2.sub_frame)
    ttk.Button(innerch2, text='Give up', command=lambda: pick_ch2('choice1')).grid(row=0, column=1)
    ttk.Button(innerch2, text='Keep looking', command=lambda: pick_ch2('choice2')).grid(row=0, column=2)
    ttk.Button(innerch2, text="Get directions from nearby deaf giraffes (Giraffe only)",
               command=lambda: pick_ch2('choice3')).grid(row=0, column=3)

    # add empty columns before and after to center
    innerch2.grid_columnconfigure(0, weight=1)
    innerch2.grid_columnconfigure(4, weight=1)
    innerch2.pack()

    ch2pick.pack()

    #################################
    # Chapter 3
    #################################
    # challenged to duel - elf option = "I have a secret: I'm not left-handed"
    #   - RIGHT SPEECH - thoughtful communication, words have great power, both good and bad
    ch3 = ToggledFrame(root, text='Chapter 3', relief="raised", borderwidth=1)
    ch3.pack(fill="x", expand=1, pady=2, padx=2, anchor="n")

    ttk.Label(ch3.sub_frame, text="That evening, Jules ordered dinner in a tavern. There were no empty tables, so she grabbed "
                                  "\na seat at a table with as few people as possible. One was a loud, drunk man who boasted "
                                  "\nabout his adventures. Jules minded her own business, but the drunk man at her table "
                                  "\naccidentally knocked over his own mead without noticing. When he turned back around and "
                                  "\nsaw his spilled drink, he looked at Jules with angry eyes and yelled at her for being so"
                                  "\nclumsy. He stood up (with difficulty) and pulled out his sword. He challenged Jules to "
                                  "\na duel.").pack()
    message = ''
    ch3pick = ttk.Label(ch3.sub_frame, text=message)
    def pick_ch3(value):
        global race
        global option3
        if value == 'choice1':
            option3 = False
            message = "The fight is over as fast as it begun; you're much too fast for his drunken reflexes. You stab him and " \
                      "\nhe falls over dead. His adopted troll son runs away screaming and sobbing. The son joins a cult of " \
                      "\nevil wizards and vows revenge. While in the cult, one of the evil wizards curses him to make all his " \
                      "\ndrinks taste like cucumber water for the rest of his life."
        elif value == 'choice2':
            option3 = True
            message = "Using a few choice words, you're able to convince him to lay down his sword. You offer to buy him another " \
                      "\ndrink and ask him about his adventures. He happily boasts for a while and reveals a few interesting " \
                      "\nsecrets that may be helpful to you on your journey. He wishes you luck on your travels and heads to bed."
        else:
            if race == 'elf':
                option3 = True
                message = "You've had many years to practice your swordplay. You brandish your sword, twirling it through the air " \
                          "\nwith incredible dexterity. The drunkard isn't scared off so easily, however. That is, until you say, " \
                          "\n\"I know something you don't know; I am not left-handed!\" You switch to your right hand. At this, " \
                          "\nhe steps back and lowers his weapon; he realizes his mistake and apologizes. You tell him not to " \
                          "\nworry and even offer to teach him a few moves. He seems grateful and offers to teach you what he knows. " \
                          "\nYou leave with a new fencing friend and a couple of new techniques that may come in handy."
            else:
                option3 = False
                message = "You're not an Elf! Pick again."
        ch3pick.config(text=message)
    innerch3 = ttk.Frame(ch3.sub_frame)
    ttk.Button(innerch3, text='Duel the drunkard', command=lambda: pick_ch3('choice1')).grid(row=0, column=1)
    ttk.Button(innerch3, text='Buy him a new drink', command=lambda: pick_ch3('choice2')).grid(row=0, column=2)
    ttk.Button(innerch3, text="Intimidate him (Elf only)", command=lambda: pick_ch3('choice3')).grid(row=0, column=3)

    # add empty columns before and after to center
    innerch3.grid_columnconfigure(0, weight=1)
    innerch3.grid_columnconfigure(4, weight=1)
    innerch3.pack()

    ch3pick.pack()

    #################################
    # Chapter 4
    #################################
    # starving sharks - share your food with them?
    #   - RIGHT ACTION - always take the ethical approach in life
    ch4 = ToggledFrame(root, text='Chapter 4', relief="raised", borderwidth=1)
    ch4.pack(fill="x", expand=1, pady=2, padx=2, anchor="n")

    ttk.Label(ch4.sub_frame,
              text="Jules eventually found her way to a short, beautiful cliff overlooking a cove that connected to the ocean. "
                   "\nShe heard screaming and looked down. She saw a troll boy splashing in the water, circled by a school of "
                   "\nsharks. He cried out to Jules for help.").pack()
    message = ''
    ch4pick = ttk.Label(ch4.sub_frame, text=message)

    def pick_ch4(value):
        global race
        global option4
        if value == 'choice1':
            option4 = False
            message = "Sharks and deep water? Screw that. You run like hell and let nature take its course. The troll boy " \
                      "\nmanages to swim to safety, but loses a hand in the process. He relives the trauma every day and " \
                      "\ngoes the rest of his life with night terrors and PTSD."
        else:
            option4 = True
            message = "You have rope you can throw him but it's too short. You run down to the water's edge and take a few " \
                      "\nbrave steps into the shark-infested waters. You toss the rope to him and he catches it. You're able " \
                      "\nto reel him in before the sharks can do any damage. He even punches a few in the nose and laughs " \
                      "\na couple times. He says thanks and runs off to tell the story of how he braved a pool of sharks to " \
                      "\nhis cultist buddies."
        ch4pick.config(text=message)

    innerch4 = ttk.Frame(ch4.sub_frame)
    ttk.Button(innerch4, text='Run away', command=lambda: pick_ch4('choice1')).grid(row=0, column=1)
    ttk.Button(innerch4, text='Try to save him', command=lambda: pick_ch4('choice2')).grid(row=0, column=2)

    # add empty columns before and after to center
    innerch4.grid_columnconfigure(0, weight=1)
    innerch4.grid_columnconfigure(3, weight=1)
    innerch4.pack()

    ch4pick.pack()

    #################################
    # Chapter 5
    #################################
    # protect a caravan - giraffe option = your long neck makes you a great lookout!
    #   - RIGHT LIVELIHOOD - pick a career that helps the community
    ch5 = ToggledFrame(root, text='Chapter 5', relief="raised", borderwidth=1)
    ch5.pack(fill="x", expand=1, pady=2, padx=2, anchor="n")

    ttk.Label(ch5.sub_frame,
              text="Jules walked east along a dirt road. A traveling caravan caught up to her, heading in the same direction. "
                   "\nThere were nine wagons, each carrying its own family and goods for sale. Roads were common places for "
                   "\nbandits to rob passersby. The leader of the caravan asked if Jules wanted to join them and even offered "
                   "\nto pay her to protect the wagons for the next couple days, until they reached the next big town.").pack()
    message = ''
    ch5pick = ttk.Label(ch5.sub_frame, text=message)

    def pick_ch5(value):
        global race
        global option5
        if value == 'choice1':
            option5 = False
            message = "You tell him you're not interested in helping. The caravan passes you. An hour later, you see the caravan" \
                      "\nagain in the distance. You catch up to it and see that it's been robbed and ransacked. There are dead" \
                      "\nbodies everywhere. There are ripped evil wizard cultist robes on the ground. There's also a pool of green " \
                      "\ntroll blood on the ground; evidently, a member of the caravan was able to injure one of the cultists " \
                      "\nwho attacked them."
        elif value == 'choice2':
            option5 = True
            message = "Your caravan approaches a small group of cultists blocking the road about an hour later. They seem " \
                      "\nhesitant due to the fact that they're outnumbered. You step forward and their confidence wavers, ever" \
                      "\nso slightly. It seems to be the straw that breaks the camel's back though; they decide to back off " \
                      "\nand let you pass. The caravan families thank you and pay you when you get to town safely."
        else:
            if race == 'giraffe':
                option5 = True
                message = "Your long neck makes you a great lookout! You can see a group of cultists far down the road and " \
                          "\nwarn the caravan not to go further. You also spot a somewhat hidden road off that appears to run" \
                          "\nparallel. You guide the caravan to this second road, which turns out to not only be bandit-free, " \
                          "\nbut a shortcut to town! The caravan families thank you profusely for protecting them. They pay" \
                          "\nyou double what you originally agreed to for showing them an alternate, safer route they can take " \
                          "\nin the future."
            else:
                option5 = False
                message = "You're not a Giraffe! Pick again."
        ch5pick.config(text=message)

    innerch5 = ttk.Frame(ch5.sub_frame)
    ttk.Button(innerch5, text='Ignore his request', command=lambda: pick_ch5('choice1')).grid(row=0, column=1)
    ttk.Button(innerch5, text='Protect the caravan', command=lambda: pick_ch5('choice2')).grid(row=0, column=2)
    ttk.Button(innerch5, text="Offer to be a lookout (Giraffe only)", command=lambda: pick_ch5('choice3')).grid(row=0, column=3)

    # add empty columns before and after to center
    innerch5.grid_columnconfigure(0, weight=1)
    innerch5.grid_columnconfigure(4, weight=1)
    innerch5.pack()

    ch5pick.pack()

    #################################
    # Chapter 6
    #################################
    # chasm with broken bridge - infp option = climb on the back of your giant bunny and hop to the other side
    #   - RIGHT EFFORT - positive attitude, cheerful determination
    ch6 = ToggledFrame(root, text='Chapter 6', relief="raised", borderwidth=1)
    ch6.pack(fill="x", expand=1, pady=2, padx=2, anchor="n")

    ttk.Label(ch6.sub_frame,
              text="Jules approached a rocky gorge with deep chasms and cracks. There was a large river at the bottom that "
                   "\nseemed tiny from this high up. An old and questionable rope bridge stretched across from one side to "
                   "\nthe other. There were no other ways across.").pack()
    message = ''
    ch6pick = ttk.Label(ch6.sub_frame, text=message)

    def pick_ch6(value):
        global race
        global option6
        if value == 'choice1':
            option6 = False
            message = "The bridge would probably break if you tried to cross it. You decide to turn back and head home. Later," \
                      "\na group of cultists approach the bridge and try to cross it. A few cultists begin to cross, including " \
                      "\na troll. The additional weight stresses the bridge and the rope snaps, sending them falling into the " \
                      "\nravine! The troll survives due to his Jiu Jitsu, but breaks several bones, including his butt. He'll " \
                      "\nnever sit comfortably again."
        elif value == 'choice2':
            option6 = True
            message = "Feeling hopeful, you cross the bridge. You make sure to be extra careful where you choose to step, but" \
                      "\nyour confidence prevents you from lingering and putting extra pressure on any one spot for too long." \
                      "\nJust as you make it to the other side, the rope finally gives way and snaps. You made it safely though," \
                      "\nand continue on your journey."
        else:
            if race == 'infp':
                option6 = True
                message = "You hug your giant bunny and climb onto its back. You scratch it behind its ears and it hops across" \
                          "\nthe chasm with joy. When you get to the other side, you notice that the rope bridge is a little weak" \
                          "\nfrom this side. You take a few minutes to re-secure the rope bridge on this side, allowing others to " \
                          "\ncross it without danger. You continue on your journey knowing you probably saved a life or two."
            else:
                option6 = False
                message = "You're not an INFP! Pick again."
        ch6pick.config(text=message)

    innerch6 = ttk.Frame(ch6.sub_frame)
    ttk.Button(innerch6, text='Turn back', command=lambda: pick_ch6('choice1')).grid(row=0, column=1)
    ttk.Button(innerch6, text='Give the bridge a chance', command=lambda: pick_ch6('choice2')).grid(row=0, column=2)
    ttk.Button(innerch6, text="Hop across with your giant bunny (INFP only)", command=lambda: pick_ch6('choice3')).grid(row=0, column=3)

    # add empty columns before and after to center
    innerch6.grid_columnconfigure(0, weight=1)
    innerch6.grid_columnconfigure(4, weight=1)
    innerch6.pack()

    ch6pick.pack()

    #################################
    # Chapter 7
    #################################
    # lava pit - swim through it and complain that it's too cold - skeletal remains of an INTJ nearby
    #   - RIGHT MINDFULNESS - be focused and undistracted in the moment
    ch7 = ToggledFrame(root, text='Chapter 7', relief="raised", borderwidth=1)
    ch7.pack(fill="x", expand=1, pady=2, padx=2, anchor="n")

    ttk.Label(ch7.sub_frame,
              text="News spread that a dragon egg had been spotted in the crater of an active volcano. An evil wizard cult"
                   "\nwanted to capture the egg for themselves to raise an evil dragon and conquer the world. When Jules "
                   "\nheard this, she knew she had to beat the cultists to the egg. She headed for the volcano and climbed "
                   "\nto the crater at the top. At the center of the lava pit was the dragon egg. Jules noticed a scorched "
                   "\nskeleton off to the side in the lava.").pack()
    message = ''
    ch7pick = ttk.Label(ch7.sub_frame, text=message)

    def pick_ch7(value):
        global race
        global option7
        if value == 'choice1':
            option7 = False
            message = "You head over to the skeleton. After careful analysis, you conclude these are the bones of an INTJ who" \
                      "\ntried to shower in the lava and burned to death. While investigating the bones, a troll cultist sneaks" \
                      "\nover to the egg and performs an evil summoning ritual. The dragon hatches and tries to eat the troll," \
                      "\nknocking him back into the lava. The troll manages to crawl out, but half his skin has melted off, leaving" \
                      "\nhim horribly disfigured. The evil ritual succeeds and so the dragon heralds an age of darkness upon " \
                      "\nthe land."
        else:
            option7 = True
            message = "You focus and head straight for the egg. As you swim through the lava pit, you complain that it's too" \
                      "\ncold. You hug the egg, showing it love and compassion. The dragon hatches as a good dragon, heralding" \
                      "\na golden age of peace and prosperity."
        ch7pick.config(text=message)

    innerch7 = ttk.Frame(ch7.sub_frame)
    ttk.Button(innerch7, text='Investigate the skeleton', command=lambda: pick_ch7('choice1')).grid(row=0, column=1)
    ttk.Button(innerch7, text='Head straight for the egg', command=lambda: pick_ch7('choice2')).grid(row=0, column=2)

    # add empty columns before and after to center
    innerch7.grid_columnconfigure(0, weight=1)
    innerch7.grid_columnconfigure(3, weight=1)
    innerch7.pack()

    ch7pick.pack()

    #################################
    # Chapter 8
    #################################
    # runes - elf option = you've lived for hundreds of years and recognize this ancient language
    #   - RIGHT CONCENTRATION - learn to focus and select worthy directions for the mind
    ch8 = ToggledFrame(root, text='Chapter 8', relief="raised", borderwidth=1)
    ch8.pack(fill="x", expand=1, pady=2, padx=2, anchor="n")

    ttk.Label(ch8.sub_frame,
              text="After saving/dooming the world, Jules decided to end her adventure. She headed back home. On the way "
                   "\nback, she found a giant boulder with a bunch of ancient runes carved into it.").pack()
    message = ''
    ch8pick = ttk.Label(ch8.sub_frame, text=message)

    def pick_ch8(value):
        global race
        global option8
        if value == 'choice1':
            option8 = False
            message = "Why would you click this?!"
        elif value == 'choice2':
            option8 = True
            message = "You feel that translating/learning languages is a worthy pursuit and take the time to decipher the runes."
        else:
            if race == 'elf':
                option8 = True
                message = "You recognize your old tongue: Quenya."
            else:
                option8 = False
                message = "You're not an Elf! Pick again."
        ch8pick.config(text=message)

    innerch8 = ttk.Frame(ch8.sub_frame)
    ttk.Button(innerch8, text="Languages are boring", command=lambda: pick_ch8('choice1')).grid(row=0, column=1)
    ttk.Button(innerch8, text="Take the time to decipher it", command=lambda: pick_ch8('choice2')).grid(row=0, column=2)
    ttk.Button(innerch8, text="Recognize the ancient language (Elf only)", command=lambda: pick_ch8('choice3')).grid(row=0, column=3)

    # add empty columns before and after to center
    innerch8.grid_columnconfigure(0, weight=1)
    innerch8.grid_columnconfigure(4, weight=1)
    innerch8.pack()

    ch8pick.pack()

    #################################
    # Epilogue
    #################################
    # display all choices and results
    epi = ToggledFrame(root, text='Epilogue', relief="raised", borderwidth=1)
    epi.pack(fill="x", expand=1, pady=2, padx=2, anchor="n")

    epipick1 = ttk.Label(epi.sub_frame)
    epipick2 = ttk.Label(epi.sub_frame)
    epipick3 = ttk.Label(epi.sub_frame)
    epipick4 = ttk.Label(epi.sub_frame)
    epipick5 = ttk.Label(epi.sub_frame)
    epipick6 = ttk.Label(epi.sub_frame)
    epipick7 = ttk.Label(epi.sub_frame)
    epipick8 = ttk.Label(epi.sub_frame)
    final1 = ttk.Label(epi.sub_frame)
    final2 = ttk.Label(epi.sub_frame)

    def pick_epi(value):
        global option1
        global option2
        global option3
        global option4
        global option5
        global option6
        global option7
        global option8

        message1 = ''
        message2 = ''
        message3 = ''
        message4 = ''
        message5 = ''
        message6 = ''
        message7 = ''
        message8 = ''

        if option1:
            message1 = "By paying the toll to help the troll, Jules demonstrated RIGHT UNDERSTANDING. " \
                       "\nShe understood that things aren't always as they appear. She saw the world as it really was."
        if option2:
            message2 = "By not giving up when she lost her way, Jules demonstrated RIGHT INTENT. " \
                       "\nHer passion for the journey and commitment to the path led her to what she sought."
        if option3:
            message3 = "By talking to the drunk man rather than fighting, Jules demonstrated RIGHT SPEECH." \
                       "\nWords have great power, both for good and for bad. Thoughtful communication helped her."
        if option4:
            message4 = "By trying to save the troll from the sharks, Jules demonstrated RIGHT ACTION." \
                       "\nShe always took the ethical approach in life, even when it wasn't easy."
        if option5:
            message5 = "By helping to protect the caravan, Jules demonstrated RIGHT LIVELIHOOD." \
                       "\nShe chose a job that helped those around her. She made a positive difference."
        if option6:
            message6 = "By crossing the chasm despite the obvious difficulties, Jules demonstrated RIGHT EFFORT." \
                       "\nHer positive attitude and cheerful determination helped her to move forward and make progress."
        if option7:
            message7 = "By going straight for the dragon egg, Jules demonstrated RIGHT MINDFULNESS." \
                       "\nShe remained focused and undistracted in the moment, keeping her primary goal in mind."
        if option8:
            message8 = "By deciphering the runes, Jules demonstrated RIGHT CONCENTRATION. " \
                       "\nShe learned to focus and select worthy directions for her mind."
        message9 = "\nJules was well on her way to Nirvana."
        message10 = "\n\nJules,\nYou've made this past month the happiest time of my life. I hope we're together for many more." \
                    "\n\nI see you.\n"

        epipick1.config(text=message1)
        epipick2.config(text=message2)
        epipick3.config(text=message3)
        epipick4.config(text=message4)
        epipick5.config(text=message5)
        epipick6.config(text=message6)
        epipick7.config(text=message7)
        epipick8.config(text=message8)
        final1.config(text=message9)
        final2.config(text=message10)

    ttk.Label(epi.sub_frame, text="Double-check your answers and then click below to generate the rune message!").pack()
    ttk.Button(epi.sub_frame, text="Generate runes",
               command=lambda: pick_epi('choice1')).pack()

    epipick1.pack()
    epipick2.pack()
    epipick3.pack()
    epipick4.pack()
    epipick5.pack()
    epipick6.pack()
    epipick7.pack()
    epipick8.pack()
    final1.pack()
    final2.pack()

    root.mainloop()

if __name__ == "__main__":
    create_dashboard()


from flask import Flask
import conversions
app = Flask(__name__)

@app.route("/speech2words/<string:speech>", methods=['GET'])
def speech2words(speech):
    converted_word = conversions.conversion_speech_to_word(speech)
    return converted_word

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


import os

os.environ.setdefault("DJANGO_SETTINGS_MODULE", "studentski_servis.settings")
import django

django.setup()
from .models import *
from datetime import datetime
import csv
import codecs

class KljucRecnika(object):
    def __init__(self, name):
        self.name = name

generisane_moguce_ucionice = "rg1,Rg1,RG1,rg2,Rg2,RG2,rg3,Rg3,RG3,rg4,Rg4,RG4,rg5,Rg5,RG5,rg6,Rg6,RG6,rg7,Rg7,RG7,rg8,Rg8,RG8,rg9,Rg9,RG9,rg10,Rg10,RG10,rg11,Rg11,RG11,rg12,Rg12,RG12,Atelje,Kolarac"

def broj_studenata_grupe(grupa):
    student_grupa = Student.grupa.through.objects.filter(grupa_id=grupa.id)
    return len(student_grupa)

def vratiTrenutnuGrupuZaStudenta(student):
    student_grupa = Student.grupa.through.objects.filter(student_id=student.id)
    student_grupa = student_grupa.latest('id')
    grupa = Grupa.objects.get(id=student_grupa.grupa_id)
    return grupa

def napraviUsernameNaloga(imeiprezime):
    imeiprezime_pocetno = imeiprezime.split()
    imeiprezime = imeiprezime.split()
    duzina = len(imeiprezime)
    tmp = ""
    if duzina > 2:
        for iks in imeiprezime:
            if iks == imeiprezime[duzina - 1]:
                break
            else:
                tmp += iks
        imeiprezime = imeiprezime[duzina - 1][0] + tmp
        return imeiprezime.lower()
    else:
        imeiprezime = imeiprezime[1][0] + imeiprezime[0]

    imeiprezime_temp = imeiprezime.lower()
    if Nalog.objects.filter(username=imeiprezime_temp).exists():
        if not Nastavnik.objects.filter(ime=imeiprezime_pocetno[1], prezime=imeiprezime_pocetno[0]).exists():
            i = 1
            while True:
                imeiprezime_temp = imeiprezime + str(i)
                if not Nalog.objects.filter(username=imeiprezime_temp).exists():
                    break
                else:
                    i = i + 1
            return imeiprezime_temp.lower()
    return imeiprezime.lower()

def provera_kapaciteta_izborne_grupe(izborna_grupa):
    try:
        broj_upisanih_studenata = len(IzborGrupe.objects.filter(izabrana_grupa=izborna_grupa))
        return broj_upisanih_studenata
    except IzborGrupe.DoesNotExist:
        print("smisli sta vracas ako ne postoji")
        return False  # ?

def vrati_podatke_tekuceg_semestra():
    """vraca podatke o tekucem semestru u redosledu: vrsta, godina_poc, godina_kraj"""
    semestar = Semestar.objects.filter(aktivan=True).order_by('-id').first()  # ako ima više aktivnih (greska), ali vratice onaj sa najvecim id-jem, nema izuzetka
    if semestar is None:
        semestar = Semestar.objects.order_by('-id').first()  # ako nema aktivnog vraca onaj sa najvecim id-jem
    return (semestar.vrsta, semestar.skolska_godina_pocetak, semestar.skolska_godina_kraj, semestar.aktivan)   #ako ne postoji aktivan semestar ovo vraca None exception

def vrati_trenutni_semestar():
    semestar = Semestar.objects.filter(aktivan=True).order_by(
        '-id').first()  # ako ima više aktivnih (greska), ali vratice onaj sa najvecim id-jem, nema izuzetka
    if semestar is None:
        semestar = Semestar.objects.order_by('-id').first()
    return semestar

def vrati_raspored_nastave_tekuceg_semestra():
    """Vraca raspored nastave tekuceg semestra"""
    semestar = vrati_podatke_tekuceg_semestra()
    semestar = Semestar.objects.get(vrsta=semestar[0], skolska_godina_pocetak=semestar[1],
                                    skolska_godina_kraj=semestar[2])
    raspored_nastave = RasporedNastave.objects.get(semestar_id=semestar.id)
    return raspored_nastave

def svi_termini_tekuceg_rasporeda():
    raspored = vrati_raspored_nastave_tekuceg_semestra()
    termini_query_set = Termin.objects.filter(raspored=raspored)
    termini = []
    for termin in termini_query_set:
        termini.append(termin)
    return termini

def termini_tekuceg_rasporeda_za_profesora(nalog):
    raspored = vrati_raspored_nastave_tekuceg_semestra()
    nastavnik = Nastavnik.objects.get(nalog=nalog)
    termini_query_set = Termin.objects.filter(raspored=raspored,nastavnik=nastavnik)
    termini = []
    for termin in termini_query_set:
        termini.append(termin)
    return termini

def vrati_grupe_tekuceg_semestra():
    """Vraca grupe koje pripadaju tekucem semestru"""
    semestar = vrati_podatke_tekuceg_semestra()
    semestar = Semestar.objects.get(vrsta=semestar[0], skolska_godina_pocetak=semestar[1],
                                    skolska_godina_kraj=semestar[2])
    grupe = Grupa.objects.filter(semestar_id=semestar.id)
    return grupe

def vrati_predmete_tekuceg_semestra():
    """Vraca sve predmete koji pripadaju tekucem semestru"""
    raspored_nastave = vrati_raspored_nastave_tekuceg_semestra()
    termini = Termin.objects.filter(raspored_id=raspored_nastave.id)
    predmeti = []
    for termin in termini:
        predmet_temp = Predmet.objects.get(id=termin.predmet_id)
        if not predmeti.__contains__(predmet_temp):
            predmeti.append(predmet_temp)
    return predmeti

def vrati_predmete_za_profesora(nastavnik):
    nastavnik_predmet = Nastavnik.predmet.through.objects.filter(nastavnik_id=nastavnik.id)
    predmeti = []
    for predmet in nastavnik_predmet:
        predmeti.append(Predmet.objects.get(id=predmet.predmet_id))
    return predmeti

def vrati_grupe_tekuceg_semestra_za_profesora(nastavnik):
    raspored_nastave = vrati_raspored_nastave_tekuceg_semestra()
    termini = Termin.objects.filter(nastavnik_id=nastavnik.id)
    termin_grupe = []
    grupe = []
    for termin in termini:
        termin_grupe.append(Termin.grupe.through.objects.filter(termin_id=termin.id))
    for termini in termin_grupe:
        for grupa in termini:
            grupe.append(Grupa.objects.get(id=grupa.grupa_id))
    return grupe

# bds - proveravaju se samo nastavnici, predmeti, datumi i vreme
# ne snima se fajl
def ucitaj_raspored_kolokvijuma(raspored_fajl):

    raspored_csv = csv.DictReader(codecs.iterdecode(raspored_fajl, 'utf-8'), delimiter=',')
    broj_ispravnih_linja = 0
    broj_neispravnih_linija = 0
    objasnjenje_za_liniju = dict()  # redni broj linje : tekst objasnjenja
    redni_broj_linije = 1
    ispravne_linje = []
    neispravne_linije = []
    ispravni_termini = []
    for linija in raspored_csv:
            redni_broj_linije+=1
            #Predmet:
            try:
                predmet = Predmet.objects.get(naziv=linija['Predmet'])
            except Predmet.DoesNotExist:
                broj_neispravnih_linija +=1
                neispravne_linije.append(linija)
                objasnjenje_za_liniju[redni_broj_linije] = ("Predmet \"" + linija['Predmet']+ "\" nije pronadjen u bazi. ",linija)
                continue
            #Nastavnik
            try:
                nastavnici = []
                if ',' in linija['Profesor']:
                    nastavnici_imena = linija['Profesor'].split(",")
                    for n in nastavnici_imena:
                        ime_prezime = n.split(" ", 1)
                        if len(ime_prezime) < 2:
                            raise Nastavnik.DoesNotExists
                        nastavnici.append(Nastavnik.objects.get(ime=ime_prezime[0].strip(), prezime=ime_prezime[1].strip()))
                else:
                    ime_prezime = linija['Profesor'].split(" ",1)
                    if len(ime_prezime) < 2:
                        raise Nastavnik.DoesNotExists
                    nastavnik = Nastavnik.objects.get(ime=ime_prezime[0], prezime=ime_prezime[1])
                    nastavnici.append(nastavnik)

            except Nastavnik.DoesNotExist:
                broj_neispravnih_linija += 1
                neispravne_linije.append(linija)
                objasnjenje_za_liniju[redni_broj_linije] = ("Nastavnik \"" + linija['Profesor'] + "\" nije pronadjen u bazi. ",linija)
                continue
            # Vreme
            try:
                vremeOdDo = linija['Vreme'].split('-')
                pocetak = datetime.strptime(vremeOdDo[0], '%H')
                zavrsetak = datetime.strptime(vremeOdDo[1], '%H')
            except ValueError:
                broj_neispravnih_linija += 1
                neispravne_linije.append(linija)
                objasnjenje_za_liniju[redni_broj_linije] = ("Neispravan datum \"" + linija['Datum'] + "\"", linija)
                continue

            # Datum
            try:
                datum_odrzavanja = datetime.strptime(linija['Datum'], '%d.%m.%Y.')
            except ValueError:
                broj_neispravnih_linija += 1
                neispravne_linije.append(linija)
                objasnjenje_za_liniju[redni_broj_linije] = ("Neispravan datum \""+linija['Datum']+"\"",linija)
                continue
            broj_ispravnih_linja+=1 # ako se nije desio ni jedan izuzetak
            ispravne_linje.append(linija)
            # snimamo jo[ jednu strukturu pripremljenu za snimanje, za svakog nastavnika posebno
            termin = linija['Vreme'].split('-')
            for n in nastavnici:
                ispravni_termini.append({'predmet':predmet.id,'nastavnik':n.id, 'datum':datum_odrzavanja.strftime("%Y-%m-%d"),'ucionice':linija['Učionice'],
                                         'dan':linija['Dan'],'pocetak':pocetak.strftime("%H"),'zavrsetak':zavrsetak.strftime('%H')})
    return {'broj_ispravnih_linija':broj_ispravnih_linja, 'broj_neispravnih_linija':broj_neispravnih_linija,
            'objasnjenja_za_linije':objasnjenje_za_liniju,'ispravne_linije':ispravne_linje, 'ispravni_termini':ispravni_termini}

def sacuvaj_termine_polaganja(termini_polaganja, id_vazan_datum):
    vazan_datum = VazniDatumi.objects.get(id=id_vazan_datum)
    raspored_polaganja = RasporedPolaganja(vazan_datum=vazan_datum)
    raspored_polaganja.save()
    for t in termini_polaganja:
        predmet = Predmet.objects.get(id=t['predmet'])
        nastavnik = Nastavnik.objects.get(id=t['nastavnik'])

        termin = TerminPolaganja(raspored_polaganja=raspored_polaganja, predmet=predmet, nastavnik=nastavnik,
                                 ucionice=t['ucionice'], pocetak=datetime.strptime(t['pocetak'], '%H'),
                                 zavrsetak=datetime.strptime(t['zavrsetak'], '%H'), dan=t['dan'], datum=t['datum'])
        termin.save()

                # def ucitaj_raspored_kolokvijuma(importovani_fajl):
#     """ucitava TerminePolaganja u bazu i vraca:
#     1)Recnik cije su vrednosti linije ucitanog fajla, gde jedna linija predstavlja jedan termin polaganja,
#       a kljucevi obavestenje o greskama do kojih je doslo prilikom parsiranja ili obavestenje da su validne.
#       Takodje sadrzi i ukupan broj gresaka.
#     2)0 ako header fajla nije u ispravnom formatu
#     Ako recnik ostane prazan to znaci da su svi termini uspesno ucitani u bazu, odnosno da nije doslo do greske
#     """
#     with open("media/" + importovani_fajl.name, encoding='utf-8') as csvfile:
#         raspored_csv = csv.DictReader(csvfile, delimiter=',')
#         # prvo ide provera korektnosti prve linije da bismo izbegli KeyError pri uzimanju vrednosti kljuceva
#         validni_elementi = ["Predmet", "Profesor", "Učionice", "Vreme", "Dan", "Datum"]
#         if not all(element in raspored_csv.fieldnames for element in validni_elementi):
#             # ne sadrzi, vracam da je problem sa prvom linijom
#             return {"heder": "heder"}
#         linije_sa_obavestenjem = {}  # recnik koji ce kao kljuc imati greske koje se nalaze u liniji, a kao vrednost samu liniju
#         dani = ["Ponedeljak", "Utorak", "Sreda", "Četvrtak", "Cetvrtak", "Petak", "Subota", "Nedelja"]
#         redni_broj_linije = 2;
#         ukupan_broj_gresaka = 0
#         for linija in raspored_csv:
#             greske = ""
#             nema_greske = True  # ako se ne naidje na gresku, termin polaganja se moze ucitati u bazu
#             # Predmet:
#             try:
#                 predmet = Predmet.objects.get(naziv=linija['Predmet'])
#             except Predmet.DoesNotExist:
#                 greske += "Predmet \"" + linija['Predmet'] + "\" nije pronadjen u bazi. "
#                 nema_greske = False
#                 ukupan_broj_gresaka += 1
#                 continue   # bds: jer brojimo samo linije
#             # Profesor:
#             ime_prezime = linija['Profesor'].split(" ")
#             if len(ime_prezime) < 2:  # ako nedostaje ime ili prezime ne moramo proveravati u bazi
#                 greske += "Nastavnik \"" + linija['Profesor'] + "\" nije pronadjen u bazi|"
#                 nema_greske = False
#                 ukupan_broj_gresaka += 1
#                 continue
#             else:
#                 try:
#                     nastavnik = Nastavnik.objects.get(ime=ime_prezime[0], prezime=ime_prezime[1])
#                 except Nastavnik.DoesNotExist:
#                     greske += "Nastavnik \"" + linija['Profesor'] + "\" nije pronadjen u bazi. "
#                     nema_greske = False
#                     ukupan_broj_gresaka += 1
#                     continue
#             #
#             #ucionice = linija['Učionice'].split(',')
#             # for oznaka_ucionice in ucionice:
#             #     try:
#             #         if oznaka_ucionice not in generisane_moguce_ucionice:
#             #             broj = int(oznaka_ucionice)
#             #             if broj > 15 or broj < 1:
#             #                 greske += "Ucionice \"" + linija['Učionice'] + "\" se ne mogu parsirati. "
#             #                 nema_greske = False
#             #                 ukupan_broj_gresaka += 1
#             #                 break
#             #     except ValueError:
#             #         greske += "Ucionice \"" + linija['Učionice'] + "\" se ne mogu parsirati. "
#             #         nema_greske = False
#             #         ukupan_broj_gresaka += 1
#             #         break
#             # Vreme:
#             vreme = linija['Vreme'].split('-')
#             if len(vreme) != 2:
#                 greske += "Vreme \"" + linija['Vreme'] + " \"se ne moze parsirati. "
#                 nema_greske = False
#                 ukupan_broj_gresaka += 1
#                 continue
#             else:
#                 try:
#                     pocetak = int(vreme[0])
#                     zavrsetak = int(vreme[1])
#                     if pocetak < 0 or zavrsetak < 0 or pocetak > 23 or zavrsetak > 23 or pocetak >= zavrsetak or len(
#                             vreme[0]) != 2 or len(vreme[1]) != 2:
#                         greske += "Vreme \"" + linija['Vreme'] + " \"se ne moze parsirati. "
#                         nema_greske = False
#                         ukupan_broj_gresaka += 1
#                 except Exception:
#                     greske += "Vreme \"" + linija['Vreme'] + " \"se ne moze parsirati. "
#                     nema_greske = False
#                     ukupan_broj_gresaka += 1
#                     continue
#             # Dan:
#             if linija['Dan'] not in dani:
#                 greske += "Dan \"" + linija['Dan'] + "\" se ne moze parsirati. "
#                 nema_greske = False
#                 ukupan_broj_gresaka += 1
#             # Datum:
#             datum = linija['Datum'].split('.')
#             if len(datum) != 3:  # zbog poslednje tacke - 22.11.
#                 greske += "Datum \"" + linija['Datum'] + "\" se ne moze parsirati. "
#                 nema_greske = False
#                 ukupan_broj_gresaka += 1
#             else:
#                 if datum[2] != "" or len(datum[0]) != 2 or len(datum[1]) != 2:  # poslednja tacka
#                     greske += "Datum \"" + linija['Datum'] + "\" se ne moze parsirati. "
#                     nema_greske = False
#                     ukupan_broj_gresaka += 1
#                 else:
#                     try:
#                         dan = int(datum[0])
#                         mesec = int(datum[1])
#                         if dan < 0 or mesec < 0 or dan > 31 or mesec > 12:
#                             greske += "Datum \"" + linija['Datum'] + "\" se ne moze parsirati. "
#                             nema_greske = False
#                             ukupan_broj_gresaka += 1
#                     except ValueError:
#                         greske += "Datum \"" + linija['Datum'] + "\" se ne moze parsirati. "
#                         nema_greske = False
#                         ukupan_broj_gresaka += 1
#
#             if nema_greske:
#                 # modifikujem datum i vreme zbog template-a, vreme mora biti u formatu sati:minuta
#                 # datum mora biti u formatu yyyy-mm-dd a ne 22.11., i mora biti 01 a ne samo 1
#                 tmp = linija['Datum'].split('.')
#                 formatiran_datum = "" + str(datetime.now().year) + "-" + tmp[1] + "-" + tmp[0]
#                 tmp = linija['Vreme'].split('-')
#                 formatirani_sati_pocetka = tmp[0] + ":" + "00"
#                 formatirani_sati_zavrsetka = tmp[1] + ":" + "00"
#                 linije_sa_obavestenjem[KljucRecnika("Ispravna")] = [linija['Predmet'], linija['Profesor'],
#                                                                     linija['Učionice'], formatirani_sati_pocetka,
#                                                                     formatirani_sati_zavrsetka, linija['Dan'],
#                                                                     formatiran_datum]
#             else:
#                 # posto postoje greske, pre formatiranja se mora proveriti da li je do greske doslo u datumu/vremenu
#                 # ako jeste, vrednost linije_sa_obavestenjem moze imati linija['Datum'] (lose formatiran datum) jer
#                 # se on nece koristi u templejtu
#                 tmp = linija['Datum'].split('.')
#                 formatiran_datum = linija['Datum'] if "Datum" in greske else "" + str(datetime.now().year) + "-" + \
#                                                                              tmp[1] + "-" + tmp[0]
#                 tmp = linija['Vreme'].split('-')
#                 formatirani_sati_pocetka = linija['Vreme'] if "Vreme" in greske else tmp[0] + ":" + "00"
#                 formatirani_sati_zavrsetka = linija['Vreme'] if "Vreme" in greske else tmp[1] + ":" + "00"
#                 izvestaj = "Redni broj linije: " + str(redni_broj_linije) + ". Greske: " + greske
#                 linije_sa_obavestenjem[KljucRecnika(izvestaj)] = [linija['Predmet'], linija['Profesor'],
#                                                                   linija['Učionice'], formatirani_sati_pocetka,
#                                                                   formatirani_sati_zavrsetka, linija['Dan'],
#                                                                   formatiran_datum]
#
#             redni_broj_linije += 1
#
#         # jos da se prilepi koliko gresaka ima
#         linije_sa_obavestenjem[KljucRecnika("Ukupan broj gresaka")] = ukupan_broj_gresaka
#         return linije_sa_obavestenjem

def ucitaj_raspored_nastave(importovani_fajl, semestar, raspored_nastave):
    with open("media/" + importovani_fajl.name, encoding='utf-8') as csvfile:
        raspored_csv = csv.reader(csvfile, delimiter=';')
        indeksPredavanja = 0
        indeksVezbi = 0
        indeksPraktikuma = 0
        indeksPredavanjaIPraktikuma = 0
        brojac = 0
        podaci_tekuceg = vrati_podatke_tekuceg_semestra()
        for red in raspored_csv:
            if not red:
                continue
            else:
                if brojac == 0:
                    brojac += 1;
                    continue
                elif brojac == 1:
                    indeksPredavanja = red.index("Predavanja")
                    indeksPraktikuma = red.index("Praktikum")
                    indeksPredavanjaIPraktikuma = red.index("Predavanja i vezbe")
                    indeksVezbi = red.index("Vezbe")
                else:
                    if len(red) <= 2:  # predmet na nultom indeksu
                        try:
                            predmet = Predmet.objects.get(naziv=red[0])
                        except:
                            return "Predmet " + red[0] + " nije pronadjen u bazi"
                    else:
                        # termini nastave:
                        if red[1] == "Nastavnik(ci)":  # indeksi za to su vec obezbedjeni
                            brojac += 1
                            continue
                        else:
                            # ovo su cisti podaci o terminima
                            ############################################################################################
                            if red[indeksPredavanja] != '':
                                # prvo provera dal nastavnik vec postoji u bazi?
                                usernameNaloga = napraviUsernameNaloga(red[indeksPredavanja])
                                # POSTOJI MOGUCNOST INDEXERROR-A, POPRAVITI TO! - napraviUsernName(samo ime/samo prezime)
                                try:
                                    nalog = Nalog.objects.get(username=usernameNaloga, uloga="Nastavnik")
                                    nastavnik = Nastavnik.objects.get(nalog=nalog)
                                except (Nalog.DoesNotExist, Nastavnik.DoesNotExist) as e:
                                    return "Nastavnik " + red[indeksPredavanja] + " nije pronadjen u bazi"
                                # dodavanje predmeta nastavniku, ako nastavnik vec nema taj predmet
                                if not predmet.nastavnik_set.filter(nalog=nalog).exists():
                                    nastavnik.predmet.add(predmet)
                                # pravljenje termina, dodavanje grupa
                                tmp = red[indeksPredavanja + 5].split('-')
                                termin = Termin(oznaka_ucionice=red[indeksPredavanja + 6], pocetak=tmp[0],
                                                zavrsetak=tmp[1] + ":00", dan=red[indeksPredavanja + 4],
                                                predmet=predmet, nastavnik=nastavnik, tip_nastave="Predavanja",
                                                raspored=raspored_nastave)
                                termin.save()
                                tmp = red[indeksPredavanja + 2].split(', ')  # grupe
                                for oznakaGrupe in tmp:
                                    try:
                                        grupa = Grupa.objects.get(oznaka_grupe=oznakaGrupe, semestar=semestar)
                                        termin.grupe.add(grupa)
                                    except Grupa.DoesNotExist:
                                        grupa = Grupa(oznaka_grupe=oznakaGrupe, semestar=semestar)
                                        grupa.save()
                                        termin.grupe.add(grupa)
                            ############################################################################################
                            if red[indeksVezbi] != '':
                                # prvo provera dal nastavnik vec postoji u bazi?
                                usernameNaloga = napraviUsernameNaloga(red[indeksVezbi])
                                try:
                                    nalog = Nalog.objects.get(username=usernameNaloga, uloga="Nastavnik")
                                    nastavnik = Nastavnik.objects.get(nalog=nalog)
                                except (Nalog.DoesNotExist, Nastavnik.DoesNotExist) as e:
                                    return "Nastavnik " + red[indeksVezbi] + " nije pronadjen u bazi"
                                # dodavanje predmeta nastavniku, ako nastavnik vec nema taj predmet
                                if not predmet.nastavnik_set.filter(nalog=nalog).exists():
                                    nastavnik.predmet.add(predmet)
                                # termini,grupe
                                tmp = red[indeksVezbi + 5].split('-')
                                termin = Termin(oznaka_ucionice=red[indeksVezbi + 6], pocetak=tmp[0],
                                                zavrsetak=tmp[1] + ":00", dan=red[indeksVezbi + 4], predmet=predmet,
                                                nastavnik=nastavnik, tip_nastave="Vezbe", raspored=raspored_nastave)
                                termin.save()
                                tmp = red[indeksVezbi + 2].split(', ')  # grupe
                                for oznakaGrupe in tmp:
                                    try:
                                        grupa = Grupa.objects.get(oznaka_grupe=oznakaGrupe, semestar=semestar)
                                        termin.grupe.add(grupa)
                                    except Grupa.DoesNotExist:
                                        grupa = Grupa(oznaka_grupe=oznakaGrupe, semestar=semestar)
                                        grupa.save()
                                        termin.grupe.add(grupa)
                            ############################################################################################
                            if red[indeksPraktikuma] != '':
                                # prvo provera dal nastavnik vec postoji u bazi?
                                usernameNaloga = napraviUsernameNaloga(red[indeksPraktikuma])
                                try:
                                    nalog = Nalog.objects.get(username=usernameNaloga, uloga="Nastavnik")
                                    nastavnik = Nastavnik.objects.get(nalog=nalog)
                                except (Nalog.DoesNotExist, Nastavnik.DoesNotExist) as e:
                                    return "Nastavnik " + red[indeksPraktikuma] + " nije pronadjen u bazi"
                                # dodavanje predmeta nastavniku, ako nastavnik vec nema taj predmet
                                if not predmet.nastavnik_set.filter(nalog=nalog).exists():
                                    nastavnik.predmet.add(predmet)
                                # termini, grupe
                                tmp = red[indeksPraktikuma + 5].split('-')
                                termin = Termin(oznaka_ucionice=red[indeksPraktikuma + 6], pocetak=tmp[0],
                                                zavrsetak=tmp[1] + ":00", dan=red[indeksPraktikuma + 4],
                                                predmet=predmet, nastavnik=nastavnik, tip_nastave="Praktikum",
                                                raspored=raspored_nastave)
                                termin.save()
                                tmp = red[indeksPraktikuma + 2].split(', ')  # grupe
                                for oznakaGrupe in tmp:
                                    try:
                                        grupa = Grupa.objects.get(oznaka_grupe=oznakaGrupe, semestar=semestar)
                                        termin.grupe.add(grupa)
                                    except Grupa.DoesNotExist:
                                        grupa = Grupa(oznaka_grupe=oznakaGrupe, semestar=semestar)
                                        grupa.save()
                                        termin.grupe.add(grupa)
                            ############################################################################################
                            if red[indeksPredavanjaIPraktikuma] != '':
                                # prvo provera dal nastavnik vec postoji u bazi?
                                usernameNaloga = napraviUsernameNaloga(
                                    red[indeksPredavanjaIPraktikuma])
                                try:
                                    nalog = Nalog.objects.get(username=usernameNaloga, uloga="Nastavnik")
                                    nastavnik = Nastavnik.objects.get(nalog=nalog)
                                except (Nalog.DoesNotExist, Nastavnik.DoesNotExist) as e:
                                    return "Nastavnik " + red[indeksPredavanjaIPraktikuma] + " nije pronadjen u bazi"
                                # dodavanje predmeta nastavniku, ako nastavnik vec nema taj predmet
                                if not predmet.nastavnik_set.filter(nalog=nalog).exists():
                                    nastavnik.predmet.add(predmet)
                                # termini, grupe
                                tmp = red[indeksPredavanjaIPraktikuma + 5].split('-')
                                termin = Termin(oznaka_ucionice=red[indeksPredavanjaIPraktikuma + 6], pocetak=tmp[0],
                                                zavrsetak=tmp[1] + ":00", dan=red[indeksPredavanjaIPraktikuma + 4],
                                                predmet=predmet, nastavnik=nastavnik, tip_nastave="Pred. i Vezbe",
                                                raspored=raspored_nastave)
                                termin.save()
                                tmp = red[indeksPredavanjaIPraktikuma + 2].split(', ')  # grupe
                                for oznakaGrupe in tmp:
                                    try:
                                        grupa = Grupa.objects.get(oznaka_grupe=oznakaGrupe, semestar=semestar)
                                        termin.grupe.add(grupa)
                                    except Grupa.DoesNotExist:
                                        grupa = Grupa(oznaka_grupe=oznakaGrupe, semestar=semestar)
                                        grupa.save()
                                        termin.grupe.add(grupa)
                            ############################################################################################
            brojac += 1
    return "Uspesno"

def vrati_termine_predavanja_za_ponovca(student):
    predmeti = []
    podaci_tekuceg = vrati_podatke_tekuceg_semestra()
    semestar = Semestar.objects.get(vrsta=podaci_tekuceg[0], skolska_godina_pocetak=podaci_tekuceg[1],
                                    skolska_godina_kraj=podaci_tekuceg[2])
    slusa_ponovac = Slusa_Ponovac.objects.filter(semestar=semestar, student=student)
    raspored = RasporedNastave.objects.get(semestar_id=semestar.id)
    for instanca in slusa_ponovac:
        for nastavnik in instanca.predmet.nastavnik_set.all():
            if nastavnik in instanca.nastavnici.all():
                termini = Termin.objects.filter(nastavnik=nastavnik, predmet=instanca.predmet, raspored=raspored)
                predmeti.extend(termini)
    return predmeti


#!/usr/bin/env python3

import os
import json
import re
from google.cloud import storage

MRGN_GCP_BUCKET = "mrgn-public"
STAKE_POOL_STATS_DIR = "stake_pool_data"
STAKE_POOL_FILENAME_TEMPLATE = "stats_{}.json"

def main():
    client = storage.Client()
    bucket = client.bucket(MRGN_GCP_BUCKET)

    script_dir = os.path.dirname(os.path.abspath(__file__))
    stats_dir = os.path.realpath(os.path.join(script_dir, "..", "output"))
    stats_files = os.listdir(stats_dir)
    stats_files.sort()
    stats_file_regex = "stats_([0-9]+).json"

    manifest = {"latest": None, "epochs": []}

    for stats_file in stats_files:
        match = re.match(stats_file_regex, stats_file)
        if match:
            epoch = int(match.groups()[0])

            blob_name = f"{STAKE_POOL_STATS_DIR}/{stats_file}"
            blob = bucket.blob(blob_name)

            stats_path = os.path.join(stats_dir, stats_file)

            print("Uploading {} to {}".format(stats_path, blob_name))
            blob.upload_from_filename(stats_path)
            blob.acl.all().grant_read()
            blob.acl.save()

            if manifest["latest"] is None or epoch > manifest["latest"]:
                manifest["latest"] = epoch
            manifest["epochs"].append(epoch)

    manifest_blob_name = f"{STAKE_POOL_STATS_DIR}/manifest.json"
    manifest_blob = bucket.blob(manifest_blob_name)
    print("Uploading manifest to {}".format(manifest_blob_name))
    manifest_blob.upload_from_string(json.dumps(manifest))
    blob.acl.all().grant_read()
    blob.acl.save()

if __name__ == "__main__":
    main()


import os

Test.Summary = '''
Test different combinations of TLS handshake hooks to ensure they are applied consistently.
'''

Test.SkipUnless(Condition.HasOpenSSLVersion("1.1.1"))

ts = Test.MakeATSProcess("ts", enable_tls=True)
server = Test.MakeOriginServer("server", ssl=True)
request_header = {"headers": "GET / HTTP/1.1\r\nHost: www.example.com\r\n\r\n", "timestamp": "1469733493.993", "body": ""}
# desired response form the origin server
response_header = {"headers": "HTTP/1.1 200 OK\r\nConnection: close\r\n\r\n", "timestamp": "1469733493.993", "body": ""}
server.addResponse("sessionlog.json", request_header, response_header)

ts.addSSLfile("ssl/server.pem")
ts.addSSLfile("ssl/server.key")
ts.addSSLfile("ssl/signer.pem")

ts.Disk.records_config.update(
    {
        # Test looks for debug output from the plugin
        'proxy.config.diags.debug.enabled': 1,
        'proxy.config.diags.debug.tags': 'ssl_client_verify_test',
        'proxy.config.ssl.server.cert.path': '{0}'.format(ts.Variables.SSLDir),
        'proxy.config.ssl.server.private_key.path': '{0}'.format(ts.Variables.SSLDir),
        'proxy.config.exec_thread.autoconfig.scale': 1.0,
        'proxy.config.ssl.CA.cert.filename': '{0}/signer.pem'.format(ts.Variables.SSLDir),
        'proxy.config.url_remap.pristine_host_hdr': 1
    })

ts.Disk.ssl_multicert_config.AddLine('dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key')

ts.Disk.remap_config.AddLine(
    'map https://foo.com:{1}/ https://127.0.0.1:{0}'.format(server.Variables.SSL_Port, ts.Variables.ssl_port))
ts.Disk.remap_config.AddLine(
    'map https://bar.com:{1}/ https://127.0.0.1:{0}'.format(server.Variables.SSL_Port, ts.Variables.ssl_port))
ts.Disk.remap_config.AddLine(
    'map https://random.com:{1}/ https://127.0.0.1:{0}'.format(server.Variables.SSL_Port, ts.Variables.ssl_port))

ts.Disk.sni_yaml.AddLines([
    'sni:',
    '- fqdn: bar.com',
    '  verify_client: STRICT',
    '- fqdn: foo.com',
    '  verify_client: STRICT',
])

Test.PrepareTestPlugin(os.path.join(Test.Variables.AtsTestPluginsDir, 'ssl_client_verify_test.so'), ts, '-count=2 -good=foo.com')

tr = Test.AddTestRun("request good name")
tr.Setup.Copy("ssl/signed-foo.pem")
tr.Setup.Copy("ssl/signed-foo.key")
tr.Setup.Copy("ssl/signed-bar.pem")
tr.Setup.Copy("ssl/signed-bar.key")
tr.Processes.Default.StartBefore(server)
tr.Processes.Default.StartBefore(Test.Processes.ts)
tr.StillRunningAfter = ts
tr.StillRunningAfter = server
tr.Processes.Default.Command = "curl --tls-max 1.2 -k --cert ./signed-foo.pem --key ./signed-foo.key --resolve 'foo.com:{0}:127.0.0.1' https://foo.com:{0}/case1".format(
    ts.Variables.ssl_port)
tr.Processes.Default.ReturnCode = 0
tr.Processes.Default.Streams.all = Testers.ExcludesExpression("Could Not Connect", "Curl attempt should have succeeded")

tr2 = Test.AddTestRun("request bad name")
tr2.StillRunningAfter = ts
tr2.StillRunningAfter = server
tr2.Processes.Default.Command = "curl --tls-max 1.2 -k --cert ./signed-bar.pem --key ./signed-bar.key --resolve 'foo.com:{0}:127.0.0.1' https://foo.com:{0}/case1".format(
    ts.Variables.ssl_port)
tr2.Processes.Default.ReturnCode = 35
tr2.Processes.Default.Streams.all = Testers.ContainsExpression("error", "Curl attempt should have failed")

tr3 = Test.AddTestRun("request badly signed cert")
tr3.Setup.Copy("ssl/server.pem")
tr3.Setup.Copy("ssl/server.key")
tr3.StillRunningAfter = ts
tr3.StillRunningAfter = server
tr3.Processes.Default.Command = "curl --tls-max 1.2 -k --cert ./server.pem --key ./server.key --resolve 'foo.com:{0}:127.0.0.1' https://foo.com:{0}/case1".format(
    ts.Variables.ssl_port)
tr3.Processes.Default.ReturnCode = 35
tr3.Processes.Default.Streams.all = Testers.ContainsExpression("error", "Curl attempt should have failed")

ts.Disk.traffic_out.Content += Testers.ContainsExpression(
    r"Client verify callback 0 [\da-fx]+? - event is good good HS", "verify callback happens 2 times")
ts.Disk.traffic_out.Content += Testers.ContainsExpression(
    r"Client verify callback 1 [\da-fx]+? - event is good good HS", "verify callback happens 2 times")
ts.Disk.traffic_out.Content += Testers.ContainsExpression(
    r"Client verify callback 0 [\da-fx]+? - event is good error HS", "verify callback happens 2 times")
ts.Disk.traffic_out.Content += Testers.ContainsExpression(
    r"Client verify callback 1 [\da-fx]+? - event is good error HS", "verify callback happens 2 times")


import numpy as np
import pandas as pd
import copy

class Action:

    """defines possible actions"""

    def __init__(self):
        self.actions = ['-1,-1', '-1,0', '-1,1', '0,-1', '0,0', '0,1', '1,-1', '1,0', '1,1']

    def select_action_column(self, x_acc, y_acc):
        """get column index based on x,y acc"""
        index = -np.inf
        for i, acts in enumerate(self.actions):
            pair = acts.split(",")
            if (int(pair[0]) == x_acc) and (int(pair[1]) == y_acc):
                index = i
                break
        return index

class Table:

    """the Q table"""

    def __init__(self, track):
        possible_actions = Action()  # actions = columns
        self.actions = possible_actions.actions
        self.speeds = self.determine_possible_speeds()  # calculates all possible speeds (-5,-5) -> (5,5)
        self.states = self.define_states(self.speeds, track)  # calculates all the states based on loc / speed combos
        self.n_states = len(self.states)
        self.n_actions = len(self.actions)
        self.zeros = self.create_zeros(self.n_states, self.n_actions)  # init chart to zeros
        self.title = track.name
        self.track = track
        self.df = pd.DataFrame(data=self.zeros, columns=self.actions, index=self.states)  # create table

    def load(self, filename):

        """load previously learned q-table"""

        self.df = pd.read_csv(filename, index_col=0)

    def determine_possible_speeds(self, low=-5, high=5):

        """returns possible speeds to help build states"""

        pairs = []
        for x in range(low, high + 1):
            for y in range(low, high + 1):
                speed = str(x) + "," + str(y)
                pairs.append(speed)
        self.speeds = pairs
        return pairs

    def define_states(self, pos_speeds, track):

        """determines all possible states for the track"""

        course_tiles = []
        possible_states = []
        for line in track.matrix:
            for tile in line:
                if tile.course:
                    course_tiles.append(tile)
        for tile in course_tiles:
            for speed in pos_speeds:
                state = tile.id + "|" + speed
                possible_states.append(state)
        self.states = possible_states
        return possible_states

    def create_zeros(self, rows, columns):
        zeros = np.zeros([rows, columns])
        self.zeros = zeros
        return zeros

    def select_state(self, x_pos, y_pos, x_speed, y_speed):

        """selects state based on pos and speed"""

        tile = self.track.get_tile(x_pos, y_pos)
        state = tile.id + "|" + str(x_speed) + "," + str(y_speed)
        return state

    def select_action(self, x_acc, y_acc):

        """selects action based on x,y acc"""

        action = str(x_acc) + "," + str(y_acc)
        return action

    def fetch(self, state, action):
        return self.df.at[state, action]

class ReinforcementLearner:

    """base class for a reinforcement learner, inherited by q and sarsa"""

    def __init__(self, car, mode=None, discount_rate=.9, learning_rate=1, epsilon=.5):
        self.discount = discount_rate
        self.learning = learning_rate
        self.epsilon = epsilon
        self.track = car.track
        self.car = car
        self.table = self.track.table
        self.actions = self.table.actions
        self.mode = mode.lower()  # q or sarsa
        self.q1 = None
        self.q2 = None
        self.selected = None
        self.follow_on = None
        self.reward = None
        self.predetermined = False

    def __str__(self):
        string = "%s learner on %s" % (self.mode, self.track.name)
        return string

    def determine_action(self, car):
        """determines the action based on policy"""
        car.set_state_action_pair()
        random = np.random.rand(1)
        if random > self.epsilon:
            q_value, index = self.get_best_action()
        else:
            index = np.random.randint(0, len(self.actions))
        action = self.actions[index]
        return action

    def get_best_action(self, trial=False, evaluate=None):
        """returns the state/action pair with highest q-value"""
        best_q = -np.infty
        possible_q = []
        q_index = None
        if not trial:
            evaluate = self.track.table.df.loc[self.car.state]
        for i, q_value in enumerate(evaluate):
            if q_value > best_q:
                best_q = q_value
                q_index = i
                possible_q = [i]
            elif q_value == best_q:
                possible_q.append(i)
        if len(possible_q) > 1:
            random = np.random.randint(0, len(possible_q))
            q_index = possible_q[random]
        return best_q, q_index

    def determine_follow_on_action(self):
        pass

    def adjust_policy(self, percent=10):
        """not used in program"""
        adjusted_epsilon = self.epsilon + self.epsilon * (percent / 100)
        if 1 > adjusted_epsilon > 0:
            self.epsilon = adjusted_epsilon
        elif adjusted_epsilon > 1:
            self.epsilon = 1
        elif adjusted_epsilon < 0:
            self.epsilon = 0
        return self.epsilon

    def get_reward(self, car):
        """gets the reward from its current position, sub 10 for crashing"""
        x = car.position.x
        y = car.position.y
        tile = self.track.get_tile(x, y)
        reward = tile.reward
        if car.crashed:
            reward = reward - 10  # because we are not actually on the out tile
        elif car.finished:
            reward = reward + 100  # extra bonus points makes finishing actually worth 200
        return reward

    def store_state_action(self, car, initial=True):
        """stores the state / action pair from the car into the learner"""
        if initial:
            self.selected = [car.state, car.action]
        else:
            self.follow_on = [car.state, car.action]

    def update_q(self):
        """q-update policy, based on q-learning. overwritten in sarsa"""
        # current_q = self.table.df.loc[self.selected[0], self.selected[1]]
        # current_q += self.learning * (self.reward + (self.discount * self.q2) - self.q1)
        current_q = self.learning * (self.reward + (self.discount * self.q2))
        self.table.df.loc[self.selected[0], self.selected[1]] = current_q

class Q(ReinforcementLearner):

    """class for q-learner"""

    def __init__(self, car, mode="q", discount_rate=.9, learning_rate=1, epsilon=.5):
        super().__init__(car, mode="q", discount_rate=.9, learning_rate=1, epsilon=.5)

    def determine_follow_on_action(self):
        """determine follow-on action based on q method"""
        ghost_car = copy.copy(self.car)  # so we don't move there create a copy
        ghost_car.crashed = False
        ghost_car.update_state()
        action = ghost_car.learner.determine_action(ghost_car, ghost=True)  # gets best action
        ghost_car.update_action(action)
        state = ghost_car.state
        # ghost_car.accelerate(action)
        q2 = ghost_car.get_current_state_action_pair_q()  # highest q
        return q2, state, action

    def determine_action(self, car, ghost=False, course=None):
        """determine action based on q method"""
        # car.set_state_action_pair()
        random = np.random.rand(1)
        if random > self.epsilon or ghost:  # ghost gets the best just like exploiting
            q_value, index = self.get_best_action()
        else:
            index = np.random.randint(0, len(self.actions))  # explore
        action = self.actions[index]
        return action

class SARSA(ReinforcementLearner):

    """the sarsa-learner"""

    def __init__(self, car, mode="sarsa", discount_rate=.9, learning_rate=.33, epsilon=.5):
        super().__init__(car, mode="sarsa", discount_rate=.9, learning_rate=.33, epsilon=.5)

    def determine_follow_on_action(self):
        """determine follow-on action and q-value using sarsa method"""
        ghost_car = copy.copy(self.car)
        ghost_car.crashed = False
        ghost_car.update_state()
        action = ghost_car.learner.determine_action(ghost_car, ghost=True)
        ghost_car.update_action(action)
        state = ghost_car.state
        # ghost_car.accelerate(action)
        q2 = ghost_car.get_current_state_action_pair_q()
        self.predetermined = True  # the learner will follow the predetermined action in next turn
        return q2, state, action

    def determine_action(self, car, ghost=False):
        """determine action based on sarsa method"""
        # car.set_state_action_pair()
        random = np.random.rand(1)
        if random > self.epsilon:  # follows normal epsilon greedy policy
            q_value, index = self.get_best_action()
        else:
            index = np.random.randint(0, len(self.actions))  # explore
        action = self.actions[index]
        return action

    def update_q(self):
        """update q-table based on sarsa update method"""
        current_q = self.table.df.loc[self.selected[0], self.selected[1]]
        current_q += self.learning * (self.reward + (self.discount * self.q2) - self.q1)
        # current_q = self.learning * (self.reward + (self.discount * self.q2))
        self.table.df.loc[self.selected[0], self.selected[1]] = current_q


# -*- coding: utf-8 -*-
from odoo import http
import werkzeug
import json
from odoo.http import request
from odoo.addons.bus.controllers.main import BusController
from odoo.addons.bus.models.bus import dispatch

class WebrtcBusController(BusController):
    # override to add channels
    def _poll(self, dbname, channels, last, options):
#       referrer_url = request.httprequest.headers.get('Referer', '')

        if request.session.uid and 'bus_inactivity' in options:
            request.env['bus.presence'].update(options.get('bus_inactivity'),options.get('is_webrtc'))

        request.cr.close()
        request._cr = None
        return dispatch.poll(dbname, channels, last, options)

class O2o(http.Controller):
    @http.route('/o2o/exercise/<int:id>', type='http', methods=['GET'],auth="user")
    def get_exercise(self,id, **kw):
        answer = http.request.env['o2o.exercise'].browse(id)

        if request.httprequest.method == 'GET':
            response = werkzeug.wrappers.Response()
            response.data = answer.content
            return response

    @http.route('/o2o/exercise/<int:id>', type='json', methods=['PUT'],auth="user")
    def put_exercise(self,id, **kw):
        answer = http.request.env['o2o.exercise'].browse(id)

        if request.httprequest.method == 'PUT':
            answer.write({'content':request.httprequest.data})

    @http.route('/o2o/online/request/<int:remote>', type='http', auth="user", website=True)
    def online_request(self,remote,slide, **kw):
        db = request.db
        self_id = request.uid
        remote_user = http.request.env['res.users'].browse(remote)

        channel = '%s,webrtc,%d'%(request._cr.dbname,remote)
        message = ['request',request.uid,slide]
        self.env['bus.bus'].sendone(channel, message)

        return http.request.render('o2o.onlinehelp', {
            'self_id':self_id,
            'remote_id':remote,
            'remote_name':remote_user.name,
            'cur_db':db
        })

    @http.route('/o2o/online/accept/<int:remote>', type='http', auth="user", website=True)
    def online_accept(self,remote, **kw):
        db = request.db
        self_id = request.uid
        remote_user = http.request.env['res.users'].browse(remote)

        channel = '%s,webrtc,%d'%(request._cr.dbname,remote)
        message = ['accept',request.uid]
        self.env['bus.bus'].sendone(channel, message)

        return http.request.render('o2o.onlinehelp', {
            'self_id':self_id,
            'remote_id':remote,
            'remote_name':remote_user.name,
            'cur_db':db
        })


from typing import List

def binary_search(nums: List[int], val: int) -> bool:
    """
    search if val is in an ascending sorted list
    :param nums:
    :param val:
    :return:
    """
    left, right = 0, len(nums) - 1

    while left <= right:
        mid = (left + right) // 2

        if nums[mid] == val:
            return True
        elif nums[mid] < val:
            left = mid + 1
        else:
            right = mid - 1

    return False

def binary_search_less_or_equal(nums: List[int], val: int) -> int:
    """
    search the number of elements in an  ascending sorted list
    which are less or equal to val
    :param nums:
    :param val:
    :return:
    """
    left, right = 0, len(nums) - 1

    while left <= right:
        mid = (left + right) // 2

        # val is in the array
        if nums[mid] == val:
            # search till the last equals to val
            while mid + 1 < len(nums) and nums[mid + 1] == val:
                mid += 1
            return len(nums[: mid + 1])
        # mid is less than val, we ignore the left half
        elif nums[mid] < val:
            left = mid + 1
        # mid is greater than val, we ignore the right half
        else:
            right = mid - 1

    # val is not in the array, but nums[mid] is the most close one to val
    if nums[mid] < val:
        # search right till the last less than val
        while mid + 1 < len(nums) and nums[mid + 1] < val:
            mid += 1
        return len(nums[: mid + 1])
    else:
        # search left till the first less then val
        while mid - 1 > -1 and nums[mid - 1] > val:
            mid -= 1
        return len(nums[: mid])


#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Sat May  4 21:21:19 2019

@author: Bowton
"""
import math
import numpy as np
import matplotlib.pyplot as plt

def getArea(): #gets user input for the length of the wind farm
               #then calculates the area and returns length and area
    length = input('What is the length of the wind farm in km?')
    length = float(length)#makes sure length isn't a string
    length = length * 1000 #makes length in meters
    area = (length**2)#our area is a grid (could be adapted to different shapes later on)
    return area, length

def getSweptArea():#gets user input for swept area, same as function above
    sweptArea = input('What is the swept area of the wind turbine in meters squared?')
    sweptArea = float(sweptArea)
    return sweptArea

def getRotorDiameter(sweptArea):#calculates the rotor diameter based on the A = pi*r^2
    diameter = 2*math.sqrt(sweptArea/math.pi)
    return diameter

def getMaxTurbines(diameter,length):#gets maximum number of turbines that will fit in the wind farm
    diameter = round(diameter)#rounds the diameter
    maxTurbines = (length / (7*diameter))**2#divides the length of the farm by 7 diameters of the wind turbine
    maxTurbines = math.floor(maxTurbines)#rounds down to nearest int because you can't go over this amount of turbines
    return maxTurbines

def getTurbineCoordinates(maxTurbines,diameter,length):#gets the coordinates of the turbines
    xCoordinates = np.zeros(maxTurbines)#array of zeros, length is max number of turbines because we need the locations of all of them, for x values
    yCoordinates = np.zeros(maxTurbines)#this array is for the y values
    x = 0
    y = 7.5*diameter #makes sure it isn't too close to the start in case there are obstacles right on the edge of the wind farm that must be avoided
    i = 0#counter
    while y < length: #makes sure it doesn't go out of bounds based on the length of the wind farm
        x = 7.5*diameter
        while x < (length): #adds values to their respective arrays incrementally

            xCoordinates[i] = x
            yCoordinates[i] = y
            x = x + 7.5*diameter
            i = i + 1
        y = y + 7.5*diameter
    return xCoordinates, yCoordinates

def graphCoordinateList(xCoordinates,yCoordinates,diameter,length):#graphs the arrays of coordinates
    j = 0
    totalTurbines = 0#number of turbines that are not at location (0,0)
    while (xCoordinates[j] != 0):#this gets the number of turbines that are not at location (0,0) and graphs them
        plt.plot(xCoordinates[j], yCoordinates[j], "b.")
        totalTurbines = totalTurbines + 1
        j = j+1 #increments
    plt.xlim(0, length+(7.5*diameter))#setting x limit of the graph
    plt.ylim(0, length+(7.5*diameter))#setting y limit of the graph
    plt.xlabel('xCoordinates')
    plt.ylabel('yCoordinates')
    plt.show()
    return totalTurbines

def totalPowerOutput(sweptArea, totalTurbines):#calculates the total power output of the wind farm
    totalPower =0
    totalPower = (0.5*(sweptArea)*(1728*1.225))/1000
    totalPower = (totalPower*totalTurbines)/1000
    print("The total power output of this wind farm is " + str(totalPower) + " Mega Watts")
    return totalPower


# stdlib
from typing import Any, List

# third party
import pandas as pd
from sksurv.ensemble import RandomSurvivalForest

# adjutorium absolute
import adjutorium.plugins.core.params as params
import adjutorium.plugins.prediction.risk_estimation.base as base
import adjutorium.plugins.prediction.risk_estimation.helper_sksurv as helper_sksurv
import adjutorium.utils.serialization as serialization

class RandomSurvivalForestPlugin(base.RiskEstimationPlugin):
    def __init__(
        self,
        n_estimators: int = 100,
        min_samples_split: int = 6,
        min_samples_leaf: int = 3,
        min_weight_fraction_leaf: float = 0,
        model: Any = None,
        **kwargs: Any
    ) -> None:
        super().__init__(**kwargs)

        if model:
            self.model = model
            return

        self.model = helper_sksurv.sksurvWrapper(
            RandomSurvivalForest(
                n_estimators=n_estimators,
                max_depth=5,
                min_samples_split=min_samples_split,
                min_samples_leaf=min_samples_leaf,
                min_weight_fraction_leaf=min_weight_fraction_leaf,
                n_jobs=2,
            )
        )

    def _fit(
        self, X: pd.DataFrame, *args: Any, **kwargs: Any
    ) -> "RandomSurvivalForestPlugin":
        self.model.fit(X, *args, **kwargs)

        return self

    def _predict(self, X: pd.DataFrame, *args: Any, **kwargs: Any) -> pd.DataFrame:
        return self.model.predict(X, *args, **kwargs)

    @staticmethod
    def name() -> str:
        return "random_survival_forest"

    @staticmethod
    def hyperparameter_space(*args: Any, **kwargs: Any) -> List[params.Params]:
        return [
            params.Integer("n_estimators", 50, 400, 50),
            params.Integer("min_samples_split", 2, 50),
            params.Integer("min_samples_leaf", 2, 30),
            params.Float("min_weight_fraction_leaf", 0, 0.5),
        ]

    def save(self) -> bytes:
        return serialization.save_model(self.model)

    @classmethod
    def load(cls, buff: bytes) -> "RandomSurvivalForestPlugin":
        model = serialization.load_model(buff)
        return cls(model=model)

plugin = RandomSurvivalForestPlugin


import os,sys
parentdir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.insert(0,parentdir)

import xmind
from xmind.core.markerref import MarkerId
xmind_name="算法"
w = xmind.load(os.path.dirname(os.path.abspath(__file__))+"\\"+xmind_name+".xmind")
s2=w.createSheet()
s2.setTitle("递归")
r2=s2.getRootTopic()
r2.setTitle("递归")

content={
'原理':[
    '系统栈',
    '函数及其变量做入栈,遇到函数操作再入栈,循环此过程',
    '直到可计算出函数值，出栈，将函数值赋值给下层的变量值,计算出函数值出栈，循环此过程',
    '直到栈底，最后将计算结果弹出'
],
'计算时间复杂度':[
    {'递归符合如下公式':[
        'T(N)=aT(N/b)+O(N^d),其中a,b,d为常数'
    ]},
    '1.如logb^a>d =>O(N^logb^a)',
    '2.如logb^a<d =>O(N^d)',
    '3.如logb^a==d =>O(N^d*logN)'
],
'一个数组，数左边比它小的数的总和，叫数的小和，所有数的小和累加，叫数组小和':[
    '等价于一个数右边有多少个数比它大，乘以此数',
    '1.判断L==R,true直接返回',
    '2.将[L..R]范围分成左右两半,左[L...Mid]右[Mid...R]',
    '3.左，右部分执行函数，分别求出其小和，并将数据在其数组上排序',
    '4.建一个新数组，长度为左部分+右部分，两个指针分别指向左右数组',
    '5.比较左指针与右指针大小',
    {'6.左指针<右指针':[
        '添加小和(右边数据总量(右边指针到右边数组末的数据量)*左指针指向数)',
        '同时将左指针的数据添加到新的数组，并将其指针右移'
    ]},
    {'7.左指针>=右指针':[
        '将右指针的数据添加到新的数组，并将其指针右移'
    ]},
    {'8.重复5,6,7的过程,直到指针越界':[
        '如左指针越界，将右指针后续数据添加到数组',
        '如右指针越界，将左指针后续数据添加到数组'
    ]},
    '9.将左右函数返回结果与3-8过程计算的小和数相加,得到数组小和',
    {'本质':[
        '在归并排序过程加了求小和的操作'
    ]},
    {'时间复杂度':[
        'T(N)=2T(N/2)+O(N^1) => O(N^1*logN)=O(N*logN)',
    ]},
    {'理解':[
        '前面的比较行为，可为后面的比较行为做基础，缩小后面行为的比较范围'
    ]}
],
'一个数组，数左边比它右边的数大，称作降序对，求有多少个降序对':[
    '原理同上',
    '在归并排序过程加了计算降序对的操作'
],

}

#构建xmind
xmind.build(content,r2)
#保存xmind
xmind.save(w,os.path.dirname(os.path.abspath(__file__))+"\\"+xmind_name+".xmind")


# def goodluck(a):
#     fsum, ssum = [int(i) for i in a[:3]], [int(i) for i in a[3:]]
#     if sum(fsum) == sum(ssum):
#         return True
#     else:
#         return False

# print("Goodluck result : ", goodluck(input("Enter number : ")))

# first

from random import randint

# def ssum(a):
#     print(a); return sum(a)

# print("Sum :", ssum([randint(1, 10) for i in range(10)]))

# # Second

# def mmax(a):
#     print(a); return max(a)

# print("Max :", mmax([randint(1, 10) for i in range(10)]))

# # Third

# def ccount(a):
#     print(a)
#     print("Even :", len([i for i in a if i % 2 == 0]))
#     print("Odd :", len([i for i in a if i % 2 != 0]))
#     print("Pos :", len([i for i in a if i > 0]))
#     print("Neg :", len([i for i in a if i < 0]))

# ccount([randint(-10,10) for i in range(10)])

# Fourth

def rever(a):
    print(a)
    return a[::-1]

print("Reverse :", rever([randint(1, 10) for i in range(10)]))

# Five

def sfind(a,b):
    if b in a:
        return True
    else:
        return False

slist = [randint(1, 20) for i in range(10)]; print(slist)
print("Number : ", sfind(slist, int(input("Enter to find : "))))

# Six

def fact(a):
    slist = []
    for i in a:
        facto = 1
        for j in range(1, i+1):
            facto *= j
        slist.append(facto)
    return slist

slist = [1,2,3,4,5,6]; print(slist)
print("Fact list : ", fact(slist))


import pandas as pd
from scipy.stats import *
from math import *

def sim_distance(data, user1, user2):
	si={}
	for item in data[user1]:
		if item in data[user2]:
			si[item]=1
	# if they have no ratings in common, return 0
	if len(si)==0: return 0
	# Add up the squares of all the differences
	sum_of_squares = sum([pow(data[user1][item] - data[user2][item],2) for item in si])
	return 1/(1+sum_of_squares)


from collections import deque
from itertools import permutations

L = [line.strip() for line in open("24.txt").readlines()]

nums = dict()
for row in range(len(L)):
    for col in range(len(L[0])):
        if L[row][col] in "01234567":
            nums[L[row][col]] = (row, col)

distances = dict()
M = [(1, 0), (0, 1), (-1, 0), (0, -1)]
for number in nums:
    togo = deque([(nums[number], 0)])
    been = dict()
    while len(togo) > 0:
        p, n = togo.popleft()
        been[p] = n
        for m in M:
            np = (p[0] + m[0], p[1] + m[1])
            if (
                0 <= np[0] < len(L)
                and 0 <= np[1] < len(L[0])
                and L[np[0]][np[1]] != "#"
                and (np not in been or been[np] > n + 1)
            ):
                togo.appendleft((np, n + 1))
    distances[number] = been

def path_len(seq):
    global nums
    s = seq[0]
    result = 0
    for point in seq[1:]:
        result += distances[s][nums[point]]
        s = point
    return result

R = 1000000
S = 1000000
for s in permutations("1234567"):
    m = path_len(["0"] + list(s))
    n = path_len(["0"] + list(s) + ["0"])
    if R > n:
        R = m
    if S > n:
        S = n
print("Part 1: ", R)
print("Part 2: ", S)


from handlers.create_order.states import MakeOrderState
from handlers.create_order.step_6_city import handlers as step_6_handlers
from handlers.create_order.step_5_surname import text_answer

async def start_surname(message):
    await MakeOrderState.next()
    answer_text = text_answer.enter_surname
    await message.answer(answer_text)

async def is_surname_valid(surname):
    return surname.isalpha()

async def surname_handler(message, state):
    if not await is_surname_valid(message.text):
        answer_text = text_answer.incorrect_surname
        await message.answer(answer_text)
    else:
        await state.update_data(surname=message.text)

        await step_6_handlers.start_city(message)


from maya.api import _OpenMaya_py2 as om2

def iterSelection():
    """
    generator style iterator over current Maya active selection
    :return: [MObject) an MObject for each item in the selection
    """
    sel = om2.MGlobal.getActiveSelectionList()
    for i in xrange(sel.length()):
        yield sel.getDependNode(i)

_MAYA_MATRIX_ATTRIBUTE_NAME = 'worldMatrix'
def wMtxFromMob(node_mob):
    """
    finds the world matrix attribute and returns its value in matrix form
    :param node_mob: [MObject] the node to get the world matrix from
    :return: [MMatrix] the matrix value of the world transform on the argument node
    """
    if not node_mob.hasFn(om2.MFn.kDagNode):
        return None

    mfn_dag = om2.MFnDagNode(node_mob)
    wMtxPlug = mfn_dag.findPlug(_MAYA_MATRIX_ATTRIBUTE_NAME, False)
    elPlug = wMtxPlug.elementByLogicalIndex(0)

    node_mob_attr = elPlug.asMObject()
    mfn_mtxData = om2.MFnMatrixData(node_mob_attr)
    return mfn_mtxData.matrix()

_MAYA_OUTPUT_ATTRIBUTE_NAME = 'output'
def getMRotFromNodeOutput(node_mob, rotOrder = om2.MEulerRotation.kXYZ):
    """
    finds the angular output of the argument node and returns it
     as a Euler rotation where that angle is the X element
    :param node_mob: [MObject] the node to get the output port from
    :param rotOrder: [int] the factory constant for the desired rotation order
                            the returned Euler rotation should be set to
    :return: [MEulerRotation] the Euler rotation composition where the
                                angular output on the argument node is the X value
    """
    mfn_dep = om2.MFnDependencyNode(node_mob)
    angle = om2.MAngle(0.0)
    if node_mob.hasFn(om2.MFn.kAnimBlend) and mfn_dep.hasAttribute(_MAYA_OUTPUT_ATTRIBUTE_NAME):
        plug = mfn_dep.findPlug(_MAYA_OUTPUT_ATTRIBUTE_NAME, False)
        angle = plug.asMAngle()

    rot = om2.MEulerRotation(angle.asRadians(), 0.0, 0.0, rotOrder)
    return rot

mobTuple = tuple(iterSelection())
if len(mobTuple) >= 2:
    if mobTuple[0] is not None:
        srtWMtx = om2.MTransformationMatrix(wMtxFromMob(mobTuple[0]))
        srtWMtx.rotateBy(getMRotFromNodeOutput(mobTuple[1]), om2.MSpace.kWorld)


#! /usr/bin/env python

import roslib
import rospy
import actionlib

from geometry_msgs.msg import Twist
from turtlesim.msg import Pose
from math import pow, atan2, sqrt

from shalaka_ros.msg import TurtleGoalAction, TurtleGoalGoal

def feedback_call(msg):
    print("Turtle is now at position: ", msg)

def call_server():
    client = actionlib.SimpleActionClient('move_turtle_to_goal', TurtleGoalAction)
    client.wait_for_server()

    # Set goal
    goal = TurtleGoalGoal()
    goal.goal_x = int(input("Enter target x-coord: "))
    goal.goal_y = int(input("Enter target y-coord: "))

    # Send goal to server and ask for feedback
    client.send_goal(goal, feedback_cb=feedback_call)

    # Wait for result
    client.wait_for_result()
    result = client.get_result()

    return result

if __name__ == '__main__':

    try:
        rospy.init_node('move_tutle_to_goal_client')

        result = call_server()

        print('The result is:', result)

    except rospy.ROSInterruptException as e:
        print('Something went wrong:', e)