from __future__ import print_function
import torch
import torch.nn as nn
import torch.nn.functional as F
import numpy as np
from future import standard_library
standard_library.install_aliases()

from builtins import input
from builtins import range
from builtins import object
import itertools
try:
    import MalmoPython
except ImportError:
    import malmo.MalmoPython as MalmoPython

import json
import logging
import math
import os
import random
import sys
import time
import malmoutils
import matplotlib.pyplot as plt
import plotting_1
from collections import deque, namedtuple
import numpy as np
from random import randint
# TODO:调整好maze地图
malmoutils.fix_print()
actionSet = ["movenorth 1", "movesouth 1", "movewest 1", "moveeast 1"]
size = 0
# ===========================================================================================================================
class StateProcessor():
    """
    Process a grid map state.
    """
    def __init__(self):
        pass

    def gridProcess(self, world_state):
        msg = world_state.observations[-1].text
        observations = json.loads(msg)
        grid = observations.get(u'floor13x13', 0)
        # print("observations______", observations)
        # Xpos = observations.get(u'XPos', 0)
        # Zpos = observations.get(u'ZPos', 0)
        obs = np.array(grid)
        # print(grid)
        obs = np.reshape(obs, [13, 13, 1])
        # if int(5+Zpos) > 12 or int(Xpos+5) > 12:
        #     print("Zpos", Zpos)
        #     print("Xpos", Xpos)
        # obs[6][6] = "human"
        # print((int)(5+ Zpos), (int)(Xpos+5))
        # print(obs)
        obs[obs == "air"] = 0
        obs[obs == "beacon"] = 1
        obs[obs == "glass"] = 1
        obs[obs == "carpet"] = 2
        obs[obs == "fire"] = 3
        obs[obs == "netherrack"] = 3
        obs[obs == "sea_lantern"] = 4
        obs[obs == "emerald_block"] = 5
        # obs[obs == "grass"] = 5
        # obs[obs == "human"] = 6

        return obs

    def squeeze_dim(self, state_to_be_squeezed):
        """
        Args:
            state_to_be_squeezed: [size, size, 1]
        Returns:
            state_squeezed: [size, size]
        """
        return np.squeeze(state_to_be_squeezed)

    def change2feature(self, state_to_be_changed):
        """
        Args:
            state_to_be_changed: [size, size]
        Returns:
            state_featured: [N_feature, size, size] # N_feature == 7
        """
        ft1 = np.where(state_to_be_changed=='0', 1, 0)
        ft2 = np.where(state_to_be_changed=='1', 1, 0)
        ft3 = np.where(state_to_be_changed=='2', 1, 0)
        ft4 = np.where(state_to_be_changed=="3", 1, 0)
        ft5 = np.where(state_to_be_changed=="4", 1, 0)
        ft6 = np.where(state_to_be_changed=="5", 1, 0)
        # ft7 = np.where(state_to_be_changed=="6", 1, 0)
        # ft7 = np.zeros(shape=(13, 13))
        # ft7[6][6] = 1   # 表示这里是人
        # ft8 = np.where(state_to_be_changed=="7", 1, 0)
        state_featured = np.array([ft1, ft2, ft3, ft4, ft5, ft6])
        return state_featured

class Estimator(nn.Module): # TODO:之后单独放在一个文件里
    def __init__(self, name, save_dir=None):
        super().__init__()
        self.name = name
        self.save_dir = save_dir
        # define the layers and maybe the conv layers are not so good
        self.conv1 = nn.Conv2d(6, 25, 6, 1)
        self.conv2 = nn.Conv2d(32, 16, 3, 1)
        self.flatten = nn.Flatten()
        self.fc1 = nn.Linear(25*8*8, 200) # (1024, 512)
        self.fc2 = nn.Linear(200, 64)  # (512, 256)
        self.fc3 = nn.Linear(64, len(actionSet)) # (64, len(actionSet))
        # loss
        self.loss = nn.SmoothL1Loss()
        # optimizer
        self.optimizer = torch.optim.Adam(params=self.parameters(), lr=0.01)
        self.fc1.weight.data.normal_(0, 0.1)   # 原来是0, 0.1
        self.fc2.weight.data.normal_(0, 0.1)   # 原来是0, 0.1
        self.fc3.weight.data.normal_(0, 0.1)   # 原来是0, 0.1

    def forward(self, x):
        x = self.conv1(x)
        x = F.relu(x)
        x = self.flatten(x)
        x = self.fc1(x)
        x = F.relu(x)
        x = self.fc2(x)
        x = F.relu(x)
        x = self.fc3(x)
        return x

    def save_model(self, pt_file):
        torch.save(self, f=pt_file)

    def load_model(self, pt_file):
        self = torch.load(pt_file)
        self.eval()

def copy_model_parameters(from_model, to_model):
    """
    Copies the model parameters of one estimator to another.
    Args:
      from_model: Estimator to copy the paramters from
      to_model: Estimator to copy the parameters to
    """
    to_model.load_state_dict(from_model.state_dict())

def make_epsilon_greedy_policy(estimator, nA):
    """
        Creates an epsilon-greedy policy based on a given Q-function approximator and epsilon.
        Args:
            estimator: An estimator that returns q values for a given state
            nA: Number of actions in the environment.
        Returns:
            A function that takes the (sess, state, epsilon) as an argument and returns
            the probabilities for each action in the form of a numpy array of length nA.
    """
    def policy_fn(state, epsilon):
        """
        Args:
            state: shape[4, size, size]
            epsilon: decaying with step_num
        """
        A = [0] * len(actionSet)
        # 第一步，找出最大的q_value预测值的action
        approx_q_values = estimator.forward(torch.unsqueeze(state, 0)).detach().numpy()
        max_a = np.argmax(approx_q_values)
        # 第二步，概率赋值
        ordinary_prob = epsilon / nA
        for i in range(len(actionSet)):
            A[i] = ordinary_prob

        A[max_a] += 1.0 - epsilon
        return A # 数组 1 * 4

    return policy_fn

class Mission_Loader():
    def __init__(self) -> None:
        pass

    def mission_load(self, mission_file):
        with open(mission_file, 'r') as f:
            print("Loading mission from %s" % mission_file)
            mission_xml = f.read()
            my_mission = MalmoPython.MissionSpec(mission_xml, True)
        my_mission.removeAllCommandHandlers()
        my_mission.allowAllDiscreteMovementCommands()
        my_mission.setViewpoint(2)
        return my_mission

    def start_mission(self, my_mission, agent_host, max_retries, my_clients, expID, my_mission_record, agentID):
        for retry in range(max_retries):
            try:
                agent_host.startMission(my_mission, my_clients, my_mission_record, agentID, "%s" % (expID))
                break
            except RuntimeError as e:
                if retry == max_retries - 1:
                    print("Error starting mission:", e)
                    exit(1)
                else:
                    time.sleep(2.5)

    def mission_load_by_num(self, mission_file):
        mazeNum = randint(0, 4)
        mission_file = os.path.join(mission_file, "maze%s.xml" % mazeNum)
        currentMission = mission_file
        return currentMission

    def get_world_state(self, agent_host):
        world_state = agent_host.getWorldState()
        while not world_state.has_mission_begun:
            print(".", end="")
            time.sleep(0.1)
            world_state = agent_host.getWorldState()
        agent_host.sendCommand("look -1")
        agent_host.sendCommand("look -1")
        while world_state.is_mission_running and all(e.text == '{}' for e in world_state.observations):
            world_state = agent_host.peekWorldState()
        return world_state

def show_train_loss(mean_loss, episode_num):
    try:
        train_loss_lines.remove(train_loss_lines[0])
    except Exception:
        pass
    train_loss_lines = plt.plot(episode_num, mean_loss, 'r', lw = 2)
    plt.title('train_loss')
    plt.xlabel('num_episode')
    plt.ylabel('loss')
    plt.legend(['train_loss'])
    if os.path.exists('./train_loss_img/episode_{}.jpg'.format(episode_num[-1]-1)):
        os.remove('./train_loss_img/episode_{}.jpg'.format(episode_num[-1]-1))
    with open(os.path.join('.', 'train_loss_img', 'episode_{}.jpg'.format(episode_num[-1])), 'wb') as f:
        plt.savefig(f) ## 保存图片

def show_success_rate(success_rate, episode_num_20):
    try:
        success_rate_lines.remove(success_rate_lines[0])
    except Exception:
        pass
    success_rate_lines = plt.plot(episode_num_20, success_rate, 'b', lw=2)
    plt.title('success_rate')
    plt.xlabel('num_episode')
    plt.ylabel('success_rate')
    plt.legend(['success_rate'])
    if os.path.exists('./success_rate/episode_{}.jpg'.format(episode_num_20[-1]-20)):
        os.remove('./success_rate/episode_{}.jpg'.format(episode_num_20[-1]-20))
    with open(os.path.join('.', 'success_rate', 'episode_{}.jpg'.format(episode_num_20[-1])), 'wb') as f:
        plt.savefig(f)

