import re
from GameObjects import Location, Collectable, Pocket
from GameEngine import screen_clear, timed_print, close_game, opensite, im_show, copyFile
from random import choice
import networkx as nx
from matplotlib.pyplot import show

"""Build all the locations"""

Main_Gate = Location(
    "Main Gate",
    "A Nice Big Arch!\n"
    "Students are coming back from their Friday night party at 12am...")
East_Gate = Location(
    "East Gate",
    "A train passes by...")
T_Point = Location(
    "T point",
    "Hunh, I can see something weird in this mirror, Oh that's just me...")
Admin = Location(
    "Admin",
    "You enter the lovely automatic sliding doors, a cool blast of AC...\n"
    "You see the IISER-M model and remember that 4 more hostels need to be built.\n"
    "But there are no funds...")
CAF = Location(
    "CAF",
    "Very sensitive machines which may be disturbed by students "
    "eating in the cafeteria\n"
    "You hear someone shouting at someone else in the distance, "
    "but do not record it, for it would be a violation of privacy")
Library = Location("Library", "So quiet...")
Computer_Center = Location("Computer Center",
                           "A few computers have not been turned off")
Health_Center = Location("Health Center", "A very dark and scary place...")

Outside_LHC = Location("Outside LHC", "The LHC may be locked at this time...")
LHC = Location("LHC", "Ah the good old LHC...")
LH1 = Location('LH1', "There's a BIG flowchart on the board!")
LH2 = Location('LH2', "There are so many computers.")
LH3 = Location(
    'LH3',
    "You can still hear the debates that happened here a few hours ago.")
LH4 = Location('LH4', "Nothing interesting")
LH5 = Location('LH5', "Someone has left their bottle outside.")
LH6 = Location(
    'LH6',
    'Someone forgot their umbrella. Some differential equations are written on the board')
LH7 = Location(
    'LH7',
    "The watchman shoos you away. The stage is too precious to even repair...")

Rotunda = Location(
    'Rotunda',
    'You see a gang of MS19 making a lot of noise...')
H5 = Location(
    'H5',
    'Caretaker\'s Office is locked. Why is it always locked? Hmm...\n'
    "It's dark outside, you may need a torch")
H5_SR = Location('H5 SR', "Back to the start...")
H6 = Location('H6', 'Hos... The rest of the banner is torn...\n'
              "It's dark outside, you may need a torch")
H6_SR = Location(
    'H6 SR',
    'You see a couple snogging. They see you. It\'s so awkward')
H7 = Location('H7', 'Someone is taking their clothes to wash...\n'
              "It's dark outside, you may need a torch")
H7_SR = Location(
    'H7 SR',
    'Those Dance Club people are still dancing in the Dance Room')
H8 = Location(
    'H8',
    'Some MS18 kids are loitering around...\n'
    "It's dark outside, you may need a torch")
H8_SR = Location(
    'H8 SR',
    'The ACs are off, it\'s so hot...\nOh wait, they are on... '
    'Why is it so hot then? Oh the ACs aren\'t working')

Stadium = Location('Stadium', 'A lapwing shouts in the distance...')
BB_Court = Location('BB Court', 'Why the fuck do lapwings make so much noise?')
VH = Location(
    'VH',
    'Dollar building. The terrace may be locked')
VH_Terrace = Location(
    'VH Terrace',
    'Haaah! Nice and windy.\n'
    'You see a couple of friends talking about the struggles of life...')
Shopping_Complex = Location(
    'Shopping Complex',
    'It\'s so empty and quiet. Aunty must have gone home...')

AB1 = Location(
    'AB1',
    'You buy a nice coffee for 10rs, coz neither of you have change')
AB1_1F = Location('AB1 1F', 'People playing Badminton...')
AB1_2F = Location('AB1 2F', 'Eerily dark and quiet')
AB1_3F = Location(
    'AB1 3F',
    'One lone MS13 is studying there. Why haven\'t they graduated yet?')
AB1_4F = Location('AB1 4F', 'Eerily dark and quiet')
EBL_Lab = Location(
    'EBL',
    'So many dead flies in flasks.\nIt\'s like a horror movie')
AB1_5F = Location(
    'AB1 5F',
    'Eerily dark and quiet, but there\'s some news article about '
    'Plastic Firecrackers...')
AB2 = Location(
    'AB2',
    'ERROR! The app devs didn\'t care enough to make 2 AB\'s.\n'
    'There\'s nothing here. Go away, shoo.')
Gazebo = Location(
    'Gazebo',
    'There\'s some MS17 party going on there. Oh god so much cake wasted.\n'
    'Talking about wasting stuff, they\'re fixing the covers...')
Behind_AB = Location(
    'Behind AB',
    'Aww! 3 cute puppies run up to you.\n'
    r"""
           A_         __         __
      (___/ "`;  [___()"`;  \___()"`;
      /,    /`   /,    /`   /,    /`
      \\"--\\   //"--//     \\"--\\

    """)
Animal_Center = Location(
    'Animal Center',
    'The everlasting humm of the machines...\n' +
    'What are these machines? What happens here? SO MANY QUESTIONS!')
Room69 = Location(
    'Room No 69',
    'Why is it numbered 69 if it is the only room here?\n' +
    'I have found this place unlocked for the first time. Should explore it a bit.')

"""Connect the Locations to make a traversable map"""
Main_Gate.append_locations([Behind_AB, Admin, CAF])
East_Gate.append_locations([Animal_Center, Behind_AB])
T_Point.append_locations([CAF, Outside_LHC, Admin, Health_Center])
Health_Center.append_locations([T_Point, BB_Court])
Admin.append_locations([Main_Gate, CAF, T_Point])
CAF.append_locations([Admin, Main_Gate, T_Point])
Library.append_locations([Outside_LHC, Gazebo, Computer_Center])
Computer_Center.append_locations([Library])

Outside_LHC.append_locations([T_Point, Library, Rotunda, Animal_Center])
LHC.append_locations([LH1, LH2, LH3, LH4, LH5, LH6, LH7, Outside_LHC])
LH1.append_locations([LHC])
LH2.append_locations([LHC])
LH3.append_locations([LHC])
LH4.append_locations([LHC])
LH5.append_locations([LHC])
LH6.append_locations([LHC])
LH7.append_locations([LHC])

Rotunda.append_locations([Outside_LHC, H5, H6, H7, H8, Stadium])
H5.append_locations([H5_SR])
H6.append_locations([Rotunda, H6_SR])
H7.append_locations([Rotunda, H7_SR])
H8.append_locations([Rotunda, H8_SR])
H5_SR.append_locations([H5])
H6_SR.append_locations([H6])
H7_SR.append_locations([H7])
H8_SR.append_locations([H8])

Stadium.append_locations([Rotunda, BB_Court, Shopping_Complex])
BB_Court.append_locations([Health_Center, Stadium])
Shopping_Complex.append_locations([Stadium, VH])
VH.append_locations([Shopping_Complex])
VH_Terrace.append_locations([VH])

AB1.append_locations([Gazebo, AB2, Behind_AB, AB1_1F])
AB1_1F.append_locations([AB1, AB1_2F])
AB1_2F.append_locations([AB1_1F, AB1_3F])
AB1_3F.append_locations([AB1_2F, AB1_4F])
AB1_4F.append_locations([AB1_3F, AB1_5F, EBL_Lab])
EBL_Lab.append_locations([AB1_4F])
AB1_5F.append_locations([AB1_4F])
AB2.append_locations([Gazebo, Behind_AB, AB1])
Gazebo.append_locations([Library, AB1, AB2, Behind_AB])
Behind_AB.append_locations([Main_Gate, East_Gate, AB1, AB2, Gazebo])
Animal_Center.append_locations([Outside_LHC, East_Gate, ])
Room69.append_locations([Animal_Center])

"""Build Actual clues"""

def clue8Action():
    print("Is half the year over already?!")
    im_show("calender.jpg")
    ans = input("Enter the correct year: ")
    if ans == "2036":
        return True
    return False

clue8 = Collectable(
    "unusually clean sheet of paper",
    "taped to the pillar, above the wash basin",
    "Seems kinda out of place between all these Melody chocolate posters from 2007",
    hidden=True,
    action=clue8Action,
    nextnotes=None,
    onComplete="Congratulations! You have successfully reached the end of this treasure hunt\n"
               "You can go back to dying of boredom now. Bye.",  # something else
    onFail="Tsk.Tsk. So close yet so far. Try again.")

def clue7Action():
    print("There is a file. Save it in your PC.")
    a = input("Would you like to proceed?[Y/N]")
    if(a == "Y"):
        _ = copyFile("image.jpg")
    b = input("Enter the number if you have found it: ")
    if(b == "690"):
        Pocket.append("Note - Truly, 69 is an important number")
        Animal_Center.append_locations([Room69])
        return True
    return False

clue7 = Collectable(
    "Found a USB drive",
    "Hanging from the ceiling by means of a thread!\n"
    "Either the developer was too sleepy to think of anything better "
    "or this is a weird place.",
    "Should plug it in my pc to check what it is",
    hidden=True,
    action=clue7Action,
    nextnotes=[clue8],
    onComplete="That was some smart work! Truly 69 is an important number!",
    onFail="What's the first thing you do when you don't know what a file is?")

def clue6Action():
    print("""
            The quest is to find the direction of your life...\n
            Two roads... first towards the accelerator and second towards jordon\n
            And let your octaves fill the keanu reeves movie\n
            Apply some contrast of free will and maybe lose the negativity ...\n
            You should be good to go now\n
            """)

    ans = input("Enter your password: ")
    if ans == "22":
        Pocket.append(
            "Clue - H-ate me or love me, you need to Study with me")
        Pocket.append("Key to VH Terrace")
        VH.append_locations([VH_Terrace])
        return True
    return False

clue6 = Collectable(
    "wooden box",
    "between H6 & H8",
    "It has a paper stuck on it...\n"
    "Man these treasure hunt people need to stop dipping paper in coffee to make it seem old..\n"
    "There's also a two digit number lock!\n",
    hidden=True,
    action=clue6Action,
    nextnotes=[clue7],
    onComplete="The box clicked open! Let's see what's inside."
    "A key to VH Terrace and a Note-\n\n"
    """
    +=================================+
    |                                 |
    |    H-ate me or love me,         |
    |    you need to Study with me    |
    |                                 |
    +=================================+

    """
    "They seriously need to drop the coffee trick",
    onFail="The box didn't open.\n"
    "Hehe seems like you're directionally challenged :)\n"
    "Look at it from a different perspective maybe")

def clue5Action():
    i = 0
    question_prompt = ["Cell's leader says 'Carry on!' suspiciously...",
                       "Is the Spanish Crown alive?", "Hiding in a plaza having a handicap",
                       "Chris, who left the hotel, heads the Public Relations Forum at Caribou Biosciences"]
    answers = ["KARYON", "CORONAVIRUS", "ZAHAVI", "CRISPR"]
    while i < len(question_prompt):
        print(question_prompt[i])
        ans = input("Enter your answer: ")
        if ans.upper() == answers[i]:
            i += 1
        else:
            return False
    Pocket.append("Bio Pop quiz answer sheet - Should show friends in Rotunda")
    return True

clue5 = Collectable(
    "Bio Pop Quiz",
    "tucked inside the bottle...?",
    "Why would someone do that?\n"
    "A small sheet with a few questions (that will definitely be counted for your consolidated grades :-))",
    True,
    clue5Action,
    nextnotes=[clue6],
    onComplete="Yay!! You answered everything correctly!\n"
    "*happy biologist noises*\n"
    "Maybe you should go tell your friends in Rotunda",
    onFail="OOPS. Looks like you'll need to start all over again")

def clue4Action():
    dst = copyFile("mutations.pdf")
    if dst:
        Pocket.append("mutations.pdf in " + dst)
        return True
    return False

clue4 = Collectable(
    "BIO211 experiment draft",
    "in the dustbin",
    "Maybe this holds some mysteries to the next location?",
    hidden=True,
    action=clue4Action,
    nextnotes=[clue5],
    onComplete="Read the copied file, the secret lies within",
    onFail="File copy error, retry")

def clue3Action():
    print("PENALTY at 45 degrees")
    im_show("cube.jpg")
    print("Message: C.Amjg md eclcrgaq")  # change this please
    a = input("What does that mean? ")
    if a == "E.Coli of genetics":  # change this please
        Pocket.append("Clue - E.Coli of genetics")
        return True
    return False

