'''
พี่โบ๊ทได้ไปเล่นเกมนึง ที่ชื่อว่า Honkai: Star Rail ซึ่งเป็นเกมแนว Turn-Based แล้วพี่โบ๊ทได้ไปสนใจระบบ Combat นึงที่ใช้ค่า Speed (SPD) ของตัวละครซึ่งเป็นค่าบ่งบอกว่า ใครจะได้เทิร์นก่อน โดยวัดจากค่า Action
ซึ่งวิธีการคำนวณโดยการ เอา 10000 หารด้วย Speed จะได้เป็นค่า Action แล้วตอน Turn แรกใครมีค่า Action น้อยที่สุดจะได้เป็นคนเริ่มก่อน

เช่น
Boat มีค่า SPD 100 / Pune มีค่า SPD 115 / Yaya มีค่า SPD 120

ในก่อน Turn แรก
Boat จะมีค่า Action 10000 / 100 = 100
Pune จะมีค่า Action 10000 / 115 = 86 (หารแบบ int คือไม่เอาเศษ)
Yaya จะมีค่า Action 10000 / 120 = 83 (หารแบบ int คือไม่เอาเศษ)

Turn 1 Yaya จะได้เป็นคนเริ่มก่อนก็จะเป็น
0-Yaya
3-Pune
17-Boat

เมื่อจบ Action ก็ให้ค่า Action เท่ากับ 10000 / SPD เช่นเดิม
จากนั้น Turn ต่อไป Pune จะเป็นคนเริ่มเล่นต่อไปโดยทุกๆ คนจะหักลบค่า Action ของคนที่ได้เทิร์นถัดไป

Turn 2 ก็จะเป็น
0-Pune
14-Boat
80-Yaya

ไปเรื่อยๆ
ข้อมูลนำเข้า : <ค่า SPD> <ชื่อตัวละคร>/<จำนวนเทิร์น>
ข้อมูลนำออก : แสดงค่า Action และชื่อตัวละคร ตามลำดับที่ได้เทิร์น

หมายเหตุ: ห้ามใช้ฟังก์ชัน built-in สำเร็จรูปในการ sort เช่น .sort() sorted()
'''

def hiddensort(list):
    for i in range(1, len(list)):
        j = i
        while j > 0 and list[j][2] <= list[j-1][2]:
            if list[j][2] == list[j-1][2]:
                if list[j][0] > list[j-1][0]:
                    list[j], list[j-1] = list[j-1], list[j]
                    j-=1
                else:
                    break
            elif list[j][2] < list[j-1][2]:
                list[j], list[j-1] = list[j-1], list[j]
                j-=1
            else:
                break
    return list

characters, turns = input('Enter list of character: ').split('/')
characters = characters.split(',')
characters_stats = []
for c in characters:
    temp = []
    speed, character_name = c.split(' ')
    temp.append(int(speed))
    temp.append(character_name)
    temp.append(int(10000/temp[0]))
    characters_stats.append(temp)

result = hiddensort(characters_stats)
print('------------------------------')
for i in range(0, int(turns)):
    print(f'Turn {i+1}')
    index = i
    if index >= len(result):
        index -= len(result)
    next_action = result[0][2]
    for j in range(0, len(result)):
        result[j][2] -= next_action
        print(f'{result[j][2]}-{result[j][1]}')
    temp = result.pop(0)
    temp[2] = int(10000/temp[0])
    result.append(temp)
    result = hiddensort(result)
    print('------------------------------')


from boto_mock.dynamodb.layer1 import Layer1
from boto_mock.dynamodb.item import Item
from boto_mock.dynamodb.table import Table
from boto_mock.dynamodb.schema import Schema
from boto.dynamodb.batch import BatchWriteList
from boto_mock.dynamodb.types import get_dynamodb_type, dynamize_value

class Layer2(object):
    def __init__(self):
        self.layer1 = Layer1()

    def get_table(self, name):
        response = self.layer1.describe_table(name)
        return Table(self,  response)

    def create_table(self, name, schema, read_units, write_units):
        response = self.layer1.create_table(name, schema.dict)
        return Table(self,  response)

    def delete_table(self, table):
        response = self.layer1.delete_table(table.name)
        table.update_from_response(response)

    def create_schema(self, hash_key_name, hash_key_proto_value,
                    range_key_name=None, range_key_proto_value=None):
        schema = {}
        hash_key = {}
        hash_key['AttributeName'] = hash_key_name
        hash_key_type = get_dynamodb_type(hash_key_proto_value)
        hash_key['AttributeType'] = hash_key_type
        schema['HashKeyElement'] = hash_key
        if range_key_name and range_key_proto_value is not None:
            range_key = {}
            range_key['AttributeName'] = range_key_name
            range_key_type = get_dynamodb_type(range_key_proto_value)
            range_key['AttributeType'] = range_key_type
            schema['RangeKeyElement'] = range_key
        return Schema(schema)

    def put_item(self, item):
        response = self.layer1.put_item(item.table.name,
                                        item)
        return response

    def delete_item(self, item):
        return self.layer1.delete_item(item.table.name, item.hash_key, item.range_key)

    def query(self, table, hash_key, range_key_condition=None,
              scan_index_forward=True):
        if range_key_condition and range_key_condition.__class__.__name__ == 'BETWEEN':
            start = range_key_condition.v1
            end = range_key_condition.v2
        else:
            start = None
            end = None
        response = True
        n = 0
        response = self.layer1.query(table.name,
                                     hash_key,
                                     start, end,
                                     scan_index_forward)
        for item in response['Items']:
            yield Item(table, attrs=item)

    def scan(self, table):
        response = self.layer1.scan(table.name)
        if response:
            for item in response['Items']:
                yield Item(table, attrs=item)

    def new_batch_write_list(self):
        return BatchWriteList(self)

    def batch_write_item(self, batch_list):
        for batch in batch_list:
            for item in batch.puts:
                self.put_item(item)
        return {'UnprocessedItems': {}}


# MIT 6.034 Lab 2: Games
# Written by 6.034 staff

from game_api import *
from boards import *
from toytree import GAME1

INF = float('inf')

# Please see wiki lab page for full description of functions and API.

#### Part 1: Utility Functions #################################################

def is_game_over_connectfour(board):
    """Returns True if game is over, otherwise False."""
    for chain in board.get_all_chains():
        if len(chain) >= 4:
            return True

    true_count = 0
    for i in range(6):
        if board.is_column_full(i):
            true_count += 1

    return true_count == 6

def next_boards_connectfour(board):
    """Returns a list of ConnectFourBoard objects that could result from the
    next move, or an empty list if no moves can be made."""
    result = []
    if is_game_over_connectfour(board):
        return []
    for i in range(7):
        if not board.is_column_full(i):
            result.append(board.add_piece(i))
    return result

def is_connectfour(board):
    """Returns True if chain is four in a row."""
    for chain in board.get_all_chains():
        if len(chain) >= 4:
            return True

def endgame_score_connectfour(board, is_current_player_maximizer):
    """Given an endgame board, returns 1000 if the maximizer has won,
    -1000 if the minimizer has won, or 0 in case of a tie."""
    if not is_connectfour(board):
        return 0
    if is_current_player_maximizer:
        return -1000
    else:
        return 1000

def endgame_score_connectfour_faster(board, is_current_player_maximizer):
    """Given an endgame board, returns an endgame score with abs(score) >= 1000,
    returning larger absolute scores for winning sooner."""
    score = endgame_score_connectfour(board, is_current_player_maximizer)

    if not is_connectfour(board) or score == 0:
        return 0
    elif score < 0:
        return -1000 - (42 - board.count_pieces(True))
    else:
        return 1000 + (42 - board.count_pieces(False))

def heuristic_connectfour(board, is_current_player_maximizer):
    """Given a non-endgame board, returns a heuristic score with
    abs(score) < 1000, where higher numbers indicate that the board is better
    for the maximizer."""
    maximizer = heuristic_score_calculator(board, is_current_player_maximizer)
    minimizer = heuristic_score_calculator(board, not is_current_player_maximizer)
    return maximizer - minimizer

def heuristic_score_calculator(board, is_current_player_maximizer):
    score = 0
    scoring = {1: 1, 2: 10, 3: 100, 4: 500}
    for chain in board.get_all_chains(is_current_player_maximizer):
        chain_length = len(chain)
        score += scoring[chain_length]
    return score

# Now we can create AbstractGameState objects for Connect Four, using some of
# the functions you implemented above.  You can use the following examples to
# test your dfs and minimax implementations in Part 2.

# This AbstractGameState represents a new ConnectFourBoard, before the game has started:
state_starting_connectfour = AbstractGameState(snapshot = ConnectFourBoard(),
                                 is_game_over_fn = is_game_over_connectfour,
                                 generate_next_states_fn = next_boards_connectfour,
                                 endgame_score_fn = endgame_score_connectfour_faster)

# This AbstractGameState represents the ConnectFourBoard "NEARLY_OVER" from boards.py:
state_NEARLY_OVER = AbstractGameState(snapshot = NEARLY_OVER,
                                 is_game_over_fn = is_game_over_connectfour,
                                 generate_next_states_fn = next_boards_connectfour,
                                 endgame_score_fn = endgame_score_connectfour_faster)

# This AbstractGameState represents the ConnectFourBoard "BOARD_UHOH" from boards.py:
state_UHOH = AbstractGameState(snapshot = BOARD_UHOH,
                                 is_game_over_fn = is_game_over_connectfour,
                                 generate_next_states_fn = next_boards_connectfour,
                                 endgame_score_fn = endgame_score_connectfour_faster)

#### Part 2: Searching a Game Tree #############################################

# Note: Functions in Part 2 use the AbstractGameState API, not ConnectFourBoard.

def dfs_maximizing(state) :
    """Performs depth-first search to find path with highest endgame score.
    Returns a tuple containing:
     0. the best path (a list of AbstractGameState objects),
     1. the score of the leaf node (a number), and
     2. the number of static evaluations performed (a number)"""
    stack = [[state]]
    num_evals = 0
    path_score = None, None

    while stack!=[]:
        path = stack.pop()
        node = path[-1]

        next_states = node.generate_next_states()

        if next_states!=[]:
            for state in next_states:
                if state not in path:
                    stack.append(path + [state])
        else:
            node_score = node.get_endgame_score(is_current_player_maximizer=True)
            num_evals += 1

            if path_score == (None, None) or node_score > path_score[-1]:
                    path_score = path, node_score

    best_path = path_score[-2]
    score = path_score[-1]
    return (best_path, score, num_evals)

# Uncomment the line below to try your dfs_maximizing on an
# AbstractGameState representing the games tree "GAME1" from toytree.py:

# pretty_print_dfs_type(dfs_maximizing(GAME1))

