import numpy as np
import os
import cv2
from dota_utils import wordname_18
# from xml.dom.minidom import parse
# import xml.dom.minidom
# from PIL import Image
import pickle
import json

cls18_dict = {'__background__': 0 ,
            'airport': 1 , 'baseball-diamond': 2 , 'basketball-court': 3 , 'bridge': 4 , 'container-crane': 5 ,
            'ground-track-field': 6 , 'harbor': 7 , 'helicopter': 8 , 'helipad': 9 , 'large-vehicle': 10 ,
            'plane': 11 , 'roundabout': 12 , 'ship': 13 , 'small-vehicle': 14 , 'soccer-ball-field': 15 ,
            'storage-tank': 16 , 'swimming-pool': 17 , 'tennis-court': 18 }

cls15_dict = {'__background__': 0 ,
            'plane': 1 , 'baseball-diamond': 2 , 'bridge': 3 , 'ground-track-field': 4 , 'small-vehicle': 5 ,
            'large-vehicle': 6 , 'ship': 7 , 'tennis-court': 8 , 'basketball-court': 9 , 'storage-tank': 10 ,
            'soccer-ball-field': 11 , 'roundabout': 12 , 'harbor': 13 , 'swimming-pool': 14 , 'helicopter': 15 }

cls15_list = ['__background__',
              'plane', 'baseball-diamond', 'bridge', 'ground-track-field', 'small-vehicle',
              'large-vehicle', 'ship', 'tennis-court', 'basketball-court', 'storage-tank',
              'soccer-ball-field', 'roundabout', 'harbor', 'swimming-pool', 'helicopter']

def get_dota_PKL(img_dir, label_dir, save_path, cls_dict):
    img_file_type = "png"
    label_file_type = "txt"

    file_list = os.listdir(img_dir)

    img_list = []

    for file_name in file_list:
        split = file_name.split(".")
        if split[len(split) - 1] == img_file_type:
            img_list.append(file_name)
    img_list.sort()
    gt_list = []
    for img_ind in range(len(img_list)):
        split = img_list[img_ind].split(".")
        gt_list.append(split[0] + "." + label_file_type)

    im_infos = []
    for index in range(len(img_list)):
        img_name = os.path.join(img_dir, img_list[index])
        gt_name = os.path.join(label_dir, gt_list[index])
        boxes = []

        # print gt_name
        gt_obj = open(gt_name, 'r')
        gt_txt = gt_obj.read()

        gt_split = gt_txt.split('\n')
        # print('len(gt_txt:', len(gt_txt))
        # print('len(gt_split:', len(gt_split))
        if not len(gt_split)-1:
            # print(gt_name)
            continue

        print('name:', img_name)
        img = cv2.imread(img_name)

        for gt_line in gt_split:
            gt_ind = gt_line.split(' ')
            if len(gt_ind) > 3:
                # condinate_list = gt_ind[2].split(' ')
                pt1 = (int(float(gt_ind[0])), int(float(gt_ind[1])))
                pt2 = (int(float(gt_ind[2])), int(float(gt_ind[3])))
                pt3 = (int(float(gt_ind[4])), int(float(gt_ind[5])))
                pt4 = (int(float(gt_ind[6])), int(float(gt_ind[7])))

                edge1 = np.sqrt((pt1[0] - pt2[0]) * (pt1[0] - pt2[0]) + (pt1[1] - pt2[1]) * (pt1[1] - pt2[1]))
                edge2 = np.sqrt((pt2[0] - pt3[0]) * (pt2[0] - pt3[0]) + (pt2[1] - pt3[1]) * (pt2[1] - pt3[1]))

                angle = 0

                if edge1 > edge2:
                    width = edge1
                    height = edge2
                    if pt1[0] - pt2[0] != 0:
                        angle = -np.arctan(float(pt1[1] - pt2[1]) / float(pt1[0] - pt2[0])) / 3.1415926 * 180
                    else:
                        angle = 90.0
                elif edge2 >= edge1:
                    width = edge2
                    height = edge1
                    # print pt2[0], pt3[0]
                    if pt2[0] - pt3[0] != 0:
                        angle = -np.arctan(float(pt2[1] - pt3[1]) / float(pt2[0] - pt3[0])) / 3.1415926 * 180
                    else:
                        angle = 90.0
                if angle < -45.0:
                    angle = angle + 180

                x_ctr = float(pt1[0] + pt3[0]) / 2  # pt1[0] + np.abs(float(pt1[0] - pt3[0])) / 2
                y_ctr = float(pt1[1] + pt3[1]) / 2  # pt1[1] + np.abs(float(pt1[1] - pt3[1])) / 2

                boxes.append([x_ctr, y_ctr, height, width, angle, gt_ind[8]])

        cls_num = len(cls_dict.keys())

        gt_boxes = []  # np.zeros((len_of_bboxes, 5), dtype=np.int16)
        gt_classes = []  # np.zeros((len_of_bboxes), dtype=np.int32)
        overlaps = []  # np.zeros((len_of_bboxes, cls_num), dtype=np.float32) #text or non-text
        seg_areas = []  # np.zeros((len_of_bboxes), dtype=np.float32)

        # print ("boxes_size:", len(boxes))
        for idx in range(len(boxes)):
            if not boxes[idx][5] in cls_dict:
                print (boxes[idx][5] + " not in list")
                continue
            gt_classes.append(cls_dict[boxes[idx][5]])  # cls_text
            overlap = np.zeros((cls_num))
            overlap[cls_dict[boxes[idx][5]]] = 1.0  # prob
            overlaps.append(overlap)
            seg_areas.append((boxes[idx][2]) * (boxes[idx][3]))
            gt_boxes.append([boxes[idx][0], boxes[idx][1], boxes[idx][2], boxes[idx][3], boxes[idx][4]])

        gt_classes = np.array(gt_classes)
        overlaps = np.array(overlaps)
        seg_areas = np.array(seg_areas)
        gt_boxes = np.array(gt_boxes)

        max_overlaps = overlaps.max(axis=1)
        # gt class that had the max overlap
        max_classes = overlaps.argmax(axis=1)
        # print(gt_name, 'box shape:', gt_boxes.shape)

        im_info = {
            'gt_classes': gt_classes,
            'max_classes': max_classes,
            'image': img_name,
            'boxes': gt_boxes,
            'flipped': False,
            'gt_overlaps': overlaps,
            'seg_areas': seg_areas,
            'height': img.shape[0],
            'width': img.shape[1],
            'max_overlaps': max_overlaps,
            'rotated': True
        }
        # print('bbox', im_info["boxes"].shape)
        im_infos.append(im_info)
        # if index>=1500:
        #     break
        # print('index:{}'.fromat(index), len(img_list))
    f_save_pkl = open(save_path, 'wb')
    pickle.dump(im_infos, f_save_pkl)
    f_save_pkl.close()
    return im_infos

def get_box(gt_line):
    gt_ind = gt_line.split(' ')
    if len(gt_ind) > 3:
        # condinate_list = gt_ind[2].split(' ')
        pt1 = (int(float(gt_ind[0])), int(float(gt_ind[1])))
        pt2 = (int(float(gt_ind[2])), int(float(gt_ind[3])))
        pt3 = (int(float(gt_ind[4])), int(float(gt_ind[5])))
        # pt4 = (int(float(gt_ind[6])), int(float(gt_ind[7])))

        edge1 = np.sqrt((pt1[0] - pt2[0]) * (pt1[0] - pt2[0]) + (pt1[1] - pt2[1]) * (pt1[1] - pt2[1]))
        edge2 = np.sqrt((pt2[0] - pt3[0]) * (pt2[0] - pt3[0]) + (pt2[1] - pt3[1]) * (pt2[1] - pt3[1]))

        angle = 0

        if edge1 > edge2:
            width = edge1
            height = edge2
            if pt1[0] - pt2[0] != 0:
                angle = -np.arctan(float(pt1[1] - pt2[1]) / float(pt1[0] - pt2[0])) / 3.1415926 * 180
            else:
                angle = 90.0
        elif edge2 >= edge1:
            width = edge2
            height = edge1
            # print pt2[0], pt3[0]
            if pt2[0] - pt3[0] != 0:
                angle = -np.arctan(float(pt2[1] - pt3[1]) / float(pt2[0] - pt3[0])) / 3.1415926 * 180
            else:
                angle = 90.0
        if angle < -45.0:
            angle = angle + 180

        x_ctr = float(pt1[0] + pt3[0]) / 2  # pt1[0] + np.abs(float(pt1[0] - pt3[0])) / 2
        y_ctr = float(pt1[1] + pt3[1]) / 2  # pt1[1] + np.abs(float(pt1[1] - pt3[1])) / 2
        return [x_ctr, y_ctr, width, height, angle], gt_ind[8]
    else:
        return None, None

def get_dota_JSON(img_dir, label_dir, save_path, cls_list):
    img_file_type = ".png"
    label_file_type = ".txt"

    file_list = os.listdir(img_dir)
    img_list = []

    for file_name in file_list:
        # split = file_name.split(".")
        # if split[len(split) - 1] == img_file_type:
        #     img_list.append(file_name)
        if file_name.endswith(img_file_type):
            img_list.append(file_name)
    img_list.sort()
    gt_list = []
    for img_ind in range(len(img_list)):
        # split = img_list[img_ind].split(".")
        gt_list.append(img_list[img_ind].replace(img_file_type, label_file_type))

    data_dict = {}
    info = {'contributor': 'captain group',
           'data_created': '2019',
           'description': 'Object detection for aerial pictures.',
           'url': 'http://rscup.bjxintong.com.cn/#/theme/2',
           'version': 'preliminary contest',
           'year': 2019}
    data_dict['info'] = info
    data_dict['images'] = []
    data_dict['categories'] = []
    data_dict['annotations'] = []
    for idex, name in enumerate(cls_list):
        if name =='__background__':
            continue
        single_cat = {'id': idex, 'name': name, 'supercategory': name}
        data_dict['categories'].append(single_cat)
    data_dict['annotations'] = []

    inst_count = 1
    image_id = 1
    with open(save_path, 'w') as f_out:
        for img_name, gt_name in zip(img_list, gt_list):
            img_path = os.path.join(img_dir, img_name)
            gt_path = os.path.join(label_dir, gt_name)

            gt_obj = open(gt_path, 'r')
            gt_txt = gt_obj.read()

            gt_split = gt_txt.split('\n')
            if not len(gt_split)-1:
                continue

            last_inst_count = inst_count
            for gt_line in gt_split:
                rbox, gt_class = get_box(gt_line)
                if rbox != None:
                    single_obj = {}
                    single_obj['area'] = rbox[2]* rbox[3]
                    single_obj['category_id'] = gt_class
                    single_obj['iscrowd'] = 0
                    single_obj['image_id'] = image_id
                    single_obj['bbox'] = rbox
                    single_obj['id'] = inst_count
                    data_dict['annotations'].append(single_obj)
                    inst_count += 1

            if inst_count != last_inst_count:
                img = cv2.imread(img_path)
                width, height, _ = img.shape
                single_image = {}
                single_image["width"] = width
                single_image["height"] = height
                single_image["file_name"] = img_name
                single_image["id"] = image_id
                data_dict['images'].append(single_image)
                image_id += 1

        print(len(data_dict['images']), len(data_dict['annotations']))
        json.dump(data_dict, f_out)

