# -*- coding: utf-8 -*-
"""
Created on Mon Sep 18 15:26:05 2017

@author: CNLAB
"""
from FCM import *

a=FCM(dataSet,2)

centroids=a.randCent(3).A

a.row, a.col=a.dataset.shape
u2,centroids=a.alg_Pfcm(centroids)


from asyncio import sleep

from telethon import Button, events

from .. import bot, users

search_buttons = [
    [
        Button.switch_inline("Search track 🎧", same_peer=True),
        Button.switch_inline("Search album 💽", query=".a: ", same_peer=True),
    ],
    [Button.inline("❌")],
]

@bot.on(events.NewMessage(pattern="/settings"))
async def settings(event):
    if hasattr(event, "query"):
        answer = event.edit
    else:
        answer = event.respond
    await answer(
        "Settings:",
        buttons=[[Button.inline("Quality 🎧", data="q")], [Button.inline("❌")]],
    )
    raise events.StopPropagation

@bot.on(events.CallbackQuery(pattern="q"))
async def settings_quality(event):
    q = users[event.query.user_id]["quality"]
    a = "Lossless"
    b = "High"
    c = "Medium"
    d = "Low"
    s = " ✅"

    if q == "FLAC":
        a += s
    elif q == "MP3_320":
        b += s
    elif q == "MP3_256":
        c += s
    elif q == "MP3_128":
        d += s

    await event.edit(
        "Select song quality: ",
        buttons=[
            [Button.inline(a, data="FLAC"), Button.inline(b, data="MP3_320")],
            [Button.inline(c, data="MP3_256"), Button.inline(d, data="MP3_128")],
            [Button.inline("◀"), Button.inline("❌")],
        ],
    )

@bot.on(events.CallbackQuery(pattern=r"(FLAC|MP3_\d{3})"))
async def callback(event):
    q = event.data.decode("utf-8")
    if users[event.query.user_id]["quality"] != q:
        users[event.query.user_id]["quality"] = q
        await event.answer("Done!")
        await settings_quality(event)
    else:
        await event.answer("Already selected!")

@bot.on(events.CallbackQuery(pattern="❌"))
async def cancel(event):
    await event.edit("Canceled.")
    await sleep(1.5)
    await event.delete()

@bot.on(events.CallbackQuery(pattern="◀"))
async def back_to_settings(event):
    await settings(event)


import re

def clean_str(s):

    # Remove all non-word characters (everything except numbers and letters)
    s = re.sub(r"[^\w\s]", '', s)

    # Replace all runs of whitespace with nothing
    s = re.sub(r"\s+", '_', s)

    return s


from collections import defaultdict

class Solution:
    def nextGreaterElement(self, nums1: List[int], nums2: List[int]) -> List[int]:
        self.hash = defaultdict(lambda:-1)
        self.stack = []

        for index, num in enumerate(nums2):

            while self.stack and nums2[self.stack[-1]] < num:
                pop_index = self.stack.pop()
                self.hash[nums2[pop_index]] = num
            self.stack.append(index)

        res = []
        for num in nums1:
            res.append(self.hash[num])
        return res


class Algo:
    def __init__(self, s):
        self.bitmap = dict()
        for idx, c in enumerate(s):
            self.bitmap[idx] = int(c == '#')

class Img:
    def __init__(self, d, alg):
        self.d = d
        self.alg = alg
        self.orig = (len(d[0]), len(d))
        self.epoch = 0

    def pr(self, rep):
        out = ''
        for r in self.d:
            out += ("".join(map(str, r))) + '\n'
        return out.replace("0", ".").replace("1", "#") if rep else out

    def __repr__(self):
        return self.pr(True)

    def box_at(self, x, y):
        out = ''
        for (i, j) in [(x - 1, y - 1), (x, y - 1), (x + 1, y - 1), (x - 1, y), (x, y), (x + 1, y), (x - 1, y + 1),
                       (x, y + 1), (x + 1, y + 1)]:
            if 0 <= i < len(self.d[0]) and 0 <= j < len(self.d):
                out += str(self.d[j][i])
            else:
                out += '0'
        return self.alg.bitmap[int(out, 2)]

    def enhance(self):
        nw = []
        for i in range(-1, 1 + len(self.d[0])):
            li = []
            for j in range(-1, 1 + len(self.d)):
                li.append(self.box_at(j, i))
            nw.append(li)
        self.d = nw
        self.epoch += 1

    def pad(self):
        nw = []
        for i in range(-1, 1 + len(self.d[0])):
            li = []
            for j in range(-1, 1 + len(self.d)):
                if 0 <= i < len(self.d[0]) and 0 <= j < len(self.d):
                    li.append(self.d[i][j])
                else:
                    li.append(0)
            nw.append(li)
        self.d = nw

    def trim(self):
        nw = []
        for i in range(len(self.d[0])):
            if i in [0, len(self.d[0])-1]:
                continue
            li = []
            for j in range(len(self.d)):
                if j in [0, len(self.d) - 1]:
                    continue
                li.append(self.d[i][j])
            nw.append(li)
        self.d = nw

    def lit(self):
        cnt = 0
        for y, r in enumerate(self.d):
            for x, c in enumerate(r):
                        cnt += c
        return cnt

with open('case1.txt') as fin:
    algo = Algo(fin.readline().strip())
    _ = fin.readline()
    image = Img([[int(_ == '#') for _ in e.strip()] for e in fin.readlines()], algo)

    print("raw")
    print(image)
    for _ in range(150):
        # print(f"pad #{1+_}")
        image.pad()
        # print(image)

    for _ in range(50):
        print(f"enhance #{1+_}")
        image.enhance()
        # print(image)

    for _ in range(85):
        image.trim()
    # print(image)
    print(f"lit: {image.lit()}")


from connection import connect
from Entity.business import Business

cnx = connect()

#Check if DAO already exists
def checkBusinessById(id):
    query = "SELECT name FROM business WHERE id = %s;"
    cursor = cnx.cursor()
    cursor.execute(query, (id, ))
    for(name) in cursor:
        result=name
    cnx.commit()
    return result

def checkBusinessOwnerById(id):
    query = "SELECT firstname FROM business_owner WHERE id = %s;"
    cursor = cnx.cursor()
    cursor.execute(query, (id, ))
    for(firstname) in cursor:
        result=firstname
    cnx.commit()
    return result


from pyexpat import model
from re import T
from django.db import models
# Create your models here.

class BookmarkModel(models.Model):
    site_title = models.CharField(max_length=200)
    site_url = models.URLField()
    site_keyword = models.JSONField()
    site_memo = models.TextField(blank=True,null=True,max_length=1000,)
    COLOR_CHOICES = (
    (1, 'ðŸŸ¥red'),
    (2, 'ðŸŸ¦blue'),
    (3, 'ðŸŸ©green'),
    (4, 'ðŸŸ¨yellow'),
    (5, 'ðŸŸ§orange'),
    (6, 'â¬›black'),
    (7, 'â¬œgray'),
    (8, 'ðŸŸªpurple')
    )
    site_color = models.IntegerField(choices=COLOR_CHOICES, default=2)


def load(filename='/Users/abergonzo/Downloads/input.txt'):
    l = []
    with open(filename, 'r') as f:
        for curr in f:
            l.append(int(curr.strip()))
    return l

def second(n=3):
    lines, increments = 0, 0
    l = load()
    prev = None
    for i in range(len(l)):
        lines += 1
        curr = sum(l[i: i + n])
        if prev and curr > prev:
            increments += 1
        prev = curr

    print(f'Lines: {lines}')
    print(f'Increments: {increments}')

def first():
    lines, increments = 0, 0

    with open('/Users/abergonzo/Downloads/input.txt', 'r') as f:
        prev = None
        for curr in f:
            curr = int(curr.strip())
            lines += 1
            if prev and curr > prev:
                increments += 1
            prev = curr

        print(f'Lines: {lines}')
        print(f'Increments: {increments}')

second()


class Headlines:
    '''
    Defines new News objects
    '''
    def __init__(self, author, title, description, url, urlToImage, publishedAt, content):
        self.author = author
        self.title = title
        self.description = description
        self.url = url
        self.urlToImage = urlToImage
        self.publishedAt = publishedAt
        self.content = content

class Sources:
    '''
    Defines new Sources objects
    '''

    def __init__(self, source_id, name, description, url, category, language, country):
        self.source_id = source_id
        self.name = name
        self.description = description
        self.url = url
        self.category = category
        self.language = language
        self.country = country


#! python3
"""Implementing artificial neurons in python
"""
import math

# Euler's constant
E = math.e

# Activation function
def sigmoid(x):
    return 1/(1 + E**-x)

# Getting the sum of inputs with weights
def activate(inputs, weights):
    h = 0
    for inp, weight in zip(inputs, weights):
        h += inp * weight

    print("weight", h)
    # Perform activation
    h = sigmoid(h)
    return h

if __name__ == "__main__":

    inputs = [0.7,0.3,0.2]
    weights = [0.4,0.7,0.2]

    output = activate(inputs, weights)
    print(output)


# A script containing various utilities for the project

import pandas as pd
import argparse
import matplotlib.pyplot as plt
import torch
import torch.nn.functional as F
from torchvision import transforms
from sklearn.model_selection import train_test_split
import numpy as np
import sys, getopt, os, glob
import hiddenlayer as hl
from PIL import Image, ImageFile

ImageFile.LOAD_TRUNCATED_IMAGES = True

# These are for command line argument parsing in some other scripts.
# This parsing solution was implemented before I knew the existence of the `argparse` library.
# And I'm too lazy to re-implement CL arg parsing in those scripts.
help_args = ("g", "help")
indir, indir_args = None, ("i:", "indir=")
outformat, outformat_args = None, ("f:", "format=")
outwidth, outwidth_args = None, ("w:", "width=")
outheight, outheight_args = None, ("h:", "height=")
outmode, outmode_args = None, ("m:", "mode=")
changename, changename_args = None, ("c:", "changename=")
outdir, outdir_args = None, ("o:", "outdir=")

def argparser(*args):
    parser = argparse.ArgumentParser()
    for arg in args:
        parser.add_argument(arg)
    args = parser.parse_args()
    return args

def make_options(*args):
    short_opts = ""
    long_opts = []
    for short_opt, long_opt in args:
        short_opts += short_opt
        long_opts.append(long_opt)
    return short_opts, long_opts

def make_args(arg_tuple):
    """
    Assumes that the input tuple has the correct form.
    """
    import re

    short_pattern = r"(\w)(:?)$"
    long_pattern = r"([\w_]+)(=?)$"
    first = re.match(short_pattern, arg_tuple[0]).group(1)
    second = re.match(long_pattern, arg_tuple[1]).group(1)
    return ("-" + first, "--" + second)

def return_args(*args):
    short_opts, long_opts = make_options(*args)
    if len(sys.argv) == 1:
        print("You must specify some commands. Use -g or --help for help.")
        sys.exit(1)
    try:
        arguments, values = getopt.getopt(sys.argv[1:], short_opts, long_opts)
    except getopt.error as e:
        print(e)
        sys.exit(1)
    return arguments, values