def deep_q_learning(agent_host,
                    q_estimator,
                    target_estimator,
                    state_processor,
                    num_episodes,
                    experiment_dir,
                    replay_memory_size=50000,
                    replay_memory_init_size=5000,
                    update_target_estimator_every=1000,
                    discount_factor=0.99,
                    epsilon_start=1.0,
                    epsilon_end=0.1,
                    epsilon_decay_steps=8000,
                    batch_size=32,
                    record_video_every=100):
    """
    Q-Learning algorithm for off-policy TD control using Function Approximation.
    Finds the optimal greedy policy while following an epsilon-greedy policy.
    Args:
        q_estimator: Estimator object used for the q values
        target_estimator: Estimator object used for the targets
        state_processor: A StateProcessor object
        num_episodes: Number of episodes to run for
        experiment_dir: Directory to save Tensorflow summaries in
        replay_memory_size: Size of the replay memory
        replay_memory_init_size: Number of random experiences to sample when initializing
          the reply memory.
        update_target_estimator_every: Copy parameters from the Q estimator to the
          target estimator every N steps
        discount_factor: Gamma discount factor
        epsilon_start: Chance to sample a random action when taking an action.
          Epsilon is decayed over time and this is the start value
        epsilon_end: The final minimum value of epsilon after decaying is done
        epsilon_decay_steps: Number of steps to decay epsilon over
        batch_size: Size of batches to sample from the replay memory
        record_video_every: Record a video every N episodes
    Returns:
        An EpisodeStats object with two numpy arrays for episode_lengths and episode_rewards.
    """
    mission_loader = Mission_Loader()

    mission_file = agent_host.getStringArgument('mission_file')
    mission_file = os.path.join(mission_file, "maze0.xml")
    currentMission = mission_file
    my_mission = mission_loader.mission_load(mission_file=mission_file)

    my_clients = MalmoPython.ClientPool()
    my_clients.add(MalmoPython.ClientInfo('127.0.0.1', 10000))  # add Minecraft machines here as available

    max_retries = 3
    agentID = 0
    total_t = 0     # 在一个episode中的total_t
    expID = 'Deep_q_learning memory'

    Transition = namedtuple("Transition", ["state", "action", "reward", "next_state", "done"])

    # The replay memory
    replay_memory = []

    # Keeps track of useful statistics
    stats = plotting_1.EpisodeStats(
        episode_lengths=np.zeros(num_episodes),
        episode_rewards=np.zeros(num_episodes))

    # Create directories for checkpoints and summaries
    checkpoint_dir = os.path.join(experiment_dir, "checkpoints")
    checkpoint_path = os.path.join(checkpoint_dir, "model")
    monitor_path = os.path.join(experiment_dir, "monitor")
    train_loss_dir = os.path.join('.', 'train_loss_img')
    success_rate_dir = os.path.join('.', 'success_rate')

    if not os.path.exists(checkpoint_dir):
        os.makedirs(checkpoint_dir)
    if not os.path.exists(monitor_path):
        os.makedirs(monitor_path)
    if not os.path.exists(train_loss_dir):
        os.makedirs(train_loss_dir)
    if not os.path.exists(success_rate_dir):
        os.makedirs(success_rate_dir)
    # Create save_dir
    save_dir = os.path.abspath("./save")
    if not os.path.exists(save_dir):
        os.makedirs(save_dir)

    save_file = os.path.join(save_dir, 'train_pytorch_q_net(2).pt')

    # The epsilon decay schedule
    epsilons = np.linspace(epsilon_start, epsilon_end, epsilon_decay_steps)

    # The policy we're following
    policy = make_epsilon_greedy_policy(
        q_estimator,
        len(actionSet))

    my_mission_record = malmoutils.get_default_recording_object(agent_host,
                                                                "save_%s-rep" % (expID))
    # start mission
    mission_loader.start_mission(my_mission=my_mission, agent_host=agent_host,
                                 max_retries=max_retries, my_clients=my_clients,
                                 expID=expID, my_mission_record=my_mission_record,
                                 agentID=agentID)

    world_state = agent_host.getWorldState()
    while not world_state.has_mission_begun:
        print(".", end="")
        time.sleep(0.1)
        print("Sleeping")
        world_state = agent_host.getWorldState()
        for error in world_state.errors:
            print("Error:", error.text)
    print()
    agent_host.sendCommand("look -1")
    agent_host.sendCommand("look -1")
    print("Populating replay memory...")

    while world_state.is_mission_running and all(e.text == '{}' for e in world_state.observations):
        print("Sleeping....")
        world_state = agent_host.peekWorldState()

    # Populate the replay memory with initial experience

    while world_state.number_of_observations_since_last_state <= 0 and world_state.is_mission_running:
        # print("Sleeping")
        time.sleep(0.1)
        world_state = agent_host.peekWorldState()

    state = state_processor.gridProcess(world_state)  # MALMO ENVIRONMENT Grid world NEEDED HERE/ was env.reset()
    state = state_processor.squeeze_dim(state)
    state = state_processor.change2feature(state)

    ###############################################################################
    # 预先填充replay容器
    ###############################################################################
    for i in range(replay_memory_init_size):
        print("%s th replay memory" % i)
        mission_file = agent_host.getStringArgument('mission_file')
        if i % 20 == 0:
            currentMission = mission_file = mission_loader.mission_load_by_num(mission_file)
        else:
            mission_file = currentMission

        print("Mission File:", mission_file)

        # 生成动作概率、选择动作、执行动作
        action_probs = policy(torch.from_numpy(state.astype('float32')), epsilons[min(total_t, epsilon_decay_steps - 1)])
        action = np.random.choice(np.arange(len(action_probs)), p=action_probs)
        agent_host.sendCommand(actionSet[action])

        # 观察执行后状态
        world_state = agent_host.peekWorldState()
        num_frames_seen = world_state.number_of_video_frames_since_last_state

        # 观察是否完成了状态转移/执行完动作
        while world_state.is_mission_running and world_state.number_of_video_frames_since_last_state == num_frames_seen:
            world_state = agent_host.peekWorldState()
        # done 获取方法：判断是否mission还在执行中
        done = not world_state.is_mission_running

        # 如果mission未结束
        if world_state.is_mission_running:
            # Getting the reward from taking a step, 重新判断world_state
            while world_state.number_of_rewards_since_last_state <= 0:
                time.sleep(0.1)
                world_state = agent_host.peekWorldState()
            # reward~!!
            reward = world_state.rewards[-1].getValue()
            print("1)Just received the reward: %s on action: %s " % (reward, actionSet[action]))

            while world_state.is_mission_running and all(e.text == '{}' for e in world_state.observations):
                world_state = agent_host.peekWorldState()

            # 如果已经done了
            if not world_state.is_mission_running:
                # next_state
                next_state = state
                # done
                done = not world_state.is_mission_running
                print("1)Action: %s, Reward: %s, Done: %s" % (actionSet[action], reward, done))
                # add replay_memory
                replay_memory.append(Transition(state, action, reward, next_state, done))

                # restart mission for next round of memory generation
                my_mission = mission_loader.mission_load(mission_file=mission_file)
                mission_loader.start_mission(my_mission=my_mission, agent_host=agent_host,
                                             max_retries=max_retries, my_clients=my_clients,
                                             expID=expID, my_mission_record=my_mission_record,
                                             agentID=agentID)

                # get new world_state for next new start state
                world_state = mission_loader.get_world_state(agent_host=agent_host)
                state = state_processor.gridProcess(world_state)  # Malmo GetworldState? / env.reset()
                state = state_processor.squeeze_dim(state)
                state = state_processor.change2feature(state)
                # state = np.stack([state] * 4, axis=0)   # shape of [4, size, size]
                # state = np.expand_dims(state, 0)

            # if not done
            else:
                # next_state
                next_state = state_processor.gridProcess(world_state)
                next_state = state_processor.squeeze_dim(next_state)
                next_state = state_processor.change2feature(next_state)
                # next_state = np.append(state[1:, :, :], np.expand_dims(next_state, 0), axis=0)
                # next_state = np.expand_dims(next_state, 0)
                # done
                done = not world_state.is_mission_running
                print("1)Action: %s, Reward: %s, Done: %s" % (actionSet[action], reward, done))
                # add replay_memory
                replay_memory.append(Transition(state, action, reward, next_state, done))

                # update state
                state = next_state

        # 如果mission结束了
        else:
            # reward
            if len(world_state.rewards) > 0:
                reward = world_state.rewards[-1].getValue()
            else:
                reward = 0

            # next_state
            next_state = state

            # done
            done = not world_state.is_mission_running

            print("2)Just received the reward: %s on action: %s " % (reward, actionSet[action]))
            print("2)Action: %s, Reward: %s, Done: %s" % (actionSet[action], reward, done))

            # 加入经验值
            replay_memory.append(Transition(state, action, reward, next_state, done))

            # restart mission for next round of memory generation
            my_mission = mission_loader.mission_load(mission_file=mission_file)
            mission_loader.start_mission(my_mission=my_mission, agent_host=agent_host,
                                            max_retries=max_retries, my_clients=my_clients,
                                            expID=expID, my_mission_record=my_mission_record,
                                            agentID=agentID)

            # get new world_state for next new start state
            world_state = mission_loader.get_world_state(agent_host=agent_host)
            state = state_processor.gridProcess(world_state)  # Malmo GetworldState? / env.reset()
            state = state_processor.squeeze_dim(state)
            state = state_processor.change2feature(state)
        total_t += 1
    print("Finished populating memory")

    #######################################################################################
    # 正式训练
    #######################################################################################
    mean_loss = []
    episode_num = []
    currentMission = mission_file
    num_success = 0
    num_20 = 0
    success_rate = []
    for i_episode in range(num_episodes):
        print("%s-th episode" % i_episode)
        episode_num.append(i_episode+1)

        # Start mission if not the first episode
        if i_episode != 0:
            mission_file = agent_host.getStringArgument('mission_file')
            if i_episode%20 == 0:
                num_success = num_20 = 0
                currentMission = mission_file = mission_loader.mission_load_by_num(mission_file)
            else:
                mission_file = currentMission
            my_mission = mission_loader.mission_load(mission_file=mission_file)
            my_mission.forceWorldReset()
            my_mission.setViewpoint(2)
            my_clients = MalmoPython.ClientPool()
            my_clients.add(MalmoPython.ClientInfo('127.0.0.1', 10000))  # add Minecraft machines here as available

            max_retries = 3
            agentID = 0
            expID = 'Deep_q_learning '
            my_mission_record = malmoutils.get_default_recording_object(agent_host,
                                                                        "save_%s-rep%d" % (expID, i))
            for retry in range(max_retries):
                try:
                    agent_host.startMission(my_mission, my_clients, my_mission_record, agentID, "%s-%d" % (expID, i))
                    break
                except RuntimeError as e:
                    if retry == max_retries - 1:
                        print("Error starting mission:", e)
                        exit(1)
                    else:
                        time.sleep(2.5)
            # restart mission and get world_state
            world_state = agent_host.getWorldState()
            print("Waiting for the mission to start", end=' ')
            while not world_state.has_mission_begun:
                print(".", end="")
                time.sleep(0.1)
                world_state = agent_host.getWorldState()
                for error in world_state.errors:
                    print("Error:", error.text)
        agent_host.sendCommand("look -1")
        agent_host.sendCommand("look -1")
        # 获取初始状态state
        while world_state.is_mission_running and all(e.text == '{}' for e in world_state.observations):
            print("Sleeping....")
            world_state = agent_host.peekWorldState()
        state = state_processor.gridProcess(world_state)  # Malmo GetworldState? / env.reset()
        state = state_processor.squeeze_dim(state)
        state = state_processor.change2feature(state)

        # loss初始化
        loss = None
        total_loss = 0

        # One step in the environment
        for t in itertools.count():
            total_t += 1

            # Epsilon for this time step
            epsilon = epsilons[min(total_t, epsilon_decay_steps - 1)]

            # Maybe update the target estimator
            if total_t % update_target_estimator_every == 0:
                copy_model_parameters(q_estimator, target_estimator)
                print("\nCopied model parameters to target network.")

            # Print out which step we're on, useful for debugging.
            print("\rStep {} ({}) @ Episode {}/{}, loss: {}".format(
                t, total_t, i_episode + 1, num_episodes, loss), end="")
            # sys.stdout.flush()
            if loss != None:
                total_loss += loss
            # 生成动作概率、选择动作、执行动作
            action_probs = policy(torch.from_numpy(state.astype('float32')), epsilon)
            action = np.random.choice(np.arange(len(action_probs)), p=action_probs)
            agent_host.sendCommand(actionSet[action])

            world_state = agent_host.peekWorldState()

            num_frames_seen = world_state.number_of_video_frames_since_last_state
            # 判断是否通过动作变化，成功转移了状态
            while world_state.is_mission_running and world_state.number_of_video_frames_since_last_state == num_frames_seen:
                world_state = agent_host.peekWorldState()

            done = not world_state.is_mission_running
            print(" IS MISSION FINISHED? ", done)

            # 如果还没有停止当前的mission
            if world_state.is_mission_running:
                while world_state.number_of_rewards_since_last_state <= 0:
                    time.sleep(0.1)
                    world_state = agent_host.peekWorldState()
                reward = world_state.rewards[-1].getValue()
                while world_state.is_mission_running and all(e.text == '{}' for e in world_state.observations):
                    world_state = agent_host.peekWorldState()
                # 如果还在运行，则从正在运行的世界环境中读取新状态
                if world_state.is_mission_running:
                    next_state = state_processor.gridProcess(world_state)
                    next_state = state_processor.squeeze_dim(next_state)
                    next_state = state_processor.change2feature(next_state)
                    # next_state = np.append(state[1:, :, :], np.expand_dims(next_state, 0), axis=0)  # TODO:这里为啥是append(state[::1:])
                    # next_state = np.expand_dims(next_state, 0)
                # 如果没有在运行，则当前状态就是下一个状态，同时标记done=True
                else:
                    print("Mission finished prematurely")
                    next_state = state
                    done = not world_state.is_mission_running

                # If our replay memory is full, pop the first element
                if len(replay_memory) == replay_memory_size:
                    replay_memory.pop(0)
                # Save transition to replay memory
                replay_memory.append(Transition(state, action, reward, next_state, done))
                # Update statistics
                stats.episode_rewards[i_episode] += reward
                stats.episode_lengths[i_episode] = t

                ##############
                # 训练
                ##############
                samples = random.sample(replay_memory, batch_size)
                states_batch, action_batch, reward_batch, next_states_batch, done_batch = map(np.array, zip(*samples))
                # all get shape of [batch_size, ?(, ...)]

                q_values_next = q_estimator.forward(torch.from_numpy(next_states_batch.astype('float32'))).detach().numpy()
                # print()
                # print(q_values_next)
                # print()
                best_actions = np.argmax(q_values_next, axis=1)
                # 我们设计target_q值时，是选择的下一个状态的最大value
                # 在DQN中，下一个状态的最大value直接使用target_net来计算并取所有动作对应q值最大者
                # 在DDQN中，为避免估计得到的target值过大，会改为：先用动态更新的q_eval_net来找到下一个状态的最优动作
                #   然后使用target_net来估计当前状态的所有动作对应的q值，然后索引所找到的下一个状态的最优动作对应的target_q值，进而
                # 更新target
                q_values_next_target = target_estimator.forward(torch.from_numpy(next_states_batch.astype('float32')))
                targets_batch = torch.from_numpy(reward_batch.astype('float32')) + torch.from_numpy(np.invert(done_batch).astype(np.float32)) * \
                                discount_factor * q_values_next_target[np.arange(batch_size), best_actions]
                states_batch = np.array(states_batch)
                old_values_batch = q_estimator.forward(torch.from_numpy(states_batch.astype('float32')))[np.arange(batch_size), action_batch]
                # optimizer
                q_estimator.optimizer.zero_grad()
                # loss
                loss = q_estimator.loss(targets_batch, old_values_batch)
                loss.backward()
                q_estimator.optimizer.step()

            if done:
                # get reward
                if len(world_state.rewards)>0:
                    reward = world_state.rewards[-1].getValue()
                    if int(reward) > 200:
                        num_success += 1
                else:
                    print("IDK no reward")
                    reward= 0
                print("Just received the reward: %s on action: %s " % (reward, actionSet[action]))

                # 当前状态即作为下一个状态
                next_state = state

                # 放入memory
                if len(replay_memory) == replay_memory_size:
                    replay_memory.pop(0)
                replay_memory.append(Transition(state, action, reward, next_state, done))

                stats.episode_rewards[i_episode] += reward
                stats.episode_lengths[i_episode] = t

                samples = random.sample(replay_memory, batch_size)
                states_batch, action_batch, reward_batch, next_states_batch, done_batch = map(np.array, zip(*samples))
                # 训练！！
                q_values_next = q_estimator.forward(torch.from_numpy(next_states_batch.astype('float32'))).detach().numpy()
                best_actions = np.argmax(q_values_next, axis=1)
                # 我们设计target_q值时，是选择的下一个状态的最大value
                # 在DQN中，下一个状态的最大value直接使用target_net来计算并取所有动作对应q值最大者
                # 在DDQN中，为避免估计得到的target值过大，会改为：先用动态更新的q_eval_net来找到下一个状态的最优动作
                #   然后使用target_net来估计当前状态的所有动作对应的q值，然后索引所找到的下一个状态的最优动作对应的target_q值，进而
                # 更新target
                q_values_next_target = target_estimator.forward(torch.from_numpy(next_states_batch.astype('float32')))
                targets_batch = torch.from_numpy(reward_batch.astype('float32')) + torch.from_numpy(np.invert(done_batch).astype(np.float32)) * \
                                discount_factor * q_values_next_target[np.arange(batch_size), best_actions]
                states_batch = np.array(states_batch)
                old_values_batch = q_estimator.forward(torch.from_numpy(states_batch.astype('float32')))[np.arange(batch_size), action_batch]
                # optimizer
                q_estimator.optimizer.zero_grad()
                # loss
                loss = q_estimator.loss(targets_batch, old_values_batch)
                loss.backward()
                q_estimator.optimizer.step()
                if t != 0:
                    mean_loss.append(float(total_loss / t))
                show_train_loss(mean_loss=mean_loss, episode_num=episode_num)
                num_20 += 1
                print('----------success_rate in episode {0}/20: {1}%----------'.format(num_20, num_success / num_20 * 100))
                print("End of Episode")
                break

        # 训练结束，保存模型
        if i_episode == num_episodes - 1:
            q_estimator.save_model(save_file)

        yield total_t, plotting_1.EpisodeStats(
            episode_lengths=stats.episode_lengths[:i_episode + 1],
            episode_rewards=stats.episode_rewards[:i_episode + 1])

    return stats