def vis_image(image_path, boxes):
    img = cv2.imread(image_path)
    #cv2.namedWindow("image")
    #cv2.setMouseCallback("image", trigger)
    for idx in range(len(boxes)):
        cx, cy, h, w, angle = boxes[idx]
        lt = [cx - w/2, cy - h/2,1]
        rt = [cx + w/2, cy - h/2,1]
        lb = [cx - w/2, cy + h/2,1]
        rb = [cx + w/2, cy + h/2,1]

        pts = []

        #angle = angle * 0.45

        pts.append(lt)
        pts.append(rt)
        pts.append(rb)
        pts.append(lb)

        angle = -angle

        #if angle != 0:
        cos_cita = np.cos(np.pi / 180 * angle)
        sin_cita = np.sin(np.pi / 180 * angle)

        #else :
        #	cos_cita = 1
        #	sin_cita = 0

        M0 = np.array([[1,0,0],[0,1,0],[-cx,-cy,1]])
        M1 = np.array([[cos_cita, sin_cita,0], [-sin_cita, cos_cita,0],[0,0,1]])
        M2 = np.array([[1,0,0],[0,1,0],[cx,cy,1]])
        rotation_matrix = M0.dot(M1).dot(M2)

        rotated_pts = np.dot(np.array(pts), rotation_matrix)

        #print im
        #print im.shape
        #			im = im.transpose(2,0,1)

        cv2.line(img, (int(rotated_pts[0,0]),int(rotated_pts[0,1])), (int(rotated_pts[1,0]),int(rotated_pts[1,1])), (0, 0, 255),3)
        cv2.line(img, (int(rotated_pts[1,0]),int(rotated_pts[1,1])), (int(rotated_pts[2,0]),int(rotated_pts[2,1])), (0, 0, 255),3)
        cv2.line(img, (int(rotated_pts[2,0]),int(rotated_pts[2,1])), (int(rotated_pts[3,0]),int(rotated_pts[3,1])), (0, 0, 255),3)
        cv2.line(img, (int(rotated_pts[3,0]),int(rotated_pts[3,1])), (int(rotated_pts[0,0]),int(rotated_pts[0,1])), (0, 0, 255),3)

    # img = cv2.resize(img, (1024, 768))
    # cv2.imshow("image", img)
    cv2.imwrite('./last_vis/{}.png'.format(image_path.split('/')[-1][:-4]), img)

def change_1809(img_dir):
    file_list = [filename for filename in os.listdir(img_dir) if 'P1809' in filename]
    print(len(file_list))
    for filename in file_list:
        file_path = os.path.join(img_dir, filename)
        with open(file_path, 'r') as read_f:
            lines = read_f.readlines()
            txt_write_lines = []
            for line in lines:
                splitline = line.strip().split(' ')
                if len(splitline)<9 or splitline[8] != 'helicopter':
                    # print(splitline)
                    txt_write_lines.append(line)
                    continue
                line = line.replace('helicopter', 'helipad')
                txt_write_lines.append(line)
                # print(line)

        # print(txt_write_lines)
        with open(file_path, 'w') as write_f:
            for txt_write_line in txt_write_lines:
                write_f.writelines(txt_write_line)

if __name__ == '__main__':
    # # pass
    # image_dir = "data/DOTA/data_800/val/images"
    # label_dir = "data/DOTA/data_800/val/labelTxt"
    # save_path = 'data/DOTA/annotations/sub800r_val2019.pkl'
    # img_infos = get_dota_PKL(image_dir, label_dir, save_path, cls18_dict)

    # image_dir = "data/DOTA/data_800/train/images"
    # label_dir = "data/DOTA/data_800/train/labelTxt"
    # save_path = 'data/DOTA/annotations/sub800r_train2019.pkl'
    # img_infos = get_dota_PKL(image_dir, label_dir, save_path, cls18_dict)

    image_dir = "data/DOTA-v1/data_800/val/images"
    label_dir = "data/DOTA-v1/data_800/val/labelTxt-v1.0"
    save_path = 'data/DOTA-v1/annotations/sub800r_val.json'
    get_dota_JSON(image_dir, label_dir, save_path, cls15_list)

    image_dir = "data/DOTA-v1/data_800/train/images"
    label_dir = "data/DOTA-v1/data_800/train/labelTxt-v1.0"
    save_path = 'data/DOTA-v1/annotations/sub800r_train.json'
    get_dota_JSON(image_dir, label_dir, save_path, cls15_list)
    # PKL2JSON('data/DOTA/annotations/sub800r_train2019.pkl', 'data/DOTA/annotations/sub800r_train2019.json')

    # change_1809('./data/DOTA/data_800/val_800/labelTxt')
    # change_1809('./data/DOTA/data_800/train_merge/labelTxt')
    # change_1809('./data/DOTA/data_ori/val/labelTxt')


import math

n = 0;

def recurringPrimeFactors(n):
    N = n
    factors = list()
    while n % 2 == 0:
        n = n / 2
    for i in range(3,int(math.sqrt(n))+1,2):
        while n % i== 0:
            if i in factors:
                print('{0} is a recurring prime factor of {1}'.format(str(i), str(N)))
                # r
            factors.append(i)
            n = n / i
    if n > 2:
        # if n in factors:
            # r
        factors.append(n)

while(n < 100):
    x = pow(10, n) + 1
    if recurringPrimeFactors(x):
        n = 101
    else:
        print('{0} does not have any recurring prime factors.'.format(str(x)))
    n = n + 1


from config import PAN_ROUTER_ADDR, PAN_FACTORY_ADDR, USER_ADDR, PRIV_KEY, MAX_NUMBER, GAS_BUFFER, GAS_PRICE, GAS_LIMIT
from helpers.abi_helper import PAN_ROUTER_ABI, PAN_FACTORY_ABI,ERC20_ABI
from web3 import Web3
import time

# simple method to create pancake router & factory v2 contract objs
def create_pancake(w3: Web3):
	# create contract w/ pancake router v2 methods
	router = w3.eth.contract(address=PAN_ROUTER_ADDR, abi=PAN_ROUTER_ABI)
	factory = w3.eth.contract(address=PAN_FACTORY_ADDR, abi=PAN_FACTORY_ABI)

	return router, factory

# buys AMOUNT of specified token TKN_ADDR
def buy_token(amount: float, path: list[str], w3: Web3, router) -> str:
	# define transaction
	buy_txn = router.functions.swapExactETHForTokensSupportingFeeOnTransferTokens(
		0,													# slippage (0 == inf)
		path,												# trade from BNB --> token
		USER_ADDR,											# wallet to send tokens to
		(int(time.time()) + 1000)							# deadline
	).buildTransaction({
		'from': USER_ADDR,									# wallet to fund trade
		'value': w3.toWei(amount, 'ether'),					# amount to buy
		'gas': 0,											# gas limit
		'gasPrice': w3.toWei(GAS_PRICE,'gwei'),				# gas price
		'nonce': w3.eth.get_transaction_count(USER_ADDR)	# metamask nonce
	})

	# get estimated gas cost of transaction
	try:
		EST_GAS = w3.eth.estimate_gas(buy_txn) + GAS_BUFFER
		buy_txn.update({'gas': EST_GAS})
	# if fails, default to flat rate
	except:
		buy_txn.update({'gas': GAS_LIMIT})

	# sign and send transaction
	signed_txn = w3.eth.account.sign_transaction(buy_txn, private_key=PRIV_KEY)
	txn_hash = w3.toHex(w3.eth.send_raw_transaction(signed_txn.rawTransaction))

	return txn_hash

# confirms the token @ TKN_ADDR s.t. pancake swap may sell it
def confirm_token(tkn_addr: str, w3: Web3) -> str:
	txn_hash = True														# if token alr confirmed --> return true
	token_contract = w3.eth.contract(address=tkn_addr, abi=ERC20_ABI)	# define token contract

	# check if needs approval
	if token_contract.functions.allowance(USER_ADDR, PAN_ROUTER_ADDR).call() == 0:

		# build approve transaction
		approve_txn = token_contract.functions.approve(PAN_ROUTER_ADDR, MAX_NUMBER).buildTransaction({
			'from': USER_ADDR,
			'gasPrice': w3.toWei(GAS_PRICE, 'gwei'),
			'nonce': w3.eth.get_transaction_count(USER_ADDR)
		})

		# sign and send
		signed_txn = w3.eth.account.sign_transaction(approve_txn, private_key=PRIV_KEY)
		txn_hash = w3.toHex(w3.eth.send_raw_transaction(signed_txn.rawTransaction))

	return txn_hash

# sells all tokens @ TKN_ADDR
def sell_token(amount, path, w3: Web3, router) -> str:
	# define transaction
	sell_txn = router.functions.swapExactTokensForETHSupportingFeeOnTransferTokens(
		amount,												# amount of token to sell
		0,													# slippage (0 == inf)
		path,												# trade from token --> BNB
		USER_ADDR,											# wallet to send BNB to
		(int(time.time()) + 1000)							# deadline
	).buildTransaction({
		'from': USER_ADDR,									# contract sending addr
		'gas': 0,											# gas limit
		'gasPrice': w3.toWei(GAS_PRICE, 'gwei'),			# gas price
		'nonce': w3.eth.get_transaction_count(USER_ADDR)	# MetaMask nonce
	})

	# get estimated gas cost of transaction
	try:
		EST_GAS = w3.eth.estimate_gas(sell_txn) + GAS_BUFFER
		sell_txn.update({'gas': EST_GAS})
	# if fails, default to flat rate
	except:
		sell_txn.update({'gas': GAS_LIMIT})

	# sign and send
	signed_txn = w3.eth.account.sign_transaction(sell_txn, private_key=PRIV_KEY)
	txn_hash = w3.toHex(w3.eth.send_raw_transaction(signed_txn.rawTransaction))

	return txn_hash


import pickle
import os
import sys
import time
import math

import numpy
from collections import OrderedDict

import theano
import theano.tensor as T
from theano.tensor.shared_randomstreams import RandomStreams

from layers.layers import LinearLayer, SigmoidLayer, HiddenLayer, GeneralLayer, MixtureDensityOutputLayer
from utils.providers import ListDataProvider

from training_schemes.rprop import compile_RPROP_train_function

import logging