def plot_images(images, n_rows=1):
    fig, axs = plt.subplots(n_rows, images.size(0) // n_rows, figsize=(8, 4))
    for ax, img in zip(axs.flat, images):
        img = img.permute(1, 2, 0) * 0.5 + 0.5
        ax.matshow(img)
        ax.set_xticks([])
        ax.set_yticks([])
        ax.tick_params(
            axis="x", which="both", bottom=False, top=False, labelbottom=False
        )
    plt.tight_layout(w_pad=0)

def compute_accuracy(
    model,
    *loaders,
    device="cuda:0",
    accuracy=True,
    criterion=torch.nn.CrossEntropyLoss()
):
    model.eval()
    device = torch.device(device)
    model = model.to(device)
    acc, total, loss = 0, 0, 0
    # To calculate average loss over all batches:
    # running_loss += batch_loss * size_of_current_batch (reduction='mean')
    # Divide running_loss by total of samples: sum_i len(loader_i.sampler)
    # or accumulate sizes of each batch in a loop.
    # Another way: append batch losses in a list (reduction='mean')
    # and take the mean of that list.
    # That is, divide the sum of batch losses by the number of batches.
    # Never use reduction='sum' (?) because some sums are not over the batches
    # e.g., multi-target NLL-loss.
    with torch.no_grad():
        for loader in loaders:
            for images, labels in loader:
                images, labels = images.to(device), labels.to(device)
                outputs = model(images)
                loss += criterion(outputs, labels).item() * labels.size(0)
                total += labels.size(0)
                predicted = torch.argmax(outputs, dim=1)
                acc += (predicted == labels).sum().item()
    acc = acc/total
    if not accuracy:
        acc = 1 - acc # 0/1 loss = 1 - accuracy
    return acc, loss/total

def train_val_test_split(X, y, val_size, test_size=None, rs_train=None, rs_test=69):
    """
    Args:
        test_size: optional proportion value. If not supplied,
            returns a train set and a validation set,
            else returns a train set, validation set, and test set
        rs_train, rs_test: random states for train split, test split
    If test_size is supplied, the test set will be produced first
    then another split is performed on the remaining data to create
    a train set and a validation set. Using this method, we can produce
    the same test set but random train and validation sets if only
    rs_test is defined.
    """
    if test_size:
        val_size = test_size / (1 - test_size)
        X, X_test, y, y_test = train_test_split(
            X, y, test_size=test_size, random_state=rs_test, shuffle=True, stratify=y
        )
        test = np.vstack((X_test, y_test))

    X, X_val, y, y_val = train_test_split(
        X, y, test_size=val_size, stratify=y, random_state=rs_train, shuffle=True
    )

    train = np.vstack((X, y))
    val = np.vstack((X_val, y_val))
    test_dict = {"test": test} if test_size else {}
    ret = {"train": train, "val": val}
    ret.update(test_dict)

    return ret

def test_predictions(loader, classes, *models, num_images=8, device="cuda:0"):
    with torch.no_grad():
        rand_idx = torch.randperm(loader.batch_size)[:num_images]
        images, labels = iter(loader).next()
        images, labels = images[rand_idx], labels[rand_idx]
        ncol = 4
        n_rows = images.size(0) // ncol
        plot_images(images, n_rows=n_rows)
        images, labels = images.to(device), labels.to(device)
        count = 0
        for model in models:
            model = model.to(device)
            # Compute predictions
            y = model(images)
            if count != 0:
                print()
            if count == 0:
                count += 1
            print(f"{model.__class__.__name__}, (Ground truth, prediction):")
            for i in range(num_images):
                ground_truth = classes[labels[i]]
                prediction = classes[y[i].argmax()]
                print((ground_truth, prediction), end=", ")
                if i % ncol == ncol - 1:
                    print()

def prepare_csv(h5file, path, write=True):
    df = {}
    n = 0
    for label in list(h5file.keys()):
        classgroup = h5file[label]
        for imgname in list(classgroup.keys()):
            df.update({n: {"imagepath": imgname, "class": label}})
            n += 1
    df = pd.DataFrame.from_dict(df, orient="index", columns=["imagepath", "class"])
    if write:
        df.to_csv(path)
    return df

def read_from_csv(csvpath=None, df=None):
    assert csvpath is not None or df is not None, "at least one arg should be supplied"
    if df is None:
        df = pd.read_csv(csvpath)
    df = df.astype({"class": 'int64'})
    paths = df["imagepath"].to_numpy()
    labels = df["class"].to_numpy()
    return np.vstack((paths, labels))

def make_df(indir, outdir=None, csv=False, header=True):

    classname = os.path.basename(indir)
    result = {}
    i = 0
    for filepath in glob.iglob(indir + "/**/*.*", recursive=True):
        result.update({i: [filepath, classname]})
        i += 1
    result = pd.DataFrame.from_dict(
        result, orient="index", columns=["imagepath", "class"]
    )
    if csv:
        result.to_csv(outdir, mode="a", header=header, index=False)
    return result

def countfiles(path):
    count = 0
    for filepath in glob.iglob(path + "/**/*.*", recursive=True):
        count += 1
    return count

def render_graph(
    model,
    save_path,
    transforms=None,
    format="pdf",
    orient="LR",
    sample_tensor=torch.zeros([1, 3, 64, 64])
):
    if transforms:
        graph = hl.build_graph(model, sample_tensor, transforms=transforms)
    else:
        graph = hl.build_graph(model, sample_tensor)
    dot = graph.build_dot()
    dot.attr("graph", rankdir=orient) #Left-Right
    dot.format = format
    dot.render(save_path)

def convert_img(img, out_size=None, out_mode=None):
    if out_size:
        img = img.resize(out_size)
    if out_mode:
        img = img.convert(out_mode)
    return img

def predict_one(img_path, model, classes, input_size=(64, 64), input_mode="RGB"):
    pathname, extension = os.path.splitext(img_path)
    basename = os.path.basename(pathname)
    try:
        img = Image.open(img_path)
    except Exception as e:
        print(e)
        return
    img = convert_img(img, out_size=input_size, out_mode=input_mode)
    transform = transforms.Compose([
            transforms.ToTensor(),
            transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))
        ])
    img = transform(img).unsqueeze(0)
    pred = model(img)
    return img, pred

def to_torchscript_and_save(model, filename, method):
    assert method == 'script' or method == 'trace', "method should be \'script\' or \'trace\'"
    script = model.to_torchscript(method=method)
    torch.jit.freeze(script).save(filename)


#!/usr/bin/python3
# -*- coding:utf8 -*-
import requests
import os

api_url = 'http://127.0.0.1:5700/send_msg'
bing_logo = 'https://fitsmallbusiness.com/wp-content/uploads/2019/03/Bing_logo2.png'

def info(msg, sign = '*') :
    # Windows 的终端好像不支持颜色输出 T_T
    # print('\033[32m['+sign+']\033[0m ' + msg)
    print('['+sign+'] ' + str(msg))
    return 0

def hr(n = 20) :
    # print('\033[35m'+'='*n+'\033[0m ')
    print('='*n)
    return 0

def send(send_msg, id, type = "private") :
    send_data = {
        'user_id': id, # qq号， 私聊时用
        'group_id': id,# 群组号
        'discuss_id': id,# 讨论组号
        'message_type': type,#究竟是发消息给谁是由这个消息的来源类型决定的
        'message': str(send_msg),
        'auto_escape': False
    }
    hr()
    info("Sending data:\n" + str(send_data))
    hr()
    status = requests.post(api_url,data=send_data).json()['status']
    if status != 'ok' :
        return False
    info("Send status: " + status)
    return True

def execute(cmd = '') :
    return os.popen(cmd).read()


import iris.tests as tests  # isort:skip

import cf_units
import numpy as np

from iris.analysis.cartography import (
    DEFAULT_SPHERICAL_EARTH_RADIUS,
    _quadrant_area,
)

class TestExampleCases(tests.IrisTest):
    def _radian_bounds(self, coord_list, dtype):
        bound_deg = np.array(coord_list, dtype=dtype)
        bound_deg = np.atleast_2d(bound_deg)
        degrees = cf_units.Unit("degrees")
        radians = cf_units.Unit("radians")
        return degrees.convert(bound_deg, radians)

    def _as_bounded_coords(self, lats, lons, dtype=np.float64):
        return (
            self._radian_bounds(lats, dtype=dtype),
            self._radian_bounds(lons, dtype=dtype),
        )

    def test_area_in_north(self):
        lats, lons = self._as_bounded_coords([0, 10], [0, 10])
        area = _quadrant_area(lats, lons, DEFAULT_SPHERICAL_EARTH_RADIUS)
        self.assertArrayAllClose(area, [[1228800593851.443115234375]])

    def test_area_in_far_north(self):
        lats, lons = self._as_bounded_coords([70, 80], [0, 10])
        area = _quadrant_area(lats, lons, DEFAULT_SPHERICAL_EARTH_RADIUS)
        self.assertArrayAllClose(area, [[319251845980.7646484375]])

    def test_area_in_far_south(self):
        lats, lons = self._as_bounded_coords([-80, -70], [0, 10])
        area = _quadrant_area(lats, lons, DEFAULT_SPHERICAL_EARTH_RADIUS)
        self.assertArrayAllClose(area, [[319251845980.763671875]])

    def test_area_in_north_with_reversed_lats(self):
        lats, lons = self._as_bounded_coords([10, 0], [0, 10])
        area = _quadrant_area(lats, lons, DEFAULT_SPHERICAL_EARTH_RADIUS)
        self.assertArrayAllClose(area, [[1228800593851.443115234375]])

    def test_area_multiple_lats(self):
        lats, lons = self._as_bounded_coords(
            [[-80, -70], [0, 10], [70, 80]], [0, 10]
        )
        area = _quadrant_area(lats, lons, DEFAULT_SPHERICAL_EARTH_RADIUS)

        self.assertArrayAllClose(
            area,
            [
                [319251845980.763671875],
                [1228800593851.443115234375],
                [319251845980.7646484375],
            ],
        )

    def test_area_multiple_lats_and_lons(self):
        lats, lons = self._as_bounded_coords(
            [[-80, -70], [0, 10], [70, 80]], [[0, 10], [10, 30]]
        )
        area = _quadrant_area(lats, lons, DEFAULT_SPHERICAL_EARTH_RADIUS)

        self.assertArrayAllClose(
            area,
            [
                [3.19251846e11, 6.38503692e11],
                [1.22880059e12, 2.45760119e12],
                [3.19251846e11, 6.38503692e11],
            ],
        )

    def test_symmetric_64_bit(self):
        lats, lons = self._as_bounded_coords(
            [[-90, -89.375], [89.375, 90]], [0, 10], dtype=np.float64
        )
        area = _quadrant_area(lats, lons, DEFAULT_SPHERICAL_EARTH_RADIUS)
        self.assertArrayAllClose(area, area[::-1])

    def test_symmetric_32_bit(self):
        lats, lons = self._as_bounded_coords(
            [[-90, -89.375], [89.375, 90]], [0, 10], dtype=np.float32
        )
        area = _quadrant_area(lats, lons, DEFAULT_SPHERICAL_EARTH_RADIUS)
        self.assertArrayAllClose(area, area[::-1])

