#!/usr/bin/env python3

from sys import argv, stdout
from threading import Thread

from matplotlib.pyplot import table
import GameData
import socket
from constants import *
import os
import time
from knowledge import Knowledge
import numpy as np

if len(argv) < 5:
    print("You need the player name to start the game.")
    print("You need to specify if you want out results in a file (True/False).")
    #exit(-1)
    playerName = "Test" # For debug
    ip = HOST
    port = PORT
    results = True
    num_games_limit = 2
    training = False
else:
    playerName = argv[3]
    ip = argv[1]
    port = int(argv[2])
    results = argv[4] == "True"
    num_games_limit = int(argv[5])
    training = argv[6] == "True"

run = True

debug = False # allow to see step by step the game by the agents, stopping at the end of each turn. Press any key to continue

verbose = False # add some more information printed on the console

loaded = True # allow to use as starting point a Q-Table already filled

q_learn = True # activate the Q-Learning procedure

statuses = ["Lobby", "Game", "GameHint"]

status = statuses[0]

card_colors = ['red', 'green', 'blue', 'yellow', 'white']

hintState = ("", "")

num_games = 0
average_score = 0.0

update = True
sleeptime = 0.1
before_action = True

last_hard = 0 #counts how many times we end to use the "Rule-based last resource"
last_q = 0 #counts how many times we end to use the "Q-Learning last resource"

my_knowledge = Knowledge(playerName) # all agent knowledge is here

def set_knowledge(data):
    global my_knowledge
    if my_knowledge.init is False: #init Info
        if hasattr(my_knowledge, 'agent'):
            agent = my_knowledge.agent
            my_knowledge = Knowledge(playerName,data,loaded_learn_qTable=loaded,training=training)
            my_knowledge.agent = agent # continue to use the same agent
        else:
            my_knowledge = Knowledge(playerName,data,loaded_learn_qTable=loaded,training=training) #very first init
        if verbose:
            print("Q-Table:")
            print(my_knowledge.agent.q_table)
    else:
        my_knowledge.updateKnowledge(data)
    time.sleep(sleeptime)
    if data.currentPlayer == playerName and update:
            my_knowledge.my_turn = True
            if verbose:
                print(my_knowledge.toString())

def discard_update(data):
    global my_knowledge
    my_knowledge.num_deck_cards -= 1
    my_knowledge.blue_tokens += 1
    if (my_knowledge.num_players < 4 and data.handLength < 5) or (my_knowledge.num_players >= 4 and data.handLength < 4):
        my_knowledge.last_round = True
    if data.lastPlayer == my_knowledge.my_name:
        if my_knowledge.my_cards[data.cardHandIndex][0] != None or my_knowledge.my_cards[data.cardHandIndex][1] != None: #if I had clues on that card
            my_knowledge.my_cards_clued -= 1
        my_knowledge.my_cards.pop(data.cardHandIndex)
        my_knowledge.my_cards.append((None, None, 0))

    # Q-Learning
    if my_knowledge.table_cards[data.card.color] >= data.card.value: #reward
            reward = 8 # discarding this card was useful
    elif data.card.value == 1 and my_knowledge.discard_pile[data.card.color][data.card.value]+1 == 3:
        reward = -7 # this was last '1' card
    elif data.card.value in [2,3,4] and my_knowledge.discard_pile[data.card.color][data.card.value]+1 == 2:
        reward = -6 # this was last '2' card
    elif data.card.value==5 and my_knowledge.discard_pile[data.card.color][data.card.value]+1 == 1:
        reward = -5 # this was last '3' card
    else:
        reward = 9 - my_knowledge.blue_tokens # we have discarded but we could hint

    next_state = my_knowledge.next_state()
    if next_state not in my_knowledge.agent.q_table:
        my_knowledge.agent.q_table[next_state] = np.zeros(len(my_knowledge.actions),dtype=float) # add new state
    ## Update the Q-Table
    my_knowledge.agent.update_q_table(my_knowledge.state,'discard',next_state,reward,False)
    my_knowledge.state = next_state

def niceMove_update(data):
    global my_knowledge
    my_knowledge.num_deck_cards -= 1
    if (my_knowledge.num_players < 4 and data.handLength < 5) or (my_knowledge.num_players >= 4 and data.handLength < 4):
        my_knowledge.last_round = True
    if data.lastPlayer == my_knowledge.my_name:
        if my_knowledge.my_cards[data.cardHandIndex][0] != None or my_knowledge.my_cards[data.cardHandIndex][1] != None: #if I had clues on that card
            my_knowledge.my_cards_clued -= 1
        my_knowledge.my_cards.pop(data.cardHandIndex)
        my_knowledge.my_cards.append((None, None, 0))

    # Q-Learning
    reward = 10. #reward
    next_state = my_knowledge.next_state()
    if next_state not in my_knowledge.agent.q_table:
        my_knowledge.agent.q_table[next_state] = np.zeros(len(my_knowledge.actions),dtype=float) # add new state
    ## Update the Q-Table
    my_knowledge.agent.update_q_table(my_knowledge.state,'play',next_state,reward,False)
    my_knowledge.state = next_state

def badMove_update(data):
    global my_knowledge
    my_knowledge.num_deck_cards -= 1
    my_knowledge.red_tokens -= 1
    if (my_knowledge.num_players < 4 and data.handLength < 5) or (my_knowledge.num_players >= 4 and data.handLength < 4):
        my_knowledge.last_round = True
    if data.lastPlayer == my_knowledge.my_name: #my fault
        if my_knowledge.my_cards[data.cardHandIndex][0] != None or my_knowledge.my_cards[data.cardHandIndex][1] != None: #if I had clues on that card
            my_knowledge.my_cards_clued -= 1
        my_knowledge.my_cards.pop(data.cardHandIndex)
        my_knowledge.my_cards.append((None, None, 0))

    # Q-Learning
    reward = -20. #reward
    next_state = my_knowledge.next_state()
    if next_state not in my_knowledge.agent.q_table:
        my_knowledge.agent.q_table[next_state] = np.zeros(len(my_knowledge.actions),dtype=float) # add new state
    ## Update the Q-Table
    my_knowledge.agent.update_q_table(my_knowledge.state,'play',next_state,reward,False)
    my_knowledge.state = next_state

def set_new_hint(hint):
    global my_knowledge

    my_knowledge.blue_tokens -= 1
    if hint.destination == my_knowledge.my_name:
        for i in hint.positions:
            if hint.type == 'value':
                if my_knowledge.my_cards[i][0] == None and my_knowledge.my_cards[i][1] == None:
                    my_knowledge.my_cards_clued += 1
                my_knowledge.my_cards[i] = (hint.value, my_knowledge.my_cards[i][1],1)
            else:
                if my_knowledge.my_cards[i][0] == None and my_knowledge.my_cards[i][1] == None:
                    my_knowledge.my_cards_clued += 1
                my_knowledge.my_cards[i] = (my_knowledge.my_cards[i][0], hint.value,1)

    # Q-Learning
    reward = my_knowledge.blue_tokens - my_knowledge.num_players #reward: it's better have more blue tokens if possible
    next_state = my_knowledge.next_state()
    if next_state not in my_knowledge.agent.q_table:
        my_knowledge.agent.q_table[next_state] = np.zeros(len(my_knowledge.actions),dtype=float) # add new state
    ## Update the Q-Table
    my_knowledge.agent.update_q_table(my_knowledge.state,'hint',next_state,reward,False)
    my_knowledge.state = next_state

def game_over(score):
    global my_knowledge
    global run
    global num_games
    global average_score
    global num_games_limit
    global update
    global before_action
    global results
    print(f"\nGame n.{num_games}: score {score}.")
    print(f"{max(my_knowledge.num_deck_cards, 0)} still in the deck.")
    print(f"Final table cards: {my_knowledge.table_cards}.")

    # Q-Learning
    # Computing reward
    if score == 0:
        reward = -50 # penalize lost games
    else:
        reward = score
    # Updating Q-Table
    next_state = (0, 0, 0, 0, 0) # reset state
    my_knowledge.agent.update_q_table(my_knowledge.state,'play',next_state,reward,is_terminal=True) #terminal action - any action is valid
    my_knowledge.state = next_state

    if results:
        if num_games == 0:
            mode = "w"
        else:
            mode = "a"
        if q_learn:
            filename = f"results_{my_knowledge.num_players}_qLearn.txt"
        else:
            filename = f"results_{my_knowledge.num_players}.txt"
        with open(filename, mode) as file_out:
            file_out.write(f"Game n.{num_games}: {score} \n")

    num_games += 1
    average_score = (average_score * (num_games-1)+score)/num_games
    print(f"Games played so far: {num_games}. Actual average score: {average_score}")

    if num_games_limit != None:
        if num_games >= num_games_limit:
            run = False
            print("Log out")
            if results:
                with open(filename, "a") as file_out:
                    file_out.write(f"----------------------------\n")
                    file_out.write(f"Avarage score: {average_score}\n")
            my_knowledge.agent.save_learned_model(f"learned_qTable_{my_knowledge.num_players}.npy")
            if verbose:
                print(f"Last hard used:{last_hard}\nLast Q-Learn used:{last_q}")
            os._exit(0)
        else:
            print("Beginning a new game...")
            update = True
            before_action = True
            agent = my_knowledge.agent
            my_knowledge = Knowledge(playerName) #reset info
            my_knowledge.agent = agent # continue to use the same agent