clue3 = Collectable(  # put the clue in lhc rn, change it to anywhere
    "Poster",
    "on the softboard",
    "It's the poster of the Cubing competition held in college some time back",
    hidden=True,
    action=clue3Action,
    nextnotes=[clue4],
    onComplete="Hmm? Is that important?",
    onFail="Just search the net man")

def clue2Action():
    opensite("clue2.html")
    a = input("What's the password? ")
    if a == "acceptme":
        Pocket.append("Clue - Large Hadron Collider")
        return True
    return False

clue2 = Collectable(
    "Quantum Computer",
    "in the BIG BIG hall",
    "Another webpage on the way, on a quantum computer!\n"
    "They used a quantum computer for opening a webpage?\n"
    "Perfect utilization of a non-existent resource",
    hidden=True,
    action=clue2Action,
    nextnotes=[clue3],  # made clue 3 next
    onComplete="Yeah, this was a joke. Now head to the Large Hadron Collider..?",
    onFail="Noooo! This one is dumb too.")

def clue1Action():
    opensite('clue1.html')
    a = input("What's the key? ")
    if a == "TUr!ng":
        Pocket.append("Clue - Costly Machines, easy clues...")
        return True
    return False

clue1 = Collectable(
    "website",
    "running on one of the computers",
    "This website seems like a clue...",
    hidden=False,
    action=clue1Action,
    nextnotes=[clue2],
    onComplete="Costly Machines, easy clues...",
    onFail="No, it's the first question. It's dumber than you think!")

def lhckey_action():
    if input("Pick it?[Y N] ") == "Y":
        Outside_LHC.append_locations([LHC])
        Pocket.append("LHC Key")
        return True
    return False

lhckey = Collectable(
    "LHC Key",
    "hanging by the security",
    "It looks like a normal key. Maybe you can finally see what's inside LHC?",
    hidden=False,
    action=lhckey_action,
    onComplete="Now get out of here before the security guard comes back",
    onFail="There was a nice art exhibition in LHC I heard?")

""" Build FLUFF """
hostel_cctv = Collectable(
    "Notice",
    "on the Soft Board",
    """
    ========================================
    |                                      |
    |   YOU ARE UNDER CCTV SURVIELLENCE!   |
    |                                      |
    ========================================
    """)

def fake_clue_action():
    print("The password is 5")  # some message
    return input("What's the password? ") == "5"  # some prompt

fake_clue = Collectable(
    "Fake Clue",
    "under some table",  # some specific place
    "This is a test clue",  # message of a clue
    False,  # Not hidden
    fake_clue_action,  # action object
    [hostel_cctv],  # next note
    "Yay! Look for a treat in the Hostels",
    "Noo, you dumb?")

def biswas_car_action():
    global here
    next_loc = choice(
        [Behind_AB, East_Gate, Animal_Center, LHC, BB_Court, Stadium, Shopping_Complex])
    print("You followed the car and ended up in " + next_loc.name + "!")
    here = next_loc
    return True

biswas_car = Collectable(
    "red sedan",
    "coming from Animal Facility road",
    "It's approaching almost quasistatically...\n"
    "Why would someone be driving around at midnight?! This is pretty shady."
    "Probably not important. It's not like they're going to run over anybody.\nRight?\n\nRIGHT?",
    hidden=False,
    action=biswas_car_action,
    onComplete="This had better be worth-- \nWAIT! THE DRIVER IS ASLEEP?! *facepalm*",
    onFail="Unreachable. Report to devs")
biswas_car.nextnotes = [biswas_car]  # Work around to skip the try again

stadium_test = Collectable(
    name="Rocket Pad",
    spot="in the stadium",
    desc="Lets fly the rocket.\n"
    "It went so high that you can't even see it!!!\n\n\n"
    "Oh no! It's falling back! RUNNN!",
    hidden=True)

def printer_3d_action():
    print("Printer shows a message 'Please input the blueprint'")
    print("You should wait for the MS19 kids to finish...\n\nOr you could just print the blueprints now...")
    if input("Do you want to print the blueprint? [Y N] ") == "Y":
        Pocket.append("3D Printed Rocket")
        return True
    return False

printer_3d = Collectable(
    name="3D printer",
    spot="outside physics lab",
    desc="You go near the 3D printer and see a bunch of MS19 students sleeping around it.\n\n"
    "They are probably tired from waiting their turn at the printer.",
    hidden=True,
    action=printer_3d_action,
    nextnotes=[stadium_test],
    onComplete="The Printer started making weird noises.\n\n\n"
    "You got a 3d printed rocket!\n"
    "You should try flying it in some open place with a lot of grass.\n"
    "Better get out of here before the MS19 kids wake up.",
    onFail="Lets get outta here")

def samrat_inno_action():
    im_show("rocket.jpg")
    print("Maybe I can 3D print this and see if it works")
    if input("Do you want to steal - no, borrow - this? [Y N] ") == "Y":
        Pocket.append("Rocket.jpg")
        return True
    return False

samrat_inno = Collectable(
    name="a Blueprint",
    spot="on the table",
    desc="Innovation #42054....\n\n",
    hidden=False,
    action=samrat_inno_action,
    nextnotes=[printer_3d],
    onComplete="We will have to find a 3D printer...",
    onFail="Nope, it's someone else's property")

def art_competition_action():
    print("- Shivali")
    im_show("art1.jpg")
    print("- Saloni Sahu")
    im_show("art2.jpg")
    print("- Shivali")
    im_show("art3.jpg")
    return False

art_competition = Collectable(
    name="multiple art pieces",
    spot="on soft boards",
    desc="There was an art competition held a few days ago.\n"
    "These are some of the beautiful paintings some people have made!",
    hidden=False,
    action=art_competition_action,
    onComplete="Unreachable. Report to devs",
    onFail="Damn! Those were so pretty! I wish I could make things like that")

def room69_action():
    im_show('69.jpg')
    Pocket.append("Clue - Go to Shopping Complex")
    print("Let's take a picture of this.")
    a = input("Do you want to continue[Y/N]")
    if(a == "Y"):
        _ = copyFile("69.jpg")
    return False

room69poster = Collectable(
    name='lot of cult articles',
    spot='everywhere, even on the ceiling',
    desc='There is a poster on the wall. Should read it.',
    hidden=False,
    action=room69_action,
    onFail="That is some weird thing...\n"
    "More than what meets the eye...\n"
    "Could it be a clue?\n\n"
    "Eh screw it... I'm hungry now... I should check if Shopping Complex is open",
    onComplete="Unreachable. Report to devs.")

def torch_action():
    print("You turn it on and it's very bright!\n")
    if input("Do you want to take it [Y N]? ") == "Y":
        H5.append_locations([Rotunda])
        Pocket.append("A red Torch")
        return True
    return False

torch = Collectable(
    "Torch",
    "on the table",
    "It's a nice red color.",
    action=torch_action,
    hidden=False,
    onComplete="You can now see in the dark and outside!",
    onFail="You should really take it...")

def mmystery_board_action():
    im_show("board.jpg")
    return False

mmystery_board = Collectable(
    name="flowchart",
    spot="on the board",
    desc="These Murder Mystery people are out of their mind.",
    hidden=False,
    action=mmystery_board_action,
    onComplete="Unreachable. Report to devs",
    onFail=""
)

def mmystery_poster_action():
    im_show("mmystery.jpg")
    return False

mmystery_poster = Collectable(
    name="poster for murder mystery",
    spot="on the table",
    desc="There's a sign under the poster. '- Bhavneet Singh'",
    hidden=False,
    action=mmystery_poster_action,
    onComplete="Unreachable. Report to devs",
    onFail="This guy can make nice posters!"
)

def vht_action():
    im_show("trails.jpg")
    im_show("vht.jpg")

vht = Collectable(
    "photo album of the night sky",
    "on the ground",
    "Such lovely images!\n"
    "These were taken by Kaustubh Verma and Amit Yogi!",
    hidden=False,
    action=vht_action,
    onComplete="Unreachable. Report to devs",
    onFail="These guys can take nice pictures!"
)

"""Add Notes to Locations"""

Computer_Center.append_collectable([clue1])
CAF.append_collectable([clue2])
EBL_Lab.append_collectable([clue4])
LHC.append_collectable([art_competition, clue3])
LH5.append_collectable([clue5])
Rotunda.append_collectable([clue6])
H8_SR.append_collectable([clue7])
Shopping_Complex.append_collectable([clue8])

VH_Terrace.append_collectable([vht])

H5.append_collectable([hostel_cctv])
H6.append_collectable([hostel_cctv])
H7.append_collectable([hostel_cctv])
H8.append_collectable([hostel_cctv])

AB1_3F.append_collectable([printer_3d])
AB1_5F.append_collectable([samrat_inno])
Stadium.append_collectable([stadium_test])

Admin.append_collectable([lhckey])
H5_SR.append_collectable([torch])
T_Point.append_collectable([biswas_car])
Room69.append_collectable([room69poster])
LH1.append_collectable([mmystery_board, mmystery_poster])

def makemap(root):
    g: nx.DiGraph = nx.DiGraph()

    def makenodes(root, l):
        if root not in l:
            l.append(root)
            for loc2 in root.locations:
                g.add_edge(root.name, loc2.name)
                makenodes(loc2, l)
    makenodes(root, [])
    nx.draw_kamada_kawai(
        g,
        with_labels=True,
        node_size=750,
        font_size=7,
        width=2,
        edge_color='#6B6B6B')
    show()

hello_banner = '''Welcome to the Virtual Treasure Hunt!
The Treasure Hunt will go on until you finish it.
Though this is an individual game, it is best served with a side of video call with your friends.
But remember that they can hide things from you and win themselves. :P

You can use the internet, but it is not necessary to have a continuous connectivity.
Please remember that if you exit from this app (by pressing the X or by
shutting down your computer), you will HAVE to restart.
You can minimize this safely, however.
We suggest that you also keep a notepad window open to note down information.

Some clues may seem too technical, but they're generally straight forward.
Just search the internet if you get stuck!

Go forth and do your best!'''

here = H5_SR

def systest():
    screen_clear()
    print("This is a system test. Report to devs if any errors are shown.")
    if input("Enter to Start systest") == "skip":
        return
    print()
    print("You will be shown a map. This test will be a success if you can see the map. Close the map to continue...")
    input("Enter to continue")
    makemap(Rotunda)
    print("makemap success")
    print()

    print("You will be shown an image. This test will be a success if you can see the image. Close the image to continue...")
    input("Enter to continue")
    im_show("owl.jpg")
    print("im_show success")
    print()

    print("You will be asked to save a file. Success if file is saved correctly")
    input("Enter to continue")
    if copyFile("test.txt"):
        print("copyFile success")
    else:
        print("copyFile fail")
    print()

    print("You will be redirected to a test site")
    input("Enter to continue")
    opensite("test.html")
    print("If website shown correctly, opensite success")
    print()

    input("This concludes systest. Enter to continue")

def mainloop():
    global here
    while True:
        screen_clear()
        msg = ""
        print(here)
        print("\n\n")
        print("If you want to search around, type search or ls")
        print("If you want to view map, type map")
        print("If you want to view pocket, type pocket")
        print("If you want to go somewhere else, "
              "type goto _location_ or cd _location_")
        print()

        inp = input("Your choice: ")
        match_obj = re.search(r"^(goto|cd) .*", inp)
        if re.search(r"^(search|ls)$", inp):
            msg = here.search()
        elif match_obj:
            new_loc = inp[len(match_obj.group(1)) + 1:]
            msg, here = here.goto(new_loc)
        elif re.search(r"^map$", inp):
            print("Close map to continue")
            makemap(here)
        elif re.search(r"^pocket$", inp):
            Pocket.show()
        elif re.search(r"^exit$", inp):
            if input("Type exit again to exit, anything else to go back: ") == "exit":
                close_game()
        else:
            msg = "Invalid Input"
        if (msg):
            timed_print(msg, 3)

screen_clear()
print(hello_banner)
input("Press Enter to start systest")
systest()
screen_clear()
print("""    How to play -
        Use `ls` or `search` to look around for clues and other helpful items
        Use `goto location name` or `cd location name` to move to connecting locations
        Use `map` to open up the map. Note that as you collect more items, new locations open up!
        Use `pocket` to view a list of items collected. This is very helpful if you get stuck.

    Go ahead and enjoy! Good Luck!
""")
input("Press Enter to start the Game!")
mainloop()