class TestErrorHandling(tests.IrisTest):
    def test_lat_bounds_1d_error(self):
        self._assert_error_on_malformed_bounds([0, 10], [[0, 10]])

    def test_lon_bounds_1d_error(self):
        self._assert_error_on_malformed_bounds([[0, 10]], [0, 10])

    def test_too_many_lat_bounds_error(self):
        self._assert_error_on_malformed_bounds([[0, 10, 20]], [[0, 10]])

    def test_too_many_lon_bounds_error(self):
        self._assert_error_on_malformed_bounds([[0, 10]], [[0, 10, 20]])

    def _assert_error_on_malformed_bounds(self, lat_bnds, lon_bnds):
        with self.assertRaisesRegex(
            ValueError, r"Bounds must be \[n,2\] array"
        ):
            _quadrant_area(np.array(lat_bnds), np.array(lon_bnds), 1.0)

if __name__ == "__main__":
    tests.main()


"""
추가 테스트 케이스 답
#1 24
#2 0
#3 6
#4 10
#5 10
#6 3
#7 8
#8 17
#9 16
#10 10
#11 7
#12 1111

구현

Memory - 79936 kb
Time - 7595 ms
"""

import sys
sys.stdin = open('5648_input.txt')

dr = [1, 0, -1, 0]          # 방향 (상 우 하 좌)
dc = [0, 1, 0, -1]

T = int(input())
answer = []

for tc in range(1, T+1):
    N = int(input())
    atoms = {}                  # 원자들 정보 (키 - 현재 원자 위치의 좌표 / 값 - 원자의 진행방향, 에너지)
    tc_answer = 0               # 폭발하는 경우의 에너지 총합

    for _ in range(N):
        x, y, direction, energe = map(int, input().split())     # 각 원자들의 정보 (좌표, 진행 방향, 에너지)

        if direction == 1: direction = 2            # 편의를 위한 원자들 진행 방향 보정
        elif direction == 2: direction = 3
        elif direction == 3: direction = 1

        atoms[(y, x)] = [(direction, energe)]       # 원자들 정보에 추가, (키-좌표 / 값-진행방향, 에너지) - 하나의 좌표에 여러 원자가 쌓일 수 있도록 값은 스택처럼 쌓이게 됨

    # print(f'----- 원자의 개수 : {N}')
    # for k, v in atoms.items():
    #     print(f'원자 위치 {k} - 속성 {v}')

    idx = 2000                              # 두개의 원자가 가장 끝에서 시작하는 경우 ((1000,0) 과 (-1000,0) 인 경우 최악의 경우 2000초 후에 충돌)
    while idx >= 0:                         # 시간이 다 될때까지 반복 (딕셔너리에 값이 남았는지 판단할 경우, 판단하는데 시간이 오래 걸려서 넣지 않는게 좋음

        remove = []                         # 0.5초 후에 충돌하여 폭발하는 경우를 추가하는 리스트

        keys = list(atoms.keys())                   # 처음에 좌표값을 모두 반복하여 진행할 방향에 이미 원자가 있는지 여부 파악 (0.5초 후에 충돌하는 경우 탐지를 위함)
        for k in keys:
            y, x = k

            r = y + dr[atoms[(y, x)][0][0]]
            c = x + dc[atoms[(y, x)][0][0]]

            if atoms.get((r, c)) and (atoms[(y, x)][0][0]+2) % 4 == atoms[(r,c)][0][0]:     # 바로 옆에 원자가 있는데, 진행하는 방향이 서로 마주보는 경우
                remove.append((y, x))                                                       # 현재 좌표 제거 명단에 추가

        if remove:                              # 0.5초후 폭발할 좌표들이 있다면
            for e in remove:
                tc_answer += atoms[e][0][1]     # 해당 좌표의 에너지를 추가 시킴
                atoms.pop(e)                    # 이제 원자는 필요없으므로 좌표 및 정보 제거

        keys = list(atoms.keys())               # 원자들 한칸씩 이동
        for k in keys:
            y, x = k

            r = y + dr[atoms[k][0][0]]
            c = x + dc[atoms[k][0][0]]

            if -1000 <= r <= 1000 and -1000 <= c <= 1000:                   # 원자들이 범위를 벗어나지 않으면
                atoms[(r, c)] = atoms.get((r, c), []) + [atoms[k][0]]       # 새로 이동할 좌표에 정보 추가 (여러개의 원자가 한곳에 모일 경우 스택처럼 쌓임)
            atoms[k].pop(0)                                                 # 기존에 있던 좌표의 정보는 제거

        keys = list(atoms.keys())       # 한곳에 만나게된 원자들 폭발
        for k in keys:
            if len(atoms[k]) > 1:                       # 정보가 여러개 있다면 (다수의 원자가 한곳에 모여있다면)
                # for k, v in atoms.items():
                #     print(f'time : {idx}')
                #     print(f'원자 위치 {k} - 속성 {v}')
                #     print(f'{tc_answer}')
                while atoms[k]:                         # 모인 모든 원자들 폭발
                    tc_answer += atoms[k].pop()[1]
                atoms.pop(k)                            # 모두 폭발했으므로 정보에서 제거
            elif len(atoms[k]) == 0:                    # 현재 좌표에 원자가 없는 경우 좌표 제거
                atoms.pop(k)

        idx -= 1

    answer.append('#{} {}'.format(tc, tc_answer))
print(*answer, sep='\n')


import ivy
from ivy.functional.frontends.torch.func_wrapper import to_ivy_arrays_and_back
from ivy.func_wrapper import with_supported_dtypes, with_unsupported_device_and_dtypes

@to_ivy_arrays_and_back
def box_area(boxes):
    return ivy.prod(boxes[..., 2:] - boxes[..., :2], axis=-1)

@with_unsupported_device_and_dtypes(
    {
        "2.1.0 and below": {
            "cpu": ("float16",),
        }
    },
    "torch",
)
@to_ivy_arrays_and_back
def clip_boxes_to_image(boxes, size):
    height, width = size
    boxes_x = boxes[..., 0::2].clip(0, width)
    boxes_y = boxes[..., 1::2].clip(0, height)
    clipped_boxes = ivy.stack([boxes_x, boxes_y], axis=-1)
    return clipped_boxes.reshape(boxes.shape).astype(boxes.dtype)

@to_ivy_arrays_and_back
def nms(boxes, scores, iou_threshold):
    return ivy.nms(boxes, scores, iou_threshold)

@to_ivy_arrays_and_back
def remove_small_boxes(boxes, min_size):
    w, h = boxes[..., 2] - boxes[..., 0], boxes[..., 3] - boxes[..., 1]
    return ivy.nonzero((w >= min_size) & (h >= min_size))[0]

@with_supported_dtypes({"2.1.0 and below": ("float32", "float64")}, "torch")
@to_ivy_arrays_and_back
def roi_align(
    input, boxes, output_size, spatial_scale=1.0, sampling_ratio=1, aligned=False
):
    return ivy.roi_align(
        input, boxes, output_size, spatial_scale, sampling_ratio, aligned
    )


import asyncio
import time
from collections import defaultdict
from decimal import Decimal
from typing import TYPE_CHECKING, Any, AsyncIterable, Dict, List, Optional, Tuple

from bidict import bidict

from hummingbot.connector.constants import s_decimal_NaN
from hummingbot.connector.derivative.binance_perpetual import (
    binance_perpetual_constants as CONSTANTS,
    binance_perpetual_web_utils as web_utils,
)
from hummingbot.connector.derivative.binance_perpetual.binance_perpetual_api_order_book_data_source import (
    BinancePerpetualAPIOrderBookDataSource,
)
from hummingbot.connector.derivative.binance_perpetual.binance_perpetual_auth import BinancePerpetualAuth
from hummingbot.connector.derivative.binance_perpetual.binance_perpetual_user_stream_data_source import (
    BinancePerpetualUserStreamDataSource,
)
from hummingbot.connector.derivative.position import Position
from hummingbot.connector.perpetual_derivative_py_base import PerpetualDerivativePyBase
from hummingbot.connector.trading_rule import TradingRule
from hummingbot.connector.utils import combine_to_hb_trading_pair
from hummingbot.core.api_throttler.data_types import RateLimit
from hummingbot.core.data_type.common import OrderType, PositionAction, PositionMode, PositionSide, TradeType
from hummingbot.core.data_type.in_flight_order import InFlightOrder, OrderUpdate, TradeUpdate
from hummingbot.core.data_type.order_book_tracker_data_source import OrderBookTrackerDataSource
from hummingbot.core.data_type.trade_fee import TokenAmount, TradeFeeBase
from hummingbot.core.data_type.user_stream_tracker_data_source import UserStreamTrackerDataSource
from hummingbot.core.utils.async_utils import safe_gather
from hummingbot.core.utils.estimate_fee import build_trade_fee
from hummingbot.core.web_assistant.web_assistants_factory import WebAssistantsFactory

if TYPE_CHECKING:
    from hummingbot.client.config.config_helpers import ClientConfigAdapter

bpm_logger = None

