# coding: utf-8
from __future__ import print_function
from __future__ import division

import torch
import torch.nn as nn
import torch.nn.functional as F

from libcity.model.abstract_model import AbstractModel
from math import sin, cos, sqrt, atan2, radians
import numpy as np

def identity_loss(y_true, y_pred):
    return torch.mean(y_pred - 0 * y_true)

class CARA1(nn.Module):

    def hard_sigmoid(self, x):
        x = x / 6 + 0.5
        x = F.threshold(-x, -1, -1)
        x = F.threshold(-x, 0, 0)
        return x

    def __init__(self, output_dim, input_dim,
                 init='glorot_uniform', inner_init='orthogonal', device=None,
                 **kwargs):
        super(CARA1, self).__init__()
        self.output_dim = output_dim
        self.init = init
        self.inner_init = inner_init
        self.activation = self.hard_sigmoid
        self.inner_activation = nn.Tanh()
        self.device = device
        self.build(input_dim)

    def add_weight(self, shape, initializer):
        ts = torch.zeros(shape)
        if initializer == 'glorot_uniform':
            ts = nn.init.xavier_normal_(ts)
        elif initializer == 'orthogonal':
            ts = nn.init.orthogonal_(ts)

        return nn.Parameter(ts)

    def build(self, input_shape):
        # self.input_spec = [InputSpec(shape=input_shape)]
        self.input_dim = input_shape

        self.W_z = self.add_weight((self.input_dim, self.output_dim),
                                   initializer=self.init)
        self.U_z = self.add_weight((self.output_dim, self.output_dim),
                                   initializer=self.init)
        self.b_z = self.add_weight((self.output_dim,),
                                   initializer='zero')
        self.W_r = self.add_weight((self.input_dim, self.output_dim),
                                   initializer=self.init)
        self.U_r = self.add_weight((self.output_dim, self.output_dim),
                                   initializer=self.init)
        self.b_r = self.add_weight((self.output_dim,),
                                   initializer='zero')
        self.W_h = self.add_weight((self.input_dim, self.output_dim),
                                   initializer=self.init)
        self.U_h = self.add_weight((self.output_dim, self.output_dim),
                                   initializer=self.init)
        self.b_h = self.add_weight((self.output_dim,),
                                   initializer='zero')

        self.A_h = self.add_weight((self.output_dim, self.output_dim),
                                   initializer=self.init)
        self.A_u = self.add_weight((self.output_dim, self.output_dim),
                                   initializer=self.init)

        self.b_a_h = self.add_weight((self.output_dim,),
                                     initializer='zero')
        self.b_a_u = self.add_weight((self.output_dim,),
                                     initializer='zero')

        self.W_t = self.add_weight((self.input_dim, self.output_dim),
                                   initializer=self.init)
        self.U_t = self.add_weight((1, self.output_dim),
                                   initializer=self.init)
        self.b_t = self.add_weight((self.output_dim,),
                                   initializer='zero')

        self.W_g = self.add_weight((self.input_dim, self.output_dim),
                                   initializer=self.init)
        self.U_g = self.add_weight((1, self.output_dim),
                                   initializer=self.init)
        self.b_g = self.add_weight((self.output_dim,),
                                   initializer='zero')

    def preprocess_input(self, x):
        return x

    def forward(self, x):
        """
        X : batch * timeLen * dims(有拓展)
        """
        tlen = x.shape[1]
        output = torch.zeros((x.shape[0], self.output_dim)).to(self.device)
        for i in range(tlen):
            output = self.step(x[:, i, :], output)
        return output

    def step(self, x, states):
        """
        用于多批次同一时间
        states为上一次多批次统一时间数据
        """
        h_tm1 = states

        # phi_t
        u = x[:, self.output_dim: 2 * self.output_dim]
        # delta_t
        t = x[:, 2 * self.output_dim: (2 * self.output_dim) + 1]
        # delta_g
        g = x[:, (2 * self.output_dim) + 1:]
        # phi_v
        x = x[:, :self.output_dim]

        t = self.inner_activation(torch.matmul(t, self.U_t))
        g = self.inner_activation(torch.matmul(g, self.U_g))
        #       Time-based gate
        t1 = self.inner_activation(torch.matmul(x, self.W_t) + t + self.b_t)
        #       Geo-based gate
        g1 = self.inner_activation(torch.matmul(x, self.W_g) + g + self.b_g)

        #       Contextual Attention Gate
        a = self.inner_activation(
            torch.matmul(h_tm1, self.A_h) + torch.matmul(u, self.A_u) + self.b_a_h + self.b_a_u)

        x_z = torch.matmul(x, self.W_z) + self.b_z
        x_r = torch.matmul(x, self.W_r) + self.b_r
        x_h = torch.matmul(x, self.W_h) + self.b_h

        u_z_ = torch.matmul((1 - a) * u, self.W_z) + self.b_z
        u_r_ = torch.matmul((1 - a) * u, self.W_r) + self.b_r
        u_h_ = torch.matmul((1 - a) * u, self.W_h) + self.b_h

        u_z = torch.matmul(a * u, self.W_z) + self.b_z
        u_r = torch.matmul(a * u, self.W_r) + self.b_r
        u_h = torch.matmul(a * u, self.W_h) + self.b_h

        #       update gate
        z = self.inner_activation(x_z + torch.matmul(h_tm1, self.U_z) + u_z)
        #       reset gate
        r = self.inner_activation(x_r + torch.matmul(h_tm1, self.U_r) + u_r)
        #       hidden state
        hh = self.activation(x_h + torch.matmul(r * t1 * g1 * h_tm1, self.U_h) + u_h)

        h = z * h_tm1 + (1 - z) * hh
        h = (1 + u_z_ + u_r_ + u_h_) * h
        return h
        # return h

def bpr_triplet_loss(x):
    positive_item_latent, negative_item_latent = x

    reg = 0

    loss = 1 - torch.log(torch.sigmoid(
        torch.sum(positive_item_latent, dim=-1, keepdim=True) -
        torch.sum(negative_item_latent, dim=-1, keepdim=True))) - reg

    return loss

class Recommender(nn.Module):
    def __init__(self, num_users, num_items, num_times, latent_dim, maxvenue=5, device=None):
        super(Recommender, self).__init__()
        self.maxVenue = maxvenue
        self.latent_dim = latent_dim
        self.device = device
        # num * maxVenue * dim
        self.U_Embedding = nn.Embedding(num_users, latent_dim)
        self.V_Embedding = nn.Embedding(num_items, latent_dim)
        self.T_Embedding = nn.Embedding(num_times, latent_dim)
        torch.nn.init.uniform_(self.U_Embedding.weight)
        torch.nn.init.uniform_(self.V_Embedding.weight)
        torch.nn.init.uniform_(self.T_Embedding.weight)
        self.rnn = nn.Sequential(
            CARA1(latent_dim, latent_dim, device=self.device, input_shape=(self.maxVenue, (self.latent_dim * 2) + 2,),
                  unroll=True,
                  ))
        #       latent_dim * 2 + 2 = v_embedding + t_embedding + time_gap + distance

    def forward(self, x):
        # INPUT = [self.user_input, self.time_input, self.gap_time_input, self.pos_distance_input,
        #          self.neg_distance_input, self.checkins_input,
        #          self.neg_checkins_input]
        # pass
        #       User latent factor
        user_input = x[0]
        time_input = x[1]
        gap_time_input = x[2]
        pos_distance_input = x[3]
        neg_distance_input = x[4]
        checkins_input = x[5]
        neg_checkins_input = x[6]

        self.u_latent = self.U_Embedding(user_input)
        self.t_latent = self.T_Embedding(time_input)

        h, w = gap_time_input.shape
        gap_time_input = gap_time_input.view(h, w, 1)
        rnn_input = torch.cat([self.V_Embedding(checkins_input), self.T_Embedding(time_input), gap_time_input], -1)
        neg_rnn_input = torch.cat([self.V_Embedding(neg_checkins_input), self.T_Embedding(time_input), gap_time_input],
                                  -1)
        h, w = pos_distance_input.shape
        pos_distance_input = pos_distance_input.view(h, w, 1)
        h, w = neg_distance_input.shape
        neg_distance_input = neg_distance_input.view(h, w, 1)
        rnn_input = torch.cat([rnn_input, pos_distance_input], -1)
        neg_rnn_input = torch.cat([neg_rnn_input, neg_distance_input], -1)
        self.checkins_emb = self.rnn(rnn_input)
        self.neg_checkins_emb = self.rnn(neg_rnn_input)

        pred = (self.checkins_emb * self.u_latent).sum(dim=1)
        neg_pred = (self.neg_checkins_emb * self.u_latent).sum(dim=1)
        return bpr_triplet_loss([pred, neg_pred])

    def rank(self, uid, hist_venues, hist_times, hist_time_gap, hist_distances):
        #         hist_venues = hist_venues + [candidate_venue]
        #         hist_times = hist_times + [time]
        #         hist_time_gap = hist_time_gap + [time_gap]
        #         hist_distances = hist_distances + [distance]

        # u_latent = self.U_Embedding(torch.tensor(uid))
        # v_latent = self.V_Embedding(torch.tensor(hist_venues))
        # t_latent = self.T_Embedding(torch.tensor(hist_times))
        u_latent = self.U_Embedding.weight[uid]
        v_latent = self.V_Embedding.weight[hist_venues.reshape(-1)].view(hist_venues.shape[0], hist_venues.shape[1], -1)
        t_latent = self.T_Embedding.weight[hist_times.reshape(-1)].view(hist_times.shape[0], hist_times.shape[1], -1)

        h, w = hist_time_gap.shape
        hist_time_gap = hist_time_gap.reshape(h, w, 1)
        h, w = hist_distances.shape
        hist_distances = hist_distances.reshape(h, w, 1)
        rnn_input = torch.cat([t_latent, torch.FloatTensor(hist_time_gap).to(self.device)], dim=-1)
        rnn_input = torch.cat([rnn_input, torch.FloatTensor(hist_distances).to(self.device)], dim=-1)

        rnn_input = torch.cat([v_latent, rnn_input], dim=-1)

        dynamic_latent = self.rnn(rnn_input)
        scores = torch.mul(dynamic_latent, u_latent).sum(1)
        # scores = np.dot(dynamic_latent, u_latent)
        return scores