#coding:utf-8
from bs4 import  BeautifulSoup
import json
import re
import urllib.request
from scrapy.selector import Selector
#from pybloom import BloomFilter
from BloomFilter import *
class HtmlParser(object):
    def parse_content(self,response):
        #soup = BeautifulSoup(open(response, encoding='utf-8'), 'lxml')
        soup = BeautifulSoup(response.text, 'lxml')
        #用户名
        userName = soup.find("span", class_='ProfileHeader-name').get_text()
        #一句话介绍
        if soup.find("span",class_='RichText ProfileHeader-headline') ==None:
            introduction = None
        else:
             introduction =soup.find("span",class_='RichText ProfileHeader-headline').get_text()
        #居住地
        if len(soup.select('div[class="ProfileHeader-infoItem"]')) == 0 :
            location = None
        else:
            location =soup.select('div[class="ProfileHeader-infoItem"]')[0].get_text("|")
        with open('topic.txt', 'a',encoding="utf-8") as f:
            f.write('用户:%s  一句话介绍:%s  其他相关信息:%s\n' %(userName,introduction,location))
        #我关注的人的总页数
        follower_maxPage = Selector(response).xpath(".//*[@class='Button PaginationButton Button--plain'][last()]/text()").extract()
        if not follower_maxPage :
            follower_maxPage = 1
        else:
            follower_maxPage = int(follower_maxPage.pop())
            if follower_maxPage>3:
                follower_maxPage = 3
        print("follower_maxPage........",follower_maxPage)
        #用户头像
        imageUrl = soup.find("img",class_='Avatar Avatar--large UserAvatar-inner').attrs['src']
        Image_Address = 'C:/Users/zhou/PycharmProjects/zhihu-Test01/Images/%s.jpg' % (userName)
        print("Image_Address.........",Image_Address)
        if imageUrl is not None:
            urllib.request.urlretrieve(imageUrl,Image_Address)

        return userName,introduction,location,Image_Address,follower_maxPage
        # userItem.userName =userItem
        # userItem.introduction = introduction
        # userItem.other_Infos = location
        # userItem.Image_Address = 'C:/Users/zhou/PycharmProjects/zhihu-Test01/Images/%s.jpg' % (userName)

    def parse_User(self,response):
        soup = BeautifulSoup(response, 'lxml')
        #soup = BeautifulSoup(open("C:/Users/zhou/Desktop/index.html", encoding='utf-8'), 'lxml')
        url_temp = soup.find_all("a",attrs={"data-za-detail-view-element_name":"User"})
        us = set()
        users = set()
        for u in url_temp:
            if u in us:
                pass
            else:
                us.add(u)
               # user='https://www.zhihu.com%s/following'%(u.attrs['href'])
                user = u.attrs['href']
                users.add(user)
        return users

    def parse(self,response):
        if response == None:
            return None
        else:
            self.parse_content(response)
            urls = self.parse_url(response)
            return urls

    def parse_asks(self,response):
        soup = BeautifulSoup(response, 'lxml')

        if response is None:
            pass
        else:
            questionHrefs = []
            questionNames = []
            if soup.find("div", class_='QuestionItem-title') is None:
                pass
            else:
                for question_link in soup.find_all("div", class_='QuestionItem-title'):
                    questionHref = question_link.find('a').attrs['href']
                    questionName = question_link.get_text()
                    # questionHrefs = '%s;%s'%(questionHrefs,questionHref)
                    # questionNames = '%s;%s'%(questionNames,questionName)
                    questionNames.append(questionName)
                    print( 'questionNames...........', questionNames)
                return questionNames

    def parse_collections(self, response):
        soup = BeautifulSoup(response, 'lxml')
        if response is None:
            pass
        else:
            collections = []
            if soup.find("div", class_='FavlistItem-title') is None:
                pass
            else:
                collectionNames = []
                for collection_link in soup.find_all("div", class_='FavlistItem-title'):
                    collectionName = collection_link.get_text()
                    # collectionNames = '%s;%s' %(collectionNames,collectionName)
                    collectionNames.append(collectionName)
                    print('collectionNames...........', collectionNames)
                return collectionNames
    #扒取用户关注的人和关注用户的人
    def parse_followers(self, response):
        soup = BeautifulSoup(response, 'lxml')
        follower_names = []
        follower_hrefs = []
        if soup.find_all("span",class_='UserLink UserItem-name') is None:
            pass
        else:
            for soup_link in soup.find_all("span",class_='UserLink UserItem-name'):
                follower_name = soup_link.get_text()
                follower_href = soup_link.find('a').attrs['href']
                follower_names.append(follower_name)
                follower_hrefs.append(follower_href)
            return follower_hrefs,follower_names
    #扒取关注用户的人
    def parse_followee_maxPage(self,response):
        #关注该用户的用户页数
        followee_maxPage = Selector(response).xpath(".//*[@class='Button PaginationButton Button--plain'][last()]/text()").extract()
        if not followee_maxPage:
            followee_maxPage = 1
        else:
            followee_maxPage = int(followee_maxPage.pop())
            if followee_maxPage > 3:
                followee_maxPage = 3
        return followee_maxPage

    def parse_question_response(self,response,question_Id):
        bf = BloomFilter()
        #问题题目
        soup = BeautifulSoup(response, 'lxml')
        question_title = soup.find("div",class_="QuestionPage").find("meta",attrs={"itemprop":"name"}).attrs["content"]
        question_keywords = soup.find("div",class_="QuestionPage").find("meta",attrs={"itemprop":"keywords"}).attrs["content"]
        question_answerCount = soup.find("div",class_="QuestionPage").find("meta",attrs={"itemprop":"answerCount"}).attrs["content"]
        question_title_details=soup.find("div",class_="QuestionRichText--collapsed").find("span").get_text()
        question_List_item = soup.find_all("div",class_="List-item")
        comments = []
        try:
            for q_L_i in question_List_item:
                comment = {}
                # 回答者
                question_item_name = q_L_i.find("meta", attrs={"itemprop": "name"}).attrs["content"]
                # 回答
                question_item_comment = q_L_i.find("span", class_="RichText CopyrightRichText-richText").get_text()
                # 支持人数
                question_item_vote = q_L_i.find("button", class_='Button VoteButton VoteButton--up').get_text()
                comment['回答者'] = question_item_name
                comment['回答'] = question_item_comment
                comment['点赞数'] = question_item_vote

                if bf.isContains(question_Id,comment):
                    print('存在该comment',comment)
                    pass
                else:
                    print('新评论',comment)
                    bf.insert(question_Id,comment)
                    comments.append(comment)
        except:
            pass
        js = {"标题": question_title, "关键字": question_keywords, "回答数": question_answerCount, "问题说明": question_title_details,
              "回答": comments, }
        question_json = json.loads(json.dumps(js, ensure_ascii=False))
        return question_json

    def parse_question_url(self,response):
        question__urls = []
        soup = BeautifulSoup(response, 'lxml')
        question_item_name = soup.find("meta", attrs={"itemprop": "url","content":re.compile('https://www.zhihu.com/question/(\d){8}')}).attrs["content"]
    #寻找根标题(如游戏、运动等)下面的子标题
    def parse_topic_url(self,response):
        soup = BeautifulSoup(response, 'lxml')
        urls = set()
        topic_finds = soup.find_all("a",attrs={"href":re.compile('/topic/(\d){8}')})
        for topic_find in topic_finds:
            topic_url = topic_find.attrs['href']
            urls.add(topic_url)
        return urls

    def parse_topic_question_url(self,response):
        #问题题目
        soup = BeautifulSoup(response, 'lxml')
        question_links_soup = soup.find_all("a",class_='question_link')
        question_links = set()
        for question_link_soup in question_links_soup:
            question_link = question_link_soup.attrs['href']
            question_links.add(question_link)
        return question_links

if __name__ == '__main__':
    zhihu = HtmlParser()
    zhihu.parse_content()


from __future__ import absolute_import
from __future__ import division
from __future__ import print_function

import os
import sys
import time
import numpy as np

from utils import parse_listfile

def parse_pairwise_score(pairwise_score):
    lines = parse_listfile(pairwise_score, [1, 2, 3])
    pairs, scores = [], []
    for i in lines:
        pairs.append((i[0], i[1]))
        scores.append(i[2])
    return pairs, scores

def parse_pair(pairlist):
    return parse_listfile(pairlist, [1, 2])

def main(lindahl_pairwise_score, lindahl_family, lindahl_superfamily, lindahl_fold):
    start = time.clock()
    # score dict
    pairs, scores = parse_pairwise_score(lindahl_pairwise_score)

    # lindahl data
    lindahl_family = parse_pair(lindahl_family)
    lindahl_superfamily = parse_pair(lindahl_superfamily)
    lindahl_fold = parse_pair(lindahl_fold)
    assert len(lindahl_family) == 1646 and len(lindahl_superfamily) == 2130 and len(lindahl_fold) == 3662

    # label +1 or -1 for scores
    fout_family = open('value-family', 'w')
    fout_superfamily = open('value-superfamily', 'w')
    fout_fold = open('value-fold', 'w')
    for i, p in enumerate(pairs):
        if not (i+1) % 100:
            print('.', end='', file=sys.stderr)
        if not (i+1) % 10000:
            print(i+1, file=sys.stderr)
        if p in lindahl_family:
            print('+1', scores[i], file=fout_family)
        elif p in lindahl_superfamily:
            print('+1', scores[i], file=fout_superfamily)
        elif p in lindahl_fold:
            print('+1', scores[i], file=fout_fold)
        else:
            print('-1', scores[i], file=fout_family)
            print('-1', scores[i], file=fout_superfamily)
            print('-1', scores[i], file=fout_fold)
    fout_family.close()
    fout_superfamily.close()
    fout_fold.close()

    stop = time.clock()
    print('Time Spent =', stop - start)

if __name__ == '__main__':
    if len(sys.argv) != 2:
        sys.exit('Usage: %s <lindahl_pairwise_score>' % sys.argv[0])
    lindahl_pairwise_score = sys.argv[1]

    prefix = os.path.dirname(sys.argv[0])
    lindahl_family = '%s/list/lindahl_family' % prefix
    lindahl_superfamily = '%s/list/lindahl_superfamily' % prefix
    lindahl_fold = '%s/list/lindahl_fold' % prefix

    main(lindahl_pairwise_score, lindahl_family, lindahl_superfamily, lindahl_fold)


from django.template import Library

from snpdb.forms import ProjectChoiceForm, VariantsTypeMultipleChoiceForm
from snpdb.models import GenomeBuild, VariantsType
from snpdb.templatetags.jqgrid_tags import get_grid_id

register = Library()

@register.inclusion_tag("snpdb/tags/vcf_grid_filter_tags.html", takes_context=True)
def vcf_grid_filter(context, grid_id_suffix, variants_type=False):
    grid_id = get_grid_id(grid_id_suffix)
    # ProjectChoiceForm is shown twice (Samples and VCF) so we need to alter the IDs
    project_form = ProjectChoiceForm()
    project_form.fields["project"].widget.attrs["id"] = f"id_project_{grid_id}"

    context = {
        'grid_id': grid_id,
        "project_form": project_form,
        "genome_builds": GenomeBuild.builds_with_annotation(),
    }

    if variants_type:
        vt_initial = {"variants_type": [c[0] for c in VariantsType.choices]}
        context["variants_type_form"] = VariantsTypeMultipleChoiceForm(initial=vt_initial)
        context["variants_type_labels"] = dict(VariantsType.choices)

    return context


# Dump the schema of a database created by using sqlalchemy
# code modified from:
# https://stackoverflow.com/questions/40619434/dump-postgresql-database-schema-with-python
# You can visualize the schema by using MySQLWorkbench:
# https://dev.mysql.com/downloads/workbench/
import io
from sqlalchemy import create_engine, MetaData
from sqlalchemy.orm import sessionmaker

class SchemaDump(object):
    def __init__(self, db_url, schema_file_path):
        self.db_url = db_url
        self.schema_file_path = schema_file_path
        self.buf = io.BytesIO()

    def dump_shema(self):
        engine = create_engine(self.db_url)
        metadata = MetaData()
        metadata.reflect(engine)

        def dump(sql, *multiparams, **params):
            f = sql.compile(dialect=engine.dialect)
            self.buf.write(str(f).strip().encode())
            self.buf.write(str(';\n').encode())

        new_engine = create_engine(self.db_url, strategy='mock', executor=dump)
        metadata.create_all(new_engine, checkfirst=True)

        with io.open(self.schema_file_path, 'wb+') as schema:
            schema.write(self.buf.getvalue())

sd = SchemaDump("sqlite:///database.db", "schema.sql")
sd.dump_shema()
print("Schema created.")


import tensorflow as tf
import cv2
import numpy as np
import model
import socket
import threading
import sys
import os
import struct