class BinancePerpetualDerivative(PerpetualDerivativePyBase):
    web_utils = web_utils
    SHORT_POLL_INTERVAL = 5.0
    UPDATE_ORDER_STATUS_MIN_INTERVAL = 10.0
    LONG_POLL_INTERVAL = 120.0

    def __init__(
            self,
            client_config_map: "ClientConfigAdapter",
            binance_perpetual_api_key: str = None,
            binance_perpetual_api_secret: str = None,
            trading_pairs: Optional[List[str]] = None,
            trading_required: bool = True,
            domain: str = CONSTANTS.DOMAIN,
    ):
        self.binance_perpetual_api_key = binance_perpetual_api_key
        self.binance_perpetual_secret_key = binance_perpetual_api_secret
        self._trading_required = trading_required
        self._trading_pairs = trading_pairs
        self._domain = domain
        self._position_mode = None
        self._last_trade_history_timestamp = None
        super().__init__(client_config_map)

    @property
    def name(self) -> str:
        return CONSTANTS.EXCHANGE_NAME

    @property
    def authenticator(self) -> BinancePerpetualAuth:
        return BinancePerpetualAuth(self.binance_perpetual_api_key, self.binance_perpetual_secret_key,
                                    self._time_synchronizer)

    @property
    def rate_limits_rules(self) -> List[RateLimit]:
        return CONSTANTS.RATE_LIMITS

    @property
    def domain(self) -> str:
        return self._domain

    @property
    def client_order_id_max_length(self) -> int:
        return CONSTANTS.MAX_ORDER_ID_LEN

    @property
    def client_order_id_prefix(self) -> str:
        return CONSTANTS.BROKER_ID

    @property
    def trading_rules_request_path(self) -> str:
        return CONSTANTS.EXCHANGE_INFO_URL

    @property
    def trading_pairs_request_path(self) -> str:
        return CONSTANTS.EXCHANGE_INFO_URL

    @property
    def check_network_request_path(self) -> str:
        return CONSTANTS.PING_URL

    @property
    def trading_pairs(self):
        return self._trading_pairs

    @property
    def is_cancel_request_in_exchange_synchronous(self) -> bool:
        return True

    @property
    def is_trading_required(self) -> bool:
        return self._trading_required

    @property
    def funding_fee_poll_interval(self) -> int:
        return 600

    def supported_order_types(self) -> List[OrderType]:
        """
        :return a list of OrderType supported by this connector
        """
        return [OrderType.LIMIT, OrderType.MARKET, OrderType.LIMIT_MAKER]

    def supported_position_modes(self):
        """
        This method needs to be overridden to provide the accurate information depending on the exchange.
        """
        return [PositionMode.ONEWAY, PositionMode.HEDGE]

    def get_buy_collateral_token(self, trading_pair: str) -> str:
        trading_rule: TradingRule = self._trading_rules[trading_pair]
        return trading_rule.buy_order_collateral_token

    def get_sell_collateral_token(self, trading_pair: str) -> str:
        trading_rule: TradingRule = self._trading_rules[trading_pair]
        return trading_rule.sell_order_collateral_token

    def _is_request_exception_related_to_time_synchronizer(self, request_exception: Exception):
        error_description = str(request_exception)
        is_time_synchronizer_related = ("-1021" in error_description
                                        and "Timestamp for this request" in error_description)
        return is_time_synchronizer_related

    def _is_order_not_found_during_status_update_error(self, status_update_exception: Exception) -> bool:
        return str(CONSTANTS.ORDER_NOT_EXIST_ERROR_CODE) in str(
            status_update_exception
        ) and CONSTANTS.ORDER_NOT_EXIST_MESSAGE in str(status_update_exception)

    def _is_order_not_found_during_cancelation_error(self, cancelation_exception: Exception) -> bool:
        return str(CONSTANTS.UNKNOWN_ORDER_ERROR_CODE) in str(
            cancelation_exception
        ) and CONSTANTS.UNKNOWN_ORDER_MESSAGE in str(cancelation_exception)

    def _create_web_assistants_factory(self) -> WebAssistantsFactory:
        return web_utils.build_api_factory(
            throttler=self._throttler,
            time_synchronizer=self._time_synchronizer,
            domain=self._domain,
            auth=self._auth)

    def _create_order_book_data_source(self) -> OrderBookTrackerDataSource:
        return BinancePerpetualAPIOrderBookDataSource(
            trading_pairs=self._trading_pairs,
            connector=self,
            api_factory=self._web_assistants_factory,
            domain=self.domain,
        )

    def _create_user_stream_data_source(self) -> UserStreamTrackerDataSource:
        return BinancePerpetualUserStreamDataSource(
            auth=self._auth,
            connector=self,
            api_factory=self._web_assistants_factory,
            domain=self.domain,
        )

    def _get_fee(self,
                 base_currency: str,
                 quote_currency: str,
                 order_type: OrderType,
                 order_side: TradeType,
                 amount: Decimal,
                 price: Decimal = s_decimal_NaN,
                 is_maker: Optional[bool] = None) -> TradeFeeBase:
        is_maker = is_maker or False
        fee = build_trade_fee(
            self.name,
            is_maker,
            base_currency=base_currency,
            quote_currency=quote_currency,
            order_type=order_type,
            order_side=order_side,
            amount=amount,
            price=price,
        )
        return fee

    async def _update_trading_fees(self):
        """
        Update fees information from the exchange
        """
        pass

    async def _status_polling_loop_fetch_updates(self):
        await safe_gather(
            self._update_order_fills_from_trades(),
            self._update_order_status(),
            self._update_balances(),
            self._update_positions(),
        )

    async def _place_cancel(self, order_id: str, tracked_order: InFlightOrder):
        symbol = await self.exchange_symbol_associated_to_pair(trading_pair=tracked_order.trading_pair)
        api_params = {
            "origClientOrderId": order_id,
            "symbol": symbol,
        }
        cancel_result = await self._api_delete(
            path_url=CONSTANTS.ORDER_URL,
            params=api_params,
            is_auth_required=True)
        if cancel_result.get("code") == -2011 and "Unknown order sent." == cancel_result.get("msg", ""):
            self.logger().debug(f"The order {order_id} does not exist on Binance Perpetuals. "
                                f"No cancelation needed.")
            await self._order_tracker.process_order_not_found(order_id)
            raise IOError(f"{cancel_result.get('code')} - {cancel_result['msg']}")
        if cancel_result.get("status") == "CANCELED":
            return True
        return False

    async def _place_order(
            self,
            order_id: str,
            trading_pair: str,
            amount: Decimal,
            trade_type: TradeType,
            order_type: OrderType,
            price: Decimal,
            position_action: PositionAction = PositionAction.NIL,
            **kwargs,
    ) -> Tuple[str, float]:

        amount_str = f"{amount:f}"
        price_str = f"{price:f}"
        symbol = await self.exchange_symbol_associated_to_pair(trading_pair=trading_pair)
        api_params = {"symbol": symbol,
                      "side": "BUY" if trade_type is TradeType.BUY else "SELL",
                      "quantity": amount_str,
                      "type": "MARKET" if order_type is OrderType.MARKET else "LIMIT",
                      "newClientOrderId": order_id
                      }
        if order_type.is_limit_type():
            api_params["price"] = price_str
        if order_type == OrderType.LIMIT:
            api_params["timeInForce"] = CONSTANTS.TIME_IN_FORCE_GTC
        if order_type == OrderType.LIMIT_MAKER:
            api_params["timeInForce"] = CONSTANTS.TIME_IN_FORCE_GTX
        if self._position_mode == PositionMode.HEDGE:
            if position_action == PositionAction.OPEN:
                api_params["positionSide"] = "LONG" if trade_type is TradeType.BUY else "SHORT"
            else:
                api_params["positionSide"] = "SHORT" if trade_type is TradeType.BUY else "LONG"
        try:
            order_result = await self._api_post(
                path_url=CONSTANTS.ORDER_URL,
                data=api_params,
                is_auth_required=True)
            o_id = str(order_result["orderId"])
            transact_time = order_result["updateTime"] * 1e-3
        except IOError as e:
            error_description = str(e)
            is_server_overloaded = ("status is 503" in error_description
                                    and "Unknown error, please check your request or try again later." in error_description)
            if is_server_overloaded:
                o_id = "UNKNOWN"
                transact_time = time.time()
            else:
                raise
        return o_id, transact_time

    async def _all_trade_updates_for_order(self, tracked_order: InFlightOrder) -> List[TradeUpdate]:
        trade_updates = []
        try:
            exchange_order_id = await tracked_order.get_exchange_order_id()
            trading_pair = await self.exchange_symbol_associated_to_pair(trading_pair=tracked_order.trading_pair)
            all_fills_response = await self._api_get(
                path_url=CONSTANTS.ACCOUNT_TRADE_LIST_URL,
                params={
                    "symbol": trading_pair,
                },
                is_auth_required=True)

            for trade in all_fills_response:
                order_id = str(trade.get("orderId"))
                if order_id == exchange_order_id:
                    position_side = trade["positionSide"]
                    position_action = (PositionAction.OPEN
                                       if (tracked_order.trade_type is TradeType.BUY and position_side == "LONG"
                                           or tracked_order.trade_type is TradeType.SELL and position_side == "SHORT")
                                       else PositionAction.CLOSE)
                    fee = TradeFeeBase.new_perpetual_fee(
                        fee_schema=self.trade_fee_schema(),
                        position_action=position_action,
                        percent_token=trade["commissionAsset"],
                        flat_fees=[TokenAmount(amount=Decimal(trade["commission"]), token=trade["commissionAsset"])]
                    )
                    trade_update: TradeUpdate = TradeUpdate(
                        trade_id=str(trade["id"]),
                        client_order_id=tracked_order.client_order_id,
                        exchange_order_id=trade["orderId"],
                        trading_pair=tracked_order.trading_pair,
                        fill_timestamp=trade["time"] * 1e-3,
                        fill_price=Decimal(trade["price"]),
                        fill_base_amount=Decimal(trade["qty"]),
                        fill_quote_amount=Decimal(trade["quoteQty"]),
                        fee=fee,
                    )
                    trade_updates.append(trade_update)

        except asyncio.TimeoutError:
            raise IOError(f"Skipped order update with order fills for {tracked_order.client_order_id} "
                          "- waiting for exchange order id.")

        return trade_updates

    async def _request_order_status(self, tracked_order: InFlightOrder) -> OrderUpdate:
        trading_pair = await self.exchange_symbol_associated_to_pair(trading_pair=tracked_order.trading_pair)
        order_update = await self._api_get(
            path_url=CONSTANTS.ORDER_URL,
            params={
                "symbol": trading_pair,
                "origClientOrderId": tracked_order.client_order_id
            },
            is_auth_required=True)
        if "code" in order_update:
            if self._is_request_exception_related_to_time_synchronizer(request_exception=order_update):
                _order_update = OrderUpdate(
                    trading_pair=tracked_order.trading_pair,
                    update_timestamp=self.current_timestamp,
                    new_state=tracked_order.current_state,
                    client_order_id=tracked_order.client_order_id,
                )
                return _order_update
        _order_update: OrderUpdate = OrderUpdate(
            trading_pair=tracked_order.trading_pair,

            update_timestamp=order_update["updateTime"] * 1e-3,
            new_state=CONSTANTS.ORDER_STATE[order_update["status"]],
            client_order_id=order_update["clientOrderId"],
            exchange_order_id=order_update["orderId"],
        )
        return _order_update

    async def _iter_user_event_queue(self) -> AsyncIterable[Dict[str, any]]:
        while True:
            try:
                yield await self._user_stream_tracker.user_stream.get()
            except asyncio.CancelledError:
                raise
            except Exception:
                self.logger().network(
                    "Unknown error. Retrying after 1 seconds.",
                    exc_info=True,
                    app_warning_msg="Could not fetch user events from Binance. Check API key and network connection.",
                )
                await self._sleep(1.0)

    async def _user_stream_event_listener(self):
        """
        Wait for new messages from _user_stream_tracker.user_stream queue and processes them according to their
        message channels. The respective UserStreamDataSource queues these messages.
        """
        async for event_message in self._iter_user_event_queue():
            try:
                await self._process_user_stream_event(event_message)
            except asyncio.CancelledError:
                raise
            except Exception as e:
                self.logger().error(f"Unexpected error in user stream listener loop: {e}", exc_info=True)
                await self._sleep(5.0)

    async def _process_user_stream_event(self, event_message: Dict[str, Any]):
        event_type = event_message.get("e")
        if event_type == "ORDER_TRADE_UPDATE":
            order_message = event_message.get("o")
            client_order_id = order_message.get("c", None)
            tracked_order = self._order_tracker.all_fillable_orders.get(client_order_id)
            if tracked_order is not None:
                trade_id: str = str(order_message["t"])

                if trade_id != "0":  # Indicates that there has been a trade

                    fee_asset = order_message.get("N", tracked_order.quote_asset)
                    fee_amount = Decimal(order_message.get("n", "0"))
                    position_side = order_message.get("ps", "LONG")
                    position_action = (PositionAction.OPEN
                                       if (tracked_order.trade_type is TradeType.BUY and position_side == "LONG"
                                           or tracked_order.trade_type is TradeType.SELL and position_side == "SHORT")
                                       else PositionAction.CLOSE)
                    flat_fees = [] if fee_amount == Decimal("0") else [TokenAmount(amount=fee_amount, token=fee_asset)]

                    fee = TradeFeeBase.new_perpetual_fee(
                        fee_schema=self.trade_fee_schema(),
                        position_action=position_action,
                        percent_token=fee_asset,
                        flat_fees=flat_fees,
                    )

                    trade_update: TradeUpdate = TradeUpdate(
                        trade_id=trade_id,
                        client_order_id=client_order_id,
                        exchange_order_id=str(order_message["i"]),
                        trading_pair=tracked_order.trading_pair,
                        fill_timestamp=order_message["T"] * 1e-3,
                        fill_price=Decimal(order_message["L"]),
                        fill_base_amount=Decimal(order_message["l"]),
                        fill_quote_amount=Decimal(order_message["L"]) * Decimal(order_message["l"]),
                        fee=fee,
                    )
                    self._order_tracker.process_trade_update(trade_update)

            tracked_order = self._order_tracker.all_updatable_orders.get(client_order_id)
            if tracked_order is not None:
                order_update: OrderUpdate = OrderUpdate(
                    trading_pair=tracked_order.trading_pair,
                    update_timestamp=event_message["T"] * 1e-3,
                    new_state=CONSTANTS.ORDER_STATE[order_message["X"]],
                    client_order_id=client_order_id,
                    exchange_order_id=str(order_message["i"]),
                )

                self._order_tracker.process_order_update(order_update)

        elif event_type == "ACCOUNT_UPDATE":
            update_data = event_message.get("a", {})
            # update balances
            for asset in update_data.get("B", []):
                asset_name = asset["a"]
                self._account_balances[asset_name] = Decimal(asset["wb"])
                self._account_available_balances[asset_name] = Decimal(asset["cw"])

            # update position
            for asset in update_data.get("P", []):
                trading_pair = asset["s"]
                try:
                    hb_trading_pair = await self.trading_pair_associated_to_exchange_symbol(trading_pair)
                except KeyError:
                    # Ignore results for which their symbols is not tracked by the connector
                    continue

                side = PositionSide[asset['ps']]
                position = self._perpetual_trading.get_position(hb_trading_pair, side)
                if position is not None:
                    amount = Decimal(asset["pa"])
                    if amount == Decimal("0"):
                        pos_key = self._perpetual_trading.position_key(hb_trading_pair, side)
                        self._perpetual_trading.remove_position(pos_key)
                    else:
                        position.update_position(position_side=PositionSide[asset["ps"]],
                                                 unrealized_pnl=Decimal(asset["up"]),
                                                 entry_price=Decimal(asset["ep"]),
                                                 amount=Decimal(asset["pa"]))
                else:
                    await self._update_positions()
        elif event_type == "MARGIN_CALL":
            positions = event_message.get("p", [])
            total_maint_margin_required = Decimal(0)
            # total_pnl = 0
            negative_pnls_msg = ""
            for position in positions:
                trading_pair = position["s"]
                try:
                    hb_trading_pair = await self.trading_pair_associated_to_exchange_symbol(trading_pair)
                except KeyError:
                    # Ignore results for which their symbols is not tracked by the connector
                    continue
                existing_position = self._perpetual_trading.get_position(hb_trading_pair, PositionSide[position['ps']])
                if existing_position is not None:
                    existing_position.update_position(position_side=PositionSide[position["ps"]],
                                                      unrealized_pnl=Decimal(position["up"]),
                                                      amount=Decimal(position["pa"]))
                total_maint_margin_required += Decimal(position.get("mm", "0"))
                if float(position.get("up", 0)) < 1:
                    negative_pnls_msg += f"{hb_trading_pair}: {position.get('up')}, "
            self.logger().warning("Margin Call: Your position risk is too high, and you are at risk of "
                                  "liquidation. Close your positions or add additional margin to your wallet.")
            self.logger().info(f"Margin Required: {total_maint_margin_required}. "
                               f"Negative PnL assets: {negative_pnls_msg}.")

    async def _format_trading_rules(self, exchange_info_dict: Dict[str, Any]) -> List[TradingRule]:
        """
        Queries the necessary API endpoint and initialize the TradingRule object for each trading pair being traded.

        Parameters
        ----------
        exchange_info_dict:
            Trading rules dictionary response from the exchange
        """
        rules: list = exchange_info_dict.get("symbols", [])
        return_val: list = []
        for rule in rules:
            try:
                if web_utils.is_exchange_information_valid(rule):
                    trading_pair = await self.trading_pair_associated_to_exchange_symbol(symbol=rule["symbol"])
                    filters = rule["filters"]
                    filt_dict = {fil["filterType"]: fil for fil in filters}

                    min_order_size = Decimal(filt_dict.get("LOT_SIZE").get("minQty"))
                    step_size = Decimal(filt_dict.get("LOT_SIZE").get("stepSize"))
                    tick_size = Decimal(filt_dict.get("PRICE_FILTER").get("tickSize"))
                    min_notional = Decimal(filt_dict.get("MIN_NOTIONAL").get("notional"))
                    collateral_token = rule["marginAsset"]

                    return_val.append(
                        TradingRule(
                            trading_pair,
                            min_order_size=min_order_size,
                            min_price_increment=Decimal(tick_size),
                            min_base_amount_increment=Decimal(step_size),
                            min_notional_size=Decimal(min_notional),
                            buy_order_collateral_token=collateral_token,
                            sell_order_collateral_token=collateral_token,
                        )
                    )
            except Exception as e:
                self.logger().error(
                    f"Error parsing the trading pair rule {rule}. Error: {e}. Skipping...", exc_info=True
                )
        return return_val

    def _initialize_trading_pair_symbols_from_exchange_info(self, exchange_info: Dict[str, Any]):
        mapping = bidict()
        for symbol_data in filter(web_utils.is_exchange_information_valid, exchange_info.get("symbols", [])):
            exchange_symbol = symbol_data["pair"]
            base = symbol_data["baseAsset"]
            quote = symbol_data["quoteAsset"]
            trading_pair = combine_to_hb_trading_pair(base, quote)
            if trading_pair in mapping.inverse:
                self._resolve_trading_pair_symbols_duplicate(mapping, exchange_symbol, base, quote)
            else:
                mapping[exchange_symbol] = trading_pair
        self._set_trading_pair_symbol_map(mapping)

    async def _get_last_traded_price(self, trading_pair: str) -> float:
        exchange_symbol = await self.exchange_symbol_associated_to_pair(trading_pair=trading_pair)
        params = {"symbol": exchange_symbol}
        response = await self._api_get(
            path_url=CONSTANTS.TICKER_PRICE_CHANGE_URL,
            params=params)
        price = float(response["lastPrice"])
        return price

    def _resolve_trading_pair_symbols_duplicate(self, mapping: bidict, new_exchange_symbol: str, base: str, quote: str):
        """Resolves name conflicts provoked by futures contracts.

        If the expected BASEQUOTE combination matches one of the exchange symbols, it is the one taken, otherwise,
        the trading pair is removed from the map and an error is logged.
        """
        expected_exchange_symbol = f"{base}{quote}"
        trading_pair = combine_to_hb_trading_pair(base, quote)
        current_exchange_symbol = mapping.inverse[trading_pair]
        if current_exchange_symbol == expected_exchange_symbol:
            pass
        elif new_exchange_symbol == expected_exchange_symbol:
            mapping.pop(current_exchange_symbol)
            mapping[new_exchange_symbol] = trading_pair
        else:
            self.logger().error(
                f"Could not resolve the exchange symbols {new_exchange_symbol} and {current_exchange_symbol}")
            mapping.pop(current_exchange_symbol)

    async def _update_balances(self):
        """
        Calls the REST API to update total and available balances.
        """
        local_asset_names = set(self._account_balances.keys())
        remote_asset_names = set()

        account_info = await self._api_get(path_url=CONSTANTS.ACCOUNT_INFO_URL,
                                           is_auth_required=True)
        assets = account_info.get("assets")
        for asset in assets:
            asset_name = asset.get("asset")
            available_balance = Decimal(asset.get("availableBalance"))
            wallet_balance = Decimal(asset.get("walletBalance"))
            self._account_available_balances[asset_name] = available_balance
            self._account_balances[asset_name] = wallet_balance
            remote_asset_names.add(asset_name)

        asset_names_to_remove = local_asset_names.difference(remote_asset_names)
        for asset_name in asset_names_to_remove:
            del self._account_available_balances[asset_name]
            del self._account_balances[asset_name]

    async def _update_positions(self):
        positions = await self._api_get(path_url=CONSTANTS.POSITION_INFORMATION_URL,
                                        is_auth_required=True)
        for position in positions:
            trading_pair = position.get("symbol")
            try:
                hb_trading_pair = await self.trading_pair_associated_to_exchange_symbol(trading_pair)
            except KeyError:
                # Ignore results for which their symbols is not tracked by the connector
                continue
            position_side = PositionSide[position.get("positionSide")]
            unrealized_pnl = Decimal(position.get("unRealizedProfit"))
            entry_price = Decimal(position.get("entryPrice"))
            amount = Decimal(position.get("positionAmt"))
            leverage = Decimal(position.get("leverage"))
            pos_key = self._perpetual_trading.position_key(hb_trading_pair, position_side)
            if amount != 0:
                _position = Position(
                    trading_pair=await self.trading_pair_associated_to_exchange_symbol(trading_pair),
                    position_side=position_side,
                    unrealized_pnl=unrealized_pnl,
                    entry_price=entry_price,
                    amount=amount,
                    leverage=leverage
                )
                self._perpetual_trading.set_position(pos_key, _position)
            else:
                self._perpetual_trading.remove_position(pos_key)

    async def _update_order_fills_from_trades(self):
        last_tick = int(self._last_poll_timestamp / self.UPDATE_ORDER_STATUS_MIN_INTERVAL)
        current_tick = int(self.current_timestamp / self.UPDATE_ORDER_STATUS_MIN_INTERVAL)
        if current_tick > last_tick and len(self._order_tracker.active_orders) > 0:
            trading_pairs_to_order_map: Dict[str, Dict[str, Any]] = defaultdict(lambda: {})
            for order in self._order_tracker.active_orders.values():
                trading_pairs_to_order_map[order.trading_pair][order.exchange_order_id] = order
            trading_pairs = list(trading_pairs_to_order_map.keys())
            tasks = [
                self._api_get(
                    path_url=CONSTANTS.ACCOUNT_TRADE_LIST_URL,
                    params={"symbol": await self.exchange_symbol_associated_to_pair(trading_pair=trading_pair)},
                    is_auth_required=True,
                )
                for trading_pair in trading_pairs
            ]
            self.logger().debug(f"Polling for order fills of {len(tasks)} trading_pairs.")
            results = await safe_gather(*tasks, return_exceptions=True)
            for trades, trading_pair in zip(results, trading_pairs):
                order_map = trading_pairs_to_order_map.get(trading_pair)
                if isinstance(trades, Exception):
                    self.logger().network(
                        f"Error fetching trades update for the order {trading_pair}: {trades}.",
                        app_warning_msg=f"Failed to fetch trade update for {trading_pair}."
                    )
                    continue
                for trade in trades:
                    order_id = str(trade.get("orderId"))
                    if order_id in order_map:
                        tracked_order: InFlightOrder = order_map.get(order_id)
                        position_side = trade["positionSide"]
                        position_action = (PositionAction.OPEN
                                           if (tracked_order.trade_type is TradeType.BUY and position_side == "LONG"
                                               or tracked_order.trade_type is TradeType.SELL and position_side == "SHORT")
                                           else PositionAction.CLOSE)
                        fee = TradeFeeBase.new_perpetual_fee(
                            fee_schema=self.trade_fee_schema(),
                            position_action=position_action,
                            percent_token=trade["commissionAsset"],
                            flat_fees=[TokenAmount(amount=Decimal(trade["commission"]), token=trade["commissionAsset"])]
                        )
                        trade_update: TradeUpdate = TradeUpdate(
                            trade_id=str(trade["id"]),
                            client_order_id=tracked_order.client_order_id,
                            exchange_order_id=trade["orderId"],
                            trading_pair=tracked_order.trading_pair,
                            fill_timestamp=trade["time"] * 1e-3,
                            fill_price=Decimal(trade["price"]),
                            fill_base_amount=Decimal(trade["qty"]),
                            fill_quote_amount=Decimal(trade["quoteQty"]),
                            fee=fee,
                        )
                        self._order_tracker.process_trade_update(trade_update)

    async def _update_order_status(self):
        """
        Calls the REST API to get order/trade updates for each in-flight order.
        """
        last_tick = int(self._last_poll_timestamp / self.UPDATE_ORDER_STATUS_MIN_INTERVAL)
        current_tick = int(self.current_timestamp / self.UPDATE_ORDER_STATUS_MIN_INTERVAL)
        if current_tick > last_tick and len(self._order_tracker.active_orders) > 0:
            tracked_orders = list(self._order_tracker.active_orders.values())
            tasks = [
                self._api_get(
                    path_url=CONSTANTS.ORDER_URL,
                    params={
                        "symbol": await self.exchange_symbol_associated_to_pair(trading_pair=order.trading_pair),
                        "origClientOrderId": order.client_order_id
                    },
                    is_auth_required=True,
                    return_err=True,
                )
                for order in tracked_orders
            ]
            self.logger().debug(f"Polling for order status updates of {len(tasks)} orders.")
            results = await safe_gather(*tasks, return_exceptions=True)

            for order_update, tracked_order in zip(results, tracked_orders):
                client_order_id = tracked_order.client_order_id
                if client_order_id not in self._order_tracker.all_orders:
                    continue
                if isinstance(order_update, Exception) or "code" in order_update:
                    if not isinstance(order_update, Exception) and \
                            (order_update["code"] == -2013 or order_update["msg"] == "Order does not exist."):
                        await self._order_tracker.process_order_not_found(client_order_id)
                    else:
                        self.logger().network(
                            f"Error fetching status update for the order {client_order_id}: " f"{order_update}."
                        )
                    continue

                new_order_update: OrderUpdate = OrderUpdate(
                    trading_pair=await self.trading_pair_associated_to_exchange_symbol(order_update['symbol']),
                    update_timestamp=order_update["updateTime"] * 1e-3,
                    new_state=CONSTANTS.ORDER_STATE[order_update["status"]],
                    client_order_id=order_update["clientOrderId"],
                    exchange_order_id=order_update["orderId"],
                )

                self._order_tracker.process_order_update(new_order_update)

    async def _get_position_mode(self) -> Optional[PositionMode]:
        # To-do: ensure there's no active order or contract before changing position mode
        if self._position_mode is None:
            response = await self._api_get(
                path_url=CONSTANTS.CHANGE_POSITION_MODE_URL,
                is_auth_required=True,
                limit_id=CONSTANTS.GET_POSITION_MODE_LIMIT_ID,
                return_err=True
            )
            self._position_mode = PositionMode.HEDGE if response.get("dualSidePosition") else PositionMode.ONEWAY

        return self._position_mode

    async def _trading_pair_position_mode_set(self, mode: PositionMode, trading_pair: str) -> Tuple[bool, str]:
        msg = ""
        success = True
        initial_mode = await self._get_position_mode()
        if initial_mode != mode:
            params = {
                "dualSidePosition": mode.value
            }
            response = await self._api_post(
                path_url=CONSTANTS.CHANGE_POSITION_MODE_URL,
                data=params,
                is_auth_required=True,
                limit_id=CONSTANTS.POST_POSITION_MODE_LIMIT_ID,
                return_err=True
            )
            if not (response["msg"] == "success" and response["code"] == 200):
                success = False
                return success, str(response)
            self._position_mode = mode
        return success, msg

    async def _set_trading_pair_leverage(self, trading_pair: str, leverage: int) -> Tuple[bool, str]:
        symbol = await self.exchange_symbol_associated_to_pair(trading_pair)
        params = {'symbol': symbol, 'leverage': leverage}
        set_leverage = await self._api_post(
            path_url=CONSTANTS.SET_LEVERAGE_URL,
            data=params,
            is_auth_required=True,
        )
        success = False
        msg = ""
        if set_leverage["leverage"] == leverage:
            success = True
        else:
            msg = 'Unable to set leverage'
        return success, msg

    async def _fetch_last_fee_payment(self, trading_pair: str) -> Tuple[int, Decimal, Decimal]:
        exchange_symbol = await self.exchange_symbol_associated_to_pair(trading_pair)
        payment_response = await self._api_get(
            path_url=CONSTANTS.GET_INCOME_HISTORY_URL,
            params={
                "symbol": exchange_symbol,
                "incomeType": "FUNDING_FEE",
            },
            is_auth_required=True,
        )
        funding_info_response = await self._api_get(
            path_url=CONSTANTS.MARK_PRICE_URL,
            params={
                "symbol": exchange_symbol,
            },
        )
        sorted_payment_response = sorted(payment_response, key=lambda a: a.get('time', 0), reverse=True)
        if len(sorted_payment_response) < 1:
            timestamp, funding_rate, payment = 0, Decimal("-1"), Decimal("-1")
            return timestamp, funding_rate, payment
        funding_payment = sorted_payment_response[0]
        _payment = Decimal(funding_payment["income"])
        funding_rate = Decimal(funding_info_response["lastFundingRate"])
        timestamp = funding_payment["time"]
        if _payment != Decimal("0"):
            payment = _payment
        else:
            timestamp, funding_rate, payment = 0, Decimal("-1"), Decimal("-1")
        return timestamp, funding_rate, payment