def is_hint_safe(hint):
    cards = my_knowledge.players[hint[1]]['cards'] #cards of the player "hinted"
    if hint[2] == 'value':
        for i in range(hint[4]+1,len(cards)): # for all cards before the hinted one
            if cards[i].value == hint[3]: # if the card hinted has the same value of a card before it
                return False
    else:
        for i in range(hint[4]+1,len(cards)):
            if cards[i].color == hint[3]:
                return False
    return True

def is_hint_not_misunderstandable(hint,real_color):
    #if there is already a card on the table that is the card before the hinted one, it's misunderstandable!
    if hint[2] == 'value' and hint[3]!=1:
        for color in card_colors:
            if color != real_color:
                if my_knowledge.table_cards[color]+1 == hint[3]:
                    return False
    return True

def compare_hints(value_hint, color_hint): #count how many cards are touched giving value hint or color hint
        cards = my_knowledge.players[value_hint[1]]['cards']
        touched_from_valueHint = 0
        touched_from_colorHint = 0
        for card in cards:
            if card.value == value_hint[3]:
                touched_from_valueHint += 1
            if card.color == color_hint[3]:
                touched_from_colorHint += 1
        if touched_from_valueHint<=touched_from_colorHint:
            return 0 #return 0 if we touch less cards with value hint
        return 1 #return 1 if we touch less cards with value hint

def useful_for_later(value_hint):
    for color in card_colors:
        if my_knowledge.table_cards[color] < value_hint:
            return True
    return False

def last_remaining(card):
            if card.value == 5:
                return True
            if card.value == 4 and my_knowledge.discard_pile[card.color][card.value] == 1:
                return True
            if card.value == 3 and my_knowledge.discard_pile[card.color][card.value] == 1:
                return True
            if card.value == 2 and my_knowledge.discard_pile[card.color][card.value] == 1:
                return True
            if card.value == 1 and my_knowledge.discard_pile[card.color][card.value] == 2:
                return True
            return False

def select_action():
        global last_hard
        global last_q
        # HARD-CODED AGENT

        ## Last round (play the newest card if we have more than one storm tokens available)
        if my_knowledge.last_round:
            if my_knowledge.red_tokens > 1 and my_knowledge.num_deck_cards > 0:
                return ('play', my_knowledge.handSize -1 )

        # Play rules with hints
        for i, card in reversed(list(enumerate(my_knowledge.my_cards))): # look from the newest card (= the most right)
            value_hint = card[0]
            color_hint = card[1]
            age_hint = card[2]
            # prioritize "completely known" cards (both color and value)
            if  value_hint != None and color_hint != None: #if I have two hints on that card
                # play
                if my_knowledge.table_cards[color_hint]+1 == value_hint:
                    return ('play', i)
            # Prioritize value hints over color hints
            if value_hint != None and color_hint == None: # CONVENTION: Value Hint --> Keep for later
                ## Check if there exists a firework that actually fits this hint and then play; otherwise try to discard it.
                for color in card_colors:
                    if my_knowledge.table_cards[color]+1 == value_hint and age_hint == 1:
                        return ('play', i)
            if color_hint != None and value_hint == None: # CONVENTION: Color Hint --> Play it immediately
                ## Check if there exists a firework that actually misses cards and if the hint is new
                if my_knowledge.table_cards[color_hint] != 5:
                    if age_hint == 1:
                        return ('play', i)

        # Hint rules
        if my_knowledge.blue_tokens > 0:
            next_player_idx = (my_knowledge.my_turn_idx + 1) % my_knowledge.num_players
            for _ in range(my_knowledge.num_players-1): #for all the other players
                player_name = my_knowledge.idx_player[next_player_idx]
                player_cards = my_knowledge.players[player_name]['cards']
                for i, card in reversed(list(enumerate(player_cards))): #for all player's cards
                    if my_knowledge.table_cards[card.color]+1 == card.value: # player has the next card for that color
                        hint_value = (my_knowledge.my_name, player_name, 'value', card.value, i)
                        hint_color = (my_knowledge.my_name, player_name, 'color', card.color, i)
                        # Give a hint that touches fewer cards
                        if compare_hints(hint_value, hint_color) == 0 or hint_value == 1: # hint on value touches less cards
                            if is_hint_safe(hint_value): # To avoid misplays, we only give hints that do not touch dangerous cards before the hinted one
                            #if is_hint_not_misunderstandable(hint_value,card.color):
                                return ('hint', player_name, hint_value[3])
                            elif is_hint_safe(hint_color):
                                return ('hint', player_name, hint_color[3])
                        else: # hint on color touches less cards
                            if is_hint_safe(hint_color): # To avoid misplays, we only give hints that do not touch dangerous cards before the hinted one
                                return ('hint', player_name, hint_color[3])
                # Hint dangerous cases
                for i, card in enumerate(player_cards): #for all player's cards
                    if last_remaining(card):
                        if card not in my_knowledge.my_last_remaining_hints:
                            my_knowledge.my_last_remaining_hints.append(card)
                            hint_value = (my_knowledge.my_name, player_name, 'value', card.value, i)
                            if is_hint_not_misunderstandable(hint_value,card.color):
                                return ('hint', player_name, hint_value[3])
                next_player_idx = (next_player_idx + 1) % my_knowledge.num_players

        ## Discard your oldest unclued card (oldest --> most left)
        if my_knowledge.blue_tokens < 8:
             for i, card in enumerate(my_knowledge.my_cards): #from my oldest card ( = the first in the list)
                value_hint = card[0]
                color_hint = card[1]
                age_hint = card[2]
                if value_hint == None and color_hint == None: #if it's totally unclued
                    return ('discard', i)
                if value_hint != None and color_hint == None:
                    if not useful_for_later(value_hint):
                        return ('discard', i)
                if color_hint != None and value_hint == None:
                    if my_knowledge.table_cards[color_hint] == 5:
                        return ('discard', i)
                if  value_hint != None and color_hint != None: #if I have two hints on that card
                    if my_knowledge.table_cards[color_hint]+1 > value_hint:
                        return ('discard', i)

        if q_learn:
            # Q-Learning
            print("Q-Learning action")
            last_q = last_q + 1
            action = my_knowledge.agent.pick_action(my_knowledge.state)
            if action == "hint" and my_knowledge.blue_tokens == 0: # you cannot pick this action
                action = "discard"
            if action == "discard" and my_knowledge.blue_tokens == 8: # you cannot pick this action
                action = "hint"

            if action == "discard":
                # discard action
                for idx, card in enumerate(my_knowledge.my_cards):
                    if card[0] == None and card[1] == None: #totally unclued
                        return ("discard", idx)
                for idx, card in enumerate(my_knowledge.my_cards):
                    if card[0] == None or card[1] == None:
                        return ("discard", idx) #partially unclued
                return ("discard", 0) #discard the oldest

            if action == "hint":
                # hint action to further plpayer respect to me
                if my_knowledge.my_turn_idx == 0:
                    furthest_player_idx = my_knowledge.num_players-1
                else:
                    furthest_player_idx = my_knowledge.my_turn_idx-1
                player_name = my_knowledge.idx_player[furthest_player_idx]
                player_cards = my_knowledge.players[player_name]['cards']
                #try to suggest to KEEP A CARD for later
                for i, card in enumerate(player_cards): #for all player's cards
                    if my_knowledge.table_cards[card.color] < card.value: # player has a next card for that color
                        hint_value = (my_knowledge.my_name, player_name, 'value', card.value, i)
                        if is_hint_not_misunderstandable(hint_value,card.color):
                            print("KEEP IT")
                            return ('hint', player_name, hint_value[3])
                #all cards of all players are useless also for the future, suggest to DISCARD
                for i, card in enumerate(player_cards): #for all player's cards
                    hint_value = (my_knowledge.my_name, player_name, 'value', card.value, i)
                    hint_color = (my_knowledge.my_name, player_name, 'color', card.color, i)
                    print("DISCARD IT")
                    ## Give a hint that touches more cards
                    if compare_hints(hint_value, hint_color) == 0: # hint on color touches more cards (to be discarded)
                            return ('hint', player_name, hint_color[3])
                    else: # hint on value touches more cards (to be discarded)
                            return ('hint', player_name, hint_value[3])

            if action == "play":
                ## Play your newest card
                return ("play", my_knowledge.handSize - 1)

        else:  #Q-Learning disabled
            print("Rule-based last resource")
            last_hard = last_hard + 1
            if my_knowledge.blue_tokens < 8:
                return ('discard', 0)
            else:
                next_player_idx = (my_knowledge.my_turn_idx + 1) % my_knowledge.num_players #try to suggest to KEEP A CARD for later
                for _ in range(my_knowledge.num_players-1): #for all the other players
                    player_name = my_knowledge.idx_player[next_player_idx]
                    player_cards = my_knowledge.players[player_name]['cards']
                    for i, card in enumerate(player_cards): #for all player's cards
                        if my_knowledge.table_cards[card.color] < card.value: # player has a next card for that color
                            hint_value = (my_knowledge.my_name, player_name, 'value', card.value, i)
                            if is_hint_not_misunderstandable(hint_value,card.color):
                                print("KEEP IT")
                                return ('hint', player_name, hint_value[3])
                    next_player_idx = (next_player_idx + 1) % my_knowledge.num_players
                next_player_idx = (my_knowledge.my_turn_idx + 1) % my_knowledge.num_players #all cards of all players are useless also for the future, suggest to DISCARD
                for _ in range(my_knowledge.num_players-1): #for all the other players
                    player_name = my_knowledge.idx_player[next_player_idx]
                    player_cards = my_knowledge.players[player_name]['cards']
                    for i, card in enumerate(player_cards): #for all player's cards
                        hint_value = (my_knowledge.my_name, player_name, 'value', card.value, i)
                        hint_color = (my_knowledge.my_name, player_name, 'color', card.color, i)
                        print("DISCARD IT")
                        ## Give a hint that touches more cards
                        if compare_hints(hint_value, hint_color) == 0: # hint on value touches more cards (to be discarded)
                                return ('hint', player_name, hint_color[3])
                        else: # hint on color touches more cards (to be discarded)
                                return ('hint', player_name, hint_value[3])
                    next_player_idx = (next_player_idx + 1) % my_knowledge.num_players