class MixtureDensityNetwork(object):
    def __init__(self, numpy_rng, n_ins=784, n_outs=24, l1_reg = None, l2_reg = None,
                 hidden_layers_sizes=[500, 500],
                 hidden_activation='tanh', output_activation='linear', var_floor=0.01,
                 n_component=1, beta_opt=False, use_rprop=0, rprop_init_update=0.001,
                 eff_sample_size=0.8, mean_log_det=-100.0):

        logger = logging.getLogger("Multi-stream DNN initialization")

        self.sigmoid_layers = []
        self.params = []
        self.delta_params   = []

        self.final_layers = []

        self.n_outs = n_outs

        self.n_layers = len(hidden_layers_sizes)

        self.output_activation = output_activation
        self.var_floor = var_floor

        self.use_rprop = use_rprop
        self.rprop_init_update = rprop_init_update

        self.l1_reg = l1_reg
        self.l2_reg = l2_reg

        self.beta_opt = beta_opt
        self.eff_sample_size = eff_sample_size
        self.mean_log_det = mean_log_det

        assert self.n_layers > 0

        # allocate symbolic variables for the data
        self.x = T.matrix('x')
        self.y = T.matrix('y')

        for i in range(self.n_layers):
            if i == 0:
                input_size = n_ins
            else:
                input_size = hidden_layers_sizes[i - 1]

            if i == 0:
                layer_input = self.x
            else:
                layer_input = self.sigmoid_layers[-1].output

            sigmoid_layer = HiddenLayer(rng=numpy_rng,
                                        input=layer_input,
                                        n_in=input_size,
                                        n_out=hidden_layers_sizes[i],
                                        activation=T.tanh)  ##T.nnet.sigmoid)  #
            self.sigmoid_layers.append(sigmoid_layer)
            self.params.extend(sigmoid_layer.params)
            self.delta_params.extend(sigmoid_layer.delta_params)

        hidden_output_size = hidden_layers_sizes[-1]

        self.final_layer = MixtureDensityOutputLayer(rng = numpy_rng,
                                                input = sigmoid_layer.output,
                                                n_in = hidden_output_size,
                                                n_out = self.n_outs,
                                                n_component = n_component,
                                                var_floor = self.var_floor)
        self.params.extend(self.final_layer.params)
        self.delta_params.extend(self.final_layer.delta_params)

        ### Maximum likelihood
        self.finetune_cost = 0.0

        self.errors = 0.0

        epsd = self.eff_sample_size**(-2.0/(n_outs + 2.0))
        beta = (epsd - 1.0) + math.sqrt(epsd*(epsd - 1.0))

        if self.beta_opt:
            assert n_component == 1, "beta optimisation only implemented for single-component MDNs"
            for i in range(n_component):  #n_component
                sigma = self.final_layer.sigma[:, i*n_outs:(i+1)*n_outs]
                mu    = self.final_layer.mu[:, i*n_outs:(i+1)*n_outs]
                mix_weight = self.final_layer.mix[:, i]

                xEx = -0.5 * beta * T.sum(((self.y - mu)**2) * T.inv(sigma), axis=1)
                exponent = (0.5 * (n_outs + 2.0) * T.log(1 + beta)) + xEx
                point_fit = T.exp(exponent) - beta

                log_det_mult = -0.5 * beta * T.sum(T.log(sigma), axis=1)

                log_det_mult += (0.5 * beta * self.mean_log_det) # normalise by mean_log_det

                beta_obj = (mix_weight**2) * point_fit * T.exp(log_det_mult)

                self.finetune_cost += -T.mean(beta_obj)

            # lines to compute debugging information for later printing
            #self.errors = T.min(T.min(T.log(sigma), axis=1))
            #self.errors = T.mean(T.sum(T.log(sigma), axis=1)) # computes mean_log_det
            #self.errors = -xEx # (vector quantity) should be about 0.5 * beta * n_outs
            #self.errors = point_fit  # (vector quantity) should be about one
            #self.errors = T.mean(T.exp(exponent)) / T.exp(T.max(exponent)) # fraction of the data used, should be about efficiency
            #self.errors = T.mean(point_fit) # should be about one
            #self.errors = log_det_mult # (vector quantity) about zero, or always less if using Rprop
            #self.errors = beta_obj # (vector quantity) objective function terms
            #self.errors = self.finetune_cost # disable this line below when debugging
        else:

            all_mix_prob = []

            print(n_component)
            for i in range(n_component):  #n_component
                sigma = self.final_layer.sigma[:, i*n_outs:(i+1)*n_outs]
                mu    = self.final_layer.mu[:, i*n_outs:(i+1)*n_outs]
                mix_weight = self.final_layer.mix[:, i]

                xEx = -0.5 * T.sum(((self.y - mu)**2) * T.inv(sigma), axis=1)
                normaliser = 0.5 * ( n_outs * T.log(2 * numpy.pi) + T.sum(T.log(sigma), axis=1))
                exponent = xEx + T.log(mix_weight) - normaliser
                all_mix_prob.append(exponent)

            max_exponent = T.max(all_mix_prob, axis=0, keepdims=True)
            mod_exponent = T.as_tensor_variable(all_mix_prob) - max_exponent

            self.finetune_cost = - T.mean(max_exponent + T.log(T.sum(T.exp(mod_exponent), axis=0)))

            #self.errors = self.finetune_cost

        if self.l2_reg is not None:
            for i in range(self.n_layers-1):
                W = self.params[i * 2]
                self.finetune_cost += self.l2_reg * T.sqr(W).sum()
            self.finetune_cost += self.l2_reg * T.sqr(self.final_layer.W_mu).sum()
            self.finetune_cost += self.l2_reg * T.sqr(self.final_layer.W_sigma).sum()
            self.finetune_cost += self.l2_reg * T.sqr(self.final_layer.W_mix).sum()

        self.errors = self.finetune_cost # disable this line if debugging beta_opt

    def build_finetune_functions(self, train_shared_xy, valid_shared_xy, batch_size):

        (train_set_x, train_set_y) = train_shared_xy
        (valid_set_x, valid_set_y) = valid_shared_xy

        # compute number of minibatches for training, validation and testing
        n_valid_batches = valid_set_x.get_value(borrow=True).shape[0]
        n_valid_batches /= batch_size

        index = T.lscalar('index')  # index to a [mini]batch
        learning_rate = T.fscalar('learning_rate')
        momentum = T.fscalar('momentum')

        layer_size = len(self.params)
        lr_list = []
        for i in range(layer_size):
            lr_list.append(learning_rate)

        ##top 2 layers use a smaller learning rate
        if layer_size > 4:
            for i in range(layer_size-4, layer_size):
                lr_list[i] = learning_rate * 0.5

        # compute list of fine-tuning updates
        # compute the gradients with respect to the model parameters
        gparams = T.grad(self.finetune_cost, self.params)

        if self.use_rprop == 0:

            updates = OrderedDict()
            layer_index = 0
            for dparam, gparam in zip(self.delta_params, gparams):
                updates[dparam] = momentum * dparam - gparam * lr_list[layer_index]
                layer_index += 1

            for dparam, param in zip(self.delta_params, self.params):
                updates[param] = param + updates[dparam]

            train_fn = theano.function(inputs=[index, theano.Param(learning_rate, default = 0.0001),
                  theano.Param(momentum, default = 0.5)],
                  outputs=self.errors,
                  updates=updates,
                  on_unused_input='ignore',
                  givens={self.x: train_set_x[index * batch_size:
                                              (index + 1) * batch_size],
                          self.y: train_set_y[index * batch_size:
                                              (index + 1) * batch_size]})

        elif self.use_rprop:
            updates = compile_RPROP_train_function(self, gparams)

            ## retain learning rate and momentum to make interface backwards compatible,
            ## but we won't use them, means we have to use on_unused_input='warn'.
            ## Otherwise same function for RPROP or otherwise -- can move this block outside if clause.
            train_fn = theano.function(inputs=[index, theano.Param(learning_rate, default = 0.0001),
                  theano.Param(momentum, default = 0.5)],
                  outputs=self.errors,
                  updates=updates,
                  on_unused_input='warn',
                  givens={self.x: train_set_x[index * batch_size:
                                              (index + 1) * batch_size],
                          self.y: train_set_y[index * batch_size:
                                              (index + 1) * batch_size]})

        valid_fn = theano.function([],
              outputs=self.errors,
              on_unused_input='ignore',
              givens={self.x: valid_set_x,
                      self.y: valid_set_y})

        valid_score_i = theano.function([index],
              outputs=self.errors,
              on_unused_input='ignore',
              givens={self.x: valid_set_x[index * batch_size:
                                          (index + 1) * batch_size],
                      self.y: valid_set_y[index * batch_size:
                                          (index + 1) * batch_size]})
        # Create a function that scans the entire validation set
        def valid_score():
            return [valid_score_i(i) for i in range(n_valid_batches)]

        return train_fn, valid_fn

    def parameter_prediction(self, test_set_x):  #, batch_size

        n_test_set_x = test_set_x.get_value(borrow=True).shape[0]

        test_out = theano.function([], self.final_layer.mu,
              givens={self.x: test_set_x[0:n_test_set_x]})

        predict_parameter = test_out()

        return predict_parameter

    def parameter_prediction_mix(self, test_set_x):  #, batch_size

        n_test_set_x = test_set_x.get_value(borrow=True).shape[0]

        test_out = theano.function([], self.final_layer.mix,
              givens={self.x: test_set_x[0:n_test_set_x]})

        predict_parameter = test_out()

        return predict_parameter

    def parameter_prediction_sigma(self, test_set_x):  #, batch_size

        n_test_set_x = test_set_x.get_value(borrow=True).shape[0]

        test_out = theano.function([], self.final_layer.sigma,
              givens={self.x: test_set_x[0:n_test_set_x]})

        predict_parameter = test_out()

        return predict_parameter

if __name__ == '__main__':

    train_scp = '/afs/inf.ed.ac.uk/group/project/dnn_tts/data/nick/nn_scp/train.scp'
    valid_scp = '/afs/inf.ed.ac.uk/group/project/dnn_tts/data/nick/nn_scp/gen.scp'

    model_dir = '/afs/inf.ed.ac.uk/group/project/dnn_tts/practice/nnets_model'

    log_dir =  '/afs/inf.ed.ac.uk/group/project/dnn_tts/practice/log'

    finetune_lr=0.01
    pretraining_epochs=100
    pretrain_lr=0.01
    training_epochs=100
    batch_size=32

    n_ins = 898
    n_outs = 229

    hidden_layers_sizes = [512, 512, 512]

#    test_DBN(train_scp, valid_scp, log_dir, model_dir, n_ins, n_outs, hidden_layers_sizes,
#             finetune_lr, pretraining_epochs, pretrain_lr, training_epochs, batch_size)

    dnn_generation()


input_num=int(input())

line=0 # 라인 수
max_num=0 # 최댓 값

# 입력 값에 따른 라인 수와 최댓 값 구하기
while input_num>max_num:
    line+=1
    max_num+=line