def minimax_endgame_search(state, maximize=True) :
    """Performs minimax search, searching all leaf nodes and statically
    evaluating all endgame scores.  Same return type as dfs_maximizing."""
    result = []
    best_path = [state]
    num_evals = 1
    if state.is_game_over():
        score = state.get_endgame_score(maximize)
        return (best_path, score, num_evals)

    moves = state.generate_next_states()
    for move in moves:
        result.append(minimax_endgame_search(move,not maximize))
    num_evals = 0
    for i in result:
        num_evals += i[2]
    if maximize:
        result = max(result,key = lambda x: x[1])
    if not maximize:
        result = min(result,key = lambda x: x[1])

    score = result[1]
    best_path = [state] + result[0]
    return (best_path, score, num_evals)

# Uncomment the line below to try your minimax_endgame_search on an
# AbstractGameState representing the ConnectFourBoard "NEARLY_OVER" from boards.py:

# pretty_print_dfs_type(minimax_endgame_search(state_NEARLY_OVER))

def minimax_search(state, heuristic_fn=always_zero, depth_limit=INF, maximize=True) :
    """Performs standard minimax search. Same return type as dfs_maximizing."""
    result = []
    best_path = [state]
    num_evals = 1
    if state.is_game_over():
        score = state.get_endgame_score(maximize)
        return (best_path, score, num_evals)

    if depth_limit == 0:
        score = heuristic_fn(state.get_snapshot(),maximize)
        return (best_path, score, num_evals)

    moves = state.generate_next_states()
    for move in moves:
        result.append(minimax_search(move, heuristic_fn, depth_limit - 1, not maximize))
    num_evals = 0
    for i in result:
        num_evals += i[2]
    if maximize:
        result = max(result,key = lambda x: x[1])
    if not maximize:
        result = min(result,key = lambda x: x[1])

    score = result[1]
    best_path = [state] + result[0]
    return (best_path, score, num_evals)

# Uncomment the line below to try minimax_search with "BOARD_UHOH" and
# depth_limit=1. Try increasing the value of depth_limit to see what happens:

# pretty_print_dfs_type(minimax_search(state_UHOH, heuristic_fn=heuristic_connectfour, depth_limit=1))

def minimax_search_alphabeta(state, alpha=-INF, beta=INF, heuristic_fn=always_zero,
                             depth_limit=INF, maximize=True) :
    """"Performs minimax with alpha-beta pruning. Same return type
    as dfs_maximizing."""
    best_path = [state]
    num_evals = 1
    if state.is_game_over():
        score = state.get_endgame_score(maximize)
        return (best_path, score, num_evals)

    if depth_limit == 0:
        score = heuristic_fn(state.get_snapshot(),maximize)
        return (best_path, score, num_evals)

    if maximize:
        maxalpha = alpha
        bestresult = None
        result = []
        moves = state.generate_next_states()
        for move in moves:
            recurse =minimax_search_alphabeta(move, maxalpha, beta, heuristic_fn, depth_limit - 1, not maximize)
            result.append(recurse)
            minalpha = maxalpha
            maxalpha = max(maxalpha,recurse[1])
            if maxalpha != minalpha:
                bestresult = recurse
            if maxalpha >= beta:
                break

        num_evals = 0
        for i in result:
            num_evals += i[2]
        bestresult = max(result,key = lambda x: x[1])

        best_path = [state] + bestresult[0]
        score = bestresult[1]
        return (best_path, score, num_evals)

    if not maximize:
        result = []
        bestresult = None
        maxbeta = beta
        moves = state.generate_next_states()
        for move in moves:
            recurse = minimax_search_alphabeta(move, alpha, maxbeta, heuristic_fn, depth_limit - 1, not maximize)
            result.append(recurse)
            minbeta = maxbeta
            maxbeta = min(maxbeta,recurse[1])
            if maxbeta != minbeta:
                bestresult = recurse
            if maxbeta <= alpha:
                break

        num_evals = 0
        for i in result:
            num_evals += i[2]
        bestresult = min(result,key = lambda x: x[1])

        best_path = [state] + bestresult[0]
        score = bestresult[1]
        return (best_path, score, num_evals)

# Uncomment the line below to try minimax_search_alphabeta with "BOARD_UHOH" and
# depth_limit=4. Compare with the number of evaluations from minimax_search for
# different values of depth_limit.

# pretty_print_dfs_type(minimax_search_alphabeta(state_UHOH, heuristic_fn=heuristic_connectfour, depth_limit=4))

def progressive_deepening(state, heuristic_fn=always_zero, depth_limit=INF,
                          maximize=True) :
    """Runs minimax with alpha-beta pruning. At each level, updates anytime_value
    with the tuple returned from minimax_search_alphabeta. Returns anytime_value."""
    anytime_value = AnytimeValue()
    value = 0
    while value < depth_limit:
        anytime_value.set_value(minimax_search_alphabeta(state, -INF, INF, heuristic_fn,
                             value+1, maximize=True))
        value += 1
    return anytime_value

# Uncomment the line below to try progressive_deepening with "BOARD_UHOH" and
# depth_limit=4. Compare the total number of evaluations with the number of
# evaluations from minimax_search or minimax_search_alphabeta.

# progressive_deepening(state_UHOH, heuristic_fn=heuristic_connectfour, depth_limit=4).pretty_print()

# Progressive deepening is NOT optional. However, you may find that
#  the tests for progressive deepening take a long time. If you would
#  like to temporarily bypass them, set this variable False. You will,
#  of course, need to set this back to True to pass all of the local
#  and online tests.
TEST_PROGRESSIVE_DEEPENING = True
if not TEST_PROGRESSIVE_DEEPENING:
    def not_implemented(*args): raise NotImplementedError
    progressive_deepening = not_implemented

#### Part 3: Multiple Choice ###################################################

ANSWER_1 = '4'

ANSWER_2 = '1'

ANSWER_3 = '4'

ANSWER_4 = '5'

#### SURVEY ###################################################

NAME = "Marisa Papagelis"
COLLABORATORS = "Peyton Wang"
HOW_MANY_HOURS_THIS_LAB_TOOK = 20
WHAT_I_FOUND_INTERESTING = None
WHAT_I_FOUND_BORING = None
SUGGESTIONS = None


#!/usr/bin/env python3

from tensorflow.python.framework import ops
from deepmd.env import op_module
from deepmd.env import tf

@ops.RegisterGradient("Tanh2Nvnmd")
def _Tanh2NvnmdGrad(op, grad):
    isround = op.get_attr("isround")
    nbit1 = op.get_attr("nbit1")
    nbit2 = op.get_attr("nbit2")
    nbit3 = op.get_attr("nbit3")
    prec = 2 ** nbit2
    x = op.inputs[0]
    x_abs = tf.abs(x)
    x1 = tf.clip_by_value(x_abs, 0, 2)
    x2 = tf.clip_by_value(x_abs, 0, 4)
    dydx = (132-64*x1-x2) * 0.0078125
    if (nbit2 > -1):
        dydx = dydx + tf.stop_gradient( tf.floor(dydx * prec) / prec - dydx )
    dx = dydx * grad
    if (nbit2 > -1):
        dx = dx + tf.stop_gradient( tf.floor(dx * prec) / prec - dx )
    return dx


import time
import random
villains = ["Lurid Lake dragon", "moss troll", "demon of candor"]
villain = random.choice(villains)
weapons = ["Mythic Flail", "Hephaestus Halberd", "Grenade from "
                                                 "Colonel Luxembourg"]
weapon = random.choice(weapons)

def print_pause(message_to_print):
    print(message_to_print)
    time.sleep(1)

def intro(villain):
    print_pause("You find yourself standing in an open field, filled with "
                "grass and yellow wildflowers.")
    print_pause(f"Rumor has it that a {villain} is somewhere around here, "
                "and has been terrorizing the nearby village.")
    print_pause("In front of you is a house.")
    print_pause("To your right is a dark cave.")
    print_pause("In your hand you hold your trusty (but not very effective) "
                "dagger.\n")

def field(item, villain):
    while True:
        response = input("Enter 1 to knock on the door.\n"
                         "Enter 2 to peer into the cave.\n"
                         "What would you like to do?\n"
                         "(Please enter 1 or 2).\n")
        if response == '1':
            print_pause("You are about to knock when the door opens and "
                        f"out steps the {villain}.")
            house(item, villain)
            break
        elif response == '2':
            print_pause("You peer cautiously into the cave.")
            cave(item, weapon)
            break
        else:
            print_pause("(Please enter 1 or 2).\n")

def house(item, villain):
    print_pause(f"Whoa! This is the {villain}'s house!")
    print_pause(f"The {villain} attacks you!")
    while True:
        response = input("Would you like to (1) fight or (2) run away?\n")
        if response == '1':
            fight(item, villain, weapon)
            break
        elif response == '2':
            run_away(item)
            break

def cave(item, weapon):
    if "weapon" not in item:
        print_pause("It turns out to be only a very small cave.")
        print_pause("Your eye catches a glint of metal behind a rock.")
        print_pause(f"You have found the {weapon}!")
        print_pause("You discard your silly old dagger and take "
                    "the legendary weapon with you.")
        item.append("weapon")
        print_pause("You walk back out into the field.\n")
        field(item, villain)
    else:
        print_pause("You've been here before and gotten all the good stuff. "
                    "It's just an empty cave now.")
        print_pause("You walk back out into the field.\n")
        field(item, villain)

def fight(item, villain, weapon):
    if "weapon" in item:
        print_pause(f"As the {villain} moves to attack, "
                    "you raise your new weapon.")
        print_pause(f"The {weapon} shines brightly in your hand as you "
                    "brace yourself for the attack.")
        print_pause(f"But the {villain} takes one look at the "
                    "legendary weapon and runs away!")
        print_pause(f"You have rid the town of the {villain}. "
                    "You are victorious!")
        print_pause("GAME OVER")
        play_again()
    elif "weapon" not in item:
        print_pause("You feel a bit under-prepared for this, what "
                    "with only having a tiny dagger.")
        print_pause("You do your best...")
        print_pause(f"but your dagger is no match for the {villain}.")
        print_pause("You have been defeated!")
        print_pause("GAME OVER")
        play_again()

def run_away(item):
    print_pause("You run back to the field. Luckily, you don't "
                "seem to be followed.\n")
    field(item, villain)

def play_again():
    response = input("Would you like to play again? (y/n)\n").lower()
    if 'n' in response:
        print_pause("Thanks for playing! See you next time.")
    elif 'y' in response:
        print_pause("Excellent! Restarting the game.")
        play_game()
    else:
        play_again()

def play_game():
    item = []
    villain = random.choice(villains)
    weapon = random.choice(weapons)
    intro(villain)
    field(item, villain)

play_game()


# Make a list that contains all integers from 1 to 100,
# then find all integers from the list that are divisible by 7 but not a multiple of 5, and store them in a separate list.
# Finally, print the list.
# Constraint: use only while loop for iteration

list_1 = []
for x in range(1, 101):
    if x % 7 == 0 and x % 5 != 0:
        list_1.append(x)
print(list_1)

c = 0
list_2 = []
while c < 100:
    if c % 7 == 0 and c % 5 != 0:
        list_2.append(c)
    c += 1

print(list_2)

start_list = list(range(1,101))
c = 1
list_3 = []
while c < len(start_list):
    if c % 7 == 0 and c % 5 != 0:
        list_3.append(c)
    c += 1