def action_to_command(action):
        for i, card in enumerate(my_knowledge.my_cards):
            if card[0] != None or card[1] != None:
                my_knowledge.my_cards[i] = (my_knowledge.my_cards[i][0], my_knowledge.my_cards[i][1], my_knowledge.my_cards[i][2] + 1) #update age of each hinted card
        if action[0] == 'discard':
            # discard
            command = f"discard {action[1]}"
        elif action[0] == 'play':
            # play
            command = f"play {action[1]}"
        else:
            if type(action[2]) == str:
                # hint color
                command = f"hint color {action[1]} {action[2]}"
            else:
                # hint value
                command = f"hint value {action[1]} {action[2]}"
        return command

def manageInput():
    command = input() ## Give the ready command
    global run
    global status
    global update
    global before_action
    while run:
        if status != "Lobby":
            if my_knowledge.init is not True:
                s.send(GameData.ClientGetGameStateRequest(playerName).serialize())
            while my_knowledge.my_turn == False:
                time.sleep(sleeptime)
                if update and run:
                    s.send(GameData.ClientGetGameStateRequest(playerName).serialize())
                pass
            update = False
            my_knowledge.my_turn = False
            s.send(GameData.ClientGetGameStateRequest(playerName).serialize()) #like "show" command in client.py, it prints the actual knowledge for the actual player
            before_action = True
            action = select_action()
            command = action_to_command(action)
            if True: # if verbose_action:
                print(command)
            if debug:
                tmp = input() #for debugging
        # Choose data to send
        if command == "exit":
            run = False
            os._exit(0)

        elif command == "ready" and status == "Lobby":
            s.send(GameData.ClientPlayerStartRequest(playerName).serialize())
            while status == 'Lobby':
                    continue

        elif command.split(" ")[0] == "discard" and status == "Game":
            try:
                cardStr = command.split(" ")
                cardOrder = int(cardStr[1])
                s.send(GameData.ClientPlayerDiscardCardRequest(playerName, cardOrder).serialize())
            except:
                print("Maybe you wanted to type 'discard <num>'?")
                continue

        elif command.split(" ")[0] == "play" and status == "Game":
            try:
                cardStr = command.split(" ")
                cardOrder = int(cardStr[1])
                s.send(GameData.ClientPlayerPlayCardRequest(playerName, cardOrder).serialize())
            except:
                print("Maybe you wanted to type 'play <num>'?")
                continue

        elif command.split(" ")[0] == "hint" and status == "Game":
            try:
                destination = command.split(" ")[2]
                t = command.split(" ")[1].lower()
                if t != "colour" and t != "color" and t != "value":
                    print("Error: type can be 'color' or 'value'")
                    continue
                value = command.split(" ")[3].lower()
                if t == "value":
                    value = int(value)
                    if int(value) > 5 or int(value) < 1:
                        print("Error: card values can range from 1 to 5")
                        continue
                else:
                    if value not in ["green", "red", "blue", "yellow", "white"]:
                        print("Error: card color can only be green, red, blue, yellow or white")
                        continue
                s.send(GameData.ClientHintData(playerName, destination, t, value).serialize())
            except:
                print("Maybe you wanted to type 'hint <type> <destinatary> <value>'?")
                continue

        elif command == "":
            continue

        else:
            print("Unknown command: " + command)
            continue
        stdout.flush()

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    request = GameData.ClientPlayerAddData(playerName)
    s.connect((HOST, PORT))
    s.send(request.serialize())
    data = s.recv(DATASIZE)
    data = GameData.GameData.deserialize(data)
    if type(data) is GameData.ServerPlayerConnectionOk:
        print("Connection accepted by the server. Welcome " + playerName)
    print("[" + playerName + " - " + status + "]: ", end="")
    Thread(target=manageInput).start()
    while run:
        dataOk = False
        data = s.recv(DATASIZE)
        if not data:
            continue
        data = GameData.GameData.deserialize(data)

        if type(data) is GameData.ServerPlayerStartRequestAccepted:
            dataOk = True
            print("Ready: " + str(data.acceptedStartRequests) + "/"  + str(data.connectedPlayers) + " players")
            data = s.recv(DATASIZE)
            data = GameData.GameData.deserialize(data)

        if type(data) is GameData.ServerStartGameData:
            dataOk = True
            print("Game start!")
            s.send(GameData.ClientPlayerReadyData(playerName).serialize())
            status = "Game"

        if type(data) is GameData.ServerGameStateData: ### done
            dataOk = True
            if (data.currentPlayer == playerName and update) or not my_knowledge.init:
                set_knowledge(data)

        if type(data) is GameData.ServerActionInvalid:
            dataOk = True
            print("Invalid action performed. Reason:")
            print(data.message)

        if type(data) is GameData.ServerActionValid: #discard feedback
            dataOk = True
            print(f"Discard action valid! Player {data.lastPlayer} discarded ({data.card.color}, {data.card.value})")
            print("Current player: " + data.player)
            discard_update(data)
            update = True

        if type(data) is GameData.ServerPlayerMoveOk: #good play feedback
            dataOk = True
            print(f"Nice move! Player {data.lastPlayer} played ({data.card.color}, {data.card.value})")
            print("Current player: " + data.player)
            niceMove_update(data)
            update = True

        if type(data) is GameData.ServerPlayerThunderStrike: #bad play feedback
            dataOk = True
            print(f"OH NO! The Gods are unhappy with you! Player {data.lastPlayer} tried to play ({data.card.color}, {data.card.value})")
            badMove_update(data)
            update = True

        if type(data) is GameData.ClientHintData: #hint given from this agent
            dataOk = True
            time.sleep(sleeptime)
            set_new_hint(data)
            print("Hint type: " + data.type)
            print(f"From player {data.source}")
            print("\tPlayer " + data.destination + " cards with value " + str(data.value) + " are:")
            for i in data.positions:
                print("\t\t" + str(i))
            update = True

        if type(data) is GameData.ServerHintData: #hint given to this agent
            dataOk = True
            time.sleep(sleeptime)
            set_new_hint(data)
            print("Hint type: " + data.type)
            print(f"From player {data.source}")
            print("\tPlayer " + data.destination + " cards with value " + str(data.value) + " are:")
            for i in data.positions:
                print("\t\t" + str(i))
            update = True

        if type(data) is GameData.ServerInvalidDataReceived:
            dataOk = True
            print(data.data)

        if type(data) is GameData.ServerGameOver:
            dataOk = True
            print(data.message)
            print(data.score)
            print(data.scoreMessage)
            stdout.flush()
            #run = False
            print("Ready for a new game!")
            game_over(data.score)

        if not dataOk:
            print("Unknown or unimplemented data type: " +  str(type(data)))

        if hasattr(data, 'currentPlayer') and data.currentPlayer == playerName and before_action:
            print("[" + playerName + " - " + status + "]: ", end="")
            before_action = False
        stdout.flush()


import json

import requests
from pyquery import PyQuery as pq

url1 = 'http://zf.ahu.cn/'
url2 = 'http://zf.ahu.cn/IdentityServer/Account/getPublicKey'
session = requests.session()
res1 = session.get(url1)
doc = pq(res1.text)
__RequestVerificationToken = doc(
    'body > div > div.login-div > div.col-md-4.form > form > input[type="hidden"]:nth-child(5)').attr("value")
print(__RequestVerificationToken)
headers = {
    '__RequestVerificationToken': __RequestVerificationToken,
    'Accept': 'application/json, text/javascript, */*; q=0.01',
    'Accept-Encoding': 'gzip, deflate',
    'Accept-Language': 'zh-CN,zh;q=0.9',
    'Content-Length': '0',
    'Host': 'zf.ahu.cn',
    'Origin': 'http://zf.ahu.cn',
    'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36',
    'X-Requested-With': 'XMLHttpRequest',
    'Proxy-Connection': 'keep-alive',
}
res2 = session.post(url2, headers=headers)
x = res2.json()
# print(x)
# print(type(x))
y = json.dumps(x)
# print(y)
# print(type(y))
print(y)


def binarySearchIterative(needle, haystack, left=None, right=None):
    # By default, `left` and `right` span the entire range of `haystack`:
    if left is None:
        left = 0  # `left` defaults to the 0 index.
    if right is None:
        right = len(haystack) - 1  # `right` defaults to the last index.

    while True:
        print('Searching:', haystack[left:right + 1])

        if left > right:
            return None  # The `needle` is not in `haystack`.

        mid = (left + right) // 2
        if needle == haystack[mid]:
            return mid  # The `needle` has been found in `haystack`
        elif needle < haystack[mid]:
            right = mid - 1
        elif needle > haystack[mid]:
            left = mid + 1

print(binarySearchIterative(13, [1, 4, 8, 11, 13, 16, 19, 19]))