x, y, predict, loss, accuracy, merged, softmax = model.build_model()
saver = tf.train.Saver()
sess = tf.InteractiveSession()

saver.restore(sess, tf.train.latest_checkpoint("./persist_model_1/"))

def predict_value(type='image', image_path=None):

    if type == 'image':
        assert image_path is not None
        image = cv2.imread(image_path)
        if image.shape != (200, 200):
            image = cv2.resize(image, (200, 200))
        image = np.asarray(image, np.float32) / 255.
        image = np.reshape(image, (1, image.shape[0], image.shape[1], image.shape[2]))
        [predict_, probabilistic] = sess.run([predict, softmax], feed_dict={x: image})
        probabilistic = np.max(probabilistic)
        print("category: %d, prob: %.4f" % (predict, probabilistic))
        if predict_ == 0:
           return 2 #有毒垃圾
        elif predict_ == 1:
            return 1 #不可回收垃圾
        elif predict_ == 2:
            return 3 #厨余垃圾
        elif predict_ == 3:
            return 0 #可回收
        elif predict_ == 4:
            return 4 #空盒子
        elif predict_ == 5:
            return 0 # 可回收垃圾
        elif predict_ == 6:
            return 1 # 不可回收垃圾

    elif type == 'video':
        capture = cv2.VideoCapture(0)
        while True:
            ret, frame = capture.read()
            resize = cv2.resize(frame, (200, 200))
            x_ = np.asarray(resize, np.float32) / 255.
            x_ = np.reshape(x_, [1, x_.shape[0], x_.shape[1], x_.shape[2]])
            [predict_, probabilistic] = sess.run([predict, softmax], feed_dict={x: x_})
            probabilistic = np.max(probabilistic)
            if predict_ == 0:
                cv2.putText(frame, "electric probabilistic: %.4f" % probabilistic, (10, 50), cv2.FONT_HERSHEY_SIMPLEX,
                            1,
                            (0, 0, 255), 2, cv2.LINE_AA)
            elif predict_ == 1:
                cv2.putText(frame, "fruit probabilistic: %.4f" % probabilistic, (10, 50), cv2.FONT_HERSHEY_SIMPLEX, 1,
                            (99, 255, 255), 2, cv2.LINE_AA)
            elif predict_ == 2:
                cv2.putText(frame, "lajiao probabilistic: %.4f" % probabilistic, (10, 50), cv2.FONT_HERSHEY_SIMPLEX, 1,
                            (0, 12, 130), 2, cv2.LINE_AA)
            elif predict_ == 3:
                cv2.putText(frame, "yilaguan probabilistic: %.4f" % probabilistic, (10, 50), cv2.FONT_HERSHEY_SIMPLEX,
                            1,
                            (19, 15, 255), 2, cv2.LINE_AA)
            elif predict_ == 4:
                cv2.putText(frame, "void hezi probabilistic: %.4f" % probabilistic, (10, 50), cv2.FONT_HERSHEY_SIMPLEX,
                            1,
                            (255, 190, 255), 2, cv2.LINE_AA)
            elif predict_ == 5:
                cv2.putText(frame, "zhi probabilistic: %.4f" % probabilistic, (10, 50), cv2.FONT_HERSHEY_SIMPLEX, 1,
                            (255, 70, 13), 2, cv2.LINE_AA)
            elif predict_ == 6:
                cv2.putText(frame, "jiaobu probabilistic: %.4f" % probabilistic, (10, 50), cv2.FONT_HERSHEY_SIMPLEX, 1,
                            (255, 0, 100), 2, cv2.LINE_AA)

            cv2.imshow("recognized", frame)
            key = cv2.waitKey(1)
            if key == 27:
                break
        cv2.destroyAllWindows()
        capture.release()
        __close_session__(sess)

def __close_session__(sess):
    sess.close()

def socket_service():
    try:
        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        s.bind(('0.0.0.0', 6666))
        s.listen(10)
    except socket.error as msg:
        print(msg)
        sess.close()
        sys.exit(1)
    print('Waiting connection...')

    while 1:
        conn, addr = s.accept()
        t = threading.Thread(target=deal_data, args=(conn, addr))
        t.start()

def deal_data(conn, addr):
    global predict
    print('Accept new connection from {0}'.format(addr))
    # conn.settimeout(500)
    conn.send('Hi, Welcome to the server!'.encode("utf-8"))

    while 1:
        fileinfo_size = struct.calcsize('128sl')
        buf = conn.recv(fileinfo_size)
        if buf:
            filename, filesize = struct.unpack('128sl', buf)
            fn = filename.strip(b"\x00").decode("utf-8")
            new_filename = os.path.join("./picturetest/test.jpg")
            print(new_filename, filesize)
            print('file new name is {0}, filesize if {1}'.format(new_filename, filesize))

            recvd_size = 0  # 定义已接收文件的大小
            fp = open(new_filename, 'wb')
            print('start receiving...')

            while not recvd_size == filesize:
                if filesize - recvd_size > 1024:
                    data = conn.recv(1024)
                    recvd_size += len(data)
                else:
                    data = conn.recv(filesize - recvd_size)
                    recvd_size = filesize
                fp.write(data)
            fp.close()
            print('end receive...')
        conn.send('已上传'.encode("utf-8"))
        try:
            print("进入识别函数")
            value = predict_value("image", "./picturetest/test.jpg")
            print("函数执行完成：", value)
            conn.send('识别结果：{0}'.format(value).encode("utf-8"))
        except Exception as e:
            print(e)
            sess.close()
            conn.send('识别失败'.encode("utf-8"))
        conn.close()
        break

if __name__ == '__main__':
    # predict_value("video")
    socket_service()


import io
import sys

_INPUT = """\
6
4 10
4 2 3 2
20 100
29 31 68 20 83 66 23 84 69 96 41 61 83 37 52 71 18 55 40 8
"""

sys.stdin = io.StringIO(_INPUT)
case_no=int(input())
for __ in range(case_no):
  #Kruskal法 max_vに頂点数,edgesに辺(重み、結んでいる２つの頂点（順不同）で入れる)
  class UnionFind():
    def __init__(self, n):
      self.n = n
      self.parents = [-1] * n
    def find(self, x):
      if self.parents[x] < 0:
        return x
      else:
        self.parents[x] = self.find(self.parents[x])
        return self.parents[x]
    def union(self, x, y):
      x = self.find(x)
      y = self.find(y)
      if x == y:
        return
      if self.parents[x] > self.parents[y]:
        x, y = y, x
      self.parents[x] += self.parents[y]
      self.parents[y] = x
    def size(self, x):
      return -self.parents[self.find(x)]
    def same(self, x, y):
      return self.find(x) == self.find(y)
    def members(self, x):
      root = self.find(x)
      return [i for i in range(self.n) if self.find(i) == root]
    def roots(self):
      return [i for i, x in enumerate(self.parents) if x < 0]
    def group_count(self):
      return len(self.roots())
    def all_group_members(self):
      return {r: self.members(r) for r in self.roots()}
    def __str__(self):
      return '\n'.join('{}: {}'.format(r, self.members(r)) for r in self.roots())
  def Kruskal(G):
    edges=set()
    for i in range(len(G)):
      for j in range(len(G[i])):
        c,k=G[i][j]
        l,m=min(i,k),max(i,k)
        edges.add((c,l,m))
    edges=list(edges)
    edges.sort()
    uf = UnionFind(len(G))
    mst = [] #最小全域木の辺すべて
    weight=0 #最小全域木の重さ
    for edge in edges:
      if not uf.same(edge[1], edge[2]):
        uf.union(edge[1], edge[2])
        mst.append(edge)
        weight+=edge[0]
    return mst,weight

  N,M=map(int,input().split())
  A=list(map(int,input().split()))
  score=[(pow(A[i],A[j],M)+pow(A[j],A[i],M))%M for i in range(N) for j in range(N)]
  G=[[] for _ in range(N)]
  for i in range(N):
    for j in range(i+1,N):
      G[i].append((-score[i*N+j],j))
      G[j].append((-score[i*N+j],i))
  print(-Kruskal(G)[1])


from datetime import datetime
import logging
from os import path

from flask import current_app as app
from saml2 import BINDING_HTTP_POST
from saml2 import xmldsig
from saml2.client import Saml2Client
from saml2.config import Config as Saml2Config
from saml2.validate import ResponseLifetimeExceed

from pcapi import settings
from pcapi.core.users import constants
from pcapi.core.users import models as user_models

from . import exceptions
from . import models

logger = logging.getLogger(__name__)

BASEDIR = path.dirname(path.abspath(__file__))
FILES_DIR = "files"
PRIVATE_KEY_FILE_PATH = path.join(BASEDIR, f"{FILES_DIR}/private.key")
PUBLIC_CERTIFICATE_FILE_PATH = path.join(BASEDIR, f"{FILES_DIR}/public.cert")

with open(PUBLIC_CERTIFICATE_FILE_PATH, "w") as certificate_file:
    certificate_file.write(settings.EDUCONNECT_SP_CERTIFICATE)
with open(PRIVATE_KEY_FILE_PATH, "w") as key_file:
    key_file.write(settings.EDUCONNECT_SP_PRIVATE_KEY)

def get_saml_client() -> Saml2Client:
    entityid = f"{settings.API_URL_FOR_EDUCONNECT}/saml/metadata.xml"
    https_acs_url = f"{settings.API_URL_FOR_EDUCONNECT}/saml/acs/"

    config = {
        "entityid": entityid,
        "metadata": {
            "local": [
                path.join(BASEDIR, f"{FILES_DIR}/educonnect.{'production' if settings.IS_PROD else 'pr4'}.metadata.xml")
            ],
        },
        "service": {
            "sp": {
                "endpoints": {
                    "assertion_consumer_service": [(https_acs_url, BINDING_HTTP_POST)],
                },
                "allow_unsolicited": True,
                "authn_requests_signed": True,
                "logout_requests_signed": True,
                "want_assertions_signed": True,
                "want_response_signed": True,
            }
        },
        "signing_algorithm": xmldsig.SIG_RSA_SHA256,
        "digest_algorithm": xmldsig.DIGEST_SHA256,
        "cert_file": PUBLIC_CERTIFICATE_FILE_PATH,
        "key_file": PRIVATE_KEY_FILE_PATH,
        "encryption_keypairs": [
            {"key_file": PRIVATE_KEY_FILE_PATH, "cert_file": PUBLIC_CERTIFICATE_FILE_PATH}  # private part
        ],
    }

    saml2_config = Saml2Config()
    saml2_config.load(config)
    saml2_config.allow_unknown_attributes = True

    saml2_client = Saml2Client(config=saml2_config)

    return saml2_client

def get_login_redirect_url(user: user_models.User) -> str:
    saml_client = get_saml_client()
    saml_request_id, info = saml_client.prepare_for_authenticate()

    logger.info(
        "Sending saml login request with educonnect request_id = %s", saml_request_id, extra={"user_id": user.id}
    )
    key = build_saml_request_id_key(saml_request_id)
    app.redis_client.set(name=key, value=user.id, ex=constants.EDUCONNECT_SAML_REQUEST_ID_TTL)

    redirect_url = next(header[1] for header in info["headers"] if header[0] == "Location")
    return redirect_url

def get_educonnect_user(saml_response: str) -> models.EduconnectUser:
    saml_client = get_saml_client()
    try:
        authn_response = saml_client.parse_authn_request_response(saml_response, BINDING_HTTP_POST)
    except ResponseLifetimeExceed as exception:
        logger.error("Educonnect response more than 10 minutes old: %s", exception)
        raise exceptions.ResponseTooOld()
    except Exception as exception:
        logger.error("Impossible to parse educonnect saml response: %s", exception)
        raise exceptions.EduconnectAuthenticationException()

    educonnect_identity = authn_response.get_identity()

    saml_request_id = authn_response.in_response_to

    try:
        return models.EduconnectUser(
            connection_datetime=datetime.strptime(educonnect_identity[_get_field_oid("6")][0], "%Y-%m-%d %H:%M:%S.%f"),
            birth_date=datetime.strptime(educonnect_identity[_get_field_oid("67")][0], "%Y-%m-%d").date(),
            educonnect_id=educonnect_identity[_get_field_oid("57")][0],
            first_name=educonnect_identity["givenName"][0],
            ine_hash=educonnect_identity[_get_field_oid("64")][0],
            last_name=educonnect_identity["sn"][0],
            logout_url=educonnect_identity[_get_field_oid("5")][0],
            saml_request_id=saml_request_id,
            student_level=educonnect_identity.get(_get_field_oid("73"), [None])[0],
        )
    except KeyError as exception:
        logger.error(
            "Key error raised when parsing educonnect saml response: %s",
            repr(exception),
            extra={"saml_request_id": saml_request_id},
        )
        raise exceptions.ParsingError()
    except Exception as exception:
        logger.error(
            "Error when parsing educonnect saml response: %s",
            repr(exception),
            extra={"saml_request_id": saml_request_id},
        )
        raise exceptions.ParsingError()

