from collections import defaultdict

part = 2

data = [x.strip('\n') for x in open("i23.txt").readlines()]
# data = [x.strip('\n') for x in open("t23.txt").readlines()]

for part in [1,2]:
    M = dict()

    for r, l in enumerate(data):
        for c, x in enumerate(l):
            if x == '#':
                M[(r,c)] = (r,c)

    dirs = [
        [(-1,0),(-1,1),(-1,-1),],
        [(1,0),(1,1),(1,-1),],
        [(0, -1),(1, -1),(-1, -1),],
        [(0, 1),(1, 1),(-1, 1),],

    ]

    def printmap(M):
        ep = M.keys()
        rs = [r for r,c in ep]
        cs = [c for r,c in ep]
        for r in range(min(rs), max(rs)+1):
            for c in range(min(cs), max(cs)+1):
                print('#' if (r,c) in M else '.', end='')
            print()

    for round in range(10 if part == 1 else 10000000):
        # print(f"\nround {round}")
        # printmap(M)
        for e in M.keys():
            found = False
            for dp in [(-1,0),(-1,1),(-1,-1),(1,0),(1,1),(1,-1),(0, -1),(0, 1),]:
                check_pos = tuple(map(sum,zip(e,dp)))
                if check_pos in M:
                    found = True
            if not found:
                M[e] = e
                continue

            for test_d in range(round, round + 4):
                d = dirs[test_d%4]
                new_pos = tuple(map(sum,zip(e,d[0])))
                found = False
                for dp in d:
                    check_pos = tuple(map(sum,zip(e,dp)))
                    if check_pos in M:
                        found = True
                        break
                if found:
                    M[e] = e
                else:
                    M[e] = new_pos
                    break

        M2 = defaultdict(int)
        for e, e2 in M.items():
            M2[e2] += 1

        M3 = dict()
        for e, e2 in M.items():
            if M2[e2] > 1:
                M3[e] = e
            else:
                M3[e2] = e2
        if part == 2 and M.keys() == M3.keys():
            print('Part2', round+1)
            break
        else:
            M = M3

    if part == 1:
        ep = M.keys()
        rs = [r for r,c in ep]
        cs = [c for r,c in ep]
        tot = (max(rs)-min(rs)+1) * (max(cs)-min(cs)+1)
        print('part1', tot - len(ep))


# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def postorderTraversal(self, root: TreeNode) -> List[int]:
        ##Keep going to right and keep adding visited to res, stack
        ##Once reached None, go back i.e. pop stack and root = left

        st, res = [], []
        while st or root:
            if root:
                st.append(root)
                res.append(root.val)
                root = root.right
            else:
                root = st.pop().left

        return res[::-1]


import binascii

def decode(string,initial):
    alph = "abcdefghijklmnopqrstuvwxyz"
    rot = initial
    decoded = ""
    for i in range(len(string)):
        c = string[i]
        plain = alph[(alph.index(c) + rot) % (len(alph) - 1)]
        decoded += plain
        rot += ord(plain) - 2
    return decoded

def find_decoding(num):
    a = num
    num = rev(num)
    num = format(num, 'x')
    num = binascii.unhexlify(num)
    num = num.decode()
    for i in range(26):
        decoded = decode(num,i)
        if ((ord(decoded[-1]) + 5) % 25) == i:
            print("magic input equal with %d is:  %s" % (a, decode(num,i)))

def rev(num):
    a = str(num)[::-1]
    return int(a)

ops= [4932739181, 6122352081, 3611099681, 5122107891, 3550866391, 3983866391, 8920866391, 6610774871]
for op in ops:
    find_decoding(op)


import requests, json, os
from requests.auth import HTTPBasicAuth

clientID = os.environ['CLIENT_ID']
clientSecret = os.environ['CLIENT_SECRET']
url = "https://accounts.spotify.com/api/token"
data = {"grant_type": "client_credentials"}
auth = HTTPBasicAuth(clientID, clientSecret)

response = requests.post(url, data=data, auth=auth)

print(response.ok)
print(response.json())
print(response.status_code)


import numpy as np
import dcor

def cal_info(X, Y, k):
	"""
		calculate the max energy distance among random vector Xs that condition
		on k classes, associated with the random discrete variable Y

		Requirments:
		dcor, which is on PyPi and can be installed using pip and conda

		Input:
		X (:obj:`numpy.ndarray`): matrix of size n x d, n observations of X
		where X is a d-dimensional random vector taking continuous values
		Y (:obj:`numpy.ndarray`): matrix of size n x 1, n observations of Y
		where Y is a 1-dimensional random vector taking discrete values
			0,1,...k-1
		k (:obj:`int`): number of discrete values Y can take

		Output:
		dist (:obj:`float`): mean energy distance of k assumed conditioanl
		distributions among Xs, the larger the more difference and the more dependence of Y
		err (:obj:`bool`): True, if the output can be used,
			and False otherwise

		Example:
		If the X is a 1000 dimensional input, Y is the 10-classification label
		and if there are 2000 observations, then
		X: float-valued matrix of size 2000 x 1000
		Y: discrete-valued vector of size 2000 x 1
		k: integer 10
		The algo returns near-zero if X and Y are independent, and positive otherwise
	"""

	n, d = X.shape
	class_ind = []
	for i in range(k):
		ind = np.where(Y == i)[0]
		if len(ind) > 0:
			class_ind.append(ind)

	# some class may be unobserved, redefine k
	##how to redefine?
	k0 = len(class_ind)
	if k0 < 2:
		return 0, False

	# use the largest class as reference for pairwise calculation
	ref = np.argmax(np.array([len(class_ind[i]) for i in range(k0)]))
	X1 = X[class_ind[ref], :]
	dists = []
	for j in range(k0):
		if j != ref:
			disttemp = dcor.energy_distance(X1, X[class_ind[j], :])
			dists.append(disttemp)
	dist = np.max(np.array(dists))
	return dist, True

# test codes
def test(n1, n2, mu):
	k = 2
	n = n1+n2
	d = 1
	X = np.zeros((n, d))
	Y = np.zeros(n)

	X[0:n1, :] = np.random.normal(loc=0.0, scale=1.0, size=d)
	X[n1:n, :] = np.random.normal(loc=mu, scale=1.0, size=d)
	Y[0:n1] = [0] * n1
	Y[n1:n] = [1] * n2

	dist, err = cal_info(X, Y, k)
	return dist

def run(m, mu):
	dists = []
	for i in range(m):
		dists.append(test(100, 100, mu))
	print(np.mean(dists), np.max(dists), np.min(dists))

if __name__ == '__main__':
	run(100, 0.0)
	run(100, 1.0)
	run(100, 2.0)
	run(100, 5.0)
	run(100, 10.0)


#!usr/bin/python
# -*- coding: utf-8 -*-
'''
单个视频截取成图片
'''
import cv2
videopath = "G:\\test.mp4"
vc = cv2.VideoCapture(videopath)
a = 1 #图片计数
c = 1 #帧数计数
# 判断是否正常打开
if vc.isOpened():
    rval, frame = vc.read() #返回一个布尔类型的 frame为图片
    print("正在截取文件，路径为：" + videopath)
else:
    rval = False
    print("加载文件失败，请检查文件路径！")
# 视频帧数间隔
timeOut = 1

while rval:
    rval, frame = vc.read()

    if (c%timeOut == 0):
        str1 = str(a)
        cv2.imwrite('G:\\aa\\' + str1.zfill(0) + '.jpg', frame)
        print("已截取第%d张图片"%a)
        a = a + 1
    c = c+1
    #cv2.waitKey(1)#表示等待键盘输入 1 表示1ms切换到下一帧图像
vc.release()#释放


import telebot
import yaml
import sys

from telebot import types

import db_access

config = yaml.safe_load(open("conf.yml"))

bot = telebot.TeleBot(config["token"])

match_dict = {}
pred_dict = {}

class Prediction:
    def __init__(self, uid):
        self.userid = uid
        self.matchid = None
        self.win = None
        self.goal = None
        self.total = None

class Match:
    def __init__(self, teamname1, teamname2):
        self.team1 = teamname1
        self.team2 = teamname2

#################### FUNCTIONS TO READ DATA ####################

# Function to handle the /start command:
# After sending this command, user gets a message how to use bot
# chat_id is added to the database (kind of user registration)
@bot.message_handler(commands=['start'])
def send_start(message):
    try:
        chat_id = message.chat.id
        bot.send_message(chat_id,
                         'Welcome to Euro 2016 prediction contest! ' +
                         'Type /help for help, ' +
                         '/rules for rules, or ' +
                         '/predict to make your predictions')
        db_access.add_user(chat_id)
    except Exception as e:
        bot.reply_to(message, 'Something went wrong! Please, contact the provider of this bot!')

# Function to handle the /help command:
# User gets the list of all available commands
@bot.message_handler(commands=['help'])
def send_help(message):
    try:
        chat_id = message.chat.id
        bot.send_message(chat_id,
                         '/start View start message\n' +
                         '/help View this message\n' +
                         '/predict Make prediction\n' +
                         '/setname Set your name\n' +
                         '/setgroup Set your group\n' +
                         '/rules Show rules\n' +
                         '/today See what happens today\n' +
                         '/ranking See the ranking of your groups\n' +
                         '/current See the predictions for current match')
    except Exception as e:
        bot.reply_to(message, 'Something went wrong! Please, contact the provider of this bot!')

# Function to handle the /rules command:
# User gets a short description of how the points are assigned
@bot.message_handler(commands=['rules'])
def send_rules(message):
    try:
        chat_id = message.chat.id
        bot.send_message(chat_id,
                         'You need to answer three questions about each match:\n' +
                         '1. Who will win the game or will there be a draw?\n' +
                         '2. What will be the difference of team goals? ' +
                         '(in case you predicted draw: how many goals will each team score?)\n' +
                         '3. What will be total of the match? (Over or Under 2.5 golas?)\n' +
                         'You may get 3 points for each correct answer.' +
                         ' If all 3 answers are correct, you get an additional point.')
    except Exception as e:
        bot.reply_to(message, 'Something went wrong! Please, contact the provider of this bot!')

# Function to handle the /today command:
# User gets a list of matches that will be played today
# The user also gets his predictions for each match
@bot.message_handler(commands=['today'])
def send_today_info(message):
    try:
        chat_id = message.chat.id
        today_matches = db_access.today_matches()
        if (len(today_matches) == 0):
            bot.send_message(chat_id, 'No matches today!')
        today_matches_ids = [c['match_no'] for c in today_matches]
        user_profile = db_access.get_user(chat_id)
        info_text = 'Matches and your predictions for today:\n'
        if (user_profile == 0):
            return (0)
        else:
            user_predictions = user_profile['predictions']
            today_user_prediction_ids = [c['match_no'] for c in user_predictions if c['match_no'] in today_matches_ids]
            # TODO: make map instead of for-loop:
            for match in today_matches:
                info_text = info_text + match['team_1'] + " vs. " + match['team_2'] + ': '
                if match['match_no'] in today_user_prediction_ids:
                    prediction = [c for c in user_predictions if c['match_no'] == match['match_no']][0]
                    if (prediction['winner'] == 0):
                        info_text = info_text + 'Draw '
                        info_text = info_text + str(prediction['goals']) + ':' + str(prediction['goals']) + ', '
                    else:
                        if (prediction['winner'] == 1):
                            info_text = info_text + match['team_1']
                        elif (prediction['winner'] == 2):
                            info_text = info_text + match['team_2']
                        info_text = info_text + ' by ' + str(prediction['goals']) + ' goals, '
                    if (prediction['total'] == 0):
                        info_text = info_text + '<2.5'
                    elif (prediction['total'] == 1):
                        info_text = info_text + '>2.5'
                else:
                    info_text = info_text + 'No prediction (yet)'
                info_text = info_text + '\n'
            info_text = info_text + 'Click /predict to make Predictions!'
            bot.send_message(chat_id, info_text)
    except Exception as e:
        bot.reply_to(message, 'Something went wrong! Please, contact the provider of this bot!')