# Main body=======================================================
if __name__ == '__main__':
    agent_host = MalmoPython.AgentHost()

    # Find the default mission file by looking next to the schemas folder:
    schema_dir = None
    try:
        # schema_dir = os.environ['mazes']
        schema_dir = "maze"
    except KeyError:
        print("MALMO_XSD_PATH not set? Check environment.")
        exit(1)
    mission_file = os.path.abspath(schema_dir)  # Integration test path
    if not os.path.exists(mission_file):
        print("Could not find Maze.xml under MALMO_XSD_PATH")
        exit(1)

    # add some args
    agent_host.addOptionalStringArgument('mission_file',
                                        'Path/to/file from which to load the mission.', mission_file)
    agent_host.addOptionalFlag('load_model', 'Load initial model from model_file.')
    agent_host.addOptionalStringArgument('model_file', 'Path to the initial model file', '')
    agent_host.addOptionalFlag('debug', 'Turn on debugging.')
    agent_host.setRewardsPolicy(MalmoPython.RewardsPolicy.LATEST_REWARD_ONLY)
    agent_host.setObservationsPolicy(MalmoPython.ObservationsPolicy.LATEST_OBSERVATION_ONLY)
    malmoutils.parse_command_line(agent_host)

    # Where we save our checkpoints and graphs
    experiment_dir = os.path.abspath("./experiments/{}".format("DeepQLearning"))

    # Create estimators
    q_estimator = Estimator(name="q", save_dir=experiment_dir)
    target_estimator = Estimator(name="target_q")

    # State processor
    state_processor = StateProcessor()
    for t, stats in deep_q_learning(agent_host,
                                    q_estimator,
                                    target_estimator,
                                    state_processor,
                                    num_episodes=500,
                                    experiment_dir=experiment_dir,
                                    replay_memory_size=10000,    # 改为2000？
                                    replay_memory_init_size=50,    # 改为500？
                                    update_target_estimator_every=100,
                                    discount_factor=0.99,
                                    epsilon_start=0.2,
                                    epsilon_end=0.1,
                                    epsilon_decay_steps=8000,
                                    batch_size=32,
                                    record_video_every=100):
        # 迭代器返回
        print("Episode {0}'s Reward is: {1}".format(t, stats.episode_rewards[-1]))

    # something to write here
    # ======================================================================================


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

import os
import logging
import pandas as pd
from .binner import Binner
from .binner import IterBinner
from sklearn.cluster import DBSCAN
import warnings
warnings.filterwarnings(action='ignore', category=DeprecationWarning)

_logger = logging.getLogger("BlendIt")

class BinnerDBSCAN(Binner):

    name = 'dbscan'

    def bin(self, eps=0.5, min_samples=3, metric='euclidean', metric_params=None, algorithm='auto', leaf_size=30,
            p=None, n_jobs=10, *args, **kwargs):
        """ dbscan clustering
        """
        clusterer = DBSCAN(eps=eps, min_samples=min_samples, metric=metric, metric_params=metric_params,
                           algorithm=algorithm, leaf_size=leaf_size, p=p, n_jobs=n_jobs)
        cluster_labels = clusterer.fit_predict(self.embedding_df)
        cluster_df = pd.DataFrame(data=cluster_labels.transpose(),
                                  columns=['cluster'],
                                  index=self.embedding_df.index)
        # write output
        output_cluster_file = os.path.join(self.output_dir, self.cluster_file)
        cluster_df.to_csv(output_cluster_file, sep="\t", header=True, index=True)

        return cluster_df

def iterative_dbscan_clustering(embeddings, assembly, contig_length_file, output_dir, prefix, force=False,
                                min_length_x=2000, min_length_y=10000, length_step=1000, binner_params={}):

    binner_param_dict = {'eps': 0.5, 'min_samples': 3, 'metric': 'euclidean',
                         'metric_params': None, 'algorithm': 'auto',
                         'leaf_size': 30, 'p': None, 'n_jobs': 10}
    binner_param_dict.update(binner_params)

    # initialize IterBinner instance
    iterbinner = IterBinner(binner_cls=BinnerDBSCAN, embeddings=embeddings, assembly=assembly,
                            contig_length_file=contig_length_file, output_dir=output_dir,
                            prefix=prefix, force=force, min_length_x=min_length_x, min_length_y=min_length_y,
                            length_step=length_step, binner_param_dict=binner_param_dict)

    # run iterbinner
    scaffold2bin_files, bin_folders = iterbinner()

    return scaffold2bin_files, bin_folders


'''
Created on Mar 24, 2010

@author: hrabe
'''

from pytom.basic.structures import PyTomClass

class CorrelationVector(PyTomClass):
    """
    CorrelationVector: Stores a vector of correlation values of one particle with many others from particle list
    @todo: Add unittest
    """

    def __init__(self,particle=None,particleList=None,particleIndex=None):
        self._correlations = []
        self._particle = particle
        self._particleList = particleList
        self._particleIndex = particleIndex

    def append(self,value):
        self._correlations.append(value)

    def getParticleIndex(self):
        return self._particleIndex

    def __len__(self):
        return len(self._correlations)

    def __getitem__(self,key):
        """
        """
        if isinstance(key, int):
            if key < len(self):
                return self._correlations[key]
            else:
                raise IndexError('Index out of range.')
        else:
            assert False

    def toXML(self):
        """
        toXML : Compiles a XML file from result object
        rtype : L{lxml.etree._Element}
        @author: Thomas Hrabe
        """
        from lxml import etree

        vectorElement = etree.Element("CorrelationVector",ParticleIndex = self._particleIndex.__str__())

        vectorElement.append(self._particle.toXML())
        vectorElement.append(self._particleList.toXML())

        for i in range(len(self._correlations)):

            valueElement = etree.Element("Correlation",Index=i.__str__(),Value=self._correlations[i].__str__())

            vectorElement.append(valueElement)

        return vectorElement

    def fromXML(self,xmlObj):
        """
        fromXML : Assigns values to job attributes from XML object
        @param xmlObj: A xml object
        @type xmlObj: L{lxml.etree._Element}
        @author: Thomas Hrabe
        """
        from lxml.etree import _Element,tostring

        if xmlObj.__class__ != _Element:
            raise ParameterError('You must provide a valid XML-CorrelationVector object.')

        from pytom.basic.structures import Particle,ParticleList

        self._particleIndex = int(xmlObj.get('ParticleIndex'))

        particleObject = xmlObj.xpath('Particle')
        self._particle = Particle('.')
        self._particle.fromXML(particleObject[0])

        particleListObject = xmlObj.xpath('ParticleList')
        self._particleList = ParticleList('/')
        self._particleList.fromXML(particleListObject[0])

        values = xmlObj.xpath('Correlation')

        self._correlations = [0  for _ in range(len(values))]

        for v in values:

            index = int(v.get('Index'))
            self._correlations[index] = float(v.get('Value'))

class CorrelationVectorJob(PyTomClass):
    """
    CorrelationVectorJob: All settings needed for a correlation vector job. Explore class for more info.
    """

    def __init__(self,particle=None,particleList=None,mask=None,particleIndex = None,applyWedge = True,binningFactor=0,lowestFrequency=-1,highestFrequency=-1):
        """
        __init__:
        @param particle: Particle
        @type particle: pytom.alignment.structures.Particle
        @param particleList: ParticleList of all particles will be correlated with self._particle
        @type particleList: pytom.alignment.structures.ParticleList
        @param mask: Mask used for correlation
        @type mask: str
        @param applyWedge: Apply wedge during correlation. True by default, disable for rotation classification.
        @type applyWedge: Bool
        @param binningFactor: Binning factor accroding to libtomc definition. 0 by default.
        @type binningFactor: unsigned int
        @param lowestFrequency: Lowest frequency for bandpass in nyquist
        @type lowestFrequency: float
        @param highestFrequency: Highest frequency for bandpass in nyquist
        @type highestFrequency: float
        """
        from pytom.basic.structures import Particle,ParticleList,Mask

        if particle and particle.__class__ != Particle:
            raise ParameterError('You must provide a Particle object.')

        if particleList and particleList.__class__ != ParticleList:
            raise ParameterError('You must provide a ParticleList object.')

        self._particle = particle
        self._particleList = particleList

        if not mask:
            mask = Mask()
        elif mask.__class__ == str:
            mask = Mask(mask)
        elif mask.__class__ != Mask:
            from pytom.basic.exceptions import ParameterError
            raise ParameterError('Mask must be a string or Mask object!')

        self._mask = mask
        self._particleIndex = particleIndex
        self._applyWedge = applyWedge
        self._binningFactor = binningFactor
        self._lowestFrequency = lowestFrequency
        self._highestFrequency = highestFrequency

    def getMask(self):
        return self._mask

    def getParticle(self):
        return self._particle

    def getParticleList(self):
        return self._particleList

    def getParticleIndex(self):
        return self._particleIndex

    def getApplyWedge(self):
        return self._applyWedge

    def getBinning(self):
        return self._binningFactor

    def getLowestFrequency(self):
        return self._lowestFrequency

    def getHighestFrequency(self):
        return self._highestFrequency

    def toXML(self):
        """
        toXML : Compiles a XML object from result object
        rtype : L{lxml.etree._Element}
        @author: Thomas Hrabe
        """

        from lxml import etree

        jobElement = etree.Element('CorrelationVectorJob',ParticleIndex = self._particleIndex.__str__(),ApplyWedge=self._applyWedge.__str__(),Binning = self._binningFactor.__str__(),LowestFrequency = str(self._lowestFrequency),HighestFrequency = str(self._highestFrequency))

        jobElement.append(self._particle.toXML())
        jobElement.append(self._particleList.toXML())
        jobElement.append(self._mask.toXML())

        return jobElement

    def fromXML(self,xmlObj):
        """
        fromXML : Assigns values to job attributes from XML object
        @param xmlObj: A xml object
        @type xmlObj: L{lxml.etree._Element}
        @author: Thomas Hrabe
        """
        from lxml.etree import _Element

        if xmlObj.__class__ != _Element:
            raise ParameterError('You must provide a valid XML-CorrelationVectorJob object.')

        from pytom.basic.structures import Particle,ParticleList,Mask

        particleObject = xmlObj.xpath('Particle')
        self._particle = Particle('.')
        self._particle.fromXML(particleObject[0])

        particleListObject = xmlObj.xpath('ParticleList')
        self._particleList = ParticleList('/')
        self._particleList.fromXML(particleListObject[0])

        maskObject = xmlObj.xpath('Mask')[0]
        self._mask = Mask()
        self._mask.fromXML(maskObject)

        self._particleIndex = xmlObj.get('ParticleIndex')
        self._applyWedge = xmlObj.get('ApplyWedge') == 'True'
        self._binningFactor = float(xmlObj.get('Binning'))

        self._lowestFrequency = float(xmlObj.get('LowestFrequency'))
        self._highestFrequency = float(xmlObj.get('HighestFrequency'))