import logging

import numpy as np
from pipeline.graph import OptimizationGraph
from optimizer.genetic import GA
from optimizer.testfunctions import (
    rosenbrock,
    animateSwarm,
    rosenbrockContourConstrained,
)

# Set logging formats
logging.basicConfig(
    level=logging.INFO,
    format=("[%(filename)8s] [%(levelname)4s] :  %(funcName)s - %(message)s"),
)

if __name__ == "__main__":

    # ========================================================

    CASE1 = True
    CASE2 = False
    CASE3 = False

    # ========================================================
    if CASE1:
        logging.info(50 * "=")
        logging.info("CASE1 - Start Testing")
        logging.info(50 * "=")

        itermax = 40
        xbounds = [(-5, 10), (0, 15)]
        ybounds = [(0, 13500)]
        cbounds = []

        def branin(X, a, b, c, r, s, t):
            return (
                a * (X[:, 1] - b * X[:, 0] ** 2 + c * X[:, 0] - r) ** 2
                + s * (1 - t) * np.cos(X[:, 0])
                + s,
                None,
            )

        t1 = []
        def myCallBackFunction(X, Y, C, iter):
            t1.append([X,Y,C,iter])

        ga = GA(
            branin,
            xbounds,
            ybounds,
            cbounds,
            callback = myCallBackFunction,
            npop=10,
            args=(1, 5.1 / (4 * np.pi ** 2), 5 / np.pi, 6, 10, 1 / (8 * np.pi)),
        )
        ga.initialize()
        ga.iterate(itermax)

        ga.restart()
        ga.iterate(5)

        logging.info(ga.xbest)
        logging.info(ga.ybest)

        print(t1)

        logging.info("CASE1 - passed :)")

    # ========================================================
    if CASE2:
        logging.info(50 * "=")
        logging.info("CASE2 - Start Testing")
        logging.info(50 * "=")

        d = 32
        # Define toolchain
        graph = OptimizationGraph(xdim=d, rdim=1, tindex=[0], cindex=[])
        graph.singleProcessChain(lambda x: np.sum(x ** 2, axis=1) / d)  #

        # Optimizer stuff
        itermax = 3
        xbounds = d * [[-4, 4]]
        ybounds = [(0, 13500)]
        cbounds = []

        ga = GA(graph.run, xbounds, ybounds, cbounds, npop=10)

        ga.initialize()
        ga.iterate(itermax)

        # # Postprocessing
        # Xcine, Ycine = graph.postprocessAnimate()
        # animateSwarm(Xcine, Ycine, rosenbrockContour, xbounds=xbounds, store=False)
        # graph.postprocess()

        del graph, ga

        logging.info("CASE2 - passed :)")

    # ========================================================
    if CASE3:
        logging.info(50 * "=")
        logging.info("CASE3 - Start Testing")
        logging.info(50 * "=")

        # Define toolchain
        graph = OptimizationGraph(
            xdim=2,
            rdim=2,
            tindex=[0],
            cindex=[1],
            xlabels=["x", "y"],
            rlabels=["z", "c"],
        )

        graph.singleProcessChain(rosenbrock)

        # Optimizer stuff
        itermax = 20
        xbounds = [(-4, 4), (-4, 4)]
        ybounds = [(0, 13500)]
        cbounds = [(0, 1.3)]

        ga = GA(graph.run, xbounds, ybounds, cbounds, npop=20)
        ga.initialize()
        ga.iterate(itermax)

        # swarm.restart(resetParticles=True)
        # swarm.iterate(5)

        Xcine, Ycine = graph.postprocessAnimate()
        animateSwarm(
            Xcine, Ycine, rosenbrockContourConstrained, xbounds=xbounds, store=False
        )
        # tc.postprocess()