print(list_3)


#Gameboard
#Author: Dominic Martindale
#Date 6/06/2019
#About: A class which creates a grid based 'game
#       board' in which ships can be placed onto.

from Position import Position

#Acts as a container for the game data which can be updated with new data.
class Gameboard:

    # constructor does setting
    def __init__(self, x_size, y_size, all_positions=None):
        self.__x = x_size
        self.__y = y_size

        #If all_postions is not specified, the gameboard will
        # create 25 instances of the position obj
        if all_positions == None:
            self.__all_positions = self.create_positions()
        else:
            self.__all_positions = all_positions

    @property # getter
    def x(self):
        return self.__x

    @property # getter
    def y(self):
        return self.__y
    # x and y setters in constructor

    @property #getter
    def all_positions(self):
        return self.__all_positions

    #Create positions based off of x and y (automated setter)
    def create_positions(self):
        x_counter = 1
        y_counter = 1
        my_list = []
        #for how many units in y (column)
        for x in range(int(self.y)):
            #for how many units in x (row)
            for x in range(int(self.x)):
                #Create a position, then append it and increment x
                new_pos = Position(x_counter, y_counter)
                my_list.append(new_pos)
                x_counter += 1
            #When x loop has finished row, increment column and reset x
            x_counter = 1
            y_counter += 1
        #Return all positions
        return my_list

    #update positon's is_occupied value to specified bool
    def update_position(self, check_position, input_bool):
        p = check_position
        n = 0 #counter

        #check for correct input of bool, continue if fine
        if type(input_bool) == bool:
            for x in self.all_positions:
                #Compares x and y values of check-pos against current co-ord in list
                if p.y == self.all_positions[n].y and p.x == self.all_positions[n].x:
                    #Change match to new boolean
                    self.all_positions[n].is_occupied = input_bool
                    break
                n +=1
            else:
                #Iterated through whole list and found no matches
                return False
        else:
            #bool not bool input
            return False

    #Checks to see if the position is taken in the gameboard
    #Returns false if taken, true if not taken.
    #Also returns false if co-ords are non-existant on the gameboard.
    def is_valid_position(self, check_position):
        p = check_position
        n = 0 #counter

        for i in self.all_positions:
            #Compares x and y values of check-pos against current co-ord in list
            if p.y == self.all_positions[n].y and p.x == self.all_positions[n].x:
                if self.all_positions[n].is_occupied == True:
                    return False
                else:
                    #Co-ords are a match to existing one on gameboard
                    #and it isnt occupied - valid position
                    return True
            n += 1

        else:
            #Iterated through whole list and found no matches
            return False


import json
from odoo import api, fields, models, _

class AsteriskBaseSettings(models.TransientModel):
    _inherit = 'res.config.settings'
    _name = 'asterisk.settings'

    no_asterisk = fields.Boolean(string='No Asterisk',
        help='When this is set all communication with Asterisk is considered successful.\n'
             'This can be used to test the management interface without errors when '
             'there is not Asterisk server connected.')

    @api.multi
    def set_params(self):
        self.ensure_one()
        self.env['ir.config_parameter'].set_param('asterisk_base.no_asterisk',
                                                  self.no_asterisk)

    def get_default_params(self, fields):
        res = {}
        res['no_asterisk'] = self.env['ir.config_parameter'].get_param(
                                        'asterisk_base.no_asterisk', '').strip()
        return res

    def reload_ami_broker(self):
        self.ensure_one()
        self.env['bus.bus'].sendone('ami_broker',
                                    json.dumps({'command': 'reload'}));


def last_indexof_max(numbers):
    ind = -1
    top = -100000
    for i in range(len(numbers)):
        if numbers[i] >= top:
            top = numbers[i]
            ind = i
    return ind

    # write the modified algorithm here


from logger import log, GameError
from maptraveler import MapTraveler
from pysikuli import Region
from src.config import CONFIG
import pyautogui as pyag
from time import sleep
import random

class Character:
    def __init__(self, maptraveler):
        self.maptraveler = maptraveler
        self.matcher = Region()

    def teleport_to(self, direction, distance, sleep_time=0.25, offset=None, mode="normal"):
        log.debug("Teleport start")
        direction_location_x, direction_location_y = MapTraveler.MOVE_DIRECTIONS[direction]
        center_x, center_y = CONFIG["CENTER_LOCATION"]

        if offset is not None:
            direction_location_x, direction_location_y = direction_location_x + offset[0], \
                                                         direction_location_y + offset[1]
        teleport_location = MapTraveler.get_move_location(direction_location_x - center_x,
                                                          direction_location_y - center_y, (distance, distance))

        log.debug("Teleport location: " + str(teleport_location))
        if mode == "normal":
            self.matcher.click(teleport_location, button="right")
        elif mode == "continuous":
            pyag.moveTo(teleport_location)
            pyag.mouseDown(button='right')
        sleep(sleep_time)
        if mode == "continuous":
            pyag.mouseUp(button='right')
        log.debug("Teleport end")

    def go_to_destination(self, destination, shift=None, move_step=(250, 350), accepted_distance=20, steps_timeout=30,
                          critical=True, map_filter=False, button="left", move_sleep=0.1):
        step = 0
        error_counter = 0
        waypoints_found = 0
        log.info("Going to destination " + str(destination))
        while True:
            step += 1
            log.info("Started moving loop nr " + str(step))
            if step > steps_timeout:
                log.error("Timeout when going to " + str(destination))
                if critical:
                    raise GameError("Timeout when going to " + str(destination))
                else:
                    log.warning("This is not critical.")
                    return False
            # Checking blockers
            try:
                if Region(*CONFIG["WAYPOINT_REGION"]).exists("images/waypoint.png", 0.1, debug=False):
                    log.warning("Waypoint image found. Closing it.")
                    pyag.press("esc")
                    waypoints_found += 1
                    if waypoints_found % 5 == 4:
                        Region().click((1251,1007))
                        sleep(2)
            except:
                log.warning("Waypoint issue found. Repeating.")
            log.info("Waypoint checked.")

            self.maptraveler.update_screen()
            diff_location = self.maptraveler.get_diff_from_destination(destination, shift=shift,
                                                                       map_filter=map_filter)
            # Error counter is used to do not fail function if we do not detect image in single iteration.
            if diff_location is None:
                log.warning("Cannot find destination.")
                sleep(0.2)
                if error_counter == 30:
                    return False
                else:
                    error_counter += 1
                    continue
            else:
                diff_location_x, diff_location_y = diff_location

            error_counter = 0
            if abs(diff_location_x) > accepted_distance or abs(diff_location_y) > accepted_distance:
                move_location = MapTraveler.get_move_location(diff_location_x, diff_location_y, move_step)
                self.matcher.click(move_location, button=button)
                sleep(move_sleep)
            else:
                log.info("Destination reached.")
                return True

    def hover_destination(self, destination, hover_image, dest_shift=None, special_shift=None):
        hover_destination_timeout = 0
        while True:
            log.info("hover_destination nr " + str(hover_destination_timeout))
            hover_destination_timeout += 1
            if hover_destination_timeout > 5:
                log.error("Failed to find " + str(hover_image))
                return False
            find_map_destination_timeout = 0
            while True:
                find_map_destination_timeout += 1
                if find_map_destination_timeout > 20:
                    log.error("Timeout when hovering destination" + str(destination))
                    raise GameError("Timeout when hovering destination" + str(destination))

                log.debug("Trying to find location nr " + str(find_map_destination_timeout))
                diff_location = self.maptraveler.get_diff_from_destination(destination,
                                                                           shift=dest_shift)
                if diff_location is not None:
                    diff_location_x, diff_location_y = diff_location
                    break

            center_x, center_y = CONFIG["CENTER_LOCATION"]

            finding_shifts = [(0, 0), (100, 0), (-100, 0), (0, 100), (0, -100), (100, 100), (100, -100), (-100, 100),
                              (-100, -100),
                              (200, 0), (-200, 0), (0, 200), (0, -200), (200, 200), (200, -200), (-200, 200),
                              (-200, -200),
                              (200, 100), (-200, 100), (100, 200), (100, -200), (200, -100), (-200, -100), (-100, 200),
                              (-100, -200),
                              (0, 250), (250, 0), (-250, 0), (0, -250), (250, 250), (250, -250), (-250, 250),
                              (-250, -250)]

            if special_shift is not None:
                special_shift_x, special_shift_y = special_shift
            else:
                special_shift_x, special_shift_y = (0, 0)

            for shift in finding_shifts:
                shift_x, shift_y = shift
                checking_location = (center_x + (diff_location_x * 15) + shift_x + special_shift_x,
                                     center_y + (diff_location_y * 15) + shift_y + special_shift_y)
                self.matcher.hover(checking_location)
                sleep(0.05)
                if self.matcher.exists(hover_image, 0.05):
                    log.info("Found {} on location {}".format(hover_image, checking_location))
                    return True

    def enter_destination(self, destination, hover_image, final_image, dest_shift=None, special_shift=None):
        enter_max_attempts = 5
        enter_timeout = 0
        while True:
            enter_timeout += 1
            # Check if no other npc was clicked not intentionally
            if Region(856, 219, 1268, 673).exists("images/cancel.png", 0.1):
                pyag.press("esc")
            if enter_timeout > enter_max_attempts:
                log.error("Timeout when entering " + str(destination))
                raise GameError("Timeout when entering " + str(destination))
            if self.hover_destination(destination, hover_image, dest_shift, special_shift):
                log.info("Destination found.")
                pyag.click()
                sleep(1)
                if Region().exists(final_image, 5):
                    log.info("Destination entered correctly.")
                    return True
                else:
                    log.warning("Failed to enter destination.")

    def goto_entrance(self):
        log.info("Going to located entrance")
        timeout_counter = 0
        while True:
            char_location = self.maptraveler.get_char_location()

            if timeout_counter > 20:
                log.error("Timeout when going to entrance.")
                return False, None

            # Check entrance position
            entrance_location = self.maptraveler.get_entrance_location()
            if entrance_location is None:
                timeout_counter += 1
                sleep(0.3)
                log.warning("Cannot find entrance location nr " + str(timeout_counter))
                continue

            log.info("Character location: {} Entrance location: {}".format(char_location, entrance_location))

            # Go to entrance possition
            entrance_x, entrance_y = entrance_location
            char_x, char_y = char_location
            if abs(entrance_x - char_x) > 40 or abs(entrance_y - char_y) > 30:
                tele_location = self.maptraveler.get_tele_location(char_location, entrance_location)
                self.maptraveler.click(tele_location, button='right')
                sleep(0.7)
                if timeout_counter > 5:
                    self.matcher.click(random.choice(list(MapTraveler.MOVE_DIRECTIONS.values())), button="right")
                    sleep(1)
            else:
                sleep(1)
                if self.hover_destination(([149, 41, 98], [235, 101, 223]), "images/dur.png"):
                    log.info("Entrance hovered")
                    if self.matcher.exists("images/3.png", threshold=0.9):
                        log.info("Entering entrance")
                        self.matcher.click(None)
                    else:
                        log.warning("Wrong entrance found.")
                        return False, self.maptraveler.get_entrance_image()
                    if Region(2162, 17, 383, 131).exists("images/indurance3.png", 5, threshold=0.9):
                        log.info("Destination entered correctly.")
                        return True, None
                    else:
                        log.info("Failed to enter durance level 3.")
                        return False, None
                else:
                    log.error("Cannot find durance description of entrance")
            timeout_counter += 1