class CorrelationMatrixJob(PyTomClass):
    """
    CorrelationVectorJob: Represents all settings for a correlation matrix job. Explore the class for further information
    """

    def __init__(self,particleList=None,mask='',resultMatrixName='',applyWedge = True,binningFactor=0,lowestFrequency=-1,highestFrequency=-1):
        """
        __init__:
        @param particleList: ParticleList of all particles that will be correlated
        @type particleList: L{pytom.basic.structures.ParticleList}
        @param mask: Mask used for correlation
        @type mask: str or L{pytom.basic.structures.Mask}
        @param resultMatrixName: Result filename
        @type resultMatrixName: str
        @param applyWedge: Apply wedge weighting if available?
        @type applyWedge: boolean, False by default
        @param binningFactor: Binning factor accroding to libtomc definition. 0 by default.
        @type binningFactor: unsigned int
        @param lowestFrequency: Lowest frequency for bandpass in nyquist
        @type lowestFrequency: float
        @param highestFrequency: Highest frequency for bandpass in nyquist
        @type highestFrequency: float
        """
        from pytom.basic.structures import ParticleList,Mask
        from pytom.tools.files import checkFileExists

        if not particleList:
            particleList = ParticleList('/')
        elif particleList.__class__ != ParticleList:
            raise ParameterError('You must provide a ParticleList object!')

        self._particleList = particleList

        if mask.__class__ == str:
            mask = Mask(mask)
        elif mask.__class__ != Mask:
            raise ParameterError('Mask must be a string or Mask object!')

        self._mask = mask
        self._resultMatrixName = resultMatrixName
        self._applyWedge = applyWedge
        self._binningFactor = binningFactor
        self._lowestFrequency = lowestFrequency
        self._highestFrequency = highestFrequency

    def getParticleList(self):
        return self._particleList

    def getMask(self):
        return self._mask

    def getResultMatrixName(self):
        return self._resultMatrixName

    def getApplyWedge(self):
        return self._applyWedge

    def getBinning(self):
        return self._binningFactor

    def getLowestFrequency(self):
        return self._lowestFrequency

    def getHighestFrequency(self):
        return self._highestFrequency

    def toXML(self):
        """
        toXML : Compiles a XML object from result object
        rtype : L{lxml.etree._Element}
        @author: Thomas Hrabe
        """
        from lxml import etree

        jobElement = etree.Element('CorrelationMatrixJob',ResultMatrixName = self._resultMatrixName, ApplyWedge=self._applyWedge.__str__(),Binning=self._binningFactor.__str__(),LowestFrequency = str(self._lowestFrequency),HighestFrequency = str(self._highestFrequency))

        jobElement.append(self._particleList.toXML())

        jobElement.append(self._mask.toXML())

        return jobElement

    def fromXML(self,xmlObj):
        """
        fromXML : Assigns values to job attributes from XML object
        @param xmlObj: A xml object
        @type xmlObj: L{lxml.etree._Element}
        @author: Thomas Hrabe
        """
        from lxml.etree import _Element

        if xmlObj.__class__ != _Element:
            raise ParameterError('You must provide a valid XML-CorrelationMatrixJob object.')

        from pytom.basic.structures import ParticleList,Mask

        particleListObject = xmlObj.xpath('ParticleList')
        self._particleList = ParticleList('/')
        self._particleList.fromXML(particleListObject[0])

        maskObject = xmlObj.xpath('Mask')[0]
        self._mask = Mask()
        self._mask.fromXML(maskObject)

        self._resultMatrixName = xmlObj.get('ResultMatrixName')
        self._applyWedge = xmlObj.get('ApplyWedge') == 'True'
        self._binningFactor = float(xmlObj.get('Binning'))

        self._lowestFrequency = float(xmlObj.get('LowestFrequency'))
        self._highestFrequency = float(xmlObj.get('HighestFrequency'))

    def toHTMLFile(self,filename):
        """
        toHTMLFile: Overrides parent method and stores CorrelationMatrixJob to HMTL
        @param filename: HTML filename
        """
        from lxml import etree
        import io
        from pytom.tools.files import getPytomPath,readStringFile

        pytomPath = getPytomPath()

        xsltString = readStringFile(pytomPath + '/xslt/CorrelationMatrix.xsl')

        xsltStringIO = io.StringIO(xsltString)

        selfHTML = self.xsltTransform(xsltStringIO)

        htmlString = etree.tostring(selfHTML,pretty_print=True)

        file = open(filename, "w")

        file.write(htmlString)

        file.close()


import argparse
import codecs
import multiprocessing as mp
from pathlib import Path
from typing import *

import dask.bag as db
import pandas as pd
from dask.diagnostics import ProgressBar

parser = argparse.ArgumentParser(
    description="Converts tagged files by tagger toyger to dataframe with an id and lemmas")
parser.add_argument("--dir", help="Str path to zip file")
parser.add_argument("--out", help="Output file name with `p` extension")

args = parser.parse_args()

def parse_path(path: Path) -> Dict[str, List[str]]:
    tweet_id = path.name.split(".")[0]
    with codecs.open(path.as_posix(), encoding='utf-8') as f:
        file_content = f.read().strip().replace("'", "").replace('"', "")
    try:
        frame = pd.read_csv(pd.compat.StringIO(file_content), quotechar="'", sep="\t", header=None)
        frame = frame[frame[4] != "interp"]
        frame = frame.drop_duplicates(subset=[1])
        frame[3] = frame[3].map(lambda x: str(x).lower().split(':')[0])
        return {
            "id_str": tweet_id,
            "lemmas": frame[3].tolist()
        }
    except:
        print(file_content)
        print(tweet_id)
        return {
            "id_str": "",
            "lemmas": []
        }

def main():
    paths = list(Path(args.dir).rglob("*.txt"))
    pbar = ProgressBar()
    pbar.register()
    a_bag = db.from_sequence(paths, npartitions=mp.cpu_count())
    a_bag = a_bag.map(lambda a_path: parse_path(a_path))
    frame_data = a_bag.compute()
    pbar.unregister()

    frame = pd.DataFrame(frame_data)
    frame.to_pickle(args.out)

if __name__ == '__main__':
    main()


from django.conf import settings
from django.core.management.base import BaseCommand, CommandError
from django.urls import reverse

from flowers_agent.messenger_bot.helpers import FbMeProfileAPI

class Command(BaseCommand):
    '''
    Reference https://developers.facebook.com/docs/messenger-platform/reference/messenger-profile-api/domain
    -whitelisting
    '''
    help = 'Set messenger whitelist urls'

    def handle(self, *args, **options):
        api = FbMeProfileAPI(getattr(settings, 'MESSENGER_ACCESS_TOKEN'))
        payload = {
            "whitelisted_domains": [
                settings.PUBLIC_URL
            ]
        }
        result = api.post(json=payload)
        if result.get('result') == 'success':
            self.stdout.write(self.style.SUCCESS('Successfully set whitelist domains.'))
        else:
            self.stderr.write(self.style.ERROR('Something went wrong. Details: ${}'.format(result)))


#coding:cp1251
#Напишите программу, которая принимает на вход координаты двух точек
#и находит расстояние между ними в 2D пространстве.

#Пример:

#- A (3,6); B (2,1) -> 5,09
#- A (7,-5); B (1,-1) -> 7,21

def Get_Distance(coord):
    result = ((coord[2] - coord[0])**2 + (coord[3] - coord[1])**2)**0.5
    return result

letters = ['X1','Y1','X2','Y2']
coord_list = []
for i in range(len(letters)):
    coord_list.append(float(input(f'Введите координату {letters[i]}: ')))

distance = Get_Distance(coord_list)
print(f'Расстояние между точками А({coord_list[0]}, {coord_list[1]}) и B({coord_list[2]}, {coord_list[3]})  = ', '{:.2f}'.format(distance))


import os
import subprocess

def get_full_path(self, partial):
    if partial.startswith("/"):
        partial = partial[1:]
    path = os.path.join(self.root, partial)

    return path

def execute(cmd):
    """Executes a command

    :return: (exit_code, stdout, stderr)

    """
    obj = subprocess.Popen(cmd.split(' '))
    stdout, stderr = obj.communicate()
    ret_code = obj.returncode

    return ret_code, stdout, stderr


#!/usr/bin/python
#
# Like a consumer but no updates after refresh messages
#
import threading
import pyrfa

p = pyrfa.Pyrfa()
p.createConfigDb("./pyrfa.cfg")
p.acquireSession("Session1")
p.createOMMConsumer()
p.login()
p.directoryRequest()
p.dictionaryRequest()

rics = "JPY=,EUR="
p.setInteractionType("snapshot")
p.marketPriceRequest(rics)

# run until all images received or timeout
def stop():
    global timeout
    timeout = True

timeout = False
t = threading.Timer(10, stop)
t.start()

refresh_received = 0
while not timeout and refresh_received < len(rics.split(',')):
    for u in p.dispatchEventQueue():
        if u:
            if u['MTYPE'] == "REFRESH":
                refresh_received += 1
            print(u['SERVICE'] + " - " + u['RIC'])
            for k,v in u.items():
                if type(v) is float:
                    print("%15s %g" % (k,v))
                else:
                    print("%15s %s" % (k,v))
            print("")
t.cancel()


import torchvision
import torch
import gym
import subprocess as sp

from networks import *
from wrappers import make_env
import random

import sys

import pyglet

path = "checkpoints/%s.pt"%sys.argv[1]

q = OCNN()
#q.load_state_dict(torch.load(path,map_location=torch.device('cpu')))
q.eval()
env = gym.make('BreakoutNoFrameskip-v0')
env = make_env(env,noop_max=10) # sometimes it no-ops until the ball is unsaveable

obs = env.reset()
action = 0

kold = None

def update(dt):
    global obs, action, kold
    env.render()
    k = q(torch.cat(obs).unsqueeze(0))
    kk = k.tolist()
    if kold != kk:
        print(*('- '[i>0]+str(round(abs(i),3)).ljust(5,'0') for i in kk[0]))
        kold = kk
    if random.random() < 0.9:
        if random.random() < 0.05:
            action = env.action_space.sample()
            #print('Random',action)
        else:
            action = k.max(1)[1].item()
            #print('Chosen',action)
    obs,_,done,_ = env.step(action)
    if done:
        obs = env.reset()

pyglet.clock.schedule_interval(update, 1./60.)
try:
    pyglet.app.run()
except:
    env.close()


#import pandas as pd #pip install pandas
#import xlwt #pip install xlwt
from openpyxl import load_workbook #pip install openpyxldd
from tqdm import tqdm #pip install tqdm
#import datetime

rb = load_workbook('./workedjournal.xlsx')
wb = load_workbook('./DataBase.xlsx')
print(wb.sheetnames)