import datetime
import os
import smtplib
from django.views.generic import View
from django.conf import settings
from django.http import HttpResponse
from xhtml2pdf import pisa
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.mime.base import MIMEBase
from email import encoders
from django.template.loader import get_template
from django.shortcuts import render, redirect
from proyectos.models import Unidades
from presupuestos.models import Constantes
from ventas.models import FeaturesUni, ImgEnlacesProyecto, Clientescontacto
from crm.models import Consulta, Tipologia
from rrhh.models import datosusuario
from ventas.functions_unidades import calculo_m2_unidad, cliente_crm, plan_financiacion_cotizador, info_para_cotizador

def cotizador(request, id_unidad):

    context = {}

    datos = Unidades.objects.get(id = id_unidad)
    today = datetime.date.today()

    m2 = calculo_m2_unidad(datos)

    precio_contado = m2*datos.proyecto.desde

    features_unidad = FeaturesUni.objects.filter(unidad = datos)

    for f2 in features_unidad:

        precio_contado = precio_contado*f2.feature.inc

    desde = round((precio_contado/m2), 4)

    if request.method == 'POST':

        try:
            context["cliente"] = cliente_crm(request.POST['email'], nombre = request.POST['nombre'], apellido = request.POST['apellido'], telefono = request.POST['telefono'])

        except:

            context["cliente"] = cliente_crm(request.POST['email'])

        context["resultados"] = plan_financiacion_cotizador(request.POST["anticipo"], request.POST["cuotas_esp"], request.POST["aporte"], request.POST["cuotas_p"], request.POST['observacion'], request.POST['descuento'], precio_contado, datos)

        context["info_coti_email"] = info_para_cotizador(context["resultados"])

    context["imagenes_carru"] = ImgEnlacesProyecto.objects.filter(proyecto = datos.proyecto)
    context["tiempo_restante"] = (datos.proyecto.fecha_f.year - today.year)*12 + (datos.proyecto.fecha_f.month - today.month)
    context["datos"] = datos
    context["precio_contado"] = precio_contado
    context["m2"] = m2

    return render(request, 'cotizador/cotizador_principal.html', context)

class PDF_cotizacion(View):

    def link_callback(self, uri, rel):

            """
            Convert HTML URIs to absolute system paths so xhtml2pdf can access those
            resources
            """
            sUrl = settings.STATIC_URL        # Typically /static/
            sRoot = settings.STATIC_ROOT      # Typically /home/userX/project_static/
            mUrl = settings.MEDIA_URL         # Typically /media/
            mRoot = settings.MEDIA_ROOT       # Typically /home/userX/project_static/media/

            if uri.startswith(mUrl):
                path = os.path.join(mRoot, uri.replace(mUrl, ""))
            elif uri.startswith(sUrl):
                path = os.path.join(sRoot, uri.replace(sUrl, ""))
            else:
                return uri

            # make sure that file exists
            if not os.path.isfile(path):
                raise Exception(
                        'media URI must start with %s or %s' % (sUrl, mUrl)
                )
            return path

    def get(self, request, id_unidad, id_cliente, info_coti, *args, **kwargs):

        #Creamos la información

        cliente = Clientescontacto.objects.get(id = id_cliente)
        unidad = Unidades.objects.get(id = id_unidad)
        features_unidad = FeaturesUni.objects.filter(unidad = unidad)
        valor_hormigon = Constantes.objects.get(id = 7)

        today = datetime.date.today()

        # Saludo de bienvenida

        saludo = saludo_bienvenida(cliente)

        # Calculo de datos

        m2 = calculo_m2_unidad(unidad)

        precio_contado = m2*unidad.proyecto.desde

        features_unidad = FeaturesUni.objects.filter(unidad = unidad)

        for f2 in features_unidad:

            precio_contado = precio_contado*f2.feature.inc

        datos_recibidos_back = info_coti.split("&")

        datos_para_calculo_cotizacion = {
            "anticipo":float(datos_recibidos_back[3]),
            "cuotas_espera":datos_recibidos_back[0],
            "aporte":datos_recibidos_back[1],
            "cuotas_posesion":datos_recibidos_back[2],
            "observacion":datos_recibidos_back[5],
            "descuento":datos_recibidos_back[4]
        }

        datos_cotizacion = plan_financiacion_cotizador(datos_para_calculo_cotizacion["anticipo"],
        datos_para_calculo_cotizacion["cuotas_espera"],
        datos_para_calculo_cotizacion["aporte"],
        datos_para_calculo_cotizacion["cuotas_posesion"],
        datos_para_calculo_cotizacion['observacion'],
        datos_para_calculo_cotizacion['descuento'],
        precio_contado, unidad)

        datos_cotizacion_json = {
            "anticipo":datos_cotizacion[0],
            "anticipo_en_hormigon":datos_cotizacion[1],
            "precio_financiado":datos_cotizacion[2],
            "cuotas_espera":datos_cotizacion[3],
            "importe_del_aporte":datos_cotizacion[4],
            "cuotas_posesion":datos_cotizacion[5],
            "importe_de_las_cuotas_espera":datos_cotizacion[6],
            "aporte":datos_cotizacion[7],
            "importe_de_las_cuotas_posesion":datos_cotizacion[8],
            "importe_de_las_cuotas_posesion_en_hormigon":datos_cotizacion[9],
            "importe_de_las_cuotas_espera_en_hormigon":datos_cotizacion[10],
            "importe_del_aporte_en_hormigon":datos_cotizacion[11],
            "valor_de_la_cuota_espera":datos_cotizacion[12],
            "valor_de_la_cuota_entrega":datos_cotizacion[13],
            "valor_de_la_cuota_posesion":datos_cotizacion[14],
            "observacion":datos_cotizacion[15],
            "descuento":datos_cotizacion[16],
            "total_en_pesos":datos_cotizacion[17],
            "total_en_hormigon":datos_cotizacion[18],
            "precio_de_contado":datos_cotizacion[19],
        }

        # Aqui llamamos y armamos el PDF

        template = get_template('cotizador/cotizador_PDF.html')

        contexto = {'cliente':cliente,
        'unidad':unidad,
        'datos_cotizacion_json':datos_cotizacion_json,
        'today':today,
        'logo':'{}{}'.format(settings.STATIC_URL, 'img/link.png'),
        'cabecera':'{}{}'.format(settings.STATIC_URL, 'img/fondo.png'),
        'fondo':'{}{}'.format(settings.STATIC_URL, 'img/fondo.jpg')}

        html = template.render(contexto)
        response = HttpResponse(content_type = "application/pdf")

        #response['Content-Disposition'] = 'attachment; filename="reporte.pdf"'

        pisaStatus = pisa.CreatePDF(html, dest=response, link_callback=self.link_callback)

        if pisaStatus.err:

            return HttpResponse("Hay un error")

        datos_email = {
            "saludo":saludo,
            "cliente":cliente,
            "unidad":unidad,
            "response":response
        }

        enviar_email = cotizacion_email_cliente(datos_email)

        cotizacion = "cotizacion{}{}.pdf".format(str(cliente.nombre).replace(" ", ""), today)

        # Creo la consulta

        usuario = datosusuario.objects.get(identificacion = request.user.username)

        try:

            tipologia = Tipologia.objects.get(nombre = unidad.tipologia)
        except:

            tipologia = Tipologia(
                nombre = unidad.tipologia
            )
            tipologia.save()

        datos_consulta = {
            "unidad":unidad,
            "cliente":cliente,
            "usuario":usuario,
            "cotizacion":cotizacion,
            "tipologia":tipologia,
        }

        guardar_consulta = cotizacion_consultas_guardar(datos_consulta)

        return redirect('modificarcliente', id = cliente.id)

def cotizacion_consultas_guardar(datos_consulta):

    today = datetime.date.today()

    try:

        new_consulta = Consulta(
            fecha = today,
            proyecto = datos_consulta['unidad'].proyecto,
            cliente = datos_consulta['cliente'],
            medio_contacto = 'RECOMENDACION',
            usuario = datos_consulta['usuario'],
            adjunto_propuesta = (datos_consulta['cotizacion']),
        )

        new_consulta.save()
        new_consulta.tipologia2.add(datos_consulta['tipologia'])
        new_consulta.save()

        return "Consulta guardada correctamente"

    except:

        return "Error al crear la consulta"

def cotizacion_email_cliente(datos_email):

    try:

        today = datetime.date.today()

        # Establecemos conexion con el servidor smtp de gmail

        mailServer = smtplib.SMTP(settings.EMAIL_HOST, settings.EMAIL_PORT)
        mailServer.ehlo()
        mailServer.starttls()
        mailServer.ehlo()
        mailServer.login(settings.EMAIL_HOST_USER, settings.EMAIL_HOST_PASSWORD)

        # Construimos el mensaje simple

        mensaje = MIMEMultipart()
        mensaje.attach(MIMEText(cuerpo_email_cotizacion(datos_email["saludo"]), 'plain'))
        mensaje['From']=settings.EMAIL_HOST_USER
        mensaje['To']=datos_email["cliente"].email
        mensaje['Subject']="LINK - Tu cotización {}".format(datos_email["cliente"].nombre)

        # Esta es la parte para adjuntar

        mRoot = settings.MEDIA_ROOT

        if datos_email["unidad"].plano_venta:

            plano_adjunto = open(mRoot + "/{}".format(datos_email["unidad"].plano_venta.name), 'rb')
            adjunto_MIME = MIMEBase('application', "octet-stream")
            adjunto_MIME.set_payload(plano_adjunto.read())
            encoders.encode_base64(adjunto_MIME)
            adjunto_MIME.add_header('Content-Disposition', 'attachment; filename="Plano de la unidad.pdf"')
            mensaje.attach(adjunto_MIME)

        adjunto_MIME = MIMEBase('application', "octet-stream")
        adjunto_MIME.set_payload(datos_email["response"].content)
        encoders.encode_base64(adjunto_MIME)
        adjunto_MIME.add_header('Content-Disposition', 'attachment; filename="Tu_cotizacion.pdf"')
        mensaje.attach(adjunto_MIME)

        with open(mRoot + "/cotizacion{}{}.pdf".format(datos_email["cliente"].nombre, today).replace(" ", ""), 'wb') as f:
            f.write(datos_email["response"].content)

        name_coti_adjunta = "cotizacion{}{}.pdf".format(str(datos_email["cliente"].nombre).replace(" ", ""), today)

        # Envio del mensaje

        mailServer.sendmail(settings.EMAIL_HOST_USER,
                        datos_email["cliente"].email,
                        mensaje.as_string())

        return "Email enviado correctamente"

    except:

        return "Error inesperado al tratar de enviar el email"