# 입력 값 라인의 최댓 값에서 입력 값을 빼서 차이를 변수에 저장
gap=max_num-input_num
if line%2==0: # 짝수 일때
    top=line-gap
    bot=gap+1
else: # 홀수 일때
    top=gap+1
    bot=line-gap
print('{0}/{1}'.format(top,bot))


class Solution:
    def minReorder(self, n: int, connections: List[List[int]]) -> int:
        visited = [False] * n
        graph = defaultdict(list)

        for x, y in connections:
            graph[x].append(y)
            graph[y].append(-x)

        def go(node):
            visited[node] = True
            res = 0

            for nei in graph[node]:
                if not visited[abs(nei)]:
                    visited[abs(nei)] = True
                    res += go(abs(nei)) + int(nei > 0)

            return res

        return go(0)


'''
Created on

Course work:

@author: Elakia VM

Source:

'''

# Import necessary modules
import random
import time

#constants

QUICK_TESTING = False

BALLS_PER_OVER  =   6
TOTAL_WICKETS   =   10
TOTAL_OVERS     =   2
CURRENT_TEAMS   = [
    'India',
    'Pakistan'
]

team_a_players = [
    "Virat Kohli",
    "Rohit Sharma",
    "Jasprit Bumrah",
    "Ravichandran Aswin",
    "Ravindra Jadeja",
    "Mohammed Shami",
    "Hardik Pandya",
    "Bhuvneshwar Kumar",
    "Kuldeep Yadav",
    "Rishabh Pant",
    "Shreyas Iyer"
]

team_b_players = [
    "Asif Ali",
    "Shoaib Malik",
    "Fakhar Zaman",
    "Mohammad Rizwan",
    "Mohammad Hafeez",
    "Imad Wasim",
    "Shaheen Afridi",
    "Hasan Ali",
    "Haider Ali",
    "Sarfaraz Ahmed",
    "Mohammad Wasim Jr"
]

team_a_total_score = 0
team_b_total_score = 0

def get_random_number(min = 0,max =6):

    return random.randint(min,max)

def is_wicket():

    r_number = get_random_number()

    if(r_number % 7 == 0):
        return True
    if(r_number % 9 == 0):
        return True
    return False

def automate_ball():
    if(QUICK_TESTING):
        return
    time.sleep(1)

def gap(count = 1):
    for space in range(count):
        print('')

def get_random_score():

    return get_random_number(0,6)

def play_single_over(
    chase_flag              = False,
    chasing_score           = 0,
    team_current_score      = 0,
    current_wicket_index    = 0
    ):

    current_over = BALLS_PER_OVER

    total_score_current_over = 0

    current_team_players = team_a_players

    if(chase_flag):
        current_team_players = team_b_players

    for ball in range(current_over):

        automate_ball()
        ball += 1

        wicket_flag = is_wicket()

        current_batsman = current_team_players[current_wicket_index]

        if(wicket_flag):
            current_run = 0
            print(f'BALL: {ball}: OUT !!!! ITS A WICKET !!! {current_batsman} is out ')

            current_wicket_index += 1

        else:
            current_run = get_random_number()

            total_score_current_over += current_run

            print(f'ball: {ball}, {current_batsman} scored: {current_run}, total runs: {total_score_current_over}')

        if(chase_flag):
            if(team_current_score > chasing_score):
                # print(f'Beat the score: chasing_score: {chasing_score}, team_innings_score: {team_innings_score}')
                return team_current_score, current_wicket_index

    return total_score_current_over, current_wicket_index

def print_score_board(playing_over, team_innings_score):

    print(f'Scoreboard: Over {playing_over}; Runs: {team_innings_score}')

def play_innings(
    chase_flag              =   False,
    over_count              =   1,
    chasing_score           =   0,
    team_current_score      =   0
):
    team_innings_score = 0

    for _current_over in range(over_count):

        playing_over = _current_over + 1

        print(f'Current over : {playing_over}')
        print('-' * 25)

        if(_current_over == 0):
            wicket_index = 0

        team_innings_score, wicket_index = play_single_over(
            chase_flag              =   chase_flag,
            chasing_score           =   chasing_score,
            team_current_score      =   team_current_score,
            current_wicket_index    =   wicket_index
        )

        print_score_board(playing_over, team_innings_score)

        if(chase_flag):
            if(team_innings_score > chasing_score):
                # print(f'Beat the score: chasing_score: {chasing_score}, team_innings_score: {team_innings_score}')

                gap()
    return team_innings_score

def play_team_a(team_a):

    #FIRST TEAM BATTING
    print(f'{team_a} batting: ')
    gap()

    team_a_total_score = play_innings(
        chase_flag              =   False,
        over_count              =   TOTAL_OVERS,
        chasing_score           =   0,
        team_current_score      =   0 )

    print(f'\n{team_a} scored: {team_a_total_score}')
    gap()

    print('-' * 70)

    return team_a_total_score

def play_team_b(
    team_b,
    chasing_score):

    #SECOND TEAM BATTING
    print(f'{team_b} batting: ')
    gap()

    global team_b_total_score
    team_b_total_score = play_innings(
        chase_flag          =   True,
        chasing_score       =   chasing_score,
        over_count          =   TOTAL_OVERS,
        team_current_score  =   team_b_total_score)

    print(f'\n{team_b} scored: {team_b_total_score}')

    gap()

    return team_b_total_score

def choose_winner(
    team_a,
    team_b,
    team_a_total_score,
    team_b_total_score
):

    if(team_b_total_score > team_a_total_score):
        print(f'{team_b} won')
    else:
        print(f'{team_a} won')
        return

    if(team_b_total_score == team_a_total_score):
        print('Its a draw!')
    return

def play_game():

    team_a = CURRENT_TEAMS[0]
    team_b = CURRENT_TEAMS[1]

    team_a_total_score = play_team_a(team_a)
    team_b_total_score = play_team_b(team_b, team_a_total_score)

    choose_winner(
    team_a,
    team_b,
    team_a_total_score,
    team_b_total_score

    )

    pass

def startpy():
    play_game()

if __name__ == '__main__':
    startpy()


import logging

logger = logging.getLogger()
logger.setLevel(logging.DEBUG)

# create file handlers
debug_fh = logging.FileHandler('logs/debug.log')
debug_fh.setLevel(logging.DEBUG)
info_fh = logging.FileHandler('logs/info.log')
info_fh.setLevel(logging.INFO)
error_fh = logging.FileHandler('logs/error.log')
error_fh.setLevel(logging.ERROR)

# create console handler with a higher log level
ch = logging.StreamHandler()
ch.setLevel(logging.ERROR)

# create formatter and add it to the handlers
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
ch.setFormatter(formatter)
debug_fh.setFormatter(formatter)
info_fh.setFormatter(formatter)
error_fh.setFormatter(formatter)

# add the handlers to logger
logger.addHandler(ch)
logger.addHandler(debug_fh)
logger.addHandler(info_fh)
logger.addHandler(error_fh)


from microbit import *
import radio

def check_hamming_code(lst, parity, data):
    occurence_of_1 = 0

    #list if the parity bit is correct
    lst1 = lst[:]

    #list if the parity bit is not correct
    lst2 = lst[:]

    #Looping through every segment of the data
    for data_index in range((2 ** parity), len(data), 2 ** (parity + 1)):

        #Looping through every bit in the segment.
        for bits_to_check in range(data_index, data_index+(2 ** parity)):
            if bits_to_check >= len(data):
                break
            if data[bits_to_check] == '1':
                occurence_of_1 += 1
            lst1[bits_to_check] = None
            if lst2[bits_to_check] is not None:
                lst2[bits_to_check] += 1

    if occurence_of_1 % 2 == 0:
        return lst1
    else:
        return lst2

def check_secded_code(lst, data):
    occurence_of_1 = 0
    for bits_to_check in range(len(data)):
        if data[bits_to_check] == '1':
            occurence_of_1 += 1

    if occurence_of_1 % 2 == 0:
        lst[0] = None

    return lst

def start(data):
    #main list
    lst = [0 for y in range(len(data))]

    index = 0
    parity = 0

    #Looping as many times as the the number of parity bits starting from P1
    while True:
        lst = check_hamming_code(lst, parity, data)

        parity += 1
        index = 2 ** parity
        if index >= len(data):
            break

    lst = check_secded_code(lst, data)

    highest = -1
    pos = None
    highest_count = 0
    for parity in range(len(lst)):
        if lst[parity] is not None and lst[parity] > highest:
            high = lst[parity]
            pos = parity
            highest_count = 0
        elif lst[parity] == highest:
            highest_count = None

    #2 bit or more bit error
    if highest_count is None:
        display.show(Image.CONFUSED)
        sleep(1000)
        display.clear()
        return
    #Error free
    elif pos is None:
        display.show(Image.YES)
        sleep(1000)
        display.clear()
        return
    #2 bit or more bit error
    elif lst[0] is None:
        display.show(Image.CONFUSED)
        sleep(1000)
        display.clear()
        return
    #1 bit correcable error
    else:
        message = list(data)
        message[pos] = str(((int(message[pos])) + 1) % 2)
        message = "".join(message)
        display.show(Image.SURPRISED)
        sleep(1000)
        display.clear()
        return

'''
*    Title: Python Main Function implementation
*    Author: Bryan Weber
*    Date: n.d
*    Code version:
*    Availability: https://realpython.com/python-main-function/
*
'''

if __name__ == "__main__":
    radio.on()
    radio.config(group=5)
    while True:
        message = radio.receive()
        #message = "01010101"
        if message:
            start(message)
            message = None


'''
Created on 11 May 2018

@author: agocsi
'''
import unittest
from trades import Trade, TradeManager, TradeManagerException, TradeException
from stocks import Stock, StockManager
from ddt import ddt, data, unpack

HEADER = ['symbol_', 'type', 'last_dividend_', 'fixed_dividend_', 'par_value_']
STOCKS = [['TEA', 'Common', 0, '', 100], ['POP', 'Common', 8, '', 100],
          ['ALE', 'Common', 23, '', 60], ['GIN', 'Preferred', 8, 0.02, 100],
          ['JOE', 'Common', 13, '',250]]