def refresh_names():
    not_RAO_array = ['АРХПОИНТ', 'Библиотечно-информационный отдел', 'Информационный центр "Библиотека имени К.Д.Ушинского"',
                 'Сектор библиотечно-информационного обслуживания РАО', 'Сектор комплектования и обработки фонда', 'Сектор обслуживания читателей',
                 'Сектор хранения фонда']
    work_sheet_wb, work_sheet_wb_RAO, work_sheet_wb_other = wb['Сотрудники'], wb['РАО'], wb['Прочие']
    work_sheet_rb = rb['visitorReport']
    flag = False
    RAO_row, oth_row = 2, 2
    for rows in work_sheet_rb.iter_rows(values_only=True):
        if flag and rows[0][0] != '2':
            if rows[3] in not_RAO_array:
                work_sheet_wb_other.cell(row=oth_row, column=1).value = rows[0]
                work_sheet_wb_other.cell(row=oth_row, column=2).value = rows[3]
                oth_row += 1
            else:
                work_sheet_wb_RAO.cell(row=RAO_row, column=1).value = rows[0]
                work_sheet_wb_RAO.cell(row=RAO_row, column=2).value = rows[3]
                RAO_row += 1
        if rows[0] == 'Сотрудник':
            flag = True

# refresh_names() # Только при добавлении новых имён в БД
# wb.save('./DataBase.xlsx')

work_sheet_wb = wb['Сотрудники']
work_sheet_wb_RAO = wb['РАО']
work_sheet_wb_main = wb['Отделы']
work_sheet_wb_other = wb['Прочие']
work_sheet_rb = rb['visitorReport']

def search_data_by_name(name):
    sheet = work_sheet_rb
    n_row, n_title_row = 0, 0
    title_row = str()
    worker_dict, by_days_info = {}, {}
    in_name_flag = False

    for rows in work_sheet_rb.iter_rows(values_only=True):
        if str(rows[0])[:1] != '2':
            in_name_flag = False
        if in_name_flag:
            for i in range(len(title_row)):
                try:
                    by_days_info[title_row[i]].append(rows[i])
                except:
                    by_days_info[title_row[i]] = [rows[i]]
        if rows[0] == 'Сотрудник':
            n_title_row = n_row
            title_row = rows

        if title_row and rows[0] == name:
            in_name_flag = True
            for i in range(len(title_row)):
                worker_dict[title_row[i]] = rows[i]
        n_row += 1
    return worker_dict, by_days_info

n_row = 0
counter = -1
days_info = []
title_dict = {
    'График работы': 3,
    'Присутствие': 4,
    'Рабочее время': 5,
    'Отсутствие': 6,
    'Переработка': 7,
    'Баланс отработанного времени': 8
}
title_dict_1 = {
    'Сотрудник': 3,
    'Присутствие': 4,
    'Рабочее время': 5,
    'Отсутствие': 6,
    'Переработка': 7,
    'Баланс отработанного времени': 8
}

for rows in tqdm(work_sheet_wb_main.iter_rows(values_only=True)):
    n_row += 1

    if counter >= 0:
        for key, value in days_info.items():
            try:
                work_sheet_wb_main.cell(row=n_row, column=title_dict_1[key]).value = value[-counter - 1]
            except:
                pass

    elif rows[1]: # Не пустая строка
        worker_dict, days_info = search_data_by_name(rows[1])
        for key, value in worker_dict.items():
            try:
                work_sheet_wb_main.cell(row=n_row, column=title_dict[key]).value = value
                counter = len(title_dict) + 1
            except:
                pass

    counter -= 1
    if n_row > 2000:
        break

wb.save('./DataBase.xlsx')

RAO_structure = {
    'Отдел Информатизации' : [],
    'РУКОВОДСТВО': [],
    'ОТДЕЛЕНИЕ ФИЛОСОФИИ ОБРАЗОВАНИЯ И ТЕОРЕТИЧЕСКОЙ ПЕДАГОГИКИ': [],
    'ОТДЕЛЕНИЕ ПСИХОЛОГИИ И ВОЗРАСТНОЙ ФИЗИОЛОГИИ': [],
    'ОТДЕЛЕНИЕ ОБЩЕГО СРЕДНЕГО ОБРАЗОВАНИЯ': [],
    'ОТДЕЛЕНИЕ ПРОФЕССИОНАЛЬНОГО ОБРАЗОВАНИЯ': [],
    'ОТДЕЛЕНИЕ ОБРАЗОВАНИЯ И КУЛЬТУРЫ': [],
    'ОТДЕЛЕНИЕ РОССИЙСКОЙ СЛОВЕСНОСТИ': [],
    'СЕКРИТАРИАТ ПОПЕЧИТЕЛЬСКОГО СОВЕТА': [],
    'УПРАВЛЕНИЕ СЕКРИТАРИАТА И ПРОТОКОЛА': [],
    'ФЕДЕРАЛЬНЫЙ РЕСУРСНЫЙ ЦЕНТР ПСИХОЛОГИЧЕСКОЙ СЛУЖБЫ В СИСТЕМЕ ВЫСШЕГО ОБРАЗОВАНИЯ': [],
    'ЦЕНТР РАЗВИТИЯ ОБРАЗОВАНИЯ': [
        'ЛАБОРАТОРИЯ НАУЧНЫХ ПОДХОДОВ В УПРАВЛЕНИИ ОБРАЗОВАТЕЛЬНЫМИ СИСТЕМАМИ',
        'ЛАБОРАТОРИЯ РАЗВИТИЯ СОДЕРЖАНИЯ ОБРАЗОВАНИЯ',
        'ЛАБОРАТОРИЯ СОВРЕМЕННЫХ ФОРМ И МЕТОДОВ ОБУЧЕНИЯ',
        'ЛАБОРАТОРИЯ АНТРОПОЛОГИИ И ПЕДАГОГИЧЕСКОЙ КОМПАРАТИВИСТИКИ',
        'ЛАБОРАТОРИЯ СОЦИОЛОГИЧЕСКИХ ИССЛЕДОВАНИЙ В ОБРАЗОВАНИИ',
        'ЛАБОРАТИРИЯ РАЗВИТИЯ ЦИФРОВОЙ ОБРАЗОВАТЕЛЬНОЙ СРЕДЫ'],
    'ЦЕНТР РАЗВИТИЯ ВЫСШЕГО И СРЕДНЕГО ПРОФЕССИОНАЛЬНОГО ОБРАЗОВАНИЯ': [
        'ЛАБОРАТОРИЯ РАЗВИТИЯ СРЕДНЕГО ПРОФЕССИОНАЛЬНОГО ОБРАЗОВАНИЯ',
        'ЛАБОРАТОРИЯ РАЗВИТИЯ ВЫСШЕГО ПРОФЕССИОНАЛЬНОГО ОБРАЗОВАНИЯ',
        'ЛАБОРАТОРИЯ КООРДИНАЦИИ И МОНИТОРИНГА ДИССЕРТАЦИОННЫХ ИССЛЕДОВАНИЙ ПО ПЕДАГОГИЧЕСКИМ И ПСИХОЛОГИЧЕСКИМ НАУКАМ'
    ],
    'ЦЕНТР ОБРАЗОВАТЕЛЬНОГО ЗАКОНОДАТЕЛЬСТВА И ПРОБЛЕМ ПРАВОПРИМЕНЕНИЯ': [],
    'УЧЕБНЫЙ ЦЕНТР': [],
    'ЦЕНТР ДУХОВНОГО-НРАВСТВЕННОГО ВОСПИТАНИЯ И ТЕОЛОГИИ': [],
    'ЦЕНТР РАЗВИТИЯ ПЕДАГОГИЧЕСКОГО ОБРАЗОВАНИЯ': [
        'Лаборатория продвижения и пиар сопровождения педагогического образования'
    ],
    'ЦЕНТР РАЗВИТИЯ ИНКЛЮЗИВНОГО ОБРАЗОВАНИЯ': [
        'Лаборатория обучающихся с особыми образовательными потребностями',
        'Лаборатория содержания и форм подготовки специалистов с детьми с ОВЗ и инвалидностью'
    ],
    'ЦЕНТР ВОСПИТАНИЯ И РАЗВИТИЯ ЛИЧНОСТИ': [
        'ЛАБОРАТОРИЯ РАЗВИТИЯ ПРОСВЕТИТЕЛЬНОЙ ДЕЯТЕЛЬНОСТИ',
        'ЛАБОРАТОРИЯ ГУМАНИТАРНОГО ОБРАЗОВАНИЯ И ФОРМИРОВАНИЯ МИРОВОЗРЕНИЯ',
        'ЛАБОРАТОРИЯ СОВРЕМЕННЫХ ФОРМ И МЕТОДОВ ВОСПИТАНИЯ',
        'ЛАБОРАТОРИЯ СОВРЕМЕННЫХ ФОРМ И МЕТОДОВ ПРОФЕССИОНАЛЬНОГО САМООПРЕДЕЛЕНИЯ И ПРОФОРИЕНТАЦИИ',
        'Лаборатория научных основ изучения личности развития ребенка',
        'Лаборатория развития содержания воспитания и социализации',
        'Лаборатория психологического сопровождения развития личности в образовательном процессе'
    ],
    'ЦЕНТР РОДНЫХ ЯЗЫКОВ И КУЛЬТУР НАРОДОВ РФ': [],
    'ЦЕНТР РУССКОГО ЯЗЫКА И СЛАВИСТИКИ': [],
    'ЦЕНТР ЭКСПЕРТИЗЫ В ОБРАЗОВАНИИ': [],
    'ИНФОРМАЦИОННЫЙ ЦЕНТР "БИБЛИОТЕКА им. К.Д. УШИНСКОГО"': [
        'МЕТОДИЧЕСКИЙ ОТДЕЛ'
    ],
    'УПРАВЛЕНИЕ КООРДИНАЦИИ НАУЧНЫХ ИССЛЕДОВАНИЙ И ПОДГОТОВКИ КАДРОВ ВЫСШЕЙ КВАЛИФИКАЦИИ': [
        'ОТДЕЛ КООРДИНАЦИИ НАУЧНЫХ ИССЛЕДОВАНИЙ',
        'ОТДЕЛ КООРДИНАЦИИ ДЕЯТЕЛЬНОСТИ ПО ПОДГОТОВКЕ КАДРОВ ВЫСШЕЙ КВАЛИФИКАЦИИ',
        'ОТДЕЛ ПО РАБОТЕ С ПРОЕКТАМИ',
        'Отдел редакционно - издательской работы'
    ],
    'УПРАВЛЕНИЕ МЕЖДУНАРОДНОГО СОТРУДНИЧЕСТВА, СВЯЗЕЙ С ОБЩЕСТВЕННОСТЬЮ И СМИ': [
        'ОТДЕЛ МЕЖДУНАРОГО СОТРУДНИЧЕСТВА',
        'ОТДЕЛ ПО СВЯЗЯМ С ОБЩЕСТВЕННОСТЬЮ И СМИ'
    ],
    'ДЕПАРТАМЕНТ УПРАВЛЕНИЯ ДЕЛАМИ РАО': [
        'ОТДЕЛ КАДРОВ И ОХРАНЫ ТРУДА'
    ],
    'УПРАВЛЕНИЕ ПРАВОВОГО ОБЕСПЕЧЕНИЯ И ДЕЛОПРОИЗВОДСТВА': [
        'ОТДЕЛ ПРАВОВОГО ОБЕСПЕЧЕНИЯ И ИМУЩЕСТВЕННЫХ ОТНОШЕНИЙ',
        'ОТДЕЛ ДЕЛОПРОИЗВОДСТВА',
        'СЕКТОР НАУЧНОГО АРХИВА'
    ],
    'УПРАВЛЕНИЕ ФИНАНСОВОГО ПЛАНИРОВАНИЯ И БУХГАЛТЕРСКОГО УЧЕТА': [
        'ПЛАНОВЫЙ ОТДЕЛ',
        'ОТДЕЛ БУХГАЛТЕРСКОГО УЧЕТА И ОТЧЕТНОСТИ',
        'КОНТРАКТНАЯ СЛУЖБА',
        'ХОЗЯЙСТВЕННЫЙ ОТДЕЛ'
    ]
}


s = input().split()
if len(s[0]) > len(s[1]):
    A = s[1]
    B = s[0]
else:
    A = s[0]
    B = s[1]

dif = []
len_dif = len(B) - len(A)
for i in range(len_dif + 1):
    prefix = ''
    postfix = ''
    for j in range(i):
        prefix += '_'
    for k in range(len_dif - i):
        postfix += '_'

    dif.append(0)
    A_1 = prefix + A + postfix
    for m in range(i, len(B) - (len_dif - i)):
        if A_1[m] != B[m]:
            dif[i] += 1