def saludo_bienvenida(cliente):

    hora_actual = datetime.datetime.now()

    if hora_actual.hour >= 20:
        saludo = "¡Buenas noches {}!".format(cliente.nombre)
    elif hora_actual.hour >= 13:
        saludo = "¡Buenas tardes {}!".format(cliente.nombre)
    else:
        saludo = "¡Buen dia {}!".format(cliente.nombre)

    return saludo

def cuerpo_email_cotizacion(saludo):
    return """

    {}

    Enviamos la cotización de hoy!, cualquier consulta no dudes en comunicarte con nosotros

    Ingresa a www.linkinversiones.com.ar para mas información

    LINK Desarrollos inmobilairios
    Vos confias porque nosotros cumplimos

    Por favor no responder este email

    """.format(saludo)


# data utils
import pandas as pd
import numpy as np
from sklearn.decomposition import PCA
from collections import Counter
import random
from operator import add
import scipy.sparse as sp
from sklearn import metrics

# model utils
from keras.layers.core import Dropout, Activation
from keras import optimizers
from keras.models import Sequential
from keras.layers import Dense, BatchNormalization
from keras.models import load_model

# read in utils
from utility import *

# read in decagon data
combo2stitch, combo2se, se2name = load_combo_se()
net, node2idx = load_ppi()
stitch2se, se2name_mono = load_mono_se()
stitch2proteins = load_targets()
se2class, se2name_class = load_categories()
se2name.update(se2name_mono)
se2name.update(se2name_class)

# read in smiles data
smiles = pd.read_csv("data/model_data/id_SMILE.txt", sep="\t", header=None)

# format smiles data to have same form as CID0*
smiles.iloc[:, 0] = [f'CID{"0"*(9-len(str(drug_id)))}{drug_id}' for drug_id in smiles.iloc[:,0]]
smiles = smiles.rename(columns={0:'drug_id', 1:'smiles'})

# get counts and create lists of all drugs and proteins

# get list of all drugs
drugs = set()
for d in combo2stitch.keys():
    d1, d2 = d.split("_")
    drugs.add(d1)
    drugs.add(d2)
drugs = list(drugs)
pd.DataFrame({"drugs": drugs}).to_csv("data/model_data/drugs_ordered.csv", index=False)

# get list of all proteins
proteins = set()
for p_set in stitch2proteins.values():
    proteins = proteins.union(p_set)
proteins = list(proteins)

# get counts to help with matrix building
n_drugs = len(drugs)
n_proteins = len(proteins)
pd.DataFrame({"proteins": proteins}).to_csv("data/model_data/proteins_ordered.csv", index=False)

print(f'total drugs: {n_drugs} | total proteins: {n_proteins} | total mono se: {len(se_mono)} | total polypharmacy se: {len(ddi_se)}')

# ------------------------------------ Construct Drug Features ----------------------------------------

# construct mono se features
se_mono=[]
for k in se2name_mono:
    se_mono.append(k)

drug_label = np.zeros((n_drugs,len(se_mono)))
for key,value in stitch2se.items():
    j = drugs.index(key)
    for v in value:
        i=se_mono.index(v)
        drug_label[j,i]=1
pd.DataFrame({"se_mono": se_mono}).to_csv("data/model_data/se_mono_ordered.csv", index=False)

# save to npy file
np.save('../data/model_data/embeddings/drug_label.npy', drug_label)

# construct drug protein features
dp_adj = np.zeros((n_drugs, n_proteins))
for i in range(n_drugs):
    drug_name = drugs[i]
    for protein_name in stitch2proteins[drug_name]:
        k = proteins.index(protein_name)
        dp_adj[i, k] = 1
# save to npy file
np.save('../data/model_data/embeddings/dp_adj.npy', dp_adj)

# read in drug molecule features (embeddings from dgllife)
molecule_embeddings  = np.load('../data/model_data/embeddings/drugname_smiles.npy')

# format to match order of drugs
mol_adj = np.zeros((n_drugs, len(molecule_embeddings[0])))
smiles_drugs = list(smiles['drug_id'])

for i in range(n_drugs):
    drug = drugs[i]
    mol_index = smiles_drugs.index(drug)
    mol_adj[i] = molecule_embeddings[mol_index]

# save to npy file
np.save('../data/model_data/embeddings/mol_adj.npy', mol_adj)

# ------------------------------------ Construct Drug-Drug Interaction Matrices ----------------------------------------
se2combo = {}
ddi_types = []
for drug_pair, val in combo2se.items():
    for se in list(val):
        ddi_types.append(se)
        if se in se2combo.keys():
            current_pairs = se2combo[se]
            current_pairs.append(drug_pair)
            se2combo[se] = current_pairs
        else:
            se2combo[se] = [drug_pair]

# only use side effects that occurred in at least 500 drug-drug pairs
ddi_counter = Counter(ddi_types)
ddi_counter_500 = Counter({k: c for k, c in ddi_counter.items() if c >= 500})

n_ddi_types = len(ddi_counter_500)
ddi_types = list(ddi_counter_500.keys())
pd.DataFrame({'ddi types': ddi_types}).to_csv("data/model_data/ddi_se_ordered.csv", index=False)

# format drug drug adjacency matrix for each side effect
dd_adj_list = []

for i in range(n_ddi_types):
    if i%100 == 0:
        print(f'On DDI matrix for SE number: {i}')
    mat = np.zeros((n_drugs, n_drugs))
    curr_se = ddi_types[i]
    drug_pairs_for_se = se2combo[curr_se]
    for dp in drug_pairs_for_se:
        d1, d2 = dp.split("_")
        drug1 = drugs.index(d1)
        drug2 = drugs.index(d2)
        mat[drug1, drug2] = 1
        mat[drug2, drug1] = 1
    dd_adj_list.append(mat)

# save to npy file
np.savez('../data/model_data/embeddings/ddi_adj.npy', *dd_adj_list)


import re

from data_structure import *
from constants import *

class UsableTimeParser(object):

    DEFAULT_SELECTOR = 'default'
    DEFAULT_USABLE_TIME = Duration(8)
    SELECTOR_TO_WEEKDAY = {
        'monday': 0,
        'tuesday': 1,
        'wednesday': 2,
        'thursday': 3,
        'friday': 4,
        'saturday': 5,
        'sunday': 6,
    }

    def __init__(self):
        pass

    def _match_single_date(value):
        return SINGLE_DATE_RE.match(value) is not None

    def _parse_single_date(value):
        components = [int(component) for component in value.split('-')]
        return Date.from_components(*components)

    def _match_date_range(value):
        return DATE_RANGE_RE.match(value) is not None

    def _parse_date_range(value):
        dates = DATE_RANGE_SPLIT_RE.split(value)
        return UsableTimeParser._parse_single_date(dates[0]), UsableTimeParser._parse_single_date(dates[1])

    def get_usable_time_dict(self, schedule_start, schedule_end, usable_time_config):
        default = Duration(UsableTimeParser.DEFAULT_USABLE_TIME.value)
        result = {}
        day_of_week_dict = {}

        # parse day_of_week_dict
        for entry in usable_time_config:
            if entry.selector.value == UsableTimeParser.DEFAULT_SELECTOR:
                default = Duration(entry.duration.value)

            elif entry.selector.value in UsableTimeParser.SELECTOR_TO_WEEKDAY:
                day_of_week_dict[
                    # UsableTimeSelector made sure that entry.selector.value is lower case
                    UsableTimeParser.SELECTOR_TO_WEEKDAY[entry.selector.value]
                ] = Duration(entry.duration.value)

        # default and weekday selectors
        date = schedule_start
        while date <= schedule_end:
            weekday = date.get_weekday()
            if weekday in day_of_week_dict:
                result[date] = Duration(day_of_week_dict[weekday].value)

            else:
                result[date] = Duration(default.value)

            date = date.add_days(1)

        # date selectors
        for entry in usable_time_config:
            if UsableTimeParser._match_single_date(entry.selector.value):
                date = UsableTimeParser._parse_single_date(entry.selector.value)
                result[date] = Duration(entry.duration.value)

            elif UsableTimeParser._match_date_range(entry.selector.value):
                date_start, date_end = UsableTimeParser._parse_date_range(entry.selector.value)
                if date_start < schedule_start:
                    date_start = schedule_start

                if schedule_end < date_end:
                    date_end = schedule_end

                date = date_start
                while date <= date_end:
                    result[date] = Duration(entry.duration.value)
                    date = date.add_days(1)

        return result

def main():
    import doctest
    doctest.testmod()

if __name__ == '__main__':
    main()


import sys
sys.stdin = open('chat.py')
input = sys.stdin.readline
sys.setrecursionlimit(100000)