class CARA(AbstractModel):
    """rnn model with long-term history attention"""

    def __init__(self, config, data_feature):
        super(CARA, self).__init__(config, data_feature)
        self.loc_size = data_feature['loc_size']
        self.tim_size = data_feature['tim_size']
        self.uid_size = data_feature['uid_size']
        self.id2locid = data_feature['id2locid']
        self.id2loc = []
        self.device = config['device']
        for i in range(self.loc_size - 1):
            self.id2loc.append(self.id2locid[str(i)])
        self.id2loc.append(self.loc_size)
        self.id2loc = np.array(self.id2loc)
        self.coor = data_feature['poi_coor']
        self.rec = Recommender(self.uid_size, self.loc_size, self.tim_size, 10, device=self.device)

    def get_time_interval(self, x):
        y = x[:, :-1]
        y = np.concatenate([x[:, 0, None], y], axis=1)
        return x - y

    def get_time_interval2(self, x):
        y = x[:-1]
        y = np.concatenate([x[0, None], y], axis=0)
        return x - y

    def get_pos_distance(self, x):
        y = np.concatenate([x[:, 0, None, :], x[:, :-1, :]], axis=1)
        r = 6373.0
        rx = np.radians(x)
        ry = np.radians(y)

        d = x - y
        a = np.sin(d[:, :, 0] / 2) ** 2 + np.cos(rx[:, :, 0]) * np.cos(ry[:, :, 0]) * np.sin(d[:, :, 1] / 2) ** 2
        c = 2 * np.arctan2(np.sqrt(a), np.sqrt(1 - a))
        return r * c

    def get_pos_distance2(self, x):
        x = np.array(x.tolist())
        y = np.concatenate([x[0, None, :], x[:-1, :]], axis=0)
        r = 6373.0
        rx = np.radians(x)
        ry = np.radians(y)

        d = x - y
        a = np.sin(d[:, 0] / 2) ** 2 + np.cos(rx[:, 0]) * np.cos(ry[:, 0]) * np.sin(d[:, 1] / 2) ** 2
        c = 2 * np.arctan2(np.sqrt(a), np.sqrt(1-a))
        return r * c

    def get_distance(self, lat1, lng1, lat2, lng2):
        r = 6373.0

        lat1 = radians(lat1)
        lon1 = radians(lng1)
        lat2 = radians(lat2)
        lon2 = radians(lng2)

        dlon = lon2 - lon1
        dlat = lat2 - lat1

        a = sin(dlat / 2) ** 2 + cos(lat1) * cos(lat2) * sin(dlon / 2) ** 2
        c = 2 * atan2(sqrt(a), sqrt(1 - a))

        distance = int(r * c)
        return distance

    def get_neg_checkins(self, vis, x, y):
        len1, len2 = x.shape
        x_res = []
        x_res_distance = y[:].copy()
        for i in range(len1):
            visits = x[i]
            j = np.random.randint(self.loc_size - 1)
            while j in vis[i]:
                j = np.random.randint(self.loc_size - 1)
            tmp = visits[:].copy()
            tmp[-1] = j
            x_res.append(tmp)
            j1 = self.coor[str(self.id2loc[visits[-1]])]
            j = self.coor[str(self.id2loc[j])]
            x_res_distance[i, -1] = self.get_distance(j1[0], j1[1], j[0], j[1])
        return x_res, x_res_distance

    def forward(self, batch):
        hloc = np.array(batch['current_loc'].cpu())[:, :5]
        target = np.array(batch['target'].cpu())
        h = target.shape
        target = target.reshape((*h, 1))
        hloc = np.concatenate([hloc, target], axis=1)
        hloc1 = self.id2loc[hloc]
        tloc = np.array(batch['current_tim'].cpu())[:, :5]
        target_tim = np.array(batch['target_tim'].cpu())
        h = target_tim.shape
        target_tim = target_tim.reshape((*h, 1))
        tloc = np.concatenate([tloc, target_tim], axis=1)
        x_users = batch['uid']
        t_interval = self.get_time_interval(tloc)

        titude = []
        for i in hloc1.reshape(-1):
            titude.append(self.coor[str(i)])
        titude = np.array(titude).reshape((hloc.shape[0], hloc.shape[1], 2))
        pos_distance = self.get_pos_distance(titude)
        x_neg_checkins, x_neg_distance = self.get_neg_checkins(np.array(batch['current_loc'].cpu()), hloc, pos_distance)
        x_neg_checkins = np.array(x_neg_checkins)
        x = [x_users, torch.tensor(tloc).to(self.device),
             torch.FloatTensor(t_interval).to(self.device), torch.FloatTensor(pos_distance).to(self.device),
             torch.FloatTensor(x_neg_distance).to(self.device), torch.tensor(hloc).to(self.device),
             torch.tensor(x_neg_checkins).to(self.device)]
        return self.rec(x)

    def predict(self, batch):
        hloc = np.array(batch['current_loc'].cpu())[:, :5]
        tloc = np.array(batch['current_tim'].cpu())[:, :5]
        x_users = batch['uid']
        my_true = batch['target']
        my_true_tim = batch['target_tim']
        output = []
        for id, mloc in enumerate(hloc):
            hlocs = []
            tlocs = []
            users = []
            t_intervals = []
            distances = []
            target = my_true[id].item()
            target_tim = my_true_tim[id].item()
            mu = x_users[id]
            mh, mt = hloc[id], tloc[id].copy()
            mt = np.append(mt, target_tim)
            mi = self.get_time_interval2(mt)
            for i in range(101):
                mh = hloc[id].copy()
                if i == 0:
                    mh = np.append(mh, target)
                    tmh = self.id2loc[mh]
                    mtt = []
                    for i in tmh.reshape(-1):
                        mtt.append(self.coor[str(i)])
                    mtt = np.array(mtt).reshape((tmh.shape[0], 2))
                    md = self.get_pos_distance2(mtt)
                else:
                    j = target
                    while j == target:
                        j = np.random.randint(0, self.loc_size - 1)
                    mh = np.append(mh, j)
                    tmh = self.id2loc[mh]
                    mtt = []
                    for i in tmh.reshape(-1):
                        mtt.append(self.coor[str(i)])
                    mtt = np.array(mtt).reshape((tmh.shape[0], 2))
                    md = self.get_pos_distance2(mtt)

                hlocs.append(mh)
                tlocs.append(mt)
                users.append(mu.item())
                t_intervals.append(mi)
                distances.append(md)
            output.append(self.rec.rank(np.array(users), np.array(hlocs), np.array(tlocs), np.array(t_intervals),
                                        np.array(distances)).cpu().detach().numpy())
        output = np.array(output)
        return torch.tensor(output).to(self.device)

    def calculate_loss(self, batch):
        return torch.mean(self.forward(batch))


# Namespaces Local vs. Global Scope
from typing import List

# Scope
# enemies: int = 1
#
# def increase_enemies() -> None:
#   enemies = 2
#   print(f"enemies inside function: {enemies}") # 2
#
# increase_enemies()
# print(f"enemies outside function: {enemies}") # 1

# Local Scope
# def drink_potion() -> None:
#     potion_strength: int = 2
#     print(potion_strength) # 2
#
# drink_potion()
# print(potion_strength) Error var is not defined

# Global Scope
# player_health: int = 10
#
# def drink_potion() -> None:
#     potion_strength: int = 2
#     print(player_health) # 10
#
# drink_potion()
# print(player_health) # 10

# There is no Block Scope
# game_level: int = 3
#
#
# def create_enemy() -> None:
#     enemies: List[str] = ["Skeleton", "Zombie", "Alien"]
#     if game_level < 5:
#         new_enemy: str = enemies[0]
#
#     print(new_enemy)

# print(new_enemy) # error var is not defined

# Modify a Global Variable
# enemies: int = 1
#
#
# def increase_enemies() -> int:
#     print(f"enemies inside function: {enemies}")  # 1
#     return enemies + 1
#
#
# enemies = increase_enemies()
# print(f"enemies outside function: {enemies}")  # 2

# Constants & Global Scope
# PI = 3.14159
# URL = "https://www.google.com"
# TWITTER_HANDLE = "@JCochenski"

# Quiz
# 1
# def a_function(a_parameter: int) -> int:
#     a_variable: int = 15
#     return a_parameter
#
#
# a_function(10)
# print(a_variable) # error Name Error

# 2
# i: int = 50
#
#
# def foo() -> int:
#     i = 100
#     return i
#
#
# foo()
# print(i) # 50

# 3
# def bar() -> None:
#     my_variable: int = 9
#
#
# if 16 > 9:
#     my_variable = 16
#
# print(my_variable) # 16
#
# bar()

# Project - Number Guessing Game
from random import randint
from art import logo

EASY_LEVEL_TURNS: int = 10
HARD_LEVEL_TURNS: int = 5

def check_answer(guess: int, answer: int, turns: int) -> int:
    if guess > answer:
        print("Too high.")
        return turns - 1
    elif guess < answer:
        print("Too low.")
        return turns - 1
    else:
        print(f"You got it! The answer was {answer}.")
        return answer

def set_difficulty() -> int:
    level: str = input("Choose a difficulty. Type 'easy' or 'hard': ")
    if level == "easy":
        return EASY_LEVEL_TURNS
    else:
        return HARD_LEVEL_TURNS

def game() -> None:
    print(logo)
    print("Welcome to the Number Guessing Game!")
    print("I'm thinking of a number between 1 and 100.")
    answer: int = randint(1, 100)
    # print(f"Pssst, the correct answer is {answer}")

    turns: int = set_difficulty()
    guess: int = 0
    while guess != answer:
        print(f"You have {turns} attempts remaining to guess the number.")

        guess = int(input("Make a guess: "))

        turns = check_answer(guess, answer, turns)
        if turns == 0:
            print("You've run out of guesses, you lose.")
            return
        elif guess != answer:
            print("Guess again.")

game()


# -*- coding: UTF-8 -*-
# Stock hammer shape judge.
from basic import log
logger = log.Log()

def is_hammer_shape(quotes):
    # 趋势 跌
    trendb = trend_before(quotes)
    if trendb > 0:
        return False
    # 成交量趋势 跌
    val_trend = trend_before(quotes, item='volume')
    if val_trend > 0:
        return False

    q = quotes[-1]
    color = 1
    line = q['high'] - q['low']     # 线高
    entity = q['close'] - q['open'] # 实体高度
    top_h = q['high'] - q['close']    # 头高度
    footer = line - (q['high'] - q['open'])  # 脚高度
    if q['open'] > q['close']:
        color = -1
        entity = q['open'] - q['close']
        top_h = q['high'] - q['open']
        footer = line - (q['high'] - q['close'])

    # 十字或者一字板
    if q['open'] == q['close']:
        return False

    # 头部长度不超过10%
    if top_h > line * 0.1:
        return False

    # 实体长度不超过40%
    if entity > line * 0.3:
        return False

    # 分数
    score = round((footer / q['low']) * 1000, 2)
    if score < 15:
        return False

    return {
        'trend_before': trendb,
        'color': color,
        'score': score,
    }

def venus_shape_judge(quotes_list):
    q1 = quotes_list[-1]
    q2 = quotes_list[-2]
    q3 = quotes_list[-3]
    if q1['open'] > q1['close']:
        q1_h = q1['open']
        q1_l = q1['close']
        q1_t = -1
    else:
        q1_h = q1['close']
        q1_l = q1['open']
        q1_t = 1

    if q2['open'] > q2['close']:
        q2_h = q2['open']
        q2_l = q2['close']
        q2_t = -1
    else:
        q2_h = q2['close']
        q2_l = q2['open']
        q2_t = 1

    if q3['open'] > q3['close']:
        q3_h = q3['open']
        q3_l = q3['close']
        q3_t = -1
    else:
        q3_h = q3['close']
        q3_l = q3['open']
        q3_t = 1

    vol2_average = ma5(quotes_list, -6, -2, "volume")
    vol3_average = ma5(quotes_list, -7, -3, "volume")

    close2_average = ma5(quotes_list, -6, -2, "close")
    close3_average = ma5(quotes_list, -7, -3, "close")
    # 前天跌，昨天跌到底，今天高开高走
    # 成交量较前五天平均值收缩
    if q1_l >= q2_h and q3_l >= q2_h and q2_t < 0 and q1_t > 0 and vol3_average > vol2_average and close3_average >= close2_average:
        c1 = (q1_l - q2_h) / q2_h
        c2 = (q3_l - q2_h) / q2_h
        c3 = (q1_h - q1_l) / q2['close']
        c4 = (vol3_average - vol2_average) / vol2_average
        return {
            'trend_before': trend_before(quotes_list),
            'color': 1,
            'score': round((c1 + c2 + c3 + c4) * 1000, 2)
        }
    # 前天跌，昨天低开高走，今天涨
    # 成交量较前五天平均值增加
    elif q1_l >= q2_h and q3_l >= q2_h and q2_t > 0 and q1_t > 0 and vol2_average < vol3_average and close3_average >= close2_average:
        c1 = (q1_l - q2_h) / q2_h
        c2 = (q3_l - q2_h) / q2_h
        c3 = (q1_h - q1_l) / q2['close']
        c4 = (vol2_average - vol3_average) / vol3_average
        return {
            'trend_before': trend_before(quotes_list),
            'color': 1,
            'score': round((c1 + c2 + c3 + c4) * 1000, 2)
        }
    else:
        return False

def is_cross_shape(quotes):
    '''底部缩量的十字星线'''
    # 趋势 跌
    trendb = trend_before(quotes)
    if trendb > 0:
        return False
    # 成交量趋势 跌
    val_trend = trend_before(quotes, item='volume')
    if val_trend >= 0:
        return False

    q = quotes[-1]
    color = 1
    line = q['high'] - q['low']  # 线高
    high = q['close']
    if q['open'] > q['close']:
        color = -1
        high = q['open']
    score = round(line / q['low'] / 2 * 1000, 2)
    # 十字, 非一字板，非T字, 分数低于15舍弃，十字数量太多
    if q['open'] == q['close'] and line != 0 and q['high'] != high and score > 15:
        return {
            'trend_before': trendb,
            'color': color,
            'score': score
        }
    else:
        return False

def ma5(quotes, sindex=-5, eindex=-1, item="close"):
    count = 0
    for i in range(sindex, eindex+1):
        count += quotes[i][item]
    return count / 5

def ma5_avg(quotes, sindex=-5, eindex=-1, item="close"):
    '''
    Pervious 5 day md5 average
    :param quotes:
    :param sindex:
    :param eindex:
    :param item:
    :return:
    '''
    count = 0
    for i in range(sindex, eindex+1):
        count += ma5(quotes, i-4, i, item)
    return count / 5

def trend_before(quotes, sindex=-1, item="close"):
    '''
    计算ma5的均线趋势，计算前5天ma5均值的平均值，与后一天收盘价比较，5%以内视为横盘
    :param quotes: 行情list
    :param startIndex:
    :param item:
    :return: 0：横盘， 1：raise， -1：drop
    '''
    avg_previous_5 = ma5_avg(quotes, sindex=sindex-5, eindex=sindex-1, item=item)
    yesterday = quotes[-1]["close"]
    if avg_previous_5 > yesterday:
        ratio = (avg_previous_5 - yesterday) / avg_previous_5
        if ratio < 0.05:
            return 0
        else:
            return -1
    else:
        ratio = (yesterday - avg_previous_5) / yesterday
        if ratio < 0.05:
            return 0
        else:
            return 1

def top(d1, d2):
    if d1 > d2:
        return d1
    else:
        return d2

def bottom(d1, d2):
    if d1 > d2:
        return d2
    else:
        return d1


import contextlib
import functools
import logging
import os

import click
import torch
from tqdm import tqdm
from transformers import WEIGHTS_NAME, AdamW, get_constant_schedule_with_warmup, get_linear_schedule_with_warmup