print(min(dif))


# © 2016 Camptocamp SA, Sodexis
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html)

from odoo import fields, models

class AccountPaymentMode(models.Model):
    _inherit = "account.payment.mode"

    workflow_process_id = fields.Many2one(
        comodel_name="sale.workflow.process", string="Automatic Workflow"
    )


import glob
import pandas as pd
import numpy as np

def ParseAOI(xml):
    with open(xml, 'r') as content_file:
        content = content_file.read()

    # content2 = content[1:99999999999]
    ## New ways to extract atlas score, status, included or excluded status
    res = []
    subres = []
    for w in content.split(">"):
        if "<" in w and '' != w.split("<")[0]:
            values = w.split("<")[0]
            if values.isdigit():
                res.append(subres)
                subres = []
            subres.append(values)

    # Agents included with atlas score turned on will be like:
    #['1', '0.982075496808', 'M5Z7Y4Q7PAL', 'true']
    # Agents included with atlas score turned off will be like:
    # ['3', '0.981889713969', '01PR84M4SP5', 'false']
    # Agents excluded will be like:
    # ['2','0.985812242907','OFFICE_HAS_BEEN_MARKED_EXCLUDED_BY_AGENCY','0NVWH4M4FP5','false']
    includes = [x for x in res if len(x) == 4]
    excludes =  [x for x in res if len(x) > 4][1:]
    num_trans = len([x for x in includes if x[0] == '1'])
    num_ats_on = len([x for x in includes if x[0]=='1' and x[3] == 'true'])
    num_ats_off = len([x for x in includes if x[0]=='1' and x[3] == 'false'])

    return res,includes,excludes,num_trans,num_ats_on,num_ats_off

# Analyze the includes data to aggregate to per transcation
# 1 label by transaction
# 2 filter out atlas off transactions
# 3 Record top agent, score, an

    ##Sth TODO: Look at agents whose atlas is on, their display order frequency count
    ## TODO: Count #number of transactions coming through per zipcode
## for each transaction the agent atlas score is on, record the actual top one agent,
# the highest score agent, number of agent
#Per zip code, # of AOI transactions where ATLAS== true, number of agents, actual ATLAS score per agent, actual conversion rate?

# def main():
#     #xml = 'listval_20170101_235902.xml'
#     # List all xml files
#     # xmlFiles = glob.glob("/san-data/atlas_id/*xml")
#     xmlFiles = glob.glob("*xml")
#     Date = []
#     Res = []
#     Includes = []
#     Excludes = []
#     Num_trans = []
#     Num_ats_on = []
#     Num_ats_off = []

#     # Parse xml files
#     for xml in xmlFiles:
#         date = xml.split('_')[1]
#         res,includes,excludes,num_trans,num_ats_on,num_ats_off = ParseAOI(xml)
#         Date.append(date)
#         Res.append(res)
#         Includes.append(includes)
#         Excludes.append(excludes)
#         Num_trans.append(num_trans)
#         Num_ats_on.append(num_ats_on)
#         Num_ats_off.append(num_ats_off)

#     df_dict = {'Date':Date,'Num':Num_trans,'Num_ats_on':Num_ats_on,'Num_ats_off':Num_ats_off
#     }

#     df = pd.DataFrame(df_dict)
#     df.to_csv('.csv')

    #return res,includes,excludes,num_trans,num_ats_on,num_ats_off

if __name__ == '__main__':
    #main()
    xmlFiles = glob.glob("*xml")
    Date = []
    #Res = []
    Includes = []
    #Excludes = []
    TopMaxAgt = []
    Num_trans = []
    Num_ats_on = []
    Num_ats_off = []

    # Parse xml files
    for xml in xmlFiles:
        date = xml.split('_')[1] # Get the date
        res,includes,excludes,num_trans,num_ats_on,num_ats_off = ParseAOI(xml) # Pasre xml
        Date.append(date)
        #Res.append(res)

        # Construct a df to store includes
        dfincludes = pd.DataFrame(includes,columns = ['Pos','ATLS_SCORE','ASSOC_ID','ATLS_APPLIED'])
        # Include date column
        dfincludes['Date'] = date
        #dfincludes['Trans'] = None
        #dfincludes['Pos'] = pd.to_numeric(dfincludes['Pos']) # Convert Pos to numeric

        transnums = []
        # Get list of agents whose atlas score is applied
        df_on = dfincludes[dfincludes.ATLS_APPLIED == 'true']
        transnum = 1
        for i in range(1, df_on.shape[0]):

            if float(df_on['Pos'].iloc[i]) <= float(df_on['Pos'].iloc[i-1]):
                transnum += 1
            transnums.append(transnum)

        transnums =  [1] + transnums
        df_on['Trans'] = transnums
        # df_on.groupby('Trans')['ATLS_SCORE'].agg('count')
        # df_on.groupby('Trans')['ATLS_SCORE'].agg(np.min)

        #idx = df_on.groupby(['Trans'])['ATLS_SCORE'].transform(max) == df_on['Trans']
        #df_MaxScoreAgent = df_on[idx]

        df_MaxScoreAgent = df_on.sort('ATLS_SCORE',ascending = False).groupby('Trans',as_index = False).first()
        df_TopAgent = df_on[df_on.Pos =='1']

        df_total = df_TopAgent.copy()
        df_total.columns = ['TopPos','TopScore','TopAgent','ATLS_APPLIED','Date','Trans']
        df_total['MaxSAgent'] = df_MaxScoreAgent.ASSOC_ID
        df_total['MaxScore'] = df_MaxScoreAgent.ATLS_SCORE
        df_total['MaxScorePos'] = df_MaxScoreAgent.Pos

        TopMaxAgt.append(df_total)

        # Append the df into a list
        #Includes.append(dfincludes)

        # Construct a df to store excludes and append to a list, run into memory issue
        # excludes_noreasons = [x[1:2]+x[-2:-1] for x in excludes]
        # excludes_reasons = [x[2:-2] for x in excludes]
        # dfexcludes = pd.DataFrame(excludes_noreasons,columns = ['ATLS_SCORE','ASSOC_ID'])
        # dfexcludes['reasons'] = excludes_reasons
        # dfexcludes['Date'] = date * dfexcludes.shape[0]
        # Excludes.append(dfexcludes)

        # Store the num trans, on and off in a list
        Num_trans.append(num_trans)
        Num_ats_on.append(num_ats_on)
        Num_ats_off.append(num_ats_off)

    # Construct num_trans, on and off list into a df and save
    AtlCount_dict = {'Date':Date,'Num':Num_trans,'Num_ats_on':Num_ats_on,'Num_ats_off':Num_ats_off
    }
    AtlCount_df = pd.DataFrame(AtlCount_dict)
    AtlCount_df.to_csv('AtlCount201701.csv')

    # Construct top displayed and max scored agent concated pd and save to csv
    TopMaxAgt_df = pd.concat(TopMaxAgt)
    TopMaxAgt_df.to_csv('TopMaxAgt201701.csv')

    # Construct includes and excludes concated pd and save to csv
    #Excludes_df = pd.concat(Excludes)
    #Includes_df = pd.concat(Includes)
    #Excludes_df.to_csv('Excludes201701.csv')
    #Includes_df.to_csv('Includes201701.csv')


from gnuradio import gr, gr_unittest
from gnuradio import blocks
import gfdm_python as gfdm
import numpy as np
import pmt

class qa_extract_burst_cc(gr_unittest.TestCase):
    def setUp(self):
        self.tb = gr.top_block()

    def tearDown(self):
        self.tb = None

    def test_001_t(self):
        n_frames = 500
        burst_len = 383
        gap_len = 53
        tag_key = 'energy_start'

        data = np.arange(burst_len)
        ref = np.array([], dtype=np.complex)
        tags = []
        for i in range(n_frames):
            frame = np.ones(burst_len) * (i + 1)
            ref = np.concatenate((ref, frame))
            tag = gr.tag_t()
            tag.key = pmt.string_to_symbol(tag_key)
            tag.offset = burst_len + i * (burst_len + gap_len)
            tag.srcid = pmt.string_to_symbol('qa')
            tag.value = pmt.make_dict()
            tags.append(tag)
            data = np.concatenate((data, frame, np.zeros(gap_len)))
        # print(np.reshape(data, (-1, burst_len)))
        # print('data len', len(data), 'ref len', len(ref))

        src = blocks.vector_source_c(data, False, 1, tags)
        burster = gfdm.extract_burst_cc(burst_len, 0, tag_key)
        snk = blocks.vector_sink_c()
        self.tb.connect(src, burster, snk)
        self.tb.run()

        res = np.array(snk.data())
        rx_tags = snk.tags()
        for i, t in enumerate(rx_tags):
            self.assertEqual(pmt.symbol_to_string(t.key), tag_key)
            self.assertTrue(pmt.is_true(t.value))
            self.assertEqual(pmt.symbol_to_string(t.srcid), burster.name())
            self.assertEqual(t.offset, i * burst_len)

        # check data
        self.assertComplexTuplesAlmostEqual(ref, res)

if __name__ == '__main__':
    gr_unittest.run(qa_extract_burst_cc)


##try other way to compute cos-similarity
import json
from matplotlib import pyplot as plt
import pandas as pd
import numpy as np
import math

with open('sample-relationshipTable.json', 'r', encoding='utf-8') as f:
    relationship = json.load(f)
f.close()

sumSim = []
for item in similarities:
    if round(item.sum(), 3) > 1:
        sumSim.append(item.sum())
plt.hist(sumSim, 100)

recordList = []
for item in similarities:
    for record in item:
        if round(record, 3) != 0 and round(record, 3) != 1:
            recordList.append(record)
plt.hist(recordList, 100)


import pyspark.pandas as ps
from flask import current_app
from pyspark.conf import SparkConf
from pyspark.sql import SparkSession
from pyspark.sql import functions as fn
from pyspark.sql.types import StructField, IntegerType, DateType, StringType, FloatType
from app import db

def _common_config(conf):
    jars = [
        "%s/%s" % (current_app.config["PACKAGE_DIRECTORY"], _)
        for _ in ["sqlite-jdbc-3.34.0.jar", "mysql-connector-j-8.0.32.jar"]
    ]
    conf = (
        conf.set("spark.python.worker.memory", "128m")
        .set("spark.task.maxFailures", "10")
        .set("spark.rdd.compress", "true")
        .set("spark.hadoop.mapreduce.fileoutputcommitter.algorithm.version", "2")
        .set("spark.jars", ",".join(jars))
        .set("spark.sql.legacy.timeParserPolicy", "LEGACY")
        .set("spark.sql.parquet.datetimeRebaseModeInWrite", "LEGACY")
        .set("spark.sql.adaptive.enabled", "true")
        .set("spark.sql.adaptive.skewJoin.enabled", "true")
        .set("spark.shuffle.spill.compress", "true")
        .set("spark.sql.broadcastTimeout", 600)
        .set("spark.network.timeout", "240s")
        .set("spark.driver.extraClassPath", current_app.config["SPARK_DB_DRIVER"])
        .set("spark.executor.extraClassPath", current_app.config["SPARK_DB_DRIVER"])
    )
    return conf

def _spark_config(app_name, num_cores, driver_memory):
    conf = (
        SparkConf()
        .setAppName(app_name)
        .setMaster("local[%s,4]" % num_cores)
        .set("spark.driver.memory", driver_memory)
    )
    return _common_config(conf)

def get_spark(
    app_name="weatherdata-api",
    num_cores=2,
    driver_memory="8g",
):
    conf = _spark_config(app_name, num_cores, driver_memory)
    spark_builder = SparkSession.builder.config(conf=conf)
    spark = spark_builder.getOrCreate()
    spark.sparkContext.setLogLevel("WARN")

    return spark

class StringField(StructField):
    def __init__(self, field_name, nullable=True):
        super().__init__(name=field_name, dataType=StringType())
        self.nullable = nullable

class IntField(StructField):
    def __init__(self, field_name, nullable=True):
        super().__init__(name=field_name, dataType=IntegerType())
        self.nullable = nullable

class DateField(StructField):
    def __init__(self, field_name, nullable=True):
        super().__init__(name=field_name, dataType=DateType())
        self.nullable = nullable

