from multiagents.reasoning_algorithms.tree_of_thought.Tree.Tree import my_tree, tree_node
from copy import deepcopy
from multiagents.reasoning_algorithms import base_search_method
from prompt_templates.Tree_search_prompts import  MAKE_REFLECTION_RPOMPT,DIVERSITY_PROMPT,VOTE_BEST_SYSTEM_PROMPT,VOTE_BEST_USER_PROMPT,DEFAULT_POLICY_SYSTEM_PROMPT, DEFAULT_POLICY_USER_PROMPT
from prompt_templates.Reflexion_prompts import MAKE_REFLEXION_USER_PROMPT
from typing import List, NamedTuple, Optional, Union
from termcolor import colored
from string import Template
from multiagents.utils.utils import AgentAction, AgentFinish
from multiagents.memory import BaseMemory, ChatHistoryMemory
import numpy as np
import re
import json
from pydantic import BaseModel, Field
from pprint import pprint
import datetime
import time
from tqdm import tqdm

def node_to_chain(node):
    chain = {
        "prompt": "",
        "query": "",
        "chains": [],
        "answer": "",
    }

    step = {}
    for i, message in enumerate(node.messages):
        if message["role"] == "system":
            chain["prompt"] = message["content"]
        elif message["role"] == "user":
            chain["query"] += message["content"]
        elif message["role"] == "assistant":
            if "function_call" in message:
                function_call = message["function_call"]
                if function_call["name"] == "Finish":
                    chain["answer"] = function_call["arguments"]
                else:
                    step["action"] = function_call["name"]
                    step["action_input"] = function_call["arguments"]
            else:
                step["thought"] = message["content"]
        elif message["role"] == "function":
            step["observation"] = message["content"]
            chain["chains"].append(step)
            step = {}

    return chain