#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from refinery.units.compression.zl import zl
from refinery.units.formats import PathExtractorUnit, UnpackResult
from refinery.lib.meta import SizeInt
from refinery.lib.dotnet.types import (
    Byte,
    StreamReader,
    StringPrimitive,
    UInt32,
    UInt64,
    ParserEOF
)

class dnsfx(PathExtractorUnit):
    """
    Extracts files from .NET single file applications.
    """
    _SIGNATURE = bytes([
        # 32 bytes represent the bundle signature: SHA-256 for '.net core bundle'
        0x8b, 0x12, 0x02, 0xb9, 0x6a, 0x61, 0x20, 0x38,
        0x72, 0x7b, 0x93, 0x02, 0x14, 0xd7, 0xa0, 0x32,
        0x13, 0xf5, 0xb9, 0xe6, 0xef, 0xae, 0x33, 0x18,
        0xee, 0x3b, 0x2d, 0xce, 0x24, 0xb3, 0x6a, 0xae
    ])

    def unpack(self, data):
        reader = StreamReader(data)
        reader.seek(self._find_bundle_manifest_offset(data))

        major_version = reader.expect(UInt32)
        minor_version = reader.expect(UInt32)
        self.log_info(F'version {major_version}.{minor_version}')

        count = reader.expect(UInt32)
        bhash = reader.expect(StringPrimitive)
        self.log_info(F'bundle {bhash} contains {count} files')

        if major_version >= 2:
            reader.expect(UInt64) # depsOffset
            reader.expect(UInt64) # depsSize
            reader.expect(UInt64) # runtimeConfigOffset
            reader.expect(UInt64) # runtimeConfigSize
            reader.expect(UInt64) # flags

        for _ in range(count):
            try:
                offset = reader.expect(UInt64)
                size = reader.expect(UInt64)
                compressed_size = 0
                if major_version >= 6:
                    compressed_size = reader.expect(UInt64)
                type = reader.expect(Byte)
                path = reader.expect(StringPrimitive)

                def _logmsg():
                    _log = F'read item at offset 0x{offset:08X}, type 0x{type:02X}, size {SizeInt(size)!r}'
                    if compressed_size:
                        return F'{_log}, compressed to size {SizeInt(compressed_size)!r}'
                    return F'{_log}, uncompressed'

                self.log_debug(_logmsg)

                with reader.checkpoint():
                    reader.seek(offset)
                    if compressed_size:
                        item_data = reader.read(compressed_size) | zl | bytearray
                    else:
                        item_data = reader.read(size)

                yield UnpackResult(path, item_data)
            except ParserEOF:
                self.log_warn('unexpected EOF while parsing bundle, terminating')
                break

    def _find_bundle_manifest_offset(self, data: bytearray) -> int:
        bundle_sig_offset = data.find(self._SIGNATURE, 0)
        if bundle_sig_offset < 0:
            raise ValueError('Cannot find valid Bundle Manifest offset. Is this a .NET Bundle?')
        return int.from_bytes(data[bundle_sig_offset - 8:bundle_sig_offset], 'little')

    @classmethod
    def handles(self, data: bytearray):
        return self._SIGNATURE in data