class FloatField(StructField):
    def __init__(self, field_name, nullable=True):
        super().__init__(name=field_name, dataType=FloatType())
        self.nullable = nullable

def table_to_df(tablename, custom_schema=None):
    """Lesson learned:
    Since sqlite was chosen as a test option, this gets messy here because
    spark/pandas can't import date fields from sqlite.
    TODO: drop sqlite and deploy with mysql container even for tests and dev
    """
    options = (
        {
            "customSchema": custom_schema,
        }
        if custom_schema
        else None
    )

    if custom_schema:
        psdf = ps.read_sql(
            tablename, con=current_app.config["SPARK_DB_CON"], options=options
        )
    else:
        psdf = ps.read_sql(tablename, con=current_app.config["SPARK_DB_CON"])

    df = psdf.to_spark(index_col=None)
    if custom_schema and "date" in custom_schema:
        df = df.withColumn("date", fn.to_date(fn.col("date"), "yyyy-MM-dd"))

    return df

def df_to_db(df, tablename, if_exists="append"):
    """
    This looks like and antipattern because it is.
    It's needed for this demo because I'm using sqlite which
    won't allow multiple write connections
    """

    df.toPandas().to_sql(tablename, con=db.engine, if_exists=if_exists, index=False)


import sys
from collections import deque
from collections import defaultdict
input = sys.stdin.readline

def bfs(start, minimum):
    visited = [False] * (N+1)
    visited[start] = True

    que = deque([start])
    cnt = 0

    while que:
        cur_node = que.popleft()

        for q, r in mootube[cur_node]:
            if not visited[q] and r >= minimum:
                visited[q] = True
                que.append(q)
                cnt += 1
    return cnt

if __name__ == "__main__":
    N, Q = list(map(int, input().split()))
    mootube = [[0] * (N+1) for _ in range(N+1)]

    mootube = defaultdict(list)
    for i in range(N-1):
        p, q, r = list(map(int, input().split()))
        mootube[p].append((q, r))
        mootube[q].append((p, r))

    for _ in range(Q):
        K, start = list(map(int, input().split()))
        print(bfs(start, K))


#Descobrindo os números primos em um range
a = int(input('Digite o primeiro bimestre: '))
while a > 10:
    a = int(input('Nota inválida! Digite o primeiro bimestre: '))

b = int(input('Digite o segundo bimestre: '))
while b > 10:
    b = int(input('Nota inválida! Digite o segundo bimestre: '))

c = int(input('Digite o terceiro bimestre: '))
while c > 10:
    c = int(input('Nota inválida! Digite o terceiro bimestre: '))

d = int(input('Digite o quarto bimestre: '))
while d > 10:
    d = int(input('Nota inválida! Digite o terceiro bimestre: '))

media = print((a + b + c + d) / 4)


import unittest
from datetime import datetime
from airflow.models import DagBag, TaskInstance

class TestXComExamplesDag(unittest.TestCase):

    def setUp(self):
        self.dagbag = DagBag()

    def test_xcoms(self):
        dag_id = 'hello_world_xcoms'
        dag = self.dagbag.get_dag(dag_id)
        push_to_xcoms_task = dag.get_task('push_to_xcoms')
        pull_from_xcoms_task = dag.get_task('pull_from_xcoms')

        execution_date = datetime.now()

        push_to_xcoms_ti = TaskInstance(task=push_to_xcoms_task, execution_date=execution_date)
        context = push_to_xcoms_ti.get_template_context()
        push_to_xcoms_task.execute(context)

        pull_from_xcoms_ti = TaskInstance(task=pull_from_xcoms_task, execution_date=execution_date)

        result = pull_from_xcoms_ti.xcom_pull(key="dummyKey")
        self.assertEqual(result, 'dummyValue')

    def test_xcom_in_templated_field(self):
        dag_id = 'hello_world_xcoms'
        dag = self.dagbag.get_dag(dag_id)
        push_to_xcoms_task = dag.get_task('push_to_xcoms')

        execution_date = datetime.now()

        push_to_xcoms_ti = TaskInstance(task=push_to_xcoms_task, execution_date=execution_date)
        context = push_to_xcoms_ti.get_template_context()
        push_to_xcoms_task.execute(context)

        templated_xcoms_value_task = dag.get_task('templated_xcoms_value')
        templated_xcoms_value_ti = TaskInstance(task=templated_xcoms_value_task, execution_date=execution_date)
        context = templated_xcoms_value_ti.get_template_context()

        bash_operator_templated_field = 'bash_command'

        rendered_template = templated_xcoms_value_task.render_template

        bash_command_value = getattr(templated_xcoms_value_task, bash_operator_templated_field)

        bash_command_rendered_value = rendered_template(bash_operator_templated_field, bash_command_value, context)

        self.assertEqual(bash_command_rendered_value, 'echo dummyValue')

suite = unittest.TestLoader().loadTestsFromTestCase(TestXComExamplesDag)
unittest.TextTestRunner(verbosity=2).run(suite)


import os

os.environ['KMP_DUPLICATE_LIB_OK'] = 'True'
import re
from paddleocr import PaddleOCR, draw_ocr
import cv2 as cv
import numpy as np
import time
from collections import defaultdict
import json
from fuzzywuzzy import fuzz
from fuzzywuzzy import process

BASE_DIR = os.path.dirname(os.path.abspath(__file__))

keyword1 = "goal"

def makedir(new_dir):
    if not os.path.exists(new_dir):
        os.makedirs(new_dir)

EVENT_DIR = "D:/dataset/event"
VIDEO_DIR = "D:/dataset/video_error"

ocr = PaddleOCR(lang="en", gpu_mem=5000, det=False,
                rec_model_dir="./inference/en_ppocr_mobile_v2.0_rec_infer/")  # 首次执行会自动下载模型文件

# 获取队名文件
team_name = []
f = open("team_name.txt", "r")
for line in f:
    line = line[:-1]
    team_name.append(line)

# result = process.extract(a, team_name, scorer=fuzz.token_set_ratio, limit=5)

def get_ocr_result(videoCap, i, h_index):
    result = ''
    ocr_list = []
    temp_result = []

    videoCap.set(cv.CAP_PROP_POS_FRAMES, i)
    # i += 100;
    boolFrame, matFrame = videoCap.read()

    if boolFrame:
        temp_jpgframe = np.asarray(matFrame)
        # 截取上面0-90区域进行OCR检测
        if h_index < 200:
            jpgframe = temp_jpgframe[0:h_index]
        else:
            jpgframe = temp_jpgframe[h_index:]

        # 得到OCR识别结果
        temp_result = ocr(jpgframe)

        for mystr, ration in temp_result[1]:
            result += mystr
            ocr_list.append(mystr)
            result += ' '
    return result, temp_result

def find_goal_location(temp_result, location, init_candidate, gt_y2):
    goal_flag = False
    tempResult_index = 0
    for ii, [strr, ration] in enumerate(temp_result[1]):
        game_time = re.findall("\d:\d", strr)
        if game_time:
            num_num = game_time[0]
            # 如果已经记录过位置，则与记录位置进行比较
            if location:
                # x1 = temp_result[0][ii][0][0]
                # x2 = temp_result[0][ii][1][0]
                # y1 = temp_result[0][ii][0][1]
                y2 = temp_result[0][ii][2][1]
                # 偏移量小于8则说明位置正确
                # if (abs(gt_x1 - x1) + abs(gt_x2 - x2) + abs(gt_y1 - y1) + abs(gt_y2 - y2) < 8):
                if abs(gt_y2 - y2) < 4:
                    num1, num2 = num_num.split(":")
                    init_candidate[num1 + "-" + num2] += 1
                    # tempResult_index = ii
                    goal_flag = True
                    break
            # 没记录过，则只记录在init_candidate
            else:
                num1, num2 = num_num.split(":")
                init_candidate[num1 + "-" + num2] += 1
                # 记录该字符串在temp_result中的索引
                tempResult_index = ii
                goal_flag = True
                break
    return init_candidate, goal_flag, tempResult_index