# Function to handle the /current command
# User gets predictions of members of all his groups
# for the current matches.
# Current match is defined as not finished and not active match
@bot.message_handler(commands=['current'])
def send_current_match_info(message):
    try:
        chat_id = message.chat.id
        user_profile = db_access.get_user(chat_id)
        current_matches = db_access.current_matches()
        if(len(current_matches) == 0):
            bot.send_message(chat_id, 'There are no matches now!')
        else:
            for match in current_matches:
                predictions_for_match = db_access.get_predictions_match(match, user_profile)
                string_to_send = match['team_1'] + ' vs. ' + match['team_2'] + ':\n'
                for prediction_for_match in predictions_for_match:
                    if ('name' in prediction_for_match):
                        string_to_send = string_to_send + prediction_for_match['name'] + ': '
                    if ('predictions' in prediction_for_match):
                        prediction_l = prediction_for_match['predictions']
                        prediction = prediction_l[0]
                        if (prediction['winner'] == 0):
                            string_to_send = string_to_send + 'Draw ' + str(prediction['goals']) + ':' + str(prediction['goals']) + ', '
                        else:
                            if (prediction['winner'] == 1):
                                string_to_send = string_to_send + match['team_1']
                            elif (prediction['winner'] == 2):
                                string_to_send = string_to_send + match['team_2']
                            string_to_send = string_to_send + ' by ' + str(prediction['goals']) + ' goal(s), '
                        if (prediction['total'] == 0):
                            string_to_send = string_to_send + '<2.5\n'
                        elif (prediction['total'] == 1):
                            string_to_send = string_to_send + '>2.5\n'
                    else:
                        string_to_send = string_to_send + 'No prediction\n'
                bot.send_message(chat_id, string_to_send)
    except Exception as e:
        bot.reply_to(message, 'Something went wrong! Please, contact the provider of this bot!')

# Help function to create a printable string from group name and ranking list
def ranking_to_str(group, ranking):
    result = group + '\n'
    # TODO: add formatting (probably, with additional function)
    for rank in ranking:
        if ('name' in rank):
            result = result + rank['name'] + '   ' + str(rank['total_points']) + '\n'
        else:
            result = result +  '   ' + str(rank['total_points']) + '\n'
    return result

# Function to handle the /ranking command
# The user gets one message per group (where he is a member)
# This message contains sorted list of group members with their points
# In case the user is not a member of any group, he may request a group,
# that he wants to get ranking for
# (this request is processed in the next function).
@bot.message_handler(commands=['ranking'])
def get_ranking(message):
    try:
        chat_id = message.chat.id
        groups = db_access.get_groups(chat_id)
        if (len(groups) == 0):
            msg = bot.reply_to(message,
                               'You are not a member of any groups! ' +
                               'Please enter the name of the group you want to get ranking!')
            bot.register_next_step_handler(msg, process_ranking)
        else:
            user_groups = groups['groups']
            for group in user_groups:
                ranking = db_access.get_ranking(group)
                ranking_sorted = sorted(ranking, key=lambda k: k['total_points'], reverse = True)
                ranking_str = ranking_to_str(group, ranking_sorted)
                msg = bot.reply_to(message, ranking_str)
    except Exception as e:
        bot.reply_to(message, 'Something went wrong! Please, contact the provider of this bot!')

# Function called if a user is not a member of any group:
# Ranking of chosen group is shown.
def process_ranking(message):
    try:
        chat_id = message.chat.id
        group = message.text
        ranking = db_access.get_ranking(group)
        ranking_sorted = sorted(ranking, key=lambda k: k['total_points'], reverse = True)
        ranking_str = ranking_to_str(group, ranking_sorted)
        msg = bot.reply_to(message, ranking_str)
    except Exception as e:
        bot.reply_to(message, 'Something went wrong! Please, contact the provider of this bot!')

#################### FUNCTIONS TO WRITE DATA ####################

# Function to handle the /setname command
# User can set his name
@bot.message_handler(commands=['setname'])
def set_name(message):
    try:
        msg = bot.reply_to(message, 'What is your name?')
        bot.register_next_step_handler(msg, process_name)
    except Exception as e:
        bot.reply_to(message, 'Something went wrong! Please, contact the provider of this bot!')

def process_name(message):
    try:
        chat_id = message.chat.id
        name = message.text
        db_access.add_name(chat_id, name)
        bot.send_message(chat_id, "Nice to meet you, " + name + "!")
    except Exception as e:
        bot.reply_to(message, 'Something went wrong! Please, contact the provider of this bot!')

@bot.message_handler(commands=['setgroup'])
def set_group(message):
    try:
        msg = bot.reply_to(message, "Type the name of the group you want to be added to:")
        bot.register_next_step_handler(msg, process_group)
    except Exception as e:
        bot.reply_to(message, 'Something went wrong! Please, contact the provider of this bot!')

def process_group(message):
    try:
        chat_id = message.chat.id
        group_name = message.text
        db_access.add_group(chat_id, group_name)
        bot.send_message(chat_id, "You were added to the group " + group_name + "!")
    except Exception as e:
        bot.reply_to(message, 'Something went wrong! Please, contact the provider of this bot!')

@bot.message_handler(commands=['predict'])
def send_predict(message):
    try:
        chat_id = message.chat.id
        pred = Prediction(chat_id)
        pred_dict[chat_id] = pred
        next_match = db_access.get_next_match(chat_id)
        if(next_match == 0):
            bot.send_message(chat_id, "Sorry! There are no matches in our database you can currently predict!")
        else:
            pred.matchid = [c['match_no'] for c in next_match][0]
            team1 = [c['team_1'] for c in next_match][0]
            team2 = [c['team_2'] for c in next_match][0]
            match = Match(team1, team2)
            match_dict[chat_id] = match
            stage = [c['type'] for c in next_match][0]
            quote = [c['quote'] for c in next_match][0]
            if (stage == 'Group'):
                stage = stage + ' ' + [c['group'] for c in next_match][0]
            markup = types.ReplyKeyboardMarkup(one_time_keyboard=True)
            team1button = types.KeyboardButton(match.team1)
            team2button = types.KeyboardButton(match.team2)
            drawbutton = types.KeyboardButton("Draw")
            markup.add(team1button, team2button, drawbutton)
            msg = bot.reply_to(message, stage + ': ' + match.team1 + ' vs. ' + match.team2 + '(Quote: ' + str(quote) + ')\n Who will win the game?', reply_markup=markup)
            bot.register_next_step_handler(msg, process_win_step)
    except Exception as e:
        bot.reply_to(message, 'Something went wrong! Please, contact the provider of this bot!')
        print("Unexpected error:", sys.exc_info()[0])

def process_win_step(message):
    try:
        chat_id = message.chat.id
        match = match_dict[chat_id]
        print("Prediction started for the match: " + match.team1 + " vs. " + match.team2)
        pred = pred_dict[chat_id]
        if (message.text == match.team1):
            pred.win = 1
        elif (message.text == match.team2):
            pred.win = 2
        elif (message.text == u'Draw'):
            pred.win = 0
        else:
            bot.send_message(chat_id, "Error!")
        print("Chat id: " + str(chat_id) + "; Prediction: " + message.text + ' (' + str(pred.win) + ')')
        if (message.text == u'Draw'):
            msg = bot.reply_to(message, "How many goals will each team score?")
            bot.register_next_step_handler(msg, process_goal_step)
        else:
            msg = bot.reply_to(message, "What will be the goal difference?")
            bot.register_next_step_handler(msg, process_goal_step)
    except Exception as e:
        bot.reply_to(message, 'Something went wrong! Please, contact the provider of this bot!')

def process_goal_step(message):
    try:
        chat_id = message.chat.id
        pred = pred_dict[chat_id]
        print("Chat id: " + str(chat_id) + "; Prediction: " + message.text)
        pred.goal = int(message.text)
        underbutton = types.KeyboardButton('< 2.5')
        overbutton = types.KeyboardButton('> 2.5')
        markup = types.ReplyKeyboardMarkup(one_time_keyboard=True)
        markup.add(underbutton, overbutton)
        msg = bot.reply_to(message, 'How many goals will the teams score?', reply_markup=markup)
        bot.register_next_step_handler(msg, process_total_step)
    except Exception as e:
        bot.reply_to(message, 'Something went wrong! Please, contact the provider of this bot!')
        print("Unexpected error:", sys.exc_info()[0])

def process_total_step(message):
    try:
        chat_id = message.chat.id
        pred = pred_dict[chat_id]
        print('Chat id: ' + str(chat_id) + '; Prediction: ' + message.text)
        if (message.text == '< 2.5'):
            pred.total = 0
        elif (message.text == '> 2.5'):
            pred.total = 1
        else:
            msg = bot.send_message(chat_id, "Error!")
        db_access.add_prediction(pred.userid, pred.matchid, pred.win, pred.goal, pred.total)
        bot.send_message(chat_id, "Your prediction for this game is saved! Click /predict to make the next prediction! Click /today to see today's matches and your predictions!")
    except Exception as e:
        bot.reply_to(message, 'Something went wrong! Please, contact the provider of this bot!')

@bot.message_handler(func=lambda message: True)
def echo_all(message):
    return (0)
    # bot.reply_to(message, "Unfortunately we do not support free text.
    # If you see this message, something went wrong
    # (or you just typed some text the bot can not understand).")

bot.polling()


import argparse
from filelock import FileLock
import os
import time

import cv2
from dynamixel_sdk import (
    PortHandler,
    PacketHandler,
    GroupBulkWrite,
    GroupBulkRead,
    COMM_SUCCESS,
    DXL_LOBYTE,
    DXL_LOWORD,
    DXL_HIBYTE,
    DXL_HIWORD,
)

argparser = argparse.ArgumentParser()
argparser.add_argument("func", type=str)
argparser.add_argument("code", type=str)

DESCRIPTION = os.getenv("O_DESCRIPTION", """
You are a small robot with a stereo camera vision module
Your vision module uses two cameras to infer 3d
Pick a function based on the robot log.
Always pick a function and provide any args required.
Here are the functions:
LOOK(direction:str)
    direction must be one of ["FORWARD", "LEFT", "RIGHT"]
    📷👀
Pick one of the functions and the args.
Here are some example outputs:
LOOK,LEFT
LOOK,FORWARD
Your response should be a single line with the chosen function code and arguments.
""")
DEFAULT_FUNC: str = os.getenv("O_DEFAULT_FUNC", "LOOK")
DEFAULT_CODE: str = os.getenv("O_DEFAULT_CODE", "FORWARD")