def main():
    log.info("Character test")
    sleep(2)
    traveler = MapTraveler()
    character = Character(traveler)
    character.enter_destination("images/malah.png", "images/malah_destination.png", "images/trade.png",
                                special_shift=(70, 200))

def waypoint_test():
    log.info("Waypoint test start.")
    sleep(2)
    if Region(*CONFIG["WAYPOINT_REGION"]).exists("images/waypoint.png", 0.1):
        log.warning("Waypoint image found. Closing it.")
        pyag.press("esc")

if __name__ == '__main__':
    waypoint_test()
    #main()


#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
# Ringtail results manager
#

from .mpmanager import MPManager
from .exceptions import ResultsProcessingError
from .storagemanager import StorageManager, StorageManagerSQLite
import typing
import logging

class ResultsManager:
    def __init__(
        self,
        storageman: StorageManager,
        storageman_class: StorageManager = StorageManagerSQLite,
        parser_manager: str = "multiprocessing",
        mode: str = "dlg",
        chunk_size: int = 1,
        max_poses: int = 3,
        interaction_tolerance: float = None,
        store_all_poses: bool = False,
        target: str = None,
        add_interactions: bool = False,
        interaction_cutoffs: list = [3.7, 4.0],
        receptor_file: str = None,
        file_sources: dict = {
            "file": [[]],
            "file_path": {"path": [[]], "pattern": "*.dlg*", "recursive": None},
            "file_list": [[]],
        },
        file_pattern: str = "*.dlg*",
        max_proc: int = None,
        _stop_at_defaults=False,
    ):

        self.parser_manager = parser_manager
        self.mode = mode
        self.chunk_size = chunk_size
        self.max_poses = max_poses
        self.store_all_poses = store_all_poses
        self.interaction_tolerance = interaction_tolerance
        self.target = target
        self.add_interactions = add_interactions
        self.interaction_cutoffs = interaction_cutoffs
        self.receptor_file = receptor_file
        self.file_sources = file_sources
        self.file_pattern = file_pattern
        self.max_proc = max_proc
        if _stop_at_defaults:
            return

        self.storageman = storageman

    def process_results(self):
        # check that we have file source(s)
        if (
            self.file_sources["file"] == [[]]
            and self.file_sources["file_path"]["path"] == [[]]
            and self.file_sources["file_list"] == [[]]
        ):
            raise ResultsProcessingError(
                "No file sources given. File sources must be given for writing results to database."
            )
        # start MP process
        logging.debug(self.file_sources)

        # NOTE: if implementing a new parser manager (i.e. serial) must add it to this dict
        implemented_parser_managers = {
            "multiprocessing": MPManager,
        }
        parser_opts = {}
        for k, v in self.__dict__.items():
            if k == "parser_manager":
                continue
            parser_opts[k] = v
        self.parser = implemented_parser_managers[self.parser_manager](**parser_opts)
        self.parser.process_files()

    @classmethod
    def get_defaults(cls):
        return cls(None, _stop_at_defaults=True).__dict__

    @classmethod
    def get_default_types(cls):
        return typing.get_type_hints(cls.__init__)


# -*- coding: utf-8 -*-

global commonInfos
commonInfos = ["Title", "Channel", "Artist", "Vocal", "Arrangement",
               "Lyric", "Circle", "Album", "Release Date", "Translation",
               "Original artist", "Original source", "Remix", "Website", "Original",
               "Illustration", "Guitar", "Bass", "Drum", "Source",
               "Length", "Event", "Genre", "Character"]
seperators = ["：", ":", " - "]

def patchInfo(info):
  # -uIgSe40BaM
  # I can't imagine such an exception occured.
  info = info.replace("Lyricss", "Lyric")

  # sRvtSH1_H0w
  info = info.replace("Released Date", "Release Date")

  # l4GQYBI4DBM
  info = info.replace("track name", "Title").replace("arranged by", "Arrangement").replace("album:", "Album:")

  # uSgHhzcvHfM
  info = info.replace("Vo:", "Vocal:").replace("Arrange:", "Arrangement:").replace("Arrange：", "Arrangement：")

  # -OzNzdlsocw
  info = info.replace("Vocals", "Vocal").replace("Lyrics", "Lyric").replace("Artwork", "Illustration")

  # mVYKcTxKro0
  info = info.replace("Arranger", "Arrangement").replace("Remixed by", "Remix").replace("Picture source", "Illustration")

  # 6zG5hmr-RvY
  info = info.replace("image", "Image").replace("Image", "Illustration").replace("歌詞／Lyric", "")

  # Turns out we replaced quite some URL by accident
  info = info.replace("/Illustration/", "/image/").replace("-Illustration/", "-image/") .replace("Illustration.", "image.")

  # l_rBFAJo1e0
  info = info.replace("Song:", "Title:")

  # jTgYtkc4kgg
  info = info.replace("Song title", "Title").replace("Original song", "Original").replace("Translated by", "Translation")\
             .replace("HP:", "Website:")

  # l_rBFAJo1e0
  info = info.replace("Original theme:", "Original:")

  # yI-5_nAJNpI
  info = info.replace("title:", "Title:").replace("length:", "Length:").replace("arrangement:", "Arrangement:")\
             .replace("vocal:", "Vocal:").replace("original:", "Original:").replace("source:", "Source:")\
             .replace("PV:", "Illustration:")

  # XO3JH6NdyDQ
  info = info.replace("Released:", "Release Date:")

  # FyVXpCSjApg
  info = info.replace("Pic source:", "Illustration:").replace("original Title:", "")

  # Qu_OzBsgRcI
  info = info.replace("Album Genre:", "Genre:").replace("Illustration Source:", "Illustration:")

  # lCQ7WuYXIHg
  info = info.replace("TITLE:", "Title:").replace("lyrics:", "Lyric:").replace("Original title:", "Original:")

  # hRmrbi8wDb0
  info = info.replace("Vocals by:", "Vocal:").replace("Lyrics by:", "Lyric:").replace("Arrangement by:", "Arrangement:")\
             .replace("Album name:", "Album:").replace("Circle name:", "Circle:").replace("Original Song", "Original")\
             .replace("Picture by:", "Illustration:")

  # _Zjhu4OfY6s
  info = info.replace("Release:", "Release Date:")

  # Ko7KQi6O3uk
  info = info.replace("Sources:", "Source:").replace("Picture Artist", "Illustration")

  # Jn8V7rWKfzA
  info = info.replace("Illustration Credit:", "Illustration:")

  # rwZIRobKIic
  info = info.replace("Song Titel:", "Title:")

  # CURT6c73UZY
  info = info.replace("Illustration Source：", "Illustration：").replace("Original Title：", "Original：")

  # -56E9ABZmtY
  info = info.replace("Original theme:", "Original:").replace("Picture:", "Illustration:")

  # Ak8AFx3pWSA
  info = info.replace("Picture artist:", "Illustration:")

  # jq77hb2OVOs
  info = info.replace("Imagen de:", "Illustration:")

  # 0QtGIK1fS4k
  info = info.replace("Publisher：", "Circle：").replace("Album Genre：", "Genre：").replace("Picture Artist：", "Illustration：")

  # 4m5q-NMfYIE
  info = info.replace("circle:", "Circle:").replace("translation:", "Translation:")

  # y30xoRA25jM
  info = info.replace("Release event:", "Event:").replace("Pics:", "Illustration:")

  # jSjUwprO0ok
  info = info.replace("Site:", "Website:").replace("Illust:", "Illustration:")

  # T6rFlUUKumY
  info = info.replace("Illust：", "Illustration：").replace("Original Composer:", "").replace("Original Composer：", "")

  # R8keaV4EDp8
  info = info.replace("illustration：", "Illustration：")

  # 3FWwrKVc3Pc
  info = info.replace("Titre :", "Title :")

  return info

def stripKeyword(line, keyword):
  for seperator in seperators:
    if seperator in line:
      return seperator.join(line.split(seperator)[1:]).strip()

  return keyword.join(line.split(keyword)[1:]).strip()

def commonDetection(lines, keywords, channelName):
  ret = {}
  mengYueWorkaround = "這是" in lines[0]
  for i in range(len(lines)):
    line = lines[i]

    # eVyR48O26BA
    if "Track List" in line:
      return {}

    for keyword in keywords:
      if keyword not in ret and keyword in line:
        if mengYueWorkaround and i < 2:
          continue
        parsed = stripKeyword(line, keyword)
        if len(parsed) > 0:
          ret[keyword] = parsed

  return ret

def detectMultiline(lines, keyword):
  ret = []
  begin = False
  for line in lines:
    if not begin:
      if "Original" in line and any(sep in line for sep in seperators):
        begin = True
        ret.append(stripKeyword(line, keyword))
    elif len(line.strip()) > 0 and ((not any(sep in line for sep in seperators)) or "Original" in line):
      ret.append(line.strip())
    else:
      break
  return {keyword: ret} if len(ret) > 0 else {}

def illustrationParser(lines):
  ret = []
  for i in range(len(lines)):
    if "Illustration" in lines[i]:
      ret.append(stripKeyword(lines[i], "Illustration"))
      try:
        while "http" in lines[i + 1]:
          ret.append(lines[i + 1])
          i += 1
      except Exception:
        pass
      finally:
        break
  return {"Illustration": ret} if len(ret) > 0 else {}

parsers = [
  lambda lines, channelName: commonDetection(lines, commonInfos, channelName),
  lambda lines, channelName: detectMultiline(lines, "Original"),
  lambda lines, channelName: illustrationParser(lines),
  lambda lines, channelName: {"Channel": channelName, "Raw Description": lines}
]

def parseVideoInfo(info, channelName):
  info = patchInfo(info).split("\n")

  ret = {}
  for parser in parsers:
    ret = {**ret, **parser(info, channelName)}

  return ret


from flask import *
from . import db
from .models import *
import datetime
teacher = Blueprint('teacher',__name__)

@teacher.route('/',methods=["GET"])
def dashboard():
    if session.get('name'):
        c_s = Course.query.filter_by(teacher_id = session.get('id')).all()
        return render_template('teacher/dashboard.html', courses=c_s,name=session.get('name'))
    else:
        return redirect('auth.login')

@teacher.route('/course',methods=['GET'])
def course():
    if session.get('name'):
        if request.args.get('id'):
            session['course']= request.args.get('id')
            c = Course.query.get(request.args.get('id'))
            e_s = Exam.query.filter_by(course_id=c.id)
            return render_template('teacher/course.html',course = c,exams=e_s)
        else:
            c = Course.query.get(session['course'])
            e_s = Exam.query.filter_by(course_id=c.id)
            return render_template('teacher/course.html',course = c,exams=e_s)
    else:
        return redirect(url_for('auth.login'))