@ddt
class TestTrade(unittest.TestCase):
    @classmethod
    def setUpClass(cls):
        cls._sm = StockManager()
        cls._sm.create_stocks_header(HEADER, STOCKS)

    @classmethod
    def tearDownClass(cls):
        cls._sm._clear()

    @data(('TEA', '2015-JAN-21 00:12:11', 1000, Trade.BUY, 1000),
          ('ALE', '2015-JAN-21 00:12:11', 1000, Trade.SELL, 1000))
    @unpack
    def testCreateATrade(self, stock_symbol_, timestamp_, quantity_, buy_or_sell_, trade_price_):
        t = Trade(stock_symbol_, timestamp_, quantity_, buy_or_sell_, trade_price_)
        self.assertTrue(t.valid())

    @data(('TEA1', '2015-JAN-21 00:12:11', 1000, Trade.BUY, 1000),
          ('TEA', '2015-JAN-42 00:12:11', -111, Trade.BUY, 1000),
          ('TEA', '2015-JANUAR-21 00:12:11', 1000, Trade.BUY, 1000),
          ('TEA', '2015-JAN-21 00:12:11', 0, Trade.BUY, 1000),
          ('TEA', '2015-JAN-21 00:12:11', -1000, Trade.BUY, 1000),
          ('TEA', '2015-JAN-21 00:12:11', 1000, Trade.BUY, -1000),
          ('TEA', '2015-JAN-21 00:12:11', 1000, Trade.BUY, 0))
    @unpack
    def testInvalidTrade(self, stock_symbol_, timestamp_, quantity_, buy_or_sell_, trade_price_):
        with self.assertRaises(TradeException):
            t = Trade(stock_symbol_, timestamp_, quantity_, buy_or_sell_, trade_price_)

    @data(('TEA', 1000, Trade.BUY, 1000),
          ('ALE', 1000, Trade.SELL, 1000))
    @unpack
    def testCreateATrade2(self, stock_symbol_, quantity_, buy_or_sell_, trade_price_):
        t = Trade.create_trade(stock_symbol_, quantity_, buy_or_sell_, trade_price_)
        self.assertTrue(t.valid())

    @data(('TEA1', 1000, Trade.BUY, 1000),
          ('TEA', 0, Trade.BUY, 1000),
          ('TEA', -1000, Trade.BUY, 1000),
          ('TEA', 1000, Trade.BUY, -1000),
          ('TEA', 1000, Trade.BUY, 0))
    @unpack
    def testInvalidTrade2(self, stock_symbol_, quantity_, buy_or_sell_, trade_price_):
        with self.assertRaises(TradeException):
            t = Trade.create_trade(stock_symbol_, quantity_, buy_or_sell_, trade_price_)

@ddt
class TestTradeManager(unittest.TestCase):
    @classmethod
    def setUpClass(cls):
        cls._sm = StockManager()
        cls._sm.create_stocks_header(HEADER, STOCKS)

    @classmethod
    def tearDownClass(cls):
        cls._sm._clear()

    def tearDown(self):
        TradeManager._clear()

    def testSingleton(self):
        tm1 = TradeManager()
        tm2 = TradeManager()
        self.assertEqual(tm1, tm2)

    @data(('TEA', '2015-JAN-21 00:12:11', 1000, Trade.BUY, 1000),
          ('ALE', '2015-JAN-21 00:12:11', 1000, Trade.SELL, 1000))
    @unpack
    def testAddingTrade(self, stock_symbol_, timestamp_, quantity_, buy_or_sell_, trade_price_):
        t = Trade(stock_symbol_, timestamp_, quantity_, buy_or_sell_, trade_price_)
        tm = TradeManager()
        tm.add(t)
        self.assertEqual(len(tm), 1)

    @data(1, 'a', True, 0.1)
    def testAddingFalseTrade(self, data):
        tm = TradeManager()
        with self.assertRaises(TradeManagerException):
            tm.add(data)

if __name__ == "__main__":
    #import sys;sys.argv = ['', 'Test.testName']
    unittest.main()


"""Drivesp Copy

Usage:
  drivesp_copy.py PUBLISHER_PATH UPDATER_PATH_WIN UPDATER_PATH_LINUX OUT_FOLDER_NAME

Options:
  -h --help     Show this screen.
"""

from docopt import docopt
import os

args = docopt(__doc__)

from distutils.dir_util import copy_tree
from shutil import copy2

dirname = os.path.dirname(__file__)
destPub = os.path.join(dirname, args["OUT_FOLDER_NAME"]+"\\")
destUpdateWin = os.path.join(dirname, args["OUT_FOLDER_NAME"]+"\\updater\\win\\.updater\\")
destUpdateLinux = os.path.join(dirname, args["OUT_FOLDER_NAME"]+"\\updater\\linux\\.updater\\")

copy_tree(args["PUBLISHER_PATH"], destPub)
copy_tree(args["UPDATER_PATH_WIN"], destUpdateWin)
copy_tree(args["UPDATER_PATH_LINUX"], destUpdateLinux)

copy2("scripts/update.bat", os.path.join(dirname, args["OUT_FOLDER_NAME"]+"\\updater\\win\\"))
copy2("scripts/install_instruction_readme.txt", os.path.join(dirname, args["OUT_FOLDER_NAME"]+"\\updater\\linux\\"))


'''Bài 5: Viết chương trình thực hiện các yêu cầu sau:
- Nhập vào 1 danh sách các số nguyên từ bàn phím (Quá trình nhập dừng khi người dùng
nhập vào 1 kí tự từ a đến z)
- Hiển thị danh sách đó ra màn hình
- Yêu cầu người dùng nhập vào một số nguyên N từ bàn phím'''
l=[]
while True:
    n = input('số nguyên nhập vào: ')
    if (n.isalpha()==True):
        break
    else:
        l.append(int(n))
print(l)


import pandas as pd

pd.options.mode.chained_assignment = None
import argparse
import csv

import numpy as np

def get_args():
    desc = (
        "Replaces the starts or ends of transcripts in a GTF with the"
        " longest alternatives (similar to the GENCODE model of"
        "calling transcripts)"
    )
    parser = argparse.ArgumentParser(description=desc)

    parser.add_argument("-gtf", dest="gtf", help="TALON GTF to serve as the template to modify")
    parser.add_argument("-read_annot", dest="annot", help="Read annot file from TALON to extract raw read ends from")
    parser.add_argument(
        "--datasets",
        "--d",
        dest="datasets_file",
        help="""A file indicating which datasets should be
                  included (one dataset name per line). Default is to include
                  all datasets.""",
        default="all",
    )
    parser.add_argument(
        "--mode",
        dest="mode",
        default="tss",
        help="Modify TSSs or TESs, 'tss', 'tes', 'both'. Default: 'tss'",
        choices={"tss", "tes", "both"},
    )
    parser.add_argument(
        "--novelty",
        dest="novelty",
        help="Whether to only modify ends from novel or all models, " + "'all' or 'novel'. Default: 'all'",
        choices={"all", "novel"},
        default="all",
    )
    parser.add_argument("-outprefix", "-o", dest="outprefix", help="Prefix for output file", default="talon")
    parser.add_argument("--verbose", "-v", action="store_true", default=False, help="Display in progress output")

    args = parser.parse_args()

    return args

# df: TALON read annotation dataframe
# how: 'tes' or 'tss' for calling ends or starts respectively
# novelty: 'all' or 'novel' based on which transcript models
#          you want to modify the ends of
# datasets: string file path of file with datasets to use when
#           calling longest ends from reads
def get_longest_ends(df, how="tes", novelty="novel", datasets="all"):
    if novelty == "novel":
        df = df.loc[df.transcript_novelty != "Known"]

    if datasets != "all":
        df = df.loc[df.dataset.isin(datasets)]

    fwd = df.loc[df.strand == "+"]
    rev = df.loc[df.strand == "-"]

    # furthest downstream for tes
    # if + strand, max coord of read end
    # if - strand, min coord of read end
    if how == "tes":
        fwd = fwd[["transcript_ID", "read_end"]]
        fwd = fwd.groupby("transcript_ID").max().reset_index()
        rev = rev[["transcript_ID", "read_end"]]
        rev = rev.groupby("transcript_ID").min().reset_index()

    # furthest upstream for tss:
    # if + strand, min coord of read start
    # if - strand, max coord of read start
    elif how == "tss":
        fwd = fwd[["transcript_ID", "read_start"]]
        fwd = fwd.groupby("transcript_ID").min().reset_index()
        rev = rev[["transcript_ID", "read_start"]]
        rev = rev.groupby("transcript_ID").max().reset_index()

    # concat fwd and rev
    df = pd.concat([fwd, rev])

    df = df.sort_values(by="transcript_ID", ascending="True")

    return df