logger = logging.getLogger(__name__)

def trainer_args(func):
    @click.option("--learning-rate", default=1e-5)
    @click.option("--lr-schedule", default="warmup_linear", type=click.Choice(["warmup_linear", "warmup_constant"]))
    @click.option("--weight-decay", default=0.01)
    @click.option("--max-grad-norm", default=0.0)
    @click.option("--adam-b1", default=0.9)
    @click.option("--adam-b2", default=0.98)
    @click.option("--adam-eps", default=1e-6)
    @click.option("--adam-correct-bias", is_flag=True)
    @click.option("--warmup-proportion", default=0.06)
    @click.option("--gradient-accumulation-steps", default=1)
    @click.option("--fp16", is_flag=True)
    @click.option("--fp16-opt-level", default="O2")
    @click.option("--fp16-min-loss-scale", default=1)
    @click.option("--fp16-max-loss-scale", default=4)
    @click.option("--save-steps", default=0)
    @functools.wraps(func)
    def wrapper(*args, **kwargs):
        return func(*args, **kwargs)

    return wrapper

class Trainer(object):
    def __init__(self, args, model, dataloader, num_train_steps, step_callback=None):
        self.args = args
        self.model = model
        self.dataloader = dataloader
        self.num_train_steps = num_train_steps
        self.step_callback = step_callback

        self.optimizer = self._create_optimizer(model)
        self.scheduler = self._create_scheduler(self.optimizer)

    def train(self):
        model = self.model
        optimizer = self.optimizer

        if self.args.fp16:
            from apex import amp

            model, optimizer = amp.initialize(
                model,
                optimizer,
                opt_level=self.args.fp16_opt_level,
                min_loss_scale=self.args.fp16_min_loss_scale,
                max_loss_scale=self.args.fp16_max_loss_scale,
            )

        if self.args.local_rank != -1:
            model = torch.nn.parallel.DistributedDataParallel(
                model,
                device_ids=[self.args.local_rank],
                output_device=self.args.local_rank,
                find_unused_parameters=True,
            )

        epoch = 0
        global_step = 0
        tr_loss = 0.0

        num_workers = torch.cuda.device_count()

        def maybe_no_sync(step):
            if (
                hasattr(model, "no_sync")
                and num_workers > 1
                and (step + 1) % self.args.gradient_accumulation_steps != 0
            ):
                return model.no_sync()
            else:
                return contextlib.ExitStack()

        model.train()

        with tqdm(total=self.num_train_steps, disable=self.args.local_rank not in (-1, 0)) as pbar:
            while True:
                for step, batch in enumerate(self.dataloader):
                    inputs = {k: v.to(self.args.device) for k, v in self._create_model_arguments(batch).items()}
                    outputs = model(**inputs)
                    loss = outputs[0]
                    if self.args.gradient_accumulation_steps > 1:
                        loss = loss / self.args.gradient_accumulation_steps

                    with maybe_no_sync(step):
                        if self.args.fp16:
                            with amp.scale_loss(loss, optimizer) as scaled_loss:
                                scaled_loss.backward()
                        else:
                            loss.backward()

                    tr_loss += loss.item()
                    if (step + 1) % self.args.gradient_accumulation_steps == 0:
                        if self.args.max_grad_norm != 0.0:
                            if self.args.fp16:
                                torch.nn.utils.clip_grad_norm_(amp.master_params(optimizer), self.args.max_grad_norm)
                            else:
                                torch.nn.utils.clip_grad_norm_(model.parameters(), self.args.max_grad_norm)

                        self.optimizer.step()
                        self.scheduler.step()
                        model.zero_grad()

                        pbar.set_description("epoch: %d loss: %.7f" % (epoch, loss.item()))
                        pbar.update()
                        global_step += 1

                        if self.step_callback is not None:
                            self.step_callback(model, global_step)

                        if (
                            self.args.local_rank in (-1, 0)
                            and self.args.output_dir
                            and self.args.save_steps > 0
                            and global_step % self.args.save_steps == 0
                        ):
                            output_dir = os.path.join(self.args.output_dir, "checkpoint-{}".format(global_step))

                            if hasattr(model, "module"):
                                torch.save(model.module.state_dict(), os.path.join(output_dir, WEIGHTS_NAME))
                            else:
                                torch.save(model.state_dict(), os.path.join(output_dir, WEIGHTS_NAME))

                        if global_step == self.num_train_steps:
                            break

                if global_step == self.num_train_steps:
                    break
                epoch += 1

        logger.info("global_step = %s, average loss = %s", global_step, tr_loss / global_step)

        return model, global_step, tr_loss / global_step

    def _create_optimizer(self, model):
        param_optimizer = list(model.named_parameters())
        no_decay = ["bias", "LayerNorm.weight"]
        optimizer_parameters = [
            {
                "params": [p for n, p in param_optimizer if p.requires_grad and not any(nd in n for nd in no_decay)],
                "weight_decay": self.args.weight_decay,
            },
            {
                "params": [p for n, p in param_optimizer if p.requires_grad and any(nd in n for nd in no_decay)],
                "weight_decay": 0.0,
            },
        ]
        return AdamW(
            optimizer_parameters,
            lr=self.args.learning_rate,
            eps=self.args.adam_eps,
            betas=(self.args.adam_b1, self.args.adam_b2),
            correct_bias=self.args.adam_correct_bias,
        )

    def _create_scheduler(self, optimizer):
        warmup_steps = int(self.num_train_steps * self.args.warmup_proportion)
        if self.args.lr_schedule == "warmup_linear":
            return get_linear_schedule_with_warmup(optimizer, warmup_steps, self.num_train_steps)
        if self.args.lr_schedule == "warmup_constant":
            return get_constant_schedule_with_warmup(optimizer, warmup_steps)

        raise RuntimeError("Unsupported scheduler: " + self.args.lr_schedule)

    def _create_model_arguments(self, batch):
        return batch


from flask import Flask, redirect, render_template, request, session
from flask_session import Session

app = Flask(__name__)
app.config["SESSION_PERMANENT"] = False
app.config["SESSION_TYPE"] = "filesystem"
Session(app)

@app.route("/")
def tasks():
    # if the cookies data not in session, then create
    if "tasknames" not in session:
        session["tasknames"] = []
    return render_template("tasks.html", tasknames=session["tasknames"])

# accept multiple request method (GET, POST)
@app.route("/add", methods=["GET", "POST"])
def add():
    if request.method == "GET":
        return render_template("add.html")
    else:
        # get from <form> so use form
        taskname = request.form.get("taskname")
        session["tasknames"].append(taskname)
        # redirect to which route instead of writing render_template which
        return redirect("/")


import sounddevice as sd
import numpy as np

# place holders and global variables
SOUND_AMPLITUDE = 0
AUDIO_CHEAT = 0

# sound variables
# SUS means next sound packet is worth analyzing
CALLBACKS_PER_SECOND = 38               # callbacks per sec(system dependent)
SUS_FINDING_FREQUENCY = 2               # calculates SUS *n* times every sec
SOUND_AMPLITUDE_THRESHOLD = 20          # amplitude considered for SUS calc

# packing *n* frames to calculate SUS
FRAMES_COUNT = int(CALLBACKS_PER_SECOND/SUS_FINDING_FREQUENCY)
AMPLITUDE_LIST = list([0]*FRAMES_COUNT)
SUS_COUNT = 0
count = 0

def print_sound(indata, outdata, frames, time, status):
    avg_amp = 0
    global SOUND_AMPLITUDE, SUS_COUNT, count, SOUND_AMPLITUDE_THRESHOLD, AUDIO_CHEAT
    vnorm = int(np.linalg.norm(indata)*10)
    AMPLITUDE_LIST.append(vnorm)
    count += 1
    AMPLITUDE_LIST.pop(0)
    if count == FRAMES_COUNT:
        avg_amp = sum(AMPLITUDE_LIST)/FRAMES_COUNT
        SOUND_AMPLITUDE = avg_amp
        if SUS_COUNT >= 2:
            #print("!!!!!!!!!!!! FBI OPEN UP !!!!!!!!!!!!")
            AUDIO_CHEAT = 1
            SUS_COUNT = 0
        if avg_amp > SOUND_AMPLITUDE_THRESHOLD:
            SUS_COUNT += 1
            #print("Sus...", SUS_COUNT)
        else:
            SUS_COUNT = 0
            AUDIO_CHEAT = 0
        count = 0

def sound():
    with sd.Stream(callback=print_sound):
        sd.sleep(-1)

def sound_analysis():
    global AMPLITUDE_LIST, FRAMES_COUNT, SOUND_AMPLITUDE
    while True:
        AMPLITUDE_LIST.append(SOUND_AMPLITUDE)
        AMPLITUDE_LIST.pop(0)

        avg_amp = sum(AMPLITUDE_LIST)/FRAMES_COUNT

        if avg_amp > 10:
            print("Sus...")

if __name__ == "__main__":
    sound()


"""
List of Helper functions used.

1. silu(conv_nd) - A modified activation function which takes a convolution layer object and applies it to a sigmoid function.
    This result is then returned

2. item_reriever(dataset, is_cifar10) - Takes a dataset object, and a boolean which specifies if the dataset being passed is CIFAR-10.
    It then returns a list containing indices of a dataset which have the wanted labels.

3. label_to_index(tensor_labels) - Takes a tensor of tensors containing single integers.
    the integers are mapped to 0-6 values, and then returned as tensors of the same format.
"""
import torch

def silu(conv_nd):
    return conv_nd * torch.sigmoid(conv_nd)

def item_retriever(dataset, is_cifar10):  # function which  takes a dataset and returns the indices of all the wanted classes.
    indices = []
    length = dataset.__len__()
    # CIFAR 10 pathway.
    if is_cifar10:
        for i in range(length):
            target = dataset.__getitem__(i)
            if (target[1] == 1):
                indices.insert(0, i)  # for separating automobiles into the first half
            elif (target[1] == 9):
                indices.append(i)  # for separating trucks into the second half
        resize = int(len(indices) / 20) # 20 chosen to let only 600 images (500 training, 100 testing) from each class through.
        indices = indices[:resize] + indices[-resize:]
        return indices
    # CIFAR 100 pathway.
    else:
        desired_classes = [8, 13, 48, 58]  # numbers that correspond to the class in cifar100 - bicycle, bus, motorcycle, pickup truck
        # CIFAR100 classes are ordered alphabetically from 0-99. Could try classes streetcar(81), tractor(89), or train(90)
        for i in range(length):
            target = dataset.__getitem__(i)
            if (target[1] in desired_classes):
                indices.append(i)
        return indices

# This function maps the irregular label numbers of CIFAR10 and CIFAR100 combined, to ordered indices which fit the number of classes.
# Using the labels on their own will throw index errors because the fully connected layer of the nn is supposed to have 6.
def label_to_index(tensor_labels):
    look_up_table = {1: 0, 9: 1, 8: 2, 13: 3, 48: 4, 58: 5}
    for i in range(len(tensor_labels)):
        tensor_labels[i] = torch.Tensor([look_up_table[int(tensor_labels[i])]])
    return tensor_labels


#!/usr/bin/python3
''' prints the State object with the name passed as argument from
    database hbtn_0e_6_usa'''

import sys
from model_state import Base, State
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker

if __name__ == "__main__":
    dbConnector = 'mysql+mysqldb://{}:{}@localhost/{}'
    engine = create_engine(dbConnector.format(
        sys.argv[1], sys.argv[2], sys.argv[3]), pool_pre_ping=True)
    Base.metadata.create_all(engine)
    Base.metadata.bind = engine
    DBSession = sessionmaker()
    DBSession.bind = engine
    session = DBSession()
    paramState = sys.argv[4]
    #
    query = session.query(State).filter(
        State.name == paramState).order_by(State.id)

    if query.count() > 0:
        for instance in query:
            print(str(instance.id))
    else:
        print("Not found")
    session.close()


from typing import Dict, List
from Modules import Logger
from Modules.dbVersioning import GuildUpgrades

import json
import random
import sqlite3

MaxCache = 250
DBSTORE = "./Data/Database.db"
SETTINGS_STORE = "./Data/Settings.json"

Log = Logger.Get("Guilds")
conn = sqlite3.connect(DBSTORE)

Guilds = {}