VIDEO_DEVICE = str(os.getenv("O_VIDEO_DEVICE", "/dev/video0"))
IMAGE_PATH = os.getenv("O_IMAGE_PATH", "/tmp/o.image.jpeg")  # Image is constantly overwritten
IMAGE_LOCK_PATH = os.getenv("O_IMAGE_LOCK_PATH", "/tmp/o.image.lock")  # Lock prevents reading while writing

LOOK_DIRECTIONS = {
    "FORWARD": [3000, 2850, 1800],
    "LEFT": [3000, 2850, 1640],
    "RIGHT": [3000, 2850, 2000],
}
SERVOS: list = [
    (1, (2825, 3536)),  # Servo ID 1
    (2, (2827, 2850)),  # Servo ID 2
    (3, (1648, 2333)),  # Servo ID 3
]

# Convert servo units into degrees for readability
# Max for units is 4095, which is 360 degrees
DEGREE_TO_UNIT: float = 4095 / 360.0

def degrees_to_units(degree: int) -> int:
    return int(degree * DEGREE_TO_UNIT)

def units_to_degrees(position: int) -> int:
    return int(position / DEGREE_TO_UNIT)

class Servos:
    def __init__(
        self,
        servos: list = SERVOS,
        protocol_version: float = 2.0,  # DYNAMIXEL Protocol version (1.0 or 2.0)
        baudrate: int = 57600,  # Baudrate for DYNAMIXEL communication
        device_name: str = "/dev/ttyUSB0",  # Name of the device (port) where DYNAMIXELs are connected
        addr_torque_enable: int = 64,  # Address for Torque Enable control table in DYNAMIXEL
        addr_goal_position: int = 116,  # Address for Goal Position control table in DYNAMIXEL
        addr_present_position: int = 132,  # Address for Present Position control table in DYNAMIXEL
        torque_enable: int = 1,  # Value to enable the torque
        torque_disable: int = 0,  # Value to disable the torque
    ):
        self.num_servos: int = len(servos)
        self.servo_ids: list = []
        self.servo_ranges: list = []
        for id, range in servos:
            self.servo_ids.append(id)
            self.servo_ranges.append(range)
        self.protocol_version = protocol_version
        self.baudrate = baudrate
        self.device_name = device_name
        self.addr_torque_enable = addr_torque_enable
        self.addr_goal_position = addr_goal_position
        self.addr_present_position = addr_present_position
        self.torque_enable = torque_enable
        self.torque_disable = torque_disable
        self.port_handler = PortHandler(self.device_name)
        self.packet_handler = PacketHandler(self.protocol_version)
        if not self.port_handler.openPort():
            raise Exception("Failed to open the port")
        if not self.port_handler.setBaudRate(self.baudrate):
            raise Exception("Failed to change the baudrate")
        self.group_bulk_write = GroupBulkWrite(self.port_handler, self.packet_handler)
        self.group_bulk_read = GroupBulkRead(self.port_handler, self.packet_handler)

    def _write_position(self, positions: list):
        for i, pos in enumerate(positions):
            dxl_id = self.servo_ids[i]
            clipped = min(max(pos, self.servo_ranges[i][0]), self.servo_ranges[i][1])
            dxl_comm_result, dxl_error = self.packet_handler.write1ByteTxRx(
                self.port_handler, dxl_id, self.addr_torque_enable, self.torque_enable
            )
            if dxl_comm_result != COMM_SUCCESS:
                raise Exception(self.packet_handler.getTxRxResult(dxl_comm_result))
            elif dxl_error != 0:
                raise Exception(self.packet_handler.getRxPacketError(dxl_error))
            self.group_bulk_write.addParam(
                dxl_id,
                self.addr_goal_position,
                4,
                [
                    DXL_LOBYTE(DXL_LOWORD(clipped)),
                    DXL_HIBYTE(DXL_LOWORD(clipped)),
                    DXL_LOBYTE(DXL_HIWORD(clipped)),
                    DXL_HIBYTE(DXL_HIWORD(clipped)),
                ],
            )
        dxl_comm_result = self.group_bulk_write.txPacket()
        if dxl_comm_result != COMM_SUCCESS:
            raise Exception(self.packet_handler.getTxRxResult(dxl_comm_result))
        self.group_bulk_write.clearParam()

    def _read_pos(self) -> list:
        for i in range(self.num_servos):
            dxl_id = self.servo_ids[i]
            dxl_addparam_result = self.group_bulk_read.addParam(
                dxl_id, self.addr_present_position, 4
            )
            if not dxl_addparam_result:
                raise Exception(f"[ID:{dxl_id}] groupBulkRead addparam failed")
        # Read present position
        dxl_comm_result = self.group_bulk_read.txRxPacket()
        if dxl_comm_result != COMM_SUCCESS:
            raise Exception(self.packet_handler.getTxRxResult(dxl_comm_result))
        # Get present position value
        positions = []
        for i in range(self.num_servos):
            dxl_id = self.servo_ids[i]
            dxl_present_position = self.group_bulk_read.getData(
                dxl_id, self.addr_present_position, 4
            )
            positions.append(units_to_degrees(dxl_present_position))
        # Clear bulk read parameter storage
        self.group_bulk_read.clearParam()
        return positions

    def _disable_torque(self) -> None:
        for id in self.servo_ids:
            dxl_comm_result, dxl_error = self.packet_handler.write1ByteTxRx(
                self.port_handler,
                id,
                self.addr_torque_enable,
                self.torque_disable,
            )
            if dxl_comm_result != COMM_SUCCESS:
                print(f"ERROR: {self.packet_handler.getTxRxResult(dxl_comm_result)}")
            elif dxl_error != 0:
                print(f"ERROR: {self.packet_handler.getRxPacketError(dxl_error)}")

    def __del__(self, *args, **kwargs) -> None:
        self._disable_torque()
        self.port_handler.closePort()

def capture_and_save_image() -> str:
    cap = cv2.VideoCapture(VIDEO_DEVICE)
    if not cap.isOpened():
        return "📷❌ cv2 error: no video device"
    ret, frame = cap.read()
    if not ret:
        cap.release()
        return "📷❌ cv2 error: on read"
    frame = cv2.flip(frame, 0)  # Flip the image vertically
    with FileLock(IMAGE_LOCK_PATH):
        cv2.imwrite(IMAGE_PATH, frame)
    cap.release()
    return "📷✅ new image"

def look(
    direction: str = DEFAULT_CODE,
    directions: list = LOOK_DIRECTIONS,
) -> str:
    servos = Servos()
    servo_pos = directions.get(direction.upper(), None)
    if servo_pos:
        servos._write_position(servo_pos)
        log = capture_and_save_image()
        return f"{log}👀✅ looked {direction}"
    else:
        return f"👀❌ unknown look direction {direction}"

def test_mode() -> None:
    print("Entering limp mode")
    servos = Servos()
    servos._disable_torque()
    for _ in range(10):
        time.sleep(0.5)
        print(servos._read_pos())

if __name__ == "__main__":
    args = argparser.parse_args()
    if args.func.upper() == "LOOK":
        print(look(args.code))
    elif args.func.upper() == "TEST":
        test_mode()
    else:
        raise ValueError(f"unknown func {args.func} code {args.code}")


import numpy as np
from scipy import misc

DefMatr = np.random.normal(loc = 1, scale = 10, size = (1000, 50))
Means = np.mean(DefMatr, axis = 0)
Stds = np.std(DefMatr, axis = 0)
SecMatr = (DefMatr - Means) / Stds
Means2 = np.mean(SecMatr, axis = 0)
#print(DefMatr)
#print(Means)
#print(Stds)
#print(Means2)
#print(SecMatr)

Z = np.array([[4, 5, 0],
             [1, 9, 3],
             [5, 1, 1],
             [3, 3, 3],
             [9, 9, 9],
             [4, 7, 1]])
Summs = np.sum(Z, axis = 1)
Logs = (Summs > 10)
TrueIndexes = np.array(np.nonzero(Logs))[0]
#print(Z)
#print(Summs)
#print(Logs)
#print(TrueIndexes)

A = np.eye(3)
B = np.eye(3)
AB = np.vstack((A, B))
print(AB)


"""initial migration

Revision ID: 5baa5fa8661a
Revises:
Create Date: 2018-02-23 19:12:28.866452

"""
from alembic import op
import sqlalchemy as sa

# revision identifiers, used by Alembic.
revision = '5baa5fa8661a'
down_revision = None
branch_labels = None
depends_on = None

def upgrade():
    # ### commands auto generated by Alembic - please adjust! ###
    op.create_table('users',
    sa.Column('id', sa.Integer(), nullable=False),
    sa.Column('username', sa.String(length=64), nullable=True),
    sa.PrimaryKeyConstraint('id')
    )
    op.create_index(op.f('ix_users_username'), 'users', ['username'], unique=True)
    op.create_table('conferences',
    sa.Column('id', sa.Integer(), nullable=False),
    sa.Column('call_sid', sa.String(length=64), nullable=True),
    sa.Column('name', sa.String(length=64), nullable=True),
    sa.Column('account_sid', sa.String(length=64), nullable=True),
    sa.Column('date_created', sa.String(length=64), nullable=True),
    sa.Column('user_id', sa.Integer(), nullable=True),
    sa.ForeignKeyConstraint(['user_id'], ['users.id'], ),
    sa.PrimaryKeyConstraint('id')
    )
    op.create_index(op.f('ix_conferences_call_sid'), 'conferences', ['call_sid'], unique=True)
    op.create_table('participants',
    sa.Column('id', sa.Integer(), nullable=False),
    sa.Column('number', sa.String(length=32), nullable=True),
    sa.Column('duration', sa.Integer(), nullable=True),
    sa.Column('direction', sa.String(length=16), nullable=True),
    sa.Column('call_sid', sa.String(length=64), nullable=True),
    sa.Column('conference_id', sa.Integer(), nullable=True),
    sa.ForeignKeyConstraint(['conference_id'], ['conferences.id'], ),
    sa.PrimaryKeyConstraint('id')
    )
    op.create_index(op.f('ix_participants_call_sid'), 'participants', ['call_sid'], unique=True)
    # ### end Alembic commands ###

def downgrade():
    # ### commands auto generated by Alembic - please adjust! ###
    op.drop_index(op.f('ix_participants_call_sid'), table_name='participants')
    op.drop_table('participants')
    op.drop_index(op.f('ix_conferences_call_sid'), table_name='conferences')
    op.drop_table('conferences')
    op.drop_index(op.f('ix_users_username'), table_name='users')
    op.drop_table('users')
    # ### end Alembic commands ###


"""
Write a Python program to add an item in a tuple.
"""

sample_tuple = ('a', 'b', 'c')
lis = list(sample_tuple)
inp = input("Enter the element you want to add:")
lis.append(inp)
print(tuple(lis))


from unicodedata import name
from selenium import webdriver
from selenium.webdriver.common.by import By
from webdriver_manager.chrome import ChromeDriverManager
from selenium.webdriver.chrome.service import Service
from image_edit import FormWyr
import sqlite3
import datetime
import time
import os

options = webdriver.ChromeOptions()
options.add_argument('--headless')
options.binary_location =os.environ.get("GOOGLE_CHROME_BIN")
options.add_argument("--disable-dev-shm-usage")
options.add_argument("--no-sandbox")
driver = webdriver.Chrome(ChromeDriverManager().install(), options=options)
driver.maximize_window()