# get the longest ends from the read annotation file
# annot: TALON read annotation file path
# how: 'tss' or 'tes', tss will find start ends and tes will find stop ends
# gtf: gtf file location
# ends: df with transcript_ID, end coordinate
# how: 'tss' or 'tes'
# opref: output file prefix
# verbose: display processing progress
# test: print out dataframe before and after editing
def replace_gtf_end_coords(gtf_df, ends, how="tes", test=False, verbose=False):
    if how == "tes":
        ends.columns = ["transcript_id", "tes"]
    elif how == "tss":
        ends.columns = ["transcript_id", "tss"]

    # merge gtf_df with end information
    #     ends.transcript_id = ends.transcript_id.astype('str')
    df = gtf_df.loc[gtf_df.transcript_id.notnull()]
    ends.transcript_id = ends.transcript_id.astype("str")
    gtf_df.transcript_id = gtf_df.transcript_id.astype("str")
    gtf_df = gtf_df.merge(ends, how="left", on="transcript_id")
    df.transcript_id = df.transcript_id.astype("str")
    df = df.merge(ends, how="inner")

    if test:
        print("Before editing")
        print(gtf_df[["transcript_id", "entry_type", "strand", "start", "stop", how]])

    # swap out read starts or ends for the longest ones
    tids = df.transcript_id.unique()
    for t, tid in enumerate(tids):
        if t % 1000 == 0 and verbose:
            print("Processing transcript {} of {}".format(t, len(tids)))

        # fwd: swap out transcript "stop" and last exon "stop"
        # rev: swap out transcript "start" and last exon "start"
        if how == "tes":
            # tes fwd
            ind = gtf_df.loc[(gtf_df.strand == "+") & (gtf_df.transcript_id == tid)].index.tolist()
            if ind:
                # stop of transcript for fwd
                i = ind[0]
                gtf_df.loc[i, "stop"] = gtf_df.loc[i, "tes"]
                # stop of last exon for fwd
                i = ind[-1]
                gtf_df.loc[i, "stop"] = gtf_df.loc[i, "tes"]

            # tes rev
            ind = gtf_df.loc[(gtf_df.strand == "-") & (gtf_df.transcript_id == tid)].index.tolist()
            if ind:
                # start of trancscript for rev
                i = ind[0]
                gtf_df.loc[i, "start"] = gtf_df.loc[i, "tes"]
                # start of last exon for rev
                i = ind[-1]
                gtf_df.loc[i, "start"] = gtf_df.loc[i, "tes"]
        # fwd: swap out transcript "start" and first exon "start"
        # rev: swap out transcript "stop" and first exon "stop"
        elif how == "tss":
            # tss fwd
            ind = gtf_df.loc[(gtf_df.strand == "+") & (gtf_df.transcript_id == tid)].index.tolist()
            if ind:
                # start of transcript for fwd
                i = ind[0]
                gtf_df.loc[i, "start"] = gtf_df.loc[i, "tss"]
                # start of first exon for fwd
                i = ind[1]
                gtf_df.loc[i, "start"] = gtf_df.loc[i, "tss"]
            # tss rev
            ind = gtf_df.loc[(gtf_df.strand == "-") & (gtf_df.transcript_id == tid)].index.tolist()
            if ind:
                # stop of transcript for rev
                i = ind[0]
                gtf_df.loc[i, "stop"] = gtf_df.loc[i, "tss"]
                # stop of first exon for rev
                i = ind[1]
                gtf_df.loc[i, "stop"] = gtf_df.loc[i, "tss"]

    # now fix gene coordinates

    # tes
    if how == "tes":
        # fwd: replace "stop" of the gene with the maximum of the "stops"
        # gene_ind = gtf_df.loc[(gtf_df.strand == '+')&(gtf_df.entry_type=='gene')&(gtf_df.tes.notnull())].index.tolist()
        # gene_ind = gtf_df.loc[(gtf_df.strand == '+')&(gtf_df.entry_type=='gene')].index.tolist()
        genes = (
            gtf_df.loc[(gtf_df.strand == "+") & (gtf_df.entry_type == "transcript") & (gtf_df.tes.notnull())]
            .gene_id.unique()
            .tolist()
        )
        gene_ind = gtf_df.loc[(gtf_df.gene_id.isin(genes) & (gtf_df.entry_type == "gene"))].index.tolist()
        if gene_ind:
            fwd = gtf_df.loc[(gtf_df.strand == "+") & (gtf_df.entry_type == "transcript")]
            if test:
                print("fwd")
                print(gtf_df.loc[gene_ind])
            gtf_df.loc[gene_ind, "stop"] = gtf_df.loc[gene_ind].apply(
                lambda x: fwd.loc[fwd.gene_id == x.gene_id, "stop"].max(), axis=1
            )

        # rev: replace "start" of the gene with the minimum of the "starts"
        # gene_ind = gtf_df.loc[(gtf_df.strand == '-')&(gtf_df.entry_type=='gene')&(gtf_df.tes.notnull())].index.tolist()
        genes = (
            gtf_df.loc[(gtf_df.strand == "-") & (gtf_df.entry_type == "transcript") & (gtf_df.tes.notnull())]
            .gene_id.unique()
            .tolist()
        )
        gene_ind = gtf_df.loc[(gtf_df.gene_id.isin(genes) & (gtf_df.entry_type == "gene"))].index.tolist()
        if gene_ind:
            rev = gtf_df.loc[(gtf_df.strand == "-") & (gtf_df.entry_type == "transcript")]
            if test:
                print("rev")
                print(gtf_df.loc[gene_ind])
            gtf_df.loc[gene_ind, "start"] = gtf_df.loc[gene_ind].apply(
                lambda x: rev.loc[rev.gene_id == x.gene_id, "start"].min(), axis=1
            )

    # tss
    elif how == "tss":
        # fwd: replace "start" of the gene with the minimum of the "starts"
        # gene_ind = gtf_df.loc[(gtf_df.strand == '+')&(gtf_df.entry_type=='gene')&(gtf_df.tss.notnull())].index.tolist()
        genes = (
            gtf_df.loc[(gtf_df.strand == "+") & (gtf_df.entry_type == "transcript") & (gtf_df.tss.notnull())]
            .gene_id.unique()
            .tolist()
        )
        gene_ind = gtf_df.loc[(gtf_df.gene_id.isin(genes) & (gtf_df.entry_type == "gene"))].index.tolist()
        if gene_ind:
            fwd = gtf_df.loc[(gtf_df.strand == "+") & (gtf_df.entry_type == "transcript")]
            gtf_df.loc[gene_ind, "start"] = gtf_df.loc[gene_ind].apply(
                lambda x: fwd.loc[fwd.gene_id == x.gene_id, "start"].min(), axis=1
            )

        # rev: replace "stop" of the gene with the maximum of the "stops"
        # gene_ind = gtf_df.loc[(gtf_df.strand == '-')&(gtf_df.entry_type=='gene')&(gtf_df.tss.notnull())].index.tolist()
        genes = (
            gtf_df.loc[(gtf_df.strand == "-") & (gtf_df.entry_type == "transcript") & (gtf_df.tss.notnull())]
            .gene_id.unique()
            .tolist()
        )
        gene_ind = gtf_df.loc[(gtf_df.gene_id.isin(genes) & (gtf_df.entry_type == "gene"))].index.tolist()
        if gene_ind:
            rev = gtf_df.loc[(gtf_df.strand == "-") & (gtf_df.entry_type == "transcript")]
            gtf_df.loc[gene_ind, "stop"] = gtf_df.loc[gene_ind].apply(
                lambda x: rev.loc[rev.gene_id == x.gene_id, "stop"].max(), axis=1
            )

    if test:
        print()
        print("After editing")
        print(gtf_df[["transcript_id", "entry_type", "strand", "start", "stop", how]])

    # cols=['chr', 'source', 'entry_type', \
    #       'start', 'stop', 'score', 'strand',\
    #        'frame', 'fields']
    # gtf_df = gtf_df[cols]
    gtf_df["start"] = gtf_df["start"].astype("int")
    gtf_df["stop"] = gtf_df["stop"].astype("int")
    # if test:
    #     fname = '{}_revised_{}_test.gtf'.format(opref, how)
    # else:
    #     fname = '{}_revised_{}.gtf'.format(opref, how)
    # gtf_df.to_csv(fname, sep='\t', header=None, index=False, quoting=csv.QUOTE_NONE)
    return gtf_df

# return a list of datasets from read_annot file
# subset by a list of datasets given from a datasets file
def get_datasets_from_read_annot(df, datasets="all"):
    if datasets != "all":
        dataset_df = pd.read_csv(datasets, header=None, names=["dataset"])
        dataset_list = dataset_df["dataset"].tolist()
        for d in dataset_list:
            if d not in df.dataset.unique().tolist():
                raise ValueError("Dataset name {} not found in read_annot".format(d))
        datasets = dataset_list
    return datasets

def main():
    args = get_args()
    gtf = args.gtf
    annot = args.annot
    mode = args.mode
    novelty = args.novelty
    opref = args.outprefix
    verbose = args.verbose
    datasets = args.datasets_file

    # print(mode)
    # return

    # read in read_annot file
    try:
        df = pd.read_csv(annot, sep="\t")
    except:
        raise Error("Problem loading read annot file {}".format(annot))

    # make sure datasets are valid
    # if datasets != 'all':
    #     dataset_df = pd.read_csv(datasets, header=None, names=['dataset'])
    #     dataset_list = dataset_df['dataset'].tolist()
    datasets = get_datasets_from_read_annot(df, datasets)

    # read gtf
    gtf_df = pd.read_csv(
        gtf,
        sep="\t",
        header=None,
        names=["chr", "source", "entry_type", "start", "stop", "score", "strand", "frame", "fields"],
        comment="#",
    )

    # get relevant values from fields
    gtf_df["transcript_id"] = np.nan
    gtf_df.loc[gtf_df.entry_type != "gene", "transcript_id"] = gtf_df.loc[gtf_df.entry_type != "gene"].fields.str.split(
        pat='talon_transcript "', n=1, expand=True
    )[1]
    gtf_df.loc[gtf_df.entry_type != "gene", "transcript_id"] = gtf_df.loc[
        gtf_df.entry_type != "gene"
    ].transcript_id.str.split(pat='"', n=1, expand=True)[0]
    gtf_df["gene_id"] = gtf_df.loc[gtf_df.entry_type != "gene"].fields.str.split(pat='talon_gene "', n=1, expand=True)[
        1
    ]
    gtf_df["gene_id"] = gtf_df.loc[gtf_df.entry_type != "gene"].gene_id.str.split(pat='"', n=1, expand=True)[0]

    # first, call ends from the read annot file
    if mode == "both":
        # tss first
        ends = get_longest_ends(df, how="tss", novelty=novelty, datasets=datasets)
        gtf_df = replace_gtf_end_coords(gtf_df, ends, how="tss", verbose=verbose)

        # tes
        ends = get_longest_ends(df, how="tes", novelty=novelty, datasets=datasets)
        gtf_df = replace_gtf_end_coords(gtf_df, ends, how="tes", verbose=verbose)

    else:
        ends = get_longest_ends(df, how=mode, novelty=novelty, datasets=datasets)
        gtf_df = replace_gtf_end_coords(gtf_df, ends, how=mode, verbose=verbose)

    cols = ["chr", "source", "entry_type", "start", "stop", "score", "strand", "frame", "fields"]
    gtf_df = gtf_df[cols]
    fname = "{}_revised_{}.gtf".format(opref, mode)
    gtf_df.to_csv(fname, sep="\t", header=None, index=False, quoting=csv.QUOTE_NONE)


import random

True_list = []
False_list = []

library_name = ["Install", "latest", "PowerShell",
                "features", "improvements Copyright", "Microsoft", "Corporation", "number", "NITRO", "directory", "meeting"]

name = random.choice(library_name)
name = name.lower()

for i in range(len(name)):
    if name[i] == " ":
        print(end="  ")
    else:
        print("_", end=" ")

while len(False_list) != 6:
    char_name = input(" enter charactr : ")
    char_name = char_name.lower()
    win = 0
    if len(char_name) == 1:
        if char_name in name:
            True_list.append(char_name)
        else:
            False_list.append(char_name)

        for i in range(len(name)):
            if name[i] == " ":
               print(end="  ")
            elif name[i] in True_list:
                print(name[i], end=" ")
            else:
                print("_", end=" ")
                win += 1

        if win == 0:
            break

    else:
        print(" please enter a character ")

if len(False_list) == 6:
    print(" game over ")

elif win == 0:
    print(" you win ðŸŽ‰ðŸŽ‰ðŸŽ‰")


from agents import Speaker, Student

import numpy as np
import random
import math
import os
import sys

GRID_SIZE = 25

# We want to see how many people end up believing strongly in one ideology or the other,
# vs. how many end up in a neutral zone. Anyone with abs(ideology_score) <= NEUTRAL_CUTOFF
# will be considered neutral.
NEUTRAL_CUTOFF = 30