class UCT_vote_function(base_search_method):
    class Config:
        arbitrary_types_allowed = True
    memory: BaseMemory = Field

    def __init__(self, diag_id, start_time, end_time, agent_name, role_description, prompt_template, llm,env, output_parser, alert_dict, alert_str, agent):
        super(UCT_vote_function, self).__init__()
        '''
        偏序驱动的信心上限树算法:
        1.由value决定回传什么节点
        2.回传反思，同时做偏序
        '''
        self.diag_id = diag_id
        self.name = agent_name
        self.role_description = role_description
        self.prompt_template = prompt_template
        self.llm = llm
        self.env = env
        self.output_parser = output_parser
        # self.simulations = []
        self.start_time = start_time
        self.end_time = end_time
        self.alert_dict = alert_dict
        self.alert_str = alert_str

        self.restart(agent)

    # def to_json(self):

    #     js_obj = {
    #         "win": self.status == 1,
    #         "simulation_count": self.now_simulation_count,
    #         "simulations": self.simulations,
    #         "tree":self.tree.to_json_recursive()
    #     }

    #     js_obj["answer_generation"] = {
    #         "valid_data": False,
    #         "final_answer": "",
    #         "chain": [],
    #     }

    #     if len(self.terminal_node) > 0:
    #         final_terminal_node = sorted(self.terminal_node, key=lambda x: sum(x.values)/(len(x.values)+1e-8), reverse=True)[0]
    #         js_obj["answer_generation"]["valid_data"] = True
    #         js_obj["answer_generation"]["final_answer"] = final_terminal_node.description
    #         js_obj["answer_generation"]["chain"] = final_terminal_node.get_chain_result_from_this_node()

    #     return js_obj

    def restart(self, agent): # 理论上用不到，清空所有的tree
        self.tree = my_tree()
        self.tree.root.node_type = "Action Input"
        self.tree.root.env = deepcopy(self.env)

        # prefix = DEFAULT_POLICY_SYSTEM_PROMPT
        # prefix = prefix.replace("{task_description}",self.env.task_description)
        # self.tree.root.messages.append({
        #     "role":"system",
        #     "content": prefix,
        # })

        # prefix = DEFAULT_POLICY_USER_PROMPT
        # prefix = prefix.replace("{input_description}",self.env.input_description)

        tool_observation = [self.tree.root.env.tool_memory.to_string()]
        #prompt = agent._fill_prompt_template(self.tree.root.env.tool, self.tree.root.env.task_description, tool_observation, self.tree.root.messages)
        prompt = agent._fill_prompt_template(self.tree.root.env.task_description, tool_observation)

        now_time = datetime.datetime.now()
        now_time = now_time.strftime("%H:%M:%S")

        self.tree.root.messages.append({
            "role":"user",
            "content": prompt,
            "time": str(now_time)
        })

        self.status = 0
        self.now_simulation_count = 0
        # self.simulations = []
        self.terminal_node = []
        self.total_vote = 0
        self.good_vote = 0

        pass

    def start(self,
              simulation_count, # chain的个数
              epsilon_new_node, # 开新节点的value
              choice_count, # vote随机次数
              vote_candidates, # vote叶节点个数
              vote_count, # 投票次数
              single_chain_max_step):

        '''
        epsilon_new_node:以多大概率扩展新节点
        vote_candidates：每次投票时选择多少candidate
        vote_count：每次投票时投多少票
        '''

        top_abnormal_metric_values = []

        while self.now_simulation_count < simulation_count:

            '''
            执行一次模拟，从根节点出发
            '''
            this_simulation = []
            now_node = self.tree.root
            while len(now_node.children) > 0:
                '''
                有儿子节点，在每个地方都决定是去扩展新节点还是选择已有节点
                '''
                # decision = self.make_decision(now_node)
                decision = self.make_decision_by_value(now_node, epsilon_new_node)

                if decision == -1:
                    print(colored("decide to make new node!","green"))
                    break
                # print(colored(f"decide to go down child {decision}","green"))

                now_node = now_node.children[decision]
                this_simulation.append({"choice":decision,"new_generated":False,"score":now_node.env.get_score()})

                while now_node.node_type != "Action Input" and len(now_node.children) > 0:
                    now_node = now_node.children[0]
                    this_simulation.append({"choice":0,"new_generated":False,"score":now_node.env.get_score()})

            if now_node.is_terminal:
                # print(colored(f"randomly go down to terminal nodes","green"))
                pass
            else:
                begin_default_policy_node = now_node

                end_node, top_abnormal_metric_values = self.default_policy(now_node,this_simulation,single_chain_max_step)
                # self.pruned self.env.check_success()

                self.now_simulation_count += 1
                # self.simulations.append(this_simulation)

                if end_node.pruned is not True: # the node is not pruned
                    self.terminal_node.append(end_node)

                if end_node.env.status == 1:
                    self.status = 1
                    # self.llm.display_conversation()
                    # return 1

                '''
                生成反思，并且回传
                '''
                self.make_reflection(begin_default_policy_node,end_node)

            '''
            针对candidate投票
            '''
            self.vote(choice_count,vote_candidates,vote_count)

        if self.terminal_node == []:
            # print(colored("No terminal node found!","red"))

            return None, top_abnormal_metric_values

        else:
            final_terminal_node = sorted(self.terminal_node, key=lambda x: sum(x.values), reverse=True)[0]

            if final_terminal_node.pruned is True:
                # print(colored("Final answer is pruned!","red"))
                return None, top_abnormal_metric_values

            return final_terminal_node, top_abnormal_metric_values

    def vote(self,choice_count,vote_candidates,vote_count):
        '''
        进行投票
        每次选vote_candidates个样本
        投出vote_count票
        '''
        # if len(self.terminal_node) < vote_candidates:
        #     return

        for choice_count in range(choice_count):
            ordered = list(range(len(self.terminal_node)))
            np.random.shuffle(ordered)

            choices = ordered[:vote_candidates] #随机选择，然后从小到大排序
            choices.sort()
            messages = []
            prompt = VOTE_BEST_SYSTEM_PROMPT
            prompt = prompt.replace("{task_description}",self.env.task_description)

            now_time = datetime.datetime.now()
            now_time = now_time.strftime("%H:%M:%S")

            messages.append({
                "role":"system",
                "content": prompt,
                "time": str(now_time)
            })

            prompt = VOTE_BEST_USER_PROMPT
            prompt = prompt.replace("{input_description}",self.env.input_description)

            candidates_description = ""
            for k, child_id in enumerate(choices):
                trice = self.tree.get_former_trice(self.tree.root,self.terminal_node[child_id],valid_types=["Action","Action Input","Observation"])
                candidates_description += f"<candidate_{k}>\n{trice}"
                # reflection = f"Reflection: {self.terminal_node[child_id].generated_reflection.strip()}\n"
                # candidates_description += reflection
                candidates_description += "*"*30 + "\n"
            prompt = prompt.replace("{candidate_description}",candidates_description)

            now_time = datetime.datetime.now()
            now_time = now_time.strftime("%H:%M:%S")

            messages.append({
                "role":"user",
                "content": prompt,
                "time": str(now_time)
            })

            real_score = [-1]*len(choices)
            max_score = self.tree.root.env.get_score()
            max_position = -1
            for k, child_id in enumerate(choices):
                now_node = self.terminal_node[child_id]
                while now_node != None:
                    real_score[k] = max(now_node.env.get_score(),real_score[k])
                    now_node = now_node.father
                if real_score[k] > max_score:
                    max_position = k
                    max_score = real_score[k]

            votes = [0]*len(choices)
            vaild_votes = 0
            for i in range(vote_count):
                '''
                多次投票
                '''
                self.llm.change_messages("", messages)

                print(colored(f"- Voting ...","grey"))
                with tqdm(total=1, bar_format='{l_bar}{bar}| {n_fmt}/{total_fmt}') as pbar:
                    message = self.llm.parse()
                    pbar.update(1)

                vote = message["content"]
                # print(vote)
                best_candiate_line = vote.split("\n")[-1]
                # print(best_candiate_line)
                re_pattern = r"\"?candidate[ \_](\d+)\"?"
                re_result = re.findall(re_pattern,best_candiate_line.lower())
                if re_result != []:
                    if not len(re_result) == 1:
                        # print(best_candiate_line)
                        # exit()
                        return
                    vote_to = int(re_result[0])
                    self.total_vote += 1
                    if vote_to >= 0 and vote_to < len(votes):
                        votes[vote_to] += 1
                        self.good_vote += (vote_to == max_position)
                        vaild_votes += 1
                        # print(colored(f"valid vote to {choices[vote_to]}","yellow"))
                    else:
                        self.good_vote += (-1 == max_position)
                        # print(colored(f"vote to Invalid candidates, both candidate punished","yellow"))
                else:
                    self.good_vote += (-1 == max_position)
                    # print(colored(f"vote to Nothing, both candidate punished","yellow"))
                    for k,child_id in enumerate(choices):
                        now_node = self.terminal_node[child_id]
                        while now_node != None:
                            now_node.pruned = True
                            now_node = now_node.father

            if vaild_votes > 0:
                for k,child_id in enumerate(choices):
                    vote_count_this_turn = votes[k]
                    value = (vote_count_this_turn / vaild_votes  - 1 / vote_candidates) / np.sqrt(vaild_votes)
                    # print(value)
                    now_node = self.terminal_node[child_id]
                    while now_node != None:
                        now_node.values.append(value)
                        now_node.vote_counts.append(vote_count_this_turn)
                        now_node = now_node.father

        if self.total_vote > 0:
            # print(f"ratio={self.good_vote}/{self.total_vote}={self.good_vote/self.total_vote}")
            pass

    def make_decision_by_value(self, now_node, epsilon_new_node):
        '''
        epsilon_new_node概率选择新节点
        否则选择当前value最高的
        '''
        # assert len(now_node.children) > 0
        # if np.random.random() < epsilon_new_node / len(now_node.children):
        #     return -1

        weights = [child.compute_weight() for child in now_node.children] + [epsilon_new_node]
        def my_softmax(x):
            exp_x = np.exp(x)
            return exp_x/np.sum(exp_x)

        weights = my_softmax(np.array(weights))
        # print(weights)
        result = np.random.multinomial(1,weights)
        for k, v in enumerate(result[:-1]):
            if v == 1:
                return k
        return -1

    def make_reflection(self,start_node,end_node):
        '''
        从start_node开始生成了新儿子，一路走到了end_node,对于过去的自己start_node有没有什么想说的
        '''
        make_reflection_prompt = MAKE_REFLEXION_USER_PROMPT

        now_time = datetime.datetime.now()
        now_time = now_time.strftime("%H:%M:%S")

        new_message = {
            "role": "user",
            "content":make_reflection_prompt,
            "time": str(now_time)
        }

        message_list = end_node.messages.copy()
        message_list.append(new_message)

        self.llm.change_messages(self.role_description, message_list)

        print(colored(f"- Reflecting ...","grey"))
        with tqdm(total=1, bar_format='{l_bar}{bar}| {n_fmt}/{total_fmt}') as pbar:
            new_message = self.llm.parse()
            pbar.update(1)

        reflection = new_message['content']
        print(colored(f"Reflexion: {reflection}","green"))

        now_time = datetime.datetime.now()
        now_time = now_time.strftime("%H:%M:%S")

        reflect_message = {
            "role": "assistant",
            "content": reflection,
            "time": str(now_time)
        }
        start_node.reflection.append(reflection)
        start_node.messages.append(reflect_message)
        if start_node != self.tree.root:
            self.tree.root.reflection.append(reflection)
            self.tree.root.messages.append(reflect_message)

        return reflection

    def default_policy(self,now_node,this_simulation,single_chain_max_step):
        assert not now_node.is_terminal
        assert now_node.messages != []
        # self.pruned self.env.check_success()
        first_time = True

        top_abnormal_metric_values = []

        while now_node.get_depth() < single_chain_max_step and not now_node.is_terminal and not now_node.env.status:
            if first_time:
                '''
                第一次要拼接diversity prompt
                '''
                if len(now_node.children) > 0:
                    diverse_prompt = DIVERSITY_PROMPT
                    former_candidates_des = ""
                    js_list = []
                    for k, child in enumerate(now_node.children):
                        temp_node = child
                        while not temp_node.is_terminal and temp_node.node_type != "Action Input" and len(temp_node.children) > 0:
                            temp_node = temp_node.children[0]
                        # child_des = self.get_former_trice(child,temp_node)
                        # former_candidates_des = former_candidates_des + f"<candidate_{k+1}>\n{child_des}"
                        if temp_node.node_type == "Action Input":
                            # import pdb; pdb.set_trace()

                            # if temp_node.description is str:
                            if isinstance(temp_node.description, str):
                                try:
                                    temp_node.description = json.loads(temp_node.description)
                                    obj_dict = {
                                        "name": temp_node.father.description,
                                        "arguments": temp_node.description,
                                        "function_output": temp_node.observation,
                                        "mento-carlo-action-value": temp_node.compute_weight(),
                                    }
                                    js_list.append(obj_dict)
                                except:
                                    pass

                    if len(js_list) > 0:
                        former_candidates_des = former_candidates_des + f"{json.dumps(js_list,indent=2)}\n"
                        if now_node.observation != "":
                            former_candidates_des = former_candidates_des + f"again, your former observation: {now_node.observation}\n"
                        diverse_prompt = diverse_prompt.replace("{previous_candidate}",former_candidates_des)
                        # record current time in hour-minutes-seconds

                        now_time = datetime.datetime.now()
                        now_time = now_time.strftime("%H:%M:%S")

                        now_node.messages.append({"role":"user", "content":diverse_prompt, "time": str(now_time)})

                        self.llm.change_messages(self.role_description, now_node.messages)
                        # self.llm.display_conversation()

            self.llm.change_messages(self.role_description, now_node.messages)
            # self.llm.display_conversation()

            print(colored(f"- Analyzing with tools ...","grey"))
            with tqdm(total=1, bar_format='{l_bar}{bar}| {n_fmt}/{total_fmt}') as pbar:
                new_message = self.llm.parse()
                pbar.update(1)

            # print(f"New message:\t{new_message['content']}")
            assert new_message["role"] == "assistant"
            if new_message not in now_node.messages:
                now_node.messages.append(new_message)

            if first_time:
                first_time = False
                '''
                如果拼接了diversity prompt，要去掉
                '''
                try:
                    if "This is not the first time you try this task" in now_node.messages[-1]["content"]:
                        now_node.messages = now_node.messages[:-1]
                except BaseException as e:
                    # print(e)
                    pass

            if "content" in new_message.keys() and new_message["content"] != None:

                for _ in range(3):
                    parsed_response = self.output_parser.parse(new_message)

                    if parsed_response != None:
                        break

                    print(colored(f"- Analyzing with tools ...","grey"))
                    with tqdm(total=1, bar_format='{l_bar}{bar}| {n_fmt}/{total_fmt}') as pbar:
                        new_message = self.llm.parse()
                        pbar.update(1)

                    time.sleep(0.5)

                # action --> temp_node
                temp_node = tree_node()
                temp_node.node_type = "Thought"
                temp_node.description = new_message["content"]

                child_env = deepcopy(now_node.env)

                temp_node.env = child_env
                temp_node.is_terminal = False
                temp_node.messages = now_node.messages.copy()
                # temp_node.messages.append(new_message)
                temp_node.father = now_node
                now_node.children.append(temp_node)
                # temp_node.print()
                now_node = temp_node
                this_simulation.append({"choice":0,"new_generated":True,"score":now_node.env.get_score()})

                if isinstance(parsed_response, AgentAction):
                    # If the response is an action, call the tool
                    # and append the observation to tool_observation
                    parameters = []
                    if "whether_is_abnormal_metric" in parsed_response.tool:

                        metric_name = self.name.lower()
                        metric_name = metric_name.replace("expert","") + "_" + "usage"

                        parameters = {"start_time": self.start_time,
                                    "end_time": self.end_time,
                                    "metric_name": metric_name}
                    elif "match_diagnose_knowledge" in parsed_response.tool and self.alert_dict != None:
                        # node_load1{instance="$instance"}
                        for alert in self.alert_dict:
                            metric_name = alert["alert_desc"].split('[')[0]
                            host = alert["alert_exporter"]
                            alert_metric = f"{metric_name}{{instance=\"{host}\"}}"

                            metric_name = self.name.lower()
                            metric_name = metric_name.replace("expert","") + "_" + "usage"

                            parameters.append({"start_time": self.start_time, "end_time": self.end_time, "metric_name": metric_name, "alert_metric": alert_metric, "diag_id": self.diag_id})
                    else:
                        # import pdb; pdb.set_trace()
                        try:
                            parameters = json.loads(parsed_response.tool_input)
                        except:
                            parameters = None

                    observation = None
                    if "obtain_start_and_end_time_of_anomaly" in parsed_response.tool and self.alert_dict != [] and self.alert_dict != None:
                        observation = f"The start time is {self.start_time}, and the end time is {self.end_time}."
                    else:
                        if isinstance(parameters, list):
                            observation = []
                            for parameter in parameters:
                                result = temp_node.env.tool.call_function(parsed_response.tool, **parameter)
                                if isinstance(result, (tuple, list)):
                                    observation.append(result[0])
                                    top_abnormal_metric_values = result[1]
                                else:
                                    observation.append(result)

                        elif parameters == None:
                            pass
                        else:
                            # observation = temp_node.env.tool.call_function(parsed_response.tool, **parameters)
                            result = temp_node.env.tool.call_function(parsed_response.tool, **parameters)

                            if isinstance(result, (tuple, list)):
                                observation = result[0]
                                top_abnormal_metric_values = result[1]
                            else:
                                observation = result

                    # tool_observation.append(
                    #     parsed_response.log.strip()
                    #     + f"\nObservation: {str(observation).strip()}"
                    # )
                    if observation == None:
                        # 0代表正常返回
                        # 1代表没有对应api名字
                        # 2代表输入有错误
                        # 3代表生成结束，出现final answer
                        # 4代表模型自己决定剪枝
                        now_node.pruned = True
                        # now_node.messages.append(new_message)
                        return now_node, top_abnormal_metric_values

                    # new the Action node
                    temp_node = tree_node()
                    temp_node.node_type = "Action"
                    temp_node.description = parsed_response.tool # check
                    child_env = deepcopy(now_node.env)

                    temp_node.env = child_env
                    temp_node.is_terminal = False
                    temp_node.messages = now_node.messages.copy()
                    temp_node.father = now_node
                    now_node.children.append(temp_node) # the action node is child of the thought node

                    # temp_node.print()
                    now_node = temp_node
                    this_simulation.append({"choice":0,"new_generated":True,"score":now_node.env.get_score()})

                    # new the Action Input and Observation node
                    function_input = parameters
                    temp_node = tree_node()
                    temp_node.node_type = "Action Input"
                    temp_node.description = function_input
                    child_env = deepcopy(now_node.env)

                    # observation, status = child_env.step(action_name=now_node.description, action_input=function_input)
                    temp_node.observation = observation
                    temp_node.env = child_env
                    temp_node.is_terminal = False
                    temp_node.messages = now_node.messages.copy()

                    now_time = datetime.datetime.now()
                    now_time = now_time.strftime("%H:%M:%S")
                    temp_message = {"role": "function", "content": f'{observation}', "time": str(now_time)}
                    if temp_message not in temp_node.messages:
                        temp_node.messages.append(temp_message)

                    temp_node.father = now_node
                    now_node.children.append(temp_node)
                    now_node = temp_node
                    this_simulation.append({"choice":0,"new_generated":True,"score":now_node.env.get_score()})
                else:
                    pass

            # if now_node.node_type == "Action Input":

            #     now_time = datetime.datetime.now()
            #     now_time = now_time.strftime("%H:%M:%S")

            #     now_node.messages.append({
            #         "role":"function",
            #         "name": parsed_response.tool,
            #         "content": str(now_node.observation),
            #         "time": str(now_time)
            #     })
            # else:
            #     now_node.messages.append(new_message)

            now_node.is_terminal = now_node.env.check_success(now_node.messages[-1])

            # evaluate whether optimization solutions are proposed in the now_node (terminal status)

        return now_node, top_abnormal_metric_values

    # def _fill_prompt_template(
    #     self, node_tools, env_description: str = "", tool_observation: List[str] = [], messages: List[dict] = []
    # ) -> str:

    #     """Fill the placeholders in the prompt template

    #     In the tool agent, these placeholders are supported:
    #     - ${agent_name}: the name of the agent
    #     - ${env_description}: the description of the environment
    #     - ${role_description}: the description of the role of the agent
    #     - ${chat_history}: the chat history of the agent
    #     - ${tools}: the list of tools and their usage
    #     - ${tool_names}: the list of tool names
    #     - ${tool_observations}: the observation of the tool in this turn
    #     """
    #     #retriever = api_retriever()

    #     #relevant_tools = retriever.query(Template(self.prompt_template).safe_substitute({"chat_history": self.memory.to_string(add_sender_prefix=True)}), self.tools)

    #     tools = "\n".join([f"> {api}: {node_tools.functions[api]['desc']}" for api in node_tools.functions])
    #     tools = tools.replace("{{", "{").replace("}}", "}")
    #     tool_names = ", ".join([api for api in node_tools.functions])

    #     if self.start_time != "":
    #         input_arguments = {
    #             "start_time": self.start_time,
    #             "end_time": self.end_time,
    #             "agent_name": self.name,
    #             "env_description": env_description,
    #             #"role_description": self.role_description,
    #             "chat_history": self.memory.to_string(add_sender_prefix=True),
    #             "tools": tools,
    #             "tool_names": tool_names,
    #             "tool_observation": "\n".join(tool_observation),
    #         }
    #     else:
    #         input_arguments = {
    #             "agent_name": self.name,
    #             "env_description": env_description,
    #             #"role_description": self.role_description,
    #             "chat_history": self.memory.to_string(add_sender_prefix=True),
    #             "tools": tools,
    #             "tool_names": tool_names,
    #             "tool_observation": "\n".join(tool_observation),
    #         }

    #     import pdb; pdb.set_trace()

    #     return Template(self.prompt_template).safe_substitute(input_arguments)