class Guild:
    rEnabled:bool = True
    rDelete:bool = True
    rTimeout:int = 604800
    rThreshold:int = 10
    rChannels:List[int] = [865270701753892896]
    rDetected_msg:List[str] = ["> {AUTHOR},You seem to have posted a repost"]

    def __init__(self, ID):
        Log.debug(f"Guild {ID} retrieved")
        self.ID = ID
        with conn:
            Settings = conn.execute(
                "Select SETTINGS from GUILDS where ID = ?",
                (self.ID,),).fetchone()

        if Settings:
            self.LoadJSON(Settings[0])
        else:
            with conn:
                conn.execute(
                    "Insert into GUILDS values(?,?);",
                    (self.ID, self.Settingjson)
                )

    @property
    def Settingjson(self) -> str:
        return json.dumps(self.Settings, indent=4, sort_keys=True)

    @property
    def Settings(self) -> dict:
        return {
            "Version": "1.1",
            "rEnabled": self.rEnabled,
            "rDelete": self.rDelete,
            "rTimeout": self.rTimeout,
            "rThreshold": self.rThreshold,
            "rChannels": self.rChannels,
            "rDetected_msg": self.rDetected_msg
        }

    @property
    def msgRepostDetected(self) -> str:
        return random.choice(self.rDetected_msg)

    def Save(self):
        Log.debug(f"Saving guild {self.ID}'s Settings")
        with conn:
            conn.execute(
                "Update GUILDS set SETTINGS = ? where ID = ?;",
                (self.Settingjson, self.ID)
            )

    def LoadJSON(self, JSON: str):
        TypeLookup = {
            "rEnabled": [bool],
            "rDelete": [bool],
            "rTimeout": [int],
            "rThreshold": [list,str],
            "rChannels": [list,int],
            "rDetected_msg": [list,int]
            }

        Log.debug(f"Loading Guild {self.ID} from JSON")
        JSON:dict = json.loads(JSON)

        Version = JSON.get("Version",None)
        JSON = GuildUpgrades[Version](JSON)

        #! Data Validation Turned Off
        # for key,value in JSON.items():
        #     if isinstance(TypeLookup[key][0], list):
        #         for x in value:
        #             assert isinstance(x,TypeLookup[key][1])
        #     else:
        #         assert isinstance(value,TypeLookup[key][0])

        self.rEnabled = JSON["rEnabled"]
        self.rDelete = JSON["rDelete"]
        self.rTimeout = JSON["rTimeout"]
        self.rThreshold = JSON["rThreshold"]
        self.rChannels = JSON["rChannels"]
        self.rDetected_msg = JSON["rDetected_msg"]

        self.Save()

def Get(ID: int) -> Guild:
    if len(Guilds) > MaxCache:
        Guilds.popitem()
    if ID not in Guilds:
        Guilds[ID] = Guild(ID)
    return Guilds[ID]

def Check(ID: int) -> Guild:
    with conn:
        Settings = conn.execute(
            "Select SETTINGS from SERVERS where ID = ?",
            (ID,),)

    return len(Settings.fetchall()) == 1


"""
u' = -a*u, u(t) is the fraction of particle that remains
u(0) = 1
"""

import ODEsolver as ODE, numpy as np, matplotlib.pyplot as plt
from math import*
#a)
class Decay:
    def __init__(self, a):
        self.a = a

    def __call__(self, u):
        self.u = u
        return -self.a*self.u

#b)
y = 500
u = []
for i in range(1,y):
    q = 1./i
    u.append(u)

u = np.array(u)
a = np.linspace(log(2)/5600.0*u, y, 50)

#c)
f = Decay(a)

rk4 = ODE.RungeKutta4(Decay)
rk4.set_initial_condition(y)
rk41,rk42 = rk4.solve(a)

plt.plot(rk41,rk42)
plt.show()


import pygame
import random

pygame.init()

# Màu sắc
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
RED = (255, 0, 0)
GREEN = (0, 255, 0)

# Các cài đặt màn hình
screen_width = 800
screen_height = 600
screen = pygame.display.set_mode([screen_width, screen_height])
pygame.display.set_caption('Piano Game')

# Khởi tạo đồng hồ
clock = pygame.time.Clock()

# Khởi tạo font chữ
font = pygame.font.Font(None, 36)

# Danh sách các phím
keys = ['C', 'D', 'E', 'F', 'G', 'A', 'B']

# Danh sách các bài hát
songs = [['C', 'D', 'E', 'C', 'E', 'F', 'G', 'C', 'D', 'E', 'C', 'E', 'F', 'G'],
         ['G', 'F', 'E', 'D', 'C', 'D', 'E', 'F', 'G', 'G', 'F', 'E', 'D', 'C'],
         ['C', 'C', 'G', 'G', 'A', 'A', 'G', 'F', 'F', 'E', 'E', 'D', 'D', 'C']]

# Chế độ chọn bài hát
song_index = 0

# Biến điểm số
score = 0

# Biến đếm số lần nhấn sai hoặc bỏ qua
misses = 0

# Hàm kiểm tra xem phím có đúng với phím trong bài hát không
def check_key(key):
    global misses, song_index, score
    if key == songs[song_index][0]:
        songs[song_index].pop(0)
        score += 10
        if len(songs[song_index]) == 0:
            song_index = (song_index + 1) % len(songs)
    else:
        misses += 1
        if misses >= 3:
            game_over()

# Hàm kết thúc trò chơi
def game_over():
    global score
    screen.fill(WHITE)
    text = font.render('Game over! Score: ' + str(score), True, BLACK)
    screen.blit(text, [screen_width/2 - text.get_width()/2, screen_height/2 - text.get_height()/2])
    pygame.display.flip()
    pygame.time.wait(3000)
    pygame.quit()
    quit()

# Vòng lặp chính
done = False
while not done:
    # Xử lý các sự kiện
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            done = True
        elif event.type == pygame.KEYDOWN:
            if event.key == pygame.K_ESCAPE:
                done = True
            elif event.key == pygame.K_a:
                check_key('C')
            elif event.key == pygame.K_s:
                check_key('D')
            elif event.key == pygame.K_d:
                check_key('E' )
            elif event.key == pygame.K_f:
                check_key('F')
            elif event.key == pygame.K_g:
                check_key('G')
            elif event.key == pygame.K_h:
                check_key('A')
            elif event.key == pygame.K_j:
                check_key('B')
            elif event.key == pygame.K_SPACE:
                song_index = (song_index + 1) % len(songs)

                # Cập nhật màn hình
screen.fill(WHITE)

                # Vẽ các cột phím
pygame.draw.rect(screen, BLACK, [0, 0, 100, screen_height])
pygame.draw.rect(screen, BLACK, [screen_width - 100, 0, 100, screen_height])
pygame.draw.rect(screen, BLACK, [screen_width / 2 - 50, 0, 100, screen_height])

                # Vẽ các phím
key_width = 100
key_height = 50
key_padding = 10
for i in range(7):
    pygame.draw.rect(screen, BLACK,
    [key_padding + i * (key_width + key_padding), 350, key_width, key_height])
    text = font.render(keys[i], True, WHITE)
    screen.blit(text, [key_padding + i * (key_width + key_padding) + key_width / 2 - text.get_width() / 2,
    350 + key_height / 2 - text.get_height() / 2])

                # Hiển thị bài hát đang chơi
text = font.render('Song: ' + str(song_index + 1), True, BLACK)
screen.blit(text, [10, 10])

                # Hiển thị điểm số
text = font.render('Score: ' + str(score), True, BLACK)
screen.blit(text, [screen_width - 10 - text.get_width(), 10])

                # Hiển thị số lần nhấn sai hoặc bỏ qua
text = font.render('Misses: ' + str(misses), True, BLACK)
screen.blit(text, [screen_width / 2 - text.get_width() / 2, 10])

                # Nếu bài hát đã kết thúc thì hiển thị thông báo
if song_index == 0 and len(songs[song_index]) == 0:
    text = font.render('You won! Final score: ' + str(score), True, GREEN)
screen.blit(text, [screen_width / 2 - text.get_width() / 2, screen_height / 2 - text.get_height() / 2])
pygame.display.flip()
pygame.time.wait(3000)
pygame.quit()
quit()

pygame.display.flip()
clock.tick(60)


import numpy as np

import ast_toolbox.mcts.AdaptiveStressTesting as AST
import ast_toolbox.mcts.AST_MCTS as AST_MCTS
import ast_toolbox.mcts.ASTSim as ASTSim
import ast_toolbox.mcts.MCTSdpw as MCTSdpw
from ast_toolbox.mcts import tree_plot