def get_frames(video_dir):
    get = 0
    miss = 0
    total_num = 0
    more = 0
    # with open('video_6_score_change.json', 'r') as fd:
    #     Video_Score_dic = json.load(fd)
    SCORES = {}

    for root, _, files in os.walk(video_dir):
        for video_index in files:
            time1 = time.time()
            video_index1 = video_index.split('_')

            if video_index1[1] not in ['0059', '0060', '0061', '0062',
                                       '0063', '0064', '0065', '0066', '0067', '0068', '0069', '0070',
                                       '0071', '0072', '0073', '1040', '1041', '1045', '1046', '1047', '1048',
                                       '1049', '1050', '1051', '1052', '1054',
                                       '1055', '1056', '1057', '1058', '1059', '1171',
                                       '1212', '1216', '1218', '1221', '1223', '1224', '1225',
                                       '1226', '1228', '1230', '1231', '1233', '1236', '1237', '1238', '1239', '1242',
                                       '1243', '1244', '1245']:

                score_dic = {}
                score_record = []
                player_score_dic = {}
                player_score_record = []
                videoCap = cv.VideoCapture(video_dir + "\\" + video_index)

                frame_height = videoCap.get(cv.CAP_PROP_FRAME_HEIGHT)
                frame_width = videoCap.get(cv.CAP_PROP_FRAME_WIDTH)
                big_h_index = int(frame_height * 7 / 10)
                big_w_index = int(frame_width / 2)
                x1_big_center = big_w_index - 50
                x2_big_center = big_w_index + 50

                frame_count = videoCap.get(cv.CAP_PROP_FRAME_COUNT)
                print("-----------------------------")
                print("video:{}".format(video_index1[1]))
                i = frame_count - 10000
                init_candidate = defaultdict(int)
                player_name_dic = defaultdict(int)
                score_time_dic = defaultdict(int)
                big_candidate = defaultdict(set)

                location_player_score = 0  # 得分球员位置，为0代表在队名下面，为1代表在队名上面
                tempResult_index = 0
                mode = 0
                modify_candidate = defaultdict(int)
                temp_result = []
                gt_y2 = 0
                left_team = ''
                right_team = ''
                team_y1 = 10000
                team_y2 = 0
                big_flag = False
                big_nums = 6
                while i < frame_count:
                    # 评估候选比分

                    # 获取ocr第i帧的直接结果temp_result， 以及字符串连接后的result
                    result, temp_result = get_ocr_result(videoCap, i, 125)
                    big_result, big_temp_result = get_ocr_result(videoCap, i, big_h_index)

                    goal_flag = False
                    big_flag = False
                    team_nums = 0

                    if big_result:
                        # 首先检测是否存在两个队名
                        for ii, [strr, ration] in enumerate(big_temp_result[1]):
                            x1_big = big_temp_result[0][ii][0][0]
                            x2_big = big_temp_result[0][ii][2][0]
                            y1_big = big_temp_result[0][ii][0][1]
                            y2_big = big_temp_result[0][ii][3][1]
                            team1 = process.extractOne(strr, team_name, scorer=fuzz.token_set_ratio,
                                                       score_cutoff=70)
                            if team1:
                                team_nums += 1
                                if x1_big > big_w_index:
                                    right_team = team1[0]
                                if x2_big < big_w_index:
                                    left_team = team1[0]
                                team_y1 = y1_big
                                team_y2 = y2_big
                                continue

                        # 检测出了两个球队名，说明是大字幕，此时team_y1，team_y2都有了
                        if team_nums == 2:
                            for ii, [strr, ration] in enumerate(big_temp_result[1]):
                                x1_big = big_temp_result[0][ii][0][0]
                                x2_big = big_temp_result[0][ii][2][0]
                                y1_big = big_temp_result[0][ii][0][1]
                                y2_big = big_temp_result[0][ii][3][1]

                                if abs(y1_big - team_y1) + abs(y2_big - team_y2) < 4:
                                    continue

                                # 首先排除时间和比分的数字影响
                                sc = re.findall("\d-\d", strr)
                                if sc:
                                    # x1_big_goal = big_temp_result[0][ii][0][0]
                                    # x2_big_goal = big_temp_result[0][ii][3][0]
                                    continue
                                game_t = re.findall("\d\d:\d\d", strr)
                                if game_t:
                                    continue

                                # 运动员进球信息格式1：
                                # 1个或多个非数字+1个或多个数字+0个或多个非数字 |
                                # 0个或多个非数字+1个或多个数字+1个或多个非数字
                                # 长度要求大于4
                                player_score_list = re.findall("\D+\d+\D*|\D*\d+\D+", strr)
                                if player_score_list and len(player_score_list[0]) > 4:
                                    player_score_temp = player_score_list[0]

                                    string_list = re.findall("[A-Z][a-z]+", player_score_temp)
                                    number_list = re.findall("\d+", player_score_temp)

                                    if not string_list:
                                        continue
                                    player_name = string_list[0]
                                    player_name_dic[player_name] += 1

                                    for number_one in number_list:
                                        if len(number_one) < 4:
                                            big_candidate[player_name].add(number_one)
                                            score_time_dic[number_one] += 1
                                            big_flag = True
                                            print("check players name: {}  goal_time: {}  frame:{}   time:{}".format(
                                                player_name, big_candidate[player_name], i,
                                                game_t))
                                    continue

                                # 运动员进球信息格式2：
                                # 运动员字符串在数字字符串前一个
                                #
                                # goal_time = re.findall("^\d+$|^\d+\'|^\d+\(", strr)
                                number_list = re.findall("\d+", strr)

                                if number_list and team_y2 and (team_y1 - y1_big > 5 or y2_big - team_y2 > 5):
                                    for jj, [sstr, ration] in enumerate(big_temp_result[1]):
                                        y1_big = big_temp_result[0][jj][0][1]
                                        y2_big = big_temp_result[0][jj][3][1]

                                    player_name, rat = big_temp_result[1][ii - 1]
                                    player_name_dic[player_name] += 1
                                    isTeam = process.extractOne(player_name, team_name, scorer=fuzz.token_set_ratio,
                                                                score_cutoff=70)
                                    if isTeam:
                                        continue

                                    number_one = re.findall("\d+", goal_time[0])

                                    for number_one in number_list:
                                        if len(number_one) < 4:
                                            big_candidate[player_name].add(number_one)
                                            score_time_dic[number_one] += 1
                                            big_flag = True
                                            print("check players name: {}  goal_time: {}  frame:{}   time:{}".format(
                                                player_name, big_candidate[player_name], i,
                                                game_t))
                        # if big_flag:
                        #     big_nums += 1
                        # elif big_nums > 2 and not big_flag:
                        #     big_nums = 1

                    # 如果检测出比分，则帧数+1检测下一帧，否则帧数+200
                    if goal_flag:
                        i += 1
                        mode = 2
                        continue
                    elif big_flag:
                        i += 2
                        big_nums += 5
                        continue
                    # 没有大字幕持续若干次
                    elif big_nums < 4 and not big_flag:
                        big_nums += 1
                        i += 2
                        continue
                    # 从有大字幕突然变成没有大字幕
                    elif big_nums > 6 and not big_flag:
                        big_nums = 1
                        i += 5
                        continue
                    # 没有大字幕持续若干次后，进行跨越，再检测
                    elif big_nums == 4:
                        # if i+10000 < frame_count-5000:
                        #     i += 10000
                        # else:
                        #     i = max(i+1000, frame_count-5000)
                        if i + 3000 < frame_count - 2000:
                            i += 3000
                        else:
                            i = max(i + 2000, frame_count - 2000)
                        big_nums = 6
                        continue
                    else:
                        i += 50
                        # print("can not get frames!")
                        continue

                # 把big_candidate里的值（set）取交集，如果不为空，就在player_name_dic里面看谁的key次数多
                # 次数少的key就在big_candidate中删除
                nn = len(big_candidate)
                names = list(big_candidate.keys())
                score_times = list(score_time_dic.keys())
                for i in range(nn):
                    if big_candidate[names[i]] != set('0'):
                        for score_time in list(big_candidate[names[i]]):
                            if score_time_dic[score_time] < 5:
                                big_candidate[names[i]].remove(score_time)
                        if big_candidate[names[i]] == set():
                            big_candidate[names[i]] = set('0')
                        for j in range(i + 1, nn):
                            if big_candidate[names[j]] != set('0'):
                                set_temp = big_candidate[names[i]] & big_candidate[names[j]]
                                if set_temp:
                                    if player_name_dic[names[i]] >= player_name_dic[names[j]]:
                                        big_candidate[names[j]] = set('0')
                                    else:
                                        big_candidate[names[i]] = set('0')
                                elif fuzz.token_set_ratio(names[i], names[j]) >= 70:
                                    big_candidate[names[i]] = big_candidate[names[i]].union(big_candidate[names[j]])
                                    big_candidate[names[i]] = set('0')

                # big_candidate里的值（set）为‘0’的key也应该删除
                for key in names:
                    if '0' in big_candidate[key]:
                        del big_candidate[key]
                    elif key.isdigit():
                        del big_candidate[key]
                    elif re.findall("\d\d", key):
                        del big_candidate[key]

                print(big_candidate)
                time2 = time.time()
                print("time for this video:{}".format(time2 - time1))

                # SCORES[video_index] = score_record

                # with open('scores_3' + '.json', 'w') as fd:
                #     json.dump(SCORES, fd)

    print("total_num:{}   get:{}   miss:{}  more:{}".format(total_num, get, miss, more))

get_frames(video_dir=VIDEO_DIR)


import numpy as np
import matplotlib.pyplot as plt

def simple_plot():
    plt.figure(figsize=(8, 6), dpi=80)
    plt.ion()
    for index in range(100):
        plt.cla()
        plt.title("Graph")
        plt.grid(True)
        x = np.linspace(-1.5 + 0.1*index, 1.5+0.1*index, 256, endpoint=True)
        y = 3 * np.pi * np.exp(-5 * np.sin(2 * np.pi * x))
        # set x axis
        plt.xlabel("X")
        plt.xlim(-3 + 0.1*index, 3 + 0.1*index)
        plt.xticks(np.linspace(-3 + 0.1*index, 3+0.1*index, 9, endpoint=True))
        # set y axis
        plt.ylabel("Y")
        plt.ylim(-1.0, 1400.0)
        plt.yticks(np.linspace(0, 1400, 20, endpoint=True))
        plt.plot(x, y, "g-", linewidth=2.0, label="h(t)")
        plt.legend(loc="upper left", shadow=True)
        plt.pause(0.1)
    plt.ioff()
    plt.show()
    return

simple_plot()


from .AnalogControl import AnalogControl

class SetPoint(AnalogControl):
	'''
	An analog control that issue a set point value.

	:normalValue: Normal value for Control.value e.g. used for percentage scaling. Default: 0.0
	:value: The value representing the actuator output. Default: 0.0
		'''

	cgmesProfile = AnalogControl.cgmesProfile

	possibleProfileList = {'class': [cgmesProfile.EQ.value, ],
						'normalValue': [cgmesProfile.EQ.value, ],
						'value': [cgmesProfile.EQ.value, ],
						 }

	serializationProfile = {}

	__doc__ += '\n Documentation of parent class AnalogControl: \n' + AnalogControl.__doc__

	def __init__(self, normalValue = 0.0, value = 0.0,  *args, **kw_args):
		super().__init__(*args, **kw_args)

		self.normalValue = normalValue
		self.value = value

	def __str__(self):
		str = 'class=SetPoint\n'
		attributes = self.__dict__
		for key in attributes.keys():
			str = str + key + '={}\n'.format(attributes[key])
		return str


# -*- coding:utf8 -*-

import time
import json
import requests
import tkinter
from tkinter import ttk, scrolledtext
from AWSIoTPythonSDK.MQTTLib import AWSIoTMQTTClient

"""
 How to compile
 py2applet --make-setup test.py
 python setup.py py2app

"""

class GUI:
    def __init__(self):
        self.main_window = tkinter.Tk()
        self.main_window.title('hue controller')
        self.main_window.geometry('500x800')
        self.press = False
        self.press2 = False

        self.canvas = tkinter.Canvas(
        self.main_window, # キャンバスの作成先アプリ
        width = 400, # キャンバスの横サイズ
        height = 400, # キャンバスの縦サイズ
        bg = "white" # キャンバスの色
        )
        self.canvas.pack()

        self.canvas2 = tkinter.Canvas(
        self.main_window, # キャンバスの作成先アプリ
        width = 400, # キャンバスの横サイズ
        height = 50, # キャンバスの縦サイズ
        bg = "blue" # キャンバスの色
        )
        self.canvas2.pack()

        self.button1 = ttk.Button(text="ON")
        self.button1.pack()
        self.button1.bind("<Button-1>",self.clickButton1)

        self.button2 = ttk.Button(text="OFF")
        self.button2.pack()
        self.button2.bind("<Button-1>",self.clickButton2)

        self.buttonAlertOn = ttk.Button(text="Alert ON")
        self.buttonAlertOn.pack()
        self.buttonAlertOn.bind("<Button-1>",self.clickAlertOn)

        self.buttonAlertOff = ttk.Button(text="Alert OFF")
        self.buttonAlertOff.pack()
        self.buttonAlertOff.bind("<Button-1>",self.clickAlertOff)

        self.button3 = ttk.Button(text="Exit")
        self.button3.pack()
        self.button3.bind("<Button-1>",self.clickButton3)

        self.canvas.bind(
            "<Motion>", # 受付けるイベント
            self.mouse_move_func # そのイベント時に実行する関数
        )

        self.canvas.bind(
            "<ButtonPress>", # 受付けるイベント
            self.mouse_click_func # そのイベント時に実行する関数
        )

        self.canvas.bind(
            "<ButtonRelease>", # 受付けるイベント
            self.mouse_release_func # そのイベント時に実行する関数
        )

        self.canvas2.bind(
            "<Motion>", # 受付けるイベント
            self.mouse_move_func2 # そのイベント時に実行する関数
        )

        self.canvas2.bind(
            "<ButtonPress>", # 受付けるイベント
            self.mouse_click_func2 # そのイベント時に実行する関数
        )

        self.canvas2.bind(
            "<ButtonRelease>", # 受付けるイベント
            self.mouse_release_func2 # そのイベント時に実行する関数
        )

        self.setupAWSIoT()

    def setupAWSIoT(self):
        self.myMQTTClient = AWSIoTMQTTClient('myClientID2') # 適当な値でOK
        self.myMQTTClient.configureEndpoint('a1gbwzf7otibfp-ats.iot.us-west-2.amazonaws.com', 8883) # 管理画面で確認
        self.myMQTTClient.configureCredentials('data/rootCA.pem', 'data/fd35544055-private.pem.key', 'data/fd35544055-certificate.pem.crt')
        self.myMQTTClient.configureOfflinePublishQueueing(-1) # Infinite offline Publish queueing
        self.myMQTTClient.configureDrainingFrequency(2) # Draining: 2 Hz
        self.myMQTTClient.configureConnectDisconnectTimeout(10) # 10 sec
        self.myMQTTClient.configureMQTTOperationTimeout(5) # 5 sec
        self.myMQTTClient.connect()

    def sendMessage(self,message):
        self.myMQTTClient.publish("myTopic2", json.dumps({'message' : message}), 1)

    def mouse_move_func(self,event):
        # 現在のマウスの位置
        x = event.x
        y = event.y

        # マウスボタンが押されている時だけ円を描画
        if self.press:
            self.canvas.create_oval(x - 3, y - 3, x + 3, y + 3, fill = "blue", width=0)
            print("drag "+str(x)+":"+str(y))
            self.sendMessage("drag:"+str(x)+":"+str(y))

    def mouse_click_func(self,event):
        # マウスボタンが押された
        self.press = True

    def mouse_release_func(self,event):
        # マウスボタンが離された
        self.press = False

    def mouse_move_func2(self,event):
        if self.press2:
            x = event.x
            print("volume "+str(x))
            self.sendMessage("volume:"+str(x))
        return

    def mouse_click_func2(self,event):
        self.press2 = True
        return

    def mouse_release_func2(self,event):
        self.press2 = False
        return

    def clickButton1(self,event):
        print("send clickButton1")
        self.sendMessage("clickButton1")
        return "break"

    def clickButton2(self,event):
        print("send clickButton2")
        self.sendMessage("clickButton2")
        return "break"

    def clickAlertOn(self,event):
        print("send clickAlertOn")
        self.sendMessage("clickAlertOn")
        return "break"

    def clickAlertOff(self,event):
        print("send clickAlertOff")
        self.sendMessage("clickAlertOff")
        return "break"

    def clickButton3(self,event):
        exit()
        return "break"

    def start(self):
        self.main_window.mainloop()
        return

def main():
    W = GUI()
    W.start()

if __name__ == "__main__":
    main()