from email.message import EmailMessage

import config
import validate_address
# ______________________________________________________________________________
# set mail server data

def BuildTable(info):
    '''
    Uses the information of a person to construct a table containing the
    payments the person has to do and the reason why they have to pay that.

    param info: information to a person
    return t: str table with the due pay ments
    '''
    t = '\n| Betrag  | Verwendungszweck'
    t += '\n----------------------------------------------------\n'
    i = 3
    while i < len(info)-1:
        value = str(info[i+1])
        if value == 'nan':
            value = 0
        elif float(value) == 0:
            value = 0
        else:
            t += '| {:6.2f}€ | {}\n'.format(float(value), info[i])
        i += 2
    return t+'\n'

def BildMail(info):
    '''Gets information of a specific person and builds the e-mail for this
    person. This then is put in a EmailMessage() which is defined in the
    package email.message. This contains all necessary propatys of the e-mail.

    param info: list of information to one person
    param ConfigFile: filename where the text that is ont changed is stored
    return message: final configured e-mail
    '''
    receiver = [info[2]]
    receiverName = info[1]  # only first name ist used
    # Seting up mail
    message = EmailMessage()
    message["From"] = config.settings['address']
    message["To"] = receiver

    if info[0] == -1:
        static = open(config.settings['static_mail_err']).read()
        static = static.split('#Cut\n')
        message["Subject"] = static[0]
        content = static[1] + ' unknown' + static[2] + '' + static[3]

    else:
        # Getting configured Text
        static = open(config.settings['static_mail']).read()
        static = static.split('#Cut\n')
        message["Subject"] = static[0]
        # gets table for mail
        table = BuildTable(info)
        # puts together all parts of the content
        content = static[1] + receiverName + static[2] + table + static[3]

    message.set_content(content, "utf-8")
    return message


import json
import logging
from unittest import mock

import olympia.core.logger
from olympia.amo.tests import TestCase
from olympia.users.models import UserProfile

class LoggerTests(TestCase):
    def make_fake_record(self, msg='Some fake message', level=logging.NOTSET):
        return logging.LogRecord(
            'loggername',  # name
            level,  # level
            '/some/path',  # pathname
            42,  # lineno
            msg,  # msg
            (),  # args
            None,  # exc_info
        )

    @mock.patch('olympia.core.get_remote_addr', lambda: '127.0.0.1')
    @mock.patch('olympia.core.get_user', lambda: UserProfile(username='fôo'))
    def test_get_logger_adapter(self):
        log = olympia.core.logger.getLogger('test')
        expected_kwargs = {
            'extra': {
                'REMOTE_ADDR': '127.0.0.1',
                'USERNAME': 'fôo',
            }
        }
        assert log.process('test msg', {}) == ('test msg', expected_kwargs)

    @mock.patch('olympia.core.get_remote_addr', lambda: '127.0.0.1')
    @mock.patch('olympia.core.get_user', lambda: None)
    def test_logger_adapter_user_is_none(self):
        log = olympia.core.logger.getLogger('test')
        expected_kwargs = {
            'extra': {
                'REMOTE_ADDR': '127.0.0.1',
                'USERNAME': '<anon>',
            }
        }
        assert log.process('test msg', {}) == ('test msg', expected_kwargs)

    @mock.patch('olympia.core.get_remote_addr', lambda: None)
    @mock.patch('olympia.core.get_user', lambda: UserProfile(username='bar'))
    def test_logger_adapter_addr_is_none(self):
        log = olympia.core.logger.getLogger('test')
        expected_kwargs = {
            'extra': {
                'REMOTE_ADDR': '',
                'USERNAME': 'bar',
            }
        }
        assert log.process('test msg', {}) == ('test msg', expected_kwargs)

    @mock.patch('olympia.core.get_remote_addr', lambda: '127.0.0.1')
    @mock.patch(
        'olympia.core.get_user',
        lambda: UserProfile(username='fôo', email='foo@bar.com'),
    )
    def test_get_logger_adapter_with_extra(self):
        log = olympia.core.logger.getLogger('test')
        expected_kwargs = {
            'extra': {
                'REMOTE_ADDR': '127.0.0.1',
                'USERNAME': 'fôo',
                'email': 'foo@bar.com',
            }
        }
        extra = {'extra': {'email': 'foo@bar.com'}}
        assert log.process('test msg', extra) == ('test msg', expected_kwargs)

    def test_json_formatter(self):
        formatter = olympia.core.logger.JsonFormatter()
        record = self.make_fake_record()
        # These would be set by the adapter.
        record.__dict__['USERNAME'] = 'foo'
        record.__dict__['REMOTE_ADDR'] = '127.0.0.1'
        formatted = json.loads(formatter.format(record))
        assert record.__dict__['uid'] == 'foo'
        assert record.__dict__['remoteAddressChain'] == '127.0.0.1'
        assert formatted['Fields'] == {
            'msg': 'Some fake message',
            'uid': 'foo',
            'remoteAddressChain': '127.0.0.1',
        }

    def test_json_formatter_severity(self):
        formatter = olympia.core.logger.JsonFormatter()

        record = self.make_fake_record(level=logging.NOTSET)
        formatted = json.loads(formatter.format(record))
        assert formatted['severity'] == 0  # For Stackdriver
        assert formatted['Severity'] == 7  # For MozLog 2.0 (7 is default)

        record = self.make_fake_record(level=logging.DEBUG)
        formatted = json.loads(formatter.format(record))
        assert formatted['severity'] == 100  # For Stackdriver
        assert formatted['Severity'] == 7  # For MozLog 2.0

        record = self.make_fake_record(level=logging.INFO)
        formatted = json.loads(formatter.format(record))
        assert formatted['severity'] == 200  # For Stackdriver
        assert formatted['Severity'] == 6  # For MozLog 2.0

        record = self.make_fake_record(level=logging.WARNING)
        formatted = json.loads(formatter.format(record))
        assert formatted['severity'] == 400  # For Stackdriver
        assert formatted['Severity'] == 4  # For MozLog 2.0

        record = self.make_fake_record(level=logging.ERROR)
        formatted = json.loads(formatter.format(record))
        assert formatted['severity'] == 500  # For Stackdriver
        assert formatted['Severity'] == 3  # For MozLog 2.0

        record = self.make_fake_record(level=logging.CRITICAL)
        formatted = json.loads(formatter.format(record))
        assert formatted['severity'] == 600  # For Stackdriver
        assert formatted['Severity'] == 2  # For MozLog 2.0


import pandas as pd
from nltk.tokenize import RegexpTokenizer
import nltk as nltk
from nltk.corpus import stopwords
from nltk.stem import PorterStemmer

nltk.download('stopwords')
nltk.download('punkt')

# federalist txt
authors = 'data/federalist.txt'

final_dataset = pd.DataFrame(columns=['author', 'body'])

f = open(authors)
full_text = f.read()
f.close

# Clean linebreaks and encodings
full_text_lower = full_text.replace(u'\ufeff', '')
full_text_lower = full_text.replace(u'\n', ' ')
full_text_lower = full_text.lower()

# Remove punctuation
tokenizer = RegexpTokenizer(r'\w+')
full_text = tokenizer.tokenize(full_text_lower)
preprocessed_text = ' '.join(full_text)

# exctact author, chapter title and text

startindex = []
endindex = []
authors = []
titles = []

for i in range(0, 85):  # Split into the 85 chapters
    search = 'federalist no ' + str(i + 1)
    startindex.append(preprocessed_text.find(search))  # Start point of chapter
    endindex.append(startindex[i] + len(search) + 1)  # End point of chapter

# find author of each chapter
for i in range(84):
    find_jay = preprocessed_text.find('jay', endindex[i], startindex[i + 1])
    find_hamilton = preprocessed_text.find('hamilton', endindex[i], startindex[i + 1])
    find_madison = preprocessed_text.find('madison', endindex[i], startindex[i + 1])
    find_HwM = preprocessed_text.find('madison with hamilton', endindex[i], startindex[i + 1])
    if find_jay != -1:
        df = {
            'author': 'jay',
            'body': preprocessed_text[find_jay + 4:startindex[i + 1]]
        }
    elif find_HwM != -1:
        df = {
            'author': 'madison with hamilton',
            'body': preprocessed_text[find_madison + 22:startindex[i + 1]]
        }
    elif find_hamilton != -1:
        df = {
            'author': 'hamilton',
            'body': preprocessed_text[find_hamilton + 9:startindex[i + 1]]
        }
    elif find_madison != -1:
        df = {
            'author': 'madison',
            'body': preprocessed_text[find_madison + 8:startindex[i + 1]]
        }
    final_dataset = final_dataset.append(df, ignore_index=True)

find_hamilton = preprocessed_text.find('hamilton', endindex[84])
df = {
    'author': 'hamilton',
    'body': preprocessed_text[find_hamilton + 9:1124005]
}
final_dataset = final_dataset.append(df, ignore_index=True)

# open each row in df and apply preproccessing

for i, text in enumerate(final_dataset['body']):
    # remove stop words
    words = nltk.word_tokenize(text)
    stop_words = set(stopwords.words('english'))
    filtered_output = [word for word in words if word not in stop_words]
    # # # stemming
    # stemmer = PorterStemmer()
    # stemmed_output = [stemmer.stem(word) for word in filtered_output]
    # # # Join the stemmed words back into a single string
    new_text = ' '.join(filtered_output)

    final_dataset.at[i, 'body'] = new_text
#
#     #
#     #
#     #
final_dataset.to_csv("data/text_stop.csv", index=False)


import sys
from pathlib import Path

DIR = Path(__file__).resolve().parent
sys.path.insert(0, str(DIR.parent.parent.parent.parent))
__package__ = DIR.name

import django