class MCTS:
    """Monte Carlo Tress Search (MCTS) with double progressive widening (DPW) [1]_ using the env's action space as its action space.

    Parameters
    ----------
    env : :py:class:`ast_toolbox.envs.go_explore_ast_env.GoExploreASTEnv`.
        The environment.
    max_path_length: int
        The maximum search depth.
    ec : float
        The exploration constant used in UCT equation.
    n_itr: int
            The iteration number, the total numeber of environment call is approximately n_itr*max_path_length*max_path_length.
    k : float
        The constraint parameter used in DPW: |N(s,a)|<=kN(s)^alpha.
    alpha : float
        The constraint parameter used in DPW: |N(s,a)|<=kN(s)^alpha.
    clear_nodes : bool
        Whether to clear redundant nodes in tree.
        Set it to True for saving memoray. Set it to False to better tree plotting.
    log_interval : int
        The log interval in terms of environment calls.
    top_paths : :py:class:`ast_toolbox.mcts.BoundedPriorityQueues`, optional
        The bounded priority queue to store top-rewarded trajectories.
    gamma : float, optional
        The discount factor.
    stress_test_mode : int, optional
        The mode of the tree search. 1 for single tree. 2 for multiple trees.
    log_tabular : bool, optional
        Whether to log the training statistics into a tabular file.
    plot_tree : bool, optional
        Whether to plot the resulting searching tree.
    plot_path : str, optional
        The storing path for the tree plot.
    plot_format : str, optional
        The storing format for the tree plot

    References
    ----------
    .. [1] Lee, Ritchie, et al. "Adaptive stress testing of airborne collision avoidance systems."
     2015 IEEE/AIAA 34th Digital Avionics Systems Conference (DASC). IEEE, 2015.
    """

    def __init__(
        self,
        env,
        max_path_length,
        ec,
        n_itr,
        k,
        alpha,
        clear_nodes,
        log_interval,
        top_paths,
        log_dir,
        gamma=1.0,
        stress_test_mode=2,
        log_tabular=True,
        plot_tree=False,
        plot_path=None,
        plot_format='png'
    ):
        self.env = env
        self.stress_test_mode = stress_test_mode
        self.max_path_length = max_path_length
        self.macts_params = MCTSdpw.DPWParams(max_path_length,
                                              gamma,
                                              ec,
                                              2 * max(n_itr * log_interval // max_path_length ** 2, 1),
                                              k,
                                              alpha,
                                              clear_nodes)
        self.log_interval = log_interval
        self.top_paths = top_paths
        self.log_tabular = log_tabular
        self.plot_tree = plot_tree
        self.plot_path = plot_path
        self.plot_format = plot_format
        self.policy = None
        self.log_dir = log_dir
        self.n_itr = n_itr

    def init(self):
        """Initiate AST internal parameters
        """
        ast_params = AST.ASTParams(self.max_path_length, self.log_interval, self.log_tabular, self.log_dir, self.n_itr)
        self.ast = AST.AdaptiveStressTest(p=ast_params, env=self.env, top_paths=self.top_paths)

    def train(self, runner):
        """Start training.

        Parameters
        ----------
        runner : :py:class:`garage.experiment.LocalRunner <garage:garage.experiment.LocalRunner>`
            ``LocalRunner`` is passed to give algorithm the access to ``runner.step_epochs()``, which provides services
            such as snapshotting and sampler control.
        """
        self.init()
        if self.plot_tree:
            if self.stress_test_mode == 2:
                result, tree = AST_MCTS.stress_test2(self.ast, self.macts_params, self.top_paths, verbose=False, return_tree=True)
            else:
                result, tree = AST_MCTS.stress_test(self.ast, self.macts_params, self.top_paths, verbose=False, return_tree=True)
        else:
            if self.stress_test_mode == 2:
                result = AST_MCTS.stress_test2(self.ast, self.macts_params, self.top_paths, verbose=False, return_tree=False)
            else:
                result = AST_MCTS.stress_test(self.ast, self.macts_params, self.top_paths, verbose=False, return_tree=False)
        self.ast.params.log_tabular = True
        print("checking reward consistance")
        for (action_seq, reward_predict) in result:
            [a.get() for a in action_seq]
            reward, _ = ASTSim.play_sequence(self.ast, action_seq, sleeptime=0.0)
            assert np.isclose(reward_predict, reward)
        print("done")
        if self.plot_tree:
            tree_plot.plot_tree(tree, d=self.max_path_length, path=self.plot_path, format=self.plot_format)


#!/usr/bin/python
# -*- coding: utf-8 -*-

import sqlite3
import os

class Shakespeare(object):
    ''' Shakespeare translator class '''
    def __init__(self, dictionary=None):
        self.dictionary = dictionary or os.path.abspath(
                          os.path.join(os.path.dirname(__file__), 'dict.db'))
        self.connection = sqlite3.connect(self.dictionary)
        self.connection.execute('PRAGMA case_sensitive_like = OFF;')
        self.cursor = self.connection.cursor()

    def __del__(self):
        self.connection.close()

    def search(self, word, searchtype=0, exact=False, reverse=False):
        """
        English to spanish
        word = word to search
        searchtype = [startswith, endswith, contains]
        exact = exact search
        reverse = translate from spanish to english
        The query is limited to 200 for performance reasons
        """
        if not word:
            return
        if exact:
            sql_search = u'{}'
        else:
            if searchtype == 0:
                sql_search = u'{}%%' # starts with
            elif searchtype == 1:
                sql_search = u'%%{}' # ends with
            else:
                sql_search = u'%%{}%%' # contains
        sql_search = sql_search.format(word)
        word_a, word_b = ('sword', 'eword') if reverse else ('eword', 'sword')
        search_string = '''select {a}, {b} from dict where {a} like\
        ? order by {a} limit 200'''.format(a=word_a, b=word_b)
        self.cursor.execute(search_string, (sql_search,))
        result = self.cursor.fetchall()
        return result

if __name__ == '__main__':
    s = Shakespeare()
    # first, search for some love :)
    print(s.search('love'))


import pytest

from teamleader.api import Teamleader
from teamleader.exceptions import InvalidInputError

def test_validate_type():
    for arg, t in ((['item'], list), ({'key': 'value'}, dict)):
        assert Teamleader._validate_type(arg, t) == arg

    for t in (list, dict):
        assert Teamleader._validate_type(None, t) == t()

    with pytest.raises(InvalidInputError):
        Teamleader._validate_type('not a list', list)

def test_convert_custom_fields():
    data = {
        'key': 'value',
        'custom_fields': {
            'key': 'value',
            'foo': 'bar'
        }
    }

    Teamleader._convert_custom_fields(data)

    assert data == {
        'key': 'value',
        'custom_field_key': 'value',
        'custom_field_foo': 'bar'
    }


'''
Drinks

Given n numbers of proportions of orange juice in a drink (pi).
Determine the proportion of the final drink if equal proportions of orange juice
is taken out of each existing drink.

Input:
line 1 - contains n, which represents the number of existing drinks.
line 2 - contains n integers of pi, which is the volume fraction of orange
         juice in the i-th drink.
Note that: 1 <= n, pi <= 100

Output:
The volume fraction in percent of orange juice in the final drink. (Error within 10^-4)

Examples:

stdin:
    3
    50 50 100
stdout:
    66.66666666666667

stdin:
    4
    0 25 50 75
stdout:
    37.50000000000000
'''

n = int(input())
s = sum(list(map(int, input().split())))

print("%.6f" % (s/n))

'''
Notes:

A relatively simple solution that only involves very
simple math operations.

Python built-in functions are very powerful, however,
it is a slow language in comparison to the other ones.
'''


from collections import deque

def bfs(graph, n, m):
    queue = deque()
    queue.append((0, 0))
    graph[0][0] = 0

    while queue:
        x, y = queue.popleft()
        for i in range(4):
            nx = x + dx[i]
            ny = y + dy[i]

            if nx < 0 or nx >= m or ny < 0 or ny >= n:
                continue
            if graph[nx][ny] == 1:
                graph[nx][ny] = graph[x][y]+1
                queue.append((nx, ny))
    return graph[m-1][n-1]

dx = [0, 0, 1, -1]
dy = [1, -1, 0, 0]

M, N = map(int, input().split())
graph = []
for i in range(M):
    graph.append(list(map(int, input())))

answer = bfs(graph, N, M)
print(answer+1)


'''
Sample Command:-
python detect_aruco_images.py --image Images/1.png --type DICT_6X6_250
'''
import numpy as np
from utils import ARUCO_DICT, aruco_display, get_rec_points, get_centre
import argparse
import cv2
import sys

ap = argparse.ArgumentParser()
ap.add_argument("-i", "--image", required=True, help="path to input image containing ArUCo tag")
ap.add_argument("-t", "--type", type=str, default="DICT_ARUCO_ORIGINAL", help="type of ArUCo tag to detect")
args = vars(ap.parse_args())

print("Loading image...")
image = cv2.imread(args["image"])
h, w, _ = image.shape
width = 1000
height = int(width*(h/w))
frame = cv2.resize(image, (width, height), interpolation=cv2.INTER_CUBIC)
img_gray = cv2.cvtColor(frame, cv2.COLOR_RGB2GRAY)

# verify that the supplied ArUCo tag exists and is supported by OpenCV
if ARUCO_DICT.get(args["type"], None) is None:
    print(f"ArUCo tag type '{args['type']}' is not supported")
    sys.exit(0)

# load the ArUCo dictionary, grab the ArUCo parameters, and detect the markers
print("Detecting '{}' tags....".format(args["type"]))
arucoDict = cv2.aruco.Dictionary_get(ARUCO_DICT[args["type"]])
arucoParams = cv2.aruco.DetectorParameters_create()

corners, ids, rejected = cv2.aruco.detectMarkers(img_gray, arucoDict, parameters=arucoParams)
detected_markers = cv2.aruco.drawDetectedMarkers(frame, corners, ids)

camera_matrix = np.load("calibration_matrix.npy")
dist_coeffs = np.load("distortion_coefficients.npy")

points = get_rec_points(corners)
if points is not None:
    for point in points:
        cv2.circle(frame, tuple(point), 4, (0, 0, 255), -1)

    org_h, org_w = 16.5, 18.5 #in cm
    points_3D = np.array([[-org_w/2, org_h/2, 0], [org_w/2, org_h/2, 0], [org_w/2, -org_h/2, 0], [-org_w/2, -org_h/2, 0]], dtype="double")

    points_2D = points.astype('float32')
    points_3D = points_3D.astype('float32')

    success, rvecs, tvecs = cv2.solvePnP(points_3D, points_2D, camera_matrix, dist_coeffs)

    len = 5 #in cm
    axis = np.float32([[-len/2, -len/2, 0], [-len/2, len/2, 0], [len/2, len/2, 0], [len/2, -len/2, 0],
                        [-len/2, -len/2, len], [-len/2, len/2, len], [len/2, len/2, len],[len/2, -len/2, len]])

    imgpts_2d, jac = cv2.projectPoints(axis, rvecs, tvecs, camera_matrix, dist_coeffs)
    imgpts_2d = np.int32(imgpts_2d).reshape(-1, 2)

    frame = cv2.drawContours(frame, [imgpts_2d[:4]], -1, (255, 0, 0), 2)
    for i, j in zip(range(4), range(4, 8)):
        frame = cv2.line(frame, tuple(imgpts_2d[i]), tuple(imgpts_2d[j]), (255, 0, 0), 2)
    frame = cv2.drawContours(frame, [imgpts_2d[4:]], -1, (255, 0, 0), 2)

    # points = np.float32(points)
    # width = 800
    # height = int(width*(org_h/org_w))
    # target_points = np.float32([[0, 0], [width, 0], [width, height], [0, height]])

    # M = cv2.getPerspectiveTransform(points, target_points)
    # warped = cv2.warpPerspective(frame, M, (width, height))

    # # cv2.imshow("Warped", warped)

cv2.imshow("Image", frame)

# # Uncomment to save
# cv2.imwrite("output_sample.png",detected_markers)

cv2.waitKey(0)


from re import X
import numpy as np
import os
import wandb

os.environ['KMP_DUPLICATE_LIB_OK']='True'
## Example W%B commands
class logger:
    def __init__(self, wandb_flag):
        self.wandb_flag=wandb_flag

    def log(self,job_history,episode,alg,widx=None, sim_timer=None):
        completed_jobs = job_history['completed_jobs']
        completed_jobs_size = np.sum(job_history['completed_jobs_size'])
        exceed_deadline = job_history['exceed_deadline']
        exceed_deadline_size = np.sum(job_history['exceed_deadline_size'])
        latency = job_history['latency']/(completed_jobs)
        throughput = job_history['throughput']/(completed_jobs+exceed_deadline)
        episode = episode
        alg = alg
        widx = widx
        caching_rate=completed_jobs/(completed_jobs+exceed_deadline)
        caching_bytes=completed_jobs_size/(completed_jobs_size+exceed_deadline_size)
        if alg == 'fedavg':
            metrics = {'Worker {} caching rate'.format(widx): caching_rate,
                        'Worker {} caching rate(bytes)'.format(widx): caching_bytes,
                        'Worker {} latency'.format(widx):latency,'Worker {} throughput'.format(widx):throughput,'Episode':episode }
        elif alg == 'fedavg_val':
            metrics = {'Fed adaptation caching rate': caching_rate,
                        'Fed adaptation caching rate(bytes)': caching_bytes,
                        'Fed adaptation latency':latency,'Fed adaptation throughput':throughput,'Episode':episode}
        elif alg == 'single':
            metrics = {'Single agent caching rate': caching_rate,
                        'Single agent caching rate(bytes)': caching_bytes,
                        'Single agent latency':latency,'Single agent throughput':throughput,'Episode':episode}
        elif alg == 'single_val':
            metrics = {'Single agent adaptation caching rate': caching_rate,
                        'Single agent adaptation caching rate(bytes)': caching_bytes,
                        'Single agent adaptation latency':latency,'Single agent adaptation throughput':throughput,'Episode':episode}
        else:
            metrics = {'Heuristic caching rate': caching_rate,
                        'Heuristic caching rate(bytes)': caching_bytes,
                        'Heuristic latency':latency,'Heuristic throughput':throughput,'Episode':episode}

        if self.wandb_flag == True:
            wandb.log(metrics)
            print('Episode {} for worker {} in {} algorithm is logged (Caching rate: {:.2f}%, Bytes: {:.2f}%) in {:.1f} sec'.format(episode,widx,alg,100*caching_rate,100*caching_bytes,sim_timer))
        else:
            print('Episode {} for worker {} in {} algorithm is done (Caching rate: {:.2f}%, Bytes: {:.2f}%) in {:.1f} sec'.format(episode,widx,alg,100*caching_rate,100*caching_bytes,sim_timer))

        return metrics


import cv2
import numpy as np

CORNER_COUNT = 6, 8
SHRINK_CONST = 6

# termination criteria
criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 0.001)

objp = np.zeros((CORNER_COUNT[0]*CORNER_COUNT[1],3), np.float32)
objp[:,:2] = np.mgrid[0:CORNER_COUNT[0],0:CORNER_COUNT[1]].T.reshape(-1,2)

# Arrays to store object points and image points from all the images.
objpoints = [] # 3d point in real world space
imgpoints = [] # 2d points in image plane.

images = []

for i in range(1, 21):
    img = cv2.imread(f"images/img{i}.jpg")
    # img = cv2.imread(f"images/img{i}.jpg", cv2.IMREAD_GRAYSCALE)
    # img = cv2.imread(f"../AssignmentIII/AssignmentIII/PartA/images/img{i}.jpg", cv2.IMREAD_GRAYSCALE)
    # img = cv2.resize(img, (img.shape[1]//4, img.shape[0]//4))
    images.append(img)
    # print(img.shape)
    # exit()
    # print(img)
    # cv2.imshow("corners", img)
    # cv2.waitKey(0)

    # cv2.destroyAllWindows()

for img in images:
    # print(img.shape[::-1])
    # img = cv2.resize(img, (img.shape[1]//10, img.shape[0]//10))
    # print(img.shape)
    # cv2.imshow("corners", img)
    # cv2.waitKey(0)
    img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    # cv2.destroyAllWindows()
    ret, corners = cv2.findChessboardCorners(img, CORNER_COUNT, None)
    # print(ret)
    # print(corners)
    if ret == True:
        objpoints.append(objp)

        corners2 = cv2.cornerSubPix(img, corners, (11, 11), (-1, -1), criteria)
        imgpoints.append(corners2)
        # blank = np.zeros(img.shape, dtype=np.uint8)
        # cv2.drawChessboardCorners(img, CORNER_COUNT, corners2, ret)
        # cv2.drawChessboardCorners(blank, CORNER_COUNT, corners2, ret)

        # cv2.imshow("corners", img)
        # cv2.waitKey(0)

        # cv2.destroyAllWindows()

ret, mtx, dist, rvecs, tvecs = cv2.calibrateCamera(objpoints, imgpoints, img.shape[::-1], None, None)