def get_ques():
    driver.get('https://either.io/')
    a2 = driver.find_elements(By.CLASS_NAME, 'option-text')
    for l in a2:
        print(l.get_attribute('textContent'))
    a = a2[0].get_attribute('textContent')
    b = a2[1].get_attribute('textContent')

    uid = a.lower().strip()+b.lower().strip()

    print('get_ques() : ',[a, b, uid])
    return ([a, b, uid])

# a1=FormWyr().get_image(a=a,b=b)
today = datetime.date.today()
date = '{}'.format([today.year, today.month, today.day])

def get_unique_ques():
    conn = sqlite3.connect('wyr_either.db')
    c = conn.cursor()
    k=0
    try:
        while True:
            time.sleep(5)
            k+=1
            print('try ',k)
            a2=get_ques()
            print('a2 : ',a2)
            uid=a2[2]
            if uid not in (c.execute("SELECT uid FROM wyr_either").fetchall()):
                print('not in table')
                c.execute("INSERT INTO wyr_either VALUES (:option1,:option2,:date,:uid)", {
                          'option1': a2[0], 'option2': a2[1], 'date': date, 'uid': a2[2]})
                conn.commit()
                conn.close()
                print('^_^ success in try ',k)
                return (a2[0],a2[1])
            else:
                continue
    except Exception as e:
        print(" Error : ",e)
    driver.close()

def formimage():
    a2=get_unique_ques()
    a5=FormWyr().get_image(a=a2[0],b=a2[1])
    return [a2[0],a2[1]]

"""    conn = sqlite3.connect('wyr_either.db')
    c = conn.cursor()
    a2=get_ques()
    uid=a2[2]
    if uid not in (c.execute("SELECT uid FROM wyr_either").fetchall()):
        print('not in table')
        a5=FormWyr().get_image(a=a2[0],b=a2[1])
        c.execute("INSERT INTO wyr_either VALUES (:option1,:option2,:date,:uid)", {
                  'option1': a2[0], 'option2': a2[1], 'date': date, 'uid': a2[2]})
        conn.commit()
        conn.close()
    else:
        print('in table')
        a3 = get_ques()
        a5=FormWyr().get_image(a=a3[0],b=a3[1])
        c.execute("INSERT INTO wyr_either VALUES (:option1,:option2,:date,:uid)", {
                  'option1': a3[0], 'option2': a3[1], 'date': date, 'uid': a3[2]})
        conn.commit()
        conn.close()"""


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

import csv
from xlrd import open_workbook

def is_municipality_row(row):
    city_code = row[0].strip()
    return city_code.isdigit() and len(city_code) == 5

def is_designed_city(city_code):
    designed_city = (
        '01100', '04100', '11100', '12100', '14100',
        '14130', '14150', '15100', '22100', '22130',
        '23100', '26100', '27100', '27140', '28100',
        '33100', '34100', '40100', '40130'
    )
    return city_code in designed_city

def is_tokyo_ward(city_code):
    return city_code.startswith('131') and city_code[-2:] != '00'

def is_acceptalbe_municipality(city_code):
    if city_code[2:] >= '201':
        return True
    elif is_designed_city(city_code):
        return True
    elif is_tokyo_ward(city_code):
        return True
    else:
        return False

def get_city(row):
    return (row[0].strip(), row[1].strip())

def get_value(sheet, index):
    for number in range(0, sheet.nrows):
        row = sheet.row_values(number)
        if is_municipality_row(row):
            city_code, city_name = get_city(row)
            if is_acceptalbe_municipality(city_code):
                yield [city_code, city_name, int(row[index])]

if __name__ == '__main__':
    names = (('pop', 2), ('unemp', 4), ('crime', 4))
    result = {}
    for name in names:
        book = open_workbook(name[0] + '.xls')
        sheet = book.sheet_by_index(0)

        for city_code, city_name, value in get_value(sheet, name[1]):
            result.setdefault(city_code, {})
            result[city_code]['name'] = city_name
            result[city_code][name[0]] = value

    with open('crime.csv', 'w') as f:
        writer = csv.writer(f)
        colnames = ['id', 'crime', 'unemp', 'pop']
        writer.writerow(colnames)
        for key, value in sorted(result.items()):
            row = [key] + [value[col] for col in colnames[1:]]
            writer.writerow(row)


from flask import Flask, render_template
import logging
from utils import *
from blueprint_post.views import post_blueprint
from blueprint_search.views import search_blueprint
from blueprint_userfeed.views import userfeed_blueprint

app = Flask(__name__)

app.register_blueprint(post_blueprint)
app.register_blueprint(search_blueprint)
app.register_blueprint(userfeed_blueprint)

logging.basicConfig(level=logging.INFO)
logger_api = logging.getLogger('logger_api')
file_handler = logging.FileHandler('api.log', encoding='utf-8')
formatter_one = logging.Formatter("%(asctime)s [%(levelname)s] %(message)s")
file_handler.setFormatter(formatter_one)
logger_api.addHandler(file_handler)

@app.route('/api/posts', methods=['GET'])
def api_posts():
    posts = get_posts_all()
    logger_api.info('Запрос /api/posts')
    return posts

@app.route('/api/posts/<int:post_id>', methods=['GET'])
def api_post_id(post_id):
    post = get_post_by_pk(post_id)
    logger_api.info(f'Запрос /api/posts/{post_id}')
    return post

@app.errorhandler(404)
def page_not_found(error):
    return render_template('error404.html'), error

@app.errorhandler(500)
def server_error(error):
    return render_template('error500.html'), error

@app.route('/', methods=['GET'])
def main_page():
    data_posts = get_posts_all()
    dict_of_comments = {post['pk']: get_comments_by_post_id(post['pk']) for post in data_posts}
    return render_template('index.html', data_posts=data_posts, comments=dict_of_comments)

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


import math
import time
import settings
import render

class map_manager:
    """
    Manages interactions b/w sticks and bugs

    in charge of bugs senses and of killing them after collisions
    """

    def __init__(self, stick_man, bug_man):
        self.stick_man = stick_man
        self.bug_man = bug_man

    def tick(self):
        self.stick_man.tick()
        self.bug_man.tick()

    def drawWorld(self):
        """
        aggregation function to draw all the the bugs
        and sticks of the world
        """
        render.drawSticks(self.stick_man.getSticks())
        render.drawBugs(self.bug_man.getBugs())

    def getColliders(self, bug, direction, getId=False):
        """
        returns list of sticks intersected by bugs vision vector

        bug: bug object used for point of origin
        direction: the direction of sight (in radians)
        getID: if True (default: False) return a list of stick id's instead
            of the stick objects
        """

        bug_x, bug_y = bug.location
        bug_slope = - math.tan(direction)
        colliders = []
        colliders_id = []
        for stk_id in self.stick_man.aggregatePoints():

            # retrieve stk info by unique identifier
            stk = self.stick_man.aggregatePoints()[stk_id]

            dx_start = stk.get('start')[0] - bug_x
            dx_stop = stk.get('stop')[0] - bug_x
            if (stk.get('start')[1] > bug_slope * dx_start + bug_y
                and stk.get('stop')[1] < bug_slope * dx_stop + bug_y):
                   # collision into stick with rotation < direction
                   if getId:
                       colliders_id.append(stk_id)
                   else:
                       colliders.append(stk.get('stick'))
            elif (stk.get('start')[1] < bug_slope * dx_start + bug_y
                and stk.get('stop')[1] > bug_slope * dx_stop + bug_y):
                   # collision into stick with rotation > direction
                   if getId:
                       colliders_id.append(stk_id)
                   else:
                       colliders.append(stk.get('stick'))

        if getId:
            return colliders_id
        else:
            return colliders

    def intersectPoints(self, bug, direction):
        """
        eye looks in direction (radians)

        returns a floating point representation of the distance to the nearest
        stick in the bugs vision vector
        """

        bug_x, bug_y = bug.location
        v_slope = - math.tan(direction)

        # filter booleans
        looking_up = (direction > 0 and direction < math.pi)
        looking_right = (math.cos(direction) > 0)

        bug_b = bug_y - v_slope * bug_x # b = y - m*x
        int_pnts = []
        stk_details = self.stick_man.aggregatePoints()
        colliders_id = self.getColliders(bug, direction, getId=True)
        for stk_id in colliders_id:

            stk_dict = stk_details[stk_id]
            stk = stk_dict['stick']
            start_x, start_y = stk_dict['start']
            stop_x, stop_y = stk_dict['stop']

            # filter the colliders on opposite side of vision
            if (start_y > bug_y and stop_y > bug_y
                    and looking_up):
                continue # skip
            elif (start_y < bug_y and stop_y < bug_y
                    and not looking_up):
                continue # skip

            stk_slope = float(start_y - stop_y) / float(start_x - stop_x)
            stk_b = start_y - stk_slope * start_x  # b = y - m * x
            """
            insections of vision and stick

            m1*x + b1 = m2*x + b2
                b2 - b1 = (m1 - m2)x
                x = (b2 - b1)/(m1 - m2)
            """
            int_x = float(stk_b - bug_b) / float(v_slope - stk_slope)
            int_y = bug_b + v_slope * int_x
            #int_y = stk_b + stk_slope * int_x
            int_pnts.append((int(int_x), int(int_y)))

        new_pnts = []
        for pnt_x, pnt_y in int_pnts:
            if (((pnt_y > bug_y) and looking_up)
                or ((pnt_y < bug_y) and not looking_up)
                or ((pnt_x < bug_x) and looking_right)
                or ((pnt_x > bug_x) and not looking_right)):
                    continue
            new_pnts.append((pnt_x, pnt_y))
        return (new_pnts, colliders_id)

    def diffDistance(self, coordA, coordB):
        """
        helper function returns simple distance between two coordinates
        """
        xA, yA = coordA
        xB, yB = coordB
        dsquared = (float(xA - xB)**2) + (float(yA-yB)**2)
        return math.sqrt(dsquared)

    def sightDistances(self, bug, eye_id=None):
        """
        returns dict of mappings of the bug's eye ID and floating point
        representations of the distance to the nearest stick within the vision
        vector of each

        if the eye_id does not see anything in its range, its distance value
        will be -1
        """
        distances = {}
        tot_int_pnts_in_range = []
        tot_colliders_id = []
        eye_ids = []
        # single eye mode
        if eye_id is not None:
            eye_ids = [eye_id]
        else:
            eye_ids = bug.eyes.keys()
        for eye_id in eye_ids:
            eye = bug.eyes[eye_id]
            min_distance = float('inf')
            # check the intercept points for the closest
            int_coord_list, colliders_id = self.intersectPoints(bug, eye.direction)
            int_pnts_in_range = []
            for int_coord in int_coord_list:
                distance = self.diffDistance(bug.location, int_coord)
                if distance < eye.length:
                    int_pnts_in_range.append(int_coord)
                    min_distance = min(distance, min_distance)
            # eye sees nothing
            if min_distance == float('inf'):
                min_distance = -1

            # add the eye's return value
            distances[eye_id] = min_distance
            # aggregate intercept points and colliders
            tot_int_pnts_in_range += int_pnts_in_range
            tot_colliders_id += colliders_id
        return (distances, tot_int_pnts_in_range, tot_colliders_id)


import sys

sys.stdin = open("input.txt")