django.setup()
from BaseClass import *
from scrapy import signals

store_url = sys.argv[4]

class PrettylittlethingScrapper(Spider_BaseClass):
    @classmethod
    def from_crawler(cls, crawler, *args, **kwargs):
        spider = super(PrettylittlethingScrapper, cls).from_crawler(crawler, *args, **kwargs)
        crawler.signals.connect(spider.spider_closed, signal=signals.spider_closed)
        return spider

    def GetProductUrls(self, response):
        topCategoryNodes = response.xpath(
            "(//nav[@class='hidden']/ul/li/div[h3/a[contains(text(),'NEW') or contains(text(),'SALE')  or  contains("
            "text(),'SUMMER') or contains(text(),'FIGURE') or contains(text(),'CLOTHING') or contains(text(),"
            "'DRESSES') or contains(text(),'MOLLY')]])[1]")
        for top_category_node in topCategoryNodes:
            top_category_title = top_category_node.xpath("./h3/a/text()").get().strip()
            print("TOP CATEGORY  :", top_category_title)
            category_nodes = top_category_node.xpath("(./ul/li[h4/a[not(contains(text(),'SHOP')) and not(contains(text("
                                                     "),'Sizes')) and not(contains(text(),'MATERNITY')) and not("
                                                     "contains(text(),'SWIMWEAR')) and not(contains(text(),"
                                                     "'ACCESSORIES')) and not(contains(text(),'SHOES')) and not("
                                                     "contains(text(),'BEAUTY'))]])[1]")
            for category_node in category_nodes:
                category_title = category_node.xpath("./h4/a/text()").get().strip()
                print("category_title :", category_title)
                sub_category_nodes = category_node.xpath(
                    "(./ul/li/a[not(contains(text(),'All')) and  contains(text(),'Dresses') or contains(text(),"
                    "'Bodysuits') or contains(text(),'Jump') or contains(text(),'Loungewear') or contains(text(),"
                    "'Petite') or contains(text(),'Skirts')])[1]")
                for sub_category_node in sub_category_nodes:
                    sub_category_title = sub_category_node.xpath("./text()").get().strip()
                    sub_category_link = sub_category_node.xpath("./@href").get()
                    if not sub_category_link.startswith(store_url):
                        sub_category_link = store_url.rstrip('/') + sub_category_link
                    print(sub_category_title, " :", sub_category_link)
                    category = top_category_title + " " + category_title + " " + sub_category_title
                    self.listing(sub_category_link, category)
        return Spider_BaseClass.AllProductUrls

    def listing(self, subCategorylink, category):
        subCategoryLinkResponse = requests.get(subCategorylink)
        subCategoryLinkResponse = HtmlResponse(url=subCategorylink, body=subCategoryLinkResponse.text,
                                               encoding='utf-8')
        product_list = subCategoryLinkResponse.xpath(
            "(//a[contains(@class,'product-url')]/@href)[1]").extract()
        for productUrl in product_list:
            if not productUrl.startswith(store_url):
                productUrl = store_url.rstrip('/') + productUrl
            print('PRODUCT URL :', productUrl)
            Spider_BaseClass.AllProductUrls.append(productUrl)
            siteMapCategory = str(Spider_BaseClass.ProductUrlsAndCategory.get(productUrl)).replace('None', '')
            if siteMapCategory:
                Spider_BaseClass.ProductUrlsAndCategory[productUrl] = siteMapCategory + " " + category
            else:
                Spider_BaseClass.ProductUrlsAndCategory[productUrl] = category
        try:
            nextPageUrl = subCategoryLinkResponse.xpath("//a[@class='load-more-btn']/@href").get()
            if not nextPageUrl.startswith(store_url):
                nextPageUrl = store_url.rstrip('/') + nextPageUrl
                print("NEXT PAGE :", nextPageUrl)
            self.listing(nextPageUrl, category)
        except:
            pass
    def GetProducts(self, response):
        ignorProduct = self.IgnoreProduct(response)
        if ignorProduct == True:
            self.ProductIsOutofStock(GetterSetter.ProductUrl)
        categoryAndName = self.GetCategory(response) + " " + self.GetName(response)
        if (re.search('Sale', categoryAndName, re.IGNORECASE) or
            re.search('New', categoryAndName, re.IGNORECASE)) and not \
                re.search(r'\b((shirt(dress?)|jump(suit?)|dress|set|gown|suit|caftan)(s|es)?)\b', categoryAndName,
                          re.IGNORECASE):
            print('Skipping Non Dress Product')
            self.ProductIsOutofStock(GetterSetter.ProductUrl)
        else:
            self.GetProductInfo(response)

    def GetName(self, response):
        color = self.GetSelectedColor(response)
        name = str(response.xpath("//h1[@class='product-view-title']/text()").get()).strip()
        if not color == '' and not re.search(color, name, re.I):
            name = name + " - " + color
        print("name =", name)
        return name

    def GetSelectedColor(self, response):
        color = str(response.xpath("//div[@class='colour-option-label']/p/span[2]/text()").get()).strip()
        return color
    def GetPrice(self, response):
        orignalPrice = response.xpath(
            "//div[contains(@class,'price-target')]/p[contains(@class,'regular')]/span/text()").get()
        if orignalPrice != None:
            return float(str(orignalPrice).strip().replace('$', '').replace(',', '').replace('USD',''))
        else:
            regularPrice = response.xpath(
                "//div[contains(@class,'price-target')]/p[contains(@class,'old')]/span/text()").get()
            return float(str(regularPrice).strip().replace('$', '').replace(',', '').replace('USD',''))

    def GetSalePrice(self, response):
        salePrice = response.xpath(
            "//div[contains(@class,'price-target')]/p[contains(@class,'new')]/span[1]/text()").get()
        if salePrice is not None:
            return float(str(salePrice).strip().replace('$', '').replace(',', '').replace('USD',''))
        else:
            return 0
    def GetDescription(self, response):
        return ' '.join(response.xpath("//div[contains(@class,'description')]//p//text()").extract()).strip()

    def GetBrand(self, response):
        brand = str(response.text).split("brand':")[1].split(',')[0].replace('"',"")
        return brand
    def GetSizes(self, response):
        sizes = []
        sizeList = response.xpath(
            "//div[contains(@class,'size-in-stock')]")
        gender = ProductFilters.objects.get(ProductUrl=GetterSetter.ProductUrl).ParentCategory.split(',')[0]
        color = self.GetSelectedColor(response)
        for size in sizeList:
            sizename = size.xpath("./text()").get().strip()
            available = True
            fitType = GetFitType(gender, sizename)
            sizes.append((color, sizename, available, fitType, 0.0, 0.0))
        return sizes
    def GetImageUrl(self, response):
        imageUrls = []
        image_nodes = response.xpath(
            "//div[@itemprop='associatedMedia']/img")
        for image in image_nodes:
            umage_url = image.xpath("./@src").get().strip()
            imageUrls.append(umage_url)
        return imageUrls
    def GetCategory(self, response):
        siteMapCategory = str(Spider_BaseClass.ProductUrlsAndCategory.get(GetterSetter.ProductUrl)).replace('None', '')
        return "Women " + siteMapCategory +  "jeans "


import numpy as np
import pandas as pd
import re
import matplotlib.pyplot as plt
import seaborn as sns

from nltk.corpus import stopwords
from nltk.stem.porter import PorterStemmer

from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.model_selection import train_test_split
from sklearn.tree import DecisionTreeClassifier
from sklearn.metrics import accuracy_score

import nltk
nltk.download('stopwords')

# printing stopwords in English
print(stopwords.words('english'))

# Data-Preprocessing
# loading the dataset
news_dataset = pd.read_csv('fake_or_real_news.csv')

# print the first 5 rows of the dataset
news_dataset.head()

# counting the number of missing valuesin the dataset
news_dataset.isnull().sum()

# replacing the null values with empty strings
news_dataset = news_dataset.fillna('')

#merging the author name and news title
news_dataset['content'] = news_dataset['text']

print(news_dataset['content'])

# separating the data and the label
X = news_dataset.drop(columns=['label'],axis=1)
Y = news_dataset['label']

# Stemming: It is the process of reducing a word to its root word.(remove␣suffix and prefix)
port_stem = PorterStemmer()

def stemming(content):
    stemmed_content = re.sub('[^a-zA-Z]',' ',content)
    stemmed_content = stemmed_content.lower()
    stemmed_content = stemmed_content.split()
    stemmed_content = [port_stem.stem(word) for word in stemmed_content if not word in stopwords.words('english')]
    stemmed_content = ' '.join(stemmed_content)
    return stemmed_content

news_dataset['content'] = news_dataset['content'].apply(stemming)

print(news_dataset['content'])

#separating the data and label
X = news_dataset['content'].values
Y = news_dataset['label'].values

# converting the textual data to numerical data
vectorizer = TfidfVectorizer()
vectorizer.fit(X)
X = vectorizer.transform(X)

# Splitting the dataset to training & test data
X_train, X_test, Y_train, Y_test = train_test_split(X, Y, test_size = 0.2,stratify=Y, random_state=42)

clf_dt=DecisionTreeClassifier()
clf_dt=clf_dt.fit(X_train, Y_train)

predictions_dt = clf_dt.predict(X_test)
test_data_accuracy_dt = accuracy_score(predictions_dt, Y_test)
test_data_accuracy_dt = round(test_data_accuracy_dt, 3)
print('Accuracy score of the test data : ', test_data_accuracy_dt)

from sklearn.metrics import classification_report
from sklearn.metrics import confusion_matrix

print(classification_report(Y_test, predictions_dt))
mat=confusion_matrix(Y_test, predictions_dt)
print(confusion_matrix(Y_test, predictions_dt))

# Making a Predictive System
X_new = X_test[3]
prediction = clf_dt.predict(X_new)
print(prediction)
if (prediction[0]=='REAL'):
    print('The news is Real')
else:
    print('The news is Fake')

classes = ['Real','Fake']

cm_df = pd.DataFrame(mat, index = classes,columns = classes)
plt.figure(figsize = (5,5))
sns.set(font_scale=1.2)
sns.heatmap(cm_df, annot = True,cbar=False,linewidth=2,fmt='d',cmap="GnBu")
plt.title('Confusion Matrix for Decision Tree Classifier')
plt.ylabel('Original Values')
plt.xlabel('Predicted Values')
plt.savefig('Cm_dt.png')
plt.show()

import joblib
joblib.dump(clf_dt, 'model.pkl')
joblib.dump(vectorizer, 'vectorizer.pkl')


from collections import defaultdict
from math import sqrt
import sys

#AC
input = sys.stdin.readline