def get_leaves(vtx):
    global leaves
    if len(adj_list[vtx]) == 0:
        leaves += 1
    else:
        for adj_vtx in adj_list[vtx]:
            if not visited[adj_vtx]:
                visited[adj_vtx] = 1
                get_leaves(adj_vtx)

def remove_children(target_vtx):
    for r_idx, row in enumerate(adj_list):  # 해당 노드 찾아서 지워
        if target_vtx in row:
            adj_list[r_idx].remove(target_vtx)
            break

    for adj_vtx in adj_list[target_vtx]:  # 연결된 노드들도 재귀
            remove_children(adj_vtx)

N = int(input())
inp_data = list(map(int, input().split()))
target = int(input())
adj_list = [[] for _ in range(N)]
leaves = 0
visited = [0] * N
removed = [0] * N

for idx, ele in enumerate(inp_data):
    if ele != -1:
        adj_list[ele].append(idx)
print(adj_list)
remove_children(target)
print(adj_list)
get_leaves(0)
print(leaves)

# 루트에서 bfs 해서 끝나고 돌아올 때 leaf ++해주기
# 삭제 후 다시 leaf 세기


from ruffus import *
import os
from rnarry.nrclip import Paths, Options, SequenceMasking, DataPreparation
from rnarry.nrclip.PipelineControl import *

@files(for_each(Paths.fulltag_genome_besthits,
                Paths.genomespace_read_database,
                Paths.ALL_SAMPLES))
@follows(SequenceMasking.resolve_genomic_multihits)
def build_genomespace_read_database(inputfile, outputfile, sample):
    outputdir = os.path.dirname(outputfile)
    runproc("""
        $PREPARE_FLATDATA_FROM_SAM $inputfile | \
        $SORT -k1,1 -k3,4 -k5,5n | \
        $BUILD_POSITIONALDB_GENOME $outputdir""", outputfile)

@files(for_each(Paths.genomespace_read_database,
                Paths.genomespace_refseq_counts,
                Paths.ALL_SAMPLES))
@follows(build_genomespace_read_database)
@follows(DataPreparation.build_nonredundant_refseq_database)
def quantitate_refseq_in_gspace(inputfile, outputfile, sample):
    gspacedir = os.path.dirname(inputfile)
    runproc(
        '$COUNT_REFSEQ_IN_GSPACE $outputfile $nr_refseq_db $gspacedir',
        outputfile)

@files([Paths.nr_refseq_list] +
       [Paths.genomespace_refseq_counts(sample)
        for sample in Paths.ALL_SAMPLES],
       Paths.genomespace_all_expressed_transcripts)
@follows(quantitate_refseq_in_gspace)
def make_list_of_expressed_transcripts(inputfiles, outputfile):
    inputlist = ' '.join(inputfiles)

    runproc("""
        $ENV MINDEPTH=$GSPACE_STATS_MINIMUM_RAW_READS \
        $REFSEQCNT_PICK_EXPRESSED $inputlist > $outputfile""", outputfile)

@files([Paths.nr_refseq_db, Paths.genomespace_all_expressed_transcripts,
        Paths.genome_fasta,
        Paths.genomespace_read_database(Options.SNPREF_SAMPLE)],
       [Paths.reftranscriptome_sequences, Paths.reftranscriptome_cds_anno])
@follows(make_list_of_expressed_transcripts)
def generate_SNPfixed_transcriptome(inputfiles, outputfiles):
    nrdb, expressed, genomeseq, gspace = inputfiles
    outseq, outanno = outputfiles

    runproc("""
        $GENFASTA_MUTATED_TRANSCRIPTOME $nrdb $expressed $genomeseq $gspace \
            $outseq $outanno""", outputfiles)
    runproc("$SAMTOOLS faidx $outseq", outputfiles)
    runproc("$FASIZE -detailed $outseq > $outseq.size", outputfiles)

@files(Paths.reftranscriptome_sequences, Paths.reftranscriptome_gmap_index)
@follows(generate_SNPfixed_transcriptome)
def generate_gsnap_transcriptome_index(inputfile, outcheck):
    runproc('$GMAP_BUILD -d $reftranscriptome_dbname -D $REFTRANSCRIPTOME_DIR '
            '-k 12 $inputfile', outcheck)

def tasks():
    return [
        build_genomespace_read_database,
        quantitate_refseq_in_gspace,
        make_list_of_expressed_transcripts,
        generate_SNPfixed_transcriptome,
        generate_gsnap_transcriptome_index,
    ]


# !/usr/bin/env python3
# _*_coding:utf-8_*_
# __author__：FLS

import base64
from  io import StringIO

'''

Python base64模块真正用的上的方法只有8个，分别是encode, decode, encodestring, decodestring, b64encode,b64decode, urlsafe_b64decode,urlsafe_b64encode。他们8个可以两两分为4组，
encode,decode一组，专门用来编码和解码文件的,也可以对StringIO里的数据做编解码；
encodestring,decodestring一组，专门用来编码和解码字符串；
b64encode和b64decode一组，用来编码和解码字符串，并且有一个替换符号字符的功能。这个功能是这样的：因为base64编码后的字符除 了英文字母和数字外还有三个字符 + / =, 其中=只是为了补全编码后的字符数为4的整数，而+和/在一些情况下需要被替换的，
b64encode和b64decode正是提供了这样的功能。至于什么情况下+和/需要被替换，最常见的就是对url进行base64编码的时候。
urlsafe_b64encode和urlsafe_b64decode 一组，这个就是用来专门对url进行base64编解码的，实际上也是调用的前一组函数。

因为base64编码后的字符除 了英文字母和数字外还有三个字符 + / =, 其中=只是为了补全编码后的字符数为4的整数，而+和/在一些情况下需要被替换的，b64encode和b64decode正是提供了这样的功能。至于什 么情况下+和/需要被替换，最常见的就是对url进行base64编码的时候

'''

# a=b'this is ok '
# res=base64.b64encode(a)
# print(res)
#
# print(base64.b64decode(res))

a=b'this is ok '
res=base64.encodebytes(a)
print(res)

a=b'this is ok'
res=base64.b64encode(a)
print(res)

# url_encode

b=b'i\xb7\x1d\xfb\xef\xff'
res=base64.urlsafe_b64encode(b)
print(res)  # b'abcd--__'  实际上应该是 b'abcd++//'

# 其实在 python3 所有的对象都是unicode 类型，所以所有的
# 将  中文  转成 bash64 编码
# 首先base64 生成的编码都是 acsii码，而 python3 默认都是 unicode 码，而 b64encode 的参数必须是 bytes 类型，所以想要将中文转为 base64 编码，首先要转码

a='你好'
b=a.encode('utf-8')
print(b)

c=base64.b64encode(b)
print(c)

# 解码过程同理


from roflan_bot.common.Storage import Storage

class ActionRecognizer:
    def __init__(self, actions_data: Storage):
        self.actions_data = actions_data

    def recognize_actions(self, text: str) -> list:
        recognized_actions = []
        split_text = text.split()

        for name, action in self.actions_data.items():
            for phrase in action["phrases"]:
                split_phrase = phrase.split()
                matching_word_count = 0

                for phrase_word in split_phrase:
                    if phrase_word in split_text:
                        matching_word_count += 1

                if matching_word_count == len(split_phrase):
                    recognized_actions.append(name)

        return recognized_actions


import logging

from trello import TrelloClient

logging.basicConfig(filename='trello_webhook_module.log', level=logging.DEBUG)

NON_CREATOR_STATE = True

class trello_handle_card_deleted(NebriOS):
    listens_to = ['card_deleted']

    def check(self):
        return self.kind == "trello_card" and self.card_deleted == True and not self.card_deleted_handled and self.card_deleted_by_noncreator == NON_CREATOR_STATE

    def action(self):
        client = self.get_client()
        user = self.get_me(client)
        member_data = self.get_member_data(user['id'])
        board = client.get_board(member_data.backup_board_id)
        backup_list = board.get_list(member_data.deleted_list_id)
        for label in self.card_json['labels']:
            board.add_label(label['name'], label['color'])
        add_card_kwargs = {'desc': self.card_json['desc'], 'labels': self.card_json['labels']}
        due_date = self.card_json.get('due', None)
        if due_date:
            add_card_kwargs['due'] = due_date
        card_backup = backup_list.add_card(self.card_json['name'], **add_card_kwargs)
        for checklist in self.card_json['checklists']:
            card_backup.add_checklist(checklist['name'], [item['name'] for item in checklist['checkItems']], itemstates=[item['state'] == 'complete' for item in checklist['checkItems']])
        for attachment in self.card_json['attachments']:
            card_backup.attach(url=attachment['url'])
        self.card_deleted_handled = True

    def get_me(self, client):
        return client.fetch_json('/members/me')

    def get_trello_token(self):
        try:
            return Process.objects.get(kind="trello_oauth_token").token
        except:
            load_card('trello-token-save')
            raise Exception('Token does not exist. Please supply one on the Trello OAuth Token Creation card or run trello_webhook_setup.')

    def get_client(self):
        return TrelloClient(api_key=shared.TRELLO_API_KEY, api_secret=shared.TRELLO_API_SECRET, token=self.get_trello_token())

    def get_member_data(self, member_id):
        member_data, _ = Process.objects.get_or_create(kind="trello_member_data", member_id=member_id)
        return member_data


import logging
from datetime import datetime

# 第三方 import
from croniter import croniter
from django.conf import settings
from django.contrib.auth.models import User
from django.db.models import Q
from django.utils import timezone

# 项目内 import
from apps.codeproj import core, models
from apps.codeproj.core import ScanSchemeManager
from apps.job.models import Job
from codedog.celery import celery_app
from util import errcode
from util.operationrecord import OperationRecordHandler
from util.webclients import AnalyseClient