newcameramtx, roi=cv2.getOptimalNewCameraMatrix(mtx,dist,img.shape[::-1],1,img.shape[::-1])
# newcameramtx, roi=cv2.getOptimalNewCameraMatrix(mtx,dist,img.shape[::-1],0,img.shape[::-1])
# ret: RMS reprojection error
# mtx: camera matrix
# dist: distortion coefficients [k1, k2, p1, p2, k3]
# k: radial distortion values
# p: tangential distortion values
# rvecs: rotation vector
# tvecs: tranlation vector
img2 = cv2.imread(f"images/img21.jpg")
# img2 = cv2.resize(img2, (img2.shape[1]//4, img2.shape[0]//4))
# img2 = cv2.resize(img2, img2.shape)
dst = cv2.undistort(img2, mtx, dist, None, newcameramtx)
# blk_dst = cv2.undistort(blank, mtx, dist, None, newcameramtx)
# print(ret)
# print("camera matrix", mtx, sep="\n")
print("distortion values", dist, sep="\n")
# print(rvecs)
# print(tvecs)
print("new camera matrix", newcameramtx, sep="\n")
# print(roi)
print(img2.shape, dst.shape)
img2 = cv2.resize(img2, (img2.shape[1]//SHRINK_CONST, img2.shape[0]//SHRINK_CONST))
dst = cv2.resize(dst, (dst.shape[1]//SHRINK_CONST, dst.shape[0]//SHRINK_CONST))
print(img2.shape, dst.shape)

# cv2.imshow("img2", img2)
# cv2.imshow("undistort", dst)

cv2.imwrite(f"calibrated_images/img{21}.jpg", img2)
cv2.imwrite(f"calibrated_images/undistort{21}.jpg", dst)
# cv2.waitKey(0)

# cv2.destroyAllWindows()

# for img in images:
for i in range(1, 21):
    img = images[i-1]
    # img = img[roi[2]:roi[3], roi[0]:roi[1]]
    dst = cv2.undistort(img, mtx, dist, None, newcameramtx)
    img = cv2.resize(img, (img.shape[1]//SHRINK_CONST, img.shape[0]//SHRINK_CONST))
    dst = cv2.resize(dst, (dst.shape[1]//SHRINK_CONST, dst.shape[0]//SHRINK_CONST))

    cv2.imshow("img2", img)
    cv2.imshow("undistort", dst)
    cv2.imwrite(f"calibrated_images/img{i}.jpg", img)
    cv2.imwrite(f"calibrated_images/undistort{i}.jpg", dst)
    # cv2.waitKey(0)

    cv2.destroyAllWindows()


import eth_abi
import pytest
from brownie import Contract, MockDAI, MockUSDC, MockUSDT, VyperMock3CRV, web3

USDC_ADDRESS = "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"
USDT_ADDRESS = "0xdAC17F958D2ee523a2206206994597C13D831ec7"
DAI_ADDRESS = "0x6B175474E89094C44Da98b954EedeAC495271d0F"
E_CRV_ADDRESS = "0x6c3F90f043a72FA612cbac8115EE7e52BDe6E490"
FRAX_CRV_ADDRESS = "0xd632f22692FaC7611d2AA1C0D552930D43CAEd3B"

@pytest.fixture(scope="function", autouse=True)
def mock_dai(admin, alice):
    _mock_dai = admin.deploy(MockDAI)
    yield _mock_dai

@pytest.fixture(scope="function", autouse=True)
def mock_usdc(admin, alice):
    _mock_usdc = admin.deploy(MockUSDC)
    yield _mock_usdc

@pytest.fixture(scope="function", autouse=True)
def mock_usdt(admin, alice):
    _mock_usdt = admin.deploy(MockUSDT)
    yield _mock_usdt

@pytest.fixture(scope="function", autouse=True)
def mock_three_crv(admin):
    three_crv = admin.deploy(VyperMock3CRV, "3CRV", "3CRV", 18, 0)
    yield three_crv

@pytest.fixture(scope="function", autouse=True)
def mint_mock_token(mock_dai, mock_usdc, mock_usdt, admin, alice, bob):
    for account in [admin, alice, bob]:
        for token in [mock_dai, mock_usdc, mock_usdt]:
            token.faucet({"from": account})

@pytest.fixture(scope="function")
def usdc(admin):
    yield Contract(USDC_ADDRESS)

@pytest.fixture(scope="function")
def usdt(admin):
    yield Contract(USDT_ADDRESS)

@pytest.fixture(scope="function")
def dai(admin):
    yield Contract(DAI_ADDRESS)

@pytest.fixture(scope="function")
def E_CRV(admin):
    yield Contract(E_CRV_ADDRESS)

@pytest.fixture(scope="function")
def FRAX_CRV(admin):
    yield Contract(FRAX_CRV_ADDRESS)

def mint_dai(account, amount):
    amount = f"{amount:#0{66}x}"
    slot = web3.keccak(
        hexstr=eth_abi.encode_abi(["address", "uint256"], (account.address, 0x2)).hex()
    )
    web3.provider.make_request(
        "hardhat_setStorageAt", [DAI_ADDRESS, slot.hex(), amount]
    )

def mint_usdc(account, amount):
    amount = f"{amount:#0{66}x}"
    slot = web3.keccak(
        hexstr=eth_abi.encode_abi(["address", "uint256"], (account.address, 0x9)).hex()
    )
    web3.provider.make_request(
        "hardhat_setStorageAt", [USDC_ADDRESS, slot.hex(), amount]
    )

def mint_usdt(account, amount):
    amount = f"{amount:#0{66}x}"
    slot = web3.keccak(
        hexstr=eth_abi.encode_abi(["address", "uint256"], (account.address, 0x2)).hex()
    )
    web3.provider.make_request(
        "hardhat_setStorageAt", [USDT_ADDRESS, slot.hex(), amount]
    )

def mint_3crv(account, amount):
    amount = f"{amount:#0{66}x}"
    slot = web3.keccak(
        hexstr=eth_abi.encode_abi(["uint256", "address"], (0x3, account.address)).hex()
    )
    hex_ = '0x' + slot.hex()[2:].lstrip('0')
    web3.provider.make_request(
        "hardhat_setStorageAt", [E_CRV_ADDRESS, hex_, amount]
    )

def mint_frax_crv(account, amount):
    amount = f"{amount:#0{66}x}"
    slot = web3.keccak(
        hexstr=eth_abi.encode_abi(["uint256", "address"], (15, account.address)).hex()
    )
    web3.provider.make_request(
        "hardhat_setStorageAt", [FRAX_CRV_ADDRESS, slot.hex(), amount]
    )


import os

initPrm = input(
    "- For port forwarding, type 'proxy'. Examples include express.js and webmin.\n\n- For services located in a webroot, type 'webroot'. [webroot] \n> ").lower() or "webroot"

APACHE_LOG_DIR = "{APACHE_LOG_DIR}"

def proxyConf():
    if not "." in domainPrm:
        print("Not a valid domain.")
    f = open(f"{domainPrm}.conf", "w")
    f.write(
        f"<VirtualHost *:80>\nServerName {domainPrm}\n{serverAlias}\nProxyPass / http://localhost:{portForForward}/\nProxyPassReverse / http://localhost:{portForForward}/\n</VirtualHost>")
    f.close()
    os.system(f'sudo cp {domainPrm}.conf {apcPa}/sites-avalible/{domainPrm}.conf')
    os.system("a2enmod proxy")
    os.system("a2enmod proxy_http")
    os.system(f"a2ensite {domainPrm}")

def regConf():
    if not "." in domainPrm:
        print("Not a valid domain.")
    f = open(f"{domainPrm}.conf", "w")
    portForForward = None
    f.write(
        f"<VirtualHost *:80>\nServerName {domainPrm}\n{serverAlias}\nDocumentRoot {webLoc}\nErrorLog ${APACHE_LOG_DIR}/error.log\nCustomLog ${APACHE_LOG_DIR}/access.log combined\n</VirtualHost>")
    f.close()
    os.system(f'sudo cp {domainPrm}.conf {apcPa}/sites-avalible/{domainPrm}.conf')
    os.system(f"a2ensite {domainPrm}")

# Domain setup
domainAnswer = input(
    "What are your domain names? [example.com] \n> ").lower() or "example.com"
domainAnswer = domainAnswer.split(",")
domainPrm = domainAnswer[0]
serverAlias = "".join(list(map(lambda d: f"{d} ", domainAnswer[1:])))
if serverAlias:
    serverAlias = "ServerAlias " + serverAlias
if initPrm == "proxy":
    portForForward = input(
        "Please enter the port you wish to forward [8080] \n> ") or "8080"
    apcPa = input(
        "Where is your Apache installation located? [/etc/apache2/] \n> ") or "/etc/apache2"
    proxyConf()
elif initPrm == "webroot":
    webLoc = input(
        "What is the absolute path of the files for your website?\n> ") or "/var/www/html"
    apcPa = input(
        "Where is your Apache installation located? [/etc/apache2/] \n> ") or "/etc/apache2"
    regConf()
else:
    print("Not a valid option.")
    exit(0)

restart = input(
    "Would you like to reload the configuration now? [n] \n> ").lower() or "n"
if restart == "y" or restart == "yes":
    os.system("sudo apachectl -k graceful")
exit(0)


import matplotlib.pyplot as plt

from skimage import data
from skimage.filters import threshold_otsu, threshold_local
from skimage.io import imread
from skimage.color import rgb2gray

image = imread('image.jpg')
image = rgb2gray(image)

global_thresh = threshold_otsu(image)
binary_global = image > global_thresh

block_size = 35
binary_adaptive = threshold_local(image, block_size, offset=10)

fig, axes = plt.subplots(nrows=3, figsize=(7, 8))
ax0, ax1, ax2 = axes
plt.gray()

ax0.imshow(image)
ax0.set_title('Image')

ax1.imshow(binary_global)
ax1.set_title('Global thresholding')

ax2.imshow(binary_adaptive)
ax2.set_title('Adaptive thresholding')

for ax in axes:
    ax.axis('off')

plt.show()


def enter(n):
    s = set()
    cnt = 0
    for i in range(n):
        record = input()
        if record == 'ENTER':
            s.clear() # 초기화
       	elif record != 'ENTER':
            if record not in s:
                cnt += 1
                s.add(record)
    return cnt

n = int(input())
print(enter(n))

백준/Silver/25192. 인사성 밝은 곰곰이/인사성 밝은 곰곰이.py

인사성 밝은 곰곰이.py


from events.movement import player_movement, display_valid_move_description
from events.event_checker import pick_available_foe, check_for_predetermined_events
from events.game_ending import game_over, goal_achieve, easter_egg

from combat.enemy_info import update_enemy_info
from combat.combat_widget import activate_battle_button, toggle_battle_buttons
from combat.player_info import drop_item
from combat.combat_result import escape_from_fight, win_fight, mid_boss_killed

from GUI import GAME_LOCATION_IMAGE_PATH
from GUI.create_widgets import update_image_label

from GUI_update.update_map_widget import map_widget_update
from GUI_update.update_status_frame import update_status_message

import pathlib
from functools import partial

def game(overall_gui_info: dict, game_info: dict, event) -> None:
    """
    Drive the game flow.
    """
    battle_round = 0
    saved_coordinate = (game_info['character']["X-coordinate"], game_info['character']["Y-coordinate"])
    progress_switch = {"move": '', "event": False, "opponent": False, "battle": False, "result": False}
    pass_value = event if type(event) is str else event.keysym
    shortcut_list = ("a", "A", "d", "D", "w", "W", "s", "S")

    if pass_value in shortcut_list:
        if player_movement(game_info, shortcut_list.index(pass_value) // 2 + 1, overall_gui_info):
            map_widget_update(game_info['character'], overall_gui_info)
            triggered_event = check_for_predetermined_events(game_info)
            progress_switch['move'] = (game_info['character']["X-coordinate"], game_info['character']["Y-coordinate"])
            progress_switch['event'] = triggered_event
            progress_switch['opponent'] = pick_available_foe(triggered_event, game_info)
            display_valid_move_description(game_info['character'], overall_gui_info)
        else:
            overall_gui_info['Event Bar'].config(text="Invalid Move!")
    if progress_switch['opponent']:
        update_enemy_info(overall_gui_info, progress_switch['opponent'],
                          f"Encountered {progress_switch['opponent']['Name']}\n\n"
                          f"{progress_switch['opponent']['Slogan']}")
        progress_switch['battle'] = True

    if progress_switch['battle']:
        toggle_battle_buttons(overall_gui_info, "enable")
        activate_battle_button(overall_gui_info, game_info['character'], progress_switch['opponent'])
        overall_gui_info['pause'].set(True)

    while progress_switch['battle']:
        battle_round += 1
        overall_gui_info['GUI'].wait_variable(overall_gui_info['pause'])
        message = "Took the hit!"
        if game_info['character']['Status'] == "Poisoned":
            game_info['character']['Current HP'] = int(game_info['character']['Current HP'] * 0.9)
            message = "You feel the poison coursing through your veins. \n You take additional damage!!"
        update_enemy_info(overall_gui_info, progress_switch['opponent'], f"Round {battle_round}\n{message}")
        overall_gui_info['Status Frame'].children['character_status'].config(
            text=update_status_message(game_info['character'], 4, -7))
        if progress_switch['opponent']['HP'] <= 0 or \
                game_info['character']['Current HP'] <= 0 or game_info['character']['Escape']:
            progress_switch['battle'] = False

    if progress_switch['opponent'] and game_info['character']['Current HP'] <= 0:
        game_over(overall_gui_info)

    if progress_switch['opponent'] and game_info['character']['Current HP'] > 0:
        overall_gui_info['Buttons Frame'].bind("<KeyPress>", partial(game, overall_gui_info, game_info))

    if progress_switch['opponent'] and progress_switch['opponent']['HP'] <= 0 < game_info['character']['Current HP']:
        win_fight(overall_gui_info, game_info, progress_switch)
        drop_item(overall_gui_info, game_info['character'], progress_switch['opponent'])
        progress_switch['result'] = "win"

    if progress_switch['opponent'] and game_info['character']['Escape']:
        escape_from_fight(overall_gui_info, game_info, saved_coordinate)
        progress_switch['result'] = "run"

    if progress_switch['move']:
        game_info['character']['Escape'] = False
        image_file = 'Default'
        if pathlib.Path(GAME_LOCATION_IMAGE_PATH.format(progress_switch['move'])).is_file():
            image_file = str(progress_switch['move'])
        if pathlib.Path(GAME_LOCATION_IMAGE_PATH.format(image_file)).is_file():
            update_image_label(overall_gui_info['Script Frame'], "image_box",
                               GAME_LOCATION_IMAGE_PATH.format(image_file))
        else:
            raise FileNotFoundError("Location image cannot be found! Please check the path!")

    if progress_switch['opponent']:
        mid_boss_killed(progress_switch, game_info['environment'], overall_gui_info, (4, 2))
        goal_achieve(progress_switch, game_info['environment'], overall_gui_info)

    if progress_switch['move'] == (0, 4):
        easter_egg(overall_gui_info)

def main():
    """
    Drive the program.
    """

if __name__ == "__main__":
    main()


from typing import List
import xlsxwriter

# 读取txt信息函数：
def ReadMatInfo(filepath):
    with open(filepath, 'r') as file:
        data: List[str] = [line.strip() for line in file.readlines()]
        return data

# 将从文件读取的物料X的已确定的MRP进行处理换行符
temp_confirmed_mrp_X = ReadMatInfo('./data_files/MRPConfirmed.txt')[0].split(' ', -1)

# 读取物料X的已确定MRP并加入数组
Confirmed_MRP_X = []
for i in range(len(temp_confirmed_mrp_X) - 1):
    Confirmed_MRP_X.insert(i, int(temp_confirmed_mrp_X[i + 1]))

# 将从文件读取的物料Y的已确定的MRP进行处理换行符
temp_confirmed_mrp_Y = ReadMatInfo('./data_files/MRPConfirmed.txt')[1].split(' ', -1)

# 读取物料Y的已确定MRP并加入数组
Confirmed_MRP_Y = []
for i in range(len(temp_confirmed_mrp_Y) - 1):
    Confirmed_MRP_Y.insert(i, int(temp_confirmed_mrp_Y[i + 1]))

# 将从文件读取的物料X的预测MRP进行处理换行符
temp_pre_mrp_X = ReadMatInfo('./data_files/MRPPredicted.txt')[0].split(' ', -1)

# 读取物料X的预测MRP
Predicted_MRP_X = []
for i in range(len(temp_pre_mrp_X) - 1):
    Predicted_MRP_X.insert(i, int(temp_pre_mrp_X[i + 1]))

# 将从文件读取的物料Y的预测MRP进行处理换行符
temp_pre_mrp_Y = ReadMatInfo('./data_files/MRPPredicted.txt')[1].split(' ', -1)

# 读取物料Y的预测MRP
Predicted_MRP_Y = []
for i in range(len(temp_pre_mrp_Y) - 1):
    Predicted_MRP_Y.insert(i, int(temp_pre_mrp_Y[i + 1]))

# 读取加工车间额定工作能力：

# 读取车间WC01的额定工作能力：
workshop01 = int((ReadMatInfo('./data_files/WCRatedCapacity.txt')[0].split(' ', -1))[1])

# 读取车间WC02的额定工作能力：
workshop02 = int((ReadMatInfo('./data_files/WCRatedCapacity.txt')[1].split(' ', -1))[1])

# 读取文件中工艺路线信息（一共有3条工艺路线）
# 读取第一条工艺路线X1
X1_process_num = int((ReadMatInfo('./data_files/Routing.txt')[0].split(' ', -1))[1])
X1_process_order = int((ReadMatInfo('./data_files/Routing.txt')[0].split(' ', -1))[2])
X1_workshop = (ReadMatInfo('./data_files/Routing.txt')[0].split(' ', -1))[3]
X1_precess_time = int((ReadMatInfo('./data_files/Routing.txt')[0].split(' ', -1))[4])
# 读取第二条工艺路线X2
X2_process_num = int((ReadMatInfo('./data_files/Routing.txt')[1].split(' ', -1))[1])
X2_process_order = int((ReadMatInfo('./data_files/Routing.txt')[1].split(' ', -1))[2])
X2_workshop = (ReadMatInfo('./data_files/Routing.txt')[1].split(' ', -1))[3]
X2_precess_time = int((ReadMatInfo('./data_files/Routing.txt')[1].split(' ', -1))[4])
# 读取第三条工艺路线Y
Y_process_num = int((ReadMatInfo('./data_files/Routing.txt')[2].split(' ', -1))[1])
Y_process_order = int((ReadMatInfo('./data_files/Routing.txt')[2].split(' ', -1))[2])
Y_workshop = (ReadMatInfo('./data_files/Routing.txt')[2].split(' ', -1))[3]
Y_precess_time = int((ReadMatInfo('./data_files/Routing.txt')[2].split(' ', -1))[4])

# 计算过去需求负荷
# 计算WC01的过去需求负载
past_demand_load1 = []
for i in range(len(Confirmed_MRP_X)):
    past_demand_load1.insert(i, Confirmed_MRP_X[i] * X1_precess_time + Confirmed_MRP_Y[i] * Y_precess_time)

# 计算WC02的过去需求负载
past_demand_load2 = []
for i in range(len(Confirmed_MRP_X)):
    past_demand_load2.insert(i, Confirmed_MRP_X[i] * X2_precess_time)

# 计算计划需求负荷
# 计算WC01的计划需求负荷
plan_demand_load1 = []
for i in range(len(Confirmed_MRP_X)):
    plan_demand_load1.insert(i, Predicted_MRP_X[i] * X1_precess_time + Predicted_MRP_Y[i] * Y_precess_time)

# 计算WC02的计划需求负荷
plan_demand_load2 = []
for i in range(len(Confirmed_MRP_X)):
    plan_demand_load2.insert(i, Predicted_MRP_X[i] * X2_precess_time)
# 计算总负荷
# 计算WC01的总负荷
total_load1 = []
for i in range(len(Confirmed_MRP_X)):
    total_load1.insert(i, past_demand_load1[i] + plan_demand_load1[i])

# 计算WC02的总负荷
total_load2 = []
for i in range(len(Confirmed_MRP_X)):
    total_load2.insert(i, past_demand_load2[i] + plan_demand_load2[i])

# 计算平均能力
# 计算WC01的平均能力
average_process_time1 = []
for i in range(len(Confirmed_MRP_X)):
    average_process_time1.insert(i, workshop01)
# 计算WC02的平均能力
average_process_time2 = []
for i in range(len(Confirmed_MRP_X)):
    average_process_time2.insert(i, workshop02)

# 计算余/欠能力
# 计算WC01的余/欠能力
surplus_capacity1 = []
for i in range(len(Confirmed_MRP_X)):
    surplus_capacity1.insert(i, total_load1[i] - average_process_time1[i])

# 计算WC02的余/欠能力
surplus_capacity2 = []
for i in range(len(Confirmed_MRP_X)):
    surplus_capacity2.insert(i, total_load2[i] - average_process_time2[i])

# 计算累计能力
# 计算WC01的累计能力
acc_capacity1 = []
acc_capacity1.insert(0, surplus_capacity1[0])
for i in range(1, len(Confirmed_MRP_X)):
    acc_capacity1.insert(i, surplus_capacity1[i] + surplus_capacity1[i - 1])
# 计算WC02的累计能力
acc_capacity2 = []
acc_capacity2.insert(0, surplus_capacity2[0])
for i in range(1, len(Confirmed_MRP_X)):
    acc_capacity2.insert(i, surplus_capacity2[i] + surplus_capacity2[i - 1])

# 将数据写入到Excel并创建表格
# 创建Excel文档
print("正在进行Excel录入中：")
wb = xlsxwriter.Workbook("./data_files/calculation_of_CRP.xlsx")
# 创建WC01计算结果的表单
ws1 = wb.add_worksheet(name="caculation_of_WC01")
calculation_item = ['过去需求量', '计划需求量', '总负荷量', '平均能力', '余/欠能力', '累计能力']
headline = ['周数', '1', '2', '3', '4', '5', '6']
# 将数据插入到表格中：
ws1.write_row('A1', headline)
ws1.write_column('A2', calculation_item)
ws1.write_row('B2', past_demand_load1)
ws1.write_row('B3', plan_demand_load1)
ws1.write_row("B4", total_load1)
ws1.write_row('B5', average_process_time1)
ws1.write_row('B6', surplus_capacity1)
ws1.write_row('B7', acc_capacity1)

# 创建WC02计算结果的表单
ws2 = wb.add_worksheet(name="caculation_of_WC02")
calculation_item = ['过去需求量', '计划需求量', '总负荷量', '平均能力', '余/欠能力', '累计能力']
headline = ['周数', '1', '2', '3', '4', '5', '6']
# 将数据插入到表格中：
ws2.write_row('A1', headline)
ws2.write_column('A2', calculation_item)
ws2.write_row('B2', past_demand_load2)
ws2.write_row('B3', plan_demand_load2)
ws2.write_row("B4", total_load2)
ws2.write_row('B5', average_process_time2)
ws2.write_row('B6', surplus_capacity2)
ws2.write_row('B7', acc_capacity2)

print("Excel录入完毕！！")
wb.close()

# 在控制台简单输出：
print("WC01结果：")
print("过去需求量是：")
print(past_demand_load1)
print("计划需求量是：")
print(plan_demand_load1)
print("总负荷是：")
print(total_load1)
print("平均能力是：")
print(average_process_time1)
print("余/欠能力是：")
print(surplus_capacity1)
print("累计能力是：")
print(acc_capacity1)

print("WC02结果：")
print("过去需求量是：")
print(past_demand_load2)
print("计划需求量是：")
print(plan_demand_load2)
print("总负荷是：")
print(total_load2)
print("平均能力是：")
print(average_process_time2)
print("余/欠能力是：")
print(surplus_capacity2)
print("累计能力是：")
print(acc_capacity2)


from ..utils import transform_data
from ..metrics import pairwise_euclid_distances
from ..kernel import GaussKernel

import numpy as np

class Bandwidth(object):
    """bandwidth selection for rbf-kernel hyperparameter.

    Args:
        cov (ndarray): [description]
        inv_cov (ndarray): [description]
        bandwidth (ndarray): [description]

    Raises:
        ValueError: [description]
        ValueError: [description]
        NotImplementedError: [description]
        ValueError: [description]

    Returns:
        [type]: [description]

    Notes:
        Bandwidth selection strongly affects kernel density estimation.
        [1] D.W. Scott, “Multivariate Density Estimation: Theory, Practice, and Visualization”, John Wiley & Sons, New York, Chicester, 1992.
        [2] B.W. Silverman, “Density Estimation for Statistics and Data Analysis”, Vol. 26, Monographs on Statistics and Applied Probability, Chapman and Hall, London, 1986.
        [3] P. Hall, “Large Sample Optimality of Least Squares Cross-Validation in Density Estimation,” Ann. Stat., vol. 11, no. 4, pp. 1156–1174, 1983.
        [4] C. J. Stone, “An Asymptotically Optimal Window Selection Rule for Kernel Density Estimates,” Ann. Stat., vol. 12, no. 4, pp. 1285–1297, 1984.
        [5] W. Härdle, P. Hall, and J. S. Marron, “How far are automatically chosen regression smoothing parameters from their optimum?,” J. Am. Stat. Assoc., vol. 83, no. 401, pp. 86–95, 1988.
    """

    def __init__(self, data, method='scott', weights=None):
        """[summary]

        Args:
            data (array-like):
                Datapoints to estimate.
                1D-array [x_1,x_2,...,x_n]. This input is treated as 1-dimensional data.
                2D-array [[x_1^d1,x_1^d2], [x_2^d1,x_2^d2],...,[x_n^d1,x_n^d2]].

            method (str or float, optional):
                Defaults to 'scott'.
                Select the bandwidth selection method from　['cov', 'scott', 'silverman', 'median', 'LCV','LSCV'] .
                - Median heuristic
                - Scott heuristic [1]
                - Silverman heuristic [2]
                - LSCV [3-5]
                - LCV [3-5]
                - covariance of data

            weights (array-like, optional):
                Defaults to None. Weights of datapoints. This must be the same shape as dataset.

        Raises:
            ValueError: [description]
        """
        self.__data = transform_data(data)
        self.__n_data, self.__ndim = self.__data.shape

        if weights is not None:
            self.__weights = np.atleast_1d(weights).astype(float)
            self.__weights /= np.sum(self.__weights)
            if (self.__weights.ndim != 1) or (self.__weights.size != self.__n_data):
                raise ValueError("`weights` input should be one-dimensional or the length of the number of datapoints.")
        else:
            self.__weights = np.ones(self.__n_data) / self.__n_data  # 1/N

        self.__neff = 1. / np.sum(self.__weights**2)  # if weight is None -> neff = N
        self.__compute_covariance()
        self.set_bandwidth(method=method)

    def __compute_covariance(self):
        epsilon = 1e-12
        lambdaI = epsilon * np.eye(self.__ndim)
        if not hasattr(self, '__data_inv_cov'):
            self.__data_cov = np.atleast_2d(np.cov(self.__data, rowvar=False, bias=False, aweights=self.__weights))

            try:
                self.__data_inv_cov = np.linalg.inv(self.__data_cov)

            except:  # noqa: E722
                self.__data_cov += lambdaI
                self.__data_inv_cov = np.linalg.inv(self.__data_cov)

    def set_bandwidth(self, method=None):
        if (method is None) or (method == 'cov'):
            self.__method = 'cov'
            self.__covariance_factor = lambda: 1.0  # band width is std of data.

        elif method == 'median':
            self.__method = method
            self.__covariance_factor = self.median_method

        elif method == 'scott':
            self.__method = method
            self.__covariance_factor = self.scott_factor

        elif method == 'silverman':
            self.__method = method
            self.__covariance_factor = self.silverman_factor

        elif method == 'LSCV':
            """
            minimizing Least Square Cross Validation.
            """
            raise NotImplementedError

        elif method == 'LCV':
            """
            maximizing Likelihood Cross Validation.
            """
            self.__method = method
            self.__covariance_factor = self.LCV_method

        elif np.isscalar(method) and not isinstance(method, str):
            self.__method = 'constant'
            self.__covariance_factor = lambda: method

        else:
            msg = "'method' should be 'cov', 'scott', 'silverman', 'scalar', 'median', 'LSCV'"
            raise ValueError(msg)

        self.__compute_cov()

    def __compute_cov(self):
        self.__factor = self.__covariance_factor()
        if self.__method not in ['median', 'LSCV', 'LCV']:
            self._cov = self.__data_cov * self.__factor**2
            self._inv_cov = self.__data_inv_cov / self.__factor**2

    def scott_factor(self):
        """
        Compute Scott's factor.
        : n ^ (-1/(d+4))
        """
        return np.power(self.__neff, -1. / (self.__ndim + 4))

    def silverman_factor(self):
        """
        Compute the Silverman's factor.
        factor = (4/(d+2))**(1/(d+4)) * n**(-1/(d+4))
        so, j-th bandwidth
        h_j = factor*sig_j
        """
        return np.power(self.__neff * (self.__ndim + 2.0) / 4.0, -1. / (self.__ndim + 4))

    def median_method(self):
        '''
        The Euclidean distance between data is calculated, and the mode of distance is defined as the bandwidth.
        '''
        dists = pairwise_euclid_distances(self.__data, self.__data, True)
        ind = np.triu_indices(self.__n_data, k=1)
        h = np.median(dists[ind])
        if self.__method == 'median':
            """Prevents the calculated cov from changing when this function is executed."""
            self._cov = np.eye(self.__ndim) * h
            self._inv_cov = np.eye(self.__ndim) / h
        return h

    def LCV_method(self):
        if self.__method == 'LCV':
            # try:
            #     import optuna
            # except ImportError:
            #     print("Cannot find optuna library, please install it to use this option.")
            #     raise
            #
            # optuna.logging.disable_default_handler()
            # def LogLikelihood(trial):
            #     epsilon=1e-12
            #     cov = []
            #     for i in range(2):
            #         cov.append(trial.suggest_loguniform(f'h{i}', 1e-3, 1e+2))
            #     cov = np.diag(cov)
            #     M = gauss_kernel(self.__data,self.__data,cov=cov)
            #     return np.log((M-np.diag(np.diag(M))).mean(axis=1)+epsilon).mean().ravel()
            #
            # study = optuna.create_study(direction='maximize')
            # study.optimize(LogLikelihood,n_trials=100)
            # self._cov = np.diag(np.fromiter(study.best_params.values(),dtype=float))
            # self._inv_cov = np.linalg.inv(self._cov)
            try:
                import gpbayesopt
            except ImportError:
                print("Cannot find gpbayesopt library, please install it to use this option. \n \
                      Install: pip install git+https://github.com/JohnYKiyo/bayesian_optimization.git")
                raise

            kernel = GaussKernel(covariance=np.diag(np.ones(self.__ndim)))

            def LogLikelihood(cov):
                # print(cov,kernel.cov)
                epsilon = 1e-12
                kernel.cov = np.diag(cov.ravel())
                M = kernel(self.__data, self.__data, normalize=True)
                return np.log((M - np.diag(np.diag(M))).mean(axis=1) + epsilon).mean().ravel()

            bo = gpbayesopt.BayesOpt(LogLikelihood,
                                     initial_input=np.atleast_2d(np.ones(self.__ndim)),
                                     alpha=1e-6,
                                     kernel=gpbayesopt.kernel.MaternKernel(),
                                     acq=gpbayesopt.acquisition.UCB,
                                     acq_optim=gpbayesopt.acquisition_optimizer.Acquisition_L_BFGS_B_LogOptimizer(bounds=np.array([[-3, 2] for i in range(self.__ndim)]), n_trial=2),
                                     maximize=True,
                                     function_input_unpacking=False)
            bo.run_optim(50)
            self._cov = np.diag(bo.best_params)
            self._inv_cov = np.linalg.inv(self._cov)
            return 1.

    @property
    def cov(self):
        return self._cov

    @property
    def inv_cov(self):
        return self._inv_cov

    @property
    def bandwidth(self):
        return np.sqrt(np.diag(self._cov).sum())

    def __repr__(self):
        val = f'Bandwidth selection method: {self.__method}\n'
        val += f'Number of data: {self.__n_data}\n'
        val += f'Dimensions: {self.__ndim}\n'
        val += f'Covariance matrix:\n {self.cov}\n'
        val += f'Bandwidth: {self.bandwidth}\n'
        return val


from itertools import groupby
from typing import Generator, List, Optional, TypeVar

from flask_sqlalchemy import SQLAlchemy
from sqlalchemy import and_

from exceptions.exceptions import ActionNotAllowed, ObjectsDuplicated
from handlers import BaseHandler
from handlers.utils import assert_name_is_valid
from models.database_models import RootTopic, Topic
from models.response_models.topic_model import RootTopicResponseModel, TopicResponseModel

SqlAlchemyModel = TypeVar('SqlAlchemyModel', bound=SQLAlchemy)

class RootTopicHandler(BaseHandler):
    _model = RootTopic

    def __init__(self, id: int = None) -> None:
        super().__init__(id)
        self.error_msg = f'Root Topic <{id}> 不存在'

    def get_topic(self) -> Generator[RootTopicResponseModel, None, None]:
        instance = self._get_sqlalchemy_instance()

        condition = and_(Topic.deleted == False, Topic.root_topic_id == self.id)
        child_topics = (TopicResponseModel(**topic.as_dict()) for topic in Topic.query.filter(condition))

        yield RootTopicResponseModel(child_topics=child_topics, **instance.as_dict())

    @staticmethod
    def sort_and_group_child_topic(
        root_topic_ids,
    ) -> Generator[List[SqlAlchemyModel], None, None]:
        child_topics = Topic.query.filter_by(deleted=False).filter(Topic.root_topic_id.in_(root_topic_ids))
        child_topics = sorted(child_topics, key=lambda x: x.root_topic_id)

        groups = {k: list(v) for k, v in groupby(child_topics, key=lambda x: x.root_topic_id)}
        yield from map(lambda k: groups.get(k, []), root_topic_ids)

    def get_topics(self) -> Generator[RootTopicResponseModel, None, None]:
        root_topics = self._model.query.filter_by(deleted=False)
        root_topic_ids = [ins.id for ins in root_topics]
        child_topics = self.sort_and_group_child_topic(root_topic_ids)

        for root_topic, topic in zip(root_topics, child_topics):
            ch_topics = (TopicResponseModel(**t.as_dict()) for t in topic)
            yield RootTopicResponseModel(child_topics=ch_topics, **root_topic.as_dict())

    def create_topic(self, **kwargs) -> Generator[RootTopicResponseModel, None, None]:
        assert_name_is_valid(message='根主题名不能为空', **kwargs)

        name = kwargs['name']
        condition = and_(self._model.deleted == False, self._model.name == name)
        instance = self._model.query.filter(condition).first()
        if instance:
            raise ObjectsDuplicated(f'名称为 <{name}> 的根 Topic 已经创建')

        instance = self._model.create(**kwargs)
        yield RootTopicResponseModel(child_topics=[], **instance.as_dict())

    def update_topic(self, **kwargs) -> Generator[RootTopicResponseModel, None, None]:
        assert_name_is_valid(message='主题名不能为空', **kwargs)
        name = kwargs['name']
        condition = and_(
            self._model.deleted == False,
            self._model.id != self.id,
            self._model.name == name,
        )
        instance = self._model.query.filter(condition).first()
        if instance:
            raise ObjectsDuplicated(f'名称为 <{name}> 的 Topic 已经创建')

        instance = self._get_sqlalchemy_instance()
        instance.update(name=name)

        yield RootTopicResponseModel(child_topics=[], **instance.as_dict())

    def delete_topic(self) -> None:
        raise ActionNotAllowed('根主题不允许被删除')


class Solution:
    def uniqueOccurrences(self, arr: List[int]) -> bool:
        map = {}
        countSet = set()

        for i in range(len(arr)):
            map[arr[i]] = 1 + map.get(arr[i], 0)

        for i in map:
            if map[i] in countSet:
                return False
            else:
                countSet.add(map[i])
        return True

Leet Code 75/Easy/1207. Unique Number of Occurrences.py


import Queue

def main():
    method, start, end, routes, heuristics = readFile("input.txt")
    if method == "BFS":
        res = bfs(start, end, routes)
    elif method == "DFS":
        res = dfs(start, end, routes, start+' 0\n', set(), set(), 1)
    elif method == "UCS":
        res = ucs(start, end, routes)
    elif method == "A*":
        res = a_star(start, end, routes, heuristics)
    else: res = ["Invalid method!"]
    f = open("output.txt", 'w')
    f.write(res)
    f.close()

def readFile(fname):
    f = open(fname, 'r')
    method = f.readline().strip()
    start = f.readline().strip()
    end = f.readline().strip()
    n_routes, routes = int(f.readline().strip()), {}
    for i in range(n_routes):
        route = f.readline().split()
        if route[0] not in routes: routes[route[0]] = []
        routes[route[0]].append((route[1], int(route[2])))
    heuristics = {}
    if method == 'A*':
        n_heu = int(f.readline().strip())
        for i in range(n_heu):
            heuristic = f.readline().split()
            heuristics[heuristic[0]] = int(heuristic[1])
    f.close()
    return (method, start, end, routes, heuristics)

def bfs(start, end, graph):
    queue, visited, res, count = Queue.Queue(), set(), "", 1
    queue.put((start, start+' 0\n', count))
    while queue:
        path = queue.get()
        state = path[0]
        visited.add(state)
        if state == end:
            return path[1]
        if state in graph:
            for nextState in graph[state]:
                newNode = nextState[0]
                if newNode not in visited:
                    newPath = path[1]+newNode+' '+str(path[2])+'\n'
                    queue.put((nextState[0], newPath, path[2]+1))
    return ["No path is detected!"]

def dfs(state, end, graph, path, visited, frontier, count):
    visited.add(state)
    if state in graph:
        neighbors = set()
        for nextState in graph[state]:
            newNode = nextState[0]
            if newNode == end:
                return path+end+' '+str(count)+'\n'
            neighbors.add(newNode)
        for nextState in graph[state]:
            newNode = nextState[0]
            if newNode not in visited and newNode not in frontier:
                newPath = path+newNode+' '+str(count)+'\n'
                newFrontier = frontier.union(neighbors)
                p = dfs(newNode, end, graph, newPath, visited, newFrontier, count+1)
                if p: return p
    if not path:
        return ["No path is detected"]

def ucs(start, end, graph):
    queue, visited, time = Queue.PriorityQueue(), set(), 0
    queue.put((0, time, start+' 0\n', start))
    while queue:
        path = queue.get()
        state = path[3]
        visited.add(state)
        if state == end:
            return path[2]
        if state in graph:
            for nextNode in graph[state]:
                newNode = nextNode[0]
                if newNode not in visited:
                    cost = path[0] + nextNode[1]
                    time += 1
                    newPath = path[2]+newNode+' '+str(cost)+'\n'
                    queue.put((cost, time, newPath, newNode))
    return ["No path is detected!"]

def a_star(start, end, graph, heus):
    queue, time, visited = Queue.PriorityQueue(), 0, {}
    queue.put((heus[start], time, start+' 0\n', start, 0))
    while queue:
        path = queue.get()
        state = path[3]
        visited[state] = path[4]
        if state == end:
            return path[2]
        if state in graph:
            for nextNode in graph[state]:
                newNode = nextNode[0]
                if newNode not in visited or visited[newNode] > path[4]+nextNode[1]:
                    heu, cost = heus[newNode], path[4] + nextNode[1]
                    time += 1
                    newPath = path[2]+newNode+' '+str(cost)+'\n'
                    queue.put((cost+heu, time, newPath, newNode, cost))
    return ["No path is detected!"]

if __name__ == "__main__":
    main()