# Updating the model to step over each agent in the simulation rather than each square
# So the model will have a 2D array that it uses to keep track of each agent in the simulation.
# For the first loop over the agents and update the interactions.
# For the second loop, update the position of each of the agents
class Model:
    def __init__(
        self,
        experiment_name,
        population_density,
        students_to_speakers_ratio,
        speaker_range,

        expected_student_diplomacy,
        expected_speaker_diplomacy,
        expected_abs_student_ideology,
        expected_abs_speaker_ideology,

        student_diplomacy_std_deviation,
        speaker_diplomacy_std_deviation,
        student_ideology_std_deviation,
        speaker_ideology_std_deviation,
        random_seed=None):
        """
        (string) experiment_name: name of the experiment being run

        (float) population_density: percentage of tiles on the grid that will be filled; should be a float,
            between 0.05 and 0.95 (inclusive)
        (int) students_to_speakers_ratio: number of students for each speaker; should be an int between 20 and
            500 (inclusive)

        (int) speaker_range: maximum distance across which a speaker can communicate with a student
        (int) expected_student_diplomacy: expected value for student diplomacy; should be an int between 0 and 100 (exclusive)
        (int) expected_speaker_diplomacy: expected value for speaker diplomacy; should be an int  between 0 and 100 (exclusive)
        (int) expected_abs_student_ideology: expected absolute value for student ideology; should be an int between 0 and 100 (exclusive)
        (int) expected_abs_speaker_ideology: expected absolute value for speaker ideology; should be an int between 0 and 100 (exclusive)

        (int) student_diplomacy_std_deviation: standard deviation for student diplomacy; should be an int between 0 and 50 (exclusive)
        (int) speaker_diplomacy_std_deviation: standard deviation for speaker diplomacy; should be an int between 0 and 50 (exclusive)
        (int) student_ideology_std_deviation: standard deviation for student ideology; should be an int between 0 and 50 (exclusive)
        (int) speaker_ideology_std_deviation: standard deviation for speaker ideology; should be an int between 0 and 50 (exclusive)
        """
        num_tiles = GRID_SIZE ** 2
        assert 0.05 <=  population_density <= 0.95, "Population density was {}, should be between 0.05 and 0.95".format(population_density)
        assert students_to_speakers_ratio == int(students_to_speakers_ratio), "Students to speakers ratio was {}, should be a whole number".format(students_to_speakers_ratio)
        assert 20 <= students_to_speakers_ratio <= 500, "Students to speakers ratio was {}, should be between 20 and 500".format(students_to_speakers_ratio)
        num_people = int(population_density * num_tiles)
        num_speakers = int(num_people / (students_to_speakers_ratio + 1))
        num_students = num_people - num_speakers
        np.random.seed(random_seed)
        random.seed(random_seed)

        for val in (expected_student_diplomacy, expected_speaker_diplomacy, expected_abs_student_ideology, expected_abs_speaker_ideology):
            assert 0 < val < 100, "expected_student_diplomacy, expected_speaker_diplomacy, expected_abs_student_ideology, expected_abs_speaker_ideology "\
            "should all be between 0 and 100 (exclusive), but they are {}, {}, {}, and {}".format(
                expected_student_diplomacy, expected_speaker_diplomacy, expected_abs_student_ideology, expected_abs_speaker_ideology)

        for val in (student_diplomacy_std_deviation, speaker_diplomacy_std_deviation, student_ideology_std_deviation, speaker_ideology_std_deviation):
            assert 0 < val < 50, "student_diplomacy_std_deviation, speaker_diplomacy_std_deviation, student_ideology_std_deviation, speaker_ideology_std_deviation "\
            "should be between 0 and 50 (exclusive), but they are {}, {}, {}, and {}".format(
                student_diplomacy_std_deviation, speaker_diplomacy_std_deviation, student_ideology_std_deviation, speaker_ideology_std_deviation)

        self.expected_abs_student_ideology = expected_abs_student_ideology
        self.expected_abs_speaker_ideology = expected_abs_speaker_ideology
        self.speaker_range = speaker_range
        self.experiment_name = experiment_name

        # Initializes a square array where each element is None. The agent objects will take the place
        # of these positions and "move" throughout the simulation.
        self.grid = [ None ] * (GRID_SIZE * GRID_SIZE)

        index = 0
        for n in range(num_students):
            # The ideology can be positive or negative
            ideology = np.random.normal(expected_abs_student_ideology, student_ideology_std_deviation)
            ideology *= random.choice([1, -1]) # flip sign with 50% probability
            # The diplomacy score must be non-negative
            diplomacy = abs(np.random.normal(expected_student_diplomacy, student_diplomacy_std_deviation))
            student = Student(ideology, diplomacy, index)
            self.grid[index] = student
            index += 1

        for n in range(num_speakers):
            ideology = np.random.normal(expected_abs_speaker_ideology, speaker_ideology_std_deviation)
            ideology *= random.choice([1, -1]) # flip sign with 50% probability
            # The diplomacy score must be non-negative
            diplomacy = abs(np.random.normal(expected_speaker_diplomacy, speaker_diplomacy_std_deviation))
            speaker = Speaker(ideology, diplomacy, index)
            self.grid[index] = speaker
            index += 1
        # print(self.grid)

        # Now to 'shuffle' the grid so that some random initial positioning of the agents takes place
        np.random.shuffle(self.grid)
        # print(self.grid)
        self.grid = np.mat(self.grid).reshape(GRID_SIZE, GRID_SIZE)
        # print(self.grid)
        # Now iterate over the entire grid, and search for position of students, speakers
        self.students = list()
        self.speakers = list()
        for r in range(GRID_SIZE):
            for c in range(GRID_SIZE):
                if isinstance(self.grid[r,c], Student):
                    self.grid[r,c].set_position(r, c)
                    # Add found student to array of students that will be used later on to iterate over?
                    self.students.append(self.grid[r,c])
                    # print("Found student at row: %d, column: %d, x: %d, y: %d, uid: %s" % \
                    #     (r, c, self.grid[r,c].x, self.grid[r,c].y, self.grid[r,c].uid))
                if isinstance(self.grid[r,c], Speaker):
                    self.grid[r,c].set_position(r, c)
                    # Add found speaker to array of speakers that will be used later on to iterate over?
                    self.speakers.append(self.grid[r,c])
                    # print("Found speaker at row: %d, column: %d, x: %d, y: %d, uid: %s" % \
                    #     (r, c, self.grid[r,c].x, self.grid[r,c].y, self.grid[r,c].uid))
        # print(self.students)
        # print(self.speakers)

        ### output statistics
        self.total_ideology_change = 0
        self.initial_polarization = self.count_polarized()

        self.log_filename = "_".join(map(str, [
            experiment_name,

            population_density,
            students_to_speakers_ratio,
            speaker_range,

            expected_student_diplomacy,
            expected_speaker_diplomacy,
            expected_abs_student_ideology,
            expected_abs_speaker_ideology,

            student_diplomacy_std_deviation,
            speaker_diplomacy_std_deviation,
            student_ideology_std_deviation,
            speaker_ideology_std_deviation,

            random_seed])) + ".vis"

        self.log_filename = os.path.join("..", "Logs", self.log_filename)

        with open(self.log_filename, "w") as f:
            f.write("width:{0}\nheight:{0}\n".format(GRID_SIZE))
            f.write("population_density:{}\n".format(population_density))
            f.write("students_to_speakers_ratio:{}\n".format(students_to_speakers_ratio))

            f.write("expected_student_diplomacy:{}\n".format(expected_student_diplomacy))
            f.write("expected_speaker_diplomacy:{}\n".format(expected_speaker_diplomacy))
            f.write("expected_abs_student_ideology:{}\n".format(expected_abs_student_ideology))
            f.write("expected_abs_speaker_ideology:{}\n".format(expected_abs_speaker_ideology))

            f.write("student_diplomacy_std_deviation:{}\n".format(student_diplomacy_std_deviation))
            f.write("speaker_diplomacy_std_deviation:{}\n".format(speaker_diplomacy_std_deviation))
            f.write("student_ideology_std_deviation:{}\n".format(student_ideology_std_deviation))
            f.write("speaker_ideology_std_deviation:{}\n".format(speaker_ideology_std_deviation))
            f.write("random_seed:{}\n".format(random_seed))

            f.write("speakers\n")

            for speaker in self.speakers:
                f.write("({},{},{},{},{})\n".format(speaker.x, speaker.y, speaker.ideology, speaker.diplomacy, speaker.uid))

            f.write("begin\n")

    def count_polarized(self):
        num_polarized = 0
        for student in self.students:
            if abs(student.ideology) > NEUTRAL_CUTOFF: # then this student is not ideologically neutral
                num_polarized += 1
        return num_polarized

    def run_model(self):
        num_steps = 500
        for t in range(num_steps):
            if t % 100 == 0:
                print("At timestep {} of {} for experiment {}".format(t, num_steps, self.experiment_name))
            self.step(t)
        self.write_final_log_portion()

    # So within each step can have the iteration to check for the interactions and then
    # another iteration to check for the steps to take
    def step(self, t):
        # The first iteration to account for whatever interactions have occurred, and
        # the second iteration to update change in location (if such a change can occur) for a given agent.
        # So first, go over speakers, and then look into iterating over students
        for speaker in self.speakers:
            # print("at speaker: %s" % (speaker.uid))
            for student in self.find_students(speaker.x, speaker.y, self.speaker_range):
                change = speaker.interacts_with(student)
                self.total_ideology_change += change
        for student in self.students:
            change = student.interacts_with(random.sample(self.find_students(student.x, student.y, 1), 1)[0])
            self.total_ideology_change += change

        # Now for the second iteration, update position of the students, follows
        # a random walk
        for student in self.students:
            # print("at student: %s, current position x: %d, y: %d" % (student.uid, student.x, student.y))
            self.move_student(student)
            # print("still at student: %s, new position x: %d, y: %d" % (student.uid, student.x, student.y))

        self.write_timestep_to_log(t)

    def write_timestep_to_log(self, t):
        student_strings = "".join(map(str, self.students))
        with open(self.log_filename, "a") as f:
            f.write("{}:{}\n".format(t, "".join(student_strings)))

    def write_final_log_portion(self):
        average_ideology_change = self.total_ideology_change / (1.0 * len(self.students))
        final_polarization = self.count_polarized()
        change_in_polarization = final_polarization - self.initial_polarization
        with open(self.log_filename, "a") as f:
            f.write("end\n")
            # TODO: add experiment outputs
            f.write("total_ideology_change:{}\n".format(self.total_ideology_change))
            f.write("average_ideology_change:{}\n".format(average_ideology_change))
            f.write("change_in_polarization:{}\n".format(change_in_polarization))

    # Function to search for unoccupied spaces surrounding given student and randomly select one of the
    # available spaces to move the student to. Currently have hardcoded max distance to move to 2,
    # might be interesting to make this a parameter to the experiment
    def move_student(self, student):
        max_move_distance = 1
        center_x = student.x
        center_y = student.y
        assert self.grid[center_x, center_y] == student
        x_min = max(center_x - max_move_distance, 0)
        y_min = max(center_y - max_move_distance, 0)
        x_max = min(center_x + max_move_distance + 1, GRID_SIZE)
        y_max = min(center_y + max_move_distance + 1, GRID_SIZE)
        found_open_space = set()

        for x in range(x_min, x_max):
            for y in range(y_min, y_max):
                if self.grid[x,y] == None:
                    found_open_space.add((x,y))
        if not len(found_open_space) == 0:
            space_chosen = random.sample(found_open_space, 1)[0]
            new_x, new_y = space_chosen
            student.set_position(new_x, new_y)
            self.grid[new_x, new_y] = student
            self.grid[center_x, center_y] = None
            # print("moved Student from ({},{}) to ({},{})".format(center_x, center_y, new_x, new_y))
            assert (center_x, center_y) != (new_x, new_y)
            assert self.grid[new_x, new_y] == student

    def find_students(self, center_x, center_y, max_range):
        # Returns a list of all people who are at most max_range units away
        # from position (center_x, center_y)
        x_min = max(center_x - max_range, 0)
        y_min = max(center_y - max_range, 0)
        x_max = min(center_x + max_range + 1, GRID_SIZE)
        y_max = min(center_y + max_range + 1, GRID_SIZE)
        # Using a set so that duplicate items are not added
        found_students = set()
        for x in range(x_min, x_max):
            for y in range(y_min, y_max):
                if isinstance(self.grid[x,y], Student):
                    # print("found student %s at r: %d, c: %d" % (self.grid[r,c].uid, r, c))
                    found_students.add(self.grid[x,y])
        # print("students found:", found_students)
        return found_students