def _get_field_oid(oid_key: str) -> str:
    return f"urn:oid:1.3.6.1.4.1.20326.10.999.1.{oid_key}"

def build_saml_request_id_key(saml_request_id: str) -> str:
    return f"educonnect-saml-request-{saml_request_id}"


#!/usr/bin/python
# -*- coding: UTF-8 -*-
#
## Player module: main module

from properties import Properties
from song import Song
from threading import Timer
import sys
import xbmc
import xbmcgui

class XBMCPlayer(xbmc.Player):
    """
        Subclass of XBMC Player class.
        Overrides onplayback* events, for custom actions.
    """
    def __init__(self, *args, **kwargs):
        # initialize our super classes
        xbmc.Player.__init__(self)

    def onPlayBackStarted(self):
        # handle start event
        self.handle_onplayback_event("onPlayBackStarted")

    def onQueueNextItem(self):
        # handle queuing event, we just pass as started will handle song change
        # TODO: test to see if this is a better event than started
        self.handle_onplayback_event("onQueueNextItem")

    def onPlayBackStopped(self):
        # handle stopped event
        self.handle_onplayback_event("onPlayBackStopped")

    def onPlayBackEnded(self):
        # handle ended event
        self.handle_onplayback_event("onPlayBackEnded")

    def onPlayBackPaused(self):
        # handle paused event
        self.handle_onplayback_event("onPlayBackPaused")

    def onPlayBackResumed(self):
        # handle resumed event
        self.handle_onplayback_event("onPlayBackResumed")

    def onPlayBackSpeedChanged(self, speed):
        # handle FF/RW event
        self.handle_onplayback_event("onPlayBackSpeedChanged", speed)

    def onPlayBackSeek(self, _time, offset):
        # handle seek event
        self.handle_onplayback_event("onPlayBackSeek", (_time, offset,))

    def onPlayBackSeekChapter(self, chapter):
        # handle chapter seek event
        self.handle_onplayback_event("onPlayBackSeekChapter", chapter)

class Player(XBMCPlayer, Properties):
    # window for setting lyrics properties
    WINDOW = xbmcgui.Window(12006)
    # control id's
    CONTROL_LIST = 110
    CONTROL_SAVE_LYRICS = 606
    # FIXME: is 20 seconds a good time?
    PREFETCH_DELAY_TIME = 20

    def __init__(self, *args, **kwargs):
        # set addon object
        self.m_addon = kwargs["addon"]
        # passing "<windowId>" from RunScript() means run in background
        self.use_gui = kwargs["gui"]
        # initialize our super classes
        XBMCPlayer.__init__(self)
        Properties.__init__(self)
        # initialize timers
        self._lyric_timer = None
        self._fetch_timer = None
        # log started action
        self._log_addon_action("started")
        # initialize our Song class
        self.song = Song(addon=self.m_addon)
        # initialize our prefetched Song class
        # TODO: remove the self.isPlayingAudio() check when/if XBMC supports offset for player
        self.prefetched_song = None
        if (self.m_addon.getSetting("prefetch_lyrics") and self.isPlayingAudio()):
            self.prefetched_song = Song(addon=self.m_addon, prefetch=True)
        # start
        if (self.use_gui):
            self._start_gui()
        else:
            self._start_background()

    def _log_addon_action(self, action):
        # log addon info
        xbmc.log("{0:-<80}".format(""), xbmc.LOGNOTICE)
        xbmc.log(
            u"[ADD-ON] - {name!r} has {action}! [{mode}]".format(
            name=self.m_addon.getAddonInfo("Name"),
            action=action,
            mode=["BACKGROUND MODE (window={id})".format(
                id=sys.argv[-1]), "GUI MODE"][self.use_gui]),
            xbmc.LOGNOTICE
        )
        xbmc.log(
            u"{0: <12}Id: {id} - Type: {type} - Version: {version}".format(
            "",
            id=self.m_addon.getAddonInfo("Id"),
            type=self.m_addon.getAddonInfo("Type"),
            version=self.m_addon.getAddonInfo("Version")),
            xbmc.LOGNOTICE
        )
        xbmc.log("{0:-<80}".format(""), xbmc.LOGNOTICE)

    def _start_gui(self):
        # import GUI class
        from resources.lib.gui import GUI
        # set our GUI class
        self._gui = GUI(
            "custom_lyrics.xbmc_lyrics-gui.xml",
            self.m_addon.getAddonInfo("Path"), "default", "720p",
            player=self
        )
        # show dialog
        self._gui.doModal()
        # free memory
        del self._gui
        # cancel any running timers
        # FIXME: why is this necessary now. before subclass changes this was unnecessary
        self.cancel_timers()

    def _start_background(self):
        # set to True so script will continue
        self._loop = True
        # set window id
        self.window_id = int(sys.argv[1]) + 10000
        # get list control if skinner included one
        try:
            window = xbmcgui.Window(self.window_id)
            listcontrol = window.getControl(self.CONTROL_LIST)
        except Exception:
            listcontrol = None
        # start
        self.startup(listcontrol)
        # loop here to keep script running
        while not xbmc.abortRequested and self._loop:
            # 100 msecs seems like a good number FIXME: play with this
            xbmc.sleep(100)
        # FIXME: why is this necessary now. before subclass changes this was unnecessary
        self.cancel_timers()

    def startup(self, listcontrol=None):
        # set listcontrol object if one exists and user preference is to support scrolling lyrics
        self.listcontrol = [None, listcontrol][self.m_addon.getSetting("enable_karaoke_mode")]
        # start
        self.onPlayBackStarted()

    def handle_onplayback_event(self, event, *args):
        # cancel any timers, (we don't want to cancel timers on queue next item
        #                     XBMC queues next item during onQueueNextItem event
        #                     and cross fading would interrupt scrolling lyrics.)
        if (event != "onQueueNextItem"):
            self.cancel_timers()
        # log event
        xbmc.log(
            "XBMCPlayer::handle_onplayback_event (Event: {event: <35} Playing: {media})".format(
                event="{name} {args}".format(name=event, args=["", "args={0}".format(args)][args != ()]),
                media=["(none)", "Audio", "Video"][int(self.isPlayingAudio()) + (int(self.isPlayingVideo()) * 2)]),
            xbmc.LOGNOTICE
        )
        # on these event there is nothing to do
        if (event in ["onQueueNextItem", "onPlayBackPaused", "onPlayBackSeek", "onPlayBackSeekChapter"]):
            pass
        # on song change fetch lyrics
        elif (event == "onPlayBackStarted"):
            # log title and artist
            xbmc.log(
                u"{0: <36}(Title: {title!r: <36} Artist: {artist!r})".format(
                    "",
                    title=unicode(xbmc.getInfoLabel("MusicPlayer.Title"), "UTF-8"),
                    artist=unicode(xbmc.getInfoLabel("MusicPlayer.Artist"), "UTF-8")),
                xbmc.LOGNOTICE
            )
            # do we have any unsaved tagged lyrics
            if (self.use_gui):
                self._gui._save_user_tagged_lyrics(ask=True)
            # set new timer (we use this in case user is skipping thru playlist)
            self._fetch_timer = Timer(self.m_addon.getSetting("fetch_lyrics_delay") / 1000, self._fetch_lyrics)
            # start timer
            self._fetch_timer.start()
        # on resume from FF/RW we need to reset any timers
        elif (event == "onPlayBackResumed"):
            # update lyric if karaoke mode is enabled
            self._update_lyric()
        # on speedchanged?
        elif (event == "onPlayBackSpeedChanged"):
            # if speed==1 (resumed) we need to update lyrics
            if (args[0] == 1):
                self._update_lyric()
        # if music has ended we want to clear lyrics
        elif (event in ["onPlayBackStopped", "onPlayBackEnded"]):
            # give time for XBMC in case a glitch in a song fired the event
            # (only seems to happen with cross-fading enabled)
            # TODO: determine if this just needs to be hard coded
            xbmc.sleep(int(self.m_addon.getSetting("fetch_lyrics_delay")))
            # if we're still playing continue
            if (self.isPlaying()): return
            # finish up
            self.finish_up()

    def _set_properties(self, lyrics="", tags=list(), lrc_lyrics=False, message="", website="", status=True, prefetched=False):
        # set window properties
        self.set_properties(lyrics, tags, lrc_lyrics, message, website, status, prefetched)
        # only need to fill lyrics list control if lyrics exist, otherwise we just use textbox to display messages.
        if (self.song.m_song.lyrics is not None):
            # fill list if karaoke mode is enabled
            self._set_karaoke_lyrics()  #lyrics, tags)

    def _set_karaoke_lyrics(self):  #, lyrics, tags):
        # if no list control or not user preference skip
        if (self.listcontrol is None or
                not self.m_addon.getSetting("enable_karaoke_mode") or
                (not self.use_gui and not xbmc.getCondVisibility("Window.IsActive({id})".format(id=self.window_id)))):
            return
        # clear list
        self.listcontrol.reset()
        # add lyrics
        self.listcontrol.addItems(self.song.m_song.lyrics.splitlines())
        # select proper lyric
        self._update_lyric()

    def _update_lyric(self):
        # if no time tags, return
        if (not self.isPlaying() or not self.song.m_song.lyrics_tags or self.listcontrol is None or
                not self.m_addon.getSetting("enable_karaoke_mode") or
                (not self.use_gui and not xbmc.getCondVisibility("Window.IsActive({id})".format(id=self.window_id)))):
            return
        #FIXME: make sure this is necessary, I don't believe it is
        # cance only lyric timer
        self.cancel_timers(fetch=False)
        # get current time
        current = self.getTime()
        # get position
        pos = [count for count, tag in enumerate(self.song.m_song.lyrics_tags + [current + 1]) if (tag > current)][0]
        # select listitem
        self.listcontrol.selectItem(pos - 1)
        # return if no more lyrics
        if (pos == len(self.song.m_song.lyrics_tags)): return
        # calculate update time, additional time necessary to limit the number of repeat timer events
        update = self.song.m_song.lyrics_tags[pos] - current + 0.02
        # set new timer
        self._lyric_timer = Timer(update, self._update_lyric)
        # start timer
        self._lyric_timer.start()

    def cancel_timers(self, fetch=True):
        # if there's a timer cancel it
        if (self._lyric_timer is not None):
            self._lyric_timer.cancel()
        if (self._fetch_timer is not None and fetch):
            self._fetch_timer.cancel()

    def _fetch_lyrics(self):
        # set fetching lyrics message
        self._set_properties(
            message=self.m_addon.getLocalizedString(30800).format(
            title=unicode(xbmc.getInfoLabel("MusicPlayer.Title"), "UTF-8"))
        )
        # if prefetching failed, we go straight to song list
        songlist = self.prefetched_song is not None and not self.prefetched_song.m_song.status
        # fetch lyrics
        self.song.get_song_info(songlist=songlist)
        # set lyrics and messages
        self._set_properties(
            self.song.m_song.lyrics,
            self.song.m_song.lyrics_tags,
            self.song.m_song.lrc_lyrics,
            self.song.m_song.message,
            self.song.m_song.website,
            self.song.m_song.status,
            self.song.m_song.prefetched
        )
        # prefetch next song
        if (self.prefetched_song is not None and xbmc.getCondVisibility("MusicPlayer.HasNext")):
            # set new prefetch delay timer
            self._fetch_timer = Timer(
                self.PREFETCH_DELAY_TIME,
                self._prefetch_lyrics,
                (self.song.m_song.message, self.song.m_song.website, self.song.m_song.status, self.song.m_song.prefetched,)
            )
            # start timer
            self._fetch_timer.start()

    def _prefetch_lyrics(self, message, website, status, prefetched):
        # set prefetching message
        self.set_info_properties(
            message=self.m_addon.getLocalizedString(30805).format(
                title=unicode(xbmc.getInfoLabel("MusicPlayer.Offset(1).Title"), "UTF-8")),
            status=status,
            prefetching=True
        )
        # fetch next songs lyrics
        self.prefetched_song.get_song_info()
        # set previous properties
        self.set_info_properties(message, website, status, prefetched)

    def save_user_tagged_lyrics(self, lyrics):
        # set default saved lyrics message
        self.song.m_song.message = self.m_addon.getLocalizedString(30863)
        # set song's lyrics
        self.song.m_song.lyrics = lyrics
        # save lyrics
        self.song.save_lyrics()
        # set new message
        self._set_properties(lyrics=None, message=self.song.m_song.message)

    def finish_up(self):
        # cancel any timer
        self.cancel_timers()
        # close dialog
        if (self.use_gui):
            # close the GUI
            self._gui.close_dialog()
        else:
            # set to False so script will exit
            self._loop = False
            # close window
            xbmc.executebuiltin("Dialog.Close({id})".format(id=self.window_id))
        # clear existing properties
        self._set_properties()
        # log ended action
        self._log_addon_action("ended")