logger = logging.getLogger(__name__)

def _now():
    now = timezone.make_aware(datetime.now(), timezone.get_current_timezone())
    return now

@celery_app.task
def sync_pkg_rule_map():
    """启动AnalysisServer规则包与规则关系同步任务
    """
    logger.info("Start to drop expired table")
    result = AnalyseClient().api("sync_pkg_rule_map", data=None)
    logger.info("drop expired table result: %s" % result)

@celery_app.task
def check_project_active():
    """检查项目是否运行正常

    1. 检查项目近一个月是否有启动扫描，如果没有则标记并发送邮件通知给分支项目创建同学
    2. 检查定时项目近10次扫描是否存在SCM相关异常，如果有，则关闭定时任务
    """
    logger.info("开始检查项目是否运行正常")
    logger.info("1. 开始检查项目近一个月是否有启动扫描")
    projects = models.Project.objects.filter(status=models.Project.StatusEnum.ACTIVE)
    codedog_user, created = User.objects.get_or_create(username=settings.DEFAULT_USERNAME)
    current_time = _now()
    for project in projects:
        # 长期未成功执行扫描
        last_success_job = Job.objects.filter(project=project).order_by("-create_time").first()
        last_active_time = last_success_job.create_time if last_success_job else project.created_time
        if current_time - last_active_time > settings.PROJECT_DISACTIVE_TIMEOUT:
            logger.info("[Project: %d][Creator: %s] 项目失活，代码库地址: %s，上一次活跃时间为: %s" % (
                project.id, project.creator, project.scm_url, last_active_time))
            models.Project.objects.filter(id=project.id).update(
                status=models.Project.StatusEnum.DISACTIVE, modifier=codedog_user, modified_time=current_time)
            OperationRecordHandler.add_project_operation_record(
                project, "项目失活", codedog_user, message="项目于%s自动标记为失活" % current_time
            )
    logger.info("2. 开始检查开启定时扫描的项目近10次扫描是否存在SCM相关异常")
    project_schedules = models.ScanSchedule.objects.filter(
        enabled=True,
        project__status=models.Project.StatusEnum.ACTIVE,
        project__scan_scheme__status=models.ScanScheme.StatusEnum.ACTIVE
    ).exclude(scan_sched=None)

    for project_sched in project_schedules:
        project = project_sched.project
        result_codes = Job.objects.filter(project=project).order_by(
            "-create_time").values_list("result_code", flat=True)[:10]
        result_codes = list(set(result_codes))
        if len(result_codes) == 1 and errcode.is_scm_error(result_codes[0]):
            msg = "项目近10次扫描错误码均为%s，关闭定时扫描任务" % result_codes[0]
            logger.warning("[Project: %s] %s" % (project.id, msg))
            OperationRecordHandler.add_project_operation_record(
                project, "项目更新配置", codedog_user, message=msg
            )
            project_sched.enabled = False
            project_sched.save()

@celery_app.task
def push_scanscheme_template(scheme_ids, ref_scheme_id, username, **kwargs):
    """推送扫描方案模板到相关子方案
    """
    user, _ = User.objects.get_or_create(username=username)
    ref_scheme = models.ScanScheme.objects.get(id=ref_scheme_id)
    op_message = ScanSchemeManager.get_sync_message(ref_scheme, **kwargs)
    scan_scheme_message = []
    for scheme_id in scheme_ids:
        scan_scheme = models.ScanScheme.objects.get(id=scheme_id)
        ScanSchemeManager.sync_with_ref_scheme(scan_scheme=scan_scheme,
                                               ref_scheme=ref_scheme,
                                               user=user,
                                               **kwargs)
        OperationRecordHandler.add_scanscheme_operation_record(scan_scheme, "方案模板同步", username, op_message)
        scan_scheme_message.append("%s" % scan_scheme)
    ref_scheme_message = "%s，同步扫描方案：%s" % (op_message, "、".join(scan_scheme_message))
    OperationRecordHandler.add_scanscheme_operation_record(ref_scheme, "方案模板同步", username, ref_scheme_message)

@celery_app.task
def handle_scheduled_projects():
    """根据project的配置定时创建扫描
    筛选范围：
    1. 配置了定时任务
    2. 项目为活跃状态
    3. 扫描方案为活跃状态
    """
    # Todo


#GRUIDE: https://towardsdatascience.com/data-science-skills-web-scraping-javascript-using-python-97a29738353f

from selenium import webdriver
import time

#Starts the driver
#Opens Dplay
#Presents welcome meny

def main():
    driver = webdriver.Firefox()
    driver.get("https://www.dplay.no")
    inp = ""
    while inp != "0":
        welcomeMeny()
        inp = input()
        checkInput(inp, driver)

    try:
        driver.close()
    except:
        print("Browser window already closed")

#Presents the user with alternatives
def welcomeMeny():
    alternatives = {0: "Exit", 1: "Fjern Reklame"}
    print("Velg hva du vil gjøre!:")
    for alt in alternatives:
        print(str(alt) + " : " + str(alternatives[alt]))

#Checks which input you've given
def checkInput(inp, driver):
    if inp == str(1):
        adBlock(driver)

#Removes the ads
def adBlock(driver):
    try:
        element = driver.find_element_by_id("adsbase")
        attr = element.get_attribute("src")
    except:
        print("No advertisement to remove\n")
        return
    newUrl = checkURL(attr)
    if newUrl:
        driver.execute_script("document.getElementById('adsbase').setAttribute('src', '')", element)
        #Should find a better soluton than sleep (i think)
        time.sleep(0.5)
        adBlock(driver)
    else:
        print("No advertisement to remove\n")

def checkURL(url):
    #Wack måte å gjøre det på, bruk regex eller noe annet
    if url[0:17] == "https://www.dplay":
        print(url[0:17])
        return False
    elif url == "":
        return False
    else:
        print(url[0:17])
        return True

main()


from parameters import *
from brian2 import *
from brian2tools import *

OnCenterOffSurround = NeuronGroup(NUM_NEURONS, eqs, threshold='v > 10*mV', reset='v = 0*mV',
                    refractory=REFRACTORY_TIME, method=INTEG_METHOD)
OnCenterOffSurround.v = 0*mV # initialize voltages to 0
OnCenterOffSurround.a = 0

OffCenterOnSurround = NeuronGroup(NUM_NEURONS, eqs, threshold='v > 10*mV', reset='v = 0*mV',
                    refractory=REFRACTORY_TIME, method=INTEG_METHOD)
OffCenterOnSurround.v = 0*mV # initialize voltages to 0
OffCenterOnSurround.a = 0


from django import forms
from .models import Order

class OrderForm(forms.ModelForm):
    class Meta:
        model = Order
        fields = ('subscription_plan', 'subscription_price', 'full_name',
                  'email', 'phone_number', 'street_address1',
                  'street_address2', 'town_or_city', 'postcode',
                  'county', 'country',)

    def __init__(self, *args, **kwargs):
        """
        Rename fields to user friendly display on form
        """
        super().__init__(*args, **kwargs)
        placeholders = {
            'subscription_price': 'subscription_price',
            'subscription_plan': 'subscription_plan',
            'full_name': 'Full Name',
            'email': 'Email',
            'phone_number': 'Phone No.',
            'street_address1': 'Address 1',
            'street_address2': 'Address 2',
            'town_or_city': 'Town / City',
            'county': 'County',
            'postcode': 'Post Code',
            'country': 'Country',
        }

        """
        Subscription plan and price set as hidden fields, these will take
        their input values from the bag in the front end
        """
        self.fields['subscription_price'].widget = forms.HiddenInput()
        self.fields['subscription_plan'].widget = forms.HiddenInput()
        # On page load, cursor placed in full name field
        self.fields['full_name'].widget.attrs['autofocus'] = True
        # Add asterisk to any fields set as required /mandatory
        for field in self.fields:
            if self.fields[field].required:
                placeholder = f'{placeholders[field]} *'
            else:
                placeholder = placeholders[field]
            # Set fields to user friendly names defined above
            self.fields[field].widget.attrs['placeholder'] = placeholder
            # Applies consistant styles across form (inc. Stripe fields)
            self.fields[field].widget.attrs['class'] = 'stripe-style-input'
            # Remove default fields labels as placeholders will be used
            self.fields[field].label = False


'''
Created on 10 ene. 2017

@author: MariaJesus
'''
from POO.Ejercicio_2_Persona import Persona
class Cuenta (object):
    def __init__(self,saldo,pin):
        self.__saldo=saldo
        self.pin=pin
    def ingresar (self,cantidad):
        self.__saldo=self.__saldo+cantidad
        # print(self.__saldo)
    def  retirar (self,cantidad):
        if cantidad<self.__saldo:
            self.__saldo=self.__saldo-cantidad
            # print(self.__saldo)
        else:
            print("Error: Usted no dispone de la cantidad que solicita")
    def Leer_Saldo (self, Pin):
        if self.pin==Pin:
            print(self.__saldo)
        else:
            print("Error: El número PIN es incorrecto")
    def Desocultar_Saldo (self):
        return self.__saldo
#--------------------------------------------------------------------
class Cuenta_ahorro(Cuenta):
    def __avisar(self,cantidad):
        if cantidad>super(Cuenta_ahorro,self).Desocultar_Saldo():
            print("Numeros rojos")
    def avisar_a(self,cantidad):
        self.avisar_a(cantidad)