@teacher.route('/exam',methods=['GET','POST'])
def exam():
    if session.get('name'):
        if request.method == 'GET':
            return render_template('teacher/exam.html')
        else:
            for key,value in request.form.items():
                if not value or value=='':
                    flash('Missing '+key+'!')
                    return redirect(url_for('teacher.exam'))
            e = Exam(
                course_id = session.get('course'),
                title = request.form.get('title'),
                date = datetime.datetime(
                    int(request.form.get('date').split('-')[0]),
                    int(request.form.get('date').split('-')[1]),
                    int(request.form.get('date').split('-')[2]),
                    int(request.form.get('time').split(':')[0]),
                    int(request.form.get('time').split(':')[1])),
                number_of_questions = request.form.get('number_of_questions'),
                duration = request.form.get('duration'),
                max_score = request.form.get('max_score')
            )
            db.session.add(e)
            db.session.commit()
            flash('Added Exam Successfully!')
            session['nq'] = int(request.form.get('number_of_questions'))
            session['q'] = 1
            session['exam'] = e.id
            return redirect(url_for('teacher.question'))
    else:
        return redirect(url_for('auth.login'))

@teacher.route('/question',methods=['GET','POST'])
def question():
    if session.get('name'):
        if request.method == 'GET':
            if session.get('q') <= session.get('nq'):
                return render_template('teacher/question.html')
            else:
                flash('All Questions Saved!')
                return redirect(url_for('teacher.question'))
        else:
            for key,value in request.form.items():
                if not value:
                    flash('Missing '+key+' !')
                    return redirect(url_for('teacher.question'))
            q = Question(
                exam_id = session.get('exam'),
                order = session.get('q'),
                body = request.form.get('body'),
                option_1 = request.form.get('option1'),
                option_2 = request.form.get('option2'),
                option_3 = request.form.get('option3'),
                option_4 = request.form.get('option4'),
                answer = request.form.get('answer')
            )
            db.session.add(q)
            db.session.commit()
            flash('Question '+str(session.get('q'))+' Saved Successfully!')
            session['q'] = session.get('q')+1
            if session.get('q') > session.get('nq'):
                flash('All Question Saved!')
                return redirect(url_for('teacher.exam'))
            return redirect(url_for('teacher.question'))
    else:
        return redirect(url_for('auth.login'))

@teacher.route('/scores',methods=['GET'])
def scores():
    if session.get('name'):
        e_i = request.args.get('exam_id')
        scs = Test_score.query.filter_by(exam_id=e_i)
        scs_list = []
        for i in scs:
            scs_list.append((i,User.query.get(i.student_id)))
        return render_template('teacher/scores.html', scores=scs_list)
    else:
        return redirect(url_for('auth.login'))


import sys
class station:
    def __init__(self):
        with open(sys.path[0] + '\\station_names.dat','r') as file:
            station_names = file.read()
        #print(station_names)
        #station_names = station_names.decode('gbk')
        self.station_list = {}
        for item in [x for x in station_names.split('@') if len(x) != 0 ]:
            tmp = item.split('|')
            self.station_list[tmp[2]] = tmp
        del station_names

    def id2name(self, id):
        return self.station_list[id][1]
    def name2id(self, name):
        for item in self.station_list.values():
            if item[1] == name:
                return item[2]
        return 'BJP'
if __name__ == '__main__':
    #print(sys.path)
    sta = station()
    print(sta.name2id('邢台'))
    print(sta.id2name('BJP'))


"""
Спиральная матрица n x n
stepic.org

Выведите таблицу размером n×n, заполненную числами от 1 до n^2 по спирали, выходящей из левого верхнего угла
и закрученной по часовой стрелке:
"""