import os
import sys
import click

import pandas as pd

from plotnine import ggplot, aes, geom_point, labs, ggsave
from sklearn.decomposition import PCA
from mlhub.pkg import get_cmd_cwd

# Ensure paths are relative to the user's cwd

os.chdir(get_cmd_cwd())

@click.command()
@click.argument('csvfile',
                type=click.File('r'),
                default=sys.stdin)
@click.option("-l", "--label",
              default="label",
              help="identify the label column")
@click.option("-o", "--output",
              default="output not given",
              help="png/pdf to save output, will print if none given")
def cli(csvfile, label, output):
    # Quit if there is no data to read

    try:
        df = pd.read_csv(csvfile)
    except pd.errors.EmptyDataError:
        click.echo("No data available.")
        sys.exit(1)

    # Return error and quit if label column is not able to be found

    if label not in df.columns:
        click.echo("Column with label not identified")
        sys.exit(1)

    # Line of dots if data is one dimension

    if len(df.columns) == 2:
        # Find the non-label column

        header_1_col = list(df.columns.values)
        header_1_col.remove(label)
        p = (ggplot(df) +
             aes(x=header_1_col[0], y=label, color=f"factor({label})") +
             labs(color="Cluster") +
             geom_point())

    # Scatter plot if data is two dimensions

    elif len(df.columns) == 3:

        # Find the non-label columns

        header_2_col = list(df.columns.values)
        header_2_col.remove(label)
        p = (ggplot(df) +
             aes(x=header_2_col[0],
                 y=header_2_col[1],
                 color=f"factor({label})") +
             labs(color="Cluster") +
             geom_point())

    # Perform PCA if there are 2+ dimensions and visualise the 2 most
    # significant components

    else:
        pca = PCA(n_components=2)

        # Remove the label column for PCA

        df_for_pca = df.drop([label], axis=1)
        principal_components = pca.fit_transform(df_for_pca)
        principal_components
        principal_df = pd.DataFrame(data=principal_components,
                                    columns=['PC 1', 'PC 2'])
        principal_label_df = pd.concat([principal_df,
                                        df[[label]]],
                                       axis=1)
        p = (ggplot(principal_label_df) +
             aes(x="PC 1", y="PC 2", color=f"factor({label})") +
             labs(color="Cluster") +
             geom_point())

    if output == "output not given":
        print(p)
    else:
        if output[-3] == '.png':
            ggsave(plot=p, filename=output)
        if output[-3] == '.pdf':
            ggsave(plot=p, filename=output)
        else:
            ggsave(plot=p, filename=output + '.png')

if __name__ == "__main__":
    cli(prog_name="visualise")


import streamlit as st
import pandas as pd
import altair as alt
from collections import Counter

st.title("Let's analyze some Video Game Sales Data ðŸŽ®ðŸ“Š.")

data_file = "./vgsales.csv"

@st.cache  # add caching so we load the data only once
def load_data():
	# Load the penguin data
	df = pd.read_csv(data_file).dropna()

	trimmed_df = df.copy(deep=True)
	trimmed_df.loc[trimmed_df["Publisher"].value_counts()[trimmed_df["Publisher"]].values < 100, "Publisher"] = "Other Publisher"
	trimmed_df.loc[trimmed_df["Platform"].value_counts()[trimmed_df["Platform"]].values < 20, "Platform"] = "Other Platform"
	return df, trimmed_df

def show_dataset(df):
	st.write("## Dataset Description")
	show_dataset_description()
	st.write("**Dataset:**")
	st.write("shape: ",df.shape)
	if st.checkbox("Show Raw Data"):
		st.write(df)

def get_melt_year_df(df, columns):
	return df[columns+["Year"]].melt('Year').rename(columns = {'variable':'Region'})

def show_yearly_sale(df):

	st.write('## Yearly Sales Trend')
	st.write("**The dataset contains yearly sales data for various games in different regions. Let's explore the sales trend in different regions through some interactions!** ðŸ‘‡ðŸ�»")

	columns = ['NA_Sales', 'EU_Sales', 'JP_Sales', 'Other_Sales', 'Global_Sales']
	select_box = alt.binding_select(options=columns, name='Select a Region:')
	sel = alt.selection_single(fields=['Region Sale'], bind=select_box, init={'Region Sale': 'Global_Sales'})

	# line chart
	st.write("ðŸ’¡ *You can select specific region by clicking on the lines*")

	data = get_melt_year_df(df, columns)
	brush = alt.selection_single(encodings=['color'])

	st.write(alt.Chart(data).mark_line(opacity=0.75,thickness=10).encode(
    	x='Year:N',
    	y=alt.Y('value:Q', title='Sale (in millions)', aggregate='sum'),
    	color=alt.condition(brush, "Region:N", alt.value('lightgrey'), scale=alt.Scale(scheme='tableau20')),
	).add_selection(
		brush
	))

	# bar chart
	st.write("ðŸ’¡ *You can select specific region with the dropdown menu below*")

	st.write(alt.Chart(df).transform_fold(
		columns,
		as_=['Region Sale', 'Sale']
	).transform_filter(
		sel
	).mark_bar().encode(
			x=alt.X('Year:N'),
			y=alt.Y('Sale:Q', title='Sale (in millions)')
	).add_selection(
		sel
	).properties(
		height=500
	))

def show_game_trend_scatter(df):

	st.write('## Individual Game Sales')
	st.write("**Now let's zoom in to explore individual games.**")

	columns = ['Global_Sales', 'NA_Sales', 'EU_Sales', 'JP_Sales', 'Other_Sales']
	select_box = alt.binding_select(options=columns, name='Select a Region:')
	sel = alt.selection_single(fields=['Select a Region:'], bind=select_box, init={'Select a Region:': 'Global_Sales'})

	colors = ['Platform', 'Genre', 'Publisher']
	select_box2 = alt.binding_select(options=colors, name='Group By:')
	sel2 = alt.selection_single(fields=['Group By:'], bind=select_box2, init={'Group By:': 'Platform'})

	brush = alt.selection_single(encodings=['color'])

	st.write("ðŸ’¡ *You can click on individual games to see the group it belongs to*")

	st.write(alt.Chart(df).mark_point(opacity=0.75).transform_fold(
		columns,
		as_=['Select a Region:', 'Sale']
	).transform_fold(
		colors,
		as_=['Group By:', 'Group']
	).transform_filter(
		sel
	).transform_filter(
		sel2
	).add_selection(
		brush
	).encode(
			x= 'Year:N',
			y= alt.Y('Sale:Q', title='Sale (in millions)', aggregate='sum', scale=alt.Scale()),
			color=alt.condition(brush, "Group:N", alt.value('lightgrey'), scale=alt.Scale(scheme='tableau20')),
			tooltip=['Name', 'Platform', 'Genre', 'Publisher']
	).add_selection(
		sel
	).add_selection(
		sel2
	).properties(
		height=500
	).interactive())

@st.cache
def get_game_agg_df(df, regions, k):
	res = {}
	for region in regions:
		res[region] = df[["Name",region]].groupby(["Name"]).agg({region:"sum"}).sort_values(by=[region], ascending=False).iloc[:k,:].reset_index()
	return res

def show_game_region_bar(df):
	st.write('## Popular Games')

	st.write("**What are the popular games in each region and over the years?ðŸ§� Let's keep exploring!**")

	st.write("ðŸ’¡ *You can select specific year range with slider*")

	min_year, max_year = get_year_range(df)
	selected_year = st.slider("View Top 10 Game in Year Range:", min_year, max_year, (min_year, max_year), 1)

	df_selected = df[ (df["Year"] >= selected_year[0]) & (df["Year"] <= selected_year[1])]

	regions = ['Global_Sales', 'NA_Sales', 'EU_Sales', 'JP_Sales', 'Other_Sales']
	new_df = get_game_agg_df(df_selected, regions, 10)

	brush = alt.selection_single(encodings=['color'])

	titles = {'Global_Sales':'Global', 'NA_Sales':'North America',
				'EU_Sales':'Europe', 'JP_Sales': 'Japan', 'Other_Sales': 'Other Regions'}
	for region in regions:
		st.write("**%s**"%(titles[region]))
		st.write(alt.Chart(new_df[region]).mark_bar().encode(
			x=alt.X("Name:N", sort='-y'),
			y=alt.Y(region, title='Sale (in millions)'),
			color=alt.Color("Name:N", scale=alt.Scale(scheme='tableau20'))
		).properties(
			width=600,
			height=350
		))

@st.cache
def get_year_range(df):
	return int(df["Year"].min()), int(df["Year"].max())

def show_genre_region_bar(df):

	st.write('## Popular Genres')
	st.write("**What about genres? Let's compare!**")

	st.write("ðŸ’¡ *You can select specific year range with slider*")
	st.write("ðŸ’¡ *Try clicking on one or more genres to see how they perform in different regions*")
	st.write("ðŸ’¡ *You can also click on the individual points in the scatterplot to see other games in its genre*")
	st.write("âŒ› *Since it takes time to load the transformed data, the response may take a few seconds. Please be patient.*")

	brush = alt.selection_multi(encodings=['color'])

	min_year, max_year = get_year_range(df)
	selected_year = st.slider("View Popular Genre in Year Range", min_year, max_year, (min_year, max_year), 1)

	new_df = df[ (df["Year"] >= selected_year[0]) & (df["Year"] <= selected_year[1])]

	hist = (alt.Chart(new_df).mark_bar().encode(
		y=alt.Y(alt.repeat('row'), aggregate='sum', type='quantitative'),
	))

	color_scheme = alt.condition(brush, "Genre:N", alt.value('lightgrey'),scale=alt.Scale(scheme='tableau20'))

	top_chart = alt.layer(hist.encode(
		x=alt.X("Genre:N", sort='-y'),
		color=color_scheme
	)).properties(
		width=500,
		height=200
	).repeat(row=['Global_Sales', 'NA_Sales', 'EU_Sales', 'JP_Sales', 'Other_Sales'], data=new_df).add_selection(
		brush
	)

	bottom_chart = alt.Chart(new_df).mark_point().encode(
		x = alt.X(alt.repeat("column"), type ='quantitative', scale=alt.Scale(type='sqrt')),
		y = alt.Y(alt.repeat("row"), type='quantitative', scale=alt.Scale(type='sqrt')),
		color = color_scheme,
		tooltip = ['Name']
	).properties(
		width=150,
		height=150
	).repeat(
		row = ["NA_Sales", "EU_Sales", "JP_Sales", "Other_Sales"],
		column = ["NA_Sales", "EU_Sales", "JP_Sales", "Other_Sales"]
	).add_selection(
		brush
	)

	complete_chart = alt.vconcat(top_chart, bottom_chart)
	st.write(complete_chart)

@st.cache
def get_publisher_agg_df(df, regions, k):
	res = {}
	for region in regions:
		res[region] = df[["Publisher", "Name", region]].groupby(["Publisher"]).agg({region:"sum", "Name":"count"}).sort_values(by=[region], ascending=False).iloc[:k,:].reset_index()
	return res

def show_publisher_region_bar(df):
	st.write('## Popular Publishers')

	st.write("**It might also be interesting to compare different publishers.ðŸ¤”**")

	st.write("ðŸ’¡ *You can select specific year range with slider*")
	st.write("ðŸ’¡ *Hover over publishers to see the number of games they released during the time*")
	min_year, max_year = get_year_range(df)
	selected_year = st.slider("View Popular Publisher in Year Range:", min_year, max_year, (min_year, max_year), 1)

	df_selected = df[ (df["Year"] >= selected_year[0]) & (df["Year"] <= selected_year[1])]

	regions = ['Global_Sales', 'NA_Sales', 'EU_Sales', 'JP_Sales', 'Other_Sales']
	new_df = get_publisher_agg_df(df_selected, regions, 10)

	brush = alt.selection_single(encodings=['color'])

	titles = {'Global_Sales':'Global', 'NA_Sales':'North America',
				'EU_Sales':'Europe', 'JP_Sales': 'Japan', 'Other_Sales': 'Other Regions'}
	for region in regions:
		st.write("**%s**"%(titles[region]))
		st.write(alt.Chart(new_df[region]).mark_bar().encode(
			x=alt.X("Publisher:N", sort='-y'),
			y=alt.Y(region, title='Sale (in millions)'),
			color=alt.Color("Publisher:N", scale=alt.Scale(scheme='tableau20')),
			tooltip=[alt.Tooltip(field="Name", title="Total Released Games", type="quantitative")]
		).properties(
			width=600,
			height=350
		))