#--------------------------------------------------------------------
class Cliente(Persona,Cuenta_ahorro):
    def __init__(self,Nombre,DNI,direccion,tlf,email,saldo,pin):
        Persona.__init__(self, Nombre, DNI, direccion, tlf, email)
        Cuenta_ahorro.__init__(self, saldo, pin)
        self.credit=1000
    def mostar_datos (self):
        print(self.Nombre, self.DNI, self.direccion, self.tlf, self.Desocultar_Saldo(), self.credit)
        if self.email!="":
            print(self.email)
#--------------------------------------------------------------------
if __name__== '__main__':
#Programa principal
    cuenta1=Cuenta(0.0, 1313)
    cantidades=[125.00, 124.00,]
    for i in range (1):
        cuenta1.ingresar(cantidades[0])
    for i in range (1):
        cuenta1.retirar(cantidades[1])
pin=int(input("Escriba su pin por favor:"))
cuenta1.Leer_Saldo(pin)
persona1=Cliente("Antonio","24597852W","C/Socrates","958414141","antonioelshulo@gmail.com",5.0,pin)
#Segundo programa principal
persona1.mostar_datos()


# Day of the Year guessing game

# list of dates in the year
import random

month_names = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]
num_days_in_month = [31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]

# reformat a list of months and a list of days to become a massive list of every day in the year
def calendar(month_names, num_days_in_month):
    # checks if there is a corresponding amount of dates for every month
    if len(month_names) != len(num_days_in_month):
        return []

    dates = []
    idx = 0

    # loop for individually adding every day the the list "first"
    while idx < len(month_names):
        for date in range(1, num_days_in_month[idx] + 1):
            dates.append(month_names[idx] + " " + str(date))
        idx = idx + 1
    return dates

# runs the calender function to get the list of days
first = calendar(month_names, num_days_in_month)

def guess_game(first = calendar(month_names, num_days_in_month)):
    # finds the center of the list
    mid = len(first) // 2
    if first[mid] == "Jul 2":
        mid = random.randint(0, len(first) - 1)

    # gets the user input
    val = is_earlier(first[mid])

    if val == 1:
        # calls itself but this time with only the dates before the center
        return guess_game(first[:mid + 1])
    elif val == 2:
        # calls itself but this time with only the dates after the center
        return guess_game(first[mid - 1:])
    else:
        # computer guesses correctly
        return first[mid]

# takes the input and returns 1, 2 or 3 for earlier, later or equal and prints the date the computer guesses
def is_earlier(guess=10):
    return int(input("{}: 1 - earlier, 2 - later, 3 - equal?: ".format(guess)))

if __name__ == '__main__':
    print('Think of a specific date in any year')
    print('e.g., Jan 1 or Feb 29 or Jul 4 or Dec 25')
    print('Truthfully answer "Yes" or "No" to the following questions')
    print('I will determine the date in ten questions or less')

    print(guess_game())


# Use: Initiate/close problem.

# Import pyCAPS module (Linux and OSx = pyCAPS.so file; Windows = pyCAPS.pyd file)
import pyCAPS

# Instantiate our CAPS problem "myProblem"
print("Initiating capsProblem")
myProblem = pyCAPS.capsProblem()

# Close our problem
print("Closing our problem")
myProblem.closeCAPS()


import requests

class SudokuSolver:
    def create_empty_board(self):
        return [
            ['', '', '', '', '', '', '', '', ''],
            ['', '', '', '', '', '', '', '', ''],
            ['', '', '', '', '', '', '', '', ''],
            ['', '', '', '', '', '', '', '', ''],
            ['', '', '', '', '', '', '', '', ''],
            ['', '', '', '', '', '', '', '', ''],
            ['', '', '', '', '', '', '', '', ''],
            ['', '', '', '', '', '', '', '', ''],
            ['', '', '', '', '', '', '', '', '']
        ]

    def print_board(self, board):
        for i in range(len(board)):
            if i % 3 == 0 and i != 0:
                print('------------------------')

            for j in range(len(board[0])):
                if j % 3 == 0 and j != 0:
                    print(' | ', end='')

                if j == 8:
                    print(board[i][j])
                else:
                    print('{} '.format(board[i][j]), end='')

    def find_empty(self, board):
        for i in range(len(board)):
            for j in range(len(board[0])):
                if board[i][j] == 0:
                    return (i, j)

    def is_valid(self, num, pos, board):
        row, col = pos

        # Check row
        for i in range(len(board[0])):
            if board[row][i] == num and col != i:
                return False

        # Check column
        for i in range(len(board)):
            if board[i][col] == num and row != i:
                return False

        # Check box
        box_x = col // 3
        box_y = row // 3

        for i in range(box_y * 3, box_y * 3 + 3):
            for j in range(box_x * 3, box_x * 3 + 3):
                if board[i][j] == num and (i, j) != (row, col):
                    return False
        return True

    def solve(self, board):
        found = self.find_empty(board)
        if not found:
            return board
        row, col = found

        for i in range(1, 10):
            if self.is_valid(i, (row, col), board):
                board[row][col] = i

                if self.solve(board):
                    return board

                # Backtrack
                board[row][col] = 0

    def multidict_to_board(self, multidict):
        li = []
        for i in range(9):
            li.append(multidict[i * 9: (i + 1) * 9])
        return li

    def new_board(self, level):
        url = f'http://www.cs.utep.edu/cheon/ws/sudoku/new/?size=9&level={level}'

        resp = requests.get(url)
        data = resp.json()

        board_from_data = data['squares']

        if resp:
            def api_board_to_list(api_board):
                new_board = self.create_empty_board()
                for row in api_board:
                    y = row['y']
                    x = row['x']
                    val = row['value']
                    # Insert a value into a specific position
                    new_board[y][x] = val
                return new_board
            new_board = api_board_to_list(board_from_data)
        board = new_board
        return board


import heapq
def lastStoneWeight(stones):
        """
        :type stones: List[int]
        :rtype: int
        """
        stones = [-x for x in stones]
        heapq.heapify(stones)

        while len(stones) > 1:
            # Picking x and y stone which are heaviest
            y = heapq.heappop(stones)
            x = heapq.heappop(stones)

            # We don't need to do anything if x == y because we already popped x and y

            # If x != y, the stone of weight x is destroyed, and the stone of weight y has new weight y - x.
            if x != y:
                heapq.heappush(stones,y-x)

        if stones:
            return abs(stones[0])
        else:
            return 0

stones = [2,7,4,1,8,8,1]
print(lastStoneWeight(stones))


import numpy as np
import cv2

# Setting up framework for determining radius of skittles

def loadImage(filepath):
	 return cv2.imread(filepath)

def convertHSV(frame=None):
	return cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)

def GaussianBlur(frame=None):
	return cv2.blur(frame, (10, 10))

# Not currently being used.
def BinaryThreshold(frame=None):
	ret, thresh = cv2.threshold(frame, 127, 255, cv2.THRESH_BIN) # Use THRESH_TRUN?
	return thresh

def findCircles(frame=None):
	circles = None

	# Tweak these parameters
	circles = cv2.HoughCircles(frame, cv2.HOUGH_GRADIENT, 1, 20, param1=50, param2=30, minRadius=40, maxRadius=100)
	return circles

if __name__ == "__main__":

	filepath = "/home/cswain/Documents/skittles.jpg"
	img = loadImage(filepath)

	# Convert from BGR color channels to HSV
	hsv_img = convertHSV(img)

	# Split HSV image into different color channels
	h, s, v = cv2.split(hsv_img)

	# Apply Gaussian Blur to value
	smooth_img = GaussianBlur(s)

	circles = findCircles(smooth_img)

	print("There are: " + str(len(circles[0])) + " circles.")
	print("There are 26 skittles in the image")

	if circles.any():
		for i in circles[0,:]:
			# Draw outer circle
			cv2.circle(img, (i[0], i[1]), i[2], (0, 0, 255), 4)

			#Draw center of circle
			cv2.circle(img, (i[0], i[1]), 2, (0, 0, 255), 4)

	# Resize images to fit on screen
	img = cv2.resize(img, (0,0), None, .25, .25)
	s = cv2.resize(s, (0,0), None, .25, .25)
	smooth_img = cv2.resize(smooth_img, (0,0), None, .25, .25)

	# Can't concatenate img because it has 3 color dimensions
	horizontal_img_concat = np.concatenate((s, smooth_img), axis=1)

	cv2.imshow("Original photo", img)
	cv2.imshow("Horizontal Concatenation", horizontal_img_concat)
	cv2.waitKey(0)
	# cv2.imshow(hsv_img)

	cv2.destroyAllWindows()


# -*- coding: utf-8 -*-
"""
Created on Mon Aug 17 18:30:39 2015

@author: thomas.douenne
"""

import pandas as pd
from pandas import concat

import openfisca_france_indirect_taxation

TaxBenefitSystem = openfisca_france_indirect_taxation.init_country()
tax_benefit_system = TaxBenefitSystem()
legislation_json = tax_benefit_system.legislation_json

def get_prix_carburants(liste_carburants):
    prix_carburants = None
    for element in liste_carburants:
        prix_dict = \
            legislation_json['children']['imposition_indirecte']['children']['prix_carburants']['children'][element]
        df_prix = pd.DataFrame.from_dict(prix_dict['values'])

        df_prix['start'] = df_prix['start'].str[:4]
        del df_prix['stop']
        df_prix = df_prix.set_index('start')
        df_prix.rename(columns = {'value': 'prix ' + element.replace('_', ' ')}, inplace = True)

        if prix_carburants is not None:
            prix_carburants = concat([prix_carburants, df_prix], axis=1)
        else:
            prix_carburants = df_prix

    return prix_carburants