# 2. 중심으로 부터의 거리를 이용하는 방식
T = int(input())
for tc in range(1, T+1):
    N = int(input())
    middle = N // 2

    farm = [list(map(int, list(input()))) for _ in range(N)]

    count = 0
    for r in range(N):
        for c in range(N):
            dr = middle - r
            if dr < 0:
                dr = -dr
            dc = middle - c
            if dc < 0:
                dc = -dc

            if 0 <= dr + dc <= middle:
                count += farm[r][c]

    print(f"#{tc} {count}")


# -*- coding: UTF-8 -*-
import os,sys
import shutil
#from django.contrib.auth import authenticate as auth

print(__file__) # 打印当前脚本路径

#modulePath = "c:\\Users\\chenhairong\\Desktop\\javaweb\\python_workspace\\python\\module"
path = os.path.dirname(__file__)
module_path = path +"\\module"
#print(module_path)
sys.path.append(module_path)

import rhc_module
from package2.pg import pg_module

def module():
    # makedirs,mkdir
    # os.makedirs(r"python\\a\\b\\c")
    if os.path.exists("test"):
        pass
    else:
        os.mkdir("test")

   # sys.path -> get system evn ivar
   # sys.argv -> get Script parameters

    #system -> exec shell cmd
    #os.system("uname")
    #os.system("ipconfig")

    # cwd,listdir
    cwd =os.getcwd()
    dir = os.listdir()
    print(f"cwd:{cwd},dir={dir}")

    #remove removedirs
    #cp file_test.py file_test_bak.py
    s = path +"\\file_test.py"
    d = path +"\\file_test_bak.py"
    try:
       shutil.copy(s,d)
    except IOError as e:
        print("Unable to copy file. %s" % e)
    except:
        print("Unexpected error:", sys.exc_info())

    os.remove(d)

    # get file properties
    pro = os.stat(s)
    print(pro)
    print(pro.st_size)
    print(os.path.getsize(s))
    #rename
    #os.rename(s,d)

    #pypi.org => 292,634 projects 2,401,871 releases 3,917,057 files 487,227 users
    #pip3 install python2-secrets

   # rhc_module.say()
   # print(sys.path)# 打印系统库路径
   # system("df -h")
#module()

def call_back(x):
    return x**2

def compare(x):
    if x > 5:
        return x

def innerFunction():
    #bool
    isB= bool(0)
    isB = bool(None)
    a = [1,0,1,1]
    isB = all(a) # all element be true  => true
    print(isB)
    isB= any(a)
    print(isB) # any element be true =>true

    #chr
    isB = chr(65) # value to ascii. A
    print(isB) # A
    #ord
    isB = ord(isB)
    print(isB) # ascii to value. 65

    #dict
    isB = dict()
    print(isB)
    isB = dict(name = "rhc",age =11)
    print(isB)

    #打印当前程序的所有变量名
   # print(dir())
   # print(__file__)# print path
    print(locals()) # 打印作用域的所有变量名 & 变量值

    #map,filter
    tmpList=list(range(10))
    res = map(call_back,tmpList) # no exec,call_back 只能一个参数
    for e in res: # exec
        print(e)
    res = filter(compare,tmpList)
    for e in res:
        print(e)

    # max
    big = max(tmpList)
    print(big,min(tmpList),sum(tmpList))

    # enumerate
    #for index,val in enumerate(range(10)):
    for index,val in enumerate(["alex","rhc"]):
        print(index,val)

    #str,type
    print(str(tmpList),type(str(tmpList)))

    #zip
    z1=["alex","jack"]
    z2=["bg","racheal","cici"]
    for i in zip(z1,z2):
        #('alex', 'bg')
        #('jack', 'racheal')
        print(i)

    # evel,exec,compile

#innerFunction()

def std_register(name,age,*args,**kwargs):#args ->array,kwargs-> dict
    print(name,age,args,args[0],kwargs)
    print(kwargs.get("addr"))

    return name,True,age,args,kwargs

# ars = std_register("a",22,"M","Girl",addr="guangzhou",hometown="hunan")
# print(ars)
# a = [1,3,4,6]
# a=[i**i for i in a]
# print(a)

# 常用字符串操作
def stringOperator():
    a = "alex li"
    print(a.center(50,"-"))
    print(a.endswith("li"))
    print(a.startswith("alex"))
    print(a.find("i"))
    print(a.isdigit())
    l=["a","b","peiqi"]
    print("-".join(l))
    #a=a.replace("l","M",1)
    #print(a)
    print(a.strip().split("l")) # strip() =>delete the \n

# build-in > global > enclose > local
#stringOperator()


# Task: Write a Python program to create a histogram from a given list of integers.

def create_histogram(numlist: list) -> None:
    for num in numlist:
        for _ in range(num):
            print("*", end=" ")
        print("\r")

create_histogram([2, 3, 6, 5])


import numpy as numpy
from astropy import units
import math
from . import Tools
from .Tools import setAttribute as setatt
from .Formatter import formatter as fmt

from .Model import Model
from .Dynamic import Dynamic
from .ExponentialPrior import ExponentialPrior
from .UniformPrior import UniformPrior
from .Prior import Prior

__author__ = "Do Kester"
__year__ = 2020
__license__ = "GPL"
__version__ = "2.5.3"
__url__ = "https://www.bayesicfitting.nl"
__status__ = "Perpetual Beta"

#  *
#  * This file is part of the BayesicFitting package.
#  *
#  * BayesicFitting is free software: you can redistribute it and/or modify
#  * it under the terms of the GNU Lesser General Public License as
#  * published by the Free Software Foundation, either version 3 of
#  * the License, or ( at your option ) any later version.
#  *
#  * BayesicFitting is distributed in the hope that it will be useful,
#  * but WITHOUT ANY WARRANTY; without even the implied warranty of
#  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
#  * GNU Lesser General Public License for more details.
#  *
#  * The GPL3 license can be found at <http://www.gnu.org/licenses/>.
#  *
#  * A JAVA version of this code was part of the Herschel Common
#  * Science System (HCSS), also under GPL3.
#  *
#  *    2003 - 2014 Do Kester, SRON (Java code)
#  *    2018 - 2020 Do Kester

class RepeatingModel( Model, Dynamic ):
    """
    RepeatingModel is a dynamic model, that calls the same model zero or more times,
    each time with the next set of parameters.

    RepeatingModel is a Dynamic model that grows and shrinks according to a growPrior.
    The growPrior defaults to ExponentialPrior, unless a maxComp (max nr of components)
    then it defaults to a UniformPrior with limits minComp .. maxComp.

    When isDynamic is set to False or minComp == maxComp, the RepeatingModel is a normal
    model with a static number of parameters/components.

    Priors and/or limits for the RepeatingModel are stored in the (encapsulated) model.

    It can be arranged that all similar parameters are the same, represented by the
    same parameters. Use keywords same=.

    Attributes
    ----------
    ncomp : int
        number of repetitions
    model : Model
        (encapsulated) model to be repeated
    same : None or int or list of int
        indices of parameters of model that get identical values
    index : list of int
        list of parameter indices not in same.
    isDyna : bool
        Whether this is a Dynamic Model.

    Attributes from Dynamic
    -----------------------
        ncomp, deltaNpar, minComp, maxComp, growPrior

    Attributes from Model
    ---------------------
        parameters, stdevs, npchain
        _next, _head, _operation
        xUnit, yUnit (relegated to model)

    Attributes from FixedModel
    --------------------------
        npmax, fixed, parlist, mlist

    Attributes from BaseModel
    --------------------------
        npbase, ndim, priors, posIndex, nonZero, tiny, deltaP, parNames

    Example
    -------
    >>> # Define a model containing between 1 and 6 VoigtModels, starting with 3
    >>> # and all with the same widths (for Gauss and Cauchy)
    >>> vgt = VoigtModel()
    >>> mdl = RepeatingModel( 3, vgt, minComp=1. maxComp=6, same=[2,3] )
    >>> print( mdl.npbase )             # 4 + 2 + 2
    >>> 8
    >>> # Define a static RepeatingModel of 5 GaussModels
    >>> gm = GaussModel()
    >>> mdl = RepeatingModel( 5, gm, isDynamic=False )
    >>> print( mdl.npbase )             # 5 * 3
    >>> 15
    >>> # Define a RepeatingModel with and exponential grow prior with scale 10
    >>> mdl = RepeatingModel( 1, gm, growPrior=ExponentialPrior( scale=10 ) )
    >>> print( mdl.npbase )             # 3
    >>> 3

    Author       Do Kester

    """
    #  *****CONSTRUCTOR*********************************************************
    def __init__( self, ncomp, model, minComp=0, maxComp=None, fixed=None,
                  same=None, growPrior=None, dynamic=True, copy=None, **kwargs ):
        """
        Repeating the same model several times.

        Parameters
        ----------
        ncomp : int
            number of repetitions
        model : Model
            model to be repeated
        minComp : int (0)
            minimum number of repetitions
        maxComp : None or int
            maximum number of repetitions
        same : None or int or list of int
            indices of parameters of model that get identical values

        growPrior : None or Prior
            governing the birth and death.
            ExponentialPrior (scale=2) if  maxOrder is None else UniformPrior
        dynamic : bool (True)
            Whether this is a Dynamic Model.
        copy : RepeatingModel
            model to copy

        Raises
        ------
        AttributeError when fixed parameters are requested
        ValueError when order is outside [min..max] range

        """
        if fixed is not None :
            raise AttributeError( "DynamicModel cannot have fixed parameters; " +
                                  " put fixed parameter(s0 in model." )
        if ncomp < minComp or ( maxComp is not None and ncomp > maxComp ) :
            raise ValueError( "ncomp outside range of [min..max] range" )

        np = ncomp * model.npchain - ( ncomp - 1 ) * Tools.length( same )
        self.isDyna = dynamic and ( maxComp is None or minComp < maxComp )

        super( RepeatingModel, self ).__init__( np, copy=copy, **kwargs )

        self.ncomp = ncomp
        self.model = model

        if copy is None :
            self.minComp = minComp
            self.maxComp = maxComp
            self.priors = model.priors          ## point to the same
        else :
            self.minComp = copy.minComp
            self.maxComp = copy.maxComp
            growPrior = copy.growPrior.copy()
            same = copy.same

        self.setSame( same )
        self.deltaNpar = len( self.index )

        if self.isDynamic() :
            if growPrior is None :
                if maxComp is None :
                    self.growPrior = ExponentialPrior( scale=2 )
                else :
                    lim = [minComp, maxComp+1]        # limits on components
                    self.growPrior = UniformPrior( limits=lim )
            else :
                self.growPrior = growPrior

    def copy( self ):
        """ Copy method.  """
        return RepeatingModel( self.ncomp, self.model, isDynamic=self.isDyna, copy=self )

    def changeNComp( self, dn ) :
        setatt( self, "ncomp", self.ncomp + dn )

    def setSame( self, same ) :
        """
        Assign similar parameters the same value.

        Parameters
        ----------
        same : None or int or [int]
            similar parameters indicated as an index in encapsulated model.
        """
        self.same = same
        if same is None :
            self.index = numpy.arange( self.model.npbase, dtype=int )
            return

        index = []
        for k in range( self.model.npbase ) :
            if not k in self.same :
                index += [k]
        self.index = numpy.array( index, dtype=int )

    def grow( self, offset=0, rng=None, **kwargs ):
        """
        Increase the the number of components by 1 (if allowed by maxComp)

        Parameters
        ----------
        offset : int
            index where the dynamic model starts
        rng : RandomState
            random numbr generator

        Return
        ------
        bool :  succes

        """
        if not self.isDynamic() :
            return False

        if self.maxComp is not None and self.ncomp >= self.maxComp:
            return False

        location = self.npbase

        dnp = self.deltaNpar if self.ncomp > 0 else self.model.npbase
        self.alterParameterSize( dnp, offset, location=location )

        head = self._head
        mdlpar = head.parameters
        k1 = location + offset
        value = numpy.zeros( dnp, dtype=float )
        if rng is not None :
            for k in range( dnp ) :
                value[k] = head.unit2Domain( rng.rand(), k + k1 )

        mdlpar = self.alterParameters( mdlpar, location, dnp, offset, value=value )

        setatt( self._head, "parameters", mdlpar )

        self.alterParameterNames( dnp )

        self.ncomp += 1

        return True

    def shrink( self, offset=0, **kwargs ):
        """
        Decrease the the number of componenets by 1 (if allowed by minComp)
        Remove an arbitrary item.

        Parameters
        ----------
        offset : int
            index where the dynamic model starts

        Return
        ------
        bool : succes

        """
        if ( not self.isDynamic() ) or self.ncomp <= self.minComp :
            return False

        location = self.npbase
        dnp = -( self.deltaNpar if self.ncomp > 1 else self.model.npbase )
        self.alterParameterSize( dnp, offset, location=location )

        head = self._head
        mdlpar = head.parameters
        mdlpar = self.alterParameters( mdlpar, location, dnp, offset )
        setatt( self._head, "parameters", mdlpar )

        self.alterParameterNames( dnp )

        self.ncomp -= 1

        return True

    def shuffle( self, param, offset, np, rng ) :
        """
        Shuffle the parameters of the components (if they are equivalent)

        Parameters
        ----------
        param : array-like
            list of all parameters
        offset : int
            index where the dynamic model starts
        np : int
            length of the parameters of the dynamic model
        rng : RNG
            random number generator
        """
        if self.ncomp <= 1 :
            return param

        off = self.model.npbase + offset
        src = numpy.arange( self.ncomp ) * self.deltaNpar + off
        per = rng.permutation( self.ncomp )
        for i in self.index :
            src[-1] = offset + i             # replace last src by index
            param[src[per]] = param[src]
            src += 1

        return param

    #  *************************************************************************
    def __setattr__( self, name, value ) :

        if self.setDynamicAttribute( name, value ) :
            return

        if name == "isDyna" :
            setatt( self, name, value, type=bool )
        elif name == "model" :
            setatt( self, name, value, type=Model )
        elif name == "same" :
            setatt( self, name, value, type=int, islist=True, isnone=True )
        elif name == "index" :
            setatt( self, name, value, type=int, islist=True, isnone=True )
        else :
            super( RepeatingModel, self ).__setattr__( name, value )

    def isDynamic( self ) :
        return self.isDyna

    #  *************************************************************************
    def baseResult( self, xdata, params ):
        """
        Returns the result of the model function.

        Parameters
        ----------
        xdata : array_like
            value at which to calculate the result
        params : array_like
             values for the parameters

        """
        result = numpy.zeros( Tools.length( xdata ), dtype=float )
        if self.ncomp == 0 :
            return result

        ke = self.model.npbase
        pars = params[:ke].copy()
        k = 1