import os
os.environ['TF_CPP_MIN_LOG_LEVEL']='2' # 滤掉乱七八糟的输出信息

# 定义checkpoin文件路径
checkpoint_dir = './cnncheckpoint1201/'
checkpoint_prefix = os.path.join(checkpoint_dir, 'model')

import tensorflow as tf
from tensorflow.examples.tutorials.mnist import input_data
mnist = input_data.read_data_sets(r'D:\tmp\MNIST_data', one_hot=True)
sess = tf.InteractiveSession()

# 定义网络层的结构函数
## 定义卷积层的函数
def conv2d(x, W):
    return tf.nn.conv2d(x, W, strides=[1, 1, 1, 1], padding='SAME')
## 定义池化层的函数
def max_pool_2x2(x):
    return tf.nn.max_pool(x, ksize=[1, 2, 2, 1],strides=[1, 2, 2, 1], padding='SAME')

#定义输入格式
x = tf.placeholder(tf.float32, [None, 784])
y_ = tf.placeholder(tf.float32, [None, 10])
x_image = tf.reshape(x, [-1,28,28,1])

#第一层卷积和池化
#
W_conv1 = tf.get_variable('w_conv1',[5, 5, 1, 32],initializer=tf.truncated_normal_initializer(stddev=0.1))
b_conv1 = tf.get_variable('b_conv1',[32],initializer=tf.constant_initializer(0.1))
h_conv1 = tf.nn.relu(conv2d(x_image, W_conv1) + b_conv1)
h_pool1 = max_pool_2x2(h_conv1)

#第二层卷积和池化
#
W_conv2 = tf.get_variable('W_conv2',[5, 5, 32, 64],initializer=tf.truncated_normal_initializer(stddev=0.1))
b_conv2 = tf.get_variable('b_conv2',[64],initializer=tf.constant_initializer(0.1))
h_conv2 = tf.nn.relu(conv2d(h_pool1, W_conv2) + b_conv2)
h_pool2 = max_pool_2x2(h_conv2)

#全连接层
#
W_fc1 = tf.get_variable('W_fc1',[7*7*64,1024],initializer=tf.truncated_normal_initializer(stddev=0.1))
b_fc1 = tf.get_variable('b_fc1',[1024],initializer=tf.constant_initializer(0.1))
h_pool2_flat = tf.reshape(h_pool2,[-1, 7*7*64])
h_fc1 = tf.nn.relu(tf.matmul(h_pool2_flat,W_fc1) + b_fc1)

#Dropout
keep_prob = tf.placeholder(tf.float32)
h_fc1_drop = tf.nn.dropout(h_fc1, keep_prob)

#softmax
W_fc2 = tf.get_variable('W_fc2',[1024,10],initializer=tf.truncated_normal_initializer(stddev=0.1))
b_fc2 = tf.get_variable('b_fc2',[10],initializer=tf.constant_initializer(0.1))
y_conv = tf.nn.softmax(tf.matmul(h_fc1_drop, W_fc2) + b_fc2)
result = tf.argmax(y_conv,1)

saver = tf.train.Saver()
#cross emtropy
cross_entropy = tf.reduce_mean(-tf.reduce_sum(y_ * tf.log(y_conv), reduction_indices=[1]))
train_step = tf.train.AdamOptimizer(1e-4).minimize(cross_entropy)

correct_prediction = tf.equal(result, tf.argmax(y_,1))

accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))
tf.global_variables_initializer().run()
for i in range(10000):
    batch = mnist.train.next_batch(50)
    if i%1000 == 0:
        train_accuracy = accuracy.eval(feed_dict={x:batch[0], y_: batch[1], keep_prob: 1.0})
        print("step %d, training accuracy %g"%(i, train_accuracy))
    train_step.run(feed_dict={x: batch[0], y_: batch[1], keep_prob: 0.5})
    if (i + 1) % 1000 == 0:
        saver.save(sess, checkpoint_prefix, global_step=i+1)
print("test accuracy %g"%accuracy.eval(feed_dict={
    x: mnist.test.images, y_: mnist.test.labels, keep_prob: 1.0}))


# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
# 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 isSubPath(self, head: Optional[ListNode], root: Optional[TreeNode]) -> bool:

        if not head: return True

        if not root: return False

        def go(node, ll, curr):
            if not curr: return True

            if not node: return False

            if node.val == curr.val:
                curr = curr.next
            elif node.val == ll.val:
                curr = ll.next
            else:
                return False

            return go(node.left, ll, curr) or go(node.right, ll, curr)

        return go(root, head, head) or self.isSubPath(head, root.left) or self.isSubPath(head, root.right)


n=int(input())
ls=list(map(int,input().split()))
res=""
for i in range(0,len(ls)//2):
    ind=str(ls[i])
    res=res + ind[0]
for i in range(len(ls)//2,len(ls)):
    ind=str(ls[i])
    res=res + ind[-1]
if((int(res)%11)==0):
    print("OUI")
else:
    print("NON")


"""
Runs 10 steps of SGD for each workload and compares results.
Run it as:
  python3 test_traindiffs.py
"""
import pickle
from subprocess import DEVNULL
from subprocess import run
from subprocess import STDOUT

from absl import flags
from absl.testing import absltest

FLAGS = flags.FLAGS

WORKLOADS = [
    'imagenet_resnet',
    'imagenet_vit',
    'wmt',
    'librispeech_conformer',
    'librispeech_deepspeech',
    'fastmri',
    'ogbg',
    'criteo1tb'
]
GLOBAL_BATCH_SIZE = 16
NUM_TRAIN_STEPS = 10

class ModelDiffTest(absltest.TestCase):

  def test_workload(self):
    # pylint: disable=line-too-long, unnecessary-lambda-assignment
    """
    Compares the multi-gpu jax and ddp-pytorch models for each workload and compares the train and eval metrics collected
    in the corresponding log files. We launch the multi-gpu jax model and the corresponding ddp-pytorch model separately
    using subprocess because ddp-pytorch models are run using torchrun. Secondly, keeping these separate helps avoid
    CUDA OOM errors resulting from the two frameworks competing with each other for GPU memory.
    """
    for workload in WORKLOADS:
      name = f'Testing {workload}'
      jax_logs = '/tmp/jax_log.pkl'
      pyt_logs = '/tmp/pyt_log.pkl'
      run(
          f'python3 -m tests.reference_algorithm_tests --workload={workload} --framework=jax --global_batch_size={GLOBAL_BATCH_SIZE} --log_file={jax_logs}'
          f' --submission_path=tests/modeldiffs/vanilla_sgd_jax.py --identical=True --tuning_search_space=None --num_train_steps={NUM_TRAIN_STEPS}',
          shell=True,
          stdout=DEVNULL,
          stderr=STDOUT,
          check=True)
      run(
          f'torchrun --standalone --nnodes 1 --nproc_per_node 8 -m tests.reference_algorithm_tests --workload={workload} --framework=pytorch --global_batch_size={GLOBAL_BATCH_SIZE} --log_file={pyt_logs}'
          f' --submission_path=tests/modeldiffs/vanilla_sgd_pytorch.py --identical=True --tuning_search_space=None --num_train_steps={NUM_TRAIN_STEPS}',
          shell=True,
          stdout=DEVNULL,
          stderr=STDOUT,
          check=True)
      with open(jax_logs, 'rb') as f:
        jax_results = pickle.load(f)
      with open(pyt_logs, 'rb') as f:
        pyt_results = pickle.load(f)

      # PRINT RESULTS
      k = next(
          iter(
              filter(lambda k: 'train' in k and 'loss' in k,
                     jax_results['eval_results'][0])))
      header = [
          'Iter',
          'Eval (jax)',
          'Eval (torch)',
          'Grad Norm (jax)',
          'Grad Norm (torch)',
          'Train Loss (jax)',
          'Train Loss (torch)',
      ]
      fmt = lambda l: '|' + '|'.join(map(lambda x: f'{x:^20s}', l)) + '|'
      header = fmt(header)
      pad = (len(header) - len((name))) // 2
      print('=' * pad, name, '=' * (len(header) - len(name) - pad), sep='')
      print(header)
      print('=' * len(header))
      for i in range(NUM_TRAIN_STEPS):
        row = map(lambda x: str(round(x, 5)),
                  [
                      jax_results['eval_results'][i][k],
                      pyt_results['eval_results'][i][k],
                      jax_results['scalars'][i]['grad_norm'],
                      pyt_results['scalars'][i]['grad_norm'],
                      jax_results['scalars'][i]['loss'],
                      pyt_results['scalars'][i]['loss'],
                  ])

        print(fmt([f'{i}', *row]))

      print('=' * len(header))

if __name__ == '__main__':
  absltest.main()


import click

from nucypher.cli.commands import (
    status,
    ursula,
    bond
)
from nucypher.cli.painting.help import (
    echo_version,
    echo_config_root_path,
    echo_logging_root_path
)

@click.group()
@click.option('--version', help="Echo the CLI version",
              is_flag=True, callback=echo_version, expose_value=False, is_eager=True)
@click.option('--config-path', help="Echo the configuration root directory path",
              is_flag=True, callback=echo_config_root_path, expose_value=False, is_eager=True)
@click.option('--logging-path', help="Echo the logging root directory path",
              is_flag=True, callback=echo_logging_root_path, expose_value=False, is_eager=True)
def nucypher_cli():
    """Top level command for all things nucypher."""

#
# Character CLI Entry Points
#

ENTRY_POINTS = (

    # Characters & Actors
    ursula.ursula,  # Untrusted Re-Encryption Proxy

    # PRE Application
    bond.bond,
    bond.unbond,

    # Utility Commands
    status.status,  # Network status explorer

)

for entry_point in ENTRY_POINTS:
    nucypher_cli.add_command(entry_point)