def show_genre_platform(df):
	st.write('## Popular Game Genres on each Platform')

	st.write("**Let's see how game trends evolve on each platform. Are gamers' preference changing over the decades?**")

	columns = list(df["Platform"].unique())
	select_box = alt.binding_select(options=columns, name='Select a Platform:')
	sel = alt.selection_single(fields=['Platform'], bind=select_box, init={'Platform': 'Wii'})

	# stacked bar chart
	st.write("ðŸ’¡ *You can select specific platform with the dropdown menu below*")
	st.write("ðŸ’¡ *Hover over the genres to see their popularities in different regions*")

	st.write(alt.Chart(df).transform_filter(
		sel
	).mark_bar().encode(
			x=alt.X('Year:N'),
			y=alt.Y('sum(Global_Sales):Q', title='Sale (in millions)'),
			color=alt.Color('Genre', scale=alt.Scale(scheme='tableau20')),
			order=alt.Order(
				'Genre',
				sort='ascending'
			),
			tooltip=['Genre', 'sum(NA_Sales)', 'sum(EU_Sales)', 'sum(JP_Sales)', 'sum(Other_Sales)']
	).add_selection(
		sel
	).properties(
		width=800,
		height=500
	))

def show_game_publisher(df):
	st.write('## Top 20 Best-selling Game for each Company/Publisher')

	st.write("**What are the most popular games by each company/publisher?**")

	columns = list(df["Publisher"].unique())
	select_box = alt.binding_select(options=columns, name='Select a Publisher:')
	sel = alt.selection_single(fields=['Publisher'], bind=select_box, init={'Publisher': 'Nintendo'})

	# stacked bar chart
	st.write("ðŸ’¡ *You can select specific publisher/company with the dropdown menu below*")
	st.write("ðŸ’¡ *Hover over the game titles to see their popularities in different regions*")

	st.write(alt.Chart(df).transform_filter(
		sel
	).mark_bar().encode(
			x=alt.X('Year:N'),
			y=alt.Y('sum(Global_Sales):Q', title='Sale (in millions)'),
			color=alt.Color('Name', scale=alt.Scale(scheme='tableau20')),
			order=alt.Order(
				'sum(Global_Sales)',
				sort='ascending'
			),
			tooltip=['Name', 'Genre', 'sum(NA_Sales)', 'sum(EU_Sales)', 'sum(JP_Sales)', 'sum(Other_Sales)']
	).transform_window(
		rank="rank(Global_Sales)",
		sort=[alt.SortField("Global_Sales", order="descending")]
	).transform_filter(
		(alt.datum.rank < 20)
	).add_selection(
		sel
	).properties(
		width=800,
		height=500
	))

@st.cache
def get_game_series(df):
	games = sorted(list(df["Name"].unique()))
	tokenized_games = [game.replace(":", "").split() for game in games]

	game_series = {}
	for idx in range(len(tokenized_games)):
		current = tokenized_games[idx]
		previous = tokenized_games[idx-1]
		game_series_cnt = 0
		for l in range(min(len(current), len(previous))):
			if current[l] == previous[l]:
				game_series_cnt += 1
		if game_series_cnt >= 1:
			game_series_name = " ".join(current[:game_series_cnt])
			if game_series_name not in game_series:
				game_series[game_series_name] = []
			game_series[game_series_name].append(" ".join(current))
			game_series[game_series_name].append(" ".join(previous))

	return game_series

@st.cache
def get_game_series_df(df, game_series):
	new_df = df.copy()
	game_serie_cnt = Counter()
	def series_name(row):
		for k in game_series:
			if row["Name"].replace(":", "") in game_series[k]:
				game_serie_cnt.update((k, 1))
				return k
	new_df["Series_Name"] = new_df.apply(lambda row: series_name(row), axis=1)
	game_serie = [game for game in game_serie_cnt if game_serie_cnt[game] > 1]
	return new_df, game_serie

def show_game_series(df):
	st.write('## Popular Game Series')

	st.write("**Let's explore some of the most popular game series**")

	game_series = get_game_series(df)
	game_series_df, columns = get_game_series_df(df, game_series)

	select_box = alt.binding_select(options=columns, name='Select a Game Series:')
	sel = alt.selection_single(fields=['Series_Name'], bind=select_box, init={'Series_Name': 'Pokemon'})

	# stacked bar chart

	st.write("ðŸ’¡ *You can select specific game serie with the dropdown menu below*")
	st.write("ðŸ’¡ *Hover over the game titles to see their popularities in different regions*")

	st.write(alt.Chart(game_series_df).transform_filter(
		sel
	).mark_bar().encode(
			x=alt.X('Year:N'),
			y=alt.Y('sum(Global_Sales):Q', title='Sale (in millions)'),
			color=alt.Color('Name', scale=alt.Scale(scheme='tableau20')),
			order=alt.Order(
				'Name',
				sort='ascending'
			),
			tooltip=['Name', 'Genre', 'sum(NA_Sales)', 'sum(EU_Sales)', 'sum(JP_Sales)', 'sum(Other_Sales)']
	).add_selection(
		sel
	).properties(
		width=800,
		height=500
	))

def show_dataset_description():
	st.write("This dataset contains a list of video games with sales greater than 100,000 copies. It was generated by a scrape of [vgchartz.com](vgchartz.com).");
	st.write("**Fields:**")

	lst = ["- Rank: Ranking of overall sales",
		"- Name: The games name",
		"- Platform: Platform of the games release (i.e. PC,PS4, etc.)",
		"- Year: Year of the game's release",
		"- Genre: Genre of the game",
		"- Publisher: Publisher of the game",
		"- NA_Sales: Sales in North America (in millions)",
		"- EU_Sales: Sales in Europe (in millions)",
		"- JP_Sales: Sales in Japan (in millions)",
		"- Other_Sales: Sales in the rest of the world (in millions)",
		"- Global_Sales: Total worldwide sales"]

	if st.checkbox("Show Field Description:"):
		for l in lst:
			st.write(l)

# Intro
st.write("# Video Game Sales Dataset")
st.write("Datset collected From [Kaggle](https://www.kaggle.com/snanilim/video-games-sales-analysis-and-visualization)")
df, trimmed_df = load_data()

# Data Set
show_dataset(df)

# General Trend Plots
show_yearly_sale(df)

# Region Plots
show_game_trend_scatter(trimmed_df)
show_game_region_bar(df)
show_genre_region_bar(df)
show_publisher_region_bar(df)

# Game Plots
show_genre_platform(df)
show_game_publisher(df)
show_game_series(df)


'''
https://adventofcode.com/2021/day/6
'''
DAY = 6

from utils import *
from collections import Counter, deque

def parser(test=False):
    input = Input(DAY, 2021, test=test, line_parser=integers)[0]
    return Counter(input)

def part1(input, N_days=80):
    fish_stages = deque([])
    for i in range(9):
        fish_stages.append(input[i])

    for _ in range(N_days):
        born = fish_stages.popleft()
        # Add the recent parents to stage 6
        fish_stages[6] += born
        # Add the newborns to stage 8
        fish_stages.append(born)

    return sum(fish_stages)

def part2(input):
    return part1(input, N_days=256)

def main():
    input = parser()
    print('RESULTS')

    result_1 = part1(input)
    print(f'Part 1: {result_1}')

    result_2 = part2(input)
    print(f'Part 2: {result_2}')

if __name__ == "__main__":
    test(DAY, parser, part1, [5934], part2, [26984457539])
    main()


import torch.nn as nn
import torch
from models.util import MyResNet34

class audio2poseLSTM(nn.Module):
    def __init__(self):
        super(audio2poseLSTM,self).__init__()

        self.em_pose = MyResNet34(256, 1)
        self.em_audio = MyResNet34(256, 1)
        self.lstm = nn.LSTM(512,256,num_layers=2,bias=True,batch_first=True)

        self.output = nn.Linear(256,6)

    def forward(self,x):
        pose_em = self.em_pose(x["img"])
        bs = pose_em.shape[0]
        zero_state = torch.zeros((2, bs, 256), requires_grad=True).to(pose_em.device)
        cur_state = (zero_state, zero_state)
        img_em = pose_em
        bs,seqlen,num,dims = x["audio"].shape

        audio = x["audio"].reshape(-1, 1, num, dims)
        audio_em = self.em_audio(audio).reshape(bs, seqlen, 256)

        result = [self.output(img_em).unsqueeze(1)]

        for i in range(seqlen):

            img_em,cur_state = self.lstm(torch.cat((audio_em[:,i:i+1],img_em.unsqueeze(1)),dim=2),cur_state)
            img_em = img_em.reshape(-1, 256)

            result.append(self.output(img_em).unsqueeze(1))
        res = torch.cat(result,dim=1)
        return res


from datetime import datetime

import base64
import MySQLdb
import MySQLdb.cursors
import logging
import eventlet
import hashlib
import requests

import xml.etree.ElementTree as ET

logging.basicConfig(level=logging.INFO)
logging.getLogger('suds.client').setLevel(logging.DEBUG)

class MySQL():

    def execute_query(self, db_connection, sql, params):
        """ Insert data into the database
        Keyword arguments:
            db_connection -- The connection to the database.
            sql -- The sql to be executed.
            params -- A parameter list holding values to be used in the sql.
        """
        try:
            cursor = db_connection.cursor()
            cursor.execute(sql, params)
        except MySQLdb.DatabaseError:
            raise
        except TypeError:
            raise

    def retrieve_all_data_params(self, db_connection, sql, params):
        """ Retrieve Data from the database

            Retrieve data from the database, returns a dictionary that
            holds the results.

            Keyword arguments:
            db_connection -- The connection to the database.
            sql -- The sql to be executed.
            params -- A parameter list holding values to be used in the sql.

        """
        results = None
        try:
            cursor = db_connection.cursor()
            cursor.execute(sql, params)
            results = cursor.fetchall()
        except MySQLdb.DatabaseError:
            raise
        return results

    def retrieve_all_data(self, db_connection, sql):
        """ Retrieve Data from the database

            Retrieve data from the database, returns a dictionary that
            holds the results.

            Keyword arguments:
            db_connection -- The connection to the database.
            sql -- The sql to be executed.
        """
        results = None
        try:
            cursor = db_connection.cursor()
            cursor.execute(sql)
            results = cursor.fetchall()
        except MySQLdb.DatabaseError:
            raise
        return results


"""
QML task on noisy PQC with vmapped Monte Carlo noise simulation
"""

import os

os.environ["TF_FORCE_GPU_ALLOW_GROWTH"] = "true"
# one need this for jax+gpu combination in some cases
import time
import tensorflow as tf
import numpy as np
import optax
import tensorcircuit as tc

K = tc.set_backend("jax")

# numpy data
(x_train, y_train), (x_test, y_test) = tf.keras.datasets.mnist.load_data()
x_train = x_train[..., np.newaxis] / 255.0

def filter_pair(x, y, a, b):
    keep = (y == a) | (y == b)
    x, y = x[keep], y[keep]
    y = y == a
    return x, y

datapoints = 200
batch = 32
logfile = "qml_param_v2.npy"
n = 9
m = 4
maxiter = 5000
data_preparation = "v1"

x_train, y_train = filter_pair(x_train, y_train, 0, 1)

if data_preparation == "v1":
    x_train = tf.image.resize(x_train, (int(np.sqrt(n)), int(np.sqrt(n)))).numpy()
    x_train = np.array(x_train > 0.5, dtype=np.float32)
    x_train = np.squeeze(x_train).reshape([-1, n])

else:  # "v2"
    from sklearn.decomposition import PCA

    x_train = PCA(n).fit_transform(x_train.reshape([-1, 28 * 28]))

mnist_data = (
    tf.data.Dataset.from_tensor_slices((x_train[:datapoints], y_train[:datapoints]))
    .repeat(maxiter)
    .shuffle(datapoints)
    .batch(batch)
)