#        print( "RM   ", self.ncomp, fmt( params, max=None ) )
        while True :
            result += self.model.result( xdata, pars )
            if k == self.ncomp :
                return result
            k += 1
            ks = ke
            ke += self.deltaNpar
#            print( "RM1  ", k, ks, ke, self.index )
            pars[self.index] = params[ks:ke]

        return result

    def basePartial( self, xdata, params, parlist=None ):
        """
        Returns the partials at the input value.

        Parameters
        ----------
        xdata : array_like
            value at which to calculate the result
        params : array_like
            values for the parameters
        parlist : array_like
            list of indices of active parameter

        """
        nxdata = Tools.length( xdata )
        partial = numpy.zeros( ( nxdata, self.npbase ), dtype=float )
        if self.ncomp == 0 :
            return partial

        ke = self.model.npbase
        pars = params[:ke].copy()
        full = numpy.arange( self.model.npbase, dtype=int )
        k = 1
        while True :
            partial[:,full] += self.model.partial( xdata, pars )
            if k == self.ncomp :
                break
            k += 1
            ks = ke
            ke += self.deltaNpar

            full[self.index] = [k for k in range( ks, ke )]
            pars[self.index] = params[ks:ke]

        if parlist is None :
            return partial

        return partial[:,parlist]

    def baseDerivative( self, xdata, params ):
        """
        Returns the derivative df/dx at the input value.

        Parameters
        ----------
        xdata : array_like
            value at which to calculate the result
        params : array_like
             values for the parameters

        """
        dfdx = numpy.zeros( Tools.length( xdata ), dtype=float )
        if self.ncomp == 0 :
            return dfdx

        ke = self.model.npbase
        pars = params[:ke].copy()
        k = 1
        while True :
            dfdx += self.model.derivative( xdata, pars )
            if k == self.ncomp :
                return dfdx
            k += 1
            ks = ke
            ke += self.deltaNpar
            pars[self.index] = params[ks:ke]

        return dfdx

    def setLimits( self, lowLimits=None, highLimits=None ) :
        self.model.setLimits( lowLimits=lowLimits, highLimits=highLimits )

    def hasPriors( self ) :
        return self.model.hasPriors()

    def basePrior( self, k ):
        """
        Return the prior for parameter k.

        Parameters
        ----------
        k : int
            the parameter to be selected.
        """
        i,k = self.par2model( k )
        return self.model.getPrior( i )

    def baseName( self ):
        """ Return a string representation of the model.  """
        return ( "Repeat %d times:\n  " % self.ncomp + self.model.baseName( ) )

    def baseParameterName( self, k ):
        """
        Return the name of the indicated parameter.

        Parameters
        ----------
        k : int
            parameter number.

        """
        i,k = self.par2model( k )
        return self.model.getParameterName( i ) + "_%d" % k

    def baseParameterUnit( self, k ):
        """
        Return the unit of the indicated parameter.

        Parameters
        ----------
        k : int
            parameter number.

        """
        self.model.xUnit = self.xUnit
        self.model.yUnit = self.yUnit

        i,k = self.par2model( k )
        return self.model.getParameterUnit( i )

    def par2model( self, k ) :
        """
        Return index in model and repetition nr for param k
        """
        if k >= self.model.npchain :
            k -= self.model.npchain
            i = self.index[ k % self.deltaNpar ]
            k = 1 + k // self.deltaNpar
        else :
            i = k
            k = 0
        return i, k


# 비트마스크의 이용
# 1, 3, 5 방문했다면
# visited[1][0][1][0][1] = 1
# visited[10101] = 1
# 2^5 개의 노드 관리 가능.

# memo[cur][visited] = 현재 i 도시에 있고,
# 이 도시에서 visited 노드들을 거쳐 0으로 향하는 경로 중 최소값
# memo[cur][visited] = min(w[cur][next]+memo[next][방문 안한 남은거])

# << 오른쪽에 0을 추가
# >> 왼쪽에 0(0 또는 양의 정수) / 1(음의 정수)를 추가, 가장 오른쪽 1비트 사라짐

# (1 << n) - 1 은 n개의 비트를 모두 켜는 것. 1000000000000 - 1 이런식이니까 다 1이 되겠지?

# 시간복잡도 계산
# 하나의 사이클이 있다면 시작점은 중요하지 않다.
# 즉 현재 방문한 변수(cur)를 n개 돌리고,
# n개의 노드가 방문했는지 안했는지 0과 1로 돌리기에 2^n
# n *(2^n)
import sys
input = sys.stdin.readline

n = int(input())
w = []

for _ in range(n):
    w.append(list(map(int, input().split())))

INF = int(1e9)
VISITED_ALL = (1 << n) - 1
memo = [[None for _ in range(2**n)] for _ in range(n)]

def travel(cur, visited):
    # 전체 방문했다면
    if visited == VISITED_ALL:
        # 마지막 노드에서 0으로 돌아올 수 있다면 그대로 return
        if w[cur][0]:
            return w[cur][0]
        # 돌아올 수 없으면 INF 값 넣기
        else:
            return INF

    # 이미 방문했다면 원래 값 반환
    if memo[cur][visited] is not None:
        return memo[cur][visited]

    # 최소거리 구하기 시작
    min_dist = INF
    for j in range(n):
        # cur에서 j가 연결되어있지 않다면
        if not w[cur][j]:
            continue
        # 이미 방문한 도시면(visited 안에 j가 있으면)
        if visited & (1 << j):
            continue

        # cur부터 j까지의 거리 + travel(j, visited에 j 추가)
        min_dist = min(min_dist, w[cur][j] + travel(j, visited | (1 << j)))

    memo[cur][visited] = min_dist
    return memo[cur][visited]

print(travel(0, 1))


from langchain.prompts import (
    HumanMessagePromptTemplate,
    SystemMessagePromptTemplate,
    ChatPromptTemplate,
    FewShotChatMessagePromptTemplate,
)

from langchain.chat_models import ChatOpenAI

from llmner.utils import (
    dict_to_enumeration,
    inline_annotation_to_annotated_document,
    align_annotation,
    annotated_document_to_few_shot_example,
    detokenizer,
    annotated_document_to_conll,
)

from llmner.templates import SYSTEM_TEMPLATE_EN

from typing import List, Dict
from llmner.data import (
    AnnotatedDocument,
    AnnotatedDocumentWithException,
    NotContextualizedError,
    Conll,
)

from tqdm import tqdm

from concurrent.futures import ThreadPoolExecutor, as_completed
import multiprocessing

CPU_COUNT = multiprocessing.cpu_count()

import logging

logger = logging.getLogger(__name__)

class BaseNer:
    """Base NER model class. All NER models should inherit from this class."""

    def __init__(
        # TODO: add env variables
        self,
        model: str = "gpt-3.5-turbo",
        max_tokens: int = 256,
        stop: List[str] = ["###"],
        temperature: float = 1.0,
        model_kwargs: Dict = {},
    ):
        """NER model. Make sure you have at least the OPENAI_API_KEY environment variable set with your API key. Refer to the python openai library documentation for more information.

        Args:
            model (str, optional): Model name. Defaults to "gpt-3.5-turbo".
            max_tokens (int, optional): Max number of new tokens. Defaults to 256.
            stop (List[str], optional): List of strings that should stop generation. Defaults to ["###"].
            temperature (float, optional): Temperature for the generation. Defaults to 1.0.
            model_kwargs (Dict, optional): Arguments to pass to the llm. Defaults to {}. Refer to the OpenAI python library documentation and OpenAI API documentation for more information.
        """
        self.max_tokens = max_tokens
        self.stop = stop
        self.model = model
        self.chat_template = None
        self.model_kwargs = model_kwargs
        self.temperature = temperature

    def query_model(self, messages: list, request_timeout: int = 600):
        chat = ChatOpenAI(
            model_name=self.model,  # type: ignore
            max_tokens=self.max_tokens,
            temperature=self.temperature,
            model_kwargs=self.model_kwargs,
            request_timeout=request_timeout,
        )
        completion = chat.invoke(messages, stop=self.stop)
        return completion