import findspark
findspark.init('/media/light/UbuntuDrive/work/spark-2.3.0-bin-hadoop2.7')

from pyspark.sql import SparkSession
from pyspark.ml.feature import StandardScaler, VectorAssembler
from pyspark.ml.clustering import KMeans

spark = SparkSession.builder.master(
    'local').appName('clustering').getOrCreate()

data = spark.read.csv('/home/light/Downloads/hack_data.csv',
                      inferSchema=True, header=True)

data.show()
data.printSchema()
data.columns

data = data.drop('Location')

columns = data.columns

assembler = VectorAssembler(inputCols=columns, outputCol='unscaled_features')

output = assembler.transform(data)

output.printSchema()

scaler = StandardScaler(inputCol='unscaled_features', outputCol='features')

scaled = scaler.fit(output).transform(output)

final_data = scaled.select('features')

KMeans

model2 = KMeans(featuresCol='features', k=2)
model3 = KMeans(featuresCol='features', k=3)

modelfit2 = model2.fit(final_data)
modelfit3 = model3.fit(final_data)

cluster_final_data2 = modelfit2.transform(final_data)

cluster_final_data2.groupby('prediction').count().show()

cluster_final_data3 = modelfit3.transform(final_data)
cluster_final_data3.groupby('prediction').count().show()

# as we can see in k =2 they are evenly splitted so we can confirm that there were 2 hackers

spark.stop()


import urllib.request, json

read = open ("death-rates-total-air-pollution.csv","r")
line1 = read.readline()

line1 = "Longitude,Latitude,"+line1
read.close()

def count_to_pos(country):
    c2 = ""
    for e in country:
        if e == " ":
            c2+="%20"
        else:
            c2+=e

    with urllib.request.urlopen(
            "http://nominatim.openstreetmap.org/search?country=" + c2 + "&format=json&polygon=0") as url:
        data = json.loads(url.read().decode())
        return data[0]["lon"],data[0]["lat"]

def update_csv():
    global line1
    read = open ("death-rates-total-air-pollution.csv","r")
    file_out = open ("death-rates-total-air-pollution-short_out.csv","w")
    file_out.write(line1)
    x = ""
    pos = (0, 0)
    for line in read.readlines()[1:]:
        if "2017" in line:
            comma = line.index(",")
            country = line[0:comma]
            if x != country:
                try:
                    pos = count_to_pos(country)
                    worked = True
                except IndexError:
                    worked = False
                x = country
            if worked:
                line_to_add = pos[0] + "," + pos[1] + "," + line
                print(line_to_add)
                file_out.write(line_to_add)
    file_out.close()

    read.close()

update_csv()


from cn.yujian95.crawler.weather.weather import get_year_weather_data
import pandas as pd

# 抓取城市
city = 'guangzhou'
# 抓取年份开始
start_year = 2011
# 抓取年份结束
end_year = 2013

print("------------开始执行程序------------")
weather_data_of_year = []
# 设定抓取的年份范围
for year in range(start_year, end_year):
    weather_data_of_year.append(get_year_weather_data(str(year), city))
# 数据拼接，重新生成索引
result = pd.concat(weather_data_of_year).reset_index(drop=True)
# 数据储存为csv格式，去除索引，解码以防止乱码
result.to_csv(str(start_year) + '_to_' + city + '_data.csv', index=False, encoding='utf-8')
file_name = 'Weather data for ' + city + ' in ' + str(start_year) + ' and ' + str(end_year) + '.csv'
result.to_csv(file_name, index=False, encoding='utf-8')
print("------------结束执行程序------------")


from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support.ui import Select
from selenium.common.exceptions import *
from traceback import print_stack
import utilities.custom_logger as cl
import logging
import time
import os

class SeleniumDriver:

    log = cl.custom_logging(logging.DEBUG)

    def __init__(self, driver):
        self.driver = driver

    def getTitle(self):
        return self.driver.title

    def getBy(self, locator_type):
        locatorType = locator_type.lower()

        if locatorType == "id":
            return By.ID
        elif locatorType == "name":
            return By.NAME
        elif locatorType == "xpath":
            return By.XPATH
        elif locatorType == "class":
            return By.CLASS_NAME
        elif locatorType == "link":
            return By.LINK_TEXT
        elif locatorType == "partial_link":
            return By.PARTIAL_LINK_TEXT
        elif locatorType == "tag":
            return By.TAG_NAME
        elif locatorType == "css":
            return By.CSS_SELECTOR
        else:
            self.log.error("*** The locator type ", locatorType, " is not valid")

        return False

    def waitForElement(self, locator, locator_type="id", timeoutSecs=7, poll_freq=1):
        element = None
        print("Waiting for the Element for max", timeoutSecs, "secs with polling frequency of", poll_freq, "secs..")
        wait = WebDriverWait(self.driver, timeout=timeoutSecs, poll_frequency=poll_freq,
                             ignored_exceptions=[NoSuchElementException,
                                                 ElementNotVisibleException,
                                                 ElementNotSelectableException])
        try:
            getby = self.getBy(locator_type)
            element = wait.until(EC.element_to_be_clickable((getby, locator)))
            self.log.info("Element was found with locator: ", locator)
        except:
            self.log.error("*** Element was not found with locator: ", locator)
        return element

    def isElementPresent(self, locator, locator_type="id", timeoutSecs=10, poll_freq=1):
        try:
            print("Waiting for the Element for max", timeoutSecs, "secs with polling frequency of", poll_freq, "secs..")
            wait = WebDriverWait(self.driver, timeout=timeoutSecs, poll_frequency=poll_freq,
                                 ignored_exceptions=[NoSuchElementException,
                                                     ElementNotVisibleException,
                                                     ElementNotSelectableException])
            getby = self.getBy(locator_type)
            element = wait.until(EC.presence_of_element_located((getby, locator)))
            self.log.info("Element is present with locator: ", locator)
            return True
        except:
            self.log.error("*** Element is not present with locator: ", locator)
            return False

    def isElementDisplayed(self, timeoutSecs=7, poll_freq=1, element=None):
        try:
            print("Waiting for the Element display for max ", timeoutSecs, " secs with polling frequency of ", poll_freq, "secs..")
            wait = WebDriverWait(self.driver, timeout=timeoutSecs, poll_frequency=poll_freq,
                                 ignored_exceptions=[NoSuchElementException,
                                                     ElementNotVisibleException,
                                                     ElementNotSelectableException])
            result = wait.until(EC.visibility_of_element_located(element))
            if result is not None:
                self.log.info("Element is displayed")
                return True
            else:
                self.log.error("*** Element is not displayed")
                return False
        except:
            self.log.error("*** Exception occurred while checking for element display")
            return False

    def clickElement(self, locator, locator_type="id"):
        try:
            element = self.waitForElement(locator, locator_type)
            element.click()
            self.log.info("Element was clicked with locator: '" + locator + "' and locator_type: " + locator_type)
        except:
            self.log.error("*** Element was not found with locator: '" + locator + "' and locator_type: " + locator_type)
            print_stack()

    def sendKeys(self, data, locator, locator_type="id"):
        try:
            element = self.waitForElement(locator, locator_type)
            element.send_keys(data)
            self.log.info("Keys were sent to element with locator: '" + locator + "' and locator_type: " + locator_type)
        except:
            self.log.error("*** Keys were not sent to element with locator: '" + locator + "' and locator_type: " + locator_type)
            print_stack()

    def screenshot(self, resultMessage):
        filename = resultMessage + "." + str(time.time() * 1000) + ".png"
        file_dir = "/screenshots/"
        full_file = file_dir + filename
        try:
            if not os.path.exists(file_dir):
                os.makedirs(file_dir)
            self.driver.save_screenshot(full_file)
            self.log.info("Screenshot saved as " + full_file)
        except:
            self.log.error("*** Exception while saving screenshot")
            print_stack()

    def scrollPage(self, direction="up"):
        if direction.lower() == "up":
            self.driver.execute_script("window.scrollBy(0, -1000);")
        elif direction.lower() == "half-up":
            self.driver.execute_script("window.scrollBy(0, -500);")
        elif direction.lower() == "half-down":
            self.driver.execute_script("window.scrollBy(0, 500);")
        elif direction.lower() == "little-up":
            self.driver.execute_script("window.scrollBy(0, -200);")
        elif direction.lower() == "little-down":
            self.driver.execute_script("window.scrollBy(0, 200);")
        else:
            self.driver.execute_script("window.scrollBy(0, 1000);")

    def switch_to_frame(self, frame_name):
        try:
            self.driver.switch_to.frame(frame_name)
            self.log.info("Switched to frame: " + frame_name)
        except:
            self.log.error("*** Exception occurred while switching to frame")

    def switch_default_content(self):
        self.driver.switch_to.default_content()

    def select_dropdown_value(self, dropdown_locator, dropdown_locator_type="id", dropdown_value="India"):
        select = Select(self.waitForElement(dropdown_locator, dropdown_locator_type))
        try:
            select.select_by_visible_text(dropdown_value)
            self.log.info("Selected dropdown value as : " + dropdown_value)
        except:
            self.log.error("*** Dropdown Value not found: " + dropdown_value)