def f(param, seed, x, pn):
    c = tc.Circuit(n)
    px, py, pz = pn, pn, pn
    for i in range(n):
        if data_preparation == "v1":
            c.rx(i, theta=x[i] * np.pi / 2)
        else:
            c.rx(i, theta=K.atan(x[i]))
    for j in range(m):
        for i in range(n - 1):
            c.cx(i, i + 1)
            c.depolarizing(i, px=px, py=py, pz=pz, status=seed[j, i, 0])
            c.depolarizing(i + 1, px=px, py=py, pz=pz, status=seed[j, i, 1])
        for i in range(n):
            c.rz(i, theta=param[j, i, 0])
        for i in range(n):
            c.rx(i, theta=param[j, i, 1])

    ypreds = K.convert_to_tensor([K.real(c.expectation_ps(z=[i])) for i in range(n)])

    return K.mean(ypreds)

vf = tc.utils.append(K.vmap(f, vectorized_argnums=1), K.mean)

def loss(param, scale, seeds, x, y, pn):
    ypred = vf(param, seeds, x, pn)
    ypred = K.sigmoid(scale * ypred)
    y = K.cast(y, "float32")
    return (
        K.real(-y * K.log(ypred) - (1 - y) * K.log(1 - ypred)),
        ypred,
    )

def acc(yps, ys):
    yps = K.numpy(yps)
    ys = K.numpy(ys)
    yps = (np.sign(yps - 0.5) + 1) / 2
    return 1 - np.mean(np.logical_xor(ys, yps))

vgloss = K.jit(K.vvag(loss, argnums=(0, 1), vectorized_argnums=(3, 4), has_aux=True))
vloss = K.jit(K.vmap(loss, vectorized_argnums=(3, 4)))

def train(param=None, scale=None, noise=0, noc=1, fixed=True, val_step=40):
    times = []
    val_times = []
    if param is None:
        param = K.implicit_randn([m, n, 2])
    if scale is None:
        scale = 15.0 * K.ones([], dtype="float32")
    else:
        scale *= K.ones([], dtype="float32")
    if K.name == "jax":
        opt = K.optimizer(optax.adam(1e-2))
        opt2 = K.optimizer(optax.adam(5e-2))
    else:
        opt = K.optimizer(tf.keras.optimizers.Adam(1e-2))
        opt2 = K.optimizer(tf.keras.optimizers.Adam(5e-2))
    pn = noise * K.ones([], dtype="float32")

    try:
        for i, (xs, ys) in zip(range(maxiter), mnist_data):  # using tf data loader here
            xs, ys = tc.array_to_tensor(xs.numpy(), ys.numpy())
            seeds = K.implicit_randu([noc, m, n, 2])
            time0 = time.time()
            _, grads = vgloss(param, scale, seeds, xs, ys, pn)
            time1 = time.time()
            times.append(time1 - time0)
            param = opt.update(grads[0], param)
            if fixed is False:
                scale = opt2.update(grads[1], scale)
            if i % val_step == 0:
                print("%s round" % str(i))
                print("scale: ", K.numpy(scale))
                time0 = time.time()
                inference(param)
                time1 = time.time()
                val_times.append(time1 - time0)
                if len(times) > 1:
                    print("batch running time est.: ", np.mean(times[1:]))
                    print("batch staging time est.: ", times[0])
                if len(val_times) > 1:
                    print("full set running time est.: ", np.mean(val_times[1:]))
                    print("full set staging time est.: ", val_times[0])
    except KeyboardInterrupt:
        pass

    np.save(logfile, K.numpy(param))
    return param

def inference(param=None, scale=None, noise=0, noc=1, debug=False):
    pn = noise * K.ones([], dtype="float32")
    if param is None:
        param = np.load(logfile)
    if scale is None:
        scale = 15.0 * K.ones([], dtype="float32")
    else:
        scale *= K.ones([], dtype="float32")
    seeds = K.implicit_randu([noc, m, n, 2])
    vs, yps = vloss(
        param,
        scale,
        seeds,
        tc.array_to_tensor(x_train[:datapoints]),
        tc.array_to_tensor(y_train[:datapoints]),
        pn,
    )
    if debug:
        print(yps)
    print("loss: ", K.mean(vs))
    print("acc on training: %.4f" % acc(yps, y_train[:datapoints]))

if __name__ == "__main__":
    train(noise=0.005, scale=30, noc=100, fixed=False)
    # inference(noise=0.01, noc=1000, scale=40, debug=True)


from functools import wraps

from flask import session, Blueprint, url_for, request, redirect, flash, render_template

from ..extensions import oauth

github = oauth.remote_app(
    'github',
    base_url='https://api.github.com',
    request_token_url=None,
    access_token_method='POST',
    authorize_url='https://github.com/login/oauth/authorize',
    access_token_url='https://github.com/login/oauth/access_token',
    app_key='GITHUB',
    request_token_params={'scope': 'user:email,repo,user:follow'}
)

@github.tokengetter
def get_github_token(token=None):
    return session.get('github_token')

def require_login(view):
    @wraps(view)
    def decorated_view(*args, **kwargs):
        if 'github_token' in session:
            return view(*args, **kwargs)
        else:
            return redirect(url_for("users.login"))

    return decorated_view

users = Blueprint("users", __name__)

@users.route("/login")
def login():
    return render_template("login.html")

@users.route("/logout")
def logout():
    session.pop('github_token', None)
    return redirect(url_for("starry.index"))

@users.route("/github/login")
def github_login():
    session.pop('github_token', None)
    return github.authorize(callback=url_for('.github_authorized',
                                             _external=True,
                                             next=request.args.get('next') or url_for("starry.index")))

@users.route('/github/authorized', methods=["GET", "POST"])
def github_authorized():
    next_url = request.args.get('next') or url_for('starry.index')
    resp = github.authorized_response()
    if resp is None:
        flash('You denied the request to sign in.')
        return redirect(next_url)

    session['github_token'] = (resp['access_token'],)
    me = github.get('/user')
    session['github_name'] = me.data['name']

    flash('You were signed in as %s' % repr(me.data['name']))
    return redirect(next_url)


from datetime import datetime

import numpy as np
import scipy as sp
from scipy import io
import netCDF4 as nc

import pyroms
import pyroms_toolbox

# ----------------- functionals ---------------------------------------------
def get_z(h, hc, N, s_rho, Cs_r, zeta, Vtrans, zice):

    hwater = h - np.abs(zice)
    z_r = np.empty((N,) + h.shape, 'd')
    if Vtrans == 1:
        for k in range(N):
            z0 = hc * s_rho[k] + (hwater - hc) * Cs_r[k]
            z_r[k, :] = z0 + zeta * (1.0 + z0 / hwater)
            z_r[k, :] = z_r[k, :] - np.abs(zice)
    elif Vtrans == 2 or Vtrans == 4 or Vtrans == 5:
        for  k in range(N):
            z0 = (hc * s_rho[k] + hwater * Cs_r[k]) / (hc + hwater)
            z_r[k, :] = zeta + (zeta + hwater) * z0
            z_r[k, :] = z_r[k, :] - np.abs(zice)
    return z_r

# ------------ read grid -----------------------------------------------
grd = pyroms.grid.get_ROMS_grid('fjord_test')
msk = grd.hgrid.mask
zr = grd.vgrid.z_r[:]
N, eta, xi = zr.shape

fh = nc.Dataset('./fjord_grd_test.nc')
zice = fh.variables['zice'][:]
fh.close()

zr = get_z(grd.vgrid.h,
           grd.vgrid.hc, grd.vgrid.N, grd.vgrid.s_rho, grd.vgrid.Cs_r,
           np.zeros(zice.shape), grd.vgrid.Vtrans,
           zice)

# ------------ generate ic file ----------------------------------------
ic_file = './fjord_ic_test.nc'
class ocean_time_info(object):
    pass
ocean_time = ocean_time_info()
ocean_time.long_name = 'seconds since 00-00-00'
ocean_time.units = 'second'

pyroms_toolbox.nc_create_roms_file(ic_file, grd, ocean_time, geogrid=False)

# ------------ write ic values -----------------------------------------
z_pyc = 10.
zeta = 0.
ubar = 0.
vbar = 0.
u = 0.
v = 0.
temp = np.zeros((1, grd.vgrid.N) + grd.vgrid.h.shape)
salt = np.zeros((1, grd.vgrid.N) + grd.vgrid.h.shape)
temp[0, :] = 4. + 2.*(np.tanh(0.025*np.pi*(zr+z_pyc))+1)
salt[0, :] = 30. - 10.*(np.tanh(0.025*np.pi*(zr+z_pyc))+1)
dye_01 = 0.
spval = -1.0e20

# zeta = 0
# ubar = 0
# vbar = 0
# u = 0
# v = 0
# dye_01 = 0
#
# data = io.loadmat('../data/carroll_2017_JGR_oceans_initialTS.mat')
# depth_raw = np.array(data['depth']).squeeze()
# temp_raw = np.array(data['temperature']).squeeze()
# salt_raw = np.array(data['salinity']).squeeze()
# depth_raw = depth_raw[::-1]
# temp_raw = temp_raw[::-1]
# salt_raw = salt_raw[::-1]
#
# temp = np.zeros((1, N, eta, xi))
# salt = np.zeros((1, N, eta, xi))
# for ieta in range(eta):
#     for ixi in range(xi):
#         temp[0, :, ieta, ixi] = np.interp(zr[:, ieta, ixi], depth_raw, temp_raw)
#         salt[0, :, ieta, ixi] = np.interp(zr[:, ieta, ixi], depth_raw, salt_raw)
#
# spval = -1.0e20
# ------------ write to ic file ----------------------------------------
fh = nc.Dataset(ic_file, 'r+')

fh.variables['ocean_time'][:] = 0

fh.createVariable('zeta', 'f8', ('ocean_time', 's_rho', 'eta_rho', 'xi_rho'), fill_value=spval)
fh.variables['zeta'].long_name = 'free-surface'
fh.variables['zeta'].units = 'meter'
fh.variables['zeta'].field = 'free-surface, scalar, series'
fh.variables['zeta'][:] = zeta

fh.createVariable('temp', 'f8', ('ocean_time', 's_rho', 'eta_rho', 'xi_rho'), fill_value=spval)
fh.variables['temp'].long_name = 'potential temperature'
fh.variables['temp'].units = 'Celsius'
fh.variables['temp'].field = 'temperature, scalar, series'
fh.variables['temp'][:] = temp

fh.createVariable('salt', 'f8', ('ocean_time', 's_rho', 'eta_rho', 'xi_rho'), fill_value=spval)
fh.variables['salt'].long_name = 'salinity'
fh.variables['salt'].units = 'PSU'
fh.variables['salt'].field = 'salinity, scalar, series'
fh.variables['salt'][:] = salt

fh.createVariable('dye_01', 'f8', ('ocean_time', 's_rho', 'eta_rho', 'xi_rho'), fill_value=spval)
fh.variables['dye_01'].long_name = 'river dye concentration'
fh.variables['dye_01'].units = ' '
fh.variables['dye_01'].field = 'dye_01, scalar, series'
fh.variables['dye_01'][:] = dye_01

fh.createVariable('u', 'f8', ('ocean_time', 's_rho', 'eta_u', 'xi_u'), fill_value=spval)
fh.variables['u'].long_name = '3D u-momentum component'
fh.variables['u'].units = 'meter second-1'
fh.variables['u'].field = 'u-velocity, scalar, series'
fh.variables['u'][:] = u

fh.createVariable('v', 'f8', ('ocean_time', 's_rho', 'eta_v', 'xi_v'), fill_value=spval)
fh.variables['v'].long_name = '3D v-momentum component'
fh.variables['v'].units = 'meter second-1'
fh.variables['v'].field = 'v-velocity, scalar, series'
fh.variables['v'][:] = v

fh.createVariable('ubar', 'f8', ('ocean_time', 'eta_u', 'xi_u'), fill_value=spval)
fh.variables['ubar'].long_name = '2D u-momentum component'
fh.variables['ubar'].units = 'meter second-1'
fh.variables['ubar'].field = 'ubar-velocity, scalar, series'
fh.variables['ubar'][:] = ubar

fh.createVariable('vbar', 'f8', ('ocean_time', 'eta_v', 'xi_v'), fill_value=spval)
fh.variables['vbar'].long_name = '2D v-momentum component'
fh.variables['vbar'].units = 'meter second-1'
fh.variables['vbar'].field = 'vbar-velocity, scalar, series'
fh.variables['vbar'][:] = vbar

fh.close()