class ZeroShotNer(BaseNer):
    """Zero-shot NER model class."""

    def contextualize(
        self,
        entities: Dict[str, str],
        prompt_template: str = SYSTEM_TEMPLATE_EN,
        system_message_as_user_message: bool = False,
    ):
        """Method to ontextualize the zero-shot NER model. You don't need examples to contextualize this model.

        Args:
            entities (Dict[str, str]): Dict containing the entities to be recognized. The keys are the entity names and the values are the entity descriptions.
            prompt_template (str, optional): Prompt template to send the llm as the system message. Defaults to a prompt template for NER in English.
            system_message_as_user_message (bool, optional): If True, the system message will be sent as a user message. Defaults to False.
        """
        self.entities = entities
        if not system_message_as_user_message:
            system_template = SystemMessagePromptTemplate.from_template(prompt_template)
        else:
            system_template = HumanMessagePromptTemplate.from_template(prompt_template)
        self.system_message = system_template.format(
            entities=dict_to_enumeration(entities), entity_list=list(entities.keys())
        )
        self.chat_template = ChatPromptTemplate.from_messages(
            [
                self.system_message,
                HumanMessagePromptTemplate.from_template("{x}"),
            ]
        )

    def fit(self, *args, **kwargs):
        """Just a wrapper for the contextualize method. This method is here to be compatible with the sklearn API."""
        return self.contextualize(*args, **kwargs)

    def _predict(
        self, x: str, request_timeout: int
    ) -> AnnotatedDocument | AnnotatedDocumentWithException:
        messages = self.chat_template.format_messages(x=x)
        try:
            completion = self.query_model(messages, request_timeout)
        except Exception as e:
            logger.warning(
                f"The completion for the text '{x}' raised an exception: {e}"
            )
            return AnnotatedDocumentWithException(
                text=x, annotations=set(), exception=e
            )
        logger.debug(f"Completion: {completion}")
        annotated_document = inline_annotation_to_annotated_document(
            completion.content, list(self.entities.keys())
        )
        aligned_annotated_document = align_annotation(x, annotated_document)
        y = aligned_annotated_document
        return y

    def _predict_tokenized(self, x: List[str], request_timeout: int) -> Conll:
        detokenized_text = detokenizer(x)
        annotated_document = self._predict(detokenized_text, request_timeout)
        if isinstance(annotated_document, AnnotatedDocumentWithException):
            logger.warning(
                f"The completion for the text '{detokenized_text}' raised an exception: {annotated_document.exception}"
            )
        conll = annotated_document_to_conll(annotated_document)
        if not len(x) == len(conll):
            logger.warning(
                "The number of tokens and the number of conll tokens are different"
            )
        return conll

    def _predict_parallel(
        self, x: List[str], max_workers: int, progress_bar: bool, request_timeout: int
    ) -> List[AnnotatedDocument | AnnotatedDocumentWithException]:
        y = []
        with ThreadPoolExecutor(max_workers=max_workers) as executor:
            for annotated_document in tqdm(
                executor.map(lambda x: self._predict(x, request_timeout), x),
                disable=not progress_bar,
                unit=" example",
                total=len(x),
            ):
                y.append(annotated_document)
        return y

    def _predict_tokenized_parallel(
        self,
        x: List[List[str]],
        max_workers: int,
        progress_bar: bool,
        request_timeout: int,
    ) -> List[List[Conll]]:
        y = []
        with ThreadPoolExecutor(max_workers=max_workers) as executor:
            for conll in tqdm(
                executor.map(lambda x: self._predict_tokenized(x, request_timeout), x),
                disable=not progress_bar,
                unit=" example",
                total=len(x),
            ):
                y.append(conll)
        return y

    def _predict_serial(
        self, x: List[str], progress_bar: bool, request_timeout: int
    ) -> List[AnnotatedDocument | AnnotatedDocumentWithException]:
        y = []
        for text in tqdm(x, disable=not progress_bar, unit=" example"):
            annotated_document = self._predict(text, request_timeout)
            y.append(annotated_document)
        return y

    def _predict_tokenized_serial(
        self, x: List[List[str]], progress_bar: bool, request_timeout: int
    ) -> List[List[Conll]]:
        y = []
        for tokenized_text in tqdm(x, disable=not progress_bar, unit=" example"):
            conll = self._predict_tokenized(tokenized_text, request_timeout)
            y.append(conll)
        return y

    def predict(
        self,
        x: List[str],
        progress_bar: bool = True,
        max_workers: int = 1,
        request_timeout: int = 600,
    ) -> List[AnnotatedDocument | AnnotatedDocumentWithException]:
        """Method to perform NER on a list of strings.

        Args:
            x (List[str]): List of strings.
            progress_bar (bool, optional): If True, a progress bar will be displayed. Defaults to True.
            max_workers (int, optional): Number of workers to use for parallel processing. If -1, the number of workers will be equal to the number of CPU cores. Defaults to 1.
            request_timeout (int, optional): Timeout in seconds for the requests. Defaults to 600 seconds.

        Raises:
            NotContextualizedError: Error if the model is not contextualized before calling the predict method.
            ValueError: The input must be a list of strings.

        Returns:
            List[AnnotatedDocument | AnnotatedDocumentWithException]: List of AnnotatedDocument objects if there were no exceptions, a list of AnnotatedDocumentWithException objects if there were exceptions.
        """
        if self.chat_template is None:
            raise NotContextualizedError(
                "You must call the contextualize method before calling the predict method"
            )
        if not isinstance(x, list):
            raise ValueError("x must be a list")
        if isinstance(x[0], str):
            if max_workers == -1:
                y = self._predict_parallel(x, CPU_COUNT, progress_bar, request_timeout)
            elif max_workers == 1:
                y = self._predict_serial(x, progress_bar, request_timeout)
            elif max_workers > 1:
                y = self._predict_parallel(
                    x, max_workers, progress_bar, request_timeout
                )
            else:
                raise ValueError("max_workers must be greater than 0")
        else:
            raise ValueError(
                "x must be a list of strings, maybe you want to use predict_tokenized instead?"
            )
        return y

    def predict_tokenized(
        self,
        x: List[List[str]],
        progress_bar: bool = True,
        max_workers: int = 1,
        request_timeout: int = 600,
    ) -> List[List[Conll]]:
        """Method to perform NER on a list of tokenized documents.

        Args:
            x (List[List[str]]): List of lists of tokens.
            progress_bar (bool, optional): If True, a progress bar will be displayed. Defaults to True.
            max_workers (int, optional): Number of workers to use for parallel processing. If -1, the number of workers will be equal to the number of CPU cores. Defaults to 1.
            request_timeout (int, optional): Timeout in seconds for the requests. Defaults to 600 seconds.

        Returns:
            List[List[Conll]]: List of lists of tuples of (token, label).
        """
        if not isinstance(x, list):
            raise ValueError("x must be a list")
        if isinstance(x[0], list):
            if max_workers == -1:
                y = self._predict_tokenized_parallel(
                    x, CPU_COUNT, progress_bar, request_timeout
                )
            elif max_workers == 1:
                y = self._predict_tokenized_serial(x, progress_bar, request_timeout)
            elif max_workers > 1:
                y = self._predict_tokenized_parallel(
                    x, max_workers, progress_bar, request_timeout
                )
            else:
                raise ValueError("max_workers must be greater than 0")
        else:
            raise ValueError(
                "x must be a list of lists of tokens, maybe you want to use predict instead?"
            )
        return y

class FewShotNer(ZeroShotNer):
    def contextualize(
        self,
        entities: Dict[str, str],
        examples: List[AnnotatedDocument],
        prompt_template: str = SYSTEM_TEMPLATE_EN,
        system_message_as_user_message: bool = False,
    ):
        """Method to ontextualize the few-shot NER model. You need examples to contextualize this model.

        Args:
            entities (Dict[str, str]): Dict containing the entities to be recognized. The keys are the entity names and the values are the entity descriptions.
            examples (List[AnnotatedDocument]): List of AnnotatedDocument objects containing the annotated examples.
            prompt_template (str, optional): Prompt template to send the llm as the system message. Defaults to a prompt template for NER in English. Defaults to a prompt template for NER in English.
            system_message_as_user_message (bool, optional): If True, the system message will be sent as a user message. Defaults to False.
        """
        self.entities = entities
        if not system_message_as_user_message:
            system_template = SystemMessagePromptTemplate.from_template(prompt_template)
        else:
            system_template = HumanMessagePromptTemplate.from_template(prompt_template)
        self.system_message = system_template.format(
            entities=dict_to_enumeration(entities), entity_list=list(entities.keys())
        )
        example_template = ChatPromptTemplate.from_messages(
            [("human", "{input}"), ("ai", "{output}")]
        )
        few_shot_template = FewShotChatMessagePromptTemplate(
            examples=list(map(annotated_document_to_few_shot_example, examples)),
            example_prompt=example_template,
        )
        self.chat_template = ChatPromptTemplate.from_messages(
            [
                self.system_message,
                few_shot_template,
                HumanMessagePromptTemplate.from_template("{x}"),
            ]
        )


from typing import List

from sqlalchemy import delete
from app.crud.crud_base import CRUDBase
from app.models.form_element_option import FormElementOption
from app.schemas import (
    FormElementOptionCreate,
    FormElementOptionUpdate,
)
from sqlalchemy.orm import Session
from app.db import session

class CRUDFormElementOption(
    CRUDBase[
        FormElementOption,
        FormElementOptionCreate,
        FormElementOptionUpdate,
    ]
):
    # def bulk_create(
    #     self,
    #     db: Session,
    #     *,
    #     objs_in: List[FormElementOptionCreate]
    # ) -> FormElementOption:
    #     db_objs = list()
    #     for obj_in in objs_in:
    #         db_obj = FormElementOption(
    #             value=obj_in.value,
    #             form_element_field_id=obj_in.form_element_field_id,
    #         )
    #         db_objs.append(db_obj)
    #     db.bulk_save_objects(db_objs)
    #     db.commit()
    #     return "Ok"

    def get_by_name_and_form_element_field_id(
        self,
        db: Session,
        *,
        form_element_field_id: str,
        value: str
    ) -> FormElementOption:
        return (
            db.query(self.model)
            .filter(
                FormElementOption.form_element_field_id
                == form_element_field_id
                and FormElementOption.value == value.lower()
            )
            .first()
        )

    def delete_by_form_element_field_id(
        self, db: Session, *, form_element_field_id: str
    ):
        # rows = db.query(self.model).filter(
        #     self.model.form_element_template_id
        #     == form_element_template_id
        # )

        # db.query(self.model).filter(
        #     self.model.form_element_template_id
        #     == form_element_template_id
        # ).delete()

        # delete_q = self.model.__table__.delete().where(
        #     self.model.form_element_template_id
        #     == form_element_template_id
        # )
        # session.engine.execute(delete_q)
        # db.session.execute(delete_q)
        # db.session.commit()

        statement = delete(self.model).where(
            self.model.form_element_field_id == form_element_field_id
        )
        # session.exec(statement)
        session.engine.execute(statement)
        # rows = query.statement.execute().fetchall()
        # for row in rows:
        #     print("row")
        #     print(row)
        # if not row:
        #     raise HTTPException(status_code=404, detail="Row not found")
        # db.delete(row)
        # db.commit()
        return "Ok"
        # return rows

form_element_option = CRUDFormElementOption(
    FormElementOption
)