def check(c, i, m): #O(sqrt(n))
    for j in range(1, int(sqrt(i))+1):
        if i%j == 0 and j <= m:
            c[i].add(j)
            if i//j <= m:
                c[i].add(i//j)

for _ in range(int(input())):
    n, m = map(int, input().split())
    arr = list(map(int, input().split()))
    arr.sort()
    c = defaultdict(set) # This dictionary contains divisors (up to 'm') of [Ai] number. #Complexity sqrt(n)
    for i in arr:
        check(c, i, m)
    d = defaultdict(int)
    j = 0
    ans = float('inf')

    # Here, if there no valid solution, we extend right pointer (j) until a valid solution.
    # While a valid solution is found we move the left pointer (i) to right while keeping the left right pointer (j) stationary and repeat.
    for i in range(n): #O(n)
        while j < n:
            if len(d) == m:
                ans = min(ans, abs(arr[i]-arr[j-1]))
                break
            else:
                for k in c[arr[j]]:
                    d[k] += 1
                j += 1
        if len(d) == m:
                ans = min(ans, abs(arr[i]-arr[j-1]))

        for k in c[arr[i]]:
            d[k] -= 1
            if d[k] == 0:
                del d[k]

    if ans == float('inf'):
        print("-1")
    else:
        print(ans)


from pathlib import Path
import sys

parent_dir = Path(__file__).parent
file_name = Path(__file__).stem

sys.stdin = open(f"{parent_dir}\{file_name} input.txt")
input = sys.stdin.readline

from collections import deque

T = int(input())
for test_case in range(1, T + 1):
    N, M = map(int, input().split())
    Q = deque([int(n) for n in input().split()])

    for _ in range(M):
        # Q.append(Q.popleft())
        Q.rotate(-1)

    print("#{} {}".format(test_case, Q[0]))


from abc import ABC, abstractmethod
from flask import request
import logging
import mlog

logger = logging.getLogger('endpoint')

class Endpoint(ABC):
    def __init__(self, dbClient, mqClient, logger, env):
        self.dbClient = dbClient
        self.mqClient = mqClient
        self.logger = logger
        self.env = env
        super().__init__()

    def publish(self, topic, data):
        self.mqClient.publish(topic, data)

    @abstractmethod
    def handle(path_data, request_data):
        pass

registered_endpoints = []

def register(url, methods):
    def decorator(cls):
        logger.debug(f'Registering class {cls.__name__} with url {url} and methods {methods}')
        cls.url = url
        cls.methods = methods

        registered_endpoints.append(cls)
    return decorator

def _make(ep, dbClient, mqClient, env):
    def _(*args, **kwargs):
        inst = ep(dbClient, mqClient, logging.getLogger(ep.__name__), env)
        logger.debug(f'Endpoint instance is of type {type(inst)}')
        path_data = kwargs
        logger.debug(f'invoked endpoint {ep.__name__}')
        logger.debug(f'path data: {path_data}')
        logger.debug(f'request data: {request}')
        return inst.handle(path_data, request)
    return _

def load(flaskApp, dbClient, mqClient, env):
    for ep in registered_endpoints:
        mlog.configLoggers([ep.__name__], env.logs_folder, env.debug_mode)
        logger.debug(f'Adding flask url rule {ep.url} with {ep.__name__}')
        flaskApp.add_url_rule(ep.url, ep.__name__, _make(ep, dbClient, mqClient, env), methods=ep.methods)


#!/usr/bin/python3

import sys
import enum
import math

import rospy
from nav_msgs.msg import Odometry
from sensor_msgs.msg import LaserScan
from geometry_msgs.msg import Twist
from argos_bridge.msg import ProximityList
from argos_bridge.msg import BaseGroundList
from argos_bridge.msg import MotoGroundList
from argos_bridge.msg import PuckList
from argos_bridge.msg import Position
from std_msgs.msg import Bool

class OrientationFromTag(enum.IntEnum):
    NOT_SPECIFIED = -1
    NORTH = 0
    EAST = 1
    SOUTH = 2
    WEST = 3

class ZoneColor(enum.Enum):
    BLACK = 0
    RED = 1
    BLUE = 2
    GREEN = 3
    YELLOW = 4

class PuckColor(enum.IntEnum):
    UNRECOGNIZED = -2
    NONPUCK = -1
    RED = 0
    BLUE = 1
    GREEN = 2
    YELLOW = 3

class Zone():
    def __init__(self):
        self.zoneColor = ZoneColor.BLACK
        self.zoneNumber = 0
        self.isInZone = False
        self.positionInZone_X = 0
        self.positionInZone_Y = 0
        self.orientationToAxisX = 0

    def SetZoneColor(self, color: ZoneColor):
        self.zoneColor = color

    def SetZoneNumber(self, number):
        self.zoneNumber = number

    def SetIsInZoneFlage(self, inZone: Bool):
        self.isInZone = inZone

    def SetPositionInZoneX(self, x):
        self.positionInZone_X = x

    def SetPositionInZoneY(self, y):
        self.positionInZone_Y = y

    def SetOrientationRad(self, orientation):
        self.orientationToAxisX = orientation

    def GetZoneColor(self):
        return self.zoneColor

    def GetZoneNumber(self):
        return self.zoneNumber

    def IsInZone(self):
        return self.isInZone

    def GetPositionInZoneX(self):
        return self.positionInZone_X

    def GetPositionInZoneY(self):
        return self.positionInZone_Y

    def GetOrientationRad(self):
        return self.orientationToAxisX

class TransportRobot:
    def __init__(self, botName):
        self.botName = botName
        self.robotStop = False

        self.isInZone = False
        self.zone = Zone()
        self.puckColor = PuckColor.NONPUCK

        self.pubMove = rospy.Publisher("/" + botName + "/cmd_vel", Twist, queue_size=10)
        self.pubGripper = rospy.Publisher("/" + botName + "/gripper", Bool, queue_size=10)
        self.move = Twist()
        self.gripper = Bool(False)

        self.proximityList = ProximityList()
        self.newProximityListMsg = False
        self.baseGround = BaseGroundList().baseGrounds
        self.newBaseGroundMsg = False
        self.motoGround = MotoGroundList().motoGrounds
        self.newMotoGroundMsg = False
        self.puckList = PuckList()
        self.newPuckListMsg = False
        self.position = Position()
        self.newPositionMsg = False

        rospy.Subscriber("/" + botName + "/proximity", ProximityList, self.callbackProximity)
        rospy.Subscriber("/" + botName + "/baseGround", BaseGroundList, self.callbackBaseGround)
        rospy.Subscriber("/" + botName + "/motoGround", MotoGroundList, self.callbackMotoGround)
        rospy.Subscriber("/" + botName + "/puck_list", PuckList, self.callbackPuckList)
        rospy.Subscriber("/" + botName + "/position", Position, self.callbackPosition)
        rospy.Subscriber("/" + botName + "/robotStop", Bool, self.callbackRobotStop)

        while self.newMotoGroundMsg == False:
            pass

        #self.TakeNearestPuck()
        #self.EnterToZone(ZoneColor.BLACK)
        #self.zone.SetZoneNumber(1)
        #self.zone.SetIsInZoneFlage(True)
        #self.GetPositionAndOrientationInZone()

        self.EnterToZone(ZoneColor.BLACK)
        self.TakeNearestPuck()
        self.EscapeFromZone()

        self.MoveToForward()
        self.MoveToForward()
        self.MoveToForward()
        self.RotateRight()
        self.MoveToForward()
        self.MoveToForward()
        self.MoveToForward()
        self.MoveToForward()

        self.EnterToZone(ZoneColor.RED)
        #self.PutDownPuckOnPosition(-2.2, 2.2)

    def callbackProximity(self, msg):
        #self.move.linear.x = 0.5
        #if msg.proximities[0].value > 0:
        #    self.move.linear.x = 0

        #print(msg.proximities[0])
        #self.pubMove.publish(self.move)

        self.proximityList = msg
        self.newProximityListMsg = True

    def callbackBaseGround(self, msg):
        self.baseGround = msg.baseGrounds
        self.newBaseGroundMsg = True

    def callbackMotoGround(self, msg):
        self.motoGround =msg.motoGrounds
        self.newMotoGroundMsg = True

    def callbackPuckList(self, msg):
        self.puckList = msg
        self.newPuckListMsg = True

    def callbackPosition(self, msg):
        self.position = msg
        self.newPositionMsg = True

    def callbackRobotStop(self, msg):
        self.robotStop = msg.data

    def GetPuckColor(self):
        return self.puckColor

    def GetOrientationFromTag(self):
        if (self.motoGround[0].value > 0.49 and self.motoGround[0].value < 0.51) and \
           (self.motoGround[3].value > 0.44 and self.motoGround[3].value < 0.46):
            return OrientationFromTag.EAST

        elif (self.motoGround[0].value > 0.44 and self.motoGround[0].value < 0.46) and \
             (self.motoGround[3].value > 0.34 and self.motoGround[3].value < 0.36):
            return OrientationFromTag.SOUTH

        elif (self.motoGround[0].value > 0.34 and self.motoGround[0].value < 0.36) and \
             (self.motoGround[3].value > 0.39 and self.motoGround[3].value < 0.41):
            return OrientationFromTag.WEST

        elif (self.motoGround[0].value > 0.39 and self.motoGround[0].value < 0.41) and \
             (self.motoGround[3].value > 0.49 and self.motoGround[3].value < 0.51):
            return OrientationFromTag.NORTH

        else:
            return OrientationFromTag.NOT_SPECIFIED

    def MoveToForward(self):
        self.move.linear.x = 0.1

        if abs(self.motoGround[0].value - self.motoGround[1].value) > 0.01 and \
           abs(self.motoGround[1].value - self.motoGround[2].value) > 0.01 and \
           abs(self.motoGround[2].value - self.motoGround[3].value) > 0.01 and \
           abs(self.motoGround[3].value - self.motoGround[0].value) > 0.01 :

            #jezeli baseGround 0 i 4 nie sa rowne 0 to poprawic pozycje - dopisac !

            run = True
            while run and not self.robotStop:
                if self.newMotoGroundMsg == True:
                    self.newMotoGroundMsg = False

                    if (self.motoGround[0].value > 0.51 or self.motoGround[0].value < 0.34) and \
                       (self.motoGround[3].value > 0.51 or self.motoGround[3].value < 0.34):
                        run = False
                        self.move.linear.x = 0
                        self.pubMove.publish(self.move)
                        break
                    else:
                        self.move.linear.x = 0.1
                        self.pubMove.publish(self.move)

        run = True
        while run and not self.robotStop:
            if self.newMotoGroundMsg == True:
                self.newMotoGroundMsg = False

                if self.motoGround[0].value <= 0.01 and self.motoGround[3].value <= 0.01:
                    self.move.linear.x = 0.3
                    self.move.angular.z = 0

                elif self.motoGround[0].value >= 0.99 and self.motoGround[3].value <= 0.01:
                    self.move.linear.x = 0.05
                    self.move.angular.z = -0.1

                elif self.motoGround[0].value <= 0.01 and self.motoGround[3].value >= 0.99:
                    self.move.linear.x = 0.05
                    self.move.angular.z = 0.1

                elif (self.motoGround[0].value >= 0.34 and self.motoGround[0].value <= 0.51) and\
                     (self.motoGround[3].value <= 0.01 or self.motoGround[3].value >= 0.99):
                    self.move.linear.x = 0.05
                    self.move.angular.z = 0.1

                elif (self.motoGround[3].value >= 0.34 and self.motoGround[3].value <= 0.51) and\
                     (self.motoGround[0].value <= 0.01 or self.motoGround[0].value >= 0.99):
                    self.move.linear.x = 0.05
                    self.move.angular.z = -0.1

                elif (self.motoGround[0].value >= 0.34 and self.motoGround[0].value <= 0.51) and\
                     (self.motoGround[3].value >= 0.34 and self.motoGround[3].value <= 0.51):
                    run = False
                    self.move.linear.x = 0
                    self.move.angular.z = 0

                elif self.motoGround[0].value >= 0.99 and self.motoGround[3].value >= 0.99:
                    print('Robot: {} got lost'.format(self.robotName))

                self.pubMove.publish(self.move)

        run = True
        while run and not self.robotStop:
            if self.newMotoGroundMsg == True:
                self.newMotoGroundMsg = False

                if (self.motoGround[1].value <= 0.01 and self.motoGround[2].value <= 0.01):
                    self.move.linear.x = 0.05
                    self.move.angular.z = 0

                elif self.motoGround[1].value >= 0.99 and self.motoGround[2].value <= 0.01:
                    self.move.linear.x = 0.05
                    self.move.angular.z = 0.1

                elif self.motoGround[1].value <= 0.01 and self.motoGround[2].value >= 0.99:
                    self.move.linear.x = 0.05
                    self.move.angular.z = -0.1

                elif abs(self.motoGround[0].value - self.motoGround[1].value) > 0.01 and \
                     abs(self.motoGround[1].value - self.motoGround[2].value) > 0.01 and \
                     abs(self.motoGround[2].value - self.motoGround[3].value) > 0.01 and \
                     abs(self.motoGround[3].value - self.motoGround[0].value) > 0.01:

                    self.move.linear.x = 0.05
                    self.move.angular.z = 0

                    if self.baseGround[1].value >= 0.99 and self.baseGround[3].value >= 0.99 and \
                       self.baseGround[5].value >= 0.99 and self.baseGround[7].value >= 0.99:

                        self.move.linear.x = 0.0
                        run = False

                self.pubMove.publish(self.move)

    def RotateLeft(self):
        if abs(self.motoGround[0].value - self.motoGround[1].value) > 0.01 and \
           abs(self.motoGround[1].value - self.motoGround[2].value) > 0.01 and \
           abs(self.motoGround[2].value - self.motoGround[3].value) > 0.01 and \
           abs(self.motoGround[3].value - self.motoGround[0].value) > 0.01 :

            orientationTag = self.GetOrientationFromTag()

            if orientationTag == OrientationFromTag.NORTH:
                finishOrientationTag = OrientationFromTag.WEST
            else:
                finishOrientationTag = orientationTag - 1

            if finishOrientationTag == OrientationFromTag.NORTH:
                finishOrientation = 0;
            elif finishOrientationTag == OrientationFromTag.EAST:
                finishOrientation = -math.pi/2;

            elif finishOrientationTag == OrientationFromTag.SOUTH:
                finishOrientation = math.pi;

            elif finishOrientationTag == OrientationFromTag.WEST:
                finishOrientation = math.pi/2;

        run = True
        while run and not self.robotStop:
            if self.newMotoGroundMsg == True:
                self.newMotoGroundMsg = False

                if finishOrientationTag != self.GetOrientationFromTag():
                    self.move.linear.x = 0
                    self.move.angular.z = 0.8

                elif abs(self.motoGround[0].value - self.motoGround[1].value) <= 0.03 or \
                     abs(self.motoGround[1].value - self.motoGround[2].value) <= 0.03 or \
                     abs(self.motoGround[2].value - self.motoGround[3].value) <= 0.03 or \
                     abs(self.motoGround[3].value - self.motoGround[0].value) <= 0.03:
                    self.move.linear.x = 0
                    self.move.angular.z = 0.6

                elif finishOrientationTag == self.GetOrientationFromTag():

                    if finishOrientationTag != OrientationFromTag.SOUTH and \
                       finishOrientation - self.position.orientation.z > 0.0116 and \
                       finishOrientation - self.position.orientation.z <= 0.05:
                        self.move.linear.x = 0
                        self.move.angular.z = 0.05

                    elif finishOrientationTag == OrientationFromTag.SOUTH and \
                         finishOrientation - self.position.orientation.z > -2*math.pi + 0.0116 and \
                         finishOrientation - self.position.orientation.z <= -2*math.pi + 0.05:
                        self.move.linear.x = 0
                        self.move.angular.z = 0.05

                    elif finishOrientation - self.position.orientation.z < -0.0116 and\
                         finishOrientation - self.position.orientation.z >= -0.05:
                        self.move.linear.x = 0
                        self.move.angular.z = -0.05

                    elif (self.baseGround[1].value >= 0.99 and self.baseGround[3].value >= 0.99 and \
                          self.baseGround[5].value >= 0.99 and self.baseGround[7].value >= 0.99) or\
                          finishOrientation - self.position.orientation.z < -0.012 or \
                         (finishOrientationTag != OrientationFromTag.SOUTH and \
                          finishOrientation - self.position.orientation.z > 0.012) or \
                         (finishOrientationTag == OrientationFromTag.SOUTH and \
                          finishOrientation - self.position.orientation.z > -2*math.pi + 0.012):
                        self.move.linear.x = 0
                        self.move.angular.z = 0.0
                        self.pubMove.publish(self.move)
                        run = False
                        break

                    else:
                        self.move.linear.x = 0
                        self.move.angular.z = 0.15

                self.pubMove.publish(self.move)

    def RotateRight(self):
        if abs(self.motoGround[0].value - self.motoGround[1].value) > 0.01 and \
           abs(self.motoGround[1].value - self.motoGround[2].value) > 0.01 and \
           abs(self.motoGround[2].value - self.motoGround[3].value) > 0.01 and \
           abs(self.motoGround[3].value - self.motoGround[0].value) > 0.01 :

            orientationTag = self.GetOrientationFromTag()

            if orientationTag == OrientationFromTag.WEST:
                finishOrientationTag = OrientationFromTag.NORTH
            else:
                finishOrientationTag = orientationTag + 1

            if finishOrientationTag == OrientationFromTag.NORTH:
                finishOrientation = 0;
            elif finishOrientationTag == OrientationFromTag.EAST:
                finishOrientation = -math.pi/2;

            elif finishOrientationTag == OrientationFromTag.SOUTH:
                finishOrientation = math.pi;

            elif finishOrientationTag == OrientationFromTag.WEST:
                finishOrientation = math.pi/2;

        run = True
        while run and not self.robotStop:
            if self.newMotoGroundMsg == True:
                self.newMotoGroundMsg = False

                if finishOrientationTag != self.GetOrientationFromTag():
                    self.move.linear.x = 0
                    self.move.angular.z = -0.8

                elif abs(self.motoGround[0].value - self.motoGround[1].value) <= 0.03 or \
                     abs(self.motoGround[1].value - self.motoGround[2].value) <= 0.03 or \
                     abs(self.motoGround[2].value - self.motoGround[3].value) <= 0.03 or \
                     abs(self.motoGround[3].value - self.motoGround[0].value) <= 0.03:
                    self.move.linear.x = 0
                    self.move.angular.z = -0.6

                elif finishOrientationTag == self.GetOrientationFromTag():

                    if finishOrientationTag != OrientationFromTag.SOUTH and \
                       finishOrientation - self.position.orientation.z > 0.0116 and \
                       finishOrientation - self.position.orientation.z <= 0.05:
                        self.move.linear.x = 0
                        self.move.angular.z = 0.05

                    elif finishOrientationTag == OrientationFromTag.SOUTH and \
                         finishOrientation - self.position.orientation.z > -2*math.pi + 0.0116 and \
                         finishOrientation - self.position.orientation.z <= -2*math.pi + 0.05:
                        self.move.linear.x = 0
                        self.move.angular.z = 0.05

                    elif finishOrientation - self.position.orientation.z < -0.0116 and\
                         finishOrientation - self.position.orientation.z >= -0.05:
                        self.move.linear.x = 0
                        self.move.angular.z = -0.05

                    elif self.baseGround[1].value >= 0.99 and self.baseGround[3].value >= 0.99 and \
                         self.baseGround[5].value >= 0.99 and self.baseGround[7].value >= 0.99 or\
                          finishOrientation - self.position.orientation.z < -0.012 or \
                         (finishOrientationTag != OrientationFromTag.SOUTH and \
                          finishOrientation - self.position.orientation.z > 0.012) or \
                         (finishOrientationTag == OrientationFromTag.SOUTH and \
                          finishOrientation - self.position.orientation.z > -2*math.pi + 0.012):
                        self.move.linear.x = 0
                        self.move.angular.z = 0.0
                        self.pubMove.publish(self.move)
                        run = False
                        break

                    else:
                        self.move.linear.x = 0
                        self.move.angular.z = -0.15

                self.pubMove.publish(self.move)

    def TakeNearestPuck(self):
        [puckPositionX, puckPositionY] = self.CalculateNearestPuckPosition()

        [puckAngle, puckRange] = self.CalculatePuckAngleAndRange(puckPositionX, puckPositionY)
        print("puck angle: ", puckAngle)
        print("puck range: ", puckRange)
        run = True
        while run and not self.robotStop:
            [puckAngle, puckRange] = self.CalculatePuckAngleAndRange(puckPositionX, puckPositionY)

            if puckRange <= 0.15:
                self.move.linear.x = 0
                self.move.angular.z = 0
                run = False

            elif puckAngle >= 0.05:
                self.move.linear.x = 0
                self.move.angular.z = 0.4

            elif puckAngle <= -0.05:
                self.move.linear.x = 0
                self.move.angular.z = -0.4

            elif puckAngle >= 0.001:
                self.move.linear.x = 0
                self.move.angular.z = 0.01

            elif puckAngle <= -0.001:
                self.move.linear.x = 0
                self.move.angular.z = -0.01

            elif puckRange >= 0.05:
                self.move.linear.x = 0.2
                self.move.angular.z = 0

            elif puckRange >= 0.001:
                self.move.linear.x = 0.01
                self.move.angular.z = 0

            self.pubMove.publish(self.move)

        self.gripper = True
        self.pubGripper.publish(self.gripper)

    def CalculateNearestPuckPosition(self):
        self.GetPositionAndOrientationInZone()
        puckListClone = self.puckList
        nearestPuck = -1
        minRange = 1000
        i = -1

        for puck in puckListClone.pucks:
            i = i + 1

            if (puck.color.r == 165 and puck.color.g == 42 and puck.color.b == 42) or \
               (puck.color.r == 255 and puck.color.g == 140 and puck.color.b == 0):
                continue
            else:
                if puck.range <= minRange:
                    nearestPuck = i
                    minRange = puck.range

        self.SetPuckColor(puckListClone.pucks[nearestPuck].color)

        puckAngle = puckListClone.pucks[nearestPuck].angle
        puckRange = puckListClone.pucks[nearestPuck].range*0.01

        alpha = puckAngle - self.zone.GetOrientationRad()

        dX = math.cos(alpha)*puckRange
        dY = math.sin(alpha)*puckRange

        puckPositionX = self.zone.GetPositionInZoneX() + dX
        puckPositionY = self.zone.GetPositionInZoneY() + dY

        return [puckPositionX, puckPositionY]

    def SetPuckColor(self, color):
        if color.r == 255 and color.g == 0 and color.b == 0:
            self.puckColor = PuckColor.RED
        elif color.r == 0 and color.g == 255 and color.b == 0:
            self.puckColor = PuckColor.GREEN
        elif color.r == 0 and color.g == 0 and color.b == 255:
            self.PuckColor = PuckColor.BLUE
        elif color.r == 255 and color.g == 255 and color.b == 0:
            self.PuckColor = PuckColor.YELLOW
        else:
            self.PuckColor = PuckColor.UNRECOGNIZED

    def CalculatePuckAngleAndRange(self, puckPositionX, puckPositionY):
        self.GetPositionAndOrientationInZone()

        dX = self.zone.GetPositionInZoneX() - puckPositionX
        dY = self.zone.GetPositionInZoneY() - puckPositionY

        range = math.sqrt(dX*dX + dY*dY)

        alpha = math.asin(dY/range)

        puckAngle = self.zone.GetOrientationRad() - alpha
        print("angle: ", puckAngle)
        return [puckAngle, range]

    def EnterToZone(self, zoneColor: ZoneColor):
        self.zone.SetZoneColor(zoneColor)
        self.zone.SetIsInZoneFlage(True)
        print(zoneColor)
        if zoneColor == ZoneColor.BLACK:

            if (self.motoGround[0].value >= 0.39 and self.motoGround[0].value <= 0.41) and \
               (self.motoGround[3].value >= 0.49 and self.motoGround[3].value <= 0.51):

                self.zone.SetZoneNumber(1)
                self.GetPositionAndOrientationInZone()

        if zoneColor == ZoneColor.RED:
            print("Red")
            if(self.motoGround[0].value >= 0.34 and self.motoGround[0].value <= 0.36) and \
              (self.motoGround[3].value >= 0.39 and self.motoGround[3].value <= 0.41):
                print("Red1")
                self.zone.SetZoneNumber(1)
                self.GetPositionAndOrientationInZone()
                print("enter to red zone")

    def GetPositionAndOrientationInZone(self):

        if self.zone.IsInZone():

            if self.zone.GetZoneColor() == ZoneColor.BLACK:
                if self.zone.GetZoneNumber() == 1:

                    [centerLanternRange, centerLanternAngle, secondLanternRange, secondLanternAngle] \
                        = self.GetOrangeBrownLantern()

                    if centerLanternRange == -1 or secondLanternRange == -1:
                        print("Can't get position in zone")
                        return
                    if centerLanternRange == -2 and secondLanternRange == -2:
                        #print("Not new position")
                        return

                    centerSecondRange = 0.525

                    alpha = math.acos((centerSecondRange*centerSecondRange \
                                       + centerLanternRange*centerLanternRange \
                                       - secondLanternRange*secondLanternRange) \
                                      /(2 *centerSecondRange*centerLanternRange))

                    self.zone.SetPositionInZoneY(-math.sin(alpha)*centerLanternRange)
                    self.zone.SetPositionInZoneX(-math.cos(alpha)*centerLanternRange)
                    print("position in zone x: ", self.zone.GetPositionInZoneX())
                    print("position in zone y: ", self.zone.GetPositionInZoneY())

                    beta = math.asin(abs(self.zone.GetPositionInZoneY())/centerLanternRange)
                    self.zone.SetOrientationRad(centerLanternAngle - beta)
                    print("orientation to axis x: ", self.zone.GetOrientationRad())

            if self.zone.GetZoneColor() == ZoneColor.RED:
               if self.zone.GetZoneNumber() == 1:

                   [centerLanternRange, centerLanternAngle, secondLanternRange, secondLanternAngle] \
                        = self.GetOrangeBrownLantern()

                   if centerLanternRange == -1 or secondLanternRange == -1:
                       print("Can't get position in zone")
                       return
                   if centerLanternRange == -2 and secondLanternRange == -2:
                       #print("Not new position")
                       return

                   #centerSecondRange = 1.16297033496
                   centerSecondRange = 0.525
                   print(((centerSecondRange*centerSecondRange \
                                      + centerLanternRange*centerLanternRange \
                                      - secondLanternRange*secondLanternRange) \
                                     /(2 *centerSecondRange*centerLanternRange)))
                   alpha = math.acos((centerSecondRange*centerSecondRange \
                                      + centerLanternRange*centerLanternRange \
                                      - secondLanternRange*secondLanternRange) \
                                     /(2 *centerSecondRange*centerLanternRange))

                   self.zone.SetPositionInZoneY(2.4-math.sin(alpha)*centerLanternRange)
                   self.zone.SetPositionInZoneX(-2.95+math.cos(alpha)*centerLanternRange)
                   print("position in zone x: ", self.zone.GetPositionInZoneX())
                   print("position in zone y: ", self.zone.GetPositionInZoneY())

                   beta = math.asin(abs(2.4-self.zone.GetPositionInZoneY())/centerLanternRange)
                   self.zone.SetOrientationRad(centerLanternAngle - beta)
                   print("orientation to axis x: ", self.zone.GetOrientationRad())

    def GetOrangeBrownLantern(self):
        centerLanternRange = -2
        centerLanternAngle = 0

        secondLanternRange = -2
        secondLanternAngle = 0

        if self.newPuckListMsg == True:
            self.newPuckListMsg = False

            centerLanternRange = -1
            centerLanternAngle = 0

            secondLanternRange = -1
            secondLanternAngle = 0

            puckListClone = self.puckList

            for puck in puckListClone.pucks:

                if centerLanternRange > -1 and secondLanternRange > -1:
                    break

                if puck.color.r == 255 and puck.color.g == 140 and puck.color.b == 0:
                    centerLanternRange = puck.range/100
                    centerLanternAngle = puck.angle

                elif puck.color.r == 165 and puck.color.g == 42 and puck.color.b == 42:
                    secondLanternRange = puck.range/100
                    secondLanternAngle = puck.angle

        return [centerLanternRange, centerLanternAngle, secondLanternRange, secondLanternAngle]

    def EscapeFromZone(self):
        if self.zone.IsInZone():

            self.GetPositionAndOrientationInZone()
            if self.zone.GetZoneColor() == ZoneColor.BLACK:
                if self.zone.GetZoneNumber() == 1:
                    escapePositionX = -0.525
                    escapePositionY = -0.3

                    [escapeAngle, escapeRange] = self.CalculateEscapeAngleAndRange(escapePositionX, escapePositionY)
                    print("escape angle: ", escapeAngle)
                    print("escepe range: ", escapeRange)
                    run = True
                    while run and not self.robotStop:
                        [escapeAngle, escapeRange] = self.CalculateEscapeAngleAndRange(escapePositionX, escapePositionY)

                        if escapeRange <= 0.0001:
                            self.move.linear.x = 0
                            self.move.angular.z = 0
                            run = False

                        elif escapeAngle >= 0.05:
                            self.move.linear.x = 0
                            self.move.angular.z = 0.4

                        elif escapeAngle <= -0.05:
                            self.move.linear.x = 0
                            self.move.angular.z = -0.4

                        elif escapeAngle >= 0.001:
                            self.move.linear.x = 0
                            self.move.angular.z = 0.01

                        elif escapeAngle <= -0.001:
                            self.move.linear.x = 0
                            self.move.angular.z = -0.01

                        elif escapeRange >= 0.05:
                            self.move.linear.x = -0.2
                            self.move.angular.z = 0

                        elif escapeRange >= 0.001:
                            self.move.linear.x = -0.01
                            self.move.angular.z = 0

                        elif escapeRange > 0.00001:
                            self.move.linear.x = -0.0001
                            self.move.angular.z = 0

                        self.pubMove.publish(self.move)

                    run = True
                    while run and not self.robotStop:
                        self.GetPositionAndOrientationInZone()
                        temp = self.zone.GetOrientationRad()

                        if temp >= 0 and temp <= math.pi - 0.05:
                            self.move.linear.x = 0
                            self.move.angular.z = -0.5

                        elif temp >= 0 and temp <= math.pi - 0.001:
                            self.move.linear.x = 0
                            self.move.angular.z = -0.01

                        elif temp >= 0 and temp <= math.pi - 0.0001:
                            self.move.linear.x = 0
                            self.move.angular.z = -0.001

                        elif temp < 0 and temp >= -math.pi + 0.05:
                            self.move.linear.x = 0
                            self.move.angular.z = 0.5

                        elif temp < 0 and temp <= -math.pi + 0.001:
                            self.move.linear.x = 0
                            self.move.angular.z = 0.01

                        elif temp < 0 and temp <= -math.pi + 0.0001:
                            self.move.linear.x = 0
                            self.move.angular.z = 0.001

                        else:
                            self.move.linear.x = 0
                            self.move.angular.z = 0
                            run = False

                        self.pubMove.publish(self.move)

                    self.zone.SetIsInZoneFlage(False)

    def CalculateEscapeAngleAndRange(self, escapePositionX, escapePositionY):
        self.GetPositionAndOrientationInZone()

        dX = self.zone.GetPositionInZoneX() - escapePositionX
        dY = self.zone.GetPositionInZoneY() - escapePositionY

        range = math.sqrt(dX*dX + dY*dY)

        alpha = math.asin(dY/range)

        escapeAngle = self.zone.GetOrientationRad() + alpha

        return [escapeAngle, range]

    def PutDownPuckOnPosition(self, positionX, positionY):
        [angle, range] = self.CalculateAngleAndRangeToPosition(positionX, positionY)

        if not self.CheckPositionIsEmpty(angle, range):
            return False

        #Dodac przesunicie pozycji bo robot ma swoja grubosc
        run = True
        while run and not self.robotStop:
            [angle, range] = self.CalculateAngleAndRangeToPosition(positionX, positionY)
            print("Angle: ", angle)
            print("Range: ", range)

            if range <= 0.2:
                self.move.linear.x = 0
                self.move.angular.z = 0
                run = False

            elif angle >= 0.05:
                self.move.linear.x = 0
                self.move.angular.z = 0.4

            elif angle <= -0.05:
                self.move.linear.x = 0
                self.move.angular.z = -0.4

            elif angle >= 0.001:
                self.move.linear.x = 0
                self.move.angular.z = 0.01

            elif angle <= -0.001:
                self.move.linear.x = 0
                self.move.angular.z = -0.01

            elif range >= 0.22:
                self.move.linear.x = 0.2
                self.move.angular.z = 0

            elif range >= 0.01:
                self.move.linear.x = 0.01
                self.move.angular.z = 0

            self.pubMove.publish(self.move)

        self.gripper = False
        self.pubGripper.publish(self.gripper)

        if self.robotStop:
            return False

        return True

    def CalculateAngleAndRangeToPosition(self, positionX, positionY):
        self.GetPositionAndOrientationInZone()

        dX = self.zone.GetPositionInZoneX() - positionX
        dY = self.zone.GetPositionInZoneY() - positionY

        range = math.sqrt(dX*dX + dY*dY)

        alpha = math.asin(dY/range)

        angle = self.zone.GetOrientationRad() - alpha
        return [angle, range]

    def CheckPositionIsEmpty(self, angle, range):
        puckListClone = self.puckList

        for puck in puckListClone.pucks:
            if (puck.range - range) <= 0.01 and (puck.angle - angle) <= 0.001:
                return False

        return True

def main():
    rospy.init_node('testBot')
    if len(sys.argv) > 1:
           botName = sys.argv[1]
    else:
           botName = "bot"

    print(botName)
    TransportRobot(botName)
    rospy.spin()

if __name__ == '__main__':
    main()


import re
from datetime import datetime
from urllib.parse import quote

import requests

from server.extensions import config

def get_twitter_user_details(url: str):
    username = re.match(r"https://(www\.)?twitter\.com/([a-zA-Z0-9_]+)/?", url).group(2)
    try:
        response = requests.get(
            f"{config['FRONTEND_URL']}/api/twitter/users/{username}"
        )
        if response.status_code != 200:
            raise Exception("")
    except Exception as e:
        print(e)
        raise Exception("The Twitter user does not exist")

    return response.json()["user"]

def get_tweets(username: str, last_scanned: "datetime"):
    try:
        response = requests.get(
            f"{config['FRONTEND_URL']}/api/twitter/tweets/{username}?last_scanned={last_scanned.isoformat()}"
        )
        if response.status_code != 200:
            raise Exception("")
    except Exception as e:
        print(e)
        raise Exception("Please try again later")

    return list(
        map(
            lambda x: {
                "text": x.get("fullText"),
                "date": x.get("createdAt"),
                "url": f"https://twitter.com/user/status/{x.get('id')}",
            },
            response.json().get("tweets"),
        )
    )


import json
import datetime
import RPi.GPIO as GPIO
from time import sleep
from flask import Flask

BIND_ADDRESS = '0.0.0.0'
PORT = 5001

GPIO.setmode(GPIO.BCM)
GPIO.setup(4,GPIO.IN)

# Date to string converter
def date_to_str(o):
    if isinstance(o, datetime.datetime):
        return o.__str__()

def get_data():
    result = GPIO.input(4)
    if result == 1:
        result = False;
    elif result == 0:
        result = True;
    else:
        result = None

    datetime_now = datetime.datetime.now()
    data = {
            "time_stamp": datetime_now,
            "light": result
        }

    sleep(1)
    return data

app = Flask(__name__)

@app.route("/api/light")
def execute_route():
    try:
        json_data = json.dumps(get_data(), default = date_to_str)
        return json_data
    except Exception as err:
        print(f'[ Error ]: err')
        return { 'error': err}

if __name__ == '__main__':
    app.run(host=BIND_ADDRESS, port=PORT, debug=True)


from celery import shared_task
from celery.task import task
from django.contrib.auth.models import User
from celery import Celery
from django.core.mail import send_mail
from django_celery_beat.models import PeriodicTask
from django.core.exceptions import ValidationError
from datetime import timedelta
import datetime
import json

from .models import Todo, CrontabSchedule, Settings

app = Celery()

app.conf.timezone = 'Europe/Vilnius'

@shared_task
def send_welcome_word(user, email, password):
    subject = (f"Welcome onboard {user}")
    body = f"""Thank You for registering on Todo App, {user}! \n
        No more missed or forgotten tasks for job, leisure, travel or anything!
        You can now track your daily activities, organize in groups and get daily reminders.\n
        Your login date is:
        Username: {user}
        Password: {password}\n
        You will receive tasks reminders to this email address as well \n\n
        Todo App Team
    """
    send_mail(subject,
    body,
    'my.todo.apl@gmail.com',
    [email])
    return None

@shared_task
def one_off_task_reminder(subject, body, email):
    send_mail(subject,
    body,
    'my.todo.apl@gmail.com',
    [email])
    return None

@shared_task
def delete_reminder(task_id):
    crontabs = CrontabSchedule.objects.all()
    for cron in crontabs:
        if cron.name.startswith("id:"+str(task_id)):
            cron.delete()

@app.task
def delete_old_tasks():
    users = User.objects.all()
    for user in users:
        interval = Settings.objects.get(user=user)
        todos = Todo.objects.filter(author=user, completed=True, created__lt=(datetime.date.today() - datetime.timedelta(days=interval.interval)))
        if todos.exists():
            for todo in todos:
                todo.delete()

@app.task
def daily_evening_reminder():
    users = User.objects.all()
    for user in users:
        list_of_task = []
        todos = Todo.objects.filter(author=user, completed=False, created=datetime.datetime.today())
        for todo in todos:
            list_of_task.append(todo.title)
        nl = '\n'
        subject = (f"Hey {user}. You have uncompleted tasks left for today!")
        msg = (f"Don't forget about your uncompleted today's tasks:\n{nl.join(map(str, list_of_task))}")
        if len(list_of_task)>0:
            send_mail(subject,
            msg,
            'my.todo.apl@gmail.com',
            [user.email])

@app.task
def daily_morning_reminder():
    users = User.objects.all()
    for user in users:
        list_of_task = []
        todos = Todo.objects.filter(author=user, completed=False, created=datetime.datetime.today())
        for todo in todos:
            list_of_task.append(todo.title)
        nl = '\n'
        subject = (f"Hey {user}. You have tasks waiting for you today!")
        msg = (f"For today your tasks are:\n{nl.join(map(str, list_of_task))}")
        if len(list_of_task)>0:
            send_mail(subject,
            msg,
            'my.todo.apl@gmail.com',
            [user.email])

def custom_reminder(reminder_time, reminder_date, user, task_id, email, title, on_off):
    reminder_hour = reminder_time[0:2]
    reminder_minute = reminder_time[3:5]
    reminder_month = reminder_date[5:7]
    reminder_day = reminder_date[8:10]
    if on_off == True:
        schedule, _ = CrontabSchedule.objects.get_or_create(
            minute=int(reminder_minute),
            hour=int(reminder_hour),
            day_of_week='*',
            day_of_month=int(reminder_day),
            month_of_year=int(reminder_month),
            timezone='Europe/Vilnius',
            name='id'+':'+str(task_id)+'_'+'reminder'+'_'+str(user)+'_'+str(reminder_month)+'_'+str(reminder_day)+'_'+str(reminder_hour)+':'+str(reminder_minute)
            )
        try:
            PeriodicTask.objects.create(
                crontab=schedule,
                name='id'+':'+str(task_id)+'_'+'reminder'+'_'+str(user)+'_'+str(reminder_month)+'_'+str(reminder_day)+'_'+str(reminder_hour)+':'+str(reminder_minute),
                task='todo_items.tasks.one_off_task_reminder',
                args=json.dumps([title, 'This is a reminder for your task!', email]),
                one_off=True,
                )
        except ValidationError:
            PeriodicTask.objects.get(
                crontab=schedule,
                name='id'+':'+str(task_id)+'_'+'reminder'+'_'+str(user)+'_'+str(reminder_month)+'_'+str(reminder_day)+'_'+str(reminder_hour)+':'+str(reminder_minute),
                task='todo_items.tasks.one_off_task_reminder',
                args=json.dumps([title, 'This is a reminder for your task!', email]),
                one_off=True,
                )
    if on_off == False:
        try:
            periodic_task = PeriodicTask.objects.get(name='id'+':'+str(task_id)+'_'+'Reminder'+'_'+str(user)+'_'+str(reminder_month)+'_'+str(reminder_day)+'_'+str(reminder_hour)+':'+str(reminder_minute))
            periodic_task.delete()
        except:
            pass


# Always prefer setuptools over distutils
from setuptools import setup, find_packages
# To use a consistent encoding
from codecs import open
from os import path

here = path.abspath(path.dirname(__file__))

# Get the long description from the relevant file
with open(path.join(here, 'DESCRIPTION.rst'), encoding='utf-8') as f:
    long_description = f.read()

setup(
    name='carrierx',
    version='0.0.1',
    description='Client library for CarrierX API.',
    long_description=long_description,
    url='https://github.com/mkching/carrierx-python',
    author='Michael Ching',
    author_email='mching@carrierx.com',
    license='MIT',
    classifiers=[
        'Development Status :: 3 - Alpha',
        'Intended Audience :: Developers',
        'Topic :: Software Development :: Libraries :: Python Modules',
        'Topic :: Communications :: Telephony',
        'License :: OSI Approved :: MIT License',
        'Programming Language :: Python :: 3',
        'Programming Language :: Python :: 3.2',
        'Programming Language :: Python :: 3.3',
        'Programming Language :: Python :: 3.4',
    ],
    keywords='carrierx',
    packages=find_packages(exclude=['contrib', 'docs', 'tests*']),
    install_requires=['requests'],
    extras_require={
        'dev': ['check-manifest'],
        'test': ['coverage'],
    },
)


""""配置文件"""
import pickle

import torch

device=torch.device("cuda:0"if torch.cuda.is_available() else "cpu")
#############语料相关############
user_dict_path="corpus/user_dict/keyword.txt"
stopwords_path=r"corpus/user_dict/stopwords.txt"#"\corpus\user_dict\stopwords.txt"
classify_corpus_train_path="corpus/classify/classify_train.txt"
classify_corpus_test_path="corpus/classify/classify_test.txt"

classify_corpus_by_word_train_path="corpus/classify/classify_train_by_word.txt"
classify_corpus_bu_word_test_path="corpus/classify/classify_test_by_word.txt"

###################################分类相关##############################
classify_model_path="model/classify.model"#词语作为特征的模型的保存地址
classify_model_path_by_word="model/classify_by_word.model"#单个字作为特征的模型的保存地址

classify_model_final_path="model/classify.model"#一个词语作为特征的模型
classify_model_final_path_by_word="model/classify_by_word.model"#单个字作为特征的模型

##################################chatbot相关################################
#
# chatbot_input_path1=r'E:\Chat_robot_project\chart_service\corpus\chatbot\input.txt'#将小黄鸡未分词的问 放到一个路径下
# chatbot_target_path1=r'E:\Chat_robot_project\chart_service\corpus\chatbot\target.txt'#将小黄鸡未分词的回答 放到一个路径下

chatbot_by_word=True
if chatbot_by_word:

    chatbot_input_path='corpus/chatbot/input_by_word.txt'#将小黄鸡未分词的问 放到一个路径下
    chatbot_target_path='corpus/chatbot/target_by_word.txt'#将小黄鸡未分词的回答 放到一个路径下

else:
    chatbot_input_path='corpus/chatbot/input.txt'#将小黄鸡未分词的问 放到一个路径下
    chatbot_target_path='corpus/chatbot/target.txt'#将小黄鸡未分词的回答 放到一个路径下

#ws
if chatbot_by_word:
    chatbot_ws_input_path = "model/chatbot/ws_by_word_input_path.pkl"
    chatbot_ws_target_path="model/chatbot/ws_by_word_target_path.pkl"
else:
    chatbot_ws_input_path="model/chatbot/ws_input_path.pkl"
    chatbot_ws_target_path="model/chatbot/ws_target_path.pkl"

chatbot_ws_input=pickle.load(open(chatbot_ws_input_path,'rb'))
chatbot_ws_target=pickle.load(open(chatbot_ws_target_path,'rb'))

chatbot_batch_size=128
if chatbot_by_word:
    chatbot_input_max_len=30
    chatbot_target_max_len = 30
else:
    chatbot_input_max_len = 12
    chatbot_target_max_len = 12

chatbot_embedding_dim=256
chatbot_encoder_num_layers=1
chatbot_encoder_hidden_size=128

chatbot_decoder_num_layer=1
chatbot_decoder_hidden_size=128

chatbot_teacher_forcing_ratio=0.7

chatbot_model_save_path="model/chatbot/seq2seq.model" if chatbot_by_word else "model/chatbot/seq2seq_by_word.model"
chatbot_optimizer_save_path="model/chatbot/optimizer.model" if chatbot_by_word else "model/chatbot/optimizer_by_word.model"

clip=0.01