class Solution(object):
    def majorityElement(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        if len(nums) == 1:
            return nums[0]
        counter = {}
        majority = (len(nums) // 2) + 1
        for i in range(len(nums)):
            if nums[i] in counter.keys():
                counter[nums[i]] += 1
                if counter[nums[i]] >= majority:
                    return nums[i]
            else:
                counter[nums[i]] = 1

        return None

sol = Solution()
print(sol.majorityElement([1]))


sanwich_orders=['tuna','pastrami','fruit','pastrami','pastrami']
finished_sandwiches=[]

print('pastrami has been sold out!')
while 'pastrami' in sanwich_orders:
	sanwich_orders.remove('pastrami')

while sanwich_orders:
	current_order=sanwich_orders.pop()
	print(f'I made your {current_order} sandwich')
	finished_sandwiches.append(current_order)

print('\nAll the sanwichs have been finished:')
for finished_sandwiche in finished_sandwiches:
	print(finished_sandwiche)


"""
Contains utility functions that I couldn't neatly categorize
"""
# will need a function to check if a cell is safe or not
from knowledge_base import *
from knowledge_base import print_knowledge_base

def reveal_space(kb, board, row, col, dim, p=False, autoReveal=False):
    """
    Reveal the chosen space on the minefield

    :param kb: Knowledge base
    :param board: Minefield board
    :param row: Row of the point I want to uncover
    :param col: Col of the point I want to uncover
    :param dim: Dimensions of the board
    :param p: whether or not I should print the results, defaults to False
    :param autoReveal: Whether or not I reveal all zero neighbors if revealed is 0
    :return: The new knowledge base, or the original knowledge base if the X or Y coord is out of bounds or space already revealed
    """

    neighbors = [(0, 1), (0, -1), (1, 0), (-1, 0), (1, 1), (1, -1), (-1, 1), (-1, -1)]
    if p == True and (row >= dim or col >= dim or row < 0 or col < 0):
        print("Out of bounds")
    else:
        if kb[row][col] == board[row][col]:
            if p:
                print("That space was already revealed!")
        else:
            kb[row][col] = board[row][col]
            if board[row][col] == 'M':
                if p:
                    print("BOOM! Mine revealed!")
            elif board[row][col] != 'M':
                if p:
                    print("Mine not detected")
                for i in range(len(neighbors)):
                    # reveal all neighbor cells that aren't mines and have no neighboring mines
                    newRow = row + neighbors[i][0]
                    newCol = col + neighbors[i][1]
                    if isValid(board, dim, newRow, newCol) and (board[row][col] == "0" or board[row][col] == 'C') and board[newRow][newCol] != 'M' and kb[row][col] == board[row][col] and autoReveal:
                        kb = reveal_space(kb, board, newRow, newCol, dim, False, True)

    return kb

def isMine(arr, dim, row, col):
    """
    Check to see if the selected cell is a mine or not
    :param arr: the array we want to check
    :param dim:  the dimension of the array
    :param row:
    :param col:
    :return: True if is a mine else false
    """
    if arr[row][col] == 'M':
        return True
    else:
        return False

def isSafe(arr, dim, row, col):
    """
    Check to see if the selected cell is safe or not
    :param arr: the array we want to check
    :param dim:  the dimension of the array
    :param row:
    :param col:
    :return: True if is safe else false
    """
    if arr[row][col] == 'M' or arr[row][col] == '?':
        return False
    else:
        return True

def isCovered(arr, dim, row, col):
    """
    Check to see if the selected cell is covered or not
    :param arr: the array we want to check
    :param dim:  the dimension of the array
    :param row:
    :param col:
    :return: True if is covered else false
    """
    if arr[row][col] == '?':
        return True
    else:
        return False

def isValid(arr, dim, row, col):
    """
    Check to see if the selected list element is in bounds

    :param arr: The array I want to check
    :param dim: The square dimensions of the array
    :param row:
    :param col:
    :return: True if in bounds, or False if out of bounds
    """
    if (row < 0) or (col < 0) or (row >= dim) or (col >= dim):
        return False
    else:
        return True


import secrets
import socket
import hashlib

choices_str = ["Rock", "Paper", "Scissors"]

print("   _____                  _        _____  _____   _____")
print("  / ____|                | |      |  __ \\|  __ \\ / ____|")
print(" | |     _ __ _   _ _ __ | |_ ___ | |__) | |__) | (___")
print(" | |    | '__| | | | '_ \\| __/ _ \\|  _  /|  ___/ \\___ \\")
print(" | |____| |  | |_| | |_) | || (_) | | \\ \\| |     ____) |")
print("  \\_____|_|   \\__, | .__/ \\__\\___/|_|  \\_\\_|    |_____/ ")
print("               __/ | |")
print("              |___/|_|                                  ")

print("\nA Cryptographically secure Rock-Paper-Scissors game, because why not\n\n")

print("Please pick a connection option : ")
print("[1] Host a game")
print("[2] Connect to a game")
print("")

while True:
    choice = input("Choice : ")

    if choice == "1":
        server_mode = True
        break

    elif choice == "2":
        server_mode = False
        break

    print("Please enter a valid choice !")

s = None
c = None

if server_mode:
    while True:
        port = input("Listen on port [4242] :")

        if port == "":
            port = 4242
        elif port.isnumeric():
            port = int(port)
        else:
            print("Please enter a valid port")
            continue

        try:
            s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            s.bind(("", port))
            break
        except Exception as e:
            print("Error while binding socket, maybe the port is already in use ?")
            print(e)

    print(f"Waiting for connection on port {port} ...")

    s.listen(1)
    c, addr = s.accept()

    print(f"Received connection from {addr} !")

else:
    while True:
        host = input("Host : ")
        port = input("Port [4242] : ")

        if port == "":
            port = 4242
        elif port.isnumeric():
            port = int(port)
        else:
            print("Please enter a valid port !")
            continue

        print(f"Connecting to {host}:{port} ... ")

        try:
            s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            s.connect((host, port))
            break
        except Exception as e:
            print("Error while connecting to host !")
            print(e)
            continue

    print("Connected successfully !")

    c = s

def make_choice():
    print("Please pick an option : ")
    print("[1] Rock")
    print("[2] Paper")
    print("[3] Scissors")

    while True:
        choice = input("choice : ")
        if choice in ["1", "2", "3"]:
            return int(choice)
        print("Please enter a valid choice !")

try:
    while True:

        choice = make_choice()

        r1 = secrets.token_bytes(256)
        r2 = secrets.token_bytes(256)

        choice_bytes = choice.to_bytes(1, "little")

        msg = r1 + r2 + choice_bytes

        # Send the commitment
        c.sendall(hashlib.sha512(msg).digest())
        c.sendall(r1)

        print("Waiting for other player ... ")

        commitment = c.recv(64)
        other_r1 = c.recv(256)

        print("Validating choices ... ")

        c.sendall(msg)
        other_msg = c.recv(513)

        if other_msg[0:256] != other_r1 or hashlib.sha512(other_msg).digest() != commitment:
            print("Invalid commitment, the other player might have tried to cheat !")
            print("Ending game ... ")
            break

        other_choice = other_msg[-1]

        print("")

        print(f"Your choice : {choices_str[choice - 1]}")
        print(f"Opponent's choice : {choices_str[other_choice - 1]}")
        print("")

        win = 0
        if choice == 1:
            if other_choice == 2:
                win = -1
            elif other_choice == 3:
                win = 1

        elif choice == 2:
            if other_choice == 3:
                win = -1
            if other_choice == 1:
                win = 1

        else:
            if other_choice == 1:
                win = -1
            elif other_choice == 2:
                win = 1

        if win == 1:
            print("You won !")
        elif win == -1:
            print("You lost !")
        else:
            print("Draw !")

        next_game = input("\nContinue ? [Y/n] : ")
        if next_game.lower() == "n":
            break

    print("Exiting ... ")
    c.close()
    if server_mode:
        s.close()
    exit(0)

except ConnectionError as e:
    print("A connection error occured : ")
    print(e)


"""
This script helps visualize the RoIs extracted from the estimated data.
"""
import json
import time
import cv2
import os
import argparse
import datetime
import copy
from src import defines as ds
from src import utilities as util

def show_window(win_name, img):
    cv2.startWindowThread()
    cv2.namedWindow(win_name)
    cv2.imshow(win_name, img)

def get_bool(prompt):
    while True:
        try:
            return {'y': True, 'n': False}[input(prompt).lower()]
        except KeyError:
            print('Invalid input please enter yes or no.')

if __name__ == '__main__':
    parser = argparse.ArgumentParser()

    parser.add_argument('-d', '--dataset', type=str, default=ds.DEFAULT_DATASET, help='Name of the dataset.')
    parser.add_argument('-s', '--subset', type=str, default=ds.TRAIN_DIRNAME, help='Name of the subset.')
    parser.add_argument('-v', '--video', type=str, default=None, help='Name of the video.')
    parser.add_argument('-t', '--type', type=str, default=ds.DEFAULT_DATATYPE_CLS, help='Name of the datatype class.')
    parser.add_argument('--frame_diff_gap', type=int, default=ds.FRAME_DIFF_GAP, help='The temporal frame gap.')
    parser.add_argument('--min_train_det_score', type=float, default=ds.DEFAULT_MIN_TRAIN_DET_SCORE)
    parser.add_argument('--min_test_det_score', type=float, default=ds.DEFAULT_MIN_TEST_DET_SCORE)
    parser.add_argument('--det_model_name', type=str, default=ds.DEFAULT_DET_MODEL_NAME, help='Det model name.')
    parser.add_argument('--n_frames_per_video', type=int, default=ds.DEFAULT_N_FRAMES_PER_VIDEO, help='Frames/video.')
    util.add_bool_parser(parser, 'normalize_images', ds.NORMALIZE_IMAGES)
    parser.add_argument('--n_samples_per_viz', type=int, default=ds.DEFAULT_N_SAMPLES_PER_VIZ, help='Frames/viz.')
    parser.add_argument('--estimations_path', type=str, default=ds.ESTIMATIONS_PATH, help='Estimations path.')

    args = parser.parse_args()

    # Get datatype class
    data_cls = util.get_class_from_name(util, args.type)

    # Prepare arguments for data init
    data_args = copy.deepcopy(args.__dict__)
    data_args.pop('subset', None)
    data_args.pop('video', None)
    data_args.pop('type', None)
    data_args.pop('holistic', None)
    data_args.pop('n_samples_per_viz', None)

    # Initialize data class
    extract_data = data_cls(**data_args)

    # Results dir
    dt = datetime.datetime.now(tz=util.EST5EDT())
    curr_script_name = os.path.splitext(os.path.basename(__file__))[0]
    results_dir = os.path.join(ds.root_dir, ds.RESULTS_DIRNAME, curr_script_name, dt.strftime('%Y-%m-%d_%Hh%Mm%Ss'))
    if not os.path.exists(results_dir):
        os.makedirs(results_dir)

    while True:
        if args.holistic:
            # Extract data
            data = extract_data.get_subset(args.subset, args.video, rand_select=True)
        else:
            data = extract_data.get_roi_subset(args.subset, args.video, rand_select=True)

        print('Data size: {}'.format(data['data_size']))

        visualize_data = get_bool('Visualize data? ')
        while visualize_data:
            # Show some randomly selected samples
            viz_image = util.visualize_data(data, n_samples_per_viz=args.n_samples_per_viz)

            # Show the stacked image
            show_window('ST RoI data', viz_image)

            key = cv2.waitKey(0)
            if key == ord('s'):  # Save th image
                cv2.imwrite(os.path.join(results_dir, '{}_{}.png'.format(ds.ROI_DATAVIZ_NAME, time.time())), viz_image)
                print('Image saved.')
            elif key == ord('v'):  # Randomly visualize other samples
                continue
            else:
                break

        cv2.destroyAllWindows()

        if not get_bool('Do you want to redo? '):
            break

    # Save commandline args
    with open(os.path.join(results_dir, ds.COMMANDLINE_ARGS_FILENAME), 'w') as f:
        json.dump(args.__dict__, f, indent=2)