import random
class RandomizedSet:

    def __init__(self):
        """
        Initialize your data structure here.
        """
        self.hashmap = {}  # Dictionary maintains key as value to be inserted/deleted, and value as the index for
        # that item in nums list. For deletion, update the lastItem's content to point to the index of the to-be-deleted
        # item, then delete the to-be-deleted-item's key.

        self.nums = []  # Keep appending to this list for every insertion, and for deletion: overwrite the current
        # location of the item with the last item, then pop off the last time.

    def insert(self, val):
        """
        Inserts a value to the set. Returns true if the set did not already contain the specified element.
        :type val: int
        :rtype: bool
        """
        if val in self.hashmap:
            return False
        self.nums.append(val)
        self.hashmap[val] = len(self.nums) - 1
        return True

    def remove(self, val):
        """
        Removes a value from the set. Returns true if the set contained the specified element.
        :type val: int
        :rtype: bool

        To remove na existing item, overwrite the location of the item with the content in the last location of the
        array, also re-point the location of the last item in the array to point to the location of the to-be-deleted item, then pop off the last item of the array, and delete the the to-be-deleted item key in dict.

        """
        if val not in self.hashmap:
            return False

        pos = self.hashmap[val]  # Location of the item to be deleted.
        lastItem = self.nums[-1]  # Content of last item

        if val != lastItem:  # No need to perform index re-assignment and hash replacement if deleted item is same as last item
            self.nums[pos] = lastItem  # Overwrite the item to the the last item in the list.
            self.hashmap[lastItem] = pos  # Update hashmap so the last item points to where the deleted item was.

        self.nums.pop()  # Get rid of last item in array, O(1)
        del self.hashmap[val]  # Get rid of last item in dict, O(1)

        return True

    def getRandom(self):
        """
        Get a random element from the set.
        :rtype: int
        """
        randomPos = random.randint(0, len(self.nums) - 1)
        return self.nums[randomPos]

# Your RandomizedSet object will be instantiated and called as such:
# obj = RandomizedSet()
# param_1 = obj.insert(val)
# param_2 = obj.remove(val)
# param_3 = obj.getRandom()


"""
作业03

@author Aaric
@version 0.3.0-SNAPSHOT
"""
import os
import numpy as np
import pymongo as pm
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LinearRegression
from keras.models import Sequential
from keras.layers import Dense

"""
mongo_client
"""
mongo_client = pm.MongoClient("mongodb://10.0.11.50:27017")
mongo_db = mongo_client["ai"]
db_collection = mongo_db["signal_gb"]
# print(db_collection)

"""
query socs (n>=100000)
"""
# condition and projection
n = 100000
query_condition = {
    # "vehicleType": "AS24",
    "vehicleBaseData_vehicleStatus": 1,  # 车辆状态：1-启动，2-熄火，3-其他
    "vehicleBaseData_chargeStatus": 3,  # 充电状态：1-停车充电，2-行驶充电，3-未充电，4-充电完成
    "vehicleBaseData_runMode": 1  # 运行状态：1-纯电，2-混动，3-燃油
}
query_projection = {
    "vin": 1,
    "vehicleBaseData_soc": 1
}

# query data
soc_items = []
data_rows = db_collection.find(query_condition, projection=query_projection).limit(n + 31).skip(1)
for row in data_rows:
    soc_items.append(row["vehicleBaseData_soc"])
print("soc_items len: ", len(soc_items))

"""
features and soc_targets
"""
soc_features = []
soc_targets = []
for i in range(0, n):
    j = i + 30
    k = i + 31
    soc_features.append(soc_items[i:j])
    soc_targets.append(soc_items[j:k])
print("soc_features len: ", len(soc_features))
print("soc_targets len:", len(soc_targets))

"""
train score
"""
x_data = np.asarray(soc_features).reshape(n, 30)
y_data = np.asarray(soc_targets)
# print(x_data)
# print(y_data)

x_train, x_test, y_train, y_test = train_test_split(x_data, y_data)
print("tts: ", x_train.shape, x_test.shape, y_train.shape, y_test.shape)

lr = LinearRegression()
train_model = lr.fit(x_train, y_train)

train_score = train_model.score(x_test, y_test)
print("score: ", train_score)

"""
train loss
"""
os.environ["TF_CPP_MIN_LOG_LEVEL"] = "2"
model = Sequential()
model.add(Dense(10, activation='relu', input_shape=(x_train.shape[1],)))
model.add(Dense(1))
model.compile(loss='mse', optimizer='rmsprop')
model.summary()
model.fit(x_train, y_train, batch_size=1000, epochs=256, validation_data=(x_test, y_test))


def solve():
    n=int(input())
    print(apart(n))

def apart(n):
    p1=int(n/2)
    p2=int(n/3)
    p3=int(n/4)

    ps=p1+p2+p3
    if ps>n:
        return apart(p1)+apart(p2)+apart(p3)
    else:
        return n

if  __name__ == '__main__' :
    total=int(input())
    for _ in range(total):
        solve()


import pandas as pd
from sklearn.metrics.pairwise import cosine_similarity
df_ratings = pd.read_csv("ratings.csv")
df_movies = pd.read_csv("movies.csv")
print(df_movies.info())
print(df_ratings.info())
df_ratings.drop('timestamp', axis=1, inplace=True)
print(df_ratings.head())
user_item_rating = pd.merge(df_ratings, df_movies, on="movieId")
print(user_item_rating.head())
movie_matrix = user_item_rating.pivot_table("rating"
                                , index="title",columns="userId")

print(movie_matrix.head())
# 널값 0으로
movie_matrix.fillna(0, inplace=True)
# 유사도 비교
item_cf = cosine_similarity(movie_matrix)
print(item_cf)
result_df = pd.DataFrame(data=item_cf, index=movie_matrix.index
                         , columns=movie_matrix.index)
print(result_df)
def get_item_based(title):
    # asc 오름 False-> desc
    return result_df[title].sort_values(ascending=False)[:10]
while True:
    text = input("좋아하는 영화 이름을 정확하게 입력하세요:")
    print(get_item_based(text))


# -*- coding: utf-8 -*-
"""
Created on Mon Sep 19 13:06:07 2022

@author: jingy
"""

def repeater(string,length,repeat):
    new_string = string[0:(length)]
    return new_string*repeat

def isPalindrome(s):
    s = str(s)
    if (len(s))%2 != 0:
        splice = int(((len(s)+1)/2))
        first_half = s[:splice]
        second_half = s[-1:(-splice)-1:-1]
    else:
       splice = int(((len(s))/2))
       first_half = s[:splice]
       second_half = s[-1:(-splice)-1:-1]
    if first_half == second_half:
        return True
    else:
        return False

def draw_grid(n):
    for i in range(1,n+1):
        for i in range(1,n+1):
            print(f'+ {"- "*4}',end='')
        print('+')
        for i in range(4):
            for i in range(1,n+1):
                print(f'{"|":10}',end='')
            print('|')
    for i in range(1,n+1):
        print(f'+ {"- "*4}',end='')
    print('+')

if __name__ == '__main__':
    print(repeater('jing',4,5))

    palindrome_odometer = []
    for i in range(100000,1000000):
        i = str(i)
        last_four = i[-1:-5:-1]
        if not isPalindrome(last_four):
            continue
        elif isPalindrome(last_four):
            i = int(i)
            i+=1
            i = str(i)
            last_five = i[-1:-6:-1]
            if isPalindrome(last_five):
                i = int(i)
                i+=1
                i = str(i)
                middle_four = i[1:5]
                if isPalindrome(middle_four):
                    i = int(i)
                    i+=1
                    i = str(i)
                    if isPalindrome(i):
                        i = int(i)
                        i-=3
                        palindrome_odometer.append(i)

    draw_grid(3)


#!/usr/bin/env python
from __future__ import print_function
import sys
import math
import numpy as np

#ROS Imports
import rospy
from sensor_msgs.msg import Image, LaserScan
from ackermann_msgs.msg import AckermannDriveStamped, AckermannDrive

#PID CONTROL PARAMS
kp = 1.0
kd = 0.5
ki = 0.5
servo_offset = 0.0
prev_error = 0.0
error = 0.0
integral = 0.0

#WALL FOLLOW PARAMS
ANGLE_RANGE = 270 # Hokuyo 10LX has 270 degrees scan
DESIRED_DISTANCE_RIGHT = 0.9 # meters
DESIRED_DISTANCE_LEFT = 0.55
VELOCITY = 2.0 # meters per second
CAR_LENGTH = 0.50 # Traxxas Rally is 20 inches or 0.5 meters

class WallFollow:
    """
    Receives lidar data and publishes Ackermann drive data for left wall follow
    """
    def __init__(self):
        #Topics & Subs, Pubs
        lidarscan_topic = '/scan'
        drive_topic = '/nav'

        self.lidar_sub = rospy.Subscriber('scan', LaserScan, self.lidar_callback)
        self.drive_pub = rospy.Publisher('drive', AckermannDriveStamped, queue_size=10)

    def getRange(self, data, angle):
        # data: single message from topic /scan
        # angle: between egrees, where 0 degrees is directly ahead
        # Outputs length in meters to object with angle in lidar scan field of view
        idx = int((angle - data.angle_min) / data.angle_increment)
        while data.ranges[idx] > data.angle_max or data.ranges[idx] < data.angle_min:
            idx = idx + 1
        return data.ranges[idx]

    def pid_control(self, error, velocity):
        global integral
        global prev_error
        global kp
        global ki
        global kd

        angle = -kp*error

        drive_msg = AckermannDriveStamped()
        drive_msg.header.stamp = rospy.Time.now()
        drive_msg.header.frame_id = "laser"
        drive_msg.drive.steering_angle = angle
        drive_msg.drive.speed = velocity
        self.drive_pub.publish(drive_msg)

    def followLeft(self, data, leftDist):
        phi_a = np.pi/3
        theta = np.pi/6

        a = self.getRange(data, phi_a)
        b = self.getRange(data, phi_a + theta)

        alpha = np.arctan((b - a*np.cos(theta)) / (a*np.sin(theta)))
        L = VELOCITY * 0.1
        D_next = b*np.cos(alpha) - L*np.sin(alpha)
        e_t = DESIRED_DISTANCE_LEFT - D_next
        return e_t

    def lidar_callback(self, data):
        error = self.followLeft(data, DESIRED_DISTANCE_LEFT)
        #send error to pid_control
        self.pid_control(error, VELOCITY)

def main(args):
    rospy.init_node("WallFollow_node", anonymous=True)
    wf = WallFollow()
    rospy.sleep(0.1)
    rospy.spin()

if __name__=='__main__':
	main(sys.argv)


def solve(m, p):
    l = []
    for k  in range(0,len(m)):
        for x in range(0,len(m[0])):
            l.append(m[k][x])
    l=sorted(l)
    #print(l)
    return l[p-1]
if __name__ == '__main__':
    x=int(input())
    m=[]
    c=0
    while c<x:
        n=input().split(",")
        n=list(map(int,n))
        m.append(n)
        c=c+1
    k=int(input())
    print(solve(m,k))


#Iteratively...
def binsearch(A, key):
    low = 0
    high = len(A) - 1
    while low <= high:
        mid = (low + high) // 2 #integer division
        if key == A[mid]:
            return True
        elif key < A[mid]:
            high = mid - 1
        else: # (key > A[mid])
            low = mid + 1
    return False

A = [1,2,3,4,5,6]
key = input("Enter the element you are searching for: ")
found = binsearch(A, int(key))
print("Element " + key + " is in the array: ", found)