n = int(input())
matrix = [[0 for j in range(n)] for i in range(n)]                    # создание матрицы n*n, заполненной нулями
matrix[0][0] = 1                                                      # точка отсчета для первого круга
for a in range(0, n // 2):                                            # переменная a в цикле будет "сжимать" круг сверху, снизу, слева и справа
  if matrix[a][a] == 0: matrix[a][a] = matrix[a][a - 1] + 1           # точка отсчета для 2+ круга
  for j in range(a + 1, n - a):                                       # заполнение строки слева направо -->
    matrix[a][j] = matrix[a][j-1] + 1
  for i in range(a + 1, n - a):                                       # заполнение столбца  сверху вниз
    matrix[i][j] = matrix[i - 1][j] + 1
  for j in range(n - 2 - a, a - 1, -1):                               # заполнение строки справа налево <---
    matrix[i][j] = matrix[i][j + 1] + 1
  for i in range(n - 2 - a, a, -1):                                   # заполнение столбца снизу вверх. Один круг заполнен!
    matrix[i][j] = matrix[i + 1][j] + 1
if matrix[n // 2][n // 2] == 0:
    matrix[n // 2][n // 2] = n ** 2                                   # для нечетного n заполняем последнюю нулевую ячейку
for raw in matrix:                                                    # вывод на печать
  print(*raw)


"""
Ejercicio 3.0.2¶

Dado que fruta es una variable de tipo cadena, ¿qué significa fruta[:]?
"""

def explicacion_ejercicio(palabra: str) -> str:
    explicacion = (f"Teniendo la palabra {palabra}, sabemos que es una cadena. "
    f"El significado de '{palabra}[:]' es lo mismo,\n"
    f"lo obviamente diferente '[:]' es para aplicar la operación"
    f"'slicing' (rebanado), por la cual se extraen\n"
    f"elementos a la cadena u otras secuencias")
    return explicacion

if __name__ == "__main__":
    # Proceso
    explicado = explicacion_ejercicio("fruta")
    # Salida
    print(explicado)


import os
import pathlib
import platform
import shutil
import subprocess
import sys
import warnings
from copy import deepcopy
from dataclasses import dataclass
from io import TextIOWrapper
from typing import Any, List, Optional, Tuple

from mlir_quantum.compiler_driver import run_compiler_driver

from catalyst._configuration import INSTALLED
from catalyst.utils.exceptions import CompileError
from catalyst.utils.filesystem import Directory

package_root = os.path.dirname(__file__)

@dataclass
class CompileOptions:
    """Generic compilation options, for which reasonable default values exist.

    Args:
        verbose (Optional[bool]): flag indicating whether to enable verbose output.
            Default is ``False``
        logfile (Optional[TextIOWrapper]): the logfile to write output to.
            Default is ``sys.stderr``
        keep_intermediate (Optional[bool]): flag indicating whether to keep intermediate results.
            Default is ``False``
        pipelines (Optional[List[Tuple[str,List[str]]]]): A list of tuples. The first entry of the
            tuple corresponds to the name of a pipeline. The second entry of the tuple corresponds
            to a list of MLIR passes.
        autograph (Optional[bool]): flag indicating whether experimental autograph support is to
            be enabled.
        lower_to_llvm (Optional[bool]): flag indicating whether to attempt the LLVM lowering after
            the main compilation pipeline is complete. Default is ``True``.
    """

    verbose: Optional[bool] = False
    logfile: Optional[TextIOWrapper] = sys.stderr
    target: Optional[str] = "binary"
    keep_intermediate: Optional[bool] = False
    pipelines: Optional[List[Any]] = None
    autograph: Optional[bool] = False
    lower_to_llvm: Optional[bool] = True

    def __deepcopy__(self, memo):
        """Make a deep copy of all fields of a CompileOptions object except the logfile, which is
        copied directly"""
        return CompileOptions(
            **{
                k: (deepcopy(v) if k != "logfile" else self.logfile)
                for k, v in self.__dict__.items()
                if k != "logfile"
            }
        )

    def get_pipelines(self) -> List[Tuple[str, List[str]]]:
        """Get effective pipelines"""
        return self.pipelines if self.pipelines is not None else DEFAULT_PIPELINES

def run_writing_command(command: List[str], compile_options: Optional[CompileOptions]) -> None:
    """Run the command after optionally announcing this fact to the user.

    Args:
        command (List[str]): command to be sent to a subprocess.
        compile_options (Optional[CompileOptions]): compile options.
    """

    if compile_options.verbose:
        print(f"[SYSTEM] {' '.join(command)}", file=compile_options.logfile)
    subprocess.run(command, check=True)

default_lib_paths = {
    "llvm": os.path.join(package_root, "../../mlir/llvm-project/build/lib"),
    "runtime": os.path.join(package_root, "../../runtime/build/lib"),
    "enzyme": os.path.join(package_root, "../../mlir/Enzyme/build/Enzyme"),
}

def get_lib_path(project, env_var):
    """Get the library path."""
    if INSTALLED:
        return os.path.join(package_root, "lib")  # pragma: no cover
    return os.getenv(env_var, default_lib_paths.get(project, ""))

DEFAULT_PIPELINES = [
    (
        "HLOLoweringPass",
        [
            "canonicalize",
            "func.func(chlo-legalize-to-hlo)",
            "stablehlo-legalize-to-hlo",
            "func.func(mhlo-legalize-control-flow)",
            "func.func(hlo-legalize-to-linalg)",
            "func.func(mhlo-legalize-to-std)",
            "convert-to-signless",
            "func.func(scalarize)",
            "canonicalize",
            "scatter-lowering",
        ],
    ),
    (
        "QuantumCompilationPass",
        [
            "lower-gradients",
            "adjoint-lowering",
        ],
    ),
    (
        "BufferizationPass",
        [
            "one-shot-bufferize{dialect-filter=memref}",
            "inline",
            "gradient-bufferize",
            "scf-bufferize",
            "convert-tensor-to-linalg",  # tensor.pad
            "convert-elementwise-to-linalg",  # Must be run before --arith-bufferize
            "arith-bufferize",
            "empty-tensor-to-alloc-tensor",
            "func.func(bufferization-bufferize)",
            "func.func(tensor-bufferize)",
            "func.func(linalg-bufferize)",
            "func.func(tensor-bufferize)",
            "quantum-bufferize",
            "func-bufferize",
            "func.func(finalizing-bufferize)",
            "func.func(buffer-hoisting)",
            "func.func(buffer-loop-hoisting)",
            "func.func(buffer-deallocation)",
            "convert-arraylist-to-memref",
            "convert-bufferization-to-memref",
            "canonicalize",
            # "cse",
            "cp-global-memref",
        ],
    ),
    (
        "MLIRToLLVMDialect",
        [
            "convert-gradient-to-llvm",
            "func.func(convert-linalg-to-loops)",
            "convert-scf-to-cf",
            # This pass expands memref ops that modify the metadata of a memref (sizes, offsets,
            # strides) into a sequence of easier to analyze constructs. In particular, this pass
            # transforms ops into explicit sequence of operations that model the effect of this
            # operation on the different metadata. This pass uses affine constructs to materialize
            # these effects. Concretely, expanded-strided-metadata is used to decompose
            # memref.subview as it has no lowering in -finalize-memref-to-llvm.
            "expand-strided-metadata",
            "lower-affine",
            "arith-expand",  # some arith ops (ceildivsi) require expansion to be lowered to llvm
            "convert-complex-to-standard",  # added for complex.exp lowering
            "convert-complex-to-llvm",
            "convert-math-to-llvm",
            # Run after -convert-math-to-llvm as it marks math::powf illegal without converting it.
            "convert-math-to-libm",
            "convert-arith-to-llvm",
            "finalize-memref-to-llvm{use-generic-functions}",
            "convert-index-to-llvm",
            "convert-quantum-to-llvm",
            "emit-catalyst-py-interface",
            # Remove any dead casts as the final pass expects to remove all existing casts,
            # but only those that form a loop back to the original type.
            "canonicalize",
            "reconcile-unrealized-casts",
        ],
    ),
]

class LinkerDriver:
    """Compiler used to drive the linking stage.
    In order to avoid relying on a single linker at run time and allow the user some flexibility,
    this class defines a compiler resolution order where multiple known compilers are attempted.
    The order is defined as follows:
    1. A user specified compiler via the environment variable CATALYST_CC. It is expected that the
        user provided compiler is flag compatilble with GCC/Clang.
    2. clang: Priority is given to clang to maintain an LLVM toolchain through most of the process.
    3. gcc: Usually configured to link with LD.
    4. c99: Usually defaults to gcc, but no linker interface is specified.
    5. c89: Usually defaults to gcc, but no linker interface is specified.
    6. cc: Usually defaults to gcc, however POSIX states that it is deprecated.
    """

    _default_fallback_compilers = ["clang", "gcc", "c99", "c89", "cc"]

    @staticmethod
    def get_default_flags():
        """Re-compute the path where the libraries exist.

        The use case for this is if someone is in a python jupyter notebook and
        needs to change the environment mid computation.
        Returns
            (List[str]): The default flag list.
        """
        mlir_lib_path = get_lib_path("llvm", "MLIR_LIB_DIR")
        rt_lib_path = get_lib_path("runtime", "RUNTIME_LIB_DIR")

        lib_path_flags = [
            f"-Wl,-rpath,{mlir_lib_path}",
            f"-L{mlir_lib_path}",
        ]

        if rt_lib_path != mlir_lib_path:
            lib_path_flags += [
                f"-Wl,-rpath,{rt_lib_path}",
                f"-L{rt_lib_path}",
            ]
        else:
            pass  # pragma: nocover

        system_flags = []
        if platform.system() == "Linux":
            system_flags += ["-Wl,-no-as-needed"]
        elif platform.system() == "Darwin":  # pragma: nocover
            system_flags += ["-Wl,-arch_errors_fatal"]

        default_flags = [
            "-shared",
            "-rdynamic",
            *system_flags,
            *lib_path_flags,
            "-lrt_backend",
            "-lrt_capi",
            "-lpthread",
            "-lmlir_c_runner_utils",  # required for memref.copy
        ]

        return default_flags

    @staticmethod
    def _get_compiler_fallback_order(fallback_compilers):
        """Compiler fallback order"""
        preferred_compiler = os.environ.get("CATALYST_CC", None)
        preferred_compiler_exists = LinkerDriver._exists(preferred_compiler)
        compilers = fallback_compilers
        emit_warning = preferred_compiler and not preferred_compiler_exists
        if emit_warning:
            msg = f"User defined compiler {preferred_compiler} is not in PATH. Using fallback ..."
            warnings.warn(msg, UserWarning)
        else:
            compilers = [preferred_compiler] + fallback_compilers
        return compilers

    @staticmethod
    def _exists(compiler):
        if compiler is None:
            return None
        return shutil.which(compiler)

    @staticmethod
    def _available_compilers(fallback_compilers):
        for compiler in LinkerDriver._get_compiler_fallback_order(fallback_compilers):
            if LinkerDriver._exists(compiler):
                yield compiler

    @staticmethod
    def _attempt_link(compiler, flags, infile, outfile, options):
        try:
            command = [compiler] + flags + [infile, "-o", outfile]
            run_writing_command(command, options)
            return True
        except subprocess.CalledProcessError as e:
            # Only warn in verbose mode, as users might see it otherwise in regular use.
            if options.verbose:
                msg = f"Compiler {compiler} failed to link executable and returned with exit code "
                msg += f"{e.returncode}. Output was: {e.output}.\nCommand: {command}"
                warnings.warn(msg, UserWarning)
            return False

    @staticmethod
    def get_output_filename(infile):
        """Rename object file to shared object

        Args:
            infile (str): input file name
            outfile (str): output file name
        """
        path = pathlib.Path(infile)
        if not path.exists():
            raise FileNotFoundError(f"Cannot find {infile}.")
        return str(path.with_suffix(".so"))

    @staticmethod
    def run(infile, outfile=None, flags=None, fallback_compilers=None, options=None):
        """
        Link the infile against the necessary libraries and produce the outfile.

        Args:
            infile (str): input file
            outfile (Optional[str]): output file
            flags (Optional[List[str]]): flags to be passed down to the compiler
            fallback_compilers (Optional[List[str]]): name of executables to be looked for in PATH
            compile_options (Optional[CompileOptions]): generic compilation options.
        Raises:
            EnvironmentError: The exception is raised when no compiler succeeded.
        """
        if outfile is None:
            outfile = LinkerDriver.get_output_filename(infile)
        if flags is None:
            flags = LinkerDriver.get_default_flags()
        if fallback_compilers is None:
            fallback_compilers = LinkerDriver._default_fallback_compilers
        if options is None:
            options = CompileOptions()
        for compiler in LinkerDriver._available_compilers(fallback_compilers):
            success = LinkerDriver._attempt_link(compiler, flags, infile, outfile, options)
            if success:
                return outfile
        msg = f"Unable to link {infile}. Please check the output for any error messages. If no "
        msg += "compiler was found by Catalyst, please specify a compatible one via $CATALYST_CC."
        raise CompileError(msg)

class Compiler:
    """Compiles MLIR modules to shared objects by executing the Catalyst compiler driver library."""

    def __init__(self, options: Optional[CompileOptions] = None):
        self.options = options if options is not None else CompileOptions()
        self.last_compiler_output = None

    def run_from_ir(self, ir: str, module_name: str, workspace: Directory):
        """Compile a shared object from a textual IR (MLIR or LLVM).

        Args:
            ir (str): Textual MLIR to be compiled
            module_name (str): Module name to use for naming
            workspace (Directory): directory that holds output files and/or debug dumps.

        Returns:
            output_filename (str): Output file name. For the default pipeline this would be the
                                   shard object library path.
            out_IR (str): Output IR in textual form. For the default pipeline this would be the
                          LLVM IR.
            A list of:
               func_name (str) Inferred name of the main function
               ret_type_name (str) Inferred main function result type name
        """
        assert isinstance(
            workspace, Directory
        ), f"Compiler expects a Directory type, got {type(workspace)}."
        assert workspace.is_dir(), f"Compiler expects an existing directory, got {workspace}."

        lower_to_llvm = (
            self.options.lower_to_llvm if self.options.lower_to_llvm is not None else False
        )

        if self.options.verbose:
            print(f"[LIB] Running compiler driver in {workspace}", file=self.options.logfile)

        try:
            compiler_output = run_compiler_driver(
                ir,
                str(workspace),
                module_name,
                keep_intermediate=self.options.keep_intermediate,
                verbose=self.options.verbose,
                pipelines=self.options.get_pipelines(),
                lower_to_llvm=lower_to_llvm,
            )
        except RuntimeError as e:
            raise CompileError(*e.args) from e

        if self.options.verbose:
            for line in compiler_output.get_diagnostic_messages().strip().split("\n"):
                print(f"[LIB] {line}", file=self.options.logfile)

        filename = compiler_output.get_object_filename()
        out_IR = compiler_output.get_output_ir()
        func_name = compiler_output.get_function_attributes().get_function_name()
        ret_type_name = compiler_output.get_function_attributes().get_return_type()

        if lower_to_llvm:
            output = LinkerDriver.run(filename, options=self.options)
            output_filename = str(pathlib.Path(output).absolute())
        else:
            output_filename = filename

        self.last_compiler_output = compiler_output
        return output_filename, out_IR, [func_name, ret_type_name]

    def run(self, mlir_module, *args, **kwargs):
        """Compile an MLIR module to a shared object.

        .. note::

            For compilation of hybrid quantum-classical PennyLane programs,
            please see the :func:`~.qjit` decorator.

        Args:
            mlir_module: The MLIR module to be compiled

        Returns:
            (str): filename of shared object
        """

        return self.run_from_ir(
            mlir_module.operation.get_asm(
                binary=False, print_generic_op_form=False, assume_verified=True
            ),
            str(mlir_module.operation.attributes["sym_name"]).replace('"', ""),
            *args,
            **kwargs,
        )

    def get_output_of(self, pipeline) -> Optional[str]:
        """Get the output IR of a pipeline.
        Args:
            pipeline (str): name of pass class

        Returns
            (Optional[str]): output IR
        """
        if len(dict(self.options.get_pipelines()).get(pipeline, [])) == 0:
            warnings.warn("Requesting an output of an empty pipeline")  # pragma: no cover

        if not self.last_compiler_output:
            return None

        return self.last_compiler_output.get_pipeline_output(pipeline)

    def print(self, pipeline):
        """Print the output IR of pass.
        Args:
            pipeline (str): name of pass class
        """
        print(self.get_output_of(pipeline))  # pragma: no cover


#MenuTitle: Report Windows Names
# -*- coding: utf-8 -*-
from __future__ import division, print_function, unicode_literals
__doc__="""
Checks for the length of nameID 1 and 4, which can cause issues in Word for Windows and Word for Mac respectively.
"""

Glyphs.clearLog() # clears macro window log

thisFont = Glyphs.font

for thisInstance in thisFont.instances:
	nameLength = len(thisInstance.windowsFamily)
	flag = "🆗"
	delta = ""
	if nameLength > 31:
		flag = "⛔"
		delta = "({})".format(31 - nameLength)
	elif nameLength == 31:
		flag = "⚠"
	print("1 {} [{}] {} {}".format(flag, nameLength, thisInstance.windowsFamily, delta))

	nameLength = len(thisInstance.fullName)
	flag = "🆗"
	delta = ""
	if nameLength > 31:
		flag = "⛔"
		delta = "({})".format(31 - nameLength)
	elif nameLength == 31:
		flag = "⚠"
	print("4 {} [{}] {} {}".format(flag, nameLength, thisInstance.fullName, delta))

	nameLength = len(thisInstance.fontName)
	flag = "🆗"
	delta = ""
	if nameLength > 31:
		flag = "⛔"
		delta = "({})".format(31 - nameLength)
	elif nameLength == 31:
		flag = "⚠"
	print("6 {} [{}] {} {}".format(flag, nameLength, thisInstance.fontName, delta))
	print("")

Glyphs.showMacroWindow()


class Juego:
    def __init__(self):
        '''
        Constructor de la clase Juego. Inizializa las variables de la instancia
        '''
        self.nombre = ""
        self.capitulo = 1

    def mostrar_mensaje(self, mensaje):
        '''
        Muestra un mensaje en la consola.
        Args:
            mensaje (str): El mensaje a mostrar.
        '''
        print(mensaje)

    def obtener_decision(self, opciones):
        '''
        Permite al jugador elegir una opción de la lista de opciones.
        Args:
            opciones (list): Una lista de cadenas que representa las opciones disponibles.
        Returns:
            str: la opción elegida por el jugador
        '''
        while True:
            eleccion = input("Elige una opción: " + " / ".join(opciones) + ": ").lower()
            if eleccion in opciones:
                return eleccion
            else:
                self.mostrar_mensaje("Opción no válida. Inténtalo de nuevo.")

    def capitulo1(self):
        '''
        Capítulo 1 del juego. El jugador debe tomar una decisión al comienzo del juego.
        '''
        self.mostrar_mensaje(f"Es momento de elegir tu rumbo, {self.nombre}: ¿Hacia la derecha o izquierda?")
        eleccion = self.obtener_decision(["derecha", "izquierda"])

        if eleccion == "izquierda":
            self.mostrar_mensaje(f"¡Felicidades, {self.nombre}! Continúas por una corriente de agua tranquila.\n")
            self.capitulo += 1
            self.capitulo2()
        else:
            self.mostrar_mensaje(f"Oh no, {self.nombre}, caíste en una cascada muy alta.")
            self.finalizar_juego()

    def capitulo2(self):
            '''
            Capítulo 2 del juego: El jugador se encuentra con monos salvajes y debe tomar una decisión.
            '''
            self.mostrar_mensaje("En el recorrido encuentras un grupo de monos salvajes en las ramas de un árbol sobre el río. Debes tomar una decisión.")

            eleccion = self.obtener_decision(["pelear", "interactuar", "pasar sigilosamente"])
            if eleccion == "pasar sigilosamente":
                self.mostrar_mensaje(f"{self.nombre}, lo lograste. No te han visto y continúas.\n")
                self.capitulo += 1
                self.capitulo3()

            else:
                self.mostrar_mensaje(f"Has elegido {eleccion}. Los monos reaccionan y te atacan. ¡Te han derrotado!")
                self.finalizar_juego()

    def capitulo3(self):
        '''
        Capítulo 3 del juego. El jugador debe elegir entre dos caminos en el río.
        '''
        self.mostrar_mensaje("El río se divide en dos caminos uno parece más corto pero peligroso, mientras que el otro es más largo pero parece más seguro.")

        eleccion = self.obtener_decision(["corto", "largo"])
        if eleccion == "corto":
            self.mostrar_mensaje("Has elegido el camino corto. Estás muy cerca de encontrar el tesoro.\n")
            self.capitulo += 1
            self.capitulo4()
        else:
            self.mostrar_mensaje(f"Has elegido el camino largo, {self.nombre}. De repente, una acaconda feroz te atrapa y termina tu aventura.")
            self.finalizar_juego()

    def capitulo4(self):
        '''
        Capítulo 4 del juego. El jugador debe encontrar un antídoto entre tres plantas.
        '''
        self.mostrar_mensaje(f"Estás muy cerca de encontrar el tesoro, {self.nombre}.")
        self.mostrar_mensaje("En la parada en la orilla, eres picado por unos abejones venenosos. Para buscar el antídoto, debes elegir entre tres plantas.")

        eleccion = self.obtener_decision(["roja", "azul", "verde"])
        if eleccion == "verde":
            self.mostrar_mensaje("Has elegido la planta color verde. ¡Enhorabuena! Elegiste la planta correcta.\n")
            self.capitulo += 1
            self.capitulo5()
        else:
            self.mostrar_mensaje("La planta que elegiste no funcionó y no te salvaste. Tu aventura termina aquí.")
            self.finalizar_juego()

    def capitulo5(self):
        '''
        Capítulo 5 del juego. El jugador debe decidir si excavar en busca del tesoro o seguir rastreando.
        '''
        self.mostrar_mensaje(f"Finalmente, {self.nombre}, llegaste a la ubicación del tesoro. Debes decidir si excavar o seguir rastreando.")

        eleccion = self.obtener_decision(["excavar", "rastrear"])
        if eleccion == "excavar":
            self.mostrar_mensaje("Has elegido excavar. ¡FELICITACIONES! Encontraste el tesoro perdido. Fin del juego.")
            self.finalizar_juego()
        else:
            self.mostrar_mensaje("Has elegido rastrear, {self.nombre}. En el recorrido encontraste un agujero y lamentablemente, has muerto.")
            self.finalizar_juego()

    def finalizar_juego(self):
        '''
        Finaliza el juego y muestra un mensaje de despedida.
        '''
        self.mostrar_mensaje("Fin del juego. ¡Gracias por jugar!")

    def iniciar_juego(self):
        '''
        Da inicio al juego solicitando el nombre del jugador y comienza el primer capítulo.
        '''
        self.nombre = input("Para comenzar el juego, escribe tu nombre: ")
        self.mostrar_mensaje(f"Bienvenido(a), {self.nombre}, al emocionante viaje por un río en medio de una exuberante jungla.")
        self.capitulo1()

if __name__ == "__main__":
    juego = Juego()
    juego.iniciar_juego()


"""
xepr_link.py
------------

Xepr interface functions, communicate with Xepr usingXeprAPI.

Pause times necesary to let Xepr process command are accessed through the
global variable ``COMPILATION_TIME`` (s, ``1`` by default).
It applies pauses of lengths:

 - ``COMPILATION_TIME`` after compilation of .exp file

 - ``COMPILATION_TIME`` after compilation of .def file

 - ``COMPILATION_TIME/4`` after compilation of .shp file

 - ``2*COMPILATION_TIME`` before and after Xepr reset

SPDX-License-Identifier: GPL-3.0-or-later

"""

import time
import XeprAPI         # load the Xepr API module
from typing import List

# global variable to control Xepr files compilation time
COMPILATION_TIME = 1  # (s)

def load_xepr():
    """
    Initialise the Xepr module and return the Xepr object thus created.

    Parameters
    ----------
    None

    Returns
    -------
    xepr : instance of XeprAPI.Xepr
        The instantiated Xepr object, used for communication with
        Xepr-the-programme.
    """
    xepr = XeprAPI.Xepr()  # start Xepr API module

    return xepr

def load_exp(xepr, exp_file: str) -> None:
    """
    Load and compile an Xepr experiment file.

    Parameters
    ----------
    xepr : instance of XeprAPI.Xepr
        The instantiated Xepr object.
    exp_file : str
        The Xepr experiment file (the full path with .exp extension).

    Returns
    -------
    None
    """
    try:
        xepr.XeprCmds.aqPgLoad(exp_file)
        xepr.XeprCmds.aqPgShowPrg()
        xepr.XeprCmds.aqPgCompValid()
        xepr.XeprCmds.aqPgCompile()

        # wait for Xepr to finish compiling
        time.sleep(COMPILATION_TIME)
    except Exception:
        raise RuntimeError("Error loading and compiling experiment file")

def modif_exp(xepr, exp_file: str, line_nb: int, new_line: str) -> None:
    """
    Modify the Xepr .exp file by overwriting a line.

    Parameters
    ----------
    xepr : instance of XeprAPI.Xepr
        The instantiated Xepr object.
    exp_file : str
        Name of the Xepr definition file (full path with .def extension).
    line_nb : int
        Number of the lines to overwrite
    new_line : str
        DESCRIPTION.

    Returns
    -------
    None
    """
    with open(exp_file, 'r') as exp_f:
        fullExp = exp_f.read()

    # write new line
    fullExp = fullExp.split("\n")
    fullExp[line_nb-1] = new_line

    # replace .exp file with modifications
    with open(exp_file, 'w') as exp_f:
        exp_f.write('\n'.join(fullExp))

    if xepr is not None:  # to allow test without Xepr
        load_exp(xepr, exp_file)

def load_def(xepr, def_file: str) -> None:
    """
    Load and compile an Xepr definition file.

    Parameters
    ----------
    xepr : instance of XeprAPI.Xepr
        The instantiated Xepr object.
    def_file : str
        Name of the Xepr definition file (full path with .def extension).

    Returns
    -------
    None
    """
    try:
        xepr.XeprCmds.aqPgDefLoad(def_file)
        xepr.XeprCmds.aqPgShowDef()
        xepr.XeprCmds.aqPgCompile()

        # wait for Xepr to finish compiling
        time.sleep(COMPILATION_TIME)
    except Exception:
        raise RuntimeError("Error loading and compiling definition file")

def modif_def_PlsSPELGlbTxt(xepr, def_file: str,
                            var_name: List[str], var_value: List[str]) -> None:
    """
    Directly modify definitions in the current experiment.

    !will not modify parameters which rely on dependency in the .def (e.g.
                                                                   'p0 = 2*p1')
    !can lead to bugs if forbiden charachters are used in the .def file (e.g.
                                                                           '%')
    !can create a bug where the Xepr stays stuck at the .def file modification
                                           (cf. documentation for more details)
    but faster than modif_def() as no compilation required

    Parameters
    ----------
    xepr : instance of XeprAPI.Xepr
        The instantiated Xepr object.
    def_file : str
        Name of the Xepr definition file (full path with .def extension).
    var_name : list of strings
        Variable names as named in the .def file.
    var_value : list of strings
        List of variable values to be input.

    Returns
    -------
    None
    """
    try:
        currentExp = xepr.XeprExperiment()
    except Exception:
        raise RuntimeError("No experiment has been selected in the"
                           " primary viewport of Xepr.")

    # get the start value for the variable
    # search for our desired variable
    # first get the text of the full PulseSpel def
    fullDefs = currentExp.getParam("PlsSPELGlbTxt").value
    # need to check if fullDefs is empty and exit cause pulsespel not being
    # loaded

    fullDefs = fullDefs.split("\n")

    for i, var_name_i in enumerate(var_name):
        cmdStr = (var_name_i
                  + " = "
                  + var_value[i])

        for line in fullDefs:
            line = line.replace(" ", "")  # getting rid of spaces
            line = line[0:len(var_name_i) + 1]  # selecting first characters
            if var_name_i + "=" == line:
                currentExp["ftEPR.PlsSPELSetVar"].value = cmdStr

def modif_def(xepr, def_file: str,
              var_name: List[str], var_value: List[str]) -> None:
    """
    Modify definitions by modifying the .def file and reloading it.

    Parameters
    ----------
    xepr : instance of XeprAPI.Xepr
        The instantiated Xepr object.
    def_file : str
        Name of the Xepr definition file (full path with .def extension).
    var_name : list of strings
        Variable names as named in the .def file.
    var_value : list of strings
        List of variable values to be input.

    Returns
    -------
    None
    """
    with open(def_file, 'r') as def_f:
        fullDefs = def_f.read()
    fullDefs = fullDefs.split("\n")

    for name, value in zip(var_name, var_value):

        for j, line in enumerate(fullDefs):

            equal_partition = line.partition("=")

            if name == equal_partition[0].replace(" ", ""):
                fullDefs[j] = equal_partition[0] + "= " + value

                # preserve possible comment at the end of the line
                comment_partition = equal_partition[-1].partition(";")
                if comment_partition[1] == ";":
                    fullDefs[j] += " " ";" + comment_partition[-1]

    # replace definition file with modifications
    with open(def_file, 'w') as def_f:
        def_f.write('\n'.join(fullDefs))

    if xepr is not None:  # to allow test without Xepr
        load_def(xepr, def_file)

def load_shp(xepr, shp_file: str) -> None:
    """
    Load and compile an Xepr shape file.

    Parameters
    ----------
    xepr : instance of XeprAPI.Xepr
        The instantiated Xepr object.
    shp_file : str
        Shape file name (full path, including .shp extension).

    Returns
    -------
    None
    """
    try:
        xepr.XeprCmds.aqPgShpLoad(shp_file)
        xepr.XeprCmds.aqPgShowShp()
        xepr.XeprCmds.aqPgCompile()

        # wait for Xepr to finish compiling
        time.sleep(COMPILATION_TIME*0.25)
    except Exception:
        raise RuntimeError("Error loading and compiling Xepr shape file")

def run2getdata_exp(xepr, SignalType: str = None, exp_name: str = None):
    """
    Run an experiment and get the data from it.

    Parameters
    ----------
    xepr : instance of XeprAPI.Xepr
        The instantiated Xepr object.
    SignalType : str, by default None
        To change the signal type (pick from {"TM", "Signal", "RM"})
    exp_name : str, by default None
        The name of the experiment to run, usually "AWGTransient" for the
        Signal or "AWG_1pulseSHP" for the TM.

    Returns
    -------
    data : XeprAPI.Dataset
        The data retrieved from Xepr. Attributes of interest are:
            - data.X      : the X-abscissa values of the dataset
            - data.O      : complex-valued numpy.ndarray of the signal
            - data.O.real : real part of the signal
            - data.O.imag : imaginary part of the signal
    """
    try:
        currentExp = xepr.XeprExperiment()
        hiddenExp = xepr.XeprExperiment("AcqHidden")
    except Exception:
        raise RuntimeError("No experiment has been selected in the"
                           " primary viewport of Xepr.")

    # change detection mode and experiment select if needed
    try:
        if SignalType is not None and \
                hiddenExp["ftBridge.Detection"].value != SignalType:
            hiddenExp["ftBridge.Detection"].value = SignalType
        if exp_name is not None and \
                currentExp["ftEpr.PlsSPELEXPSlct"].value != exp_name:
            currentExp["ftEpr.PlsSPELEXPSlct"].value = exp_name
    except Exception:
        raise RuntimeError("Error changing detection mode to TM,"
                           " or in experiment selection")

    # run new experiment
    try:
        currentExp.aqExpRunAndWait()
    except Exception:
        raise RuntimeError("Error running current experiment")

    # retrieve data
    data = xepr.XeprDataset()

    # no data? -- try to run current experiment (if possible)
    if not data.datasetAvailable():
        try:
            print("Trying to run current experiment to create some data...")
            xepr.XeprExperiment().aqExpRunAndWait()
        except XeprAPI.ExperimentError:
            raise RuntimeError("No dataset available and no (working)"
                               " experiment to run; aborting")
    if not data.datasetAvailable():
        raise RuntimeError("No dataset available; aborting")

    return data

def reset_exp(xepr) -> None:
    """
    Copy the current experiment and use it to replace the current experiment.

    Needed to reset the AWG after 114 sequential shape load and run.

    Parameters
    ----------
    xepr : instance of XeprAPI.Xepr
        The instantiated Xepr object.

    Returns
    -------
    None
    """
    # wait for Xepr to be ready to reset the experiment
    time.sleep(2*COMPILATION_TIME)

    # get current experiment name
    curr_exp = xepr.XeprExperiment()
    expt_name = curr_exp.aqGetExpName()

    # duplicate current experiment
    print(f"replacing experiment <{expt_name}> with new"
          " instance of its copy...")
    xepr.XeprCmds.aqExpCut(expt_name)

    print(f"new instance of experiment <{expt_name}> created...")
    xepr.XeprCmds.aqExpPaste()

    # select new experiment
    xepr.XeprCmds.aqExpSelect(expt_name)
    print(f"new instance of experiment <{expt_name}> selected...")

    # activate new experiment
    xepr.XeprCmds.aqExpActivate(expt_name)
    print(f"new instance of experiment <{expt_name}> activated.")

    # open parameter panel
    xepr.XeprCmds.aqParOpen()

    # ask user to allow .exp file to be loaded
    print('Experiment reset')
    print('clik twice the PulseSPEL button to load the .exp file')
    print('(located at the bottom of FT EPR parameters window)')
    input('when done, press enter in python console to continue:')

    # wait for Xepr to reset the experiment
    time.sleep(2*COMPILATION_TIME)

    # prevent Xepr from reseting high power attenuation value
    xepr.XeprCmds.aqParStep("AcqHidden", "ftBridge.Attenuation", "Fine 1")
    xepr.XeprCmds.aqParStep("AcqHidden", "ftBridge.Attenuation", "Fine -1")


import os
import glob
import json

TARGETS = [
    'Java',
    'Perl',
    'POSIX',
    'Python',
    'JavaScript',
    'PHP',
    'Golang',
    'Rust',
    'C#',
    'Scala',
    'Kotlin'
]

def read_resources(component: str, directory: str):
    base = os.path.dirname(os.path.realpath(__file__))

    for file in sorted(glob.glob('{}/resources/{}/{}/*.json'.format(base,
                                                                    component,
                                                                    directory))):
        with open('{}'.format(file), 'r') as f:
            info = json.load(f)

        with open(file.replace('.json', '.out'), 'r') as f:
            expected = {}
            for i, line in enumerate(f.readlines()):
                line = line.strip()

                if i == 0 or i % 3 == 0:
                    expected[line] = {}
                    lang = line
                elif (i - 1) == 0 or (i - 1) % 3 == 0:
                    expected[lang]['compiled'] = line
                else:
                    expected[lang]['regex'] = line

        yield info, expected


# -*- coding: utf-8 -*-
import re
import click
import logging
from pathlib import Path
from dotenv import find_dotenv, load_dotenv
import pandas as pd
import numpy as np

@click.command()
@click.argument("input_filepath", type=click.Path(exists=True))
@click.argument("output_filepath", type=click.Path())
def main(
    input_filepath: str = "../data/raw/train.csv.zip",
    output_filepath: str = "../data/processed/train_processed.csv",
) -> None:
    """Runs data processing scripts to turn raw data from (../raw) into
    cleaned data ready to be analyzed (saved in ../processed).
    """
    print("Loading zip files..")
    data = pd.read_csv(input_filepath, compression="zip")
    # labels = ['toxic', 'severe_toxic', 'obscene', 'threat','insult', 'identity_hate']
    data["total_classes"] = data.iloc[:, 2:8].apply(lambda x: sum(x), axis=1)
    data["non_toxic"] = data.iloc[:, 2:8].apply(
        lambda x: 1 if (sum(x) == 0) else 0, axis=1
    )
    cleaned_data = data.copy()

    # Removing Hyperlinks from text
    # The below code is a re pattern that matches URLs beginning with http or https, followed by :// and one or more
    # non-whitespace characters, or URLs beginning with www., followed by one or more non-whitespace characters.

    print("Cleaning the data..")
    cleaned_data["comment_text"] = cleaned_data["comment_text"].map(
        lambda x: re.sub(r"https?://\S+|www\.\S+", "", x)
    )
    cleaned_data["comment_text"] = cleaned_data["comment_text"].map(
        lambda x: re.sub(
            "["
            "\U0001F600-\U0001F64F"
            "\U0001F300-\U0001F5FF"
            "\U0001F680-\U0001F6FF"
            "\U0001F1E0-\U0001F1FF"
            "\U00002702-\U000027B0"
            "\U000024C2-\U0001F251"
            "]+",
            "",
            x,
            flags=re.UNICODE,
        )
    )

    # matches of css style,class elements and attributes
    idxs_css = []
    for i in range(len(cleaned_data)):
        if re.findall(r"[{][|].+\n", cleaned_data.loc[i, "comment_text"]):
            idxs_css.append(i)

    # Comments Containing Css style, class and attributes
    cleaned_data.loc[idxs_css, "total_classes"].value_counts()
    cleaned_data.drop(idxs_css, inplace=True)

    # Removing html tags from text
    cleaned_data["comment_text"] = cleaned_data["comment_text"].map(
        lambda x: re.sub(r"<.*?>", "", x)
    )
    cleaned_data["comment_text"] = cleaned_data["comment_text"].map(
        lambda x: re.sub(r"\"\"", '"', x)
    )  # replacing "" with "
    cleaned_data["comment_text"] = cleaned_data["comment_text"].map(
        lambda x: re.sub(r"^\"", "", x)
    )  # removing quotation from start and the end of the string
    cleaned_data["comment_text"] = cleaned_data["comment_text"].map(
        lambda x: re.sub(r"\"$", "", x)
    )

    # Removing Punctuation / Special characters (;:'".?@!%&*+) which appears more than twice in the text
    cleaned_data["comment_text"] = cleaned_data["comment_text"].map(
        lambda x: re.sub(r"[^a-zA-Z0-9\s][^a-zA-Z0-9\s]+", " ", x)
    )

    # Removing Special characters
    cleaned_data["comment_text"] = cleaned_data["comment_text"].map(
        lambda x: re.sub(r"[^a-zA-Z0-9\s\"\',:;?!.()]", " ", x)
    )

    # Removing extra spaces in text
    cleaned_data["comment_text"] = cleaned_data["comment_text"].map(
        lambda x: re.sub(r"\s\s+", " ", x)
    )
    cleaned_data.reset_index(inplace=True)
    cleaned_data.drop(columns=["index"], inplace=True)
    Final_data = cleaned_data.copy()

    # Keeping 15291 comments from non_toxic comments and dropping the rest
    C_indexs = cleaned_data[cleaned_data["total_classes"] == 0].index
    drop_indxs = np.random.choice(C_indexs, size=127696, replace=False)

    # Randomly selecting and dropping non_toxic comments from datasets and leaving 5000 behind
    Final_data.drop(drop_indxs, inplace=True)

    Final_data.to_csv(output_filepath, index=False)
    print("Saved file in data\processed")

    logger = logging.getLogger(__name__)
    logger.info("making final data set from raw data")

if __name__ == "__main__":
    log_fmt = "%(asctime)s - %(name)s - %(levelname)s - %(message)s"
    logging.basicConfig(level=logging.INFO, format=log_fmt)

    # not used in this stub but often useful for finding various files
    project_dir = Path(__file__).resolve().parents[2]

    # find .env automagically by walking up directories until it's found, then
    # load up the .env entries as environment variables
    load_dotenv(find_dotenv())

    main()