[
  {
    "path": ".gitignore",
    "content": "# Byte-compiled / optimized / DLL files\n__pycache__/\n*.py[cod]\n*$py.class\n\n# C extensions\n*.so\n\n# Distribution / packaging\n.Python\nbuild/\ndevelop-eggs/\ndist/\ndownloads/\neggs/\n.eggs/\nlib/\nlib64/\nparts/\nsdist/\nvar/\nwheels/\n*.egg-info/\n.installed.cfg\n*.egg\nMANIFEST\n\n# PyInstaller\n#  Usually these files are written by a python script from a template\n#  before PyInstaller builds the exe, so as to inject date/other infos into it.\n*.manifest\n*.spec\n\n# Installer logs\npip-log.txt\npip-delete-this-directory.txt\n\n# Unit test / coverage reports\nhtmlcov/\n.tox/\n.coverage\n.coverage.*\n.cache\nnosetests.xml\ncoverage.xml\n*.cover\n.hypothesis/\n.pytest_cache/\n\n# Translations\n*.mo\n*.pot\n\n# Django stuff:\n*.log\n.static_storage/\n.media/\nlocal_settings.py\n\n# Flask stuff:\ninstance/\n.webassets-cache\n\n# Scrapy stuff:\n.scrapy\n\n# Sphinx documentation\ndocs/_build/\n\n# PyBuilder\ntarget/\n\n# Jupyter Notebook\n.ipynb_checkpoints\n\n# pyenv\n.python-version\n\n# celery beat schedule file\ncelerybeat-schedule\n\n# SageMath parsed files\n*.sage.py\n\n# Environments\n.env\n.venv\nenv/\nvenv/\nENV/\nenv.bak/\nvenv.bak/\n\n# Spyder project settings\n.spyderproject\n.spyproject\n\n# Rope project settings\n.ropeproject\n\n# mkdocs documentation\n/site\n\n# mypy\n.mypy_cache/\n\n# Windows:\nThumbs.db\nehthumbs.db\nDesktop.ini\ndata\n.idea\n*.csv/application/api_demo_pygame.py\n/application/pygameTest.py\n*.csv\n/application/api_demo2.py\n/application/api_demo_pygame.py\n/application/rule_test.py\n/environment/render/render_th.py\n/application/array.py\n/environment/encryption/pyarmor\n/environment/encryption/.pyarmor_capsule.zip\n/environment/encryption/.pyarmor_config\n*.macalog\n*.pkl\n/tournament/result\n"
  },
  {
    "path": "README.md",
    "content": "# MaCA\n![](https://img.shields.io/badge/language-python-green.svg)\n![](https://img.shields.io/badge/platform-windows-green.svg)\n![](https://img.shields.io/badge/platform-linux-green.svg)\n![](https://img.shields.io/badge/platform-mac-green.svg)\n![](https://img.shields.io/badge/stability-experimental-green.svg)\n\nMulti-agent Combat Arena (MaCA) is a heterogeneous multi-agent distributed decision and control technology reasearch platform produced by CETC-TFAI team. It focuses on the application of AI technologies e.g. reinforcement learning in multi-agent cooperation and confrontation\n\n![](https://leonfg.github.io/maca/resource/maca.gif)\n\n## System Requirements\n- Linux 64-bit or Mac OS with Python 3.6\n- numpy 1.14.2 or later\n- pygame 1.9.3 or later\n\nThere is no limitation on agents' structure. You can write rule-based algorithms or use deep learning frameworks.\n## Quick Start Guide\n### Installation\n```bash\npip install -U numpy pandas pygame\ngit clone https://github.com/CETC-TFAI/MaCA.git\ncd MaCA\nexport PYTHONPATH=$(pwd)/environment:$PYTHONPATH\n```\n### Run a combat between two agents\n[fight_mp.py](fight_mp.py) can execute two agents. It uses two instances of a fixed-rule agent to fight each other by default.\n```bash\npython fight_mp.py\n```\nYou can specify agents and map by input arguments. In addition an agent should provide a call interface follows the MaCa platform specification.\n### Replay\nMaCa can record runtime log while playing and training. Use [replay.py](replay.py) to perform a replay.\n\nFirst, run [fight_mp.py](fight_mp.py) and enable log record function\n```bash\npython fight_mp.py --log\n```\n\nThen, run [replay.py](replay.py) to replay the log\n```bash\npython replay.py fix_rule_vs_fix_rule\n```\nThe log structure of MaCA is a set of .macalog files, they will be saved in path \"log/log-name/\".\nWhen you run the [replay.py](replay.py), You must input a \"log-name\" as the parameter to specify which log you want to replay.\n\nFor more information, see [tutorial](/doc/tutorial.md)"
  },
  {
    "path": "agent/airc_homo_rule/agent.py",
    "content": "#! /usr/bin/env python\n# -*- coding: utf-8 -*-\n\"\"\"\n@author: Xunyun Liu\n@contact: xunyunliu@gmail.com\n@software: PyCharm\n@file: agent.py\n@time:\n@desc: rule based agent\n\"\"\"\n\nfrom agent.base_agent import BaseAgent\n\nimport copy\nimport random\nimport utility as ut\nimport numpy as np\n\nDETECTOR_NUM = 0\nFIGHTER_NUM = 10\nCOURSE_NUM = 16\nATTACK_IND_NUM = (DETECTOR_NUM + FIGHTER_NUM) * 2 + 1  # long missile attack + short missile attack + no attack\nACTION_NUM = COURSE_NUM * ATTACK_IND_NUM\nLONG_MISSILE_RANGE = 120\nSHORT_MISSILE_RANGE = 50\nSQUARE_SIZE = 50\n\n\nclass Agent(BaseAgent):\n    def __init__(self):\n        \"\"\"\n        Init this agent\n        :param size_x: battlefield horizontal size\n        :param size_y: battlefield vertical size\n        :param detector_num: detector quantity of this side\n        :param fighter_num: fighter quantity of this side\n        \"\"\"\n        BaseAgent.__init__(self)\n        self.obs_ind = 'airc_homo_rule'\n        self.last_random_action_set = {}\n        self.to_explore_set = {}\n        self.explore_destination_set = {}\n        self.rule_set = 'attack'\n\n        # if not os.path.exists('model/simple/model.pkl'):\n        #     print('Error: agent simple model data not exist!')\n        #     exit(1)\n        # self.fighter_model = dqn.RLFighter(ACTION_NUM)\n\n    def set_map_info(self, size_x, size_y, detector_num, fighter_num):\n        self.size_x = size_x\n        self.size_y = size_y\n        self.detector_num = detector_num\n        self.fighter_num = fighter_num\n\n        # some eligibility checks\n        if self.detector_num != 0:\n            print('Error: agents using airc_homo_rule can only be used in a homogeneous environment!')\n            exit(1)\n        if self.size_x % SQUARE_SIZE != 0 or self.size_y % SQUARE_SIZE != 0:\n            print('Error, the map size is not a multiple of SQUARE_SIZE')\n            exit(1)\n\n        # initialise data structures for map exploration\n        self.to_explore_set = set(range((size_x // SQUARE_SIZE) * (size_y // SQUARE_SIZE)))\n        # initialise last_random_action_set\n        for i in range(self.fighter_num):\n            # it doesn't matter what the initial value is as it will be overwritten in the first round\n            self.last_random_action_set[i] = [0, 1, 0, 0]\n\n    def __reset(self):\n        pass\n\n    def get_action(self, obs_dict, step_cnt):\n        \"\"\"\n        get actions\n        :param detector_obs_list:\n        :param fighter_obs_list:\n        :param joint_obs_dict:\n        :param step_cnt:\n        :return:\n        \"\"\"\n        # initialise the explore_destination_set based on the birthplace of the agent\n        if step_cnt == 1:\n            for i in range(self.fighter_num):\n                self.explore_destination_set[i] = (self.size_x - obs_dict[i]['pos_x'], obs_dict[i]['pos_y'])\n        detector_action = []\n        fighter_action = []\n        # loop over the fighter list to generate actions\n        for index in range(self.fighter_num):\n            # [0, 1, 0, 0] is just a placeholder\n            tentative_action = np.array([0, 1, 0, 0], dtype=np.int32)\n            if obs_dict[index]['alive']:\n                try:\n                    if self.rule_set == 'random':\n                        tentative_action = self.choose_action_random(index, step_cnt)\n                    elif self.rule_set == 'random_attack':\n                        tentative_action = self.choose_action_random_attack(obs_dict, index, step_cnt)\n                    elif self.rule_set == 'explore':\n                        tentative_action = self.choose_action_explore(obs_dict, index)\n                    elif self.rule_set == 'attack':\n                        tentative_action = self.choose_action_attack(obs_dict, index)\n                    elif self.rule_set == 'still':\n                        tentative_action = self.choose_action_still(step_cnt)\n                except AttributeError:\n                    print(\"agent is missing a rule_set attribute. Now flying towards right as default.\")\n                # action formation\n                # true_action[0] = int(360 / COURSE_NUM * int(tmp_action[0] / ATTACK_IND_NUM))\n                # true_action[3] = int(tmp_action[0] % ATTACK_IND_NUM)\n            # radar and interference logic\n\n            tentative_action[1] = step_cnt % 10 + 1\n            tentative_action[2] = step_cnt % 10 + 1\n            tmp_action = {}\n            tmp_action['course'] = tentative_action[0]\n            tmp_action['r_iswork'] = True\n            tmp_action['r_fre_point'] = 2\n            tmp_action['j_iswork'] = True\n            tmp_action['j_fre_point'] = 2\n            if tentative_action[3] > self.fighter_num:\n                tmp_action['hit_target'] = tentative_action[3] - self.fighter_num\n                tmp_action['missile_type'] = 2\n            else:\n                tmp_action['hit_target'] = tentative_action[3]\n                tmp_action['missile_type'] = 1\n            fighter_action.append(copy.deepcopy(tmp_action))\n        # fighter_action = np.array(fighter_action)\n        return detector_action, fighter_action\n\n    # the logic of engagement with enemies\n    def engage_enemy(self, tmp_action, obs_dict, index):\n        # default -- no attack allowed\n        tmp_action[3] = 0\n        if 'target_list' in obs_dict[index]:\n            # flying towards the nearest enemy\n            tmp_action[0] = obs_dict[index]['target_list'][0]['angle']\n            target_id = obs_dict[index]['target_list'][0]['id']\n            target_distance = obs_dict[index]['target_list'][0]['distance']\n            # check if the nearest enemy has been attacked\n            strike_list = obs_dict['strike_list']\n            strike_target_id_set = set(ele['target_id'] for ele in strike_list)\n            if target_id in strike_target_id_set:\n                return tmp_action\n            # perform attack while having enough ammunition\n            if obs_dict[index]['s_missile_left'] + obs_dict[index]['l_missile_left'] == 0:\n                return tmp_action\n            elif target_distance <= SHORT_MISSILE_RANGE:\n                if obs_dict[index]['s_missile_left'] > 0:\n                    tmp_action[3] = target_id + 10\n                else:\n                    tmp_action[3] = target_id\n            elif SHORT_MISSILE_RANGE < target_distance <= LONG_MISSILE_RANGE:\n                if obs_dict[index]['l_missile_left'] > 0:\n                    tmp_action[3] = target_id\n        return tmp_action\n\n    def choose_action_random(self, index, step_cnt):\n        if step_cnt % 20 == 1:\n            self.last_random_action_set[index][0] = random.randint(0, 359)\n        return self.last_random_action_set[index]\n\n    def choose_action_random_attack(self, obs_dict, index, step_cnt):\n        random_action = self.choose_action_random(index, step_cnt)\n        return self.engage_enemy(random_action, obs_dict, index)\n\n    def choose_action_explore(self, obs_dict, index):\n        # maintain the data structure for map exploration\n        area_x = int(obs_dict[index]['pos_x'] / SQUARE_SIZE)\n        area_y = int(obs_dict[index]['pos_y'] / SQUARE_SIZE)\n        explored_index = area_x * (self.size_y / SQUARE_SIZE) + area_y\n        if explored_index >= (self.size_x / SQUARE_SIZE) * (self.size_y / SQUARE_SIZE):\n            print('explored_index out of range!')\n            explored_index = (self.size_x / SQUARE_SIZE) * (self.size_y / SQUARE_SIZE) - 1\n        if explored_index in self.to_explore_set:\n            self.to_explore_set.remove(explored_index)\n            if len(self.to_explore_set) == 0:\n                self.to_explore_set = set(range(round((self.size_x / SQUARE_SIZE) * (self.size_y / SQUARE_SIZE))))\n        # if agent has a destination to explore\n        if index in self.explore_destination_set:\n            # delete the destination when getting close enough\n            if ut.distance(obs_dict[index]['pos_x'], obs_dict[index]['pos_y'], self.explore_destination_set[index][0],\n                           self.explore_destination_set[index][1]) <= 5:\n                # print('trying to delete the key')\n                del self.explore_destination_set[index]\n                # print('delete succesfully')\n\n        # if the agent has no destination, randomly select a destination from the to_explore_set\n        if index not in self.explore_destination_set:\n            if len(self.to_explore_set) == 0:\n                print('Error! to_explore_set is empty')\n            selected_ele = random.sample(self.to_explore_set, 1)\n            # print('selected_ele: ', selected_ele)\n            ele_index_x = int(selected_ele[0] / (self.size_y / SQUARE_SIZE))\n            # print('ele_index_x: ', ele_index_x)\n            ele_index_y = int(selected_ele[0] % (self.size_y / SQUARE_SIZE))\n            # print('ele_index_y', ele_index_y)\n            ele_pos_x = int(ele_index_x * SQUARE_SIZE + SQUARE_SIZE / 2)\n            ele_pos_y = int(ele_index_y * SQUARE_SIZE + SQUARE_SIZE / 2)\n            # print('ele_pos_x: ', ele_pos_x, 'ele_pos_y', ele_pos_y)\n            self.explore_destination_set[index] = (ele_pos_x, ele_pos_y)\n            # print('self.explore_destination_set[index]: ', self.explore_destination_set[index])\n            # print('angle: ',\n            #      ut.angle(obs_dict[index]['pos_x'], obs_dict[index]['pos_y'], self.explore_destination_set[index][0],\n            #               self.explore_destination_set[index][1]))\n\n        # navigating towards the explore destination\n        return [ut.angle(obs_dict[index]['pos_x'], obs_dict[index]['pos_y'], self.explore_destination_set[index][0],\n                         self.explore_destination_set[index][1]), 1, 0, 0]\n\n    def choose_action_attack(self, obs_dict, index):\n        return self.engage_enemy(self.choose_action_explore(obs_dict, index), obs_dict, index)\n\n    @staticmethod\n    def choose_action_still(step_cnt):\n        if 1 <= step_cnt % 40 <= 10:\n            return [0, 1, 0, 0]\n        elif 11 <= step_cnt % 40 <= 20:\n            return [90, 1, 0, 0]\n        elif 21 <= step_cnt % 40 <= 30:\n            return [180, 1, 0, 0]\n        else:\n            return [270, 1, 0, 0]\n"
  },
  {
    "path": "agent/base_agent.py",
    "content": "#! /usr/bin/env python\n# -*- coding: utf-8 -*-\n\"\"\"\n@author: Gao Fang\n@contact: gaofang@cetc.com.cn\n@software: PyCharm\n@file: base_agent.py\n@time: 2018/3/22 0022 14:13\n@desc: base class of agent\n\"\"\"\n\n\nclass BaseAgent:\n    def __init__(self):\n        \"\"\"\n        init\n        \"\"\"\n        self.obs_ind = 'raw'\n        self.size_x = 0\n        self.size_y = 0\n        self.detector_num = 0\n        self.fighter_num = 0\n\n    def get_obs_ind(self):\n        \"\"\"\n        get obs info\n        :return: obs const class path.\n        \"\"\"\n        return self.obs_ind\n"
  },
  {
    "path": "agent/fix_rule/agent.py",
    "content": "#! /usr/bin/env python\n# -*- coding: utf-8 -*-\nfrom pytransform import pyarmor_runtime\npyarmor_runtime()\n\"\"\"\n@author: Gao Fang\n@contact: gaofang@cetc.com.cn\n@software: PyCharm\n@file: agent.py\n@time: 2018/3/13 0013 10:51\n@desc: rule based agent\n\"\"\"\n\nfrom agent.fix_rule.agent_core import Agent as ag\n\n\nclass Agent:\n    def __init__(self):\n        \"\"\"\n        Init this agent\n        \"\"\"\n        self.agent_core = ag()\n\n    def set_map_info(self, size_x, size_y, detector_num, fighter_num):\n\n        return self.agent_core.set_map_info(size_x, size_y, detector_num, fighter_num)\n\n    def get_action(self, obs_dict, step_cnt):\n        \"\"\"\n        get actions\n        :param detector_obs_list:\n        :param fighter_obs_list:\n        :param joint_obs_dict:\n        :param step_cnt:\n        :return:\n        \"\"\"\n        return self.agent_core.get_action(obs_dict, step_cnt)\n\n    def get_obs_ind(self):\n        return self.agent_core.get_obs_ind()\n"
  },
  {
    "path": "agent/fix_rule/agent_core.py",
    "content": "__pyarmor__(__name__, __file__, b'\\xe7\\x50\\x8c\\x64\\x26\\x42\\xd6\\x01\\xb9\\x4e\\x3f\\xdf\\x40\\x99\\x74\\xef\\xb8\\xc9\\x91\\x76\\x3b\\x40\\xaa\\xbe\\x5d\\xc5\\xbd\\x32\\x0b\\xf3\\x42\\x40\\xe3\\xce\\x4f\\x75\\x5d\\x9f\\x4c\\x04\\x35\\x6e\\xf5\\xb9\\xdb\\xfc\\x44\\xa8\\x11\\xd0\\xdb\\xb1\\x0f\\x62\\xe2\\x75\\xc1\\x38\\x66\\x9c\\x65\\x70\\xe1\\x0d\\x2b\\x57\\x65\\xd2\\x85\\x6d\\x0e\\x9d\\xb5\\x16\\x6d\\x19\\x4c\\x08\\x05\\x50\\xe0\\xd6\\x28\\xd8\\xe5\\x1b\\x68\\xb7\\x96\\xd4\\x21\\x0e\\x87\\x99\\x7d\\xc0\\x18\\x75\\xb0\\x67\\x5d\\x77\\xba\\xb0\\xc6\\xdf\\x31\\x69\\x39\\x6e\\xd1\\x45\\x73\\xec\\xd7\\xec\\x65\\x93\\xcb\\x46\\x43\\xd3\\x68\\x99\\x09\\xa8\\x80\\xd9\\x28\\xa0\\xf6\\xc2\\xa2\\xe5\\xc3\\xe7\\x36\\x9b\\xec\\xf2\\x0f\\x2a\\xf1\\x9d\\xb6\\x41\\xae\\x5c\\x09\\x7b\\x21\\x59\\x72\\xee\\xc1\\x98\\x30\\x0e\\xb3\\xe9\\x7e\\x44\\x8a\\x9b\\x52\\x69\\x33\\xac\\x8f\\x31\\xb4\\x23\\xde\\xcc\\xe2\\xad\\xb2\\x31\\x53\\x7a\\x9b\\xb1\\x57\\xd3\\x1c\\x71\\x51\\x17\\x75\\x19\\x03\\x24\\x0c\\x7a\\x01\\x93\\x06\\x9a\\x0b\\x6e\\xee\\xa6\\xc5\\xb4\\xc2\\x8d\\x0a\\x69\\x52\\xbf\\xd2\\xaf\\xd4\\xc5\\xa7\\x60\\xb1\\x44\\xd6\\xfa\\xbb\\xc3\\x19\\x93\\x06\\x7f\\x83\\x00\\x59\\x12\\xb4\\xaf\\x74\\x36\\xa9\\x34\\x5a\\x43\\xc5\\xd2\\xdf\\xa7\\x6e\\x78\\x20\\x07\\x75\\x3f\\xae\\x92\\x75\\x22\\xd7\\xc6\\xc7\\x4c\\xc5\\x2a\\x22\\x8d\\xb0\\x44\\xe9\\xeb\\xf4\\x69\\x59\\x8c\\x53\\x63\\x94\\xa7\\x15\\x85\\x68\\xfa\\xc7\\x20\\x49\\x9e\\x36\\x1e\\x2b\\x40\\xe2\\x98\\x34\\xa8\\x51\\x55\\xfc\\xc9\\x13\\xee\\x24\\x60\\x57\\x6c\\xdf\\xad\\x56\\x49\\x4e\\x38\\x9d\\x4d\\x49\\xda\\x4d\\x2e\\xfe\\xe2\\x09\\x0b\\x42\\xaf\\x41\\x88\\x2a\\x47\\x73\\xa7\\x5f\\x24\\xcf\\x2c\\x1d\\x84\\xe7\\x99\\x71\\x01\\x66\\xce\\xdd\\xaa\\xb3\\xf3\\xfe\\xab\\xf7\\x11\\x30\\x95\\xbd\\xc0\\xfa\\xbb\\xa7\\x7c\\x06\\xbe\\xb6\\x9c\\x18\\x0c\\xac\\x47\\x43\\xdd\\x4a\\x65\\x10\\x58\\x25\\x7a\\x93\\x57\\x0d\\x03\\xeb\\x9b\\x25\\x1c\\xec\\x3b\\xb7\\x91\\x12\\xac\\xad\\x85\\xf6\\x3b\\x99\\x7d\\x4b\\xe8\\x89\\x28\\x3a\\xd5\\xa7\\x92\\x64\\x06\\xcb\\xa3\\x14\\x52\\xf2\\x1b\\x3e\\xa3\\x4a\\x01\\x0d\\x59\\x18\\x76\\x35\\x10\\x06\\x55\\x18\\xcd\\x7e\\x34\\x24\\x70\\x5d\\xfc\\xd1\\x0a\\x68\\x16\\xeb\\xb1\\x70\\xb2\\x6b\\x17\\xe3\\xa9\\x7a\\xc5\\xc1\\x34\\x37\\x3b\\xae\\xe3\\x00\\xe0\\x09\\xf2\\x1e\\xb4\\xca\\xa2\\x20\\xef\\xf8\\xd9\\x5b\\x06\\xd2\\xa3\\x50\\xdb\\xdd\\x20\\xfe\\x0f\\xc1\\x43\\x52\\x48\\x3c\\xf9\\x61\\x17\\xdb\\x1a\\xd2\\xb3\\xee\\x0a\\xe4\\xf4\\x9d\\x8c\\xe3\\x37\\xdd\\x3d\\x74\\xf9\\xaf\\xe3\\x99\\x15\\x41\\x7d\\xcd\\x03\\x08\\x92\\x92\\x8b\\xc1\\x4d\\x83\\x4f\\x89\\x2f\\x04\\xf0\\xcf\\xae\\x25\\x5a\\x92\\x62\\xa6\\x94\\x92\\xdf\\xe1\\xa6\\xe4\\x15\\x7b\\xe2\\x3b\\xa8\\x42\\x1a\\xe8\\xfb\\xa0\\x38\\x71\\x46\\xfa\\xde\\x4d\\xad\\x43\\x60\\x96\\x6a\\xd8\\x03\\x87\\xa2\\x30\\x50\\x2e\\x68\\xfb\\xfa\\xa4\\xb9\\x8c\\xfd\\x3a\\x94\\xe7\\x82\\x42\\xce\\x89\\xc8\\x8c\\xa2\\x17\\x93\\x75\\x23\\x46\\xdf\\xb6\\x28\\x32\\x2d\\xcf\\x6d\\xe0\\xfb\\x8e\\xdd\\x7f\\xbe\\x79\\x67\\x17\\xae\\x74\\xc9\\x0e\\xec\\x81\\x52\\x38\\x1e\\x78\\x4b\\x97\\xe8\\x61\\xae\\x16\\x32\\x97\\xdb\\x2b\\xbe\\x41\\x00\\xd4\\xd6\\x3a\\xe0\\xac\\xd3\\x85\\x02\\x95\\x4a\\x1d\\x32\\xab\\xbb\\x7b\\x4c\\xb0\\x35\\x26\\x39\\x31\\x1b\\xcc\\xe8\\xa6\\xb3\\xc8\\x8d\\x77\\x42\\x95\\x26\\x6d\\xef\\x37\\xbf\\x6c\\x28\\xa2\\x21\\xaf\\xdd\\xd4\\x58\\xcf\\x52\\xa0\\x2f\\x94\\xf1\\xe9\\x2d\\xef\\xd4\\x58\\xf5\\xa5\\x79\\xed\\xb5\\x9a\\x7b\\x95\\xd0\\x0c\\xea\\x45\\x1c\\xa0\\xe8\\x6f\\x76\\xfa\\xcf\\x8c\\x63\\x6a\\x7a\\xc7\\x73\\x36\\x85\\x4f\\x7b\\xde\\x9f\\x37\\x18\\x99\\x0f\\x97\\x21\\xd4\\x78\\x02\\x8b\\xbc\\x55\\x7a\\x88\\x32\\x78\\x13\\xc6\\x4d\\xbf\\x12\\x9c\\x52\\xea\\x83\\x9e\\x79\\x33\\xde\\x63\\x93\\x1f\\xfe\\xf1\\x15\\x64\\x87\\x38\\x26\\x1b\\x83\\x5e\\x80\\x70\\xfc\\x85\\x3d\\x7c\\xae\\x2d\\x4f\\x0d\\x13\\xf4\\xb4\\xa4\\x94\\x3c\\x6b\\x5c\\x85\\xdc\\xd4\\xc7\\xd2\\x85\\x3a\\x9c\\x10\\x28\\x25\\x1f\\xc3\\x95\\xd4\\x11\\x88\\xe1\\x3a\\x5a\\xfc\\xc0\\xde\\x86\\x4f\\x7a\\x8a\\xb2\\x06\\x1a\\x53\\xbb\\x46\\x72\\xe4\\xec\\xb8\\x68\\x4c\\xa2\\xf9\\xda\\xf5\\x17\\x6a\\xb2\\x76\\xd3\\x92\\x36\\x70\\x6b\\xcd\\xeb\\xa7\\x22\\x4f\\x14\\x48\\xc2\\x96\\x10\\xff\\x36\\xe1\\xf3\\xcc\\x81\\xec\\xe2\\x58\\xc4\\x56\\x3c\\x6a\\x50\\xb3\\x5a\\xb0\\x59\\xae\\xce\\x26\\x54\\xb0\\xf6\\x05\\xf3\\xb1\\x7e\\x8e\\x2a\\xa8\\xc6\\x2e\\x22\\x59\\x55\\x80\\x2f\\xe6\\x6d\\xee\\xb7\\xcd\\xcc\\xb1\\x57\\x67\\xef\\x7a\\x5e\\xf5\\x23\\xad\\x2b\\xaf\\x7a\\xcb\\x4e\\xad\\x59\\x46\\xd7\\xe1\\xd0\\x71\\xad\\xe6\\xe9\\x86\\x41\\x55\\x15\\x77\\x86\\x8c\\xab\\x4c\\xf9\\xa0\\x3b\\x20\\x6b\\x38\\xc5\\x68\\x64\\x24\\x00\\xca\\x9d\\xff\\x20\\x74\\x60\\xb4\\x39\\x6c\\xc9\\x9e\\x99\\xa7\\x86\\x0b\\x92\\xc6\\xe4\\xe4\\x8d\\x1f\\x14\\xe7\\x08\\x4e\\x2b\\x69\\x3f\\xdb\\x71\\x76\\xaf\\x2f\\x40\\xe7\\x2a\\xd8\\x74\\x06\\x4a\\xcb\\xc4\\x6c\\x52\\x08\\xc8\\xe3\\x0e\\x52\\x8d\\x3d\\x5d\\x2b\\xfb\\x32\\x37\\x5a\\x8d\\xed\\x15\\xe8\\x64\\xde\\x88\\xf7\\x39\\x73\\x82\\x91\\xc5\\x00\\xa1\\xe1\\x4c\\x8c\\xd2\\x38\\x07\\xff\\xe5\\xae\\x9e\\x17\\xc4\\xb2\\xd6\\xee\\x53\\x59\\xcb\\x17\\xdf\\xbe\\x25\\x63\\xa1\\x77\\x3e\\x31\\xcf\\xc8\\x2f\\x82\\x3b\\xcd\\x20\\xa6\\xce\\x49\\x9d\\x35\\x53\\xd5\\x49\\xc2\\x5d\\x4f\\xd3\\xaf\\x12\\x13\\x6f\\xff\\x36\\x26\\xa7\\x7b\\xc4\\xbe\\xf3\\x38\\xe1\\x6c\\xd8\\xb1\\xe3\\xa5\\xd4\\x8b\\x32\\xfd\\xf6\\xa0\\x82\\x0e\\xd5\\xc0\\xa8\\x0d\\xf7\\xc5\\x23\\x9a\\x0f\\xa2\\xda\\xa9\\x31\\x24\\xf6\\xe7\\xe7\\x60\\x92\\xf3\\x86\\xc6\\x0f\\x19\\x67\\xd3\\x3e\\x4e\\x2c\\x3f\\xf4\\x0e\\xa8\\xb1\\xa5\\xb5\\xfe\\xc6\\x1b\\xb8\\xf4\\x2e\\x01\\x2d\\x7d\\x3d\\x9d\\x7a\\xa3\\x18\\x22\\x48\\xd0\\x3c\\xd7\\xdd\\x7e\\x5f\\x03\\x9f\\x93\\xc7\\x76\\x67\\x13\\x0d\\x46\\x1a\\xde\\xdd\\xd1\\xd3\\x6b\\x84\\xa1\\x94\\x58\\x3f\\xc7\\x63\\x5f\\xca\\xb6\\xd8\\x29\\x29\\x1f\\xb5\\x0e\\xb2\\x62\\x62\\x82\\xe1\\x60\\x09\\x3b\\x0e\\x5e\\x4b\\x3f\\xe4\\xe3\\x3e\\x28\\x7a\\x27\\xbc\\x13\\xc3\\xe5\\x3b\\x9d\\xea\\x47\\xf6\\x30\\x89\\xb1\\x5e\\xc4\\x60\\xc1\\x2c\\x40\\x76\\x3c\\x50\\x9e\\xed\\xc4\\x2e\\xf2\\x8d\\xca\\xe1\\x81\\xff\\xf0\\xaf\\xd4\\xbe\\x9f\\x61\\x58\\x7c\\xa3\\x27\\xb4\\x06\\x44\\x43\\xfe\\x60\\x76\\x7c\\x23\\x01\\x72\\x86\\x3d\\x2f\\xdc\\xef\\xd6\\xd2\\xc6\\x53\\xbe\\xf6\\x80\\xfa\\xdc\\xe7\\x0b\\x1b\\x8a\\x5b\\x0f\\xd5\\x20\\xaa\\x4b\\x03\\xe2\\x42\\x75\\x56\\x44\\x8a\\x4c\\x8d\\xe6\\xa4\\x58\\x95\\x6f\\x01\\x42\\x45\\x27\\xc5\\x00\\x45\\xba\\x51\\xad\\x7f\\x25\\x15\\x01\\x9b\\x5f\\xdd\\xf8\\xeb\\x5b\\x35\\x9f\\xb5\\x60\\x70\\x9e\\x07\\x70\\x5b\\xff\\x15\\xf2\\x3d\\xb7\\xc6\\xfb\\xbe\\xcf\\x5b\\xf5\\x20\\xdc\\x09\\xea\\x28\\x27\\x66\\xd7\\xab\\x34\\xd1\\x38\\x2a\\x62\\x2a\\x2f\\xab\\x58\\xf1\\xf4\\x42\\x2c\\x5f\\x10\\x58\\xf7\\xd8\\x36\\x88\\x25\\x37\\x93\\xeb\\x16\\xab\\xbd\\x1a\\x40\\xc8\\x44\\xfa\\x0f\\xe4\\x00\\xfa\\x98\\x90\\xb6\\x7c\\xc8\\x7f\\x5a\\xb3\\x83\\xf7\\x77\\x61\\xe6\\xb9\\x69\\xf3\\x96\\x7a\\xd0\\xa0\\xf8\\xf9\\xec\\x57\\x8c\\xe3\\xed\\x1f\\xea\\x74\\xb2\\xcc\\x14\\xfb\\xdb\\x17\\x5d\\x89\\x61\\x96\\x54\\x1f\\x9c\\x6a\\x63\\x39\\x80\\x84\\x01\\x7c\\x18\\xad\\x64\\x1d\\x0e\\xae\\xd9\\x6a\\x07\\x2f\\x21\\x50\\x26\\x93\\x0d\\x68\\xae\\xe0\\xc6\\xe3\\x1d\\x18\\xe4\\x52\\x2f\\xe0\\xae\\x7f\\xc1\\x9c\\x12\\xf4\\x42\\x46\\xdb\\x5d\\x9d\\x31\\x8a\\xa9\\xeb\\x14\\x20\\x96\\xf6\\x4f\\x08\\xfe\\x6a\\xcf\\x65\\x7e\\xb7\\x97\\xe9\\xbc\\xb3\\xd1\\xa9\\x13\\xaa\\x70\\x66\\x73\\x7d\\x96\\x42\\xe5\\x10\\xa5\\xb5\\x36\\x15\\x12\\x3e\\x10\\x60\\x52\\x39\\xf2\\x93\\xc8\\xaf\\x8e\\xe5\\x83\\x0b\\xda\\x64\\xa4\\x83\\x9a\\x0f\\x83\\x07\\x7b\\x0f\\x93\\x58\\x29\\xd6\\x4b\\x73\\xd3\\xb3\\x71\\xc5\\xd0\\xc2\\x99\\xdd\\x5d\\x41\\x28\\xa9\\x3e\\x57\\x48\\x2e\\xdf\\x33\\x0e\\xc7\\xaa\\xcb\\x8b\\x59\\xfc\\xd4\\xd9\\x42\\x45\\x37\\x77\\x03\\xfb\\x8f\\x6e\\x33\\x29\\x54\\x01\\xfa\\xf7\\x59\\x8b\\x3c\\xa3\\x9e\\xee\\x12\\xc5\\xb1\\x82\\x66\\xcc\\xfb\\xcb\\x5b\\xee\\x3d\\xcc\\x7c\\x5d\\xc2\\xdb\\x7f\\xeb\\x94\\x33\\xb7\\xf9\\x44\\x48\\x72\\x32\\xc9\\xd7\\x19\\x2a\\x7e\\x30\\x50\\x1e\\x68\\x77\\x77\\xb1\\xd4\\xc9\\x09\\xe2\\x07\\x29\\xfd\\xf5\\x1c\\xc1\\xa2\\x02\\x5d\\x11\\x33\\xa7\\x96\\x8a\\x90\\x29\\x5d\\xfa\\xb4\\x3d\\x82\\x02\\x4c\\xf2\\x59\\x18\\x79\\x45\\x21\\x8c\\x1b\\x2b\\x5b\\x8a\\xe5\\x07\\x00\\xd7\\x48\\x79\\xf0\\xcc\\xd0\\xc9\\x7a\\x0f\\x22\\x3b\\x4e\\xdb\\x15\\x06\\xc2\\x3f\\x9f\\xe5\\x25\\x02\\x9f\\xdf\\x26\\x20\\xec\\xb5\\xb6\\x87\\x30\\x1f\\xde\\x48\\x5b\\x60\\x8c\\x13\\x85\\x20\\xc1\\x0f\\xf4\\x49\\x90\\x31\\x11\\xed\\x23\\xdd\\xf9\\xa5\\xe6\\x9e\\xbc\\x2e\\x68\\xf5\\x95\\x2b\\x2b\\x03\\x65\\xf4\\xf9\\x0d\\x9d\\xc4\\x2a\\xb0\\xac\\x14\\x25\\xa3\\x78\\xdf\\x8b\\xc6\\x99\\xfa\\x67\\x0f\\xda\\x5a\\x63\\x4e\\x3c\\x29\\xe3\\x25\\x90\\xd3\\x93\\x92\\xdf\\x51\\xb8\\xd1\\x1e\\x3f\\x9f\\xe8\\x8b\\x5f\\xe4\\xc7\\x7b\\x36\\xba\\xf6\\x29\\x3a\\x08\\x28\\x53\\xc6\\x90\\xa3\\x6d\\x44\\x40\\x3a\\xd4\\x37\\xf7\\xbc\\x6d\\x44\\x19\\xba\\x00\\xcb\\x26\\x02\\x61\\x6f\\x42\\xb5\\x35\\x1f\\x22\\x60\\x69\\x1e\\x1c\\x82\\xff\\x17\\xa0\\xe2\\xb9\\xd2\\xdd\\xbc\\xd2\\xe0\\xce\\xa4\\x37\\xb9\\x59\\xec\\x52\\x5e\\x7b\\x7c\\x07\\xc5\\x48\\x04\\x0f\\x8f\\x6d\\x06\\x5c\\x89\\x32\\x05\\x00\\x18\\x91\\x7e\\xbe\\x64\\xc5\\xfc\\xf5\\x3d\\x22\\xde\\x34\\xe3\\xa3\\xda\\x9a\\x39\\x2e\\x1b\\x94\\x6f\\x8d\\x3e\\xbb\\x2f\\x6a\\xd3\\xfb\\xa0\\x2d\\xf4\\xaa\\x66\\x6a\\x7d\\xf4\\x79\\xe5\\x3b\\x84\\xfd\\xc6\\x58\\x76\\x1e\\xb3\\xa6\\xe6\\x22\\xb8\\xcf\\x65\\x96\\x0e\\xe7\\xcc\\xb3\\xbc\\xf3\\xe6\\xa2\\x3d\\xf8\\xa0\\x04\\x5b\\x71\\x72\\x29\\xa4\\x79\\xbf\\xf1\\x2e\\x69\\xe8\\x65\\x77\\x54\\x58\\x8e\\xf8\\x28\\x2d\\x46\\xbf\\xe2\\x1d\\xe7\\xb2\\x08\\xea\\xa5\\x38\\xbc\\x5b\\x66\\xa9\\x37\\xa2\\x14\\xe7\\xc3\\x89\\x4d\\xf4\\xf7\\xb6\\xac\\xee\\x18\\xad\\xdd\\xe3\\xa4\\x6c\\x4a\\xab\\x1a\\x8b\\xee\\xf9\\x27\\xbc\\x25\\xe2\\xab\\xf3\\xd9\\x3e\\xba\\x45\\xe9\\xb4\\xa1\\x98\\xb0\\x5e\\xd5\\x0f\\x6d\\x23\\x1c\\xb0\\x1b\\x57\\xa6\\x4b\\x05\\x06\\x6d\\x96\\x57\\xf3\\x61\\x8b\\x10\\x7d\\x26\\xd8\\x54\\xca\\x53\\x6b\\xb6\\x67\\x08\\x5b\\xc6\\x65\\x45\\x7c\\x0b\\x20\\xcc\\x63\\x73\\x45\\x76\\xe1\\x4a\\x9b\\x90\\x92\\x25\\x94\\xac\\x95\\x06\\xca\\x7b\\x6f\\xec\\x2d\\x56\\xf0\\x81\\xb2\\x97\\x31\\x51\\xec\\x85\\x32\\x20\\x5f\\x3e\\x45\\x8d\\x80\\x11\\xed\\x33\\xbd\\x75\\xe6\\xdb\\xb3\\x51\\x78\\xa6\\x75\\x05\\xb4\\x67\\xd3\\xc1\\x19\\x90\\x89\\x49\\xf4\\xbf\\x39\\x9d\\xfd\\x4a\\x05\\x90\\x0e\\x54\\xf8\\x43\\x2d\\xeb\\xa2\\xfd\\xfe\\x88\\xe0\\xa5\\xa3\\x35\\x45\\x27\\x49\\x90\\xae\\x84\\x0a\\x74\\x8d\\x30\\x2f\\xde\\x37\\x1a\\xc7\\xd2\\xd8\\x7e\\x30\\x51\\xb7\\x3b\\xf7\\xb8\\xe4\\x13\\xfb\\x7f\\xbb\\x06\\xea\\xac\\xa4\\xd7\\x6b\\xc1\\x20\\x49\\xf4\\x2d\\xa4\\xb7\\x67\\x1f\\x4c\\xe4\\x87\\xc9\\x3b\\x01\\xb8\\xd9\\x34\\xe9\\x80\\xb0\\xda\\xf6\\x10\\xcd\\xb4\\xe0\\xac\\x1f\\x6b\\x26\\x6c\\xb9\\xc3\\x95\\xd2\\x76\\x13\\x52\\xc9\\x86\\xee\\x56\\x07\\x6d\\x9d\\xdf\\x5c\\x10\\xd4\\x82\\x61\\xb2\\xa8\\x2c\\xf6\\x40\\x20\\xdc\\x46\\x33\\xf9\\x92\\xce\\xa8\\xf0\\x84\\xec\\x24\\x77\\xa1\\xe7\\xed\\x4c\\x38\\xd9\\x64\\x3d\\xdd\\x97\\x3a\\xe4\\x48\\x83\\x94\\xda\\x9c\\xb0\\x6c\\x67\\xf9\\xaf\\x84\\x7e\\x6c\\x90\\x63\\x46\\x22\\x1e\\x25\\xcc\\x2a\\xb4\\x92\\x8e\\xb4\\x8c\\xda\\x97\\xb6\\xc9\\xe8\\xf4\\x7f\\xcb\\x1e\\x98\\x59\\x0e\\x1d\\x2f\\x55\\xad\\x8d\\xeb\\xa0\\x33\\x43\\xf0\\xdd\\x57\\x81\\xb3\\xa8\\x19\\xd8\\xb8\\x9c\\x40\\xd3\\x8e\\xa8\\x42\\x97\\xb9\\xea\\xf3\\x4b\\x9f\\x50\\x59\\xc0\\x26\\xeb\\x1a\\xfe\\x43\\xba\\x90\\x3a\\xb9\\x95\\x22\\x3d\\x3f\\xb0\\xb5\\x5b\\x80\\xba\\xb8\\xc1\\xfd\\x09\\xf1\\x8f\\x4a\\xc7\\x60\\x19\\x41\\xee\\x30\\x0d\\xdc\\x77\\x7b\\x7a\\x3b\\xfe\\xe5\\x2c\\x44\\xa7\\xdf\\x1b\\xd3\\x72\\x2b\\x36\\x92\\x06\\xe3\\xef\\x3a\\x4f\\x44\\xe2\\xe9\\xed\\x3d\\x41\\x44\\x2d\\x89\\x9b\\xb4\\x81\\xa6\\x6e\\x22\\x4e\\x29\\x67\\xe8\\x74\\x86\\x31\\x4b\\xdd\\xde\\xb3\\x0e\\x40\\x47\\xe4\\xdc\\xe4\\x92\\xf5\\xf6\\x2e\\xd9\\xc5\\x86\\xf3\\x1b\\x48\\x30\\xcc\\x8a\\x09\\xd6\\x61\\x38\\xc4\\x94\\xf0\\x00\\x62\\xad\\xb9\\x5d\\x57\\x31\\xf5\\xa7\\xff\\x9c\\x78\\xc8\\x47\\xf1\\x37\\x9a\\x8b\\x92\\x8e\\xd0\\x03\\x8c\\x6c\\x7f\\x15\\x3d\\xa0\\xba\\xc3\\x69\\x8a\\x88\\xa2\\x7f\\x7f\\xe0\\xc8\\x78\\x89\\x6f\\xa6\\xfc\\xc3\\x71\\x4e\\x76\\x9a\\xdf\\xfb\\x89\\x7e\\x55\\x96\\x53\\x34\\xb3\\xa2\\x78\\xf8\\x2b\\x87\\x6b\\x26\\xa0\\xb0\\xf6\\x14\\x64\\xd7\\x69\\x20\\xfc\\x54\\x22\\x7a\\x9f\\xb6\\x72\\xdc\\xdd\\x75\\xbc\\x68\\xd2\\x1f\\x56\\xac\\xb1\\x17\\x0f\\x49\\x6e\\x33\\xf6\\x12\\x29\\x44\\x79\\x11\\xec\\xea\\x9c\\x6d\\x4d\\xe7\\x48\\x29\\xf9\\x74\\xa3\\x91\\x5a\\xb7\\x20\\x59\\x75\\x99\\x76\\xcf\\xa7\\xca\\xb5\\x51\\xee\\xe7\\x20\\x64\\x1e\\x32\\xd2\\x00\\xa4\\x9f\\x14\\x5f\\x1b\\xd1\\x4f\\xc7\\x1f\\xe0\\x87\\xdf\\xad\\x6b\\x56\\xa8\\xc8\\x45\\x9a\\xbf\\xf2\\xff\\xe5\\x0f\\x09\\x46\\x85\\xdb\\xe1\\x5d\\x77\\x63\\x45\\x74\\x55\\x4d\\x9e\\x5c\\xdb\\x9b\\x04\\x2b\\x86\\x63\\xe7\\xe1\\xf3\\x82\\x9d\\x80\\x76\\x9b\\xd4\\x5b\\x42\\xbc\\x47\\x61\\x50\\xa8\\xd9\\x22\\x9d\\x7e\\x35\\x10\\xf5\\xeb\\x0d\\x0d\\xb3\\x74\\xc4\\x18\\xd3\\x82\\x28\\x15\\x1a\\xff\\xdc\\x81\\x26\\x72\\x99\\x07\\x37\\x9f\\xc6\\xff\\xa4\\x5b\\x54\\xb5\\x2f\\xc4\\x79\\x01\\x1e\\x8b\\x54\\x41\\x9c\\x41\\x2e\\x1c\\x62\\x98\\x4d\\xb7\\x4b\\x60\\x62\\xb6\\x24\\xf9\\x33\\x42\\x26\\xe3\\xfc\\xc7\\x74\\x9a\\xfe\\x02\\x7e\\x6d\\x26\\xac\\xb6\\x8e\\xbd\\xa7\\x7a\\x5d\\xb0\\xdf\\x79\\x81\\xc1\\x9b\\x86\\x8f\\x07\\x2a\\x12\\xa1\\x4e\\x15\\xeb\\x35\\xf9\\xc2\\xe0\\x9e\\xad\\xe7\\x74\\x32\\x3c\\x93\\x0f\\xcb\\xc6\\x3b\\xd3\\x65\\xe7\\x7a\\xf1\\x05\\xa2\\x10\\x43\\xe9\\x2b\\x9e\\xc6\\x15\\xfe\\xde\\x9f\\xf5\\x57\\x5e\\x0c\\x0b\\xf6\\xdf\\x55\\x52\\xf5\\x90\\x91\\x02\\x60\\xf1\\xf1\\xc6\\x59\\x17\\x86\\x61\\x3c\\x26\\x2a\\x73\\x97\\xe8\\x2a\\xa0\\x37\\xa4\\x06\\xa4\\x95\\xcc\\xba\\xca\\x75\\xaa\\x17\\x84\\x4b\\xa7\\x15\\x25\\x28\\xfc\\xea\\x1c\\xba\\x7c\\x01\\x6e\\x56\\x1d\\x7f\\x3e\\x73\\xbf\\x04\\x56\\xf4\\x73\\xaa\\xea\\x53\\xd6\\x4e\\xca\\x49\\xe1\\x2f\\xb8\\x34\\x76\\x78\\x3e\\x7c\\x41\\xd4\\x59\\x7e\\x75\\x3e\\xfb\\x21\\xcf\\x5c\\x6f\\x64\\x79\\x90\\xab\\x3b\\x96\\x96\\x62\\x96\\x6d\\x53\\x32\\x4b\\x41\\x63\\xc6\\x11\\x2e\\xe2\\xef\\x47\\x52\\xd6\\x0d\\xa1\\x06\\xce\\xea\\x81\\xb2\\x18\\x22\\x26\\xd0\\x2b\\x97\\xb4\\xe2\\xc2\\xf9\\x61\\xcb\\x11\\xec\\xbf\\x88\\xfa\\x29\\xb6\\xcb\\x93\\x11\\x4f\\x00\\x10\\xff\\x2d\\xa3\\xb0\\xef\\x11\\xc8\\xe3\\xbe\\xfe\\xd3\\x2c\\xbd\\x02\\xf1\\xbf\\x76\\x93\\x58\\x69\\x53\\xcb\\xc5\\xd1\\xfb\\x95\\x09\\xd2\\xa7\\xbc\\x2a\\x1f\\x02\\x91\\x5f\\x6a\\xe1\\x8f\\xf4\\x40\\x5c\\xb9\\x58\\xfb\\xcf\\x21\\xa0\\x65\\xb6\\x11\\x47\\x73\\x16\\xbf\\x75\\x21\\x08\\x53\\x7e\\xdd\\xd3\\x62\\x19\\xe4\\xb5\\x99\\xea\\x67\\xfb\\x58\\x45\\xc3\\x46\\x9e\\x8c\\x68\\x50\\x99\\x5b\\x1a\\xc5\\xd0\\x48\\xbd\\x1f\\x62\\xfa\\x1f\\x47\\xc1\\x1e\\x00\\x60\\xaf\\x11\\xa4\\x76\\x86\\xce\\xea\\x50\\xa0\\x1a\\xe6\\x36\\x96\\xc7\\x64\\x8b\\x18\\x91\\x9f\\xbf\\xe8\\x9b\\x19\\x24\\xb6\\x57\\x5a\\xaa\\x84\\x58\\x87\\xe0\\x14\\xb5\\x76\\x1b\\x7a\\x1a\\xad\\x00\\xc7\\x96\\x8b\\x3f\\xa2\\x33\\x91\\x2e\\x57\\x4b\\x10\\x34\\x51\\x04\\xa8\\x78\\xfa\\x99\\xf2\\x6e\\x4c\\x32\\x6e\\xc5\\x52\\xdb\\x4b\\x58\\xe4\\x74\\x74\\x56\\x18\\x26\\xb5\\x1b\\xe5\\x10\\x5b\\x35\\x4e\\xf0\\x5b\\x02\\x90\\x6b\\x22\\x7e\\x60\\x90\\x5c\\x78\\xc5\\xd0\\x6d\\xb5\\x93\\x50\\x35\\x59\\xd5\\x67\\xe8\\x0f\\x26\\x74\\xc7\\xf5\\x9d\\xc8\\xd6\\x30\\x86\\x83\\xe3\\x2e\\xb9\\xe1\\x95\\x7f\\xe9\\x96\\xb9\\xf9\\xb5\\xa0\\x33\\x56\\x9f\\xe7\\xdf\\xce\\x28\\xf3\\x06\\xdc\\x1f\\x7b\\x73\\x8a\\xa1\\x99\\xd5\\x3b\\x18\\x90\\xbb\\xba\\x9f\\x08\\x66\\xf2\\x3e\\xdc\\xea\\x29\\xda\\x58\\xb3\\xc1\\xeb\\xdf\\xf0\\xf7\\x7b\\xc9\\x1e\\x9c\\x66\\x09\\x6c\\x97\\x83\\x9f\\xea\\x80\\x9c\\x5e\\x1a\\x7e\\x89\\x92\\x41\\x50\\xb9\\xd0\\x0f\\xe5\\x63\\x3a\\x05\\xf9\\x6e\\x0f\\x6f\\x90\\x56\\x1d\\x26\\x51\\xc6\\x1c\\x91\\x86\\x84\\xbd\\xa5\\x69\\xb6\\x33\\x3e\\x94\\xea\\x2f\\xa2\\x94\\x8b\\x05\\x00\\x5a\\xbb\\xa4\\x5a\\x91\\xf9\\x32\\x02\\xb7\\xb1\\xf9\\x60\\x92\\x03\\x72\\x66\\x46\\xd1\\xf1\\xdf\\xfa\\x90\\x51\\x94\\x5e\\x1b\\xba\\xe9\\x65\\x6a\\x68\\x4f\\x71\\x54\\xbe\\x93\\x09\\x3d\\x23\\x14\\xdd\\x0a\\xb7\\x89\\xad\\x87\\x59\\x99\\xc2\\xe3\\xe7\\x1d\\x8a\\xf5\\x1c\\xe3\\xdd\\x72\\x62\\xce\\x11\\x44\\x8f\\x18\\x3d\\xfd\\x36\\xc3\\x1d\\x78\\x89\\xe4\\xfb\\x57\\x6a\\x14\\xa5\\xdc\\xb1\\x32\\x19\\x59\\x19\\xae\\x90\\xfd\\x22\\xa6\\xf2\\xf5\\x9a\\xb7\\xea\\x9e\\xef\\xbd\\x9d\\xde\\x5c\\x11\\xe4\\x23\\xd5\\xc5\\x56\\x59\\x11\\xf3\\x5c\\x7b\\xdd\\xfa\\x6e\\x15\\x93\\xea\\x26\\xd2\\xee\\xde\\xbd\\xc7\\xfa\\xd6\\x51\\x72\\xaa\\x8c\\xeb\\x62\\x10\\x67\\x14\\x50\\xed\\xa1\\xe3\\x3a\\x3b\\x79\\x23\\x3f\\x2d\\xca\\xc3\\x3b\\x5b\\x6c\\x90\\xc2\\xa7\\x0a\\xf7\\x47\\x77\\x6d\\xd2\\x83\\xe3\\x2d\\x04\\x19\\x18\\xd7\\x62\\x80\\xdf\\xdf\\x69\\x06\\xea\\x1c\\xe5\\x75\\x09\\xfa\\x7f\\x99\\xcb\\xb3\\x88\\x28\\xbc\\x38\\xfe\\x58\\xfc\\xac\\x3e\\x33\\xe5\\x7a\\xc3\\x8d\\x88\\x86\\x0b\\x0d\\xda\\xf6\\xf9\\xff\\x55\\x20\\xae\\x64\\x4a\\x83\\x6f\\xd7\\x1d\\xf6\\xac\\x7c\\x09\\xde\\x15\\xc3\\xb1\\xec\\x08\\x1f\\x23\\x3f\\xdb\\x09\\x41\\x8c\\xf8\\x96\\x62\\xc7\\x75\\x21\\xce\\x19\\x05\\xae\\xe7\\x59\\x66\\xdf\\x05\\x34\\x84\\x93\\x3e\\x5a\\xe2\\x01\\x39\\x2d\\xaa\\xe4\\x74\\xa0\\xd0\\x03\\x0d\\xf3\\x2f\\x75\\xdc\\x2e\\x32\\xb2\\x0e\\xbc\\x47\\xbc\\x95\\xd6\\x28\\xf8\\x12\\xc9\\x6b\\x45\\xb3\\x36\\x6f\\x39\\xfd\\xae\\x9c\\xea\\xae\\x84\\x23\\x64\\xa5\\x3a\\xea\\x9c\\xe4\\xa8\\x74\\xa4\\xf9\\x4c\\x59\\x2d\\x67\\x03\\x58\\xa2\\x61\\x33\\x1f\\x13\\x01\\x30\\x1f\\xb5\\x5e\\x4d\\x6b\\x95\\x45\\x49\\x41\\x99\\x99\\xae\\xd9\\x3d\\x62\\x5b\\x6f\\x73\\xce\\x95\\x67\\x38\\x41\\xd5\\x02\\xed\\x88\\x51\\xc3\\x3a\\x6b\\x32\\x19\\x36\\x08\\x97\\xe5\\xf3\\x53\\xb9\\x2c\\xda\\x2c\\x7e\\x57\\xd7\\xbc\\xe0\\x64\\x0d\\xa6\\x22\\x7b\\xf0\\xb4\\xad\\xc1\\x4e\\xba\\xb8\\x12\\x2a\\x0b\\x7b\\x43\\xee\\x79\\x01\\x90\\xa0\\x8e\\x5e\\xc1\\x74\\xb2\\xee\\x7b\\x96\\x98\\x51\\xfc\\x58\\xd2\\x69\\xcd\\x5e\\x52\\x79\\x95\\x9a\\x24\\xc7\\x93\\x6f\\x2c\\x7a\\x0f\\xf1\\x20\\x3e\\xca\\x45\\x53\\xc9\\xe7\\x78\\xd3\\xa2\\x64\\x52\\x1e\\x7c\\x77\\xa1\\x6f\\x42\\x64\\x07\\x9d\\x59\\xe0\\xb8\\x72\\x93\\xa6\\x2d\\x01\\xf9\\x99\\x4b\\x8f\\xb6\\xe7\\x91\\x4f\\xc2\\xb9\\x03\\x4f\\xec\\x16\\x34\\x84\\x75\\x58\\xef\\x44\\xa0\\x30\\x4f\\x9c\\xe1\\x9e\\xce\\xfe\\x76\\x2c\\xb5\\x2b\\xf4\\x13\\x01\\x5b\\x7f\\x26\\xee\\x12\\x8d\\x3c\\xdf\\x74\\x4c\\x1e\\x73\\xac\\x83\\x7c\\x2e\\x58\\x58\\xfb\\x37\\x7f\\x6f\\x02\\x74\\x0b\\xf1\\x95\\x3a\\xb1\\x22\\x2f\\x93\\x3d\\x1f\\x2a\\x1a\\x48\\x51\\x61\\xfc\\xf7\\x3e\\x57\\x06\\x3a\\x8b\\x91\\x92\\xf3\\x3d\\x95\\x57\\x1e\\xb6\\xd5\\x82\\x94\\x6f\\x26\\xe1\\xb1\\xd8\\x16\\x10\\x84\\xc9\\xde\\xaf\\x23\\x1a\\x6d\\x92\\x89\\xbb\\x1e\\xe4\\x22\\xe6\\xd7\\x5d\\x78\\x76\\xcd\\xc0\\xe9\\xd9\\x39\\xb2\\x97\\x99\\x4a\\xa7\\x70\\x4f\\x64\\x2b\\xa7\\x24\\x9b\\xcd\\x2b\\x68\\x06\\xc6\\x63\\xc0\\xaf\\xac\\x9f\\xb7\\x12\\xe1\\x8e\\xea\\x9c\\x8e\\x05\\xa6\\xe2\\x0b\\xad\\x78\\x8d\\xc0\\x83\\xf6\\xcd\\x81\\x7a\\xca\\xe7\\x94\\x96\\xaa\\x95\\x31\\x2c\\xf1\\x58\\x5f\\x92\\x86\\xc3\\x0e\\xa1\\xfe\\x00\\xf5\\x59\\x66\\x29\\x39\\xb1\\x7b\\x12\\x59\\x90\\x42\\xb1\\xdd\\x2c\\x95\\xa5\\xc4\\x0e\\x5d\\xf5\\x7b\\xc4\\xe8\\x42\\x65\\x54\\xc2\\xac\\x62\\xc0\\xb0\\x95\\xec\\x78\\xf2\\x45\\xfe\\x88\\xee\\x1c\\xf1\\x86\\x80\\x5c\\x81\\x22\\xb3\\x46\\xa0\\x8a\\x28\\xec\\x9b\\xae\\xb6\\xf9\\x8d\\x4f\\x5b\\x7d\\xc5\\x02\\x22\\x21\\xce\\x11\\x18\\x78\\x11\\x58\\xdc\\xbb\\x18\\x39\\x02\\x7c\\x55\\xd1\\x33\\x15\\x72\\x13\\x5c\\xc5\\x29\\xfd\\x0c\\xdd\\x10\\xf6\\x29\\xae\\x5f\\xe5\\x34\\xfa\\xce\\x3f\\xdb\\x1a\\x42\\xe5\\x01\\x66\\xdd\\x9e\\x74\\x95\\x98\\xfc\\x10\\x45\\x05\\x2b\\x08\\x84\\x3c\\x0f\\x5f\\xff\\x09\\x8e\\x37\\x7b\\x65\\xaa\\xf0\\xc2\\x38\\xb6\\x70\\x98\\xdb\\x67\\xc2\\xf1\\x6d\\xaa\\xa9\\xf3\\xa9\\x70\\xda\\x42\\xe6\\x41\\xa6\\x6e\\xb8\\x57\\x4e\\x67\\x3e\\xc4\\x5b\\x33\\xcd\\x5f\\x34\\x9c\\x9b\\x39\\xab\\x67\\xb5\\xd9\\x82\\x35\\xc4\\xc9\\x8e\\xdb\\x5d\\xdd\\xe7\\x9e\\x8b\\xb8\\x1c\\xf8\\xb4\\x17\\x2e\\x66\\x0e\\x36\\xbb\\x3a\\x4e\\xc0\\xf8\\x4d\\x89\\x23\\xe2\\xb6\\x0d\\x74\\x46\\x05\\x97\\x26\\x55\\xf0\\x71\\x3b\\x80\\x13\\x2d\\x99\\xa4\\x7f\\xbc\\xbf\\x6a\\xfe\\x13\\x6a\\x9b\\x46\\xb3\\x3d\\xc8\\x44\\x92\\xe1\\xc7\\x22\\x35\\x78\\x4a\\xe0\\x10\\x44\\x7e\\x89\\xf2\\xd6\\x4d\\x83\\xd0\\xf5\\xab\\x92\\x56\\x0a\\x72\\x0a\\x3c\\x72\\x73\\xc2\\xb3\\xef\\xdf\\x6d\\x79\\xdb\\x6d\\x90\\x15\\x95\\x4a\\x4c\\x8f\\x69\\x4b\\x40\\x12\\xf8\\x7c\\x72\\xa5\\x2a\\x91\\xa2\\x27\\x5c\\x32\\x14\\x53\\xd1\\xf2\\xf0\\xaf\\xfe\\xbe\\x3e\\x82\\x6b\\x45\\x80\\xa5\\x57\\x41\\xa9\\x5b\\xa4\\x59\\x03\\x3c\\x75\\xb2\\x77\\x8e\\xfd\\x8f\\xfd\\x80\\xe5\\x4f\\xb4\\x8c\\xd7\\x00\\xc6\\x9b\\x54\\xa3\\xca\\x36\\xb0\\x01\\x99\\xc5\\x02\\x00\\x39\\x3e\\x6b\\x16\\x7e\\x2f\\xa8\\x36\\x33\\xa0\\x35\\x85\\x02\\x08\\xe9\\x1f\\x66\\x12\\x96\\xb1\\xf6\\xbc\\xb6\\x1e\\x5b\\x44\\x20\\x57\\x4a\\xb3\\xb7\\x48\\x5d\\x40\\x21\\x87\\x69\\xd1\\x91\\xd7\\xff\\xd6\\x7c\\xb7\\x68\\x38\\x36\\xe9\\xa0\\x39\\x6a\\x85\\x8f\\x24\\x0d\\xfc\\x0e\\xfd\\x83\\x8e\\xf2\\xcf\\x5a\\xa9\\x06\\x13\\x9f\\xdb\\x36\\xe6\\x6e\\xcc\\x59\\x23\\x3d\\x20\\xf9\\x37\\x87\\x6b\\x84\\x82\\xb7\\x34\\xda\\xc5\\x06\\x5d\\x75\\xea\\x47\\xeb\\x77\\xac\\x98\\x46\\x4d\\xb3\\xaf\\x47\\x12\\x78\\xd4\\x40\\xb1\\x2a\\x43\\x92\\x1f\\x9d\\x48\\x86\\x8a\\x0c\\x18\\xc9\\x37\\x2d\\x79\\x46\\x39\\x13\\x26\\xfe\\xf9\\x78\\xd7\\xdb\\x92\\x2d\\xe6\\x53\\x2d\\x3d\\xd3\\x35\\x9c\\x86\\x0b\\xd6\\xfc\\xfb\\xad\\x25\\x01\\xfc\\xa4\\xa2\\xc0\\x44\\x25\\x6e\\x31\\x10\\x2f\\xb6\\x78\\xd3\\xfe\\xac\\x72\\xf7\\x3f\\x4b\\xb2\\x84\\x1d\\xd4\\x9b\\x68\\x55\\xd9\\x9d\\x96\\x68\\x3e\\x9b\\x32\\xdc\\x46\\xfb\\x1c\\xf2\\x69\\x51\\x21\\xf3\\xe0\\x21\\x3c\\x9c\\xff\\xa8\\xd6\\x05\\x70\\x7e\\xb8\\x3f\\xef\\x1a\\x97\\x7d\\xf8\\x18\\xb3\\xb3\\x70\\x80\\xdf\\x32\\xf1\\xd5\\xac\\xd5\\x61\\x47\\x25\\x95\\x13\\x60\\x3d\\x2e\\x40\\x23\\x92\\xd1\\x42\\xee\\x05\\x72\\xa4\\xd2\\x6e\\x72\\xe3\\x7e\\xf4\\x54\\xb2\\x2b\\x57\\x3c\\xa4\\x23\\x38\\xcd\\x8b\\x87\\xed\\xe5\\x30\\x2a\\x0f\\x2d\\xdc\\xc0\\xdc\\x1e\\x50\\xdd\\x53\\xff\\x5f\\x62\\x9a\\x68\\x1b\\x11\\xbe\\x59\\xb5\\xf4\\xd3\\xf6\\x0e\\xbb\\x62\\x3e\\xf2\\xcb\\x44\\xfe\\x13\\x09\\x5c\\xb1\\x6b\\x1c\\xb7\\x5f\\xd6\\xd5\\xb7\\xa4\\xf2\\x96\\x0a\\x91\\x59\\xf2\\xa4\\xc6\\xde\\xbe\\x8f\\xf2\\x24\\x5a\\x84\\x5f\\xd7\\x63\\x75\\x7c\\x56\\xf0\\x85\\x12\\x0e\\x47\\xba\\x57\\xd7\\x80\\xf3\\x56\\xed\\x04\\x4d\\xab\\x0b\\x7e\\xdd\\xbf\\xd8\\xf3\\xa9\\x4c\\x41\\xa0\\x46\\x1f\\x34\\x7d\\xbb\\x83\\xaa\\xdf\\xa5\\x17\\xc0\\x93\\x5b\\xa7\\x5e\\xa0\\xae\\x32\\x3e\\x87\\x54\\x01\\xb8\\xdf\\x98\\xd0\\x79\\x4b\\xc5\\x83\\x3c\\xbf\\xdf\\x30\\x23\\xd6\\xcc\\xf0\\xc4\\x4a\\x07\\x76\\x0b\\xb9\\x4f\\x43\\xc5\\xa3\\x85\\xca\\x59\\x7a\\x23\\xa7\\x44\\x09\\x21\\x01\\x92\\x5e\\x0f\\x49\\x22\\xb0\\x9d\\xca\\xea\\x10\\x2c\\x5a\\xe1\\x98\\x3d\\x2f\\x59\\xfb\\x4b\\xb7\\xb6\\xb7\\x66\\x4e\\xcc\\xea\\x29\\xa6\\xa9\\x3d\\x12\\xa1\\x4f\\xb1\\x15\\xed\\xbf\\x06\\xef\\xdb\\x1d\\xdb\\xe9\\xfd\\x0c\\x51\\x35\\x98\\xbb\\x12\\xdb\\x6a\\x82\\x5c\\x29\\xfc\\x06\\x73\\xef\\xd3\\x25\\xa1\\x39\\x49\\xc2\\xd4\\x54\\xc1\\x13\\x57\\x71\\xc1\\xea\\xa3\\x63\\x1f\\xcb\\xee\\xb1\\xbd\\xc9\\x74\\x6e\\x89\\xbc\\x6e\\x28\\xac\\x54\\x72\\x3a\\xba\\xad\\xfe\\x14\\x49\\x04\\x56\\x56\\xa8\\x53\\x2b\\x74\\x7b\\xc7\\x5f\\xab\\xaa\\x60\\xe5\\x8c\\xe9\\x43\\xda\\x20\\x65\\x1c\\xe8\\xf9\\x97\\x01\\xec\\x7c\\xa3\\x3b\\x48\\x0a\\x5e\\xaf\\x41\\xf0\\xe5\\x5e\\x62\\x4f\\x2e\\x5b\\xb8\\x2e\\x92\\x23\\x59\\xe8\\xb1\\x79\\x6a\\xa1\\x5d\\x26\\xdf\\xf3\\x3d\\x30\\xf2\\x2f\\xe8\\x92\\x45\\xa4\\xa5\\xbc\\x91\\xe9\\x72\\x32\\x0a\\xa7\\x4e\\x43\\x1e\\xe9\\xf1\\x87\\xad\\x3e\\x99\\x94\\x58\\x82\\xa0\\x99\\x63\\xde\\xe9\\xf9\\x61\\xaf\\x89\\xd1\\x47\\x98\\x2e\\xca\\x17\\x61\\xaa\\x89\\x6c\\xc9\\xde\\x1b\\xae\\x00\\xcf\\x75\\x8d\\x73\\x75\\x76\\x97\\x7a\\x57\\xa4\\x4a\\x43\\xd9\\x2b\\x03\\xcc\\xbb\\xa2\\x92\\x38\\x86\\x5d\\x0e\\x62\\x84\\x4c\\xaf\\x2f\\x79\\x47\\xd8\\x0e\\x9c\\x9e\\x60\\x04\\x09\\x95\\xe2\\x35\\xb3\\xc2\\xe2\\xf7\\x0b\\x78\\xa6\\x79\\x25\\xb4\\x5d\\x79\\xa5\\x21\\xdb\\xf1\\xf7\\xcf\\x9a\\x49\\x30\\x7f\\x9e\\x90\\x92\\x80\\xae\\x0d\\xae\\x68\\x64\\x35\\x83\\x35\\x90\\x8c\\x34\\x8e\\xe7\\xb2\\x51\\x6b\\xf7\\xd2\\xd0\\x79\\xcd\\x61\\x0e\\x25\\x64\\xc2\\x9c\\xec\\x5e\\x76\\x62\\xf9\\xc7\\x25\\x1a\\xa0\\xe5\\x1c\\x40\\xe9\\x4c\\x2e\\x55\\x1f\\x0c\\xd3\\x38\\x6a\\x71\\x2b\\xbf\\x43\\x48\\x4a\\x9a\\xfd\\x4b\\x64\\x4a\\x09\\x9f\\x4b\\xc1\\x32\\x52\\x86\\x79\\x71\\x6b\\x60\\xfa\\x59\\x3c\\x1e\\x35\\x00\\x9b\\x81\\x32\\x6c\\x35\\x31\\x18\\xcc\\x2f\\x5a\\x18\\x84\\x07\\xe5\\x9b\\xc5\\xc9\\xee\\xef\\x8f\\x8d\\xaf\\x8f\\x92\\xce\\x1b\\x6f\\xee\\xdb\\xad\\xa2\\xfd\\x1a\\x6c\\x7b\\xfc\\x04\\xcc\\x92\\xe5\\x40\\xa1\\xca\\x70\\x91\\x4a\\x2a\\xb5\\x92\\x5b\\x91\\x1c\\x04\\x9f\\xff\\xdd\\x7e\\x02\\xcc\\x68\\xea\\x8e\\xcb\\x8d\\xb5\\x17\\x37\\x99\\x1f\\xd8\\xbd\\x25\\xf8\\xb0\\x9a\\x99\\xad\\x1d\\x4d\\x33\\xf6\\xec\\xba\\xf9\\x1f\\xa4\\x7d\\x24\\x73\\x53\\x56\\xda\\xd1\\x93\\xfb\\x21\\xc5\\x43\\xd9\\x00\\x10\\xf5\\xb7\\x3b\\x3f\\x05\\x84\\x6f\\xb3\\x8d\\xcc\\xa6\\x6f\\xb8\\x2e\\x66\\x7b\\x71\\x9a\\x3d\\xc0\\x15\\x3e\\x77\\x61\\xc0\\x37\\x02\\x3c\\xe7\\x68\\xcc\\x3b\\x57\\x50\\x6f\\x2f\\xdb\\x35\\x39\\xe5\\xd0\\x37\\xd4\\x84\\x8e\\xa5\\x98\\xef\\xfb\\x01\\x33\\x3f\\xc0\\xec\\x80\\xe0\\x74\\xe0\\x4b\\xda\\x86\\x93\\xcb\\xa3\\x31\\x05\\xe1\\xfa\\x6e\\xd7\\x5e\\x2d\\x10\\x1e\\xbc\\xdb\\xfa\\x4d\\xf7\\xc1\\xf1\\x51\\xf7\\x31\\x2b\\x10\\xfa\\x34\\x1d\\x76\\x36\\x58\\x9c\\xca\\x90\\x96\\x04\\x79\\xcd\\xa6\\x9b\\xcf\\x99\\x09\\x56\\x79\\x09\\xfa\\x28\\x9a\\x46\\x21\\x13\\xdd\\x2e\\xf2\\x51\\xe8\\x2f\\x7b\\x53\\x4a\\x03\\x92\\x0e\\xc8\\xb2\\x55\\xdc\\x16\\x3c\\xb0\\x09\\x9e\\xe5\\x32\\xc8\\x09\\xd7\\xca\\xcf\\x27\\x92\\x44\\x2e\\x9c\\xcd\\x85\\x19\\x02\\x57\\x31\\x77\\x64\\x05\\x6c\\x08\\x91\\xae\\xa6\\xf9\\x2f\\x5c\\x97\\x72\\x32\\x4c\\x75\\xf7\\xef\\x53\\x27\\x11\\xb2\\x25\\xd1\\x65\\x85\\x73\\x13\\xf4\\xce\\xa4\\x08\\xa4\\xa4\\x47\\x3f\\xce\\xa4\\x2d\\xab\\x41\\x1b\\x9b\\x8a\\x23\\xa8\\xd7\\xa0\\xa6\\x1a\\x85\\xcc\\xd1\\x8b\\xff\\x0e\\x6b\\x1e\\xf7\\x90\\x67\\xf3\\x54\\x97\\x48\\x63\\xec\\x18\\x5d\\x24\\x5b\\x62\\xed\\xf2\\x31\\xc1\\x45\\x5d\\xed\\xbe\\x42\\xb3\\x50\\x01\\xd0\\x5d\\x5d\\x8b\\x2e\\x99\\xe2\\xef\\x88\\xce\\xfc\\x8a\\x8a\\x30\\x1a\\x6e\\x12\\xac\\xdb\\xee\\x28\\x73\\xcf\\xfc\\x08\\x83\\xe3\\x98\\x36\\x97\\xbe\\x9b\\xee\\x13\\x54\\x0e\\x3e\\x3f\\x96\\xd9\\xbb\\x37\\xf4\\xa1\\x7d\\xdd\\x8d\\x05\\xbc\\x62\\x0b\\x4e\\x02\\x4c\\xe8\\xa9\\x40\\xa6\\xaf\\xd4\\xa9\\x61\\x1e\\x74\\x5e\\x04\\xfe\\xee\\x2b\\x47\\x1e\\xd8\\x73\\x10\\x3c\\xea\\x02\\x6b\\x6e\\x64\\xef\\x36\\x81\\x31\\x38\\x77\\x6f\\xf7\\x71\\x79\\xd8\\x7a\\xf1\\xdb\\xa6\\x24\\xa3\\x2a\\x08\\x5b\\xa6\\xaa\\x3b\\xf2\\x6c\\x0d\\x8d\\xdd\\xbb\\xad\\x77\\x68\\xdd\\x2d\\x06\\x58\\xb5\\x5f\\xbe\\xe2\\xbc\\xb5\\x7b\\x43\\xf7\\xa0\\x26\\x80\\xc1\\x53\\x46\\xf0\\x0c\\xa1\\x4f\\x15\\x33\\x91\\x45\\x94\\x1b\\x8e\\x20\\xe8\\x31\\x45\\x49\\xdf\\xc9\\xb2\\xa9\\xa3\\x93\\x5c\\x9f\\x11\\xa0\\xd2\\xf7\\xc5\\xf2\\x89\\x42\\x88\\xcf\\x78\\x35\\x34\\xdc\\x64\\xe4\\x1d\\x4d\\xb1\\xc1\\x0f\\x6b\\xc5\\xb3\\xe0\\x34\\xfa\\x91\\x43\\xbf\\x60\\xc1\\x14\\x89\\x1a\\x87\\xf2\\xdc\\xd8\\x56\\x2a\\xe6\\x6d\\x9e\\x22\\xf2\\xf1\\x11\\xe6\\x36\\x07\\xd8\\xb1\\xb4\\x9d\\xee\\xaa\\x72\\x14\\xe3\\xf2\\xfd\\x95\\x67\\x8d\\x72\\x98\\x85\\xab\\xe2\\xab\\x7e\\x88\\xcd\\xb8\\xc6\\x1a\\x0b\\xec\\x18\\x09\\x5a\\xb5\\x06\\xdb\\x88\\x64\\xbb\\xf1\\xdd\\x5a\\xb9\\xe8\\x36\\x56\\xcb\\x0f\\xa4\\x5a\\x72\\x77\\xae\\x4e\\x0d\\x75\\x1e\\x4f\\x22\\x79\\x01\\xdc\\xbf\\x52\\x00\\xf3\\xa6\\xe2\\x2d\\x08\\x9d\\xcd\\x60\\xb3\\xdf\\x5c\\xa1\\x2b\\x4f\\x6f\\x39\\xd5\\xb4\\x15\\x93\\x7c\\x62\\x00\\x37\\x5d\\x86\\xf5\\xab\\x98\\xdb\\x62\\xa6\\x6b\\xf3\\xae\\x44\\xd8\\x91\\xd6\\xa3\\x24\\x0c\\x37\\x32\\x06\\x02\\xc8\\x95\\x9d\\x12\\x43\\x0e\\xdf\\x1b\\x02\\x85\\x0e\\x02\\x32\\xfb\\xa7\\xe1\\xca\\xc4\\xdd\\x9d\\x69\\x4e\\xb7\\x33\\x33\\xa0\\x81\\x0a\\x06\\xe3\\xa7\\x1d\\x04\\x12\\x97\\x4f\\x25\\x7f\\x75\\xcf\\x85\\x4c\\xd7\\x5b\\x97\\xd7\\x84\\xf0\\x62\\x54\\xe4\\x60\\x0b\\xa5\\x0b\\x31\\x67\\x85\\x55\\xa5\\xb9\\x0f\\x37\\xb1\\x71\\x33\\xda\\x83\\xcd\\x6d\\x56\\xd6\\xeb\\x81\\x0a\\xae\\xed\\x27\\xcb\\xe7\\xfa\\x80\\x67\\x34\\xc3\\xf2\\x31\\x4b\\xd1\\x28\\x2b\\x7f\\x27\\x55\\xe4\\x20\\xd0\\x70\\x51\\x27\\x38\\x34\\xae\\x34\\x51\\x47\\x93\\xe1\\x1c\\x17\\x23\\x16\\x2e\\xdd\\xb2\\xc0\\xa4\\x9e\\xe1\\xc1\\x5d\\x0d\\xe1\\xed\\x32\\x9e\\x72\\xff\\x7b\\x3e\\x8f\\xc0\\xd2\\x57\\x9a\\xb7\\x28\\x29\\x33\\x22\\x1f\\x4e\\xd5\\x0e\\xd9\\x65\\x4b\\xb6\\xc0\\xa8\\xf3\\xa3\\xfb\\x98\\x85\\xb3\\xbe\\xbf\\x9d\\xcd\\x51\\xf7\\x3f\\xa3\\x03\\xbc\\xba\\x5f\\x44\\x14\\xc4\\x11\\x8a\\xb1\\xeb\\xad\\xc8\\x04\\x48\\x67\\x1b\\x96\\x00\\x81\\xb6\\xcc\\xbe\\x2a\\x7f\\x50\\x4f\\x99\\x18\\x83\\x23\\x72\\xee\\xb6\\x5c\\xb6\\xef\\xdb\\x4b\\xce\\x9c\\xec\\xc4\\xa3\\x33\\xa7\\x23\\xd9\\x12\\x96\\x48\\x93\\x6a\\x50\\x7b\\x58\\x3d\\x70\\x8a\\x8b\\x01\\xd2\\x56\\x86\\xf8\\x95\\xab\\x40\\xd5\\xee\\x01\\xb9\\x0d\\x56\\xe2\\x00\\x53\\x16\\x25\\x46\\xe4\\x93\\xce\\xa0\\xbb\\x9a\\xc3\\x2f\\xd1\\x44\\x6d\\xb6\\x90\\xfb\\x01\\x70\\x19\\xc2\\xb2\\x30\\xf2\\xe7\\x36\\x8a\\x17\\x18\\x51\\x24\\xc3\\xf2\\xb7\\x7c\\xfc\\x29\\x52\\xbd\\x5f\\x58\\xd1\\x3d\\xf6\\x1b\\x38\\xf8\\x00\\xea\\x59\\x0e\\xc7\\xd3\\x84\\x5f\\x15\\x1e\\x1d\\x11\\xa4\\xbd\\xb3\\xb7\\x39\\xa0\\x10\\xc9\\x10\\xd5\\x86\\xc9\\x6e\\xac\\xed\\x7d\\xff\\x97\\x96\\x19\\xa9\\x0c\\x1a\\x0a\\x4f\\x01\\xe4\\xe4\\x48\\xa8\\xfe\\x24\\x69\\x23\\x4f\\x82\\x17\\x25\\xb0\\x8f\\x33\\xd8\\xe2\\xca\\xd6\\xcb\\x19\\x58\\x31\\x9f\\xd2\\x41\\xfb\\xf7\\xd4\\x73\\xfc\\x2a\\x6d\\x29\\x03\\x5a\\x17\\x21\\x7b\\x94\\x12\\x62\\xae\\xfb\\x4b\\x1e\\x25\\xe1\\xeb\\xdf\\xad\\x8a\\x81\\x6d\\xb7\\x38\\xe6\\x52\\x66\\x08\\x0a\\xc8\\x43\\xf7\\xdf\\x5e\\x1c\\x87\\x34\\xb7\\xa9\\x7b\\x99\\xed\\xf5\\xb2\\x8e\\x6b\\xb5\\x29\\x4a\\x98\\x35\\x3d\\xa6\\x05\\x97\\x2b\\x8a\\x41\\xfa\\x61\\x18\\x58\\x93\\xe5\\x26\\x55\\x01\\xfd\\x34\\x02\\xbb\\x72\\x53\\xe8\\x48\\x19\\x84\\xe3\\x84\\xe8\\x07\\xde\\x26\\xed\\xce\\x6a\\x9e\\x58\\x82\\xb6\\x53\\x20\\x09\\xed\\x6c\\xe7\\x30\\xd5\\x54\\xb0\\xc8\\x31\\x4d\\x4b\\xb4\\xda\\xce\\xc6\\x49\\x80\\x67\\x1f\\xb5\\x1d\\x3f\\x3f\\xa1\\xbc\\x68\\x42\\x2f\\x87\\x2b\\xf6\\x25\\xbc\\x97\\xec\\x2c\\xfe\\xab\\x13\\x1f\\xcf\\x61\\x1b\\xd4\\x50\\xe3\\x2e\\x44\\xcb\\xe3\\x92\\xf0\\x77\\x93\\x13\\xb3\\x5d\\xbd\\x14\\x51\\x30\\xa3\\xbd\\x2a\\x64\\xf4\\x5a\\xb4\\x7d\\xd9\\xa1\\xf2\\xfe\\xd7\\x51\\x44\\x0c\\xbe\\xbf\\x63\\x27\\x10\\x56\\x23\\x66\\xa3\\x51\\x09\\xd9\\xbf\\x18\\xed\\xcc\\x03\\x31\\x8f\\x4a\\xaa\\x86\\xea\\xe9\\x0c\\x2b\\x66\\xe2\\x9d\\xf2\\xfd\\xf1\\xe3\\xaa\\x90\\xfa\\xc5\\x2f\\xa7\\xb8\\x5f\\x2a\\x11\\xc4\\x9c\\x9d\\xdb\\x2d\\xb8\\x2d\\x72\\x16\\x16\\x96\\x3b\\x4b\\x5f\\xa3\\xe8\\x15\\xf0\\x7a\\x38\\xcf\\x0a\\xe4\\x2d\\x27\\x19\\xd0\\x05\\x4d\\x28\\xe9\\x0d\\xc2\\x69\\xec\\x13\\xf6\\x27\\x0b\\x26\\x3b\\x12\\x09\\x9d\\x30\\xf4\\x8b\\xc5\\xef\\x8a\\x19\\xdd\\xdb\\xc8\\x6c\\x8f\\x65\\x08\\x9a\\x80\\x94\\xfd\\x9d\\x47\\x45\\x37\\xa1\\xb2\\x74\\x0e\\x88\\x38\\x24\\xf5\\x85\\xe0\\x01\\x48\\x35\\xc6\\x6f\\x57\\xd9\\x1c\\x8a\\x44\\x10\\xcf\\xc3\\x7c\\x02\\x74\\x37\\x85\\x77\\x85\\x0a\\x66\\x7b\\x48\\xc8\\x33\\xa5\\x3c\\xf4\\x72\\x0f\\x59\\x89\\xed\\xf1\\x35\\xc6\\xe0\\x10\\x7d\\x6a\\xc8\\xb1\\xd7\\x12\\xb8\\x2b\\x66\\x9c\\xf5\\x70\\x72\\x7e\\x63\\x7b\\x12\\xe1\\xe6\\x79\\x99\\xa9\\xb9\\xdd\\x66\\xf8\\x01\\xc5\\x76\\x9e\\x3b\\x2d\\x70\\x65\\x7e\\x20\\x03\\x05\\x57\\xa9\\x04\\xe1\\x87\\x21\\x46\\xa6\\x5b\\xea\\x5a\\x5f\\x3d\\x4b\\x20\\xb6\\x74\\xcb\\x2a\\x32\\xa3\\x58\\x5a\\x29\\xc1\\x1a\\xe9\\xfe\\xcf\\xfd\\x60\\x6c\\xfc\\x54\\x88\\xa3\\x4f\\x8c\\x7f\\x3a\\x62\\x4c\\x67\\x4b\\x6e\\xd1\\x98\\x28\\xb1\\x9b\\x5d\\xfe\\x98\\x12\\x66\\x2a\\x72\\xe4\\x96\\xb5\\x25\\x30\\x74\\x4a\\xf9\\xd8\\x42\\xee\\x4a\\x54\\xf7\\x64\\xcf\\x75\\x98\\x9b\\xa7\\x9b\\xc2\\x7b\\xba\\x7e\\x30\\xd0\\xe6\\x32\\x0c\\x3c\\x88\\x69\\xfe\\x0f\\x89\\x21\\x3e\\x8c\\xc9\\xef\\x67\\x37\\x14\\x98\\x27\\x12\\xe9\\xba\\xeb\\x12\\x9e\\xd3\\x47\\xfc\\x25\\x78\\xa7\\x90\\xc3\\x2b\\x08\\xae\\x39\\x86\\xd0\\xac\\xdd\\xc7\\x6b\\xcc\\xe0\\x3b\\x51\\x11\\x59\\x7d\\x46\\x19\\xf5\\xbc\\xbc\\xb8\\x6a\\x74\\xa6\\x9f\\xd8\\x44\\x51\\x0d\\xf4\\xed\\x89\\xc1\\x44\\xe1\\xfb\\x1d\\x0a\\x91\\x9c\\x3f\\x87\\xb5\\xc3\\x4f\\xde\\xc1\\x93\\x27\\x6b\\xb7\\x6c\\xb2\\x5a\\xda\\xc9\\xe2\\xe0\\x3d\\x5a\\xa0\\x2b\\x49\\xe7\\xc6\\xbb\\x48\\x4d\\x8a\\x69\\xbe\\x17\\x08\\x99\\x1a\\x16\\x10\\xc7\\xa8\\xce\\x8c\\x0b\\x3a\\x24\\xd1\\x66\\xb0\\xd9\\xc7\\xf4\\x22\\xfa\\x5c\\xad\\xdc\\xc0\\x25\\x53\\x5d\\xc6\\xaa\\x8c\\xc5\\x89\\xf7\\x83\\xa7\\x54\\xbe\\xde\\x47\\xe2\\x9b\\x74\\x31\\xf1\\xc3\\x3d\\x60\\x20\\xf3\\x6d\\xd0\\xd7\\xfe\\x3b\\xcb\\x54\\xcc\\x3c\\xff\\xed\\x25\\x32\\x9c\\xf9\\x22\\xe1\\xbd\\xa7\\x14\\x56\\x02\\xec\\x6b\\x8d\\x92\\xe7\\x4f\\x22\\x73\\x0e\\x1a\\xce\\x5f\\x33\\xea\\xfc\\xba\\x05\\x6b\\xd1\\x9c\\x41\\x0e\\x8b\\xb9\\xed\\x57\\xc1\\x65\\x67\\x26\\x57\\xa5\\x9f\\x6f\\x07\\xef\\xca\\x0b\\xb0\\xc5\\xf3\\x20\\x24\\xb7\\xc0\\x02\\x33\\x7d\\x7a\\xf4\\x8a\\x00\\x3b\\x89\\x06\\x5c\\x6b\\xf2\\x17\\x13\\xed\\x4f\\xd7\\x63\\xfd\\x7b\\x59\\x4d\\x8e\\x38\\xc1\\xe1\\x10\\x8d\\x8b\\xfe\\xb5\\xde\\xd7\\x98\\x7c\\xe3\\x1b\\xe2\\x16\\x17\\x72\\x55\\xb7\\x36\\x0b\\xbe\\x90\\x87\\x9c\\x52\\x12\\x3a\\x79\\x8c\\xaf\\x1e\\xea\\x66\\x47\\x20\\x28\\x70\\x14\\x74\\x06\\xc2\\xd0\\x03\\xab\\x26\\xe7\\xbd\\xb2\\xab\\x70\\x6e\\x77\\x7c\\x99\\x36\\x25\\x1c\\x7f\\x7d\\xf0\\x9c\\x89\\xb2\\x5c\\x8e\\x7a\\xb6\\xf7\\xf7\\x45\\x62\\x38\\x59\\x0b\\xa5\\x80\\x04\\x0f\\x7e\\x6d\\x96\\x07\\x59\\x92\\x73\\xb9\\x93\\x07\\x00\\xde\\x92\\x8f\\xfd\\xc8\\xb9\\x9c\\xae\\x26\\x05\\xfb\\x3b\\x14\\xfb\\xd0\\xb5\\xc5\\xae\\xd9\\xb1\\x91\\x4f\\x7b\\xe1\\x0a\\xa5\\xf1\\x11\\xf3\\x77\\x20\\x72\\x77\\x19\\xca\\x9e\\xee\\x29\\xf0\\xc2\\x04\\x73\\x23\\x8c\\x53\\xa4\\xca\\x14\\xd4\\x5d\\x9a\\x96\\x9f\\x41\\xd5\\x12\\x1e\\x6b\\xd8\\xb6\\xe3\\x1d\\xdf\\x8d\\xd7\\xe6\\x54\\x55\\x02\\x2c\\xc6\\xfe\\x61\\x17\\x09\\x5c\\x51\\x5a\\xb9\\x2d\\xc8\\xa6\\x6f\\x5f\\xd1\\x2e\\xe8\\x1d\\x0d\\xe5\\x41\\x47\\xb0\\x0c\\x3c\\x31\\x12\\x4d\\xdb\\x37\\x2f\\x0c\\x6f\\x7b\\x66\\x90\\xc8\\x17\\xed\\xe0\\x60\\x23\\x35\\xab\\xf9\\xcd\\x93\\x9a\\x69\\xee\\x60\\x00\\x1a\\xb7\\xf5\\xe5\\x47\\x7a\\xcb\\x9e\\xdc\\x75\\x5c\\x4b\\xe1\\x1b\\xfc\\x18\\x40\\x54\\xb4\\x96\\xab\\xdb\\xf7\\x07\\x5b\\x92\\xc1\\x07\\xbd\\x80\\x4a\\x90\\x7b\\x97\\xd0\\xe3\\xad\\xfa\\x34\\xe4\\x24\\x10\\x47\\xd0\\xdf\\xf1\\x1a\\x30\\xa9\\xae\\x98\\x3d\\x2d\\xb2\\x15\\xa4\\x71\\xf0\\x7a\\x85\\x21\\xa5\\xea\\x7b\\xc3\\x74\\x08\\x07\\xb3\\x4f\\x80\\x01\\xd3\\x85\\x77\\x2e\\x94\\xf7\\x32\\x69\\x25\\x73\\xf5\\x1b\\xaa\\x44\\xd0\\xb0\\x0a\\x32\\x8e\\xbd\\x37\\x0c\\xaf\\x62\\x46\\x07\\xcd\\xfa\\x8f\\x2b\\x8a\\x0e\\xfe\\xf8\\x33\\xde\\x69\\xd3\\xe6\\x31\\x28\\x76\\x3d\\x90\\x47\\x88\\xf2\\xee\\x39\\x6f\\xae\\xd0\\x82\\x82\\xa8\\xa5\\x94\\xb1\\x75\\x27\\x2f\\x08\\xf5\\xdf\\x53\\x41\\xf5\\xfa\\xa0\\x26\\xcb\\x1a\\xa8\\xb5\\xde\\xb5\\x7e\\x2b\\xa7\\x06\\x39\\x42\\x38\\x19\\xea\\x93\\x17\\x45\\xd5\\x25\\x1c\\x82\\x0b\\xe0\\x0b\\x3b\\x90\\x8b\\xeb\\x7d\\x4b\\xa7\\xb4\\xda\\xc5\\xe2\\xcb\\xde\\xc4\\xb6\\x72\\xc4\\x03\\x6d\\xab\\xe0\\xad\\xfe\\x5a\\x86\\xbc\\x61\\x50\\xfc\\x53\\xe1\\x51\\x6b\\x9c\\x42\\xdb\\xc8\\x7c\\x24\\x3f\\x48\\x31\\x5e\\x46\\x31\\x2b\\x45\\x29\\x78\\x3d\\x54\\x02\\x08\\x60\\x58\\x42\\x5a\\x91\\xbd\\x20\\x32\\x93\\xf2\\xd2\\x5f\\x62\\x3f\\xd5\\x4f\\xaf\\xde\\xd7\\x2e\\x2d\\x0b\\x32\\x9c\\xf7\\x60\\xa8\\x04\\xf6\\x72\\xd8\\xbf\\xe1\\x50\\xab\\xdf\\x05\\xd0\\x6f\\x8c\\x98\\x9f\\x31\\x55\\x90\\x41\\xb2\\xf0\\xee\\xb4\\xce\\x5b\\x99\\xa5\\x19\\x08\\xbb\\x02\\x9a\\x6c\\x22\\x7a\\x2c\\x59\\xee\\x78\\xac\\x4a\\x10\\x3d\\x17\\x52\\x30\\x30\\x42\\xe1\\x6a\\x04\\x7a\\xb3\\x57\\x76\\x82\\x06\\xa2\\x8f\\x24\\x3c\\x40\\xb2\\x50\\x6a\\x08\\x95\\x5c\\xc4\\xc9\\x89\\x8f\\x6a\\x32\\xe3\\x87\\x26\\xb4\\x1a\\x69\\x30\\xe1\\xda\\x47\\xdf\\xd8\\x4e\\xc0\\x6f\\x52\\xa1\\x25\\xa3\\xd2\\x4c\\x84\\x0c\\x92\\x75\\x20\\xc1\\x61\\x0b\\x6f\\x7e\\x4f\\x5d\\x8a\\xda\\x2e\\x1f\\xb8\\xe1\\x80\\x17\\xfe\\x91\\x93\\x3d\\x30', 1)"
  },
  {
    "path": "agent/fix_rule/license.lic",
    "content": "HSpGTEFHUzoBKkNPREU6UHlhcm1vci1Qcm9qZWN0OHD4jbg3oaZPjPlTyiQyadr7bY7WVZJHSrbRS3HjpzdMKMC4qTYbE97ZIZZ8XWDTHSJrrOVqGCnWjuZ71LGMWNMESpvXwaRyL9WGqf9kmUO9iYDYVWwF8u/DddUuYjq4k/V1JEGKftwPFwieTkza8iiUts7xUu/dHRKLwANb/MU="
  },
  {
    "path": "agent/fix_rule/product.key",
    "content": "Bې?CA\u0016k8a\u0011\u00136W\fH0vY\ry\n\u001e\r}\u001f\u0005q\u0001#fRq+JBwzʱnƐS*T\u0011E`wN(\u0005RGy0t\u001dD\u001c&y\u001d\nP:C\u001fq\\8SBV]"
  },
  {
    "path": "agent/fix_rule/pytransform.py",
    "content": "# Because ctypes is new from Python 2.5, so pytransform doesn't work\n# before Python 2.5\n#\nfrom ctypes import cdll, c_char, c_char_p, c_int, c_void_p, \\\n                   pythonapi, py_object, PYFUNCTYPE\nfrom ctypes.util import find_library\n\nimport os\nimport sys\nimport platform\nimport struct\n\n#\n# Global\n#\n_pytransform = None\n_get_error_msg = None\n\n#\n# Options\n#\n\n# How to show error message return from dynamic library _pytransform.\n#\n# Each time call a dll function, if something is wrong, _get_error_msg\n# will return the reason.\n#\n# Enable _verbose_mode will print the details got from _get_error_msg.\n# Disable this options will print only a short message.\n_verbose_mode = 1\n\n# In debug mode, print trace stack when raise exception.\n# Otherwise only show a short message.\n#\n# Run python with command option \"-d\", or set environment variable\n# PYTHONDEBUG. For example\n#\n#   python -d pyarmor.py xxxx\n#\n_debug_mode = sys.flags.debug\n\nclass PytransformError(Exception):\n    def __init__(self, *args, **kwargs):\n        super(Exception, self).__init__(*args, **kwargs)\n        if _debug_mode:\n            self._print_stack()\n\n    @classmethod\n    def _print_stack(self):\n        try:\n            from traceback import print_stack\n        except Exception:\n            _debug_mode = 0\n            sys.stderr.write('Disabled debug mode.\\n')\n        else:\n            print_stack()\n\ndef dllmethod(func):\n    def format_message(msg, *args, **kwargs):\n        if _verbose_mode:\n            s1 = str(args)[:-1]\n            s2 = ', '.join(['%s=%s' % (k, repr(v)) for k, v in kwargs.items()])\n            sep = ', ' if (s1 and s2) else ''\n            line = 'Call with arguments: %s%s%s)' % (s1, sep, s2)\n            return msg\n        return msg.split('\\n')[-1]\n    def wrap(*args, **kwargs):\n        args = [(s.encode() if isinstance(s, str) else s) for s in args]\n        result = func(*args, **kwargs)\n        errmsg = _get_error_msg()\n        if errmsg:\n            raise PytransformError(format_message(errmsg, *args, **kwargs))\n        return result\n    return wrap\n\n@dllmethod\ndef init_pytransform():\n    major, minor = sys.version_info[0:2]\n    # Python2.5 no sys.maxsize but sys.maxint\n    # bitness = 64 if sys.maxsize > 2**32 else 32\n    prototype = PYFUNCTYPE(c_int, c_int, c_int, c_void_p)\n    init_module = prototype(('init_module', _pytransform))\n    init_module(major, minor, pythonapi._handle)\n\n@dllmethod\ndef init_runtime(systrace=0, sysprofile=1, threadtrace=0, threadprofile=1):\n    pyarmor_init()\n    prototype = PYFUNCTYPE(c_int, c_int, c_int, c_int, c_int)\n    _init_runtime = prototype(('init_runtime', _pytransform))\n    _init_runtime(systrace, sysprofile, threadtrace, threadprofile)\n\n@dllmethod\ndef import_module(modname, filename):\n    global _import_module\n    if _import_module is None:\n        prototype = PYFUNCTYPE(py_object, c_char_p, c_char_p)\n        _import_module = prototype(('import_module', _pytransform))\n    return _import_module(modname, filename)\n_import_module = None\n\n@dllmethod\ndef exec_file(filename):\n    global _exec_file\n    if _exec_file is None:\n        prototype = PYFUNCTYPE(c_int, c_char_p)\n        _exec_file = prototype(('exec_file', _pytransform))\n    return _exec_file(filename)\n_exec_file = None\n\n@dllmethod\ndef encrypt_project_files(proname, filelist, mode=0):\n    prototype = PYFUNCTYPE(c_int, c_char_p, py_object, c_int)\n    dlfunc = prototype(('encrypt_project_files', _pytransform))\n    return dlfunc(proname, filelist, mode)\n\n@dllmethod\ndef encrypt_files(key, filelist, mode=0):\n    t_key = c_char * 32\n    prototype = PYFUNCTYPE(c_int, t_key, py_object, c_int)\n    dlfunc = prototype(('encrypt_files', _pytransform))\n    return dlfunc(t_key(*key), filelist, mode)\n\ndef generate_project_capsule(licfile):\n    prikey, pubkey, prolic = _generate_project_capsule()\n    capkey = _encode_capsule_key_file(licfile)\n    return prikey, pubkey, capkey, prolic\n\n@dllmethod\ndef _generate_project_capsule():\n    prototype = PYFUNCTYPE(py_object)\n    dlfunc = prototype(('generate_project_capsule', _pytransform))\n    return dlfunc()\n\n@dllmethod\ndef _encode_capsule_key_file(licfile):\n    prototype = PYFUNCTYPE(py_object, c_char_p, c_char_p)\n    dlfunc = prototype(('encode_capsule_key_file', _pytransform))\n    return dlfunc(licfile, None)\n\n@dllmethod\ndef generate_module_key(pubname, key):\n    t_key = c_char * 32\n    prototype = PYFUNCTYPE(py_object, c_char_p, t_key, c_char_p)\n    dlfunc = prototype(('generate_module_key', _pytransform))\n    return dlfunc(pubname, t_key(*key), None)\n\n@dllmethod\ndef generate_license_file(filename, priname, rcode, start=-1, count=1):\n    prototype = PYFUNCTYPE(c_int, c_char_p, c_char_p, c_char_p, c_int, c_int)\n    dlfunc = prototype(('generate_project_license_files', _pytransform))\n    return dlfunc(filename, priname, rcode, start, count)\n\n@dllmethod\ndef get_registration_code():\n    prototype = PYFUNCTYPE(py_object)\n    dlfunc = prototype(('get_registration_code', _pytransform))\n    return dlfunc()\n\n@dllmethod\ndef get_expired_days():\n    prototype = PYFUNCTYPE(py_object)\n    dlfunc = prototype(('get_expired_days', _pytransform))\n    return dlfunc()\n\n@dllmethod\ndef get_trial_days():\n    prototype = PYFUNCTYPE(py_object)\n    dlfunc = prototype(('get_trial_days', _pytransform))\n    return dlfunc()\n\n@dllmethod\ndef version_info():\n    prototype = PYFUNCTYPE(py_object)\n    dlfunc = prototype(('version_info', _pytransform))\n    return dlfunc()\n\ndef get_hd_sn():\n    size = 256\n    t_sn = c_char * size\n    sn = t_sn()\n    if (_pytransform.get_hd_sn(sn, size) == -1):\n        return ''\n    return sn.value.decode()\n\ndef show_hd_info():\n    return _pytransform.show_hd_info()\n\ndef get_license_info():\n    info = {\n        'expired': 'Never',\n        'restrict_mode': 'Enabled',\n        'HARDDISK': 'Any',\n        'IFMAC': 'Any',\n        'IFIPV4': 'Any',\n        'DOMAIN': 'Any',\n        'CODE': '',\n    }\n    rcode = get_registration_code().decode()\n    index = 0\n    if rcode.startswith('*TIME:'):\n        from time import ctime\n        index = rcode.find('\\n')\n        info['expired'] = ctime(float(rcode[6:index]))\n        index += 1\n\n    if rcode[index:].startswith('*FLAGS:'):\n        info['restrict_mode'] = 'Disabled'\n        index += len('*FLAGS:') + 1\n\n    prev = None\n    start = index\n    for k in ['HARDDISK', 'IFMAC', 'IFIPV4', 'DOMAIN', 'FIXKEY', 'CODE']:\n        index = rcode.find('*%s:' % k)\n        if index > -1:\n            if prev is not None:\n                info[prev] = rcode[start:index]\n            prev = k\n            start = index + len(k) + 2\n    info['CODE'] = rcode[start:]\n\n    return info\n\n# Load _pytransform library\ndef _load_library(path=None):\n    if path is None:\n        path = os.path.dirname(__file__)\n    plat = platform.system().lower()\n    bitness = struct.calcsize('P'.encode()) * 8\n    libpath = os.path.join(path, 'platforms', '%s%s' % (plat, bitness))\n    if not os.path.isdir(libpath):\n        libpath = path\n    try:\n        if plat == 'linux':\n            if libpath == '':\n                m = cdll.LoadLibrary(os.path.abspath('_pytransform.so'))\n            else:\n                m = cdll.LoadLibrary(os.path.join(libpath, '_pytransform.so'))\n            m.set_option('libc'.encode(), find_library('c').encode())\n        elif plat == 'darwin':\n            m = cdll.LoadLibrary(os.path.join(libpath, '_pytransform.dylib'))\n        elif plat == 'windows':\n            m = cdll.LoadLibrary(os.path.join(libpath, '_pytransform.dll'))\n        elif plat == 'freebsd':\n            m = cdll.LoadLibrary(os.path.join(libpath, '_pytransform.so'))\n        else:\n            raise RuntimeError('Platform not supported')\n    except Exception:\n        raise PytransformError('Could not load _pytransform from \"%s\"', libpath)\n\n    # Required from Python3.6\n    m.set_option('byteorder'.encode(), sys.byteorder.encode())\n\n    # m.set_option('enable_trace_log'.encode(), c_char_p(1))\n\n    # # Deprecated from v3.4\n    # m.set_option('enable_encrypt_generator'.encode(), c_char_p(1))\n    # # Deprecated from v3.4\n    # m.set_option('disable_obfmode_encrypt'.encode(), c_char_p(1))\n\n    if not os.path.abspath('.') == os.path.abspath(path):\n        m.set_option('pyshield_path'.encode(), path.encode())\n    return m\n\ndef pyarmor_init(path=None):\n    global _pytransform\n    global _get_error_msg\n    if _pytransform is None:\n        _pytransform = _load_library(path)\n        _get_error_msg = _pytransform.get_error_msg\n        _get_error_msg.restype = c_char_p\n        init_pytransform()\n\ndef pyarmor_runtime(path=None):\n    pyarmor_init(path)\n    init_runtime(0, 0, 0, 0)\n"
  },
  {
    "path": "agent/fix_rule_no_att/agent.py",
    "content": "#! /usr/bin/env python\n# -*- coding: utf-8 -*-\nfrom pytransform import pyarmor_runtime\npyarmor_runtime()\n\"\"\"\n   Copyright 2018 Information Science Academy of China Electronics Technology Group Corporation\n\n   Licensed under the Apache License, Version 2.0 (the \"License\");\n   you may not use this file except in compliance with the License.\n   You may obtain a copy of the License at\n\n     http://www.apache.org/licenses/LICENSE-2.0\n\n   Unless required by applicable law or agreed to in writing, software\n   distributed under the License is distributed on an \"AS IS\" BASIS,\n   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n   See the License for the specific language governing permissions and\n   limitations under the License.\n\n@author: Gao Fang\n@contact: gaofang@cetc.com.cn\n@software: PyCharm\n@file: agent.py\n@time: 2018/3/13 0013 10:51\n@desc: rule based agent without attack ability\n\"\"\"\n\nfrom agent.fix_rule_no_att.agent_core import Agent as ag\n\n\nclass Agent:\n    def __init__(self):\n        \"\"\"\n        Init this agent\n        \"\"\"\n        self.agent_core = ag()\n\n    def set_map_info(self, size_x, size_y, detector_num, fighter_num):\n\n        return self.agent_core.set_map_info(size_x, size_y, detector_num, fighter_num)\n\n    def get_action(self, obs_dict, step_cnt):\n        \"\"\"\n        get actions\n        :param detector_obs_list:\n        :param fighter_obs_list:\n        :param joint_obs_dict:\n        :param step_cnt:\n        :return:\n        \"\"\"\n        return self.agent_core.get_action(obs_dict, step_cnt)\n\n    def get_obs_ind(self):\n        return self.agent_core.get_obs_ind()\n"
  },
  {
    "path": "agent/fix_rule_no_att/agent_core.py",
    "content": "__pyarmor__(__name__, __file__, b'\\xe7\\x50\\x8c\\x64\\x26\\x42\\xd6\\x01\\xb9\\x4e\\x3f\\xdf\\x40\\x99\\x74\\xef\\xb8\\xc9\\x91\\x76\\x3b\\x40\\xaa\\xbe\\x5d\\xc5\\xbd\\x32\\x0b\\xf3\\x42\\x40\\xe3\\xce\\x4f\\x75\\x5d\\x9f\\x4c\\x04\\x35\\x6e\\xf5\\xb9\\xdb\\xfc\\x44\\xa8\\x11\\xd0\\xdb\\xb1\\x0f\\x62\\xe2\\x75\\xc1\\x38\\x66\\x9c\\x65\\x70\\xe1\\x0d\\x2b\\x57\\x65\\xd2\\x85\\x6d\\x0e\\x9d\\xb5\\x16\\x6d\\x19\\x4c\\x08\\x05\\x50\\xe0\\xd6\\x28\\xd8\\xe5\\x1b\\x68\\xb7\\x96\\xd4\\x21\\x0e\\x87\\x99\\x7d\\xc0\\x18\\x75\\xb0\\x67\\x5d\\x77\\xba\\xb0\\xc6\\xdf\\x31\\x69\\x39\\x6e\\xca\\xf0\\x57\\xec\\xb8\\x3a\\xce\\x56\\xaf\\x00\\xa6\\x55\\x5c\\x7e\\xa5\\x9a\\xdd\\x2a\\xa9\\x02\\x64\\x01\\xd9\\x77\\x1a\\x29\\xd9\\x74\\xcf\\x5b\\x91\\xc7\\x0b\\xda\\xe7\\xdc\\x65\\x49\\x7c\\x95\\x35\\x85\\x75\\x0c\\x31\\x79\\x1a\\x0e\\xc3\\x17\\x86\\x4d\\xf0\\x69\\x33\\x2f\\x58\\x15\\x05\\x13\\x7b\\xd9\\x9a\\x22\\x0d\\xce\\x35\\xad\\x50\\x98\\xfc\\x5d\\x92\\x7c\\xbc\\x4f\\x9c\\xe5\\xf1\\xb5\\x08\\x7f\\x61\\x2d\\x11\\x4f\\xc9\\x21\\xd5\\x96\\x7b\\x1b\\x22\\xeb\\xe5\\xd8\\x44\\x2f\\x35\\xa9\\x76\\x77\\xaf\\x82\\xd0\\xe9\\x4f\\x19\\xe5\\xe5\\x90\\x97\\x8e\\x68\\xfa\\x23\\x61\\xcc\\xf0\\x2f\\x4b\\x7a\\xc4\\x67\\x87\\x47\\xd3\\xf3\\xf1\\x87\\x98\\xb9\\xcd\\xea\\xe2\\x86\\x45\\x25\\xda\\xfb\\xad\\x72\\x5f\\x64\\x27\\x02\\xb5\\x28\\xd5\\x5e\\xeb\\x85\\x6c\\xcb\\xed\\xc7\\x1c\\xbb\\x0d\\x53\\x03\\xe1\\x53\\x57\\x81\\x56\\x6b\\x46\\x8d\\x6a\\x78\\xc6\\x28\\xcb\\x0f\\x12\\x6f\\x0b\\x0f\\xda\\x71\\x55\\x4d\\x6d\\x91\\x15\\x10\\x20\\x55\\x95\\xca\\x9d\\xb5\\x26\\xda\\x64\\xfa\\xb5\\x4e\\x11\\xb2\\x03\\xaf\\x3f\\x38\\x0c\\x0a\\x56\\x47\\x51\\x1f\\x89\\x1a\\x9f\\xbc\\x42\\x90\\x52\\x98\\xc4\\x5f\\x0e\\x54\\xeb\\x6c\\xa9\\x11\\x85\\x6e\\x19\\x59\\xae\\x91\\xcd\\x33\\x99\\xc6\\x0b\\x53\\x56\\xd9\\x72\\xfe\\x0b\\x1a\\xa7\\xd5\\xd8\\xcc\\x01\\x7b\\x78\\x38\\x8b\\x49\\xd1\\x0a\\xb9\\xda\\xe7\\xbb\\x9d\\x0f\\xc9\\xdd\\xda\\x5b\\xc5\\x89\\x36\\x5d\\x70\\x09\\x63\\x35\\xc0\\x3f\\xf5\\x77\\xbe\\x32\\xa2\\xcf\\x8e\\xc6\\xfc\\x62\\xf8\\xe3\\x63\\xad\\x47\\x59\\x99\\xf7\\x27\\x5d\\x7a\\x56\\x33\\xa2\\xb9\\x64\\xde\\x6b\\xeb\\xe8\\x04\\x40\\x14\\x2b\\xac\\x68\\x55\\x62\\xcc\\x48\\x36\\x58\\xad\\xb4\\x23\\xc2\\xfa\\x26\\xac\\x49\\xee\\xca\\xcc\\xdf\\x25\\x4e\\x99\\xc9\\x83\\x31\\x58\\x5e\\xfe\\x30\\xef\\x4b\\x78\\xb2\\x38\\x13\\x67\\x43\\x69\\xb0\\x75\\xb3\\x1b\\xe6\\x32\\xbd\\x42\\xc0\\x5b\\x7b\\x0e\\x16\\xc3\\xfe\\xb2\\x23\\xeb\\xdd\\x78\\xa0\\xde\\x25\\xf8\\x4d\\x43\\xc9\\xc8\\xa9\\x13\\x5c\\x50\\x53\\xb9\\x2d\\xc6\\x67\\x91\\x42\\x8e\\x24\\xde\\xfe\\x8c\\x5e\\x0a\\x2a\\x21\\xab\\xe2\\xcc\\x46\\xea\\x7d\\x40\\x6e\\x83\\xeb\\xb4\\x7b\\xe0\\x01\\x37\\x5b\\x37\\x05\\xde\\x71\\xf2\\x13\\x13\\x9c\\x25\\x23\\x62\\xa8\\x27\\x3f\\x13\\x4d\\x65\\xf8\\x03\\x33\\xbb\\xac\\xc6\\x56\\x5b\\x98\\x1b\\xc5\\xac\\xda\\x3f\\xbe\\x25\\xb8\\xc9\\xe9\\x13\\xb3\\x29\\x3c\\x84\\x52\\x47\\x74\\xe2\\x4d\\x50\\x73\\xfc\\xc1\\xa3\\x7e\\xe1\\x5e\\xdb\\x70\\xce\\xb0\\x56\\xe8\\xc0\\x0d\\x40\\x50\\xf2\\x60\\x26\\x92\\xf8\\x2c\\x4a\\xe5\\xb8\\xf2\\xfb\\x28\\x84\\x26\\xb0\\x4a\\xc4\\xf4\\xa3\\xd1\\xc0\\x37\\xa1\\xfa\\x5a\\x90\\x20\\xea\\x23\\xe9\\xf5\\xc5\\xf3\\xd5\\x27\\xe6\\x1f\\xab\\xee\\x90\\xa5\\x26\\x11\\x84\\x5e\\x1b\\x37\\x98\\x6e\\x89\\x09\\xa3\\x49\\xc8\\xdb\\x4c\\x7e\\x79\\x8f\\x00\\x8a\\x09\\x80\\xb4\\x5b\\xb4\\x87\\xef\\xbb\\x87\\x99\\x6f\\x85\\xc0\\xfc\\x24\\xff\\xe6\\xfc\\xc1\\x4b\\x78\\x2e\\x45\\x7b\\xe8\\x4c\\x96\\x52\\x1b\\xdb\\x38\\x80\\x64\\xca\\x35\\x4b\\x0b\\x0c\\xe1\\xfb\\x3f\\x05\\x3e\\xac\\xe7\\x86\\x44\\x22\\xa2\\x14\\x36\\x60\\x36\\x9a\\x8e\\xe7\\x83\\xaa\\xb1\\x4f\\xac\\x54\\x61\\xb9\\xcc\\x4c\\x01\\x70\\x79\\x7b\\x2a\\x6c\\xd8\\xfd\\xf9\\xfd\\x33\\x49\\x39\\x13\\x2b\\xa2\\xe2\\x98\\x29\\x8e\\xe6\\x00\\xe2\\x20\\xa6\\x7b\\x6e\\x16\\x14\\x00\\x61\\x5c\\xbf\\xb4\\x23\\x79\\xda\\x3a\\x6e\\x72\\xf7\\x33\\x83\\x3a\\x6e\\xf2\\x0a\\x3d\\xa0\\x7a\\x8b\\xaa\\x49\\x40\\xbe\\x38\\xeb\\xe7\\xae\\x8a\\x12\\xad\\x08\\x69\\x1b\\x42\\x78\\x4c\\x81\\x7e\\x23\\x3e\\xc3\\xff\\x3a\\x33\\xa1\\x48\\x14\\xe7\\xd2\\x63\\xb6\\xa9\\xff\\x29\\x34\\x0a\\xd9\\x1c\\x21\\x32\\xb9\\x36\\x72\\x5d\\x8c\\x59\\xc1\\x75\\xb9\\x4a\\xf9\\x51\\xf1\\x47\\x8a\\x05\\x4d\\xe5\\xca\\x63\\xce\\xe2\\x2f\\x0e\\xa7\\x96\\x02\\x1d\\x90\\x6a\\x11\\x07\\x98\\x97\\x2e\\xcc\\x00\\x87\\x6c\\xf4\\x0c\\x87\\x87\\x77\\xac\\xa9\\x8f\\xb2\\x2c\\x51\\x8f\\xc1\\x31\\x6f\\x1f\\xb0\\xe0\\xfd\\x4c\\xcc\\xc8\\xa6\\x36\\xd1\\x4d\\x42\\x90\\x6d\\x95\\x4a\\x73\\x1b\\x82\\x72\\xb1\\xc4\\x37\\xac\\xae\\xf7\\x6f\\x76\\xa3\\x58\\xe5\\xf2\\x9c\\xfd\\x51\\xc8\\x5d\\x7c\\x3e\\x10\\x79\\xcd\\x27\\x3b\\xa0\\x95\\x02\\x5e\\x91\\xcf\\x53\\x55\\x5d\\x24\\x0f\\x0a\\xaa\\x4d\\x58\\x3c\\x90\\xc4\\xfd\\x31\\xb0\\xda\\xc2\\x62\\xe0\\x87\\x8a\\x0f\\xa9\\x5b\\x3d\\x1b\\x46\\xef\\x14\\x9a\\xc0\\x53\\x92\\x09\\x0a\\x99\\x2e\\x5e\\xd8\\x29\\xe8\\x7c\\xde\\x17\\x71\\x7e\\xf7\\xd0\\xdd\\xb9\\x74\\x1d\\xd1\\xf9\\x20\\xc9\\x82\\xa6\\x73\\x70\\xf1\\xbf\\x33\\x59\\x0b\\x18\\x39\\xc7\\xa8\\xb4\\x55\\x7c\\x1f\\x54\\xa6\\x0f\\x0d\\xb8\\x6b\\x01\\x06\\xbb\\x93\\xfb\\xc9\\xaa\\xc2\\x61\\x1e\\x64\\xc2\\x92\\x9e\\xf9\\x48\\xa4\\x2b\\x62\\xe5\\x58\\x9d\\x5b\\x4f\\xf6\\x20\\xab\\x03\\x2b\\x9b\\x22\\x49\\x61\\x9a\\x9a\\x7d\\x3d\\x04\\x4f\\x58\\xee\\x07\\x7a\\xba\\xf5\\x32\\x28\\x47\\xab\\x99\\xd1\\x47\\x88\\x36\\x76\\xbd\\xa2\\xd5\\xdc\\xda\\x93\\x2f\\x2a\\xac\\x15\\x55\\xff\\x90\\x8c\\xf7\\xdc\\xf3\\xff\\x4a\\x28\\xef\\x0e\\x10\\xe9\\xc0\\x13\\x70\\xa3\\xb9\\xef\\x33\\x00\\xb8\\x10\\x27\\x35\\x89\\xd5\\x53\\xc5\\x8a\\x65\\xb8\\x56\\x44\\xb1\\x33\\x1e\\xce\\xe8\\xa9\\x7d\\x9f\\x87\\x35\\x61\\x72\\x9c\\x2f\\x2a\\x65\\x2a\\x9d\\xad\\x44\\x3a\\x20\\xa2\\x53\\x8f\\xd6\\x9f\\x8a\\xab\\xd4\\x3c\\xc5\\xe8\\x58\\xff\\xe5\\x37\\xb2\\xcb\\x5c\\xa3\\x50\\xfc\\x71\\x6f\\x59\\x6a\\x41\\x26\\xb9\\x86\\x77\\x5b\\x65\\xf0\\x3b\\xc6\\xb2\\xca\\x63\\x10\\x67\\xb3\\x54\\x6c\\x5d\\x77\\x8b\\x17\\xfd\\x34\\xc1\\x48\\xa9\\x04\\xc9\\xeb\\x08\\xf6\\xe0\\xe4\\x0f\\xd8\\xb6\\x47\\xe7\\xe5\\x5a\\x0f\\xc5\\x86\\xaf\\xa8\\xde\\x49\\x72\\xc8\\x9e\\x74\\x97\\x32\\xd0\\x1d\\x18\\xb8\\x41\\xc6\\x34\\x15\\x15\\x9b\\xd2\\x37\\xb8\\xa0\\xe4\\x3e\\x92\\x44\\xb7\\xea\\xb8\\xb0\\x06\\x7a\\xe8\\x18\\x9d\\x94\\xc5\\xf0\\x19\\xd3\\x8f\\xa4\\xb0\\x8d\\x87\\x31\\x31\\x9f\\xa5\\x85\\x24\\x1b\\x99\\xe2\\x7b\\x31\\xba\\x3a\\x63\\x6a\\xf4\\xc8\\xcb\\x7e\\x01\\x05\\x93\\x00\\xcb\\x61\\x42\\x33\\xa4\\x6c\\x89\\x37\\xf6\\x8e\\x8a\\xf2\\x72\\xee\\x9c\\xd6\\xdb\\x58\\x88\\x16\\xf2\\x6f\\x5e\\x2b\\x89\\x57\\x53\\x2c\\x4f\\xf8\\x85\\x23\\xd2\\x88\\xdf\\x33\\x34\\x12\\x49\\x3c\\x20\\xf9\\xa4\\xf4\\x4d\\x2b\\xa5\\x33\\x50\\xf5\\x5e\\x19\\xd6\\x71\\x11\\x66\\x0c\\x3a\\x9c\\xed\\x7b\\xe7\\xe1\\xdc\\xc5\\x53\\xb1\\xdb\\xbf\\x1b\\xf2\\xc8\\xa5\\x4f\\x41\\x3d\\x79\\x88\\x71\\x2a\\x08\\xb4\\xca\\xd9\\x22\\xab\\xf9\\xfd\\x59\\xbb\\x51\\x28\\x9a\\xf9\\x03\\xa7\\xfb\\xf7\\xdb\\x91\\x11\\x4a\\x58\\xa6\\xe5\\xb6\\x4a\\xd6\\xd9\\xf4\\x2f\\xae\\xdd\\xf3\\x53\\x6f\\xe0\\x3d\\xa3\\x48\\x4d\\x96\\xdb\\x9b\\xfe\\x76\\x23\\xd3\\xac\\xe4\\x4e\\x1c\\x90\\xb8\\x54\\x5e\\xea\\x90\\xb8\\xc7\\xad\\x43\\x00\\x9d\\xe4\\x1d\\x6d\\x3d\\xb5\\x7d\\xf6\\xc7\\xc5\\xe5\\x82\\xb1\\xa0\\x97\\xc0\\x96\\x5f\\x39\\x70\\x20\\x11\\xc8\\x73\\x97\\x1a\\x8e\\x06\\x44\\xd1\\x5a\\x02\\x3f\\x92\\x86\\x26\\x1f\\xff\\x69\\x89\\xc6\\x5a\\x34\\x47\\x9c\\xf9\\xd0\\xdc\\x6c\\xe7\\x6a\\x47\\x1b\\x3e\\x79\\xbb\\x57\\xbe\\x5b\\x3a\\x22\\x43\\x1d\\x29\\xe8\\x56\\x23\\x33\\x2e\\xd6\\x3c\\xb1\\xa5\\x16\\xc3\\x68\\x44\\x2d\\xfd\\x40\\xd3\\x44\\x0b\\x09\\xa1\\x06\\x5d\\x06\\x8a\\xea\\x4d\\xc0\\xe5\\x02\\xc1\\xf1\\x21\\xe4\\x4d\\xd1\\x0f\\x1d\\xc1\\x82\\xcb\\xdf\\x87\\x62\\xf4\\xfe\\x64\\xa5\\xcc\\x1c\\xb6\\x23\\x94\\x74\\xaa\\x49\\x61\\x8f\\x9f\\x5f\\x9c\\x28\\xb5\\x57\\x2c\\x34\\xf3\\x62\\x47\\x51\\xad\\xed\\xd6\\x67\\x34\\x2a\\x44\\x88\\xde\\xce\\x19\\x8c\\xc2\\x02\\x2d\\x7f\\x2a\\x76\\xb6\\x9d\\xb6\\x33\\x77\\xb5\\x88\\x1c\\x8f\\xa9\\x4b\\xc3\\x35\\xe9\\xc8\\x10\\x69\\xfd\\x13\\x19\\x54\\x82\\xfe\\xd1\\x83\\x47\\x5e\\xb4\\xa3\\x14\\xfc\\xcb\\xfe\\xcd\\x01\\xa8\\x67\\x37\\x50\\x64\\x43\\x0f\\x0c\\x4e\\x69\\xf3\\x48\\x02\\xf8\\xcd\\xec\\x3c\\x34\\x01\\xa6\\x30\\x36\\xf5\\x05\\xc9\\x4f\\x23\\x1e\\x05\\xea\\x3d\\x2a\\x55\\xd6\\xbc\\xe9\\xff\\x37\\x77\\xa0\\x3b\\xb4\\x2d\\x37\\x02\\x8b\\xd2\\x56\\xaa\\xd9\\xea\\x3b\\xd5\\x32\\xf1\\x1e\\x7a\\x9b\\x49\\x1b\\x2b\\xf2\\x03\\xcb\\x3a\\xbf\\x4b\\x50\\x01\\x6f\\xff\\x40\\x08\\x20\\xe9\\x3e\\x45\\xd4\\xa2\\xb0\\xd0\\x98\\x2c\\xb4\\x7e\\xd0\\x22\\xfa\\x5b\\x98\\xd7\\x67\\x90\\xa3\\xfb\\x74\\x7c\\x2f\\xea\\xe4\\x06\\x6e\\xb0\\xbb\\x9f\\x6e\\x54\\x66\\x2c\\xd3\\x69\\xac\\xb3\\xd7\\x71\\xa8\\x5d\\xfa\\x51\\x33\\x64\\x98\\x51\\xf5\\x52\\xd9\\xcf\\xe7\\xc2\\x41\\xde\\xc3\\x5c\\xf1\\x5c\\x26\\x37\\x8f\\xeb\\xba\\x7e\\x07\\xe0\\x08\\xb6\\x6f\\x9a\\x89\\x97\\x1f\\xd4\\x77\\x8a\\x71\\x69\\x08\\xd2\\xd6\\xbd\\x61\\xe8\\x69\\x57\\x84\\x54\\x13\\xdf\\x05\\x3f\\x62\\x61\\x25\\xf2\\x1a\\x76\\x31\\x38\\x51\\xd3\\x33\\xdc\\x08\\x12\\x56\\xb1\\x36\\x5d\\x9c\\xcc\\x35\\xd7\\x4c\\xc2\\x52\\x57\\x80\\xbd\\x19\\xe6\\x98\\x60\\x16\\xb1\\xd9\\x28\\x03\\x47\\xb6\\xa8\\x6c\\x9c\\xab\\xf5\\x6d\\x41\\x36\\x18\\x90\\xe8\\x56\\x1b\\x23\\x92\\xba\\x2c\\x11\\x3e\\x9d\\x26\\x0b\\x99\\xce\\x0b\\x65\\x63\\xb8\\xba\\x92\\xf6\\x1e\\xbf\\xd4\\xdd\\x2b\\x52\\x7a\\x34\\x41\\x59\\xa9\\x48\\x98\\x79\\xe3\\xf0\\xd1\\xdd\\x0b\\x10\\x03\\x5f\\x76\\x8d\\x09\\xf8\\xc3\\x64\\x76\\x82\\xd6\\x2d\\xd9\\xfc\\x9d\\x4a\\x29\\xa9\\xf0\\xd4\\xb6\\xd0\\xab\\x78\\xf4\\xc7\\x64\\x7d\\xd0\\x6d\\xba\\x3a\\xb1\\xe5\\xac\\xea\\x95\\x9d\\x9f\\x8f\\x36\\x20\\x1d\\x78\\x0d\\x7e\\x97\\xca\\xaf\\x8c\\x1d\\xb2\\x33\\xde\\x52\\xd2\\xf7\\xf6\\xf3\\xed\\x97\\x88\\xc8\\xb6\\x81\\xca\\xb9\\x55\\x3e\\x7f\\x93\\xca\\xe5\\x71\\x9c\\x97\\x9e\\x2c\\xfa\\xed\\x98\\x18\\xb0\\x2e\\xf6\\x4e\\xec\\x9d\\xac\\xe1\\x15\\xd5\\x70\\xb2\\x7f\\xe0\\xc8\\x5a\\x4e\\xb2\\x3c\\x39\\xd8\\x93\\x4a\\x36\\xca\\x0a\\x20\\x18\\x11\\xab\\x76\\x3a\\xcf\\x00\\x79\\x0a\\xe0\\xf9\\x73\\xbf\\x5c\\xd7\\xf1\\xda\\xa3\\x55\\x21\\xfb\\x58\\x61\\xcc\\xd0\\x32\\x11\\x4f\\xb0\\x7a\\x3c\\xab\\xbb\\x3b\\x49\\xff\\xe1\\x3b\\x21\\x51\\x16\\xa1\\xe6\\x65\\x9e\\x7b\\xc6\\x09\\xb2\\xf9\\xdf\\x78\\xe6\\x00\\x86\\xbe\\xda\\x60\\xbc\\x82\\x9c\\xe8\\x03\\xc6\\x79\\xf3\\x47\\x3b\\x36\\xec\\xcf\\xf6\\x0c\\xeb\\x85\\x14\\x6d\\x20\\x8a\\x5d\\x1a\\x63\\xb9\\x4f\\x56\\x19\\x46\\xd5\\xf9\\x42\\x6a\\x89\\x4c\\xbe\\x91\\x9d\\xf3\\x83\\x6d\\x02\\xee\\x2c\\xe3\\x49\\x50\\xa2\\xbe\\x77\\xf3\\x64\\x43\\x1f\\xdc\\x67\\x89\\x28\\x96\\x2a\\x0a\\x6a\\x23\\x77\\x44\\xfd\\x2f\\x6e\\xe0\\x05\\xca\\x3d\\x39\\xfb\\x9e\\x98\\xd8\\xee\\x7c\\xf5\\xf7\\xf3\\x34\\x84\\x7b\\xb9\\xf8\\xac\\x57\\x41\\x57\\x16\\x8b\\x0b\\x56\\x15\\x2b\\xad\\x4f\\xc3\\xb9\\xce\\x7b\\x31\\x6c\\xca\\xad\\xf9\\x08\\x1b\\x5e\\xa5\\x4d\\xcd\\x16\\xbb\\x85\\x87\\x20\\xce\\xa9\\x42\\xd4\\x7f\\x2b\\x4b\\xd8\\x9c\\xef\\x9a\\x87\\xb5\\xf9\\x0d\\xf0\\xdb\\xc0\\x43\\xa1\\x7e\\x1c\\x8e\\xe2\\x01\\xea\\x28\\xda\\xd3\\x6e\\xcb\\x9b\\x5d\\x6d\\xde\\x56\\x21\\x37\\x8e\\x7b\\x8a\\x4a\\x7d\\x1e\\x2f\\x1a\\xf0\\x77\\x62\\xaa\\xc4\\x34\\x57\\xc8\\xdc\\xdc\\xa3\\x4e\\xb4\\x97\\x40\\x22\\xfb\\x2c\\x9e\\x0c\\x58\\xfb\\x98\\xbb\\x08\\x46\\xea\\x05\\x2f\\x26\\xcf\\x3d\\xf9\\xfa\\xc2\\x9a\\xed\\xf9\\xfd\\xc5\\x4c\\x95\\xe9\\xc2\\xd1\\x5b\\x00\\x6e\\xd3\\xc0\\xdd\\xed\\xcf\\x53\\xcb\\x06\\x54\\x13\\x24\\x5b\\x62\\xcc\\x71\\xe4\\x69\\xf5\\x9b\\x8f\\x7f\\xd3\\x3a\\xf3\\x86\\x89\\x7a\\x6f\\x68\\x4e\\x37\\x6d\\x6b\\xee\\x2d\\x91\\x2e\\xd9\\xf7\\x2d\\x7b\\x23\\x64\\x36\\xfd\\x40\\x9f\\x6e\\xf3\\xdf\\x55\\x86\\x57\\xd1\\x9e\\x92\\x8b\\x15\\xf1\\xa2\\xb1\\x12\\x4d\\xe4\\xe1\\x02\\xa3\\x70\\xd1\\xf6\\x45\\x2b\\xdc\\x72\\x9f\\x69\\x19\\xb8\\xff\\x1b\\x55\\x27\\xe7\\x66\\x1b\\xa7\\x48\\xac\\x23\\x3e\\xe4\\x03\\x29\\x89\\x0f\\x33\\x2d\\xab\\x9e\\x2a\\x66\\xb0\\xf3\\x22\\x4a\\xbc\\x59\\x76\\x42\\xf9\\x2e\\x41\\x02\\x56\\x2a\\xbe\\xfe\\x25\\x63\\x4a\\xcb\\xed\\x80\\x5b\\x80\\xfd\\xd0\\xfc\\x3d\\xf7\\xa4\\x48\\xa4\\x89\\x51\\xf2\\xbd\\x6e\\x8b\\x9b\\xe2\\xd5\\xe3\\x14\\xef\\x98\\xa1\\x01\\x72\\x57\\xbb\\xe4\\x71\\x22\\x97\\xd0\\x99\\x0b\\x8e\\x51\\x5c\\x6b\\xfd\\xeb\\x0f\\x9d\\x55\\x4e\\x33\\xde\\x24\\x80\\x35\\x68\\x67\\x44\\x8d\\x17\\xc7\\xec\\xb3\\x7a\\xe9\\x4d\\x53\\x6e\\x83\\x1e\\x8d\\xc3\\x3b\\x29\\x4a\\x34\\xb0\\xca\\xea\\xbe\\x10\\xe7\\x6d\\x07\\xaa\\xf8\\xf8\\x43\\x0a\\x93\\x0a\\xfb\\xde\\x9e\\x9a\\xd4\\x2b\\x35\\xaa\\x7c\\x54\\x19\\x4a\\xde\\xc3\\xd7\\x76\\x59\\xc1\\x04\\xad\\xdb\\x51\\x6d\\x47\\x12\\x62\\xe9\\xee\\xd6\\x86\\x5e\\x52\\x1a\\xa2\\xcb\\x88\\xfd\\x96\\xdf\\xbf\\x54\\xc0\\x32\\x70\\x3a\\x80\\x76\\x5c\\xb5\\x29\\x26\\xc8\\x61\\xe3\\x6b\\xed\\x31\\xb4\\x33\\x78\\x23\\x68\\xbf\\xad\\x45\\x5b\\x98\\x43\\xbd\\x93\\x25\\xd7\\x43\\x79\\x08\\x5d\\xaf\\x92\\x28\\x25\\x62\\xe9\\x63\\x8f\\x78\\x6f\\xfc\\xb0\\xfa\\x64\\x8e\\x9e\\xf6\\x06\\xb6\\xd4\\xa5\\xcc\\x97\\x53\\xba\\x62\\xf0\\x41\\x06\\xc0\\xf2\\x42\\x45\\x86\\x25\\xa8\\x5c\\xb1\\xae\\x13\\x77\\xde\\x13\\xf4\\x30\\x5a\\x38\\xfd\\x98\\xe7\\x56\\x28\\x5c\\x61\\x56\\x1d\\x50\\xbd\\xd4\\x4a\\xe3\\xaa\\xeb\\xce\\xda\\xc4\\xc7\\xe7\\xb1\\x46\\x94\\x2c\\x51\\x66\\x99\\x8a\\xdc\\xc1\\x1e\\xc3\\xeb\\xf4\\xe1\\xfa\\x65\\x3d\\x23\\x0c\\xd2\\x37\\xdb\\x93\\x7a\\xa1\\x65\\xc5\\x17\\x56\\xc3\\x8e\\x84\\x4b\\x1c\\x6a\\x85\\x83\\x77\\x6d\\x4a\\xe3\\x39\\x93\\x0a\\xce\\x69\\xbf\\x64\\x41\\xfa\\xf4\\xbf\\x2b\\x92\\x9c\\xe0\\x8a\\xab\\xab\\x7c\\x0f\\xdc\\xf6\\x36\\xe7\\xaa\\xbb\\x11\\x41\\x6e\\xfb\\x80\\x1d\\xb8\\x39\\xa4\\xea\\x69\\x38\\xc9\\x7e\\xe1\\xcc\\xa0\\x1a\\xd5\\xbf\\x04\\x65\\xde\\x1c\\x06\\x26\\x8b\\xfa\\x82\\xe4\\xb0\\x5e\\x47\\x53\\x6d\\xe8\\xc5\\x25\\xde\\xb8\\x6f\\x07\\x4d\\x21\\xc7\\x64\\xb7\\x57\\xd2\\xfd\\x7b\\xf0\\xc1\\x35\\x59\\xbe\\xa1\\x5b\\xcd\\xcf\\xed\\xac\\x88\\x0e\\x69\\xf5\\xaa\\x13\\x88\\x08\\xac\\x1d\\x3a\\xd5\\x69\\x4c\\x22\\x78\\xe9\\x3a\\x11\\x8e\\x2c\\x9c\\x2d\\xae\\x9c\\xed\\xb1\\x55\\xe8\\x14\\x69\\x44\\xe1\\x93\\x25\\x81\\x5f\\xe4\\x1e\\x93\\xa9\\x7f\\x38\\xad\\xe5\\xb5\\x62\\x28\\xa7\\x82\\xf3\\x77\\x44\\xe3\\x41\\xd9\\x91\\x59\\x10\\xac\\xe7\\xf3\\xbc\\xd3\\xe4\\x61\\xcd\\xa7\\xb6\\xfc\\x60\\x69\\xf0\\x89\\x8e\\x86\\x48\\x68\\xc2\\x72\\x9b\\xbc\\xfc\\x17\\x53\\xad\\x40\\x90\\x30\\xce\\x8f\\xe3\\x88\\xea\\x16\\x6b\\xbd\\xd8\\xdc\\x08\\xe6\\x37\\xe1\\x04\\x29\\xb6\\x2a\\xa9\\xe5\\x88\\xa1\\x5b\\x09\\x2e\\x07\\x64\\x48\\xc8\\x35\\x32\\x07\\x64\\x7f\\x87\\x2c\\x45\\x46\\xa1\\x96\\xa2\\x3c\\x8a\\xcf\\x2c\\xb9\\x2a\\x83\\x16\\x87\\x94\\x9b\\xc1\\x38\\x3a\\x9b\\x1c\\x17\\xfa\\x34\\x3a\\x94\\x47\\x93\\x3e\\x0f\\x08\\xac\\xb6\\x64\\x6a\\x82\\xa6\\x75\\x0f\\xda\\x44\\xcf\\xaa\\x24\\x34\\xa6\\xd7\\x95\\x67\\x62\\x19\\xb1\\x4d\\x9a\\xdb\\x8c\\xfd\\x87\\xca\\xf9\\x63\\x8f\\x32\\x97\\xb1\\xe1\\x96\\x88\\x25\\xab\\xf9\\x7b\\x24\\x46\\x0f\\xe8\\x8c\\x95\\x84\\x0d\\x64\\x66\\xb1\\x4f\\x31\\xe6\\xc0\\x5f\\x43\\x5a\\x30\\x5e\\x2c\\xb1\\xc8\\x72\\x8c\\x29\\xc7\\xa4\\x74\\x41\\x95\\xd5\\xad\\x3b\\x50\\x28\\x75\\xe7\\x70\\x5e\\xd8\\x61\\x4f\\xff\\x05\\x77\\x01\\x1f\\x31\\xe9\\x53\\xfb\\x1c\\x6e\\xcc\\x18\\xdc\\x7b\\x03\\x8c\\x29\\x03\\x55\\xa1\\x24\\xbc\\x80\\x3e\\xa0\\xb6\\xa8\\x0d\\xd2\\x7f\\x20\\x3f\\x19\\x3e\\x09\\xdc\\x19\\x01\\xa4\\x4a\\xe6\\x07\\x8e\\x5e\\xaa\\xdf\\x05\\x2a\\xe0\\xc7\\x56\\xb9\\x55\\x00\\x85\\x9a\\x21\\x8d\\xb7\\x5a\\x14\\x08\\x0e\\xf0\\x4b\\xaa\\xf9\\x8a\\x57\\x77\\x2d\\x4a\\x7c\\x1c\\x02\\x27\\x3a\\xd5\\x15\\x89\\xb6\\x11\\x47\\x9d\\x62\\x88\\xeb\\x97\\x7f\\x54\\xa4\\xe6\\x3f\\x3b\\xa4\\x37\\x61\\xef\\x97\\xd7\\x05\\x63\\xb4\\xc3\\xb4\\x72\\xae\\x35\\x24\\x52\\x23\\x6c\\xcf\\xc8\\x57\\x17\\xf4\\xbc\\x20\\xde\\x43\\x74\\x8b\\x2c\\x41\\xf2\\x68\\x74\\x64\\xbe\\x9c\\x64\\xe1\\x93\\x48\\x5c\\x65\\xd7\\x7e\\x07\\x46\\xd0\\xce\\xfc\\xf9\\x2d\\xf4\\x03\\x80\\xbc\\xe8\\x41\\x44\\x97\\xed\\x72\\x13\\x09\\xd6\\x70\\x84\\x23\\xe7\\x1c\\x44\\x28\\x56\\x7c\\x2e\\xb6\\xdc\\x68\\xe3\\x4f\\x15\\x4c\\xa1\\x66\\x03\\x72\\xa0\\x6f\\xb0\\x34\\x50\\xba\\x16\\x33\\xef\\xed\\x79\\x70\\xea\\x20\\x1e\\xad\\x7b\\x33\\x98\\x4b\\xd4\\x18\\x40\\xdb\\x13\\x7b\\xdf\\x43\\x0a\\x52\\xaa\\xae\\x00\\x64\\xa5\\x04\\xe6\\xbc\\x70\\x8e\\xf1\\xd2\\xbb\\x50\\x1c\\x1e\\x1d\\x4b\\xdc\\x6c\\x68\\x66\\x0f\\x3c\\x5a\\xa2\\x75\\x92\\xb3\\x94\\xc9\\x22\\xfb\\x58\\x17\\xf6\\x69\\x28\\xed\\x6e\\x99\\xab\\x4c\\x74\\x6e\\x22\\x1e\\xf0\\x2a\\x40\\x4a\\xe9\\x8f\\xd8\\xfa\\x90\\xca\\x90\\xcf\\x1b\\xe2\\x82\\xd4\\x93\\x18\\x58\\xdc\\x4e\\xb5\\x12\\x78\\xed\\xf0\\xd1\\x6b\\x0d\\xd7\\x7d\\xd1\\x78\\x53\\xcb\\x29\\x21\\x40\\xa4\\x2a\\xcc\\x72\\x65\\x43\\x6a\\xf5\\x5e\\x7d\\xd2\\xa2\\xcd\\x7e\\xa7\\x9f\\xae\\x44\\x43\\x1b\\xbf\\x2e\\x10\\x94\\x4b\\xf5\\xca\\x47\\xb3\\x82\\xef\\x1c\\xb3\\x28\\x1a\\xcd\\x45\\x13\\x4a\\x58\\x10\\x2f\\x4e\\x62\\x1e\\x3d\\xcf\\xc9\\x13\\x43\\x0c\\xdb\\x0b\\x8c\\x44\\x9e\\xdb\\x54\\x50\\x26\\xb1\\x87\\x6c\\x68\\x46\\x73\\xa2\\xb3\\xf7\\x99\\xf7\\xa5\\x01\\x3b\\x13\\xe2\\x5a\\xe4\\xa3\\x6b\\x3d\\xd8\\x13\\xb3\\xa9\\x73\\xc8\\x2e\\xf0\\xe4\\xd2\\x75\\x83\\xa6\\xc3\\xfd\\xd6\\x15\\xde\\x6b\\x93\\xda\\x4e\\x88\\xd8\\x8a\\xa8\\x5c\\xbe\\x45\\xcc\\x8d\\x54\\xcb\\xa3\\x0d\\x9b\\x89\\x5f\\x53\\xd7\\xb2\\x5c\\x6a\\xb3\\x04\\x51\\x5e\\x9a\\x52\\xab\\xa4\\x02\\x1f\\x18\\xca\\x1b\\x6e\\x38\\x62\\x1b\\xbb\\x65\\x6b\\xf3\\xf9\\x0b\\x6d\\xa4\\x8e\\x23\\x1b\\xd9\\xe1\\xf7\\xcb\\x44\\x55\\xb5\\xa7\\xb0\\xed\\x1e\\x68\\x84\\x1d\\x69\\x38\\x31\\x27\\x94\\x59\\x72\\x4f\\xeb\\x2b\\x4b\\x88\\xea\\x26\\x62\\x5f\\x6b\\x2d\\x93\\x6d\\xd9\\xca\\xbe\\xa7\\x27\\xc4\\x8a\\xba\\xfd\\xd4\\x58\\xe0\\x51\\x1f\\x76\\xda\\x95\\x53\\x3e\\xf5\\x58\\xea\\xd3\\x8c\\x1a\\x9e\\x5f\\xc1\\xf7\\x49\\xd6\\x1e\\x56\\x2e\\xe1\\x2a\\x4a\\x83\\xa6\\x64\\x52\\x0b\\x1e\\xd3\\xe3\\x98\\xee\\x32\\x07\\x49\\x68\\xc9\\x6d\\xc9\\x06\\x4b\\xe8\\xb6\\x1d\\xc7\\x38\\x22\\xec\\x65\\x3b\\x43\\xfc\\xef\\x79\\xc8\\x9b\\x80\\xb1\\x33\\x7d\\x94\\x34\\xbc\\xeb\\x03\\x8b\\xf4\\x98\\x52\\x3d\\x8b\\x02\\xf1\\xf6\\x23\\x75\\x6a\\xb6\\xec\\x8f\\x73\\xd3\\x71\\x86\\xf6\\xa7\\x3b\\x86\\xd5\\x02\\xa1\\x75\\xfd\\x7c\\x9c\\x11\\xe4\\xab\\xb4\\xd6\\xbb\\xc5\\xe4\\xdc\\x85\\xec\\x6b\\xed\\x25\\xff\\xec\\xa9\\x54\\xd9\\xe4\\xa8\\x5f\\xd7\\x00\\x7f\\xc0\\xbe\\xdb\\x4b\\x66\\x0c\\x0e\\x78\\xbd\\xa5\\x69\\x6b\\x17\\x62\\xc3\\x2f\\x58\\x08\\x27\\x8d\\x7e\\xaa\\x0e\\x6d\\xe9\\xc7\\xa4\\xc0\\xf6\\x95\\x0a\\xe2\\x4a\\x17\\xba\\x70\\x9c\\x69\\xa6\\xf8\\xb0\\x07\\xcc\\xa7\\xb6\\x3c\\x4e\\x02\\xff\\xc6\\xb8\\x15\\x52\\xfa\\x19\\x06\\x14\\x9a\\x50\\x50\\x52\\x37\\xe4\\xa2\\x5c\\x25\\xf4\\x5d\\x01\\xb8\\xf0\\xee\\x7d\\xe5\\x37\\xcc\\xac\\xd8\\x12\\x92\\x1e\\x78\\x69\\x45\\xc2\\xd5\\x43\\xfa\\xd3\\xd6\\x64\\x81\\x60\\x60\\x5f\\xe6\\x4f\\xc9\\xe0\\x5f\\x5a\\xbd\\x07\\xa0\\xb9\\x22\\x89\\x21\\x0b\\x3c\\x75\\xcc\\xa9\\x49\\x63\\x09\\x83\\xf2\\xe3\\x4f\\x9c\\x29\\x85\\x66\\xd2\\xd9\\x50\\x82\\x15\\xe7\\x59\\x23\\x46\\xa5\\xdc\\x3b\\xaa\\x35\\x37\\xb3\\x9f\\x3c\\x7f\\x91\\xb4\\x52\\x4a\\xa1\\xa8\\xf6\\xc4\\xa8\\x93\\xa1\\x8b\\xc9\\x9a\\x8b\\x71\\xfd\\x42\\x7c\\xbb\\x98\\xe6\\xa5\\xad\\x76\\xb0\\x31\\x06\\xa0\\x5a\\x21\\xf0\\x00\\x1d\\x5c\\xd7\\x05\\xe4\\xc0\\x1b\\x62\\x94\\xaa\\x94\\x66\\x7a\\x06\\x5c\\x5e\\x02\\x7d\\x91\\x1d\\xe2\\xc8\\xb2\\x7f\\x8f\\xf2\\xb0\\xcb\\x2f\\xb5\\x3a\\x6c\\xed\\x98\\x36\\x00\\x0b\\x69\\x61\\xe4\\x2d\\x7a\\x3f\\xde\\x7e\\x90\\x84\\x17\\x49\\x88\\x7e\\xbe\\x94\\xdc\\x13\\x3f\\xaf\\x82\\xec\\x70\\x5d\\x3a\\xd1\\xf6\\x6a\\xd4\\x61\\xc4\\x66\\x5d\\xaf\\xc7\\xfc\\xe1\\x37\\x9d\\xe5\\x5b\\xea\\xdf\\xe7\\x66\\xfe\\xd2\\x25\\x86\\xdb\\xfb\\xa9\\xe2\\xe4\\x17\\x36\\x42\\xa6\\x72\\x89\\x92\\xfb\\x03\\x01\\xe1\\xef\\x62\\x06\\xfe\\x0c\\xa5\\x79\\xd9\\x88\\x4c\\x28\\x9b\\xbf\\x97\\x48\\xc5\\x04\\xac\\xce\\x47\\xc0\\x54\\x22\\xda\\xcc\\x90\\xa6\\x11\\x86\\xd6\\x50\\x39\\xaa\\x94\\x3f\\x66\\xf6\\x98\\xd4\\xe0\\x46\\xf6\\x27\\x72\\x14\\x1f\\xbe\\x8f\\x24\\xde\\xcf\\x81\\x88\\x1e\\x19\\x45\\x00\\x63\\xc2\\xf8\\x76\\x43\\x1c\\xf9\\x8a\\xa4\\xc6\\xa5\\x47\\x00\\x0f\\xd1\\x2a\\x07\\x42\\xa2\\xfb\\xa2\\xad\\x69\\xfd\\x27\\x39\\xa1\\xfc\\xec\\xcc\\x1e\\x24\\x7e\\x15\\xc0\\xe1\\x7e\\x73\\x80\\x73\\x8c\\x39\\x95\\x9c\\xad\\xc0\\x4c\\xac\\x99\\x0b\\x11\\x38\\xa4\\x17\\x9b\\xf4\\x63\\xcf\\x9f\\x41\\xdd\\x89\\x0a\\xbc\\x10\\xd0\\x4e\\x6f\\x2e\\xc8\\xbc\\x3b\\x75\\x65\\x33\\xa0\\xbc\\x97\\x78\\x2f\\x63\\x59\\xd6\\x15\\x64\\x97\\x57\\x18\\xad\\x0f\\x11\\x34\\x3e\\x06\\xef\\x97\\xf0\\x4d\\xec\\x53\\x60\\x0d\\xea\\x43\\x20\\xd7\\xce\\xd6\\x60\\x94\\x80\\xbc\\xe9\\x15\\x5a\\x20\\xbb\\x85\\xe6\\x62\\xe6\\xb5\\x98\\x05\\x35\\xe4\\xc6\\xed\\x5a\\x0d\\xb4\\xd4\\x97\\x9e\\x02\\x24\\x30\\x94\\x87\\xad\\xf1\\xac\\x5e\\x18\\x4c\\x0a\\x77\\x5b\\xf7\\xb5\\x0a\\xf0\\xa3\\xfe\\x18\\xfe\\x07\\x6d\\x11\\x79\\x26\\x10\\x7f\\x1e\\x63\\x84\\x71\\x7b\\xc9\\xc2\\x36\\xf6\\xcc\\x93\\x24\\xe2\\x3e\\x26\\xb6\\x55\\xda\\xa4\\xf1\\xb4\\x21\\x38\\x60\\x8f\\x80\\x9c\\x64\\x23\\xdc\\xf8\\xaa\\x9f\\x01\\x39\\xce\\x94\\xad\\x42\\x31\\x9d\\xa6\\x12\\x2d\\xba\\x66\\x00\\x1c\\xe2\\x8e\\xbf\\xc4\\x1c\\x4b\\xa8\\x0d\\x74\\x63\\x1a\\xd3\\x08\\x76\\xe9\\x4f\\x23\\x91\\x2d\\xb4\\xb4\\x77\\xaa\\xae\\x55\\xd6\\xb6\\x64\\x68\\x96\\xb9\\xcb\\x43\\x85\\x7e\\x71\\x2d\\x14\\x59\\x13\\xa5\\xca\\xf0\\xad\\x56\\x04\\x5f\\x99\\x6e\\x63\\x1f\\x5b\\x34\\xf9\\xd0\\x38\\x47\\x79\\x15\\x5a\\xb3\\x59\\x45\\x5f\\x0e\\xfd\\xde\\x8b\\x0f\\x2f\\x88\\xd8\\xeb\\x16\\xd0\\xaf\\xa3\\x6a\\x67\\x0a\\x47\\x6c\\x81\\x02\\x5b\\xc1\\x15\\xde\\x7d\\xc4\\x99\\xf2\\x6e\\x2d\\xfc\\x11\\x8b\\x13\\x38\\xbe\\xdf\\x50\\xdd\\xe0\\x44\\x35\\xbd\\x25\\x62\\xaf\\x87\\xb5\\x47\\x1e\\x95\\x1b\\xff\\x1e\\xa0\\x91\\x99\\x13\\xf0\\x1e\\x34\\xc7\\xdf\\x48\\xe7\\x16\\x1d\\xbf\\xed\\x31\\x4c\\x77\\x76\\xb6\\xf5\\xa7\\x56\\x61\\xe5\\xa1\\xe8\\x15\\xbf\\xdd\\x9e\\x91\\x6c\\xf6\\x07\\x82\\x06\\xd1\\x35\\x25\\x57\\x8b\\xf4\\xaf\\xef\\x3e\\xb3\\x31\\x57\\x04\\xe4\\xf5\\x67\\x36\\xba\\x81\\xcd\\x0a\\x8d\\x0a\\xe4\\xb9\\xdf\\x0b\\x84\\x2c\\x42\\x39\\xfa\\xec\\x37\\x6f\\xa0\\x5e\\x0e\\x83\\xee\\xe2\\x17\\x5e\\xb4\\x17\\x23\\x0b\\xc7\\x6a\\x48\\x4d\\x0b\\x04\\xf0\\xbe\\xf7\\x6f\\xa3\\x16\\x8e\\xe6\\x0b\\x87\\x18\\x5e\\x70\\x75\\xad\\xc0\\xc5\\xe7\\x3d\\x89\\xc8\\xd0\\xcd\\xfd\\xf4\\x3e\\xa9\\xeb\\x68\\xb5\\x04\\x30\\x7b\\x8a\\x2e\\xa3\\x11\\x1b\\x53\\x8f\\xb2\\x19\\x0a\\x54\\x55\\xda\\xbb\\xec\\x7a\\x85\\xff\\xac\\x60\\xa4\\x65\\x26\\xbf\\x8e\\x48\\xd7\\x36\\x72\\x2d\\xcb\\xb2\\x3f\\x18\\x1e\\xe9\\x5e\\xfc\\x60\\x5c\\x5e\\x98\\x2f\\xee\\x9a\\xa7\\x91\\xe8\\xcd\\x21\\xad\\x85\\xea\\xd4\\x3b\\x8e\\xb2\\xb5\\x60\\xd1\\x23\\x62\\xbc\\x2e\\xe1\\xfd\\x6e\\x74\\x84\\x84\\x73\\xca\\x64\\x68\\x85\\x16\\xbb\\x13\\xe2\\x4d\\x33\\xae\\x79\\x29\\x3e\\xbc\\xa7\\x9c\\x21\\xce\\xdf\\x6c\\xb4\\x24\\x13\\xc1\\x82\\xcc\\xfd\\x38\\x1c\\x85\\x6d\\x03\\x87\\x9a\\x7b\\x3c\\x57\\x0f\\x18\\xbe\\xf8\\xfb\\xd0\\xa7\\x9b\\xbb\\x55\\x7e\\xaf\\xc3\\x7f\\xfa\\x50\\x87\\x9a\\x60\\xc7\\x57\\x60\\x26\\x14\\x4d\\xe7\\x7c\\x51\\x23\\xfa\\x4c\\x5d\\x4d\\x6d\\xf2\\xbd\\xfd\\xfe\\x34\\x9d\\xba\\x8f\\xde\\x71\\x99\\x27\\x61\\x80\\x57\\x33\\xde\\xce\\xfb\\xe9\\x5f\\x92\\xba\\xb5\\xad\\x40\\xd4\\x70\\x8d\\xb5\\x04\\xea\\x22\\xfb\\x5b\\x98\\x2b\\x66\\x5c\\xa4\\x8e\\x7f\\x16\\xfe\\x90\\x29\\xa9\\xce\\x73\\xdd\\x14\\x23\\x25\\x46\\xf2\\xbd\\x11\\x2f\\x6d\\x9a\\x24\\xfe\\x6d\\x09\\x02\\x96\\x86\\x4e\\x99\\x4c\\x8c\\xdf\\xeb\\xe9\\x10\\x55\\x0d\\xad\\x94\\xe8\\x18\\xc3\\x41\\x22\\xa9\\xcf\\xf5\\x9c\\xb9\\x08\\xcf\\xf0\\x24\\x2a\\x2a\\x4b\\x8e\\xb0\\x8b\\x8c\\x71\\x38\\x30\\x6a\\x84\\x14\\x60\\x73\\x90\\x20\\x0c\\x63\\xae\\x80\\x4a\\x6f\\xef\\x2d\\xcd\\x5e\\xe4\\x79\\x81\\x40\\x4b\\x2c\\x70\\xe4\\x76\\xfe\\xe0\\x74\\x61\\x71\\x72\\xed\\xd4\\xeb\\x15\\x77\\x8a\\x5d\\xca\\x8e\\x30\\x54\\xf8\\x67\\xcf\\xe1\\x60\\x5a\\x7d\\x71\\x4c\\xa3\\xde\\xd5\\x5a\\x7d\\xc0\\x02\\x79\\xbe\\x1c\\x6e\\xe2\\x0a\\x10\\xb1\\xf3\\x8a\\xe4\\x8a\\xaa\\xce\\x13\\xc2\\xb9\\xb5\\xa1\\x67\\x6b\\x8e\\xae\\x3f\\xa6\\x6d\\x52\\x0e\\xed\\x50\\x93\\x2f\\x7b\\x81\\x84\\x04\\x6a\\x7d\\x15\\xd2\\xf7\\xeb\\xf6\\xfd\\xad\\x69\\x57\\x16\\x17\\xaf\\x74\\x9b\\x0b\\x78\\xa1\\x8d\\x3f\\x0e\\x28\\xf8\\x4b\\x08\\x08\\xa9\\x3f\\x05\\x1d\\xec\\xc8\\x88\\xfc\\xa9\\x56\\xaa\\x81\\x51\\x11\\x4c\\x45\\x89\\xe6\\x3a\\xd3\\x78\\xc2\\xad\\xb2\\xfc\\xd0\\x7a\\xf0\\xa9\\x3a\\xb5\\x34\\x5b\\xf0\\x12\\x31\\x91\\xba\\xa0\\xac\\x23\\x6d\\x34\\xc4\\x91\\xf1\\xec\\x57\\x39\\xba\\x92\\x31\\x5b\\xfb\\xe5\\x87\\x9f\\xa9\\xed\\x98\\x2d\\x86\\x6b\\xc3\\xee\\x01\\x90\\x9b\\xbd\\xe2\\xf1\\x79\\x12\\x16\\x90\\xe6\\x4d\\x16\\x6b\\x8e\\xd8\\x66\\xf1\\x0c\\xa0\\x53\\xb9\\x7c\\xc6\\xd2\\x1f\\x7a\\xff\\xe5\\xc4\\x0c\\x64\\x5f\\xe0\\x3e\\x6e\\x26\\xac\\xe8\\x2a\\x08\\x88\\x6c\\x9e\\x39\\xaf\\x70\\xf8\\x80\\xbf\\x3e\\xb8\\x64\\xb0\\xc9\\x40\\x7a\\x7c\\xa4\\xaa\\xc3\\xf3\\xfc\\xfd\\x96\\x69\\x3e\\xdb\\xec\\x56\\x11\\x11\\x41\\xd0\\x53\\x0e\\xf3\\xfe\\x93\\xba\\x5c\\x44\\x49\\xaf\\x60\\xa2\\xb3\\x93\\x40\\xd6\\x95\\x7b\\x74\\x92\\x98\\x69\\x7f\\xfe\\x62\\x9e\\x6b\\x23\\xd3\\x10\\xab\\x3b\\x76\\xc3\\xd3\\xf0\\x42\\x3c\\xfe\\xcf\\x18\\x3a\\x05\\x42\\x15\\xb1\\x8d\\x2c\\x8a\\x7d\\x4f\\x31\\x77\\x14\\xcd\\x5b\\xe5\\xb7\\x99\\xff\\x61\\xdf\\xf5\\x1d\\x1d\\xde\\x55\\x1b\\xd9\\x35\\xf5\\xde\\xd2\\xb2\\xa1\\xb0\\x1d\\xd7\\xa3\\xd9\\x96\\xd9\\x66\\xbb\\xc0\\x04\\x1b\\x00\\x3d\\x77\\x3b\\x01\\x21\\x75\\xfd\\x93\\x59\\xe8\\xba\\x4e\\x11\\x07\\x3b\\xd8\\xe6\\x3d\\x6d\\x59\\xc3\\x20\\xf7\\xfb\\xdb\\xa0\\x90\\x41\\x61\\x66\\xf1\\x15\\x3f\\x9e\\xcc\\x58\\x32\\x89\\xd5\\x60\\x9d\\xc2\\xf5\\xcc\\xdc\\x69\\xec\\xc2\\x3d\\xa4\\x03\\x05\\x34\\xab\\x4a\\x20\\xd9\\x5c\\x6e\\xe7\\x49\\xe3\\xf5\\x04\\x81\\x63\\x28\\x30\\x32\\x8d\\xd8\\x59\\xff\\x97\\xfe\\x33\\xbe\\x13\\xd9\\x9e\\x75\\x57\\x29\\x29\\xf1\\x06\\x53\\xc8\\x38\\x0e\\x3f\\x0c\\xd8\\x83\\x66\\x38\\xd2\\x5d\\x7a\\x29\\xea\\x53\\xba\\x33\\x39\\x75\\xf4\\xaa\\x1a\\x6f\\xca\\x18\\x89\\xfc\\x7a\\xb6\\x80\\xfc\\xa1\\x03\\x58\\x8b\\xe5\\x86\\xa2\\x15\\x8f\\xd1\\x4e\\x5e\\xf8\\x9d\\x10\\xe6\\x34\\x27\\xcb\\xb8\\xcc\\xd5\\x88\\x5c\\xad\\xaf\\x19\\x45\\x47\\xb3\\x54\\x90\\xcb\\xa8\\x68\\xd8\\xb9\\x2d\\xd8\\x02\\x34\\x12\\xe4\\xe7\\x82\\x6b\\x23\\xe2\\xcf\\xb9\\xfe\\x76\\x25\\x6e\\xb4\\x52\\x99\\x9d\\xba\\x98\\xec\\x0b\\xc2\\x83\\x7b\\x47\\x8d\\x0b\\x0b\\x01\\x7c\\xce\\x2d\\xf4\\x80\\x57\\xeb\\xb7\\x56\\xe0\\x0a\\x52\\xfd\\xf4\\x2f\\xb9\\x50\\xfc\\x5c\\x78\\xd3\\x64\\x45\\x69\\xc2\\xc7\\x75\\xf2\\x03\\x27\\xc4\\x52\\xd1\\xa7\\x68\\xc0\\xb4\\xc0\\x25\\x46\\x97\\x57\\x7e\\xde\\xaa\\x7f\\x33\\xfd\\xc7\\xbd\\x7c\\x36\\xc6\\xe3\\x32\\x1e\\x73\\x2b\\x0f\\x8e\\x21\\x12\\x8f\\x64\\x17\\x16\\xa7\\x1a\\x74\\x7a\\xbe\\x30\\x6c\\x58\\x6e\\xbe\\x92\\x80\\x6e\\x46\\x28\\xd1\\x81\\x30\\x9c\\x59\\x50\\x0a\\x91\\x19\\x43\\x29\\x12\\xb2\\x89\\x62\\xf3\\x60\\x4a\\xcf\\xe5\\x61\\x60\\x27\\x18\\xed\\x49\\x7d\\x32\\x05\\x57\\x9d\\xe6\\x4a\\xa6\\xd7\\x2a\\x86\\x04\\xf1\\x82\\x53\\x32\\x32\\x8b\\xf6\\x2e\\x2a\\xf7\\x7e\\xde\\xe2\\xea\\x34\\xb4\\x84\\xe1\\xcb\\xee\\xef\\xa5\\xd6\\x0c\\x50\\x9a\\x5d\\x40\\x94\\x8e\\x62\\x90\\x81\\x38\\x39\\xaf\\xa3\\xb9\\x41\\x73\\x1e\\xec\\xf5\\xef\\xbc\\x43\\xfc\\xca\\xae\\x1b\\x04\\x60\\xd4\\x1d\\xed\\x79\\x47\\x06\\xec\\x86\\x12\\x20\\x33\\xb4\\xb1\\x24\\x34\\x61\\x5d\\x48\\x5b\\x57\\x53\\xb3\\xc3\\x9f\\x37\\xdf\\x28\\xac\\x4e\\x55\\xe4\\x60\\x2f\\xec\\xe6\\xf6\\x55\\x72\\xd4\\x01\\x22\\xdb\\xfe\\x48\\xc0\\x3d\\x5a\\x4b', 1)"
  },
  {
    "path": "agent/fix_rule_no_att/license.lic",
    "content": "HSpGTEFHUzoBKkNPREU6UHlhcm1vci1Qcm9qZWN0egMhJ6NNlQdmKa/iVehg0LovCYkZYgMtBOQo6jHlP0slLc0iYjbS9NAnZQslmFBVRWO6JERZBMANwGUlKeAdkFUMv/8JT6WquK7BFnlYcPnuhV6z5zP2O/hWCaJzDGRL4pWU7A1javZizykc2gPVHAnWW1cvuMMbeNlS2tMSCeo="
  },
  {
    "path": "agent/fix_rule_no_att/product.key",
    "content": "Bې?CA\u0016k8a\u0011\u00136W\fH0vY\ry\n\u001e\r}\u001f\u0005q\u0001#fRq+JBwzʱnƐS*T\u0011E`wN(\u0005RGy0t\u001dD\u001c&y\u001d\nP:C\u001fq\\8SBV]"
  },
  {
    "path": "agent/fix_rule_no_att/pytransform.py",
    "content": "# Because ctypes is new from Python 2.5, so pytransform doesn't work\n# before Python 2.5\n#\nfrom ctypes import cdll, c_char, c_char_p, c_int, c_void_p, \\\n                   pythonapi, py_object, PYFUNCTYPE\nfrom ctypes.util import find_library\n\nimport os\nimport sys\nimport platform\nimport struct\n\n#\n# Global\n#\n_pytransform = None\n_get_error_msg = None\n\n#\n# Options\n#\n\n# How to show error message return from dynamic library _pytransform.\n#\n# Each time call a dll function, if something is wrong, _get_error_msg\n# will return the reason.\n#\n# Enable _verbose_mode will print the details got from _get_error_msg.\n# Disable this options will print only a short message.\n_verbose_mode = 1\n\n# In debug mode, print trace stack when raise exception.\n# Otherwise only show a short message.\n#\n# Run python with command option \"-d\", or set environment variable\n# PYTHONDEBUG. For example\n#\n#   python -d pyarmor.py xxxx\n#\n_debug_mode = sys.flags.debug\n\nclass PytransformError(Exception):\n    def __init__(self, *args, **kwargs):\n        super(Exception, self).__init__(*args, **kwargs)\n        if _debug_mode:\n            self._print_stack()\n\n    @classmethod\n    def _print_stack(self):\n        try:\n            from traceback import print_stack\n        except Exception:\n            _debug_mode = 0\n            sys.stderr.write('Disabled debug mode.\\n')\n        else:\n            print_stack()\n\ndef dllmethod(func):\n    def format_message(msg, *args, **kwargs):\n        if _verbose_mode:\n            s1 = str(args)[:-1]\n            s2 = ', '.join(['%s=%s' % (k, repr(v)) for k, v in kwargs.items()])\n            sep = ', ' if (s1 and s2) else ''\n            line = 'Call with arguments: %s%s%s)' % (s1, sep, s2)\n            return msg\n        return msg.split('\\n')[-1]\n    def wrap(*args, **kwargs):\n        args = [(s.encode() if isinstance(s, str) else s) for s in args]\n        result = func(*args, **kwargs)\n        errmsg = _get_error_msg()\n        if errmsg:\n            raise PytransformError(format_message(errmsg, *args, **kwargs))\n        return result\n    return wrap\n\n@dllmethod\ndef init_pytransform():\n    major, minor = sys.version_info[0:2]\n    # Python2.5 no sys.maxsize but sys.maxint\n    # bitness = 64 if sys.maxsize > 2**32 else 32\n    prototype = PYFUNCTYPE(c_int, c_int, c_int, c_void_p)\n    init_module = prototype(('init_module', _pytransform))\n    init_module(major, minor, pythonapi._handle)\n\n@dllmethod\ndef init_runtime(systrace=0, sysprofile=1, threadtrace=0, threadprofile=1):\n    pyarmor_init()\n    prototype = PYFUNCTYPE(c_int, c_int, c_int, c_int, c_int)\n    _init_runtime = prototype(('init_runtime', _pytransform))\n    _init_runtime(systrace, sysprofile, threadtrace, threadprofile)\n\n@dllmethod\ndef import_module(modname, filename):\n    global _import_module\n    if _import_module is None:\n        prototype = PYFUNCTYPE(py_object, c_char_p, c_char_p)\n        _import_module = prototype(('import_module', _pytransform))\n    return _import_module(modname, filename)\n_import_module = None\n\n@dllmethod\ndef exec_file(filename):\n    global _exec_file\n    if _exec_file is None:\n        prototype = PYFUNCTYPE(c_int, c_char_p)\n        _exec_file = prototype(('exec_file', _pytransform))\n    return _exec_file(filename)\n_exec_file = None\n\n@dllmethod\ndef encrypt_project_files(proname, filelist, mode=0):\n    prototype = PYFUNCTYPE(c_int, c_char_p, py_object, c_int)\n    dlfunc = prototype(('encrypt_project_files', _pytransform))\n    return dlfunc(proname, filelist, mode)\n\n@dllmethod\ndef encrypt_files(key, filelist, mode=0):\n    t_key = c_char * 32\n    prototype = PYFUNCTYPE(c_int, t_key, py_object, c_int)\n    dlfunc = prototype(('encrypt_files', _pytransform))\n    return dlfunc(t_key(*key), filelist, mode)\n\ndef generate_project_capsule(licfile):\n    prikey, pubkey, prolic = _generate_project_capsule()\n    capkey = _encode_capsule_key_file(licfile)\n    return prikey, pubkey, capkey, prolic\n\n@dllmethod\ndef _generate_project_capsule():\n    prototype = PYFUNCTYPE(py_object)\n    dlfunc = prototype(('generate_project_capsule', _pytransform))\n    return dlfunc()\n\n@dllmethod\ndef _encode_capsule_key_file(licfile):\n    prototype = PYFUNCTYPE(py_object, c_char_p, c_char_p)\n    dlfunc = prototype(('encode_capsule_key_file', _pytransform))\n    return dlfunc(licfile, None)\n\n@dllmethod\ndef generate_module_key(pubname, key):\n    t_key = c_char * 32\n    prototype = PYFUNCTYPE(py_object, c_char_p, t_key, c_char_p)\n    dlfunc = prototype(('generate_module_key', _pytransform))\n    return dlfunc(pubname, t_key(*key), None)\n\n@dllmethod\ndef generate_license_file(filename, priname, rcode, start=-1, count=1):\n    prototype = PYFUNCTYPE(c_int, c_char_p, c_char_p, c_char_p, c_int, c_int)\n    dlfunc = prototype(('generate_project_license_files', _pytransform))\n    return dlfunc(filename, priname, rcode, start, count)\n\n@dllmethod\ndef get_registration_code():\n    prototype = PYFUNCTYPE(py_object)\n    dlfunc = prototype(('get_registration_code', _pytransform))\n    return dlfunc()\n\n@dllmethod\ndef get_expired_days():\n    prototype = PYFUNCTYPE(py_object)\n    dlfunc = prototype(('get_expired_days', _pytransform))\n    return dlfunc()\n\n@dllmethod\ndef get_trial_days():\n    prototype = PYFUNCTYPE(py_object)\n    dlfunc = prototype(('get_trial_days', _pytransform))\n    return dlfunc()\n\n@dllmethod\ndef version_info():\n    prototype = PYFUNCTYPE(py_object)\n    dlfunc = prototype(('version_info', _pytransform))\n    return dlfunc()\n\ndef get_hd_sn():\n    size = 256\n    t_sn = c_char * size\n    sn = t_sn()\n    if (_pytransform.get_hd_sn(sn, size) == -1):\n        return ''\n    return sn.value.decode()\n\ndef show_hd_info():\n    return _pytransform.show_hd_info()\n\ndef get_license_info():\n    info = {\n        'expired': 'Never',\n        'restrict_mode': 'Enabled',\n        'HARDDISK': 'Any',\n        'IFMAC': 'Any',\n        'IFIPV4': 'Any',\n        'DOMAIN': 'Any',\n        'CODE': '',\n    }\n    rcode = get_registration_code().decode()\n    index = 0\n    if rcode.startswith('*TIME:'):\n        from time import ctime\n        index = rcode.find('\\n')\n        info['expired'] = ctime(float(rcode[6:index]))\n        index += 1\n\n    if rcode[index:].startswith('*FLAGS:'):\n        info['restrict_mode'] = 'Disabled'\n        index += len('*FLAGS:') + 1\n\n    prev = None\n    start = index\n    for k in ['HARDDISK', 'IFMAC', 'IFIPV4', 'DOMAIN', 'FIXKEY', 'CODE']:\n        index = rcode.find('*%s:' % k)\n        if index > -1:\n            if prev is not None:\n                info[prev] = rcode[start:index]\n            prev = k\n            start = index + len(k) + 2\n    info['CODE'] = rcode[start:]\n\n    return info\n\n# Load _pytransform library\ndef _load_library(path=None):\n    if path is None:\n        path = os.path.dirname(__file__)\n    plat = platform.system().lower()\n    bitness = struct.calcsize('P'.encode()) * 8\n    libpath = os.path.join(path, 'platforms', '%s%s' % (plat, bitness))\n    if not os.path.isdir(libpath):\n        libpath = path\n    try:\n        if plat == 'linux':\n            if libpath == '':\n                m = cdll.LoadLibrary(os.path.abspath('_pytransform.so'))\n            else:\n                m = cdll.LoadLibrary(os.path.join(libpath, '_pytransform.so'))\n            m.set_option('libc'.encode(), find_library('c').encode())\n        elif plat == 'darwin':\n            m = cdll.LoadLibrary(os.path.join(libpath, '_pytransform.dylib'))\n        elif plat == 'windows':\n            m = cdll.LoadLibrary(os.path.join(libpath, '_pytransform.dll'))\n        elif plat == 'freebsd':\n            m = cdll.LoadLibrary(os.path.join(libpath, '_pytransform.so'))\n        else:\n            raise RuntimeError('Platform not supported')\n    except Exception:\n        raise PytransformError('Could not load _pytransform from \"%s\"', libpath)\n\n    # Required from Python3.6\n    m.set_option('byteorder'.encode(), sys.byteorder.encode())\n\n    # m.set_option('enable_trace_log'.encode(), c_char_p(1))\n\n    # # Deprecated from v3.4\n    # m.set_option('enable_encrypt_generator'.encode(), c_char_p(1))\n    # # Deprecated from v3.4\n    # m.set_option('disable_obfmode_encrypt'.encode(), c_char_p(1))\n\n    if not os.path.abspath('.') == os.path.abspath(path):\n        m.set_option('pyshield_path'.encode(), path.encode())\n    return m\n\ndef pyarmor_init(path=None):\n    global _pytransform\n    global _get_error_msg\n    if _pytransform is None:\n        _pytransform = _load_library(path)\n        _get_error_msg = _pytransform.get_error_msg\n        _get_error_msg.restype = c_char_p\n        init_pytransform()\n\ndef pyarmor_runtime(path=None):\n    pyarmor_init(path)\n    init_runtime(0, 0, 0, 0)\n"
  },
  {
    "path": "agent/simple/agent.py",
    "content": "#! /usr/bin/env python\n# -*- coding: utf-8 -*-\n\"\"\"\n@author: Gao Fang\n@contact: gaofang@cetc.com.cn\n@software: PyCharm\n@file: agent.py\n@time: 2018/3/13 0013 10:51\n@desc: rule based agent\n\"\"\"\n\nimport os\nfrom agent.base_agent import BaseAgent\nfrom agent.simple import dqn\nimport interface\nfrom world import config\nimport copy\nimport random\nimport numpy as np\n\nDETECTOR_NUM = 0\nFIGHTER_NUM = 10\nCOURSE_NUM = 16\nATTACK_IND_NUM = (DETECTOR_NUM + FIGHTER_NUM) * 2 + 1 # long missile attack + short missile attack + no attack\nACTION_NUM = COURSE_NUM * ATTACK_IND_NUM\n\n\nclass Agent(BaseAgent):\n    def __init__(self):\n        \"\"\"\n        Init this agent\n        :param size_x: battlefield horizontal size\n        :param size_y: battlefield vertical size\n        :param detector_num: detector quantity of this side\n        :param fighter_num: fighter quantity of this side\n        \"\"\"\n        BaseAgent.__init__(self)\n        self.obs_ind = 'simple'\n        if not os.path.exists('model/simple/model.pkl'):\n            print('Error: agent simple model data not exist!')\n            exit(1)\n        self.fighter_model = dqn.RLFighter(ACTION_NUM)\n\n    def set_map_info(self, size_x, size_y, detector_num, fighter_num):\n        self.size_x = size_x\n        self.size_y = size_y\n        self.detector_num = detector_num\n        self.fighter_num = fighter_num\n\n    def __reset(self):\n        pass\n\n    def get_action(self, obs_dict, step_cnt):\n        \"\"\"\n        get actions\n        :param detector_obs_list:\n        :param fighter_obs_list:\n        :param joint_obs_dict:\n        :param step_cnt:\n        :return:\n        \"\"\"\n\n        detector_action = []\n        fighter_action = []\n        for y in range(self.fighter_num):\n            true_action = np.array([0, 1, 0, 0], dtype=np.int32)\n            if obs_dict['fighter'][y]['alive']:\n                true_action = np.array([0, 1, 0, 0], dtype=np.int32)\n                tmp_img_obs = obs_dict['fighter'][y]['screen']\n                tmp_img_obs = tmp_img_obs.transpose(2, 0, 1)\n                tmp_info_obs = obs_dict['fighter'][y]['info']\n                tmp_action = self.fighter_model.choose_action(tmp_img_obs, tmp_info_obs)\n                # action formation\n                true_action[0] = int(360 / COURSE_NUM * int(tmp_action[0] / ATTACK_IND_NUM))\n                true_action[3] = int(tmp_action[0] % ATTACK_IND_NUM)\n            fighter_action.append(copy.deepcopy(true_action))\n        fighter_action = np.array(fighter_action)\n\n        return detector_action, fighter_action\n\n\n\n"
  },
  {
    "path": "agent/simple/dqn.py",
    "content": "#! /usr/bin/env python\n# -*- coding: utf-8 -*-\n\"\"\"\n@author: Gao Fang\n@contact: gaofang@cetc.com.cn\n@software: PyCharm\n@file: dqn.py\n@time: 2018/7/25 0025 13:38\n@desc: \n\"\"\"\nimport torch\nimport torch.nn as nn\nimport numpy as np\n\n\nclass NetFighter(nn.Module):\n    def __init__(self, n_actions):\n        super(NetFighter, self).__init__()\n        self.conv1 = nn.Sequential(     # 100 * 100 * 3\n            nn.Conv2d(\n                in_channels=5,\n                out_channels=16,\n                kernel_size=5,\n                stride=1,\n                padding=2,\n            ),\n            nn.ReLU(),\n            nn.MaxPool2d(2),\n        )\n        self.conv2 = nn.Sequential(     # 50 * 50 * 16\n            nn.Conv2d(16, 32, 5, 1, 2),\n            nn.ReLU(),\n            nn.MaxPool2d(2),            # 25 * 25 * 32\n        )\n        self.info_fc = nn.Sequential(\n            nn.Linear(3, 256),\n            nn.Tanh(),\n        )\n        self.feature_fc = nn.Sequential(    # 25 * 25 * 32 + 256\n            nn.Linear((25 * 25 * 32 + 256), 512),\n            nn.ReLU(),\n        )\n        self.decision_fc = nn.Linear(512, n_actions)\n\n    def forward(self, img, info):\n        img_feature = self.conv1(img)\n        img_feature = self.conv2(img_feature)\n        info_feature = self.info_fc(info)\n        combined = torch.cat((img_feature.view(img_feature.size(0), -1), info_feature.view(info_feature.size(0), -1)),\n                             dim=1)\n        feature = self.feature_fc(combined)\n        action = self.decision_fc(feature)\n        return action\n\n# Deep Q Network off-policy\nclass RLFighter:\n    def __init__(\n            self,\n            n_actions,\n    ):\n        self.n_actions = n_actions\n        self.gpu_enable = torch.cuda.is_available()\n\n        self.target_net = NetFighter(self.n_actions)\n        if self.gpu_enable:\n            print('GPU Available!!')\n            self.target_net = self.target_net.cuda()\n            self.target_net.load_state_dict(torch.load('model/simple/model.pkl'))\n        else:\n            self.target_net.load_state_dict(torch.load('model/simple/model.pkl', map_location=lambda storage, loc: storage))\n\n    def choose_action(self, img_obs, info_obs):\n        img_obs = torch.unsqueeze(torch.FloatTensor(img_obs), 0)\n        info_obs = torch.unsqueeze(torch.FloatTensor(info_obs), 0)\n        if self.gpu_enable:\n            img_obs = img_obs.cuda()\n            info_obs = info_obs.cuda()\n        actions_value = self.target_net(img_obs, info_obs)\n        action = torch.max(actions_value, 1)[1]\n        if self.gpu_enable:\n            action = action.cpu()\n        action = action.numpy()\n        return action\n\nclass NetDetector(nn.Module):\n    def __init__(self, n_actions):\n        super(NetDetector, self).__init__()\n        self.conv1 = nn.Sequential(     # 100 * 100 * 3\n            nn.Conv2d(\n                in_channels=3,\n                out_channels=16,\n                kernel_size=5,\n                stride=1,\n                padding=2,\n            ),\n            nn.ReLU(),\n            nn.MaxPool2d(2),\n        )\n        self.conv2 = nn.Sequential(     # 50 * 50 * 16\n            nn.Conv2d(16, 32, 5, 1, 2),\n            nn.ReLU(),\n            nn.MaxPool2d(2),            # 25 * 25 * 32\n        )\n        self.info_fc = nn.Sequential(\n            nn.Linear(3, 256),\n            nn.Tanh(),\n        )\n        self.feature_fc = nn.Sequential(    # 25 * 25 * 32 + 256\n            nn.Linear((25 * 25 * 32 + 256), 512),\n            nn.ReLU(),\n        )\n        self.decision_fc = nn.Linear(512, n_actions)\n\n    def forward(self, img, info):\n        img_feature = self.conv1(img)\n        img_feature = self.conv2(img_feature)\n        info_feature = self.info_fc(info)\n        combined = torch.cat((img_feature.view(img_feature.size(0), -1), info_feature.view(info_feature.size(0), -1)),\n                             dim=1)\n        feature = self.feature_fc(combined)\n        action = self.decision_fc(feature)\n        return action\n\n"
  },
  {
    "path": "common/agent_process.py",
    "content": "#! /usr/bin/env python\n# -*- coding: utf-8 -*-\n\"\"\"\n@author: Gao Fang\n@contact: gaofang@cetc.com.cn\n@software: PyCharm\n@file: fight.py\n@time: 2019/3/12 0009 16:41\n@desc: agent sub proc\n\"\"\"\nimport importlib\nimport time\nfrom multiprocessing import Process, Queue\n\nAGENT_INIT_TIMEOUT = 60\nAGENT_RESP_TIMEOUT = 60\n\n\nclass AgentProc(Process):\n    '''\n    agent子进程\n    '''\n    def __init__(self, agent_name, size_x, size_y, detector_num, fighter_num, recv_queue, send_queue):\n        super().__init__()\n        self.agent_name = agent_name\n        self.size_x = size_x\n        self.size_y = size_y\n        self.detector_num = detector_num\n        self.fighter_num = fighter_num\n        self.recv_queue = recv_queue\n        self.send_queue = send_queue\n        self.agent = None\n        self.obs_construct = None\n        self.obs_ind = 'raw'\n\n    def run(self):\n        agent_import_path = 'agent.' + self.agent_name + '.agent'\n        agent_module = importlib.import_module(agent_import_path)\n        self.agent = agent_module.Agent()\n        self.agent.set_map_info(self.size_x, self.size_y, self.detector_num,self.fighter_num)\n        self.obs_ind = self.agent.get_obs_ind()\n        if self.obs_ind != 'raw':\n            obs_path = 'obs_construct.' + self.obs_ind + '.construct'\n            obs_module = importlib.import_module(obs_path)\n            self.obs_construct = obs_module.ObsConstruct(self.size_x, self.size_y, self.detector_num,self.fighter_num)\n        # time.sleep(5)\n        self.send_queue.put('Init OK')\n        self.__decision_proc()\n\n    def __decision_proc(self):\n        while True:\n            obs_data = self.recv_queue.get()\n            obs_raw_dict = obs_data['obs_raw_dict']\n            step_cnt = obs_data['step_cnt']\n            if self.obs_ind == 'raw':\n                obs_dict = obs_raw_dict\n            else:\n                obs_dict = self.obs_construct.obs_construct(obs_raw_dict)\n            detector_action, fighter_action = self.agent.get_action(obs_dict, step_cnt)\n            action_dict = {'detector_action': detector_action, 'fighter_action': fighter_action}\n            self.send_queue.put(action_dict)\n\n\nclass AgentCtrl:\n    '''\n    agent子进程维护\n    '''\n    def __init__(self, agent_name, size_x, size_y, detector_num, fighter_num):\n        self.agent_name = agent_name\n        self.size_x = size_x\n        self.size_y = size_y\n        self.detector_num = detector_num\n        self.fighter_num = fighter_num\n        self.send_q = None\n        self.recv_q = None\n        self.agent = None\n\n    def agent_init(self):\n        self.send_q = Queue(1)\n        self.recv_q = Queue(1)\n        self.agent = AgentProc(self.agent_name, self.size_x, self.size_y, self.detector_num, self.fighter_num,\n                               self.send_q, self.recv_q)\n        self.agent.start()\n        try:\n            agent_msg = self.recv_q.get(True, AGENT_INIT_TIMEOUT)\n        except:\n            self.terminate()\n            return False\n        else:\n            return True\n\n    def terminate(self):\n        if self.agent:\n            if self.agent.is_alive():\n                self.agent.terminate()\n        self.agent = None\n        if self.send_q:\n            self.send_q.close()\n        self.send_q = None\n        if self.recv_q:\n            self.recv_q.close()\n        self.recv_q = None\n\n    def get_action(self, obs_raw_dict, step_cnt):\n        '''\n        获得动作\n        :param obs_raw_dict: raw obs\n        :param step_cnt: step计数，从1开始\n        :return: action: 动作信息\n        :return: result: 0, 正常; 1, 崩溃; 2, 超时\n        '''\n        action = []\n        result = 0\n        self.send_q.put({'obs_raw_dict': obs_raw_dict, 'step_cnt': step_cnt})\n        try:\n            action = self.recv_q.get(True, AGENT_RESP_TIMEOUT)\n        except:\n            if not self.agent.is_alive():\n                # 子进程不存在，崩溃\n                result = 1\n            else:\n                # 子进程存在，卡死\n                result = 2\n            self.__agent_restart()\n        return action, result\n\n    def __agent_restart(self):\n        '''\n        重启agent。由于重启代表之前成功启动过，所以此处认为重启也会成功。但若重启不成功将导致程序卡死。若后续出现此类问题应重点排查此处。\n        :return:\n        '''\n        self.terminate()\n        self.send_q = Queue(1)\n        self.recv_q = Queue(1)\n        self.agent = AgentProc(self.agent_name, self.size_x, self.size_y, self.detector_num, self.fighter_num,\n                               self.send_q, self.recv_q)\n        self.agent.start()\n        self.recv_q.get()\n"
  },
  {
    "path": "configuration/reward.py",
    "content": "#! /usr/bin/env python\n# -*- coding: utf-8 -*-\n\"\"\"\n@author: Gao Fang\n@contact: gaofang@cetc.com.cn\n@software: PyCharm\n@file: reward.py\n@time: 2018/4/19 0019 14:39\n@desc: reward config\n\"\"\"\n\n\nclass GlobalVar:\n    # reward\n    # detector radar see a detector\n    reward_radar_detector_detector = 20\n    # detector radar see a fighter\n    reward_radar_detector_fighter = 10\n    # fighter radar see a detector\n    reward_radar_fighter_detector = 20\n    # fighter radar see a fighter\n    reward_radar_fighter_fighter = 10\n\n    # Missile hit a detector\n    reward_strike_detector_success = 100\n    # Missile miss a detector\n    reward_strike_detector_fail = 0\n    # Missile hit a fighter\n    reward_strike_fighter_success = 100\n    # Missile miss a fighter\n    reward_strike_fighter_fail = 0\n\n    # A detector been destroyed\n    reward_detector_destroyed = -100\n    # A fighter been destroyed\n    reward_fighter_destroyed = -100\n\n    # A valid attack action\n    reward_strike_act_valid = 10\n    # An invalid attack action\n    reward_strike_act_invalid = -10\n\n    # Keep alive in a step\n    reward_keep_alive_step = 0\n\n    # Round reward：totally win\n    reward_totally_win = 200\n    # Round reward：totally lose\n    reward_totally_lose = -200\n    # Round reward：win\n    reward_win = 100\n    # Round reward：lose\n    reward_lose = -100\n    # Round reward：draw\n    reward_draw = 0\n\n\ndef get_reward_radar_detector_detector():\n    return GlobalVar.reward_radar_detector_detector\n\n\ndef get_reward_radar_detector_fighter():\n    return GlobalVar.reward_radar_detector_fighter\n\n\ndef get_reward_radar_fighter_detector():\n    return GlobalVar.reward_radar_fighter_detector\n\n\ndef get_reward_radar_fighter_fighter():\n    return GlobalVar.reward_radar_fighter_fighter\n\n\ndef get_reward_strike_detector_success():\n    return GlobalVar.reward_strike_detector_success\n\n\ndef get_reward_strike_detector_fail():\n    return GlobalVar.reward_strike_detector_fail\n\n\ndef get_reward_strike_fighter_success():\n    return GlobalVar.reward_strike_fighter_success\n\n\ndef get_reward_strike_fighter_fail():\n    return GlobalVar.reward_strike_fighter_fail\n\n\ndef get_reward_detector_destroyed():\n    return GlobalVar.reward_detector_destroyed\n\n\ndef get_reward_fighter_destroyed():\n    return GlobalVar.reward_fighter_destroyed\n\n\ndef get_reward_strike_act_valid():\n    return GlobalVar.reward_strike_act_valid\n\n\ndef get_reward_strike_act_invalid():\n    return GlobalVar.reward_strike_act_invalid\n\n\ndef get_reward_keep_alive_step():\n    return GlobalVar.reward_keep_alive_step\n\n\ndef get_reward_win():\n    return GlobalVar.reward_win\n\n\ndef get_reward_lose():\n    return GlobalVar.reward_lose\n\n\ndef get_reward_totally_win():\n    return GlobalVar.reward_totally_win\n\n\ndef get_reward_totally_lose():\n    return GlobalVar.reward_totally_lose\n\n\ndef get_reward_draw():\n    return GlobalVar.reward_draw\n"
  },
  {
    "path": "configuration/system.py",
    "content": "#! /usr/bin/env python\n# -*- coding: utf-8 -*-\n\"\"\"\n@author: Gao Fang\n@contact: gaofang@cetc.com.cn\n@software: PyCharm\n@file: system.py\n@time: 2018/4/19 0019 14:46\n@desc: system config\n\"\"\"\n\n\nclass GlobalVar:\n    # attack effect delay\n    attack_effect_delay = True\n    # hit probability enable\n    hit_prob_enable = True\n\n\ndef get_attack_effect_delay():\n    return GlobalVar.attack_effect_delay\n\n\ndef get_hit_prob_enable():\n    return GlobalVar.hit_prob_enable\n\n"
  },
  {
    "path": "doc/tutorial.md",
    "content": "# 多智能体对抗仿真环境MaCA完全入门指南\n[TOC]\n## 1 前言\n中国电子科技集团公司认知与智能技术重点实验室发布的MaCA（Multi-agent Combat Arena）环境，是国内首个可模拟军事作战的轻量级多智能体对抗与训练平台，是多智能体对抗算法研究、训练、测试和评估的绝佳环境，可支持作战场景和规模自定义，智能体数量和种类自定义，智能体特征和属性自定义，支持智能体行为回报规则和回报值自定义等。目前发布的MaCA环境中预设了两种智能体类型，探测单元和攻击单元：探测单元可模拟L、S波段雷达进行全向探测，支持多频点切换；攻击单元具备侦察、探测、干扰、打击等功能，可模拟X波段雷达进行指向性探测，模拟L、S、X频段干扰设备进行阻塞式和瞄准式电子干扰，支持多频点切换。攻击单元还可模拟对敌方进行火力攻击，同时具有无源侦测能力，可模拟多站无源协同定位和辐射源特征识别。\nMaCA 环境为研究利用人工智能方法解决大规模多智能体分布式对抗问题提供了很好的支撑，专门面向多智能体深度强化学习开放了 RL-API 接口。环境支持使用 Python 语言进行算法实现，并支持Tensorflow、Pytorch 等常用深度学习框架的集成调用。\n\n## 2 MaCA安装\n### 2.1 系统要求\n- Linux 64-bit 、Mac OS或windows10 x64操作系统\n- Python 3.6及后续版本\n- Numpy、Pandas、Pygame软件包\n\n### 2.2 环境安装\n1. 安装支撑软件包\n```bash\npip install -U numpy pandas pygame\n```\n2. 下载环境\n```bash\ngit clone https://github.com/CETC-TFAI/MaCA.git\n```\n3. 环境配置\n- 命令行形式（适用于Linux、Mac）\n```bash\ncd MaCA\nexport PYTHONPATH=$(pwd)/environment:$PYTHONPATH\n```\n- Pycharm中配置（适用于Windows、Linux、Mac）\n\t- 在Pycharm打开MaCA\n\t- 将“[environment](/environment)”文件夹设置为“Sources Root”\n\t- 运行MaCA中任何py文件必须将其“Working Directory”设置为MaCA根目录\n\n## 3 MaCA初探\n### 3.1 运行一个对抗场景\n运行[fight_mp.py](/fight_mp.py)，即可开启一场基于预置规则的异构对抗\n```bash\npython fight_mp.py\n```\n对抗场景如下图：\n![对抗示例](https://leonfg.github.io/maca/resource/maca.gif)\n### 3.2 观看回放录像\n1. 运行对抗时增加“--log”参数，即可在log路径下生成以“红方_名称vs_蓝方名称”命名的日志文件夹，其中存储本局对抗相关信息。\n```bash\npython fight_mp.py --log\n```\n2. 默认对抗示例的日志名称为“fix_rule_vs_fix_rule”，使用replay.py即可进行日志回放：\n```bash\npython replay.py fix_rule_vs_fix_rule\n```\n## 4 MaCA详解\n### 4.1 MaCA架构简介\n![MaCA架构图](https://leonfg.github.io/maca/resource/maca_arch_cn.png)\n\nMaCA核心架构如上图所示，由推演引擎环境辅以对抗调度模块，对抗场景库（maps）构成。与外围的决策算法代码相结合，实现多智能体决策训练及对抗。主要模块功能如下：\n- 推演环境：承担核心推演功能，负责载入作战场景，对外输出原始战场状态数据（raw obs），接收双方决策算法给出的动作控制信息，执行一系列位置更新、电磁传播、攻击决策算法，实现对抗推演，同时具有现实及日志记录功能。\n- 调用接口：外部模块与推演环境的交互接口\n- 对抗调度：负责启动红蓝对抗，可对对抗多方面参数进行自定义，如双方决策程序指定、对抗局数、场景选择、每局最高持续帧数等等，同时向决策进程转发推演环境输出的状态数据，接收决策进程输出的动作信息\n- 决策进程：红蓝双方对抗控制决策以单独子进程形式存在，相互隔离，主要包括两个模块\n\t- 决策算法：智能体决策算法，接收观测数据，输出动作控制数据\n\t- 观测构建：每个决策算法对应的观测信息构建，由原始状态数据生成与决策算法需求对应的观测数据。\n\nMaCA代码结构与上述模块划分一致，具体如下图：\n\n![MaCA代码结构](https://leonfg.github.io/maca/resource/code_arch.png)\n- [environment/](/environment/)：推演环境\n\t- [interface.py](/environment/interface.py)：环境调用接口\n- [agent/](/agent/)：用于存储封装好的可直接调用的智能体决策代码，每个决策代码可单独设立一个文件夹，按照标准封装，系统直接调用\n\t- [fix_rule/](/agent/fix_rule/)：基于规则的同构异构对抗决策算法\n\t- [fix_rule_no_att/](/agent/fix_rule_no_att/)：基于规则的同构异构对抗决策算法（无攻击能力）\n\t- [simple/](/agent/simple/)：基于DQN的同构对抗决策示例算法，需使用pytorch\n- [obs_construct/](/obs_construct/)：观测值组织形式自定义，开发者可根据算法需要自定义obs结构\n\t- [simple/](/obs_construct/simple/)：基于DQN的同构对抗决策示例对应的obs组织\n- [fight_mp.py](/fight_mp.py)：对抗调度程序\n- [replay.py](/replay.py) 日志回放入口程序\n- [maps/](/maps/)：对抗场景库\n\t- [1000_1000_2_10_vs_2_10.map](/maps/1000_1000_2_10_vs_2_10.map)：预置异构对抗场景\n\t- [1000_1000_fighter10v10.map](/maps/1000_1000_fighter10v10.map)：预置同构对抗场景\n- [configuration/](/configuration/)：配置数据\n\t- [reward.py](/configuration/reward.py)：部分预置回报检查点的赋值\n\t- [system.py](/configuration/system.py)：部分系统推演规则定义\n- [train/](/train)：决策算法训练所在路径\n\t- [simple/](/train/simple/)：simple决策模型训练代码\n- [model/](/model/)：决策模型数据存储路径\n\t- [simple/](model/simple/)：simple决策模型数据存储路径\n- [common/](/common)：多模块复用代码\n\t- [agent_process.py](/common/agent_process.py)：对抗调度和比赛调度模块公用子进程管理代码\n- [log/](/log/)：对抗日志存储路径\n- [tournament/](/tournament/)：多智能体比赛调度及结果统计模块\n\t- [tournament_mp.py](/tournament/tournament_mp.py)：比赛调度程序\n\t- [config_gen.py](/tournament/config_gen.py)：比赛配置辅助生成工具\n\n### 4.2 环境调用接口说明\nMaCA环境的接口定义在[interface.py ](/environment/interface.py )文件的Environment类中，其接口函数如下：\n\n| 接口函数 | 描述 |\n|  ---- |  ---- |\n| init | 环境实例初始化 |\n| reset | 环境重置 |\n| step | 环境运行一步 |\n| get_obs | 获得组合的观测信息 |\n| get_done | 判断对抗是否结束 |\n| get_alive_status | 获取各作战单元的存活状态 |\n| get_map_size | 获取地图大小信息 |\n| get_unit_num | 获取各类别作战单元数目 |\n| get_unit_property_list | 获取各作战单元属性信息 |\n| get_reward | 获取回报 |\n\n#### 4.2.1 init\n参数：\n\n| 序号 | 参数名          | 功能                  | 存在性 | 赋值规则                                                     |\n| ---- | --------------- | --------------------- | ------ | ------------------------------------------------------------ |\n| 1 | map_path        | 地图路径              | 必选   | MaCA根目录下开始的完整地图文件路径，如“maps/1000_1000_fighter10v10.map” |\n| 2 | side1_obs_ind   | 红方使用的obs构建模块 | 必选   | 使用raw obs则赋值为“raw”，使用其他自定义obs构建则输入对应构建模块所在文件夹名 |\n| 3 | side2_obs_ind   | 蓝方使用的obs构建模块 | 必选   | 同side2_obs_ind                                              |\n| 4 | max_step        | 每局最大步长          | 可选   | 正整数值，不赋值此参数则使用默认值5000                       |\n| 5 | render          | 是否开启显示          | 可选   | True：开启显示，False：关闭显示。不使用此参数则为默认不开启  |\n| 6 | render_interval | 每隔几步显示一帧      | 可选   | 正整数值，不赋值此参数则使用默认每步都显示                   |\n| 7 | random_pos      | 是否使用随机出生位置  | 可选   | True：开启随机出生，False：关闭示。不使用此参数则为默认红方在左侧蓝方在右侧 |\n| 8 | log             | 日志记录开启指示      | 可选   | False：不开启日志，其他字符串值：日志文件夹名称。不使用此参数则默认不开启 |\n| 9 | random_seed     | 指定随机种子          | 可选   | -1：不指定随机种子，其他正整数：指定随机种子。不使用此参数则默认不指定，由环境生成。该参数主要用于回放时载入原始种子重现对抗场景，fight和train时不需考虑。 |\n\n返回值：无\n#### 4.2.2 reset\n参数：无\n返回值：无\n#### 4.2.3 step\n参数：\n\n| 序号 | 参数名                | 功能                   | 存在性 | 赋值规则  |\n| ---- | --------------------- | ---------------------- | ------ | --------- |\n| 1 | side1_detector_action | 红方探测单元动作集     | 必选   | 参见动作结构 |\n| 2 | side1_fighter_action  | 红方干扰打击单元动作集 | 必选   | 参见动作结构 |\n| 3 | side2_detector_action | 蓝方探测单元动作集     | 必选   | 参见动作结构 |\n| 4 | side2_fighter_action  | 蓝方干扰打击单元动作集 | 必选   | 参见动作结构 |\n\n#### 4.2.4 get_obs\n参数：无\n返回值：\n\n| 序号 | 返回值名  | 功能    | 数据形式                                |\n| ---- | --------- | ------- | --------------------------------------- |\n| 1 | side1_obs | 红方obs | 参见raw obs |\n| 2 | side2_obs | 蓝方obs | 同上                                    |\n\n#### 4.2.5 get_done\n参数：无\n返回值：无\n\n#### 4.2.6 get_reward\n参数：无\n返回值：\n\n| 序号 | 返回值名       | 功能                     | 数据形式  |\n| ---- | -------------- | ------------------------ | --------- |\n| 1 | side1_detector | 红方探测单元单步回报     | 整型 |\n| 2 | side1_fighter  | 红方打击干扰单元单步回报 | 整型 |\n| 3 | side1_round    | 红方本局输赢回报         | 整型 |\n| 4 | side2_detector | 蓝方探测单元单步回报     | 整型 |\n| 5 | side2_fighter  | 蓝方打击干扰单元单步回报 | 整型 |\n| 6 | side2_round    | 蓝方本局输赢回报         | 整型 |\n\n### 4.3 自定义obs信息统一接口\n为使得环境能够返回Agent对抗或训练时自定义的状态信息，自组织状态信息的接口统一放在[obs_construct/](/obs_construct/)下，如simple智能体中指定obs_ind为simple，则应在obs_construct模块下构建simple文件夹，每一个信息组织形式文件夹下必须包含construct.py文件，且该文件定义ObsConstruct类及obs_construct成员函数，成员函数接口如下：\n```python\ndef obs_construct(self, obs_raw_dict)\n# obs_raw_dict为raw信息结构\n```\n### 4.4 多智能体对抗决策程序（agent）统一接口\n为方便统一对抗调用形式，限定Agent必须包含如下成员、函数接口及固定格式的返回值。\n```python\nfrom agent.base_agent import BaseAgent\nclass Agent(BaseAgent):\n\ndef __init__(self):\t\t\t\t#初始化接口\n    BaseAgent.__init__(self)\t#从BaseAgent继承\n\tself.obs_ind = 'raw'\t\t#状态信息形式，’raw’表示原始信息形式\n\t#注：可根据原始信息自行组织新的信息,可参考simple\n\ndef set_map_info(self, size_x, size_y, detector_num, fighter_num):#读取地图信息\n    pass\t\t\t\t\t\t#根据需要自行选择函数实现形式\n\ndef get_action(self, obs_dict, step_cnt):\t#obs_dict为状态,step_cnt为当前步数(从1开始)\n\treturn detector_action, fighter_action\n```\n\n### 4.5 主要数据格式定义\n#### 4.5.1 raw obs信息结构\n环境底层原始观测数据Raw data Observation结构为字典，包含三部分内容分别为detector_obs_list、fighter_obs_list、join_obs_dict。\ndetector_obs_list表示探测单元信息，结构为detector数目的list。每一个元素为字典结构，表示当前detector的obs信息，具体内容如下：\n\n| Key            | Value                                                        |\n| -------------- | ------------------------------------------------------------ |\n| id             | 探测单元id编号,从1开始                                       |\n| alive          | 攻击单元存活状态                                             |\n| pos_x          | 横向坐标（位置坐标体系圆点为左上角，水平向右为x，垂直向下为y） |\n| pos_y          | 纵向坐标（位置坐标体系圆点为左上角，水平向右为x，垂直向下为y） |\n| course         | 航向(0-359)，水平向右为0度，顺时针旋转                       |\n| r_iswork       | 雷达开关状态                                                 |\n| r_fre_point    | 雷达频点                                                     |\n| r_visible_list | 雷达观测到的敌方单位列表，每一元素字典，表示敌方单位信息，结构为   {‘id’:编号,’type’:类型(0:探测单元，1：攻击单元) ,‘pos_x’:横向坐标,’pos_y’:纵向坐标} |\n| last_reward    | 上一个状态采用动作的回报                                     |\n| last_action    | 上一个状态采用的动作(字典结构)   {‘course’:,’r_iswork’:,’r_fre_point’:   } |\n\nfighter_obs_list表示攻击单元信息，结构为detector数目的list。每一个元素为字典结构，表示当前detector的obs信息，具体内容如下：\n\n| Key                | Value                                                        |\n| ------------------ | ------------------------------------------------------------ |\n| id                 | 攻击单元id编号,编号从探测单元数目开始                        |\n| alive              | 攻击单元存活状态                                             |\n| pos_x              | 横向坐标（位置坐标体系圆点为左上角，水平向右为x，垂直向下为y） |\n| pos_y              | 纵向坐标（位置坐标体系圆点为左上角，水平向右为x，垂直向下为y） |\n| course             | 航向(0-359)，水平向右为0度，顺时针旋转                       |\n| r_iswork           | 雷达开关状态                                                 |\n| r_fre_point        | 雷达频点                                                     |\n| r_visible_list     | 雷达观测到的敌方单位列表，每一元素字典，表示敌方单位信息，结构为   {‘id’:编号,’type’:类型(0:探测单元，1：攻击单元) ，‘pos_x’:横向坐标,’pos_y’:纵向坐标} |\n| j_iswork           | 干扰雷达开关                                                 |\n| j_fre_point        | 干扰雷达频点                                                 |\n| j_recv_list        | 雷达被动观测的敌方单位列表，每一元素字典，表示敌方单位信息，结构为   {‘id’:编号,’type’: 类型(0:探测单元，1：攻击单元) ，’direction’:目标相对自身的方向,’r_fp’:频点} |\n| l_missle_left      | 远程导弹剩余数目                                             |\n| s_missle_left      | 短程导弹剩余数目                                             |\n| striking_list      | 打击列表[{'attacker_id': 攻击者编号, 'target_id': 目标编号, 'missile_type': 导弹类型(1：远程，2：中程), information_source_type: 信息来源类型（0：L探测单元，1:S探测单元，2：战机，3：被动侦测） step_count: step计数, op_count: 观测点计数, del_ind: 删除指示(默认false)}] |\n| striking_dict_list | 攻击列表[{‘target_id’:目标编号，‘pos_x’:横向坐标,’pos_y’:纵向坐标，‘type’: 类型(0:探测单元，1：攻击单元) }] |\n| last_reward        | 上一个状态采用动作的回报                                     |\n| last_action        | 上一个状态采用的动作(字典结构)   {‘course’:,’r_iswork’:,’r_fre_point’:,’j_iswork’:,’j_fre_point’;,’hit_target’:,’missle_type’:} |\n\njoint_obs_list为表示全局信息的字典{‘strike_list’:打击列表，’passive_detection_enemy_list’:被动侦测列表}。strike_list为每一个作战单元striking_list的并集，passive_detection_enemy_list：[{‘id’:敌方编号,’type’: 类型(0:探测单元，1：攻击单元)，‘pos_x’:横向坐标,’pos_y’:纵向坐标}]\n\n#### 4.5.2 动作信息结构\n以2个探测单元，10个攻击单元为例，则：\n**detector_action为2*2的数组，每一行表示每一个探测单元的两个动作：**\n\n|       | 意义           | 取值范围                                          |\n| ----- | -------------- | ------------------------------------------------- |\n| 动作1 | 航向           | [0-359]离散值                                     |\n| 动作2 | 雷达开关及频点 | 频点[0,频点总数],0表示雷达关，非0表示开机对应频点 |\n\n\n**fighter_action为10*4的数组，每一行表示每一个攻击单元的四个动作：**\n\n|       | 意义                       | 取值范围                                                     |\n| ----- | -------------------------- | ------------------------------------------------------------ |\n| 动作1 | 航向                       | [0-359]离散值                                                |\n| 动作2 | 雷达开关及频点             | 频点[0,频点总数],0表示关，非0表示开机对应频点                |\n| 动作3 | 干扰设备开关机频点         | 频点[0,频点总数+1],0表示关，[1,频点总数]表示开机对应频点   频点总数+1：阻塞干扰 |\n| 动作4 | 是否发射导弹及攻击目标的id | [0,25]   0：表示不发射导弹   1-12: 表示远程导弹攻击敌方目标id   13-24: 表示中程导弹攻击敌方目标id+12 |\n\n#### 4.5.3 回报结构\n回报信息可以通过Environment 接口中的get_reward获得，具体结构如下：\n**以2个探测单元，10个攻击单元为例，则：**\n- detector_reward为(2,)的numpy数组，每一个元素表示每一个探测单元的动作回报\n- fighter_reward为(10,)的numpy数组，每一个元素表示每一个攻击单元的动作回报\n- round_reward为游戏输赢的回报，此回报只有当一局对抗结束才有效\n\n## 5 多智能体算法\n### 5.1 算法与MaCA环境交互关系\n![工作流程](https://leonfg.github.io/maca/resource/workflow.png)\n### 5.2 算法实现示例\n#### 5.2.1 多智能体决策（agent）\n决策的功能是接收观测量并处理，选择合适的动作，并与环境交互。这里将多智能体决策程序称为agent，代码存放在agent路径中，子文件夹名称作为该agent名称。其中，agent.base_agent模块定义了所有agent的基类BaseAgent，其中定义了一些基本数据以及观测信息构建类指示函数:\n```python\ndef get_obs_ind(self):\n    \"\"\"\n    obs indication\n    :return: obs构建程序路径指示字符串。对应obs_construct中同名观测构建代码，若该项赋值为'raw'代表使用原始raw obs data\n    \"\"\"\n    '''返回obs_ind的值'''\n\n```\nagent程序最主要的方法是get_action，即接收观测量并返回动作。\n一个简单的agent应具有如下形式：\n```python\nclass SimpleAgent(BaseAgent):\n\tdef __init__(self):\n    \tBaseAgent.__init__(self)\n        self.obs_ind = 'simple_agent'\t# 指示本决策agent需要使用哪个观测构建类\n        '''初始化数据'''\n\n    def set_map_info(self, size_x, size_y, detector_num, fighter_num):\n    \t\"\"\"\n        获取地图信息\n        :param size_x: 横向尺寸\n        :param size_y: 纵向尺寸\n        :param detector_num: 探测单元数量\n        :param fighter_num: 攻击单元数量\n        :return: N/A\n        \"\"\"\n    \t'''初始化地图、作战实体相关信息'''\n\n    def get_action(self, obs_data, step_cnt):\n    \t\"\"\"\n        获取动作\n        :param obs_data: obs数据\n        :param step_cnt: 当前step数\n        :return:\n        detector_action：侦查单元动作\n        fighter_action：攻击单元动作\n        \"\"\"\n        '''由观测信息得到动作并输出'''\n```\n#### 5.2.2 观测信息构建\n环境输出的底层观测信息称为raw obs，该数据包括红方或蓝方自身所有可知状态信息。对于不同技术思路的agent来说，可能并不需要所有信息，或者数据构建形式不能满足agent自身需求，此时需要agent编写者基于raw obs进行观测信息重构，环境提供此机制便于开发者自定义观测数据。\n观测重构代码应存放于obs_construct/“obs_ind名称”/construct.py，其中“obs_ind名称”应与agent中obs_ind变量赋值相同。一个典型的obs重构代码应具有如下形式：\n```python\nclass ObsConstruct:\n    def __init__(self, size_x, size_y, detector_num, fighter_num):\n        \"\"\"\n        obs construct init\n        :param size_x: 战场横向尺寸\n        :param size_y: 战场纵向尺寸\n        :param detector_num: 探测单元数量\n        :param fighter_num: 攻击单元数量\n        \"\"\"\n        '''内部数据初始化'''\n\n    def obs_construct(self, obs_raw_dict):\n        '''\n        obs构建调用接口\n        :param obs_raw_dict: raw obs数据\n        :return: 自定义obs数据\n        '''\n        '''接收raw obs，构建新obs'''\n```\nagent及配套obs construct按上述要求编写完成后，使用fight_mp进行对抗时会自动生成agent所需观测数据提供给agent进行动作决策。\n#### 5.2.3 训练\n对于使用强化学习等机器学习方法构建的agent程序，需要进行一系列的训练，形成模型数据，才可以实现较好的动作决策。推荐将训练代码存放于“train/agent同名子文件夹”路径下，生成的模型数据存放于“model/agent同名子文件夹”，便于管理使用。\n由于不同技术思路下的agent训练过程各不相同，本环境无法提类似fight_mp的统一训练管控入口，需要开发者自己编写训练调度程序，调用环境接口进行训练。对抗执行流程如下：\n1. 实例化双方agent\n2. 获取双方obs_ind\n3. 调用environment.interface.Environment()创建环境\n4. environment.interface.get_map_info()获取地图信息\n5. 将地图信息传给每个agent各自的set_map_info()\n6. 进入step推进的循环\n\t- environment.interface.Environment.get_obs()获取obs信息\n\t- 使用agent的get_action()将obs传输给agent并获取动作指令\n\t- environment.interface.Environment.step()将动作返回环境，进行下一步推演\n\t- 每一step完成后通过environment.interface.Environment.get_reward()获得回报数据，通过每一step完成后通过environment.interface.Environment.get_done()判断本局是否结束。\n\n具体训练流程可参考[train/simple/main.py](/train/simple/main.py)\n## 6 小结\n中国电子科技集团公司认知与智能技术重点实验室发布的MaCA环境为多智能体对抗算法研究领域带来了一个全新的实验、训练与评估验证平台，为广大研究者提供了更多的交流学习机会。众多军队科研机构，企业科研机构，高等院校都在这个“竞技场”上修炼升级，同台竞技，相互促进，共同提高，将极大地促进军事智能算法研究和重大基础科学问题的解决，实现军事智能跨越式发展和实质性突破，为军事智能未来应用打下坚实基础。"
  },
  {
    "path": "environment/error_log.py",
    "content": "{'speed': 3, 'r_band': 2, 'j_band': 2, 'l_missile_num': 2, 's_missile_num': 4, 'id': 3, 'alive': True, 'pos_x': 576, 'pos_y': 649, 'course': 20, 'radar_enable': True, 'radar_fp': 1, 'radar_visible_list': [], 'passive_location_ind': False, 'detection_count_list': [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 'l_missile_left': 0, 's_missile_left': 3, 'j_enable': True, 'j_fp': 0, 'j_receive_list': []} \n\n[{'speed': 1, 'r_band': 0, 'id': 1, 'alive': False, 'pos_x': 491, 'pos_y': 333, 'course': 0, 'radar_enable': True, 'radar_fp': 1, 'radar_visible_list': [{'id': 11, 'type': 1, 'pos_x': 464, 'pos_y': 361}], 'passive_location_ind': False, 'detection_count_list': [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]}, {'speed': 1, 'r_band': 1, 'id': 2, 'alive': False, 'pos_x': 330, 'pos_y': 666, 'course': 0, 'radar_enable': True, 'radar_fp': 1, 'radar_visible_list': [{'id': 2, 'type': 0, 'pos_x': 622, 'pos_y': 666}, {'id': 11, 'type': 1, 'pos_x': 363, 'pos_y': 654}], 'passive_location_ind': False, 'detection_count_list': [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]}] \n\n{'id': 2, 'alive': False, 'pos_x': 487, 'pos_y': 666, 'course': 0, 'radar_enable': True, 'radar_fp': 1, 'radar_visible_list': [{'id': 1, 'type': 0, 'pos_x': 491, 'pos_y': 333}, {'id': 3, 'type': 1, 'pos_x': 520, 'pos_y': 638}], 'passive_location_ind': False, 'detection_count_list': [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]} \n\n{'speed': 3, 'r_band': 2, 'j_band': 2, 'l_missile_num': 2, 's_missile_num': 4, 'id': 3, 'alive': True, 'pos_x': 578, 'pos_y': 650, 'course': 20, 'radar_enable': True, 'radar_fp': 1, 'radar_visible_list': [], 'passive_location_ind': False, 'detection_count_list': [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 'l_missile_left': 0, 's_missile_left': 2, 'j_enable': True, 'j_fp': 0, 'j_receive_list': []} \n\n[{'speed': 1, 'r_band': 0, 'id': 1, 'alive': False, 'pos_x': 491, 'pos_y': 333, 'course': 0, 'radar_enable': True, 'radar_fp': 1, 'radar_visible_list': [{'id': 11, 'type': 1, 'pos_x': 464, 'pos_y': 361}], 'passive_location_ind': False, 'detection_count_list': [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]}, {'speed': 1, 'r_band': 1, 'id': 2, 'alive': False, 'pos_x': 330, 'pos_y': 666, 'course': 0, 'radar_enable': True, 'radar_fp': 1, 'radar_visible_list': [{'id': 2, 'type': 0, 'pos_x': 622, 'pos_y': 666}, {'id': 11, 'type': 1, 'pos_x': 363, 'pos_y': 654}], 'passive_location_ind': False, 'detection_count_list': [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]}] \n\n{'id': 2, 'alive': False, 'pos_x': 487, 'pos_y': 666, 'course': 0, 'radar_enable': True, 'radar_fp': 1, 'radar_visible_list': [{'id': 1, 'type': 0, 'pos_x': 491, 'pos_y': 333}, {'id': 3, 'type': 1, 'pos_x': 520, 'pos_y': 638}], 'passive_location_ind': False, 'detection_count_list': [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]} \n\n{'speed': 3, 'r_band': 2, 'j_band': 2, 'l_missile_num': 2, 's_missile_num': 4, 'id': 3, 'alive': True, 'pos_x': 580, 'pos_y': 650, 'course': 19, 'radar_enable': True, 'radar_fp': 1, 'radar_visible_list': [], 'passive_location_ind': False, 'detection_count_list': [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 'l_missile_left': 0, 's_missile_left': 1, 'j_enable': True, 'j_fp': 0, 'j_receive_list': []} \n\n[{'speed': 1, 'r_band': 0, 'id': 1, 'alive': False, 'pos_x': 491, 'pos_y': 333, 'course': 0, 'radar_enable': True, 'radar_fp': 1, 'radar_visible_list': [{'id': 11, 'type': 1, 'pos_x': 464, 'pos_y': 361}], 'passive_location_ind': False, 'detection_count_list': [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]}, {'speed': 1, 'r_band': 1, 'id': 2, 'alive': False, 'pos_x': 330, 'pos_y': 666, 'course': 0, 'radar_enable': True, 'radar_fp': 1, 'radar_visible_list': [{'id': 2, 'type': 0, 'pos_x': 622, 'pos_y': 666}, {'id': 11, 'type': 1, 'pos_x': 363, 'pos_y': 654}], 'passive_location_ind': False, 'detection_count_list': [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]}] \n\n{'id': 2, 'alive': False, 'pos_x': 487, 'pos_y': 666, 'course': 0, 'radar_enable': True, 'radar_fp': 1, 'radar_visible_list': [{'id': 1, 'type': 0, 'pos_x': 491, 'pos_y': 333}, {'id': 3, 'type': 1, 'pos_x': 520, 'pos_y': 638}], 'passive_location_ind': False, 'detection_count_list': [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]} \n\n{'speed': 3, 'r_band': 2, 'j_band': 0, 'l_missile_num': 2, 's_missile_num': 4, 'id': 11, 'alive': True, 'pos_x': 526, 'pos_y': 329, 'course': 336, 'radar_enable': True, 'radar_fp': 1, 'radar_visible_list': [], 'passive_location_ind': False, 'detection_count_list': [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 'l_missile_left': 0, 's_missile_left': 1, 'j_enable': True, 'j_fp': 0, 'j_receive_list': []} \n\n[{'speed': 1, 'r_band': 0, 'id': 1, 'alive': False, 'pos_x': 669, 'pos_y': 333, 'course': 0, 'radar_enable': True, 'radar_fp': 1, 'radar_visible_list': [{'id': 1, 'type': 0, 'pos_x': 350, 'pos_y': 333}, {'id': 3, 'type': 1, 'pos_x': 570, 'pos_y': 310}], 'passive_location_ind': False, 'detection_count_list': [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]}, {'speed': 1, 'r_band': 1, 'id': 2, 'alive': False, 'pos_x': 487, 'pos_y': 666, 'course': 0, 'radar_enable': True, 'radar_fp': 1, 'radar_visible_list': [{'id': 1, 'type': 0, 'pos_x': 491, 'pos_y': 333}, {'id': 3, 'type': 1, 'pos_x': 520, 'pos_y': 638}], 'passive_location_ind': False, 'detection_count_list': [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]}] \n\n{'id': 3, 'alive': True, 'pos_x': 615, 'pos_y': 651, 'course': 0, 'radar_enable': True, 'radar_fp': 1, 'radar_visible_list': [], 'passive_location_ind': False, 'detection_count_list': [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 'l_missile_left': 0, 's_missile_left': 0, 'j_enable': True, 'j_fp': 0, 'j_receive_list': []} \n\nstrike_context:  {'attacker_id': 11, 'target_id': 3, 'missile_type': 2, 'step_count': 1, 'op_count': 0, 'del_ind': False}\nTraceback (most recent call last):\n  File \"fight.py\", line 136, in <module>\n    env.step(side1_detector_action, side1_fighter_action, side2_detector_action, side2_fighter_action)\n  File \"/home/boris/MaCA/environment/interface.py\", line 151, in step\n    return self.env.step(side1_detector_action, side1_fighter_action, side2_detector_action, side2_fighter_action)\n  File \"<frozen environment.world.em_battle>\", line 1506, in step\n  File \"<frozen environment.world.em_battle>\", line 401, in __step_list\n  File \"<frozen environment.world.em_battle>\", line 441, in __under_strike_proc\n  File \"<frozen environment.world.em_battle>\", line 693, in __under_strike_proc_delay\n  File \"/home/boris/MaCA/environment/world/strike_calc.py\", line 97, in strike_judge\n    if missile_type == config.get_s_missile_type() and step_count >= 4:\nUnboundLocalError: local variable 'step_count' referenced before assignment\n\n\ndis_update\ndis_update(self, done, step, o_detector_data_obs_list, o_fighter_data_obs_list, e_detector_data_obs_list, e_fighter_data_obs_list, o_detector_data_reward_list, o_fighter_data_reward_list, e_detector_data_reward_list, e_fighter_data_reward_list, o_all_reward, e_all_reward)\n\n\ndis_update_done_font\ndis_update_done_font(self)\n\n\ndis_update_font\ndis_update_font(self, step, red_reward, blue_reward, red_detector_num, blue_detector_num, red_fighter_num, blue_fighter_num, red_missile_num, blue_missile_num)\n\ndis_update_pos\ndis_update_pos(self, o_detector_pos_list, o_fighter_pos_list, e_detector_pos_list, e_fighter_pos_list)\n\n\ndraw_course\ndraw_course(self, center_point_x, center_point_y, course, course_r)\n\n\ndraw_fight_rela\ndraw_fight_rela(self, center_point_x, center_point_y, striking_list, detector_list, fighter_list, line_colour)\n\n\n"
  },
  {
    "path": "environment/interface.py",
    "content": "#! /usr/bin/env python\n# -*- coding: utf-8 -*-\nfrom pytransform import pyarmor_runtime\npyarmor_runtime()\n\"\"\"\n@author: Gao Fang\n@contact: gaofang@cetc.com.cn\n@software: PyCharm\n@file: interface.py\n@time: 2018/4/10 0010 8:52\n@desc: environment interface\n\"\"\"\n\nimport importlib\nfrom world.em_battle import BattleField\nfrom world.replay import Replay\nfrom world.load_map import Map\nimport world.position_calc as position_calc\nfrom render.render_pic import Render\n\nclass Environment:\n    \"\"\"\n    Environment interface\n    \"\"\"\n    def __init__(self, map_path, side1_obs_ind, side2_obs_ind, max_step=5000, render=False, render_interval=1,\n                 random_pos=False, log=False, random_seed=-1):\n        \"\"\"\n        Environment initiation\n        :param size_x: battlefield horizontal size. got from LoadMap.get_map_size\n        :param size_y: battlefield vertical size. got from LoadMap.get_map_size\n        :param side1_detector_list: side 1 detector configuration. got from LoadMap.get_unit_property_list\n        :param side1_fighter_list: side 1 fighter configuration. got from LoadMap.get_unit_property_list\n        :param side2_detector_list: side 2 detector configuration. got from LoadMap.get_unit_property_list\n        :param side2_fighter_list: side 2 fighter configuration. got from LoadMap.get_unit_property_list\n        :param max_step: max step，0：unlimited\n        :param render: display enable control, True: enable display, False: disable display\n        :param render_interval: display interval, skip how many steps to display a frame\n        :param random_pos: start location initial method. False: side 1 on right, side2 on left. True: random position on top, bottom, right and left)\n        :param log: log control，False：disable log，other value：the folder name of log.\n        :param random_seed: random digit，-1：generate a new one，other value：use an exist random digit value\n        \"\"\"\n\n        # load map\n        self.map = Map(map_path)\n        self.size_x, self.size_y = self.map.get_map_size()\n        self.side1_detector_num, self.side1_fighter_num, self.side2_detector_num, self.side2_fighter_num = self.map.get_unit_num()\n        # make env\n        self.side1_detector_list, self.side1_fighter_list, self.side2_detector_list, self.side2_fighter_list = self.map.get_unit_property_list()\n        self.env = BattleField(self.size_x, self.size_y, self.side1_detector_list, self.side1_fighter_list,\n                               self.side2_detector_list, self.side2_fighter_list, max_step, render, render_interval,\n                               random_pos, log, random_seed)\n\n        # for item in dir(Render):\n        #     print(item)\n        # return\n\n        # print(help(Render.draw_fight_rela))\n        # return\n\n\n        # import obs construct class\n        if 'raw' == side1_obs_ind:\n            self.side1_obs_path = 'raw'\n        else:\n            self.side1_obs_path = 'obs_construct.' + side1_obs_ind + '.construct'\n            self.agent1_obs_module = importlib.import_module(self.side1_obs_path)\n            self.agent1_obs = self.agent1_obs_module.ObsConstruct(self.size_x, self.size_y, self.side1_detector_num,\n                                                                  self.side1_fighter_num)\n        if 'raw' == side2_obs_ind:\n            self.side2_obs_path = 'raw'\n        else:\n            self.side2_obs_path = 'obs_construct.' + side2_obs_ind + '.construct'\n            self.agent2_obs_module = importlib.import_module(self.side2_obs_path)\n            self.agent2_obs = self.agent2_obs_module.ObsConstruct(self.size_x, self.size_y, self.side2_detector_num,\n                                                                  self.side2_fighter_num)\n\n\n    def get_done(self):\n        \"\"\"\n        Get done\n        :return: done: True, False\n        \"\"\"\n        # TODO: modified\n        return self.env.get_done()\n\n    def get_obs(self):\n        \"\"\"\n        Get image-based observation\n        :return: side1_obs\n        :return: side2_obs\n        \"\"\"\n        side1_obs_raw_dict, side2_obs_raw_dict = self.get_obs_raw()\n        if 'raw' == self.side1_obs_path:\n            side1_obs = side1_obs_raw_dict\n        else:\n            side1_obs = self.agent1_obs.obs_construct(side1_obs_raw_dict)\n\n        if 'raw' == self.side2_obs_path:\n            side2_obs = side2_obs_raw_dict\n        else:\n            side2_obs = self.agent2_obs.obs_construct(side2_obs_raw_dict)\n\n        return side1_obs, side2_obs\n\n    def get_obs_raw(self):\n        \"\"\"\n        Get raw data observation\n        :return: side1_detector_data\n        :return: side1_fighter_data\n        :return: side2_detector_data\n        :return: side2_fighter_data\n        detector obs:{'id':id, 'alive': alive status, 'pos_x': horizontal coordinate, 'pos_y': vertical coordinate, 'course': course, 'r_iswork': radar enable status, 'r_fre_point': radar frequency point, 'r_visible_list': radar visible enemy}\n        fighter obs:{'id':id, 'alive': alive status, 'pos_x': horizontal coordinate, 'pos_y': vertical coordinate, 'course': course, 'r_iswork': radar enable status, 'r_fre_point': radar frequency point, 'r_visible_list': radar visible enemy, 'j_iswork': jammer enable status, 'j_fre_point': jammer frequency point, 'j_recv_list': jammer received enemy, 'l_missile_left': long range missile left, 's_missile_left': short range missile left}\n        \"\"\"\n\n        side1_obs_dict = {}\n        side2_obs_dict = {}\n        side1_detector_data_obs_list, side1_fighter_data_obs_list, side1_joint_data_obs_dict, \\\n        side2_detector_data_obs_list, side2_fighter_data_obs_list, side2_joint_data_obs_dict = self.env.get_obs_raw()\n        side1_obs_dict.update({'detector_obs_list': side1_detector_data_obs_list})\n        side1_obs_dict.update({'fighter_obs_list': side1_fighter_data_obs_list})\n        side1_obs_dict.update({'joint_obs_dict': side1_joint_data_obs_dict})\n        side2_obs_dict.update({'detector_obs_list': side2_detector_data_obs_list})\n        side2_obs_dict.update({'fighter_obs_list': side2_fighter_data_obs_list})\n        side2_obs_dict.update({'joint_obs_dict': side2_joint_data_obs_dict})\n        return side1_obs_dict, side2_obs_dict\n\n    def get_alive_status(self,side1_detector_obs_raw_list,side1_fighter_obs_raw_list,side2_detector_obs_raw_list,side2_fighter_obs_raw_list):\n        return self.env.get_alive_status(side1_detector_obs_raw_list,side1_fighter_obs_raw_list,side2_detector_obs_raw_list,side2_fighter_obs_raw_list)\n\n    def get_reward(self):\n        \"\"\"\n        get reward\n        :return:side1_detector：side1 detector reward，side1_fighter：side1 fighter reward，side1_round: side1 round reward, side2_detector：side2 detector reward，side2_fighter：side2 fighter reward，side2_round: side1 round reward\n        \"\"\"\n        return self.env.get_reward()\n\n    def reset(self):\n        \"\"\"\n        Reset environment\n        :return: none\n        \"\"\"\n        self.env.reset()\n    def step(self, side1_detector_action, side1_fighter_action, side2_detector_action, side2_fighter_action):\n        \"\"\"\n        Run a step\n        :param side1_detector_action: Numpy ndarray [detector_quantity, 2]\n        :param side1_fighter_action: Numpy ndarray [fighter_quantity, 4]\n        :param side2_detector_action: Numpy ndarray [detector_quantity, 2]\n        :param side2_fighter_action: Numpy ndarray [fighter_quantity, 4]\n        :return: True, run succeed, False, run Failed\n        \"\"\"\n        return self.env.step(side1_detector_action, side1_fighter_action, side2_detector_action, side2_fighter_action)\n\n    def get_map_size(self):\n        \"\"\"\n        Get map size\n        :return: size_x: horizontal size\n        :return: size_y: vertical size\n        \"\"\"\n        return self.map.get_map_size()\n\n    def get_unit_num(self):\n        \"\"\"\n        Get unit number\n        :return: side1_detector_num\n        :return: side1_fighter_num\n        :return: side2_detector_num\n        :return: side2_fighter_num\n        \"\"\"\n        return self.map.get_unit_num()\n\n    def get_unit_property_list(self):\n        \"\"\"\n        Get unit config information\n        :return: side1_detector_list, should be directly forward to Environment init interface\n        :return: side1_fighter_list, should be directly forward to Environment init interface\n        :return: side2_detector_list, should be directly forward to Environment init interface\n        :return: side2_fighter_list, should be directly forward to Environment init interface\n        \"\"\"\n        return self.map.get_unit_property_list()\n\n    def set_surrender(self, side):\n        '''\n        surrender\n        :param side: side1: 0, side2: 1\n        :return:\n        '''\n        return self.env.set_surrender(side)\n\n\nclass PlayBack:\n    \"\"\"\n    Replay\n    \"\"\"\n    def __init__(self, log_name, display_delay_time=0):\n        \"\"\"\n        Initial replay class\n        :param log_name:\n        :param display_delay_time:\n        \"\"\"\n        self.rp = Replay(log_name, display_delay_time)\n\n    def start(self):\n        \"\"\"\n        Replay begin\n        \"\"\"\n        self.rp.start()\n\n# Utilities\ndef get_distance(a_x, a_y, b_x, b_y):\n    \"\"\"\n    Get distance between two coordinates\n    :param a_x: point a horizontal coordinate\n    :param a_y: point a vertical coordinate\n    :param b_x: point b horizontal coordinate\n    :param b_y: point b vertical coordinate\n    :return: distance value\n    \"\"\"\n    return position_calc.get_distance(a_x, a_y, b_x, b_y)\n\n\ndef angle_cal(o_x, o_y, e_x, e_y):\n    \"\"\"\n    Get a direction (angle) from a point to another point.\n    :param o_x: starting point horizontal coordinate\n    :param o_y: starting point vertical coordinate\n    :param e_x: end point horizontal coordinate\n    :param e_y: end point vertical coordinate\n    :return: angle value\n    \"\"\"\n    return position_calc.angle_cal(o_x, o_y, e_x, e_y)\n"
  },
  {
    "path": "environment/license.lic",
    "content": "FCpGTEFHUzoBKkNPREU6cHJvLTAyZ5BCrprWffXaRJeFaCw1aihFNyaQ/BLeHa7NWyCHrDf43ud9WKhQVbrO3PWhLjHKZEZE9FkBbDV440VAFJ+knAcuTEk5zc3I2eS0qAeZUKjiIb4i91gy9kKIfgyqOIg4cXwgasxk3icpOEj9B/yzhnDMXeZn4WUQGOKIbslIdcM="
  },
  {
    "path": "environment/product.key",
    "content": "Bې?CA\u0016k8a\u0011\u00136W\fH0vY\ry\n\u001e\r}\u001f\u0005q\u0001#fRq+JBwzʱnƐS*T\u0011E`wN(\u0005RGy0t\u001dD\u001c&y\u001d\nP:C\u001fq\\8SBV]"
  },
  {
    "path": "environment/pytransform.py",
    "content": "# Because ctypes is new from Python 2.5, so pytransform doesn't work\n# before Python 2.5\n#\nfrom ctypes import cdll, c_char, c_char_p, c_int, c_void_p, \\\n                   pythonapi, py_object, PYFUNCTYPE\nfrom ctypes.util import find_library\n\nimport os\nimport sys\nimport platform\nimport struct\n\n#\n# Global\n#\n_pytransform = None\n_get_error_msg = None\n\n#\n# Options\n#\n\n# How to show error message return from dynamic library _pytransform.\n#\n# Each time call a dll function, if something is wrong, _get_error_msg\n# will return the reason.\n#\n# Enable _verbose_mode will print the details got from _get_error_msg.\n# Disable this options will print only a short message.\n_verbose_mode = 1\n\n# In debug mode, print trace stack when raise exception.\n# Otherwise only show a short message.\n#\n# Run python with command option \"-d\", or set environment variable\n# PYTHONDEBUG. For example\n#\n#   python -d pyarmor.py xxxx\n#\n_debug_mode = sys.flags.debug\n\nclass PytransformError(Exception):\n    def __init__(self, *args, **kwargs):\n        super(Exception, self).__init__(*args, **kwargs)\n        if _debug_mode:\n            self._print_stack()\n\n    @classmethod\n    def _print_stack(self):\n        try:\n            from traceback import print_stack\n        except Exception:\n            _debug_mode = 0\n            sys.stderr.write('Disabled debug mode.\\n')\n        else:\n            print_stack()\n\ndef dllmethod(func):\n    def format_message(msg, *args, **kwargs):\n        if _verbose_mode:\n            s1 = str(args)[:-1]\n            s2 = ', '.join(['%s=%s' % (k, repr(v)) for k, v in kwargs.items()])\n            sep = ', ' if (s1 and s2) else ''\n            line = 'Call with arguments: %s%s%s)' % (s1, sep, s2)\n            return msg\n        return msg.split('\\n')[-1]\n    def wrap(*args, **kwargs):\n        args = [(s.encode() if isinstance(s, str) else s) for s in args]\n        result = func(*args, **kwargs)\n        errmsg = _get_error_msg()\n        if errmsg:\n            raise PytransformError(format_message(errmsg, *args, **kwargs))\n        return result\n    return wrap\n\n@dllmethod\ndef init_pytransform():\n    major, minor = sys.version_info[0:2]\n    # Python2.5 no sys.maxsize but sys.maxint\n    # bitness = 64 if sys.maxsize > 2**32 else 32\n    prototype = PYFUNCTYPE(c_int, c_int, c_int, c_void_p)\n    init_module = prototype(('init_module', _pytransform))\n    init_module(major, minor, pythonapi._handle)\n\n@dllmethod\ndef init_runtime(systrace=0, sysprofile=1, threadtrace=0, threadprofile=1):\n    pyarmor_init()\n    prototype = PYFUNCTYPE(c_int, c_int, c_int, c_int, c_int)\n    _init_runtime = prototype(('init_runtime', _pytransform))\n    _init_runtime(systrace, sysprofile, threadtrace, threadprofile)\n\n@dllmethod\ndef import_module(modname, filename):\n    global _import_module\n    if _import_module is None:\n        prototype = PYFUNCTYPE(py_object, c_char_p, c_char_p)\n        _import_module = prototype(('import_module', _pytransform))\n    return _import_module(modname, filename)\n_import_module = None\n\n@dllmethod\ndef exec_file(filename):\n    global _exec_file\n    if _exec_file is None:\n        prototype = PYFUNCTYPE(c_int, c_char_p)\n        _exec_file = prototype(('exec_file', _pytransform))\n    return _exec_file(filename)\n_exec_file = None\n\n@dllmethod\ndef encrypt_project_files(proname, filelist, mode=0):\n    prototype = PYFUNCTYPE(c_int, c_char_p, py_object, c_int)\n    dlfunc = prototype(('encrypt_project_files', _pytransform))\n    return dlfunc(proname, filelist, mode)\n\n@dllmethod\ndef encrypt_files(key, filelist, mode=0):\n    t_key = c_char * 32\n    prototype = PYFUNCTYPE(c_int, t_key, py_object, c_int)\n    dlfunc = prototype(('encrypt_files', _pytransform))\n    return dlfunc(t_key(*key), filelist, mode)\n\ndef generate_project_capsule(licfile):\n    prikey, pubkey, prolic = _generate_project_capsule()\n    capkey = _encode_capsule_key_file(licfile)\n    return prikey, pubkey, capkey, prolic\n\n@dllmethod\ndef _generate_project_capsule():\n    prototype = PYFUNCTYPE(py_object)\n    dlfunc = prototype(('generate_project_capsule', _pytransform))\n    return dlfunc()\n\n@dllmethod\ndef _encode_capsule_key_file(licfile):\n    prototype = PYFUNCTYPE(py_object, c_char_p, c_char_p)\n    dlfunc = prototype(('encode_capsule_key_file', _pytransform))\n    return dlfunc(licfile, None)\n\n@dllmethod\ndef generate_module_key(pubname, key):\n    t_key = c_char * 32\n    prototype = PYFUNCTYPE(py_object, c_char_p, t_key, c_char_p)\n    dlfunc = prototype(('generate_module_key', _pytransform))\n    return dlfunc(pubname, t_key(*key), None)\n\n@dllmethod\ndef generate_license_file(filename, priname, rcode, start=-1, count=1):\n    prototype = PYFUNCTYPE(c_int, c_char_p, c_char_p, c_char_p, c_int, c_int)\n    dlfunc = prototype(('generate_project_license_files', _pytransform))\n    return dlfunc(filename, priname, rcode, start, count)\n\n@dllmethod\ndef get_registration_code():\n    prototype = PYFUNCTYPE(py_object)\n    dlfunc = prototype(('get_registration_code', _pytransform))\n    return dlfunc()\n\n@dllmethod\ndef get_expired_days():\n    prototype = PYFUNCTYPE(py_object)\n    dlfunc = prototype(('get_expired_days', _pytransform))\n    return dlfunc()\n\n@dllmethod\ndef get_trial_days():\n    prototype = PYFUNCTYPE(py_object)\n    dlfunc = prototype(('get_trial_days', _pytransform))\n    return dlfunc()\n\n@dllmethod\ndef version_info():\n    prototype = PYFUNCTYPE(py_object)\n    dlfunc = prototype(('version_info', _pytransform))\n    return dlfunc()\n\ndef get_hd_sn():\n    size = 256\n    t_sn = c_char * size\n    sn = t_sn()\n    if (_pytransform.get_hd_sn(sn, size) == -1):\n        return ''\n    return sn.value.decode()\n\ndef show_hd_info():\n    return _pytransform.show_hd_info()\n\ndef get_license_info():\n    info = {\n        'expired': 'Never',\n        'restrict_mode': 'Enabled',\n        'HARDDISK': 'Any',\n        'IFMAC': 'Any',\n        'IFIPV4': 'Any',\n        'DOMAIN': 'Any',\n        'CODE': '',\n    }\n    rcode = get_registration_code().decode()\n    index = 0\n    if rcode.startswith('*TIME:'):\n        from time import ctime\n        index = rcode.find('\\n')\n        info['expired'] = ctime(float(rcode[6:index]))\n        index += 1\n\n    if rcode[index:].startswith('*FLAGS:'):\n        info['restrict_mode'] = 'Disabled'\n        index += len('*FLAGS:') + 1\n\n    prev = None\n    start = index\n    for k in ['HARDDISK', 'IFMAC', 'IFIPV4', 'DOMAIN', 'FIXKEY', 'CODE']:\n        index = rcode.find('*%s:' % k)\n        if index > -1:\n            if prev is not None:\n                info[prev] = rcode[start:index]\n            prev = k\n            start = index + len(k) + 2\n    info['CODE'] = rcode[start:]\n\n    return info\n\n# Load _pytransform library\ndef _load_library(path=None):\n    if path is None:\n        path = os.path.dirname(__file__)\n    plat = platform.system().lower()\n    bitness = struct.calcsize('P'.encode()) * 8\n    libpath = os.path.join(path, 'platforms', '%s%s' % (plat, bitness))\n    if not os.path.isdir(libpath):\n        libpath = path\n    try:\n        if plat == 'linux':\n            if libpath == '':\n                m = cdll.LoadLibrary(os.path.abspath('_pytransform.so'))\n            else:\n                m = cdll.LoadLibrary(os.path.join(libpath, '_pytransform.so'))\n            m.set_option('libc'.encode(), find_library('c').encode())\n        elif plat == 'darwin':\n            m = cdll.LoadLibrary(os.path.join(libpath, '_pytransform.dylib'))\n        elif plat == 'windows':\n            m = cdll.LoadLibrary(os.path.join(libpath, '_pytransform.dll'))\n        elif plat == 'freebsd':\n            m = cdll.LoadLibrary(os.path.join(libpath, '_pytransform.so'))\n        else:\n            raise RuntimeError('Platform not supported')\n    except Exception:\n        raise PytransformError('Could not load _pytransform from \"%s\"', libpath)\n\n    # Required from Python3.6\n    m.set_option('byteorder'.encode(), sys.byteorder.encode())\n\n    # m.set_option('enable_trace_log'.encode(), c_char_p(1))\n\n    # # Deprecated from v3.4\n    # m.set_option('enable_encrypt_generator'.encode(), c_char_p(1))\n    # # Deprecated from v3.4\n    # m.set_option('disable_obfmode_encrypt'.encode(), c_char_p(1))\n\n    if not os.path.abspath('.') == os.path.abspath(path):\n        m.set_option('pyshield_path'.encode(), path.encode())\n    return m\n\ndef pyarmor_init(path=None):\n    global _pytransform\n    global _get_error_msg\n    if _pytransform is None:\n        _pytransform = _load_library(path)\n        _get_error_msg = _pytransform.get_error_msg\n        _get_error_msg.restype = c_char_p\n        init_pytransform()\n\ndef pyarmor_runtime(path=None):\n    pyarmor_init(path)\n    init_runtime(0, 0, 0, 0)\n"
  },
  {
    "path": "environment/render/__init__.py",
    "content": "__pyarmor__(__name__, __file__, b'\\xec\\x50\\x8c\\x64\\x26\\x42\\xd6\\x01\\x10\\x54\\xca\\x9c\\xb6\\x36\\x84\\x05\\x6a\\x0b\\xf3\\xc4\\x16\\x01\\xb0\\x49\\xdd\\x1c\\xf4\\xf8\\x5a\\xe1\\xe0\\xc4\\xbe\\x1b\\x41\\x5d\\x2c\\x21\\x77\\xb1\\x53\\x58\\xd9\\xeb\\x22\\xb3\\x4c\\x09\\x12\\xdb\\x19\\xce\\x41\\x3b\\xeb\\xb0\\x0d\\x17\\x26\\x12\\xf9\\x51\\x94\\x9e\\xf1\\xf5\\x85\\x77\\xd0\\x70\\xdf\\xce\\x84\\x05\\x76\\x90\\x38\\xf1\\x10\\xd7\\x44\\x53\\x87\\x32\\x78\\xa3\\x65\\xcd\\x08\\xcf\\x45\\x20\\x53\\x90\\x31\\x2c\\x73\\xa3\\x04\\x11\\xfb\\x6f\\xf4\\x36\\xd1\\x62\\xd3\\x8e\\xcd\\x56\\x1e\\xfa\\x95\\xb6\\xcf\\x95\\xbc\\x7b\\x99\\x14\\x01\\xd1\\x68\\x33\\xcd\\x33\\xf0\\x81\\xb8\\xc9\\xea\\x5c\\x41\\x40\\x4e\\xa4\\xc6\\x33\\x22\\x8b\\xbe\\x9f\\x5e\\x52\\x39\\x81\\x68\\x68\\x4e\\x6b\\x3e\\x50\\xfa\\xd3\\xe2\\x15', 1)"
  },
  {
    "path": "environment/render/render_pic.py",
    "content": "__pyarmor__(__name__, __file__, b'\\xe7\\x50\\x8c\\x64\\x26\\x42\\xd6\\x01\\xb9\\x4e\\x3f\\xdf\\x40\\x9b\\x76\\xef\\x72\\x6c\\x30\\x53\\x5b\\x51\\x12\\xe5\\x74\\x7d\\x05\\x68\\xb6\\x2a\\x70\\xff\\x5a\\x6c\\xe7\\x13\\x67\\xad\\x90\\xbb\\xcf\\x70\\x39\\x65\\x6e\\xea\\x70\\xef\\xf9\\xcc\\xa6\\x0c\\xbc\\x59\\xd1\\x77\\xa1\\x9a\\x9a\\xb6\\x68\\xa1\\x4b\\x30\\x9d\\x0c\\xa4\\x01\\xb7\\xfc\\x29\\xe8\\x56\\xe1\\x9c\\x8d\\x63\\x89\\x24\\xd9\\x30\\x14\\xfd\\x61\\x5e\\x83\\x04\\x18\\xd3\\x5d\\xcd\\xcc\\x5c\\x89\\xe0\\x07\\xd2\\xcb\\xfe\\x13\\x0a\\x78\\x56\\x02\\x8a\\x04\\x02\\x6a\\x09\\xef\\x28\\x22\\xbb\\x60\\xf5\\x30\\xc8\\x17\\x27\\xb2\\xa2\\xa9\\x45\\x38\\x34\\x79\\x7c\\xae\\x0f\\xf8\\xce\\x4f\\x4b\\x60\\xaf\\xcb\\x51\\xc7\\xfc\\xfb\\xb9\\xd5\\xe6\\x91\\x62\\xac\\xd3\\x5c\\x55\\xc3\\xef\\xbb\\xd7\\xe4\\xe2\\xac\\xff\\x0d\\xf5\\x8f\\xac\\xf6\\xe9\\x1c\\x20\\xbd\\xa5\\x8a\\x81\\x12\\x3c\\x4e\\xb9\\x90\\xd7\\x7e\\xf8\\xaf\\x2b\\xe5\\xce\\x65\\x83\\xd1\\xe2\\x99\\xcb\\x02\\x83\\x95\\xfe\\x0b\\xa0\\x16\\x3d\\x75\\x65\\xfb\\x34\\x5b\\x6d\\x04\\xfa\\xd5\\x5b\\x41\\x7e\\xe8\\x91\\x58\\xe1\\xe1\\xd6\\xbd\\xa4\\x6e\\x64\\x28\\x93\\x8c\\x95\\x49\\xe4\\x32\\x1f\\xf1\\x96\\x9e\\x70\\x58\\x34\\x18\\x1a\\x22\\x24\\x53\\xd8\\xdf\\x59\\x8f\\x93\\x37\\x83\\x40\\xf9\\x4c\\x2b\\x69\\xad\\x37\\xfc\\x92\\xc9\\x45\\x3e\\x5a\\x13\\x8f\\xbd\\x36\\xd7\\xdf\\x8a\\xa3\\x1c\\xdf\\x4f\\x36\\xde\\xfa\\x23\\x33\\x36\\x92\\x40\\xef\\xdc\\xf5\\x15\\x15\\x6e\\x35\\x81\\x54\\x5a\\x63\\xbc\\x92\\xc8\\x8f\\x0e\\x7f\\x9d\\x09\\x73\\x26\\x51\\xb9\\x71\\x34\\xff\\x1b\\x58\\x31\\xdb\\x2a\\x5c\\x4f\\xab\\xb7\\x7a\\xcc\\x5d\\x58\\xca\\xd4\\x7d\\x6d\\x7d\\x1d\\x89\\x0b\\x1a\\x41\\x76\\xed\\x90\\x0d\\xd5\\x93\\x39\\x9a\\xa9\\x74\\x79\\x25\\x3b\\x09\\x39\\x8b\\xff\\xc8\\x3a\\x60\\x5b\\x64\\xa3\\xb6\\x31\\x67\\x31\\x54\\x14\\xb2\\x7d\\x20\\x11\\x25\\x1f\\x6d\\x0d\\x5c\\x7b\\x59\\xcc\\x86\\x94\\xba\\x11\\x77\\xbb\\x37\\xe7\\xa6\\xde\\x89\\x28\\x0c\\xb3\\x4f\\xd0\\x6e\\x84\\x3c\\x5b\\xbd\\x9c\\x4b\\x4d\\x36\\x1b\\x92\\x9e\\x9d\\x08\\x8f\\x40\\x48\\x86\\x5b\\x07\\x2b\\x1f\\x0b\\x1c\\x68\\xa1\\xd1\\xd4\\x96\\x90\\xf0\\x46\\x51\\x1d\\x07\\x82\\x23\\x5f\\x23\\x4b\\xce\\x28\\x0e\\xd2\\x49\\x87\\x6e\\xa5\\x7e\\xc3\\x9d\\x5f\\x48\\x44\\x86\\xdf\\xae\\x6a\\xf1\\xc4\\x34\\x48\\xcc\\xcc\\x42\\xc1\\x13\\x56\\x4b\\x08\\x4c\\xe4\\x35\\x1e\\x65\\x74\\xc8\\xa2\\x68\\x48\\x99\\xe3\\x71\\x9a\\xa5\\xb8\\x5e\\x02\\x96\\x8d\\xdf\\x01\\x1e\\x43\\x9f\\x56\\xe0\\x6a\\xdc\\xfb\\x2a\\x64\\xde\\x02\\xea\\xc9\\xd0\\xa3\\x1a\\xb0\\x2a\\x85\\x14\\x49\\x6b\\x99\\x74\\xef\\xee\\xac\\x1b\\x49\\x63\\xe9\\x6a\\x7d\\x6e\\xea\\x70\\x59\\xef\\x6a\\x5d\\x5c\\x5c\\x4b\\xe9\\xb9\\xe4\\xd8\\xc7\\x1a\\x23\\x4a\\x54\\xf3\\x59\\x0f\\xb8\\x0c\\xe7\\x8d\\x72\\x37\\x16\\x1b\\xe0\\x17\\x43\\x80\\xf9\\xb1\\x72\\x8b\\x01\\xf7\\x1f\\x34\\x2c\\x2a\\x09\\x47\\xef\\x49\\xbd\\xa1\\x76\\x1c\\xd8\\x3b\\x85\\xc0\\x41\\xf6\\x5c\\xaf\\xf7\\x07\\x03\\xd8\\x05\\xad\\x2d\\xb8\\x14\\x73\\x7f\\xe8\\xb8\\xab\\x2e\\x32\\x01\\xc8\\xc6\\xbf\\xa1\\xf5\\xae\\xf5\\xb1\\x47\\x80\\xe4\\xb2\\xbd\\x7e\\xd1\\xb0\\x7a\\x42\\x9a\\xd3\\x46\\x26\\x4a\\x24\\xcb\\xb9\\x8d\\xfa\\x46\\x96\\x27\\x49\\x57\\x16\\x35\\x63\\xfe\\x90\\xe6\\x0f\\x7e\\x6b\\x83\\x61\\x2f\\xe9\\x03\\xd1\\x08\\x83\\x9a\\x39\\x55\\xd0\\x62\\x17\\x6f\\x38\\x1f\\x77\\x10\\x4f\\xe1\\x0f\\x31\\xae\\x4e\\xa6\\x39\\x06\\xf8\\xc9\\x46\\xca\\xfc\\x1f\\x08\\xec\\x9f\\xc3\\xfd\\xe6\\x62\\x64\\xff\\xae\\x5f\\x5e\\x2a\\x64\\xbb\\x35\\x5d\\x2f\\x4c\\x7c\\xde\\x9f\\x05\\xd5\\x39\\xd6\\x38\\x04\\xdb\\x03\\xe5\\xe7\\x91\\xc6\\x4e\\xa0\\x1d\\x14\\x83\\x74\\xee\\x0e\\xfd\\x07\\xba\\xc6\\x15\\xf7\\x43\\xf9\\xf5\\xfc\\x3f\\xec\\x5c\\x94\\x6a\\x01\\xfc\\x4d\\x10\\x9c\\xab\\x17\\xc3\\x46\\xc3\\xf9\\x58\\x83\\x58\\x5c\\x19\\x6a\\x4d\\xcc\\xd1\\x4c\\x36\\x9c\\xc4\\x7f\\xc8\\x1e\\x81\\x38\\x25\\x1f\\x55\\x8c\\x6f\\x20\\x26\\x29\\x8a\\x6b\\x1e\\xab\\x71\\x88\\x33\\x6a\\x4e\\xdd\\x4f\\xb9\\x67\\xe7\\x49\\xcf\\xe6\\xb2\\x9d\\x26\\xad\\xab\\x00\\x0f\\x3b\\x44\\xab\\xc3\\x98\\x5f\\xbc\\x5c\\xbb\\x7e\\x25\\xa0\\xf9\\x13\\x88\\xdf\\xc7\\x4f\\xfa\\xcd\\x96\\xfd\\x0d\\x12\\x9f\\x6f\\x56\\xe2\\x59\\x3b\\x5a\\x0a\\xf8\\xf6\\xa6\\xbc\\xcd\\x01\\x95\\x41\\x2e\\xa9\\x7b\\x5c\\x05\\x7b\\xdf\\x52\\x22\\xc8\\x7d\\xe4\\xb2\\x41\\x0e\\x38\\xd7\\x9f\\x81\\x63\\xf9\\x04\\xba\\x5e\\xa4\\xe3\\x47\\xbe\\xe5\\x25\\x9f\\x31\\xb9\\x24\\xaa\\x34\\xd6\\x81\\xca\\xba\\xbf\\x8b\\x8c\\x02\\x18\\xe6\\xa1\\x59\\xbe\\xea\\x89\\xa3\\x13\\x6b\\x6c\\xb9\\x20\\xcc\\x58\\x87\\x12\\x74\\xe0\\x75\\x10\\x5d\\xfd\\x31\\x6f\\x7c\\xb6\\xc7\\xf0\\x38\\xc7\\x9c\\x70\\x33\\xd0\\x56\\xd8\\x2e\\x03\\x45\\x80\\xdb\\x08\\x4d\\xc2\\x6b\\xd0\\x90\\x95\\x0b\\xd8\\x3f\\xb7\\x27\\x24\\xc6\\x46\\x93\\x35\\xb8\\xa9\\x69\\x24\\x86\\xd3\\xa0\\x11\\xb2\\x22\\xee\\xbb\\x3f\\xa9\\x28\\x8e\\xc9\\x2a\\x3d\\xea\\xe7\\x6a\\x9e\\xcc\\xc2\\x92\\x88\\xdb\\x8d\\x32\\x91\\x22\\x16\\x79\\xb6\\x80\\x97\\x30\\x34\\x57\\x3d\\xe3\\x73\\xa3\\x10\\x4b\\xb6\\xb7\\x99\\xc8\\x60\\xb8\\x8b\\x22\\x2f\\xf2\\xd4\\xcc\\xc5\\xa4\\xa5\\x8c\\x49\\xf9\\xed\\xef\\x5d\\xfa\\x77\\xa3\\xfd\\x1c\\x4a\\xe9\\x2a\\x49\\xea\\x7d\\xdd\\x8d\\x3a\\x36\\x39\\x48\\x25\\x93\\xd2\\x7b\\x7f\\x14\\x55\\x59\\x60\\x13\\x28\\x05\\x4a\\xa1\\x85\\x69\\xe2\\x91\\x70\\x74\\x22\\x71\\x24\\x40\\x28\\xc5\\xf9\\x11\\x74\\xf8\\x88\\x51\\x4c\\x29\\xa0\\xcb\\x15\\xb8\\x99\\xcc\\x9e\\xa2\\xb4\\xec\\x2c\\x25\\x0a\\xee\\xbd\\x61\\xbd\\x33\\x04\\x27\\xab\\xaa\\xcb\\x08\\x1e\\x87\\x77\\x13\\x78\\xc7\\x22\\x6a\\xae\\x9d\\x3b\\xe6\\xcb\\x78\\x9e\\x59\\xff\\x77\\x1c\\xf5\\xf2\\x69\\x02\\x7d\\xfa\\xdc\\x86\\x13\\x4d\\x18\\x3c\\x4e\\x04\\x97\\x81\\x7c\\x41\\xe0\\x67\\x36\\xe5\\x57\\xcb\\x36\\x51\\xeb\\xd3\\x93\\x48\\x18\\x39\\xb9\\x9a\\xc8\\x7e\\xac\\x54\\x0c\\x46\\xc7\\xd6\\x2e\\x00\\xb0\\x41\\x0f\\x59\\x50\\x8f\\xc5\\xbe\\x50\\x8a\\x2f\\x7e\\x79\\x1f\\x06\\x35\\x6f\\x3f\\xd1\\x17\\x0f\\x6c\\xe3\\x58\\x34\\x63\\x29\\x80\\x0f\\xa6\\x43\\xe0\\x3c\\x21\\x59\\x50\\x34\\xc9\\xab\\x94\\x3a\\x92\\x12\\x81\\x4e\\xbc\\x0e\\x2e\\x52\\xa6\\xc8\\x0d\\x2e\\xb3\\x0a\\xf5\\xee\\xe5\\x6b\\x9b\\x71\\x62\\x04\\x11\\x4e\\x55\\xe4\\xd5\\x6c\\xdc\\xf9\\x9d\\xfe\\xac\\x2a\\xa8\\x22\\x71\\x7e\\xca\\xd6\\x3f\\xe0\\x11\\xd3\\x43\\x0f\\xb1\\xd9\\xb4\\x3f\\x89\\x4c\\x15\\x74\\x94\\xf0\\x39\\x11\\x62\\x2e\\x2d\\x8e\\x68\\xf9\\x0b\\x0f\\x43\\x3f\\x89\\x48\\xb1\\x43\\x2e\\xdc\\xdf\\xb2\\x20\\x3e\\x8b\\xcf\\xaf\\x8e\\xaf\\x1b\\x31\\xc6\\x58\\x61\\x5c\\x06\\x81\\xfe\\x19\\xe3\\x22\\x53\\x1c\\x0f\\x6d\\x14\\x34\\x51\\xd3\\x73\\xb7\\xd2\\x9b\\xc9\\xf8\\xc2\\xc0\\xfb\\x7a\\xd1\\x25\\x46\\x18\\xd1\\xea\\x4f\\xe3\\xf5\\xfc\\xd5\\xe6\\xb7\\xcf\\x52\\x11\\xd2\\x17\\xc5\\x05\\x29\\xc4\\xf9\\x06\\x3b\\x12\\x71\\xf2\\x19\\xcc\\x4c\\xca\\xa4\\x9c\\x9b\\xd4\\x20\\xc5\\xfe\\x9f\\x9f\\x2b\\x02\\x2b\\xbf\\x1d\\x86\\x58\\xfb\\x27\\x20\\xe6\\x45\\xba\\x7c\\xe1\\xc4\\xa5\\x3d\\x33\\xa2\\xea\\x2a\\xa3\\xd5\\x0c\\xfd\\x0d\\xbe\\xd2\\x00\\xef\\x5b\\xe3\\x36\\xb1\\x3d\\xd8\\x38\\x62\\x6e\\xb9\\xcb\\x49\\x67\\xf0\\x10\\x01\\xdb\\x67\\x30\\xfa\\xbf\\xa6\\xea\\x15\\x2f\\x65\\x70\\x0b\\x35\\xe7\\x7b\\x19\\x21\\xaf\\xcc\\x76\\x97\\xf8\\x5e\\xd1\\xd7\\x0f\\xe1\\x6b\\x61\\x31\\xb5\\x08\\x98\\x35\\x3d\\x0f\\x11\\xec\\xed\\x6d\\x89\\x7e\\xa3\\x8a\\x87\\x09\\x87\\xe9\\x8a\\x03\\xb7\\xde\\x89\\x70\\x39\\x22\\x77\\xd9\\x7e\\xd3\\xef\\x91\\xb5\\x81\\x62\\xa6\\x5d\\xf3\\x74\\x97\\x37\\x40\\xc7\\xad\\x0a\\x73\\x2a\\x88\\x76\\x6f\\xd5\\x94\\x00\\xef\\x1e\\x41\\x3a\\x07\\xf0\\x28\\xa2\\x27\\xdb\\x79\\xf8\\xe5\\xa1\\xf7\\xb6\\x91\\x48\\xf4\\x95\\xc6\\xd4\\x4e\\x65\\x8b\\x0a\\x47\\x23\\x8a\\xc2\\xd7\\x32\\xe4\\x02\\x74\\x44\\x36\\xad\\xf0\\xd5\\x8b\\xed\\xbe\\xe3\\x5b\\xbb\\x13\\x07\\x11\\x35\\x52\\xe2\\xd7\\x20\\x01\\x80\\x54\\xd1\\x25\\x13\\x2c\\x9b\\x86\\x3f\\xc3\\xbe\\xd5\\xac\\x11\\xf5\\xf4\\xb9\\xd1\\x53\\x62\\x7f\\x4f\\xf5\\x62\\xe0\\xec\\x8f\\x81\\xa8\\xf2\\xbe\\xb4\\x54\\xbf\\x7b\\xbd\\xcd\\xb6\\xb4\\x94\\x21\\x94\\xbe\\xd1\\xff\\xf9\\x37\\x25\\xfd\\xe3\\xce\\x14\\xb2\\x1d\\x96\\x55\\x89\\x55\\x5e\\x75\\xba\\xfe\\x08\\x44\\xc5\\x06\\xa5\\xd5\\x5e\\x86\\x14\\x6a\\xfe\\x08\\x47\\xab\\x31\\x4f\\x05\\xab\\x28\\x1c\\x7e\\xdd\\x78\\x7a\\xb2\\x81\\x27\\x18\\xf5\\xdb\\x45\\x73\\x1b\\x69\\xec\\x86\\x6c\\x17\\xe6\\x2c\\xde\\x70\\x97\\x79\\x2b\\xa6\\x6a\\x05\\xd8\\x5f\\x31\\x61\\x8d\\xa4\\x6f\\x1b\\x17\\x49\\xe5\\x9f\\x2c\\x03\\x14\\xd6\\x9b\\x6f\\xb9\\x50\\xfd\\x2e\\x18\\x2d\\xbf\\x2f\\xec\\xd6\\xd8\\xc3\\x87\\x1d\\x35\\x9f\\x1f\\x43\\x80\\xdd\\x28\\xe0\\x71\\x4b\\xd4\\x72\\xe1\\x45\\x62\\x9c\\xa5\\x27\\x03\\xc2\\xbe\\x27\\xed\\x47\\xc9\\xd6\\xe4\\x18\\x65\\x08\\xe4\\x53\\x51\\x38\\x40\\xb3\\xb2\\x2e\\x10\\xd2\\xe7\\x06\\x53\\xbe\\xb4\\xdb\\x91\\x2f\\xa6\\xb6\\x01\\xb1\\xa9\\x27\\xf0\\xa6\\xb9\\x7c\\x06\\x32\\xf6\\xb1\\x4f\\x78\\x4f\\x31\\xcc\\x95\\xbc\\x62\\x44\\xb4\\x75\\x00\\x3d\\xfb\\xbb\\xfd\\x17\\x6f\\x3b\\x91\\x29\\xc6\\xf4\\x05\\x0b\\x52\\xf2\\xc3\\xfe\\x89\\x8b\\xde\\x7e\\x06\\xb2\\x09\\x8d\\x63\\xcd\\x6f\\x8f\\x66\\x33\\x25\\x55\\x18\\xa7\\xc9\\xd4\\xb5\\xba\\x62\\x33\\xbf\\xf1\\x84\\x76\\x98\\x08\\xae\\x06\\x1a\\x56\\x42\\xd6\\x83\\xeb\\x12\\xd5\\x1c\\x02\\xa3\\xd6\\x22\\xb9\\x47\\x44\\x41\\x23\\x93\\xa7\\xbe\\x73\\xa5\\x90\\x6f\\xce\\x56\\x90\\x27\\x2a\\x65\\xda\\x63\\xff\\x0d\\xc8\\x4f\\xa5\\xb1\\xd1\\x96\\x84\\xe4\\x31\\xbe\\xfb\\x4d\\x16\\x34\\x3c\\xdc\\x47\\x93\\x84\\x83\\x89\\xc5\\x88\\x85\\x46\\x5f\\x50\\xb5\\xee\\x1c\\x8d\\x8c\\x30\\x3c\\x20\\x61\\x23\\xd1\\x1b\\x39\\x4f\\xe1\\xfd\\x81\\x8d\\x4a\\xe2\\x33\\x59\\x68\\x58\\x90\\x28\\x64\\x3a\\xd6\\x76\\xb0\\xf3\\x04\\x93\\x8b\\xb5\\x99\\xcb\\xa7\\xba\\x38\\x5b\\x62\\x39\\xda\\x5b\\x79\\x3e\\x44\\x9e\\x5c\\xff\\xb7\\xa7\\x51\\x69\\xf1\\x27\\x5e\\x0a\\xa4\\xf5\\x8b\\x4f\\xe5\\xb3\\xe8\\xfd\\x1b\\x95\\x4d\\x68\\xc2\\xb2\\x8a\\xe6\\x28\\xad\\x32\\xe6\\x08\\x58\\xc4\\x3c\\xc5\\x76\\x51\\xb5\\xac\\xf8\\xc7\\xf9\\xfa\\x4b\\xe9\\xc1\\xc0\\x72\\x0d\\x88\\xd4\\xf3\\xc9\\x5e\\xe0\\x2a\\x64\\x50\\xaa\\xa8\\x5c\\xe4\\xa5\\x63\\xeb\\x09\\xb1\\xe7\\x5d\\x0c\\xcf\\x07\\x7b\\x26\\x42\\xfc\\xff\\x54\\xb8\\xdf\\x08\\xa4\\x4f\\x87\\x27\\x24\\xbf\\x20\\x8e\\x9b\\xd1\\xb1\\xfd\\x49\\x26\\x6b\\x89\\x9f\\x60\\xec\\x12\\xf3\\x30\\xa3\\x95\\xb9\\xc9\\xcc\\x54\\xc8\\x06\\xe6\\xda\\x7c\\x40\\x27\\x4e\\x73\\x3c\\xb3\\x1d\\x70\\x04\\xd1\\xba\\x5b\\x7c\\xa1\\x4c\\x01\\xe9\\x23\\xb6\\xfc\\x86\\x8d\\xe4\\x93\\xab\\xea\\xd0\\xee\\xa1\\xf1\\xaa\\xef\\x1c\\x00\\xe2\\x05\\x9d\\xdb\\xfa\\xa3\\xda\\x1c\\x60\\xcd\\xcc\\x7d\\x6c\\x2c\\x95\\x94\\x5d\\x79\\x2d\\xdf\\x58\\x87\\x95\\x04\\x89\\x2c\\x47\\x8c\\x28\\xaa\\x7c\\x40\\xc4\\xfe\\x36\\x0b\\xdf\\xb8\\x0a\\xfe\\x1a\\x1f\\x03\\x6e\\xde\\xbe\\xc7\\x75\\x6d\\xf9\\xbc\\xa7\\x10\\x74\\x70\\xc4\\xf7\\x66\\xac\\x1e\\x9d\\x8d\\xda\\xde\\x36\\x1b\\xd4\\x0f\\x87\\xdf\\x90\\x30\\x56\\x90\\x21\\xa9\\xec\\x01\\x17\\x44\\xb6\\xab\\x7f\\xad\\xf5\\xb5\\xa0\\x40\\x8e\\x44\\x92\\xbe\\xff\\xc6\\x7c\\x82\\x8f\\x9f\\x46\\x9a\\xc9\\xd1\\x50\\x6c\\xd9\\x4c\\xeb\\x99\\x06\\xf2\\x30\\x9a\\x7e\\xcc\\xf0\\x1d\\xc3\\x7c\\x97\\xfe\\x0e\\x5e\\x63\\xd6\\x81\\xbc\\x7f\\xca\\xf6\\xf4\\x8e\\x7f\\x26\\x95\\x77\\x05\\x64\\x42\\x53\\x39\\x55\\xc6\\xd5\\x59\\xf1\\x4c\\xb0\\xd0\\xc4\\x65\\xa6\\x54\\x1a\\xe3\\xc1\\x62\\xec\\xa2\\xa9\\x29\\x34\\x42\\xa9\\xfb\\xf9\\x99\\x25\\x5b\\xef\\xfe\\x03\\x31\\x42\\x03\\xc1\\x49\\xc7\\x6b\\x0d\\xb4\\xf4\\x7e\\x94\\x84\\x9c\\x45\\x44\\xcf\\xcf\\x16\\x6b\\x51\\x46\\x9a\\xc6\\x97\\x8e\\xfd\\x33\\x9d\\xfd\\x9b\\xda\\xc6\\x01\\x68\\xd2\\x09\\x84\\x6e\\x61\\x2a\\x7b\\xff\\xda\\x3e\\x9a\\x0b\\x4a\\x89\\x79\\x58\\xbe\\xa7\\xc3\\xcc\\x42\\x26\\xca\\x9d\\x25\\x6c\\xd0\\x33\\xba\\xfc\\x22\\x52\\x48\\xc3\\x42\\xf9\\x80\\x0f\\x85\\xe3\\x89\\xaa\\xbd\\x20\\x72\\x31\\xe1\\xdd\\x6f\\xa5\\xc5\\xa6\\x52\\x44\\x99\\xd7\\x05\\x35\\xe6\\x43\\xaf\\x1b\\xed\\x30\\xea\\xa3\\x5c\\xa4\\xf0\\x9c\\x8e\\x04\\x9b\\x6a\\xc0\\x56\\xb0\\x2d\\x00\\x6a\\x86\\x64\\x43\\xd0\\xee\\xd4\\xdb\\xa3\\xa3\\x42\\x6c\\x5b\\xdf\\x10\\x81\\xf9\\xd9\\x11\\x08\\x96\\xe6\\x9a\\x61\\x3f\\x2a\\x1e\\xdb\\xf6\\x64\\xeb\\xa5\\x51\\xa5\\xea\\x00\\x24\\x1c\\x1d\\x64\\x00\\xdb\\x77\\x70\\xa8\\xc9\\x29\\xf0\\x36\\xf4\\xc5\\xe2\\x61\\xda\\xab\\x78\\x9a\\x27\\x90\\xc1\\x70\\xfa\\xbb\\xea\\xb6\\xe4\\x0f\\xbe\\xbf\\x60\\x98\\x96\\x15\\x2f\\xd7\\xfc\\xb7\\x8f\\x70\\x82\\x2a\\x6e\\x4a\\x52\\xf5\\xcb\\x8d\\xc3\\x8c\\xd1\\xea\\x21\\x6f\\x1a\\xe8\\xfa\\x57\\xec\\x02\\x73\\x79\\x10\\x8c\\x83\\x02\\x18\\xf3\\x0a\\xb4\\xf1\\x09\\xe6\\x08\\xa3\\x10\\x4e\\x1b\\xcb\\x2b\\xcd\\x3f\\x4c\\xcd\\xfe\\x4b\\xf0\\x0c\\xb3\\x7f\\x86\\x43\\xec\\x07\\xf3\\x47\\x8f\\x50\\x2e\\xb8\\x4b\\x28\\x0c\\x20\\x47\\xf8\\x0f\\x1f\\x36\\x00\\xb7\\xd3\\xde\\xc4\\xdd\\x49\\xed\\x2c\\x6b\\x17\\x79\\xdc\\xf5\\xde\\xa4\\x5d\\x37\\xae\\xb8\\xa8\\xb1\\x01\\x7b\\x2d\\xb8\\x3f\\xdd\\x15\\xe5\\x20\\x44\\xd3\\x4c\\xc1\\xed\\x31\\x43\\x17\\x27\\xa0\\x59\\x45\\x17\\x7b\\x04\\xd6\\x62\\x6f\\x6c\\xc9\\xd1\\x56\\x97\\xd7\\x7c\\x3c\\x74\\x10\\xfd\\x38\\xba\\x41\\xa2\\xae\\xfb\\xf0\\x1d\\xac\\x73\\x54\\x44\\xb5\\x20\\x79\\x81\\xa9\\x05\\x63\\x3e\\x2a\\xbe\\x35\\x3e\\x93\\x56\\x8d\\x24\\xbf\\x3c\\x80\\x21\\xf7\\xda\\xd8\\x84\\x51\\x8c\\xa6\\x8c\\xd8\\x29\\x66\\xea\\x94\\xcb\\x8a\\xc2\\x3c\\x49\\x12\\x6a\\x78\\xce\\x45\\xa5\\x82\\xd6\\x39\\xa3\\x69\\x4e\\x70\\xdf\\xb4\\xd0\\x6a\\xd7\\x42\\xaa\\x80\\x48\\xa0\\xd9\\x1d\\xd2\\x63\\x55\\xa5\\x07\\x11\\x57\\x3f\\xf7\\x45\\xf1\\x72\\x47\\x5f\\x0f\\x0f\\xdf\\xa7\\x0f\\xc0\\x29\\x14\\xf9\\xfd\\x37\\xc2\\x65\\x5e\\x68\\xc6\\xe2\\xdb\\x7e\\xb7\\x37\\xf2\\x69\\x90\\x4c\\xb2\\xe7\\x13\\x4e\\xc3\\xa4\\x36\\xdd\\x98\\x80\\x62\\x20\\xb1\\x37\\xb1\\x01\\x91\\x2a\\xa5\\xb2\\x51\\x85\\x51\\xf2\\xfe\\x59\\x45\\xce\\x48\\x1d\\xb0\\xb7\\x66\\x97\\x6a\\xbd\\x02\\x0f\\x33\\x41\\x6a\\x67\\x33\\xf8\\x01\\xe9\\x75\\x7b\\xbd\\x94\\x2f\\x7e\\x9a\\x28\\x97\\xdc\\x41\\x4b\\x29\\xc5\\xc8\\xa8\\x3a\\x0f\\xb0\\xae\\xdb\\xcb\\xd9\\x51\\x44\\x89\\x18\\xc1\\x9d\\x99\\x9c\\x85\\x06\\x17\\xa4\\x38\\x53\\xb3\\x95\\x39\\xf8\\x74\\x40\\x57\\xa0\\x3f\\xc6\\x33\\x95\\x03\\x96\\x9e\\x32\\xd5\\xe8\\x1a\\xd8\\x7e\\x01\\xf7\\x50\\x31\\x97\\x08\\xe4\\x5b\\x39\\xdd\\x02\\x32\\x50\\x1b\\xaa\\x9f\\xe1\\x60\\xb2\\x06\\x8a\\x74\\x01\\xd5\\xae\\xa2\\xe8\\xb3\\x37\\xa9\\x61\\x81\\xd5\\x77\\xd9\\xe0\\x7e\\xc4\\x13\\x1d\\x55\\x8d\\x38\\xad\\x65\\xdd\\x8f\\x31\\xcd\\x64\\x02\\x5d\\xf1\\xf9\\x32\\x47\\x31\\x60\\x24\\xcf\\x4e\\x1d\\xbd\\x06\\xc3\\x31\\xac\\x00\\xff\\x90\\xc9\\x58\\x46\\x0d\\xc4\\xba\\x4b\\x5b\\x63\\x12\\xeb\\xc9\\x95\\x87\\x2d\\x60\\xda\\xcc\\xb9\\xf5\\xd1\\x17\\xdd\\x77\\xc8\\x2e\\x74\\x9e\\x28\\x34\\x36\\x2f\\x63\\x68\\x36\\x72\\x50\\xe7\\x97\\xf7\\xfb\\x7c\\xe8\\x40\\xdb\\x62\\xff\\x9f\\xd1\\xb4\\x23\\xe1\\x84\\x66\\x70\\x3b\\x1f\\x0a\\xba\\x11\\x6e\\xc1\\x69\\x26\\x60\\x8b\\xa8\\x1a\\x55\\xfe\\x26\\x45\\x98\\x8b\\xa3\\x27\\xf9\\xe2\\x82\\xa2\\x0c\\x1d\\x28\\x9b\\xae\\xc9\\xca\\xbc\\xdd\\x9e\\x73\\x5f\\x73\\xd9\\x0f\\x57\\x62\\x2e\\x12\\x22\\xfc\\x3b\\x6b\\x73\\x40\\x12\\x64\\x53\\x76\\x8e\\x0b\\xf0\\x04\\x45\\x08\\x0a\\x4a\\x9d\\x56\\x11\\x5a\\x05\\x8d\\x13\\x2f\\xcc\\xa4\\x58\\xe3\\x99\\x1d\\xac\\x9b\\x2f\\x04\\xb2\\x09\\x23\\xf5\\xf7\\xbf\\xdd\\x93\\xac\\x97\\x76\\xa5\\x77\\xc6\\x7b\\xac\\x87\\xb1\\x23\\x4d\\xb5\\x0b\\xea\\x20\\x1c\\x7e\\x02\\x16\\x8a\\x2d\\xec\\x9d\\xe8\\x55\\xa0\\x71\\x1d\\xda\\x68\\xa2\\xfa\\x88\\x15\\xdc\\x31\\x5b\\xc7\\x61\\xb3\\x93\\xca\\x18\\x4c\\x94\\x2c\\x7f\\x76\\x8b\\xa2\\x65\\xef\\x9b\\x69\\xde\\x8a\\x6a\\xa3\\xf3\\x27\\x7b\\x00\\x42\\xab\\x6b\\xca\\x4d\\xf8\\x7a\\x66\\xeb\\x19\\x37\\x0d\\x56\\x33\\x76\\x74\\x69\\x0f\\x2b\\x10\\x7a\\x4f\\xb3\\x43\\x12\\xeb\\x9b\\xca\\x12\\x9f\\xf8\\x81\\xb1\\xed\\x4d\\xdd\\xae\\xb9\\x35\\x8f\\xab\\xf5\\x20\\xdb\\x76\\x97\\xfe\\xd9\\xc4\\x36\\xd1\\x92\\x1a\\xe3\\xc6\\xd2\\x95\\xdd\\xb0\\xe4\\x82\\x0f\\x46\\x5f\\x52\\xe1\\x8a\\x21\\x6f\\x77\\xa4\\x6d\\x7c\\xb4\\x79\\xc8\\xb7\\x53\\x30\\x2b\\x11\\xa3\\x31\\xd2\\xfc\\x70\\xd2\\xa0\\x7d\\xef\\x55\\x4f\\x06\\x3c\\xf9\\xd4\\x78\\xa9\\x12\\xf2\\xc7\\x98\\x80\\x18\\x65\\x20\\xa5\\x9c\\xdb\\x8b\\x26\\x38\\x6d\\xa0\\x43\\x48\\x06\\x26\\x28\\x18\\x26\\x6c\\x28\\xaf\\xe6\\x1b\\xb7\\xc3\\x97\\x7e\\x9a\\x4b\\x5e\\x1b\\xa0\\xb5\\xe5\\x99\\xe2\\x9f\\xb9\\x71\\x2b\\xf7\\x0a\\x85\\x66\\xb1\\x17\\xb9\\xa8\\x31\\x5b\\xb4\\xd1\\xcd\\x02\\xa0\\x75\\x7b\\x46\\xe1\\xd2\\xf1\\x9a\\xc1\\xbd\\x4d\\x14\\x0a\\xa4\\xaf\\x48\\x91\\xf6\\x65\\x14\\x5d\\xb0\\xa6\\xf3\\xb5\\x3a\\x15\\x3a\\x7c\\x85\\x39\\x36\\xe9\\xe7\\x43\\x1d\\xb3\\xcf\\xcc\\xbc\\x27\\xf6\\x24\\x1d\\x0b\\x6f\\x4c\\x6e\\x1a\\x39\\xb9\\xe3\\xeb\\xc0\\xd5\\x41\\xa7\\xca\\x85\\x34\\xbe\\xc1\\x1d\\xbd\\xf0\\xb0\\x45\\x9a\\x8a\\x7d\\x9e\\xb3\\x9b\\xc4\\x84\\xbc\\x99\\x95\\x78\\x3d\\xf0\\xac\\x7b\\xb0\\x3b\\x6e\\x22\\x3e\\xd2\\x76\\xe8\\x96\\xae\\x6d\\xd7\\x7d\\xfd\\xfd\\x60\\x4d\\x68\\xee\\x83\\x52\\x5b\\x7b\\xc3\\x9a\\xb9\\x05\\xee\\xf7\\xd5\\x80\\x49\\x4a\\xd8\\xd4\\x1e\\x61\\x80\\x51\\x29\\x07\\xfa\\x83\\x3f\\xed\\xef\\xe2\\x63\\x4d\\x20\\x83\\x68\\xc1\\x1c\\xc5\\x3d\\xa5\\x14\\xd8\\x10\\x21\\xab\\x34\\xf5\\x52\\x2b\\xcb\\x80\\x21\\xba\\x07\\xb5\\x31\\xd5\\x36\\xca\\xf3\\xcd\\x85\\xf3\\x84\\x30\\x58\\x00\\x7a\\xaa\\x64\\xcc\\xc7\\x62\\xa9\\x25\\x18\\x50\\xc7\\xda\\x08\\x3b\\x71\\x60\\x6f\\x10\\x36\\xa7\\x14\\xe3\\xe8\\x9d\\x02\\x81\\x97\\xcc\\x12\\x1e\\x2f\\xc9\\x15\\x4d\\x99\\x74\\x19\\x21\\xb3\\x88\\x6b\\xba\\x0e\\x02\\x99\\x32\\xa2\\x97\\x86\\x47\\x1b\\xfc\\x5b\\xdf\\x28\\x55\\xd6\\xc3\\x2c\\x84\\x42\\xb7\\x33\\x54\\x15\\x47\\xd6\\x83\\x3f\\x80\\x01\\xe9\\x23\\x96\\xc3\\xe1\\x79\\x06\\x21\\x48\\xa9\\xd2\\x96\\xce\\x0f\\xfc\\xbf\\x7a\\xed\\x2c\\x2f\\xf2\\x00\\x40\\xcf\\x74\\xec\\xea\\xe1\\x07\\x28\\xfd\\x01\\x7d\\xb4\\xd5\\xf9\\x6d\\x0b\\xb2\\xe1\\x4b\\xfa\\xce\\x0d\\xd0\\xe1\\xd0\\x9a\\xf7\\x9b\\x89\\x1a\\x78\\x52\\x1f\\xea\\x5f\\x7f\\x13\\x08\\x98\\xb1\\x55\\xb0\\x15\\x88\\xba\\x0a\\xfa\\x28\\xe8\\x37\\xe8\\x49\\x6e\\x77\\x73\\x8b\\xb3\\x3b\\x2c\\x1b\\x08\\x8f\\xe5\\x54\\xc8\\x1a\\xba\\x61\\x2a\\xdd\\x6e\\xed\\x4c\\xc4\\xd9\\x92\\x32\\x2b\\x8b\\x38\\x0f\\x6f\\x36\\xfb\\x81\\x8a\\x7e\\xc7\\xdd\\x4c\\x86\\xac\\xd0\\x35\\xb4\\xbb\\x0b\\xe3\\x3c\\xaf\\x0e\\x42\\x3b\\x49\\x1c\\x2f\\x7c\\xdc\\x33\\x25\\x48\\xe1\\x76\\x38\\x66\\x42\\x08\\xae\\x16\\xb2\\x3c\\x15\\x91\\x0e\\x58\\x52\\xf2\\xa3\\x0c\\x50\\xcc\\xec\\x3a\\xc3\\xae\\x33\\x3f\\x03\\xfb\\xa5\\xa2\\x01\\xa9\\x97\\x46\\xf7\\x36\\x12\\x40\\xff\\x88\\xcf\\x03\\x71\\xc2\\xf9\\x05\\xec\\xf9\\x10\\xb9\\x4e\\x57\\xf1\\x20\\xbd\\x71\\x49\\x7b\\x97\\xe2\\x25\\x51\\x38\\x27\\xd3\\xd1\\x1a\\xba\\x29\\x22\\x04\\x23\\x20\\x36\\x4a\\xe9\\x92\\x40\\xe2\\xe2\\xdc\\x5a\\x05\\x62\\x3c\\x97\\xfe\\x8f\\xed\\x6f\\xf5\\x7f\\xc8\\xf7\\x23\\x9c\\xe4\\x0b\\x01\\x12\\x70\\xcf\\x57\\x87\\x50\\xee\\x7a\\x4b\\x48\\xc4\\x6a\\xbf\\x11\\xc9\\x00\\xfe\\xd3\\xd7\\xd5\\xaa\\x0c\\x57\\xde\\xfc\\xb6\\x4c\\x53\\xb7\\xe3\\x58\\xa9\\x31\\x0c\\xf1\\xff\\x1d\\x18\\x07\\x30\\xec\\x1b\\x56\\x7b\\x51\\xa0\\x1e\\x8e\\x41\\x69\\xea\\x86\\x84\\x05\\xb0\\x4d\\x5f\\xdd\\x45\\xad\\x4e\\x3c\\xa7\\xf5\\x4c\\x17\\x48\\x5f\\xaf\\xf2\\xcc\\xf2\\x7b\\x84\\x0a\\x97\\x51\\x2a\\xa7\\x9e\\xaf\\x81\\xcc\\x1d\\xf0\\x73\\x35\\x81\\x45\\xda\\xb9\\xaa\\x75\\x1d\\xe5\\xa7\\x9e\\xf2\\xdf\\x8b\\x4a\\x32\\x2e\\xb5\\x38\\xe5\\xc8\\x15\\xe9\\x05\\xa3\\x2e\\x4c\\x8c\\x75\\x85\\x24\\x22\\x9e\\x9f\\xf1\\x17\\x6e\\x14\\xe0\\x41\\x10\\x1e\\x6e\\x4f\\xcf\\x8f\\xd9\\x12\\xee\\xbb\\x28\\x99\\x74\\xa0\\x50\\x87\\x4d\\x26\\x66\\xb8\\xd5\\x8b\\x44\\x57\\xa3\\x12\\x12\\x49\\x41\\x7c\\xc0\\x9a\\x0e\\x35\\x9e\\x94\\xa2\\x65\\xa1\\xdd\\x0d\\xc1\\x18\\x05\\xa2\\x59\\x01\\x0c\\x87\\xf1\\x6a\\x32\\x33\\xef\\x4c\\x97\\x79\\x16\\xdb\\x74\\x56\\x7a\\xab\\xfe\\x11\\x42\\xb5\\xcf\\xf0\\xfd\\xb0\\xc2\\xc7\\xc0\\xce\\xca\\x7b\\x3f\\x6e\\xd4\\x92\\xd4\\xec\\xcb\\x0c\\xd1\\x4d\\x04\\xc3\\xb0\\xc0\\x89\\x4e\\xa0\\xa2\\x9d\\xbd\\x48\\x0d\\x67\\xbf\\x99\\x78\\x99\\x88\\x3d\\xe3\\x58\\x14\\xe2\\x2b\\x79\\xd5\\x72\\xa4\\xe9\\xcc\\x09\\xb1\\xeb\\x11\\x29\\x67\\x57\\x75\\x46\\x7b\\x3a\\x50\\x48\\x2b\\xe4\\x03\\x2f\\x71\\x6c\\x0f\\x9d\\x79\\x6a\\x7e\\x59\\xea\\x0c\\xae\\xce\\x8c\\x55\\x48\\x68\\xc2\\xfa\\x89\\xc5\\x53\\x1d\\xf3\\x31\\x6b\\xf8\\x7e\\x41\\xc3\\x2d\\xd9\\x62\\x32\\x4f\\x1d\\x12\\x5f\\x04\\xa8\\x57\\xd0\\x3a\\xef\\xa5\\xdb\\x13\\xc7\\x42\\x3e\\x3c\\x1d\\x4d\\xeb\\x0f\\xa0\\x14\\x21\\x8e\\x1e\\x71\\x5d\\x04\\x16\\x17\\xe8\\x85\\xaa\\x11\\x31\\x41\\x18\\x72\\xcc\\x40\\x70\\x54\\x2b\\x36\\x4f\\x16\\xe6\\x47\\x97\\x96\\xd6\\xc9\\x90\\x08\\x05\\x5b\\x4e\\xb8\\xe1\\x74\\xa6\\xbb\\xca\\xd3\\x76\\x43\\xd3\\x74\\xfe\\x41\\x99\\x9d\\xf0\\x51\\x7c\\x6a\\xd7\\xa5\\x75\\x77\\xc7\\xad\\xb7\\x85\\x94\\xfb\\x0d\\xdf\\x03\\xa6\\xa4\\xaa\\x03\\x42\\x2c\\x1e\\x3d\\x80\\x3d\\x23\\xe9\\x01\\x2b\\xf3\\x78\\x4d\\x48\\x63\\x2b\\x59\\xe1\\x33\\x6d\\x9f\\xad\\xa2\\xf4\\x91\\x15\\xe5\\xf2\\xbd\\x5b\\xdd\\x71\\x96\\x22\\x01\\x57\\x01\\x11\\xb6\\x83\\x18\\x00\\xb6\\x08\\x52\\xd0\\xad\\xf7\\x74\\xb4\\x38\\x6b\\x96\\x93\\x52\\x4b\\x9b\\xc4\\x70\\x3f\\x6b\\x3a\\xe8\\x63\\x1b\\x56\\xeb\\x68\\x0b\\x53\\xee\\xf7\\x4b\\xc5\\x71\\xd5\\x78\\x96\\x73\\xd2\\x4a\\x77\\x52\\xbf\\x73\\x32\\x0c\\x9e\\x01\\x32\\x00\\x2e\\xd0\\x33\\x08\\x33\\x3c\\x48\\x8f\\x02\\xc6\\xb4\\xf9\\x26\\x66\\x22\\xc8\\x0a\\x30\\xf2\\x01\\xa8\\x21\\x81\\x6e\\x40\\xfa\\x48\\x0f\\x0f\\x04\\xfb\\xad\\xca\\xcc\\xaa\\x5c\\x7e\\xad\\x3c\\x8c\\x3e\\x9e\\xc8\\x14\\xa6\\x39\\x03\\x23\\x4b\\xdc\\xb3\\xb8\\xfb\\xa4\\x81\\xa8\\x95\\xbd\\xb9\\x01\\xb2\\x25\\x25\\xf1\\xfb\\x9e\\x08\\x5b\\x60\\x0e\\xcd\\x69\\x0b\\x51\\x5b\\xdf\\x78\\x95\\x73\\x41\\xfd\\xfe\\xdd\\xfb\\x40\\xba\\xcc\\x32\\x92\\x63\\x14\\xfe\\xdf\\x12\\xce\\x78\\x04\\x62\\x23\\xe1\\xd9\\xa5\\xa1\\xb7\\x6e\\x45\\x0d\\xa2\\xf0\\xfd\\x16\\x64\\xa7\\xca\\x06\\xab\\xab\\x7e\\xef\\xd0\\xc3\\x61\\x9d\\xd9\\xa7\\x64\\xad\\x8c\\xdf\\xed\\x2a\\x05\\xa0\\x19\\xa8\\x34\\xbe\\xbe\\x18\\xf5\\x93\\xd6\\x51\\x6a\\x3a\\x6d\\x6c\\xe1\\x22\\x74\\xca\\xe6\\x1a\\xb1\\xc5\\xfc\\x1a\\x8f\\x4e\\x56\\x06\\x16\\x29\\x25\\x72\\x1f\\x06\\x00\\x76\\x50\\x51\\xc3\\xb4\\xd8\\x13\\xed\\xa5\\xe5\\xad\\xd6\\x8b\\x00\\x82\\x09\\x86\\x5b\\xfb\\xdc\\x89\\xf8\\x18\\xea\\x96\\x09\\x3a\\xff\\x76\\xf7\\x1a\\xc6\\x00\\xc6\\xe3\\x4f\\x20\\x3b\\x6e\\x3b\\xef\\x84\\x43\\xb1\\x81\\x51\\xc6\\x00\\x41\\xf3\\x2e\\x36\\xf1\\xf0\\x44\\x05\\x75\\xff\\x87\\x14\\x42\\xc9\\x0a\\x92\\x57\\x3a\\x31\\x05\\x8b\\x64\\xd8\\xe7\\x10\\x1c\\x5b\\x9e\\x5a\\xad\\x32\\x88\\x1d\\x12\\x7b\\xea\\x84\\xeb\\x3c\\x7e\\x3a\\xbe\\x40\\xfb\\xb4\\x43\\xb2\\xd6\\x20\\xc4\\x5c\\x7a\\x38\\xe2\\x8a\\xd8\\xa9\\x66\\xf8\\x2d\\x82\\x6b\\x74\\x6d\\x12\\x73\\xb7\\x52\\x9d\\xa1\\x1b\\xfc\\xc8\\xcc\\xbb\\x4b\\x1f\\x77\\x40\\x88\\x52\\x91\\xf9\\xe5\\x62\\x17\\x7e\\xb2\\x42\\xa8\\x1b\\x80\\x11\\xf6\\xda\\x00\\xe8\\x53\\xf8\\xbe\\xf4\\x4c\\xf3\\x05\\x58\\x20\\x28\\x5c\\xf2\\x6a\\xe5\\xdd\\xd7\\x56\\xe1\\xd4\\x12\\x77\\xac\\x13\\xe9\\x5e\\xbf\\x92\\x4e\\xb9\\x25\\x12\\x46\\xf6\\xdf\\x33\\x05\\x02\\xf8\\xf5\\x28\\x32\\x69\\xfc\\x0e\\xf8\\x9d\\x2a\\x13\\x07\\x6c\\x0b\\x22\\x72\\x58\\x5d\\x80\\xde\\xb4\\x0e\\xe3\\x6f\\xa5\\x32\\xcc\\x6e\\x73\\xe1\\xc6\\xd4\\x94\\xa7\\x94\\xb1\\x8a\\x1e\\xa1\\x24\\x4e\\x1b\\x11\\xd7\\xf7\\xbd\\xdc\\x54\\xb6\\xb8\\xa2\\x51\\x4b\\x3c\\xe9\\x73\\x74\\x39\\xc0\\x15\\xdf\\xef\\x03\\x72\\x95\\x69\\x6f\\x8c\\xd3\\xe4\\x68\\x8b\\x9b\\x65\\xac\\x02\\x9a\\x49\\x39\\x0f\\x74\\x32\\x94\\x3a\\xb2\\xd3\\xf6\\xdf\\x74\\xfa\\x17\\x78\\x0a\\xcf\\xb8\\xbb\\xd4\\xcc\\x93\\x1c\\x67\\x01\\xf4\\xf9\\xcf\\x3e\\xcd\\xfd\\x36\\x05\\x62\\x12\\x99\\x30\\xd5\\xb4\\x71\\xf9\\x27\\xe4\\x3b\\x86\\x26\\x26\\x21\\x92\\x84\\x91\\x11\\x0c\\xfb\\x5b\\xe5\\x7c\\x5f\\xb4\\xe6\\x1a\\xd9\\xd8\\x0f\\x3d\\x2d\\x8f\\x52\\xc4\\x14\\xea\\xcc\\x14\\x72\\x3c\\xcf\\xd6\\x43\\x1c\\xa6\\x45\\x50\\xfc\\x6b\\xa7\\xa2\\x6e\\x24\\xc4\\x25\\x43\\xe8\\x9d\\xc5\\x32\\x2e\\x48\\xba\\x44\\x02\\x69\\xaa\\x61\\x3b\\xea\\xa1\\x6e\\x22\\x48\\x06\\xed\\x30\\xfa\\xcf\\x79\\xd3\\xa4\\xea\\x23\\x27\\xf6\\x3f\\x3d\\xe9\\x49\\xfb\\x1b\\x99\\xc8\\xc3\\x86\\xba\\x7f\\x16\\xcf\\xfe\\xe8\\x2b\\x64\\x9c\\x8b\\x3f\\x1f\\xf4\\x0f\\x62\\x79\\x98\\xc6\\x7b\\x82\\x5e\\x80\\x8a\\x82\\xd6\\x26\\x5e\\xbc\\xb0\\x84\\x39\\x6b\\xd0\\x72\\x35\\x70\\x48\\xd6\\x04\\x98\\xe8\\x1e\\xbb\\x93\\x60\\x3e\\x47\\x97\\xbc\\x0c\\x78\\x21\\xce\\xee\\xb8\\xf7\\x34\\x70\\xd2\\xa1\\x55\\x4f\\xe0\\x0c\\x93\\x77\\xa1\\x94\\x67\\x14\\x4d\\x8a\\x41\\x37\\x9a\\x87\\x19\\xa6\\xec\\x95\\xd9\\x3c\\x6b\\xbe\\x1d\\x1c\\x39\\x86\\xf9\\xd5\\x1f\\x05\\xf6\\x72\\xdf\\xa0\\xa7\\x90\\xeb\\x25\\xac\\xe3\\xcc\\x63\\x2a\\x3f\\x82\\x6e\\x5b\\x18\\xbe\\x4f\\x04\\x5a\\xbc\\x32\\xda\\x24\\x2f\\x21\\xcb\\xa4\\x51\\x40\\xf4\\xfe\\x8c\\x0b\\xda\\x82\\x9b\\xa4\\x52\\x29\\xf9\\xbd\\x73\\x49\\x23\\xca\\x6e\\xb1\\xd9\\xdd\\x26\\x1a\\xd4\\xb3\\xac\\xb7\\xee\\x48\\x1d\\x5b\\xfa\\x5b\\x0f\\x49\\x03\\x44\\x2c\\xc0\\x41\\x61\\x43\\x64\\x11\\x82\\xe8\\xd9\\x8a\\xfc\\xd4\\xf8\\xe4\\x12\\xc1\\x0f\\x12\\x80\\x58\\xc7\\xfc\\xc1\\xca\\xa1\\x20\\x90\\x9a\\x1f\\x4d\\x54\\x1c\\x2d\\xd9\\xfa\\x2b\\x34\\x52\\x3e\\xc3\\x77\\x06\\xb7\\x5c\\xa5\\xb4\\xd6\\xa5\\x1a\\xc2\\x89\\x5c\\x74\\x93\\xe5\\x37\\xd9\\x92\\x76\\x94\\xdb\\x1a\\x3a\\xb0\\x17\\xd2\\x8a\\xb6\\x11\\x5c\\xbd\\x66\\x11\\xf1\\x70\\xd9\\x73\\x5c\\x5e\\x25\\xe8\\xbc\\x13\\x5e\\x73\\x3b\\x3f\\x18\\x4c\\x83\\x4d\\xf6\\x29\\x8e\\x93\\x51\\x35\\x89\\xa1\\x0e\\xbd\\xcd\\xcc\\x98\\x38\\x0b\\xf8\\x2c\\x3f\\x62\\x96\\x82\\xa0\\x4f\\x30\\xaf\\x9b\\x7a\\x6b\\x9c\\x51\\xa6\\xf2\\x20\\xd3\\xd7\\xef\\x1f\\x8c\\xea\\xbd\\xea\\x26\\x9a\\x36\\x45\\x1d\\x87\\x89\\xb7\\xdc\\x0a\\xc1\\x81\\xb5\\xc8\\xe3\\xa1\\xdb\\x7d\\xb8\\x52\\xcb\\x3a\\x4f\\x87\\x4a\\xa3\\x83\\xe8\\x64\\x76\\x85\\xe0\\xca\\xc2\\xb5\\xf7\\x9a\\x28\\x3c\\x79\\xe0\\x5a\\x7c\\x27\\x6e\\x3d\\x80\\x41\\xd6\\x6d\\x5a\\xb7\\x74\\x86\\x36\\xfe\\xbd\\x2c\\x24\\x6d\\x9e\\x34\\x63\\x85\\xcd\\x9a\\x90\\x58\\x2e\\x57\\xf1\\x5c\\xfb\\x06\\xdb\\xdd\\x47\\xbe\\x82\\x15\\x73\\x32\\x11\\x17\\xc1\\xe7\\x60\\xef\\x76\\x71\\x5c\\xa7\\x3c\\x53\\x24\\xfc\\x0e\\xe6\\x8d\\xcd\\xdc\\x87\\x61\\xd4\\x4b\\x14\\xc0\\xef\\xc7\\x6b\\x48\\x5e\\x5f\\xd3\\xa3\\x96\\xdc\\x25\\xcd\\x4a\\x67\\x2f\\xc8\\x51\\xee\\xa2\\x8b\\x4b\\x57\\xc5\\xf0\\x73\\xe9\\xf4\\x9f\\xc2\\x94\\xeb\\x7b\\x00\\x6a\\xd6\\x8d\\x2c\\x57\\xc8\\xb3\\xe6\\x1b\\x88\\xe1\\xed\\x10\\x72\\x79\\xde\\xe2\\x2a\\xa4\\xea\\x2e\\x62\\xae\\x84\\xef\\xa9\\xba\\xc9\\x09\\x9c\\x92\\x97\\x56\\x15\\x2f\\x5a\\x5f\\xa6\\x1d\\xff\\x90\\x4e\\x18\\xa4\\xe6\\x35\\x3b\\x0c\\xae\\x60\\xf5\\x2a\\xdd\\x0c\\xcd\\xe5\\x1d\\x39\\x10\\x8a\\x77\\x27\\xff\\x0e\\xaf\\xde\\x9a\\x2b\\xf9\\x88\\x27\\xaf\\x28\\xb2\\xb0\\x5e\\x82\\x96\\x8d\\xfa\\xa7\\xa6\\xb0\\x08\\xf2\\xd2\\x0f\\x91\\xef\\xb2\\x72\\xfb\\x17\\x9b\\x60\\xa1\\xef\\xfe\\x63\\x8c\\x05\\xab\\x8d\\x8f\\xbc\\xac\\x53\\x06\\xa2\\x51\\x3c\\xd0\\x00\\x61\\x92\\xa6\\x41\\x6d\\x71\\x2d\\xee\\xf6\\x60\\x4a\\x9b\\x67\\x08\\x11\\x0d\\xde\\xd9\\x60\\x3e\\x6a\\xed\\x8c\\x7f\\x49\\xbe\\xaf\\x1e\\x54\\x20\\xad\\xc8\\x56\\x37\\x94\\xf3\\xe0\\x03\\x53\\x81\\xbf\\x98\\x21\\x47\\x30\\x87\\xd3\\x41\\x79\\xf9\\x56\\x77\\x9f\\x3e\\xd5\\x53\\xd6\\x04\\xf0\\x93\\x78\\x27\\x64\\x9b\\x53\\x15\\xff\\x3e\\xa5\\xcc\\x5b\\x90\\xba\\x63\\x54\\x78\\xe4\\x8f\\x50\\xbc\\x53\\x1b\\x28\\x3c\\xe1\\xd8\\x49\\x6f\\x77\\xc5\\x59\\x38\\x98\\x95\\xe3\\x0f\\x10\\x59\\x43\\x74\\xf0\\x42\\xc5\\xb4\\x9e\\xd5\\x25\\xca\\xc6\\xba\\x0b\\x34\\x4b\\x59\\x06\\x26\\x65\\x24\\xf7\\x2f\\xbc\\x03\\xf2\\x68\\x89\\xef\\x97\\xa7\\xb3\\x5a\\x8d\\xf5\\xbc\\x05\\xe8\\xca\\x79\\x37\\x68\\xbc\\xae\\x9d\\xe5\\x2f\\xcc\\x07\\xde\\xda\\x97\\x09\\x2c\\x1b\\x28\\x9c\\x9e\\x60\\xca\\x08\\x0b\\x62\\x08\\xde\\x61\\x5d\\x49\\x32\\x7d\\xe6\\x30\\x8f\\x23\\xed\\x15\\xd5\\x6e\\xdc\\x0e\\x4b\\x0e\\x6d\\x89\\xb5\\x09\\x82\\x23\\x55\\xa1\\xf7\\x4e\\x1b\\x93\\x43\\xc7\\x32\\x56\\xf9\\x5d\\x6a\\x4d\\x48\\x01\\x91\\xa7\\xb1\\xf2\\x26\\xa7\\xb5\\xb2\\xd6\\xd0\\xbf\\x8d\\x02\\x6a\\x2b\\x83\\xba\\x4a\\xf3\\x0d\\xbc\\x7f\\xba\\xa3\\x2d\\x62\\x74\\xd5\\x54\\x89\\xfc\\x34\\x49\\xf9\\xf1\\xe9\\xac\\x4f\\xb1\\x1d\\xc7\\xc4\\x6b\\x43\\x2d\\xb1\\x30\\x9a\\x62\\x78\\x2c\\x7b\\x9f\\x27\\xd8\\x2d\\xd8\\x91\\xc1\\xd1\\x89\\xc6\\x96\\x3d\\xa4\\x8a\\x96\\x8c\\x89\\x5b\\x83\\x3b\\x40\\x58\\x5e\\xe9\\x8d\\xe0\\x5e\\xeb\\x32\\x80\\x79\\x70\\x80\\xfb\\xdf\\x35\\x9a\\xec\\x33\\x99\\x12\\x63\\x11\\xa7\\x71\\x4d\\x08\\xb7\\x36\\xab\\x1c\\x01\\xc9\\xca\\xe4\\x02\\xe9\\x37\\xf6\\x24\\xa6\\xec\\x5a\\xfa\\x8a\\x5b\\xcf\\x45\\x3c\\xda\\xc9\\x3b\\x88\\xbc\\x12\\xb7\\xfc\\xfe\\x7c\\x92\\x85\\x8b\\x07\\xdf\\x8f\\xb7\\xcf\\xa8\\xbc\\x16\\x34\\xa4\\x25\\xaf\\xd2\\xb3\\x7c\\xd3\\x49\\xa5\\x56\\xa2\\xd4\\x3c\\x00\\x23\\xbb\\xf6\\x42\\x23\\x64\\x59\\x4e\\xa4\\xaf\\x2b\\x53\\x63\\xb3\\xb3\\x3d\\x53\\x2e\\xed\\x74\\xca\\xe2\\xf9\\x48\\xc3\\xae\\x66\\x95\\x8f\\x82\\xcc\\xc4\\xbf\\x22\\x51\\xbc\\xd9\\xe8\\x27\\x4d\\x5c\\xf7\\x58\\x9b\\xfd\\x33\\x57\\xaf\\x93\\xa4\\xd1\\xd8\\x56\\xb2\\xb2\\xee\\x1e\\xfa\\x20\\x7e\\x1e\\x24\\xce\\xf9\\x4b\\x4f\\xc7\\xef\\x37\\x1a\\x32\\x79\\x30\\xa0\\xf4\\xab\\xf4\\x0e\\x0d\\xa3\\x09\\x3f\\x53\\x16\\xb9\\x8a\\x90\\xaa\\xef\\x2a\\x9a\\xa9\\x14\\x2a\\xcc\\x90\\x7e\\xce\\x7a\\xc6\\x97\\x1e\\xba\\xa4\\xcd\\x2f\\x37\\xd4\\xd2\\xd4\\x88\\x3f\\x67\\xf8\\xc9\\xc9\\x9d\\x0d\\xed\\x9f\\xc1\\x9f\\x75\\x59\\x60\\xa7\\x8f\\x17\\x49\\xd9\\xfb\\x90\\xce\\xc5\\x40\\x9b\\xe1\\x8a\\x0e\\x61\\xa1\\x9a\\x2a\\xc4\\x14\\xbb\\xc3\\x28\\x4c\\x3e\\x64\\x15\\x66\\x6a\\x43\\xf5\\x53\\x3b\\x31\\xb7\\x36\\x33\\x77\\xbd\\x66\\x88\\xdd\\xe0\\xb1\\x4c\\x2c\\x21\\x88\\xbe\\xdd\\xeb\\x26\\x2b\\x3d\\xf6\\x95\\xf3\\xa2\\x65\\x37\\x33\\x5a\\x3e\\xac\\x7a\\xaa\\x2a\\x59\\x43\\xd3\\x3d\\xbd\\x67\\xa6\\xf5\\x75\\x84\\x78\\x51\\x5f\\x29\\x3f\\xae\\x91\\x5b\\x6e\\x68\\x11\\xed\\x60\\x4e\\xa5\\xf7\\x06\\xb9\\x0d\\x68\\xa1\\xf0\\x06\\xe2\\x6d\\xdd\\x67\\xf9\\xae\\xfe\\xd9\\x5a\\xbf\\x80\\xbb\\x97\\x7b\\x25\\x54\\x01\\xb7\\x08\\xfb\\x15\\x6a\\x4c\\x73\\x85\\x5e\\x74\\x09\\x97\\x0e\\x08\\xde\\x3d\\x7d\\x1a\\x97\\x92\\x90\\xe3\\xdd\\x26\\x9e\\xeb\\xee\\xb6\\x6c\\xa1\\x15\\xc1\\xd6\\x91\\x47\\x12\\xcb\\x55\\x8f\\x2e\\xf7\\xae\\x1f\\xb3\\x60\\xdb\\xd4\\x4f\\xa1\\xef\\x53\\xb2\\xef\\x6b\\x59\\x8c\\x1a\\x4e\\xaf\\x67\\x8f\\x54\\xb5\\x63\\x03\\xd9\\x3d\\xfa\\xe8\\x61\\x4c\\xb2\\x1d\\x02\\xd8\\x0a\\xf8\\x30\\xe9\\x2c\\xfe\\x76\\x97\\xb6\\x68\\xe1\\x08\\xe7\\x6a\\x37\\xc3\\xb7\\x85\\x74\\x12\\x5f\\xe9\\x31\\xc2\\xb5\\x9c\\x33\\x3e\\x9d\\x72\\x31\\xc4\\x68\\xc7\\x4a\\x9a\\x4d\\xee\\x68\\x01\\x54\\xca\\xba\\x19\\x52\\x2c\\x80\\x64\\xab\\x17\\x9a\\xf5\\x9c\\xae\\x95\\xe4\\x96\\x8c\\x95\\x1d\\xc5\\x46\\x7f\\xeb\\x5f\\x99\\x55\\x63\\xdd\\x7f\\x78\\xc0\\x4a\\x70\\x0d\\xb0\\x92\\x7f\\xaa\\x76\\xa1\\x02\\x0d\\x05\\xbf\\x0b\\x06\\x1e\\x7f\\xc2\\x61\\xb6\\x7a\\xea\\x02\\xc5\\xb2\\xbd\\x6f\\x8a\\x90\\x28\\x4e\\xd7\\x55\\xfa\\x8a\\xc8\\xe7\\x9f\\x47\\x5f\\xdc\\x9f\\x26\\xdc\\x63\\xca\\x27\\xa8\\x0f\\xb9\\xf4\\xb0\\xb8\\x72\\xcf\\xe0\\x86\\xcf\\x6c\\x7c\\x8e\\x6a\\xf4\\xf8\\x44\\x43\\x3e\\x01\\xd7\\x08\\xc8\\x90\\x0f\\x4d\\x40\\xe6\\x67\\x0b\\xaf\\x70\\x6a\\xcb\\x23\\xb0\\x29\\x30\\x91\\x2e\\x5c\\x23\\x7c\\x1d\\x98\\xb4\\x28\\x34\\x0b\\x97\\xfb\\x6e\\x65\\xc8\\x88\\xe3\\xbc\\x73\\xe5\\x98\\x34\\x29\\x8c\\xd8\\x81\\x27\\x22\\x06\\xe2\\x8a\\xc2\\xc5\\xb4\\xf6\\x1c\\xfa\\xf7\\xd6\\x32\\xf9\\x31\\x68\\xb2\\x57\\x31\\x70\\x7b\\xbe\\x50\\xb6\\x48\\xf0\\xaa\\x61\\xbf\\xf3\\x24\\xb9\\x82\\x5e\\xa0\\xe3\\x94\\xb5\\x9a\\x56\\x36\\x89\\x16\\xd1\\x74\\x12\\x67\\x37\\x8d\\x5d\\x3d\\x55\\xda\\xca\\x7d\\x70\\x5e\\x71\\xa0\\x55\\x13\\x80\\xe3\\x38\\xae\\x1a\\x80\\x07\\x13\\xcc\\x25\\xad\\xfa\\x2d\\xa5\\x4d\\xb1\\xb9\\xee\\xc1\\x86\\xc3\\xa0\\x79\\xa5\\xb7\\x0a\\x1f\\x5a\\xe7\\x8e\\x7b\\x10\\x0f\\x10\\xe1\\x4b\\xd6\\x42\\xeb\\xb7\\x95\\x1d\\xf2\\x2b\\xa3\\x22\\x37\\xa5\\x0f\\xf2\\xe1\\x91\\x84\\xcb\\xa9\\xd0\\x60\\xac\\xa2\\xdb\\xd0\\xcc\\xcb\\xc7\\xf4\\x0c\\x59\\x8a\\xc0\\x76\\x89\\x35\\xb5\\x02\\x2c\\x0a\\x70\\x0c\\xb3\\x73\\xad\\xfd\\x42\\x44\\x4b\\x31\\xc8\\x94\\x05\\x70\\xdd\\x6b\\x8e\\xb4\\x36\\xf9\\x6a\\xd4\\x4e\\xee\\x54\\x2a\\x3b\\x95\\x85\\x5f\\x43\\xdd\\x94\\x9b\\x9d\\x3c\\x1d\\x8f\\x68\\x80\\xa2\\xdc\\x31\\x98\\x6b\\x84\\x6d\\x81\\xdf\\xb5\\xae\\xe0\\x00\\xf4\\xb1\\xca\\x5c\\x8f\\x66\\xa8\\x0f\\xa3\\x04\\xe2\\x61\\x1b\\x21\\x67\\x0e\\x14\\xe4\\x56\\x5c\\x7e\\x0d\\xd5\\x86\\x61\\x38\\xc0\\x85\\x89\\xea\\x89\\x68\\x74\\xc0\\xa8\\xc0\\xa1\\x59\\x6b\\xb6\\x06\\xb3\\x23\\xb4\\xb9\\x85\\xf1\\xce\\x69\\xd7\\x29\\x47\\xec\\xe2\\x4a\\x8f\\x83\\xd9\\x65\\x56\\x66\\x31\\xd1\\x10\\x23\\x7d\\x45\\xad\\xd8\\x15\\x8f\\x99\\x14\\x61\\x34\\xc3\\x90\\xf4\\xf0\\x49\\x88\\xa8\\xb1\\x4e\\x7d\\x39\\xbe\\xf9\\x61\\x62\\x59\\xff\\xe8\\x45\\xbb\\xf8\\xcb\\xad\\x15\\x4c\\x7b\\xd5\\x42\\xbc\\x28\\x87\\x14\\x4e\\x8c\\xfb\\xc0\\x62\\x3d\\x88\\x13\\x51\\x35\\x25\\x0d\\xf4\\xd9\\xee\\xe5\\xf3\\xee\\x84\\xf7\\x58\\x4d\\x1c\\x4f\\x7a\\x0b\\x8f\\x82\\xae\\x8d\\x19\\x9b\\x33\\xfd\\xd3\\x14\\x86\\x0e\\x73\\x9c\\x46\\xce\\x1e\\x20\\x7f\\xa4\\xb7\\x86\\xbd\\x75\\x57\\x34\\xc7\\x98\\x54\\x41\\x73\\x96\\x6f\\xbf\\x1d\\x2a\\x81\\xad\\x3b\\x8c\\x7a\\xbb\\xe6\\x36\\x02\\x2b\\x74\\x09\\xb7\\xc2\\x17\\xc0\\xe5\\x57\\x76\\x5d\\x6c\\x76\\xcf\\x49\\xdc\\x72\\x3c\\x15\\xee\\xea\\xe4\\xb5\\x29\\x50\\x14\\x1d\\x06\\xd4\\x06\\xe1\\xe8\\x0c\\xab\\x1a\\x16\\x1d\\xbf\\xec\\x41\\x5e\\xa4\\xcc\\xa4\\x29\\x34\\xeb\\x52\\x85\\xa2\\xcc\\x6d\\x26\\xc2\\x76\\xfb\\xa4\\x61\\x8d\\x65\\x8d\\xed\\x26\\x69\\x39\\xd5\\xe6\\x8a\\x8c\\xd7\\x29\\xe5\\xb2\\x03\\x75\\xeb\\x74\\x44\\xfe\\x1d\\xc4\\x02\\x8f\\x5e\\x2d\\x1f\\x4a\\xe0\\x51\\x59\\x95\\x1c\\x80\\x70\\x8f\\x51\\xe2\\x12\\xbb\\x54\\x87\\x46\\x1c\\xf1\\xf6\\x4c\\xcd\\x99\\xb8\\xe1\\xb2\\xc2\\x5e\\xc4\\x1a\\xe3\\x88\\x0b\\x02\\x7f\\xdd\\xde\\xa0\\x1c\\x5b\\x0d\\xd6\\xaf\\xa1\\x7e\\x48\\x17\\xc1\\xd4\\x65\\xd2\\xff\\x9f\\x2a\\xe1\\xf0\\xf4\\x4c\\xe0\\x2f\\x99\\xb4\\x72\\x51\\x87\\xd9\\x2b\\x57\\xd2\\x2c\\x5c\\xbf\\x76\\xa9\\xb4\\x38\\xaf\\x4c\\xd9\\xd6\\x1e\\x57\\x9e\\x43\\xc6\\x8f\\xb0\\xdc\\xa5\\xaf\\x1d\\xf9\\x00\\x9a\\x32\\x78\\x75\\x59\\x1c\\x55\\x22\\xe8\\x65\\xc3\\x14\\x41\\x4b\\x92\\xdb\\x14\\x26\\x87\\x76\\xdb\\x8f\\x12\\x53\\xf3\\x03\\x92\\x54\\xf4\\x60\\x12\\xbb\\xed\\x62\\x16\\x4d\\x7f\\x9f\\x0e\\xc6\\xc5\\x29\\xd6\\x9d\\x99\\x11\\xfe\\xea\\x13\\x5d\\x3d\\x04\\x91\\xa8\\x04\\x96\\x77\\x63\\x57\\x69\\x9c\\x1d\\x07\\xfb\\x9c\\x6a\\xa2\\x3f\\xec\\xdc\\xb7\\x60\\x1b\\x9e\\xcf\\x1c\\xbd\\x51\\x5e\\x08\\x40\\x07\\x92\\x95\\x1b\\xc6\\x0a\\xac\\xac\\xfa\\x7e\\x7d\\xae\\x21\\x0d\\x3c\\x08\\xca\\xa6\\xa7\\x24\\x23\\xfe\\x7f\\x82\\x2c\\x53\\x83\\xbd\\xd9\\x01\\xdb\\xc6\\xb4\\x69\\x94\\x32\\x33\\x3d\\xbf\\x46\\x1a\\xb8\\x7e\\xe0\\xc9\\xa0\\xa6\\x23\\xc2\\xf8\\xd9\\x0e\\x76\\xc9\\x3d\\x41\\x86\\xc2\\x43\\xd9\\x17\\x83\\xe3\\x62\\xe9\\xaa\\x9d\\x28\\x6b\\xf5\\x2c\\x86\\x66\\xcf\\x6b\\xfa\\xe3\\x53\\x68\\xb4\\xa6\\x98\\x08\\x64\\xbb\\x3e\\xaf\\xb3\\x3a\\x83\\x50\\xd7\\x14\\xd0\\xe9\\x65\\x97\\xe4\\xe9\\x11\\xa8\\x8c\\x3d\\x83\\xe9\\xd8\\xe6\\x53\\xa6\\x6c\\xe9\\x70\\xd1\\x35\\xbd\\x6e\\xa6\\x50\\xa1\\xee\\xc9\\xc2\\xc9\\x21\\x0a\\xe1\\x8b\\xa7\\xe1\\xfc\\x61\\x07\\xae\\x5b\\x08\\x03\\xf2\\x24\\x80\\x5a\\x28\\x2d\\xe9\\x5b\\xb3\\x6f\\x60\\x55\\xbb\\x94\\x9b\\x6e\\x75\\x8e\\x29\\xbf\\x5f\\x10\\x65\\x35\\xad\\x6e\\x0c\\xcc\\x45\\x15\\x5a\\x36\\x3b\\x3d\\x40\\x62\\x63\\xa4\\xdc\\xde\\x00\\xdc\\xde\\x0d\\x8c\\xd3\\x50\\xf1\\x33\\x8a\\x3c\\x0f\\xc8\\xc6\\xd2\\x7f\\xcb\\x7d\\x2a\\x88\\x7d\\xf7\\x88\\x7e\\x7f\\xd2\\x16\\x72\\x93\\x5e\\xc6\\xbc\\x70\\x0b\\x02\\xf4\\x22\\x5f\\xcc\\xed\\x3d\\x3e\\x21\\x6a\\x2c\\x52\\x4a\\xb4\\x3b\\x51\\x0a\\xa4\\x5f\\x41\\x61\\xc2\\xc9\\xe8\\xb7\\x08\\x7c\\xff\\xac\\xae\\x2c\\xff\\xb6\\x72\\xf6\\x41\\x6d\\x6b\\xda\\xd6\\xcb\\x4c\\xf4\\x7e\\xf3\\x2b\\x9e\\xe1\\x1e\\x63\\x0f\\x08\\xed\\x20\\x65\\xb5\\x8d\\x56\\x5c\\x6a\\xcc\\x9d\\x29\\xfb\\x24\\x71\\x15\\x1f\\x51\\x14\\xf1\\x01\\x0d\\x2a\\x55\\x7e\\x37\\x5b\\x5f\\x5d\\xa3\\x01\\x3a\\x29\\x3d\\x80\\x4a\\xd7\\xbd\\xb0\\x0f\\xad\\xfc\\x66\\x62\\x49\\x68\\x84\\x73\\xd3\\xf9\\xf1\\x41\\xaf\\x32\\x96\\x4b\\x83\\xba\\xda\\xe6\\xc9\\xfb\\xe5\\xf8\\x41\\x68\\xdd\\x12\\x4d\\x46\\xc6\\x72\\xb8\\x4d\\x5c\\x85\\x1c\\xa8\\xce\\x7d\\x32\\xe5\\x18\\xa4\\x11\\xb7\\x93\\x7d\\x75\\xca\\xd0\\x64\\x06\\x6d\\xee\\x14\\x68\\xe0\\x37\\xd5\\x0a\\x3a\\x50\\x66\\x19\\x3c\\x9b\\xd8\\xc4\\x80\\x18\\xed\\x9b\\x96\\x79\\x46\\xa5\\x63\\xca\\xfe\\x26\\x4b\\xc9\\xb8\\x15\\xec\\x5e\\xb2\\xa7\\x9d\\x7a\\xbf\\xcc\\xeb\\x6b\\x3d\\x04\\x9c\\x47\\xbd\\x80\\x50\\x05\\x34\\x8f\\xf9\\x94\\x9a\\xb4\\xa9\\x01\\x2d\\x71\\xfa\\x63\\x75\\x61\\x5e\\x78\\x79\\xbb\\xd4\\x5f\\x2e\\x99\\x0f\\x51\\x3d\\x29\\x06\\x99\\x34\\x4f\\xf9\\x16\\x87\\x70\\xca\\x5f\\x0b\\x36\\x06\\xd0\\x23\\xf8\\x3c\\x09\\x96\\x1d\\xad\\x0b\\x9f\\xf0\\xcd\\x98\\xe8\\x96\\x7a\\xf3\\x71\\xfc\\x92\\xed\\xf2\\xa7\\xa0\\x44\\xfa\\xa2\\x0d\\x15\\x92\\x96\\x5c\\xe8\\xc3\\xa6\\x28\\xf2\\xbf\\xc3\\x59\\x98\\xb3\\x78\\xf5\\xb1\\x4b\\x95\\x0b\\x5a\\xbd\\x1a\\x3c\\xfd\\x90\\xc6\\x80\\xa3\\xa3\\x25\\xbf\\xcd\\xd8\\x54\\x69\\x22\\x32\\x81\\x77\\x83\\xa4\\x67\\x8b\\x16\\xdb\\xc7\\x88\\x2a\\xde\\xa0\\x68\\xb8\\xdc\\xe6\\x0f\\x6f\\x34\\x17\\xdd\\x27\\x25\\x61\\xa5\\xe3\\xb7\\xe1\\xfe\\xf7\\x92\\x58\\x01\\x07\\xea\\xc0\\x23\\x09\\xa2\\xbc\\x5a\\xcf\\x12\\x6f\\xbd\\xfc\\x6a\\x65\\x71\\x16\\x02\\x3f\\x4c\\x56\\x89\\xf9\\xc6\\x99\\xd9\\x4c\\xa5\\x70\\xef\\xcd\\x8f\\x39\\x76\\xaf\\x1f\\xf7\\xa7\\x7b\\x07\\x4d\\xb9\\x89\\xaf\\x26\\x26\\xd8\\xbc\\xcb\\xce\\x92\\x3c\\xdc\\x0b\\x12\\x54\\x61\\xa8\\x41\\x9a\\x75\\x2a\\x3f\\xab\\xf0\\xe5\\x1b\\xa6\\x43\\xdd\\x73\\x14\\x44\\x0b\\x54\\x0d\\x31\\xd3\\xa8\\xd0\\x3e\\xfc\\x54\\x19\\x32\\x6e\\x75\\x31\\x91\\x07\\xf7\\xf2\\xdb\\x1a\\x7a\\x02\\x43\\xf2\\x49\\x8c\\x57\\xce\\x31\\x1c\\x00\\xb2\\x08\\xf8\\xec\\x00\\xa3\\xbc\\x96\\xab\\x0f\\xf4\\xd8\\xc9\\xec\\x32\\x72\\x73\\x24\\xef\\x2c\\x00\\x3f\\x6b\\xbb\\xe3\\x0c\\xff\\xce\\xca\\xad\\x96\\x98\\x63\\xca\\x01\\x44\\x69\\x83\\x10\\x92\\x0b\\xae\\xfa\\x71\\x20\\x11\\x5e\\xaf\\x7a\\x92\\x63\\x4e\\x11\\xdb\\x08\\x5c\\x3c\\x2e\\xb6\\xf0\\xf7\\x96\\x5e\\xed\\xd5\\x27\\x7b\\xea\\xea\\x8c\\x8f\\xf8\\x9f\\xcc\\xff\\x85\\x22\\x6e\\x1a\\x47\\x4d\\x64\\xd6\\xee\\x74\\x7d\\x83\\x59\\x34\\xba\\x1d\\x7e\\x20\\x0c\\xa0\\x91\\x38\\x3b\\xd2\\x98\\xb0\\xe5\\x2d\\x6d\\x62\\x01\\x35\\x16\\x77\\x4a\\x3c\\xaa\\x2e\\xde\\xe1\\x32\\xbd\\x68\\x9e\\xed\\x8a\\xa5\\xa3\\xc1\\xb1\\xe2\\xaa\\xa2\\x68\\x4f\\x94\\x2e\\x21\\x55\\xfd\\xc3\\xd2\\xd2\\xf9\\x6e\\xd1\\x81\\x02\\x88\\x7a\\x47\\x63\\x46\\x61\\xee\\x3c\\x44\\x6a\\xc9\\x76\\x5a\\xea\\x67\\x78\\x80\\x5b\\x7d\\x15\\xb2\\x73\\x65\\xbd\\x81\\x86\\xaa\\xc0\\x0c\\x26\\x26\\x9c\\x25\\x2c\\x50\\x82\\xa4\\x21\\x2e\\x9a\\x0a\\xcf\\x77\\xbc\\x4b\\x5c\\xeb\\x77\\xdb\\xf0\\x2a\\xe5\\x02\\x99\\x05\\xa8\\xeb\\x15\\xa2\\x68\\x58\\xb9\\x74\\xe8\\xdc\\x29\\x06\\xa6\\x33\\xee\\x26\\x66\\x84\\xa3\\xcd\\x8c\\x89\\xe6\\xba\\x5e\\x4a\\x85\\x90\\x6a\\xfa\\x71\\x79\\x18\\x90\\x3e\\x71\\xb1\\xd8\\x0b\\xdb\\xb0\\x03\\x50\\x2b\\x18\\xff\\x75\\x41\\x90\\xa7\\x8b\\x09\\x6e\\x9a\\x6b\\xe8\\x36\\xaa\\xab\\xad\\x1a\\xbc\\x3a\\x9d\\x3c\\x38\\x0c\\x35\\xa9\\x4e\\x06\\x0b\\xe5\\x9d\\x35\\x96\\x82\\xd0\\xa0\\xa2\\x79\\x94\\xdd\\x14\\x83\\xdf\\xb3\\x7c\\x2b\\xa4\\xa4\\x2a\\x85\\x8a\\xf3\\xbf\\x6d\\x37\\x31\\xe7\\x74\\x9c\\x7c\\x6c\\x9b\\x5e\\x14\\x29\\xb5\\xdb\\xe7\\x77\\xb6\\x99\\x37\\xe0\\xeb\\xf0\\x2c\\x69\\x40\\x09\\xb1\\x69\\x19\\xc3\\x5f\\x06\\x00\\x4d\\xed\\xaa\\x2a\\xa9\\x15\\x94\\x28\\xe7\\x32\\x33\\x29\\xcd\\x2c\\x95\\x8e\\xa7\\xc6\\xca\\xe8\\x06\\x29\\xb0\\x8d\\x2e\\x2b\\x0d\\xb6\\x11\\xb2\\x10\\x5b\\xf6\\x1e\\xb0\\x43\\xe2\\x78\\x13\\x90\\x1d\\xac\\x74\\x0a\\x62\\xb4\\x81\\xbe\\x13\\x33\\x51\\x78\\xdf\\x61\\x1e\\x96\\xdf\\xff\\xe9\\xf0\\x39\\xd5\\xc1\\x45\\x0e\\xfb\\x33\\x69\\x8e\\x4d\\x70\\x0f\\xf3\\xed\\x52\\x5f\\xb4\\xdc\\xce\\x23\\x88\\xb8\\x19\\x5c\\x08\\x79\\xa8\\xd4\\xc3\\x48\\x36\\x56\\xd5\\x01\\xa1\\x3c\\x36\\xc0\\x6c\\xc4\\x5e\\xff\\xf4\\xcf\\x11\\x37\\x3a\\x6e\\x8e\\xe7\\xd0\\xf0\\xdf\\x26\\x8e\\x79\\xb8\\x93\\xe3\\x68\\x65\\x33\\xe1\\x7e\\xf2\\x9b\\xcf\\x5b\\x5c\\x8e\\x99\\x49\\x6f\\xa4\\x42\\x73\\x36\\xcb\\x0e\\xf2\\x74\\x48\\xbe\\xb0\\x5f\\x84\\x98\\x83\\xa7\\x11\\x13\\x4d\\x88\\x93\\x8b\\x1e\\x2c\\x2c\\x5d\\x1d\\x74\\x28\\x79\\x64\\xc7\\x83\\x5b\\x85\\x05\\x27\\xb4\\xfc\\x54\\xd6\\x50\\x9c\\x9b\\x1c\\x7c\\x89\\x13\\x7c\\xff\\xd6\\x47\\xc9\\x49\\x40\\xe8\\xef\\x53\\xdb\\x51\\xde\\xa1\\xac\\xb6\\x95\\xc3\\xb0\\x69\\x8e\\x98\\x54\\xd1\\x71\\xb2\\x9f\\x00\\x1f\\xa2\\xe8\\xf6\\x12\\xec\\xed\\xa6\\xba\\x8e\\x0b\\x1d\\xa0\\xaf\\xbd\\x21\\x3b\\xbc\\x7a\\x4f\\x00\\xe3\\x08\\x65\\xd5\\xd0\\x05\\xde\\x94\\xb7\\x81\\x3e\\xa0\\xd4\\xab\\x59\\x40\\xf0\\x21\\x40\\x9d\\xb5\\xba\\x87\\x34\\xd9\\xea\\x12\\x34\\x82\\xe4\\x7c\\x07\\x65\\xb8\\x7f\\xd0\\x2c\\xf9\\x88\\x40\\xf8\\xda\\xff\\xf8\\x6a\\x3b\\xd7\\xf6\\x97\\x56\\x36\\x0c\\xbf\\xa9\\xe0\\xb4\\xf6\\x40\\x08\\xdf\\x1a\\xf8\\xd9\\x14\\xb9\\x35\\x9f\\x0d\\xf3\\x18\\x55\\x8d\\x47\\x23\\x74\\x27\\x45\\xf3\\x68\\x86\\x7c\\x6a\\xd2\\x29\\x0a\\x87\\x34\\x63\\xc2\\x98\\xa9\\x5e\\xc5\\xab\\x94\\x54\\xc6\\x90\\x18\\x66\\xc9\\x56\\x4e\\x82\\x3b\\x5e\\x32\\x72\\xf1\\x69\\xa7\\xb6\\x03\\x3d\\xa3\\x82\\x6d\\x88\\x67\\x21\\x1d\\xfc\\x94\\x49\\xe1\\x20\\x69\\x87\\x79\\x14\\xdf\\x81\\x69\\x2d\\x27\\x3a\\xd8\\x86\\xc6\\xfe\\x32\\xf0\\x9c\\x7c\\x47\\x4b\\x58\\xf7\\xd4\\xcd\\xe7\\x31\\xc9\\x0c\\xd4\\x46\\xdb\\x91\\x0d\\x95\\x1a\\x8e\\xac\\xcb\\x09\\xbf\\xbd\\x7c\\x26\\xd3\\xf2\\x74\\xcd\\x83\\xe4\\xa4\\x60\\xe5\\xb5\\x87\\x12\\x36\\x00\\xc5\\xa4\\x25\\xc5\\xde\\x19\\xe4\\x64\\x83\\xad\\xb6\\x50\\x52\\xd8\\x51\\xcd\\x0c\\xad\\x6a\\x61\\xf8\\x22\\x54\\x81\\x70\\xe5\\x2e\\xd1\\xd2\\x77\\xfb\\x0c\\x9d\\xcd\\xb2\\xe2\\x5b\\x4f\\x10\\x2f\\x27\\x3e\\x46\\xe6\\x6f\\x87\\x45\\x80\\x55\\x72\\xb2\\x9a\\x8e\\xf8\\xf0\\x0f\\x03\\xd7\\x8e\\xa2\\x48\\x41\\x52\\xbc\\xbb\\x2b\\x78\\x05\\x11\\xb4\\x50\\x0c\\xe8\\x6a\\x23\\x6f\\x55\\x0c\\xca\\xc4\\x91\\xb1\\xab\\x1b\\xb7\\xec\\x73\\x44\\x5a\\xfb\\x4b\\x27\\xcf\\x06\\x39\\x6b\\xcc\\xbf\\xd2\\xea\\x8a\\xab\\x6c\\xf5\\x52\\x18\\x61\\xb9\\x73\\x64\\x6d\\x7f\\x52\\xd4\\xec\\xca\\xce\\x2b\\xe7\\x22\\xd2\\xe3\\x56\\xdd\\x24\\x6e\\x16\\xdb\\xd8\\xda\\x98\\x6d\\x94\\x00\\x9d\\xc8\\x1a\\x5c\\xe6\\xef\\x88\\x40\\x05\\xf3\\x0c\\xe7\\x8c\\x51\\x80\\x52\\x50\\x26\\xad\\x9a\\x3a\\x61\\xff\\x61\\xb2\\x8c\\xa0\\xa6\\x2c\\x87\\x66\\x17\\xb1\\xb7\\x29\\x06\\x75\\x4d\\xd3\\x8f\\x14\\x1a\\xce\\x3d\\xbf\\xe9\\xe9\\x7c\\x84\\xcf\\x05\\x48\\xdb\\x58\\x16\\x7f\\x73\\xcd\\xb0\\x3f\\xc8\\x02\\x32\\xd9\\xc3\\xe9\\xd5\\xc7\\x40\\x81\\xbd\\xdb\\xa5\\x96\\xad\\x78\\x9a\\x30\\xf7\\x73\\x7f\\xe8\\xa3\\x6a\\x23\\x8c\\xc5\\x0b\\xc0\\xb0\\x46\\x10\\x0a\\x46\\x2a\\xbf\\xd7\\xbb\\x82\\x27\\xc9\\xfb\\xc3\\xdf\\xd8\\x55\\x32\\x51\\xb5\\x1f\\xf0\\x4e\\x8f\\x3e\\xac\\x03\\x00\\xe7\\xb6\\x22\\x59\\xce\\x64\\x99\\x1e\\xb8\\x86\\x6b\\xd8\\xc3\\x5c\\x3a\\x67\\x16\\xad\\xd5\\x95\\x44\\xa5\\xc8\\xb9\\x3d\\x5b\\x5e\\xae\\x62\\x2d\\xfe\\xb2\\x13\\xd6\\x77\\x69\\xf6\\x06\\xaa\\x51\\xde\\xc6\\xd5\\xf5\\xc1\\x3e\\x79\\x56\\x08\\x6a\\x02\\x12\\x23\\xd9\\x1a\\x99\\xb1\\x08\\x74\\x80\\x7f\\x86\\x42\\x14\\xbd\\xbe\\x27\\x4b\\x63\\x36\\x30\\x3f\\x26\\x56\\x5e\\x1c\\x89\\x38\\xc6\\xea\\x54\\x37\\x73\\x69\\xf2\\x7d\\x50\\xb1\\x61\\x9e\\xa7\\x0c\\xa8\\xec\\xfa\\xe7\\x4e\\x13\\x5f\\x8d\\x43\\x44\\x31\\x9d\\x47\\xa0\\x30\\x26\\xce\\xbc\\x85\\x7f\\x05\\x7b\\xb7\\xcd\\x4d\\xe4\\x9d\\x7d\\x66\\x04\\x3d\\xf5\\x24\\x15\\x8a\\xb7\\x73\\xf6\\x27\\xe1\\x45\\x90\\x4c\\x33\\x8b\\x2f\\x61\\xf0\\xaa\\x10\\xd1\\x66\\x68\\x5c\\x11\\x89\\x8b\\x90\\xe8\\xb5\\xdf\\xb5\\xa8\\xb5\\xaf\\x14\\xea\\xd8\\xb8\\xc8\\x34\\x98\\xb9\\x20\\x0f\\xd2\\xdb\\x08\\x06\\x93\\xeb\\xba\\xbd\\x6d\\xe5\\xe7\\x70\\xb9\\x46\\x03\\x94\\x99\\x9c\\x52\\xae\\x55\\x51\\x99\\x71\\x99\\xae\\x63\\xbc\\x48\\x2a\\xa6\\x08\\x85\\x4d\\xf1\\xda\\x15\\xcf\\x18\\xa4\\x97\\x1c\\xdf\\xef\\x09\\x2d\\x45\\x66\\x78\\x20\\x45\\x4e\\xc6\\x1c\\x0e\\x7f\\x80\\xdc\\xf6\\x9b\\xd4\\xbc\\x2c\\x29\\xd8\\x5d\\xef\\x01\\x1c\\x73\\xc7\\x95\\xf8\\x28\\x9a\\xdd\\xca\\x3c\\x5c\\x87\\x87\\x93\\x76\\x4c\\x7b\\xd3\\x2e\\x0e\\x58\\xb2\\xa6\\x7e\\xe8\\x26\\x74\\x13\\x29\\x78\\xf9\\x13\\x8e\\xb7\\x7d\\xb6\\xd8\\x15\\xbd\\x84\\x8c\\x55\\x74\\x14\\x6b\\xe6\\x9c\\xa7\\x41\\x37\\xb1\\xe2\\x6e\\x69\\x3b\\x61\\xa0\\x61\\xf8\\x7e\\xb2\\x8e\\x99\\xbd\\x8f\\x58\\x3e\\xff\\x1d\\xb8\\x8f\\xed\\xe4\\xd6\\x53\\x9b\\x37\\xed\\x0f\\x85\\xaf\\x95\\x0a\\x81\\xb8\\x80\\xfa\\xc9\\x64\\xaf\\x98\\xca\\xdf\\x4d\\xf4\\xcf\\xae\\xd7\\x31\\x8d\\x1e\\x6d\\xa2\\xaf\\x69\\xb1\\xc7\\x8e\\xd3\\x15\\x43\\xe1\\x65\\xa2\\x87\\x6b\\xb6\\x39\\xd5\\x84\\x91\\xf7\\xff\\xb4\\x30\\x12\\xb0\\x28\\xe5\\xf5\\x05\\xa2\\xce\\x22\\x3b\\x9f\\x2d\\x78\\x11\\x01\\xf7\\x78\\x8e\\x94\\xee\\x58\\x7b\\x7e\\x39\\xba\\x97\\x9e\\xaf\\x39\\x82\\x54\\x86\\x08\\xa1\\xe2\\x23\\x61\\x57\\xc1\\x2c\\x42\\x4d\\x06\\xc8\\x7e\\x65\\xdb\\x7c\\xbf\\xd3\\x49\\x41\\x67\\x66\\x2e\\x76\\x0f\\x89\\xb8\\x17\\x46\\x49\\x83\\xc2\\xa2\\xc5\\x9d\\x62\\x3b\\x9e\\xee\\xd2\\x50\\x56\\x18\\x75\\xdd\\xae\\x6c\\x91\\x97\\xb5\\x41\\x4b\\x28\\xa5\\xf2\\x7b\\x31\\x75\\x0c\\x4a\\xc3\\xad\\x3e\\x52\\xea\\x5e\\x8f\\x2f\\xa1\\xef\\xfa\\x37\\x5f\\x45\\x3b\\x2f\\x7f\\x16\\xa6\\x00\\x19\\xbf\\x9d\\x2b\\xf2\\x62\\x1d\\x06\\x14\\x85\\x65\\x23\\x75\\x6c\\xce\\xac\\xec\\x75\\x37\\x30\\xfd\\xf4\\x8f\\x12\\x3e\\x39\\xe2\\x8b\\xeb\\xa6\\xde\\x47\\x91\\x6e\\x8c\\xf4\\xd0\\x51\\x63\\x6c\\xbb\\x48\\x8a\\x7c\\xb7\\xbc\\xc8\\xee\\x3a\\xda\\x93\\x7b\\x38\\x34\\xdb\\x13\\x0d\\x9c\\xc9\\x97\\x38\\x26\\xfc\\xcb\\x9d\\x16\\x85\\xc2\\x48\\x42\\x68\\x5a\\xae\\x68\\xf4\\x4c\\x99\\x48\\xc7\\x2b\\xc5\\x13\\x22\\x57\\xee\\xad\\xa8\\xeb\\x5b\\xa3\\x08\\x2e\\x04\\xc2\\xab\\x33\\xe2\\x0a\\x08\\xa2\\x47\\x72\\x7d\\x66\\xbf\\x07\\xe9\\x2c\\x7a\\xf4\\x34\\xef\\x1f\\xee\\x4d\\xf6\\xac\\xf3\\xab\\x71\\xd1\\x08\\xae\\xad\\x4f\\xf3\\x27\\x08\\x87\\x62\\x2e\\x9e\\x19\\x9e\\x03\\x64\\xea\\x99\\xd6\\xcf\\x72\\x4b\\xbc\\xef\\x5f\\x4c\\x66\\xa0\\xda\\x17\\x16\\x48\\x31\\x57\\x68\\xf7\\x60\\x59\\x06\\xa6\\x7d\\xa2\\x09\\x6f\\xd1\\xbb\\x3a\\xee\\x11\\x0e\\x1f\\x98\\x1a\\x44\\x55\\x96\\xf3\\xe3\\x22\\x4f\\xe2\\xe7\\x8c\\xe1\\xde\\xa4\\x6d\\x30\\x41\\x16\\xe0\\xd3\\x12\\x15\\xb9\\xed\\x66\\x3b\\xf9\\xeb\\x3f\\x75\\x4a\\x01\\x2b\\x6c\\x26\\x78\\xf9\\xf6\\x6d\\xf2\\xff\\x69\\xfa\\x23\\x5b\\x43\\x6a\\xb3\\xf5\\x68\\xd8\\xa6\\x43\\x3e\\x13\\x8e\\xef\\x09\\x47\\xeb\\xec\\x42\\x65\\x19\\x71\\x77\\x8e\\xe7\\x54\\x2c\\xeb\\x3e\\x1f\\xf4\\x20\\x24\\xd7\\x43\\xb2\\x0f\\x64\\x7c\\x00\\xdb\\x56\\xe6\\xfc\\xf2\\xef\\x79\\x57\\xad\\xed\\x9d\\x3e\\x1a\\x0a\\x54\\xeb\\xb4\\xa0\\xe2\\xb1\\x74\\x32\\x7a\\x09\\xd6\\x19\\xe8\\xbd\\x9e\\x21\\x6a\\xbc\\x4c\\x9c\\xa3\\x48\\xbb\\xa1\\x3a\\x72\\x12\\x16\\x2e\\xb6\\x7a\\x20\\x1c\\xab\\xfb\\xc8\\xbd\\x1b\\xa5\\x1f\\xef\\x1e\\xc6\\xaa\\x06\\xf7\\x51\\x6d\\xf9\\xec\\xc4\\x03\\xbb\\xb2\\xbe\\x2a\\x1f\\x30\\x99\\x35\\xe1\\x32\\x01\\xf9\\xf3\\x1e\\x38\\x0d\\xb3\\x02\\x67\\x07\\x52\\x30\\xa4\\xdc\\x54\\x75\\x8f\\xe6\\x98\\xde\\x73\\x45\\x86\\x5b\\x53\\x82\\x05\\xdf\\x62\\xdc\\x82\\xab\\xef\\xa1\\xc7\\xad\\x9d\\x5c\\x04\\xd3\\x5a\\xba\\x23\\x55\\x4f\\x8a\\x55\\xda\\xb6\\x23\\x6b\\x8c\\x92\\xb1\\x9c\\xc2\\xd9\\x23\\x27\\xd1\\x93\\xe3\\x56\\x38\\x02\\x0d\\x49\\x91\\xfc\\x7a\\x24\\xf3\\xa9\\xda\\xf7\\xce\\xf8\\x51\\x49\\x0c\\x1d\\xbf\\x03\\xf4\\xa0\\xa7\\xef\\xd6\\xea\\x64\\xda\\x18\\x4f\\x30\\xb9\\xb4\\xdf\\x03\\xd1\\x0a\\x89\\xad\\xbe\\x07\\xf7\\x61\\x88\\xb7\\x79\\x58\\x5d\\xac\\x11\\xd8\\x66\\xc5\\x08\\xf7\\x93\\xa4\\x13\\x87\\x49\\xe2\\xfa\\xfd\\x64\\x52\\xb8\\xd2\\xfd\\x7d\\x50\\x9c\\x4e\\x6e\\x0e\\x8f\\xd7\\x73\\xbe\\x61\\x7b\\x0b\\xc1\\x67\\xee\\xad\\x1e\\xe1\\x57\\x12\\x56\\xf8\\x8b\\xb0\\x8b\\xfb\\xc3\\xaf\\x00\\xd9\\x9d\\x85\\x92\\xfa\\x50\\x70\\xf8\\x0d\\x44\\xd6\\xa3\\xf5\\xf5\\x3d\\xb2\\xa7\\x0e\\xba\\xbe\\x11\\x31\\x62\\x14\\xc6\\x8c\\xf0\\xa7\\x12\\xb7\\x47\\x86\\x19\\x52\\xc1\\x93\\xbd\\x80\\x0a\\x7a\\x5e\\xe0\\xdf\\x9d\\x88\\xab\\x05\\x6a\\x55\\x64\\xc5\\xfa\\x50\\x61\\x0c\\xb8\\xde\\x86\\x09\\xec\\x28\\xb1\\xde\\x89\\x8d\\xe5\\x6f\\x4c\\x2b\\x53\\x84\\x6b\\xe0\\x7e\\x37\\xc7\\x88\\x6e\\x29\\xdd\\x41\\x64\\x80\\xa5\\x9e\\x5e\\xb4\\x1f\\x86\\x0a\\x3e\\x99\\x38\\x56\\x99\\x80\\x4b\\x90\\x6d\\x25\\xdd\\xf4\\xa0\\x9d\\x9c\\xe7\\xae\\x9f\\x03\\x39\\xc0\\x4f\\xb9\\x7d\\x63\\xdc\\xb4\\xb0\\x57\\xe1\\x92\\x41\\x84\\xec\\x01\\x1a\\xc0\\x21\\x05\\x5f\\x80\\x34\\x2c\\xb1\\xee\\x06\\x6d\\x97\\xdc\\x8d\\xde\\x32\\x67\\x0c\\x01\\x65\\xee\\x80\\x4e\\x3c\\x49\\xdd\\x5d\\x92\\xa6\\xf7\\x26\\x9f\\x2d\\x9c\\x54\\xcc\\x4f\\x6d\\x21\\xfe\\x93\\x8e\\x9e\\xc4\\x5d\\x50\\xbf\\x27\\x59\\xef\\x39\\x47\\x4e\\x65\\xed\\xcd\\xac\\xdb\\x1d\\xd2\\xdb\\xde\\x1b\\xc7\\xcb\\xfd\\x51\\x28\\x3e\\xf9\\x8e\\x66\\x8a\\x30\\xa0\\x10\\x76\\xc6\\x82\\x74\\xd0\\x15\\xdd\\xfc\\xed\\xc6\\x3f\\x2a\\xca\\x9e\\xd3\\x04\\xa5\\x6c\\x4f\\x58\\x55\\x2a\\x43\\xc0\\x2c\\xac\\xd4\\xbe\\x2a\\xea\\x09\\x8e\\x92\\x8b\\x92\\x0f\\xc1\\xb8\\x7b\\xc8\\x57\\xca\\x08\\x84\\xe2\\x32\\x4d\\xb7\\xb7\\xce\\x98\\x1e\\x10\\x5b\\x90\\x49\\x37\\x24\\x35\\x0d\\x39\\x7c\\x74\\x44\\x24\\x89\\x86\\x32\\xb2\\x31\\x51\\xbb\\x98\\x6d\\xa3\\x6e\\x6f\\xef\\x5f\\x37\\x77\\xa7\\x59\\xc2\\x1c\\x67\\xcd\\x55\\x0e\\x85\\x43\\x13\\xca\\x41\\x19\\xc4\\x67\\x9e\\x61\\x74\\x09\\x65\\xb4\\x12\\xc1\\x1b\\xa6\\xb9\\xc1\\x67\\xae\\xc0\\x47\\x07\\x18\\xdc\\x1a\\x50\\x47\\x51\\x06\\x55\\xf3\\x5e\\xe8\\x94\\xc7\\x44\\x5e\\x4b\\xb1\\x66\\x69\\x4f\\x2c\\xf1\\xc7\\xe0\\x62\\x14\\x3d\\x91\\x18\\x5f\\xb3\\xa6\\xf7\\x9b\\xc3\\x99\\x28\\x56\\x8d\\x10\\x54\\x8e\\xfa\\xa8\\x9d\\xf6\\x8e\\x79\\x0e\\x6b\\x7e\\x96\\x12\\x42\\x5b\\x71\\xd7\\x31\\x86\\x3e\\x73\\x10\\x82\\x94\\xe9\\x47\\x80\\x2d\\x9d\\xf4\\x04\\xa6\\x0e\\x29\\x2f\\x22\\x3a\\xc5\\x36\\x1a\\xc1\\xfd\\xdd\\xad\\x3b\\x2f\\xa1\\xd8\\x64\\xcd\\x55\\x7d\\xc2\\x64\\x33\\x5e\\xa9\\x6c\\x46\\xcf\\xe5\\xf3\\x75\\x71\\x99\\xfe\\x37\\x49\\x96\\xcb\\xf2\\x66\\x8f\\xf0\\x6f\\x60\\xa2\\x83\\x7a\\xb3\\xf7\\xa4\\x81\\x42\\x08\\x34\\x6b\\xd3\\xa5\\x4e\\xd6\\x46\\x29\\x7a\\x4f\\x37\\xc9\\xfd\\xc7\\x27\\x9b\\xf9\\x4b\\xa3\\xfb\\x5b\\x7b\\xa3\\x48\\xe0\\xfa\\xb0\\x77\\xdc\\x98\\x90\\x6e\\x99\\xd0\\xed\\x07\\x80\\x49\\x05\\xe1\\x88\\x39\\x4d\\xac\\x18\\xf9\\xa7\\xbf\\x4a\\x89\\x4b\\xba\\x15\\x1b\\x86\\x78\\x22\\x99\\xe7\\x9e\\x17\\x4c\\x53\\x40\\x98\\x3b\\x8f\\x9a\\x86\\x03\\x60\\x9c\\xed\\xd9\\x0f\\xa3\\x4c\\x2e\\x96\\x88\\x9d\\xd5\\xdb\\x19\\x1c\\xf9\\x31\\xf4\\x24\\x02\\xbe\\x0d\\xc8\\xd7\\x64\\x03\\xe2\\x37\\x5f\\x69\\x12\\xc2\\xd1\\x42\\x7c\\xdb\\xf6\\x83\\x6f\\xf9\\xea\\xd0\\x49\\x6a\\xf1\\x63\\x55\\x1a\\x00\\x8f\\xbb\\xaf\\x5d\\x1c\\x0e\\xd1\\xa6\\x41\\x63\\x13\\x70\\x71\\x68\\x74\\xd9\\x53\\x89\\x48\\xa5\\x2b\\x2d\\x80\\x2e\\x3a\\xab\\xe8\\xa7\\x6c\\x84\\x4d\\x41\\xa3\\x59\\xd9\\xe7\\x79\\xdf\\xb2\\x7e\\xa1\\x29\\x8d\\xe0\\x0b\\x9b\\x4e\\xd8\\x9d\\x56\\xe1\\xed\\xef\\xd1\\x95\\x55\\x52\\x0b\\x7a\\xff\\x57\\xd3\\x4c\\xca\\x5c\\xfa\\x31\\x09\\xa1\\x05\\x06\\x9d\\x1a\\x0a\\x2a\\x07\\xe4\\xd0\\x8e\\xfd\\x30\\x84\\xb8\\xc7\\x91\\xe7\\x1f\\xfa\\x22\\x87\\x12\\xc5\\x37\\x02\\xe5\\xda\\xb8\\x0c\\x3c\\x5e\\x49\\xdb\\x53\\x36\\xb7\\xf6\\xc5\\xf1\\x8a\\xe7\\xcd\\x74\\x37\\x05\\x69\\xe0\\x3d\\x4f\\xb9\\x55\\x1a\\x8d\\x1e\\x4f\\x72\\x93\\x31\\xba\\xe5\\xb3\\x00\\x4b\\x1f\\xfa\\xf7\\xdd\\xc3\\x29\\x2d\\x08\\xf1\\x81\\x81\\x93\\xd5\\xb5\\x77\\xbb\\x3a\\x66\\x87\\x5c\\xa9\\xfd\\x6f\\x64\\xe4\\x2a\\x37\\x81\\xfd\\x32\\x29\\x70\\x2c\\x7c\\x67\\x6f\\x78\\x59\\x46\\x0f\\x8b\\xf0\\x73\\xeb\\xa3\\x94\\xf4\\x81\\xb6\\x53\\x05\\xc1\\x4a\\x3b\\x97\\x0f\\x59\\x22\\xc4\\xc9\\x4a\\x9a\\x9d\\x63\\x30\\x5e\\xb8\\x28\\x8a\\xe8\\xf5\\xed\\xa7\\x32\\x63\\xe4\\x87\\xb4\\xff\\x78\\xb3\\x94\\x3b\\x58\\xfc\\xaa\\x84\\x20\\xa9\\x43\\xd8\\x77\\x67\\xe7\\x36\\x67\\x9a\\x7d\\x6c\\x40\\x3f\\x01\\xcd\\xf1\\x63\\x44\\xaa\\x08\\xaf\\xb4\\x01\\x39\\xba\\x19\\x7d\\xfb\\x72\\xab\\xaa\\x6a\\xf3\\x01\\x09\\x04\\x50\\xe3\\x3f\\x63\\x21\\xe6\\xa6\\x87\\x14\\x74\\xdb\\xb8\\x03\\x79\\x69\\xac\\xb5\\x1e\\xca\\x9a\\x90\\x8b\\x30\\x27\\x48\\x0f\\x33\\xb3\\x53\\x28\\x22\\xe1\\x89\\x0f\\xcf\\x46\\xb0\\x8c\\x84\\xca\\xb4\\x3b\\xcf\\x0f\\x7a\\xb8\\x58\\x8c\\xf5\\xb4\\xe0\\xb0\\xfc\\xb5\\x03\\x9d\\x4c\\xc3\\x32\\x0a\\xea\\x34\\xaf\\x08\\x48\\x03\\x78\\x57\\x5f\\x68\\x43\\x3d\\xb0\\xb9\\xfc\\x2b\\x19\\x12\\x1f\\xaa\\x7c\\x98\\x26\\x5e\\x25\\x8a\\xa4\\xcc\\x26\\x47\\xd9\\x11\\x48\\x3a\\x9b\\x9a\\x35\\xfe\\x57\\x8d\\x7a\\xf8\\x73\\x7a\\x4b\\xb7\\x3c\\xb8\\x6a\\xa4\\x9d\\x0e\\x6e\\xd7\\xb0\\x09\\xed\\xdf\\x07\\x6b\\x51\\xe3\\x13\\x8e\\x2b\\x95\\xf1\\xb7\\x7d\\xbb\\x45\\x3a\\xeb\\xd0\\x80\\xf9\\xf4\\xef\\xbd\\x3c\\x43\\xd3\\x4a\\x7d\\x5b\\x1e\\x9e\\x64\\x67\\x54\\xfb\\x7e\\x3c\\xcc\\x7d\\x98\\xc2\\x21\\x85\\xbe\\x39\\x8e\\x44\\x54\\xf5\\x16\\x83\\x60\\x0a\\xf7\\x82\\x7b\\xec\\x88\\x0e\\xb5\\x64\\x83\\x61\\x89\\x15\\xfc\\xa4\\x7c\\xf4\\x34\\x59\\x66\\xe8\\xb6\\x61\\x1d\\x97\\xfa\\xc1\\xad\\xce\\xe4\\x59\\xc7\\xec\\x7a\\x2e\\xbc\\x40\\xa2\\xaf\\x9d\\xfa\\x0b\\x47\\x5c\\xff\\xde\\x18\\x1f\\x65\\xe3\\xa6\\xee\\x24\\xdd\\xf7\\x34\\x7c\\x6a\\xca\\xb2\\xa7\\x55\\x24\\x28\\x39\\xcc\\xbd\\x50\\xc5\\xc4\\x3d\\x2f\\xdc\\x6c\\x2f\\x7b\\xaa\\x14\\xe6\\x1d\\x85\\x32\\x95\\xea\\xd6\\xcf\\xaf\\x2b\\x04\\x6a\\xef\\xb7\\xc8\\xe9\\xdb\\xc1\\xce\\xd5\\x00\\x87\\x06\\xd3\\x19\\x98\\x95\\x72\\xaf\\x2c\\x5d\\xdc\\x91\\xae\\x54\\xf9\\xfd\\x77\\x96\\xfe\\x80\\x6d\\xde\\x23\\x5a\\xd2\\x23\\x8d\\xff\\x51\\x84\\x6b\\x05\\x8a\\x0c\\x3c\\xff\\xf9\\xc6\\x32\\x10\\xff\\x26\\xf1\\x75\\xdb\\xc7\\x2e\\xf4\\xe6\\x23\\x0b\\x2d\\xd6\\x6b\\x1b\\xcb\\x2b\\x58\\xe4\\x8b\\x97\\x4e\\x2f\\x01\\xe9\\x9f\\xd6\\x33\\x42\\x9c\\x97\\xb0\\x31\\x08\\xc5\\xa7\\xff\\x61\\x1f\\x5a\\x6d\\xf8\\x2a\\xdc\\xf1\\x15\\x9b\\x46\\xfe\\xe3\\x09\\x73\\xce\\x1f\\x7f\\xfb\\x68\\x95\\x26\\xce\\x23\\x3d\\xa0\\x31\\x2c\\xaf\\x12\\x85\\x91\\x0c\\x9d\\x9e\\xd4\\xa4\\xdc\\x2d\\x2e\\x8c\\x8a\\x56\\x45\\xf7\\xec\\xd9\\x33\\xac\\xcb\\xf0\\x82\\xc7\\x8b\\x3b\\x62\\x6f\\x9e\\xb2\\x0a\\xc7\\xbf\\xfe\\x87\\xe9\\xb1\\x97\\xc6\\x75\\x53\\x37\\x1a\\xa9\\xa8\\xa5\\x09\\x8b\\x57\\x64\\x45\\xbc\\x58\\x56\\xc5\\xf9\\xf6\\x02\\x91\\xcf\\x1a\\x5e\\x67\\x4d\\x91\\x99\\xe4\\x61\\x7d\\xa2\\x7f\\x35\\xca\\xa8\\x68\\x52\\x9c\\x69\\x8a\\x2a\\x39\\x9b\\xc0\\x9c\\x15\\x8a\\xfb\\x20\\xdd\\xc2\\xf5\\x1b\\x7e\\xfb\\x19\\x6e\\xff\\xac\\xab\\xba\\x61\\x98\\xdc\\xd6\\xed\\xb7\\xf1\\xe1\\x94\\xf2\\xe4\\xd0\\xef\\x76\\x8f\\xe7\\xf5\\x4e\\x57\\x5c\\xfd\\x52\\x28\\x16\\x04\\x65\\xe1\\x1d\\xd8\\xc1\\x66\\xeb\\x96\\x92\\x86\\xc3\\x33\\xd6\\x10\\x5f\\x38\\x8c\\x9e\\xc2\\x4d\\x7b\\xb2\\x04\\xb0\\x49\\x43\\x80\\x49\\xfa\\xff\\xce\\xb3\\xa7\\xfb\\xe4\\x8f\\x31\\x4a\\x07\\xd3\\x1f\\x7e\\xd6\\xe1\\x37\\xe2\\xce\\xb1\\x9f\\x7f\\xcf\\xa8\\xf5\\x21\\x49\\x54\\x73\\xc1\\xc8\\xf0\\xee\\xe0\\x4b\\x99\\xe0\\xec\\x80\\x15\\x3c\\xdf\\x83\\x91\\xcb\\x5d\\xf4\\xab\\x2c\\xc0\\x76\\xef\\x9e\\x19\\x6b\\x18\\xb8\\x98\\x19\\x7b\\x42\\xab\\x31\\xdd\\xe2\\x08\\x8d\\xbe\\xcc\\xe6\\x27\\x27\\xad\\x04\\x1c\\x68\\x71\\x35\\x4e\\x1c\\x38\\xcf\\x34\\x12\\xc2\\xc0\\x97\\x0a\\x42\\x02\\x0c\\xa3\\x38\\x53\\x77\\x6e\\x96\\x22\\x2d\\x5e\\xa7\\x4b\\xcd\\x82\\x4f\\x00\\x16\\x7e\\xdd\\xd7\\x0f\\xbe\\x7c\\x81\\xe9\\xa2\\xc5\\x17\\xad\\x34\\x09\\x9c\\xff\\xde\\x08\\x49\\x11\\x3b\\xce\\xa0\\xdc\\x73\\x3b\\x57\\x18\\x49\\x21\\xb3\\x2f\\x30\\xed\\x0e\\xbe\\x08\\x50\\x08\\x72\\x14\\xeb\\xd1\\x0f\\x03\\x94\\x6a\\x5f\\x4c\\x51\\x70\\xeb\\xfe\\x94\\xb1\\xc2\\xb8\\x29\\xd3\\x9b\\x6d\\x18\\x8d\\x8e\\xe9\\xa9\\x39\\x2f\\x50\\x3f\\x5f\\x36\\xff\\xdc\\x23\\x13\\xf1\\x3a\\x2c\\x1c\\x30\\xfe\\xce\\xf0\\x10\\x98\\x94\\x41\\xc5\\x2d\\x87\\xb9\\xc6\\x0e\\x11\\x3c\\x73\\xb6\\x1b\\x8f\\xbb\\x55\\x03\\xd0\\xbb\\x70\\x73\\x2f\\x66\\x60\\x21\\xa9\\x62\\x3f\\x41\\x32\\xb7\\x79\\x94\\xf5\\xe3\\x90\\x81\\xdb\\x1f\\xf5\\xdc\\xf9\\x0b\\x2b\\x93\\x8f\\x69\\xa0\\x0d\\x98\\xae\\x22\\xfe\\x96\\x98\\x08\\xd9\\x4f\\xe1\\xdc\\xd3\\xd4\\xbf\\x69\\xe9\\x59\\xdd\\xfc\\x91\\x1c\\x6a\\x7d\\xce\\x09\\x99\\x24\\x9d\\xb4\\x3f\\x9c\\x2e\\x15\\x3d\\x73\\x07\\x5d\\xea\\x69\\xcf\\xec\\xb3\\xe9\\x42\\xdc\\x62\\xbe\\xc1\\xd0\\xd0\\x26\\x62\\xc2\\x75\\x05\\x49\\x54\\x43\\x2e\\xf1\\x46\\x38\\x2f\\x3b\\xc8\\x38\\xb6\\xdf\\xa1\\x9a\\x82\\x33\\xdd\\x68\\x41\\x9f\\x71\\xa7\\x17\\xd6\\xc2\\x5f\\xd6\\xe6\\xb5\\xdc\\x55\\xcc\\x5b\\x9c\\xac\\x78\\xbf\\x9b\\x15\\x09\\x67\\xb9\\x27\\xe0\\x64\\x63\\xd6\\xc1\\xfc\\xe0\\xe1\\x72\\x98\\x4a\\x7e\\x7c\\xca\\x80\\x2c\\x29\\x8d\\xac\\xc7\\xf2\\xf5\\xbc\\xbc\\xa3\\x8f\\xba\\xbc\\xe4\\x3a\\x32\\x0b\\xa4\\xc3\\x00\\x0f\\x33\\xb7\\x3a\\x50\\xbd\\x35\\x15\\x98\\x0c\\x06\\xca\\x8a\\x7f\\x51\\x21\\xe2\\x44\\x34\\x7f\\x34\\x9f\\x56\\x52\\x22\\x7d\\x26\\x51\\x6c\\x09\\x48\\xe7\\x6b\\x92\\x8d\\x32\\x1f\\x8b\\x49\\x59\\x16\\xec\\x92\\x71\\xa8\\x19\\x91\\xc1\\x43\\x4c\\xdb\\xf9\\x0c\\x76\\x70\\x1a\\x3d\\x05\\xd2\\xb7\\xc7\\x57\\x17\\x20\\xcc\\xcb\\x3b\\x41\\x67\\xf6\\xc9\\x37\\xf1\\xac\\x4b\\x72\\x1a\\x3a\\x82\\x0c\\xaf\\xe6\\x56\\x7d\\xa5\\x97\\x26\\xa6\\x16\\x96\\xf8\\xf8\\xcd\\x91\\x1a\\xd0\\xb0\\x9b\\x68\\x7e\\xfb\\x18\\x85\\x78\\x6d\\x9d\\x88\\x43\\x18\\xc4\\x31\\x7c\\xe3\\x66\\x77\\xd8\\x8a\\xa9\\x0b\\x4c\\x45\\x50\\xaa\\xea\\x8d\\xde\\x35\\x20\\xfe\\x6e\\x09\\xc5\\xd4\\xb0\\xc4\\xd1\\xa1\\x63\\x8d\\x5f\\x50\\x6e\\xfd\\x31\\x4f\\x19\\xa9\\xb3\\x04\\x50\\x52\\x44\\x44\\x33\\x60\\x22\\x62\\xd9\\x0b\\x4d\\x23\\xf8\\xe8\\x18\\x98\\x44\\xda\\x14\\xfa\\xca\\x9e\\xfd\\x0f\\x3d\\x91\\x70\\xb8\\x6c\\xab\\x05\\x79\\xfd\\x6b\\xe8\\xe8\\x47\\xde\\x98\\x87\\x1b\\x23\\xbc\\x91\\x40\\xbf\\x49\\x7a\\x64\\x1a\\x7d\\x7f\\xa9\\x0e\\x80\\xe1\\x44\\xb3\\xd5\\x69\\xcf\\x0e\\x5f\\x7f\\x72\\xa6\\x94\\xaa\\xb0\\xb8\\x11\\x34\\xaa\\x02\\xd5\\xeb\\x55\\x10\\xc0\\xdc\\xa6\\x40\\x7c\\x93\\x38\\xaa\\x4f\\xb9\\xae\\xb6\\xed\\x48\\x0e\\x17\\xf8\\x74\\x84\\x05\\x4f\\x60\\x7a\\x8f\\xd8\\x81\\xad\\xcc\\x7a\\x43\\x74\\xd2\\xe5\\x82\\x6a\\x40\\x92\\x53\\x8e\\x51\\x58\\xaa\\x74\\xb2\\x24\\x8e\\x38\\xd9\\xeb\\x01\\xda\\xaa\\x16\\xdd\\xcc\\xbc\\xf5\\x5c\\xae\\xe6\\x6f\\xcf\\xee\\x6b\\x84\\x8b\\x97\\x89\\x7a\\xb2\\xc3\\x15\\x6c\\x46\\x11\\x96\\x55\\xca\\xd5\\xc7\\x4c\\x96\\xd4\\x02\\xdf\\x1f\\x69\\xcb\\x46\\xb4\\x76\\xa2\\x82\\xe0\\x9f\\x64\\x55\\x6a\\xd8\\x57\\xcb\\xe9\\xe8\\x99\\xbe\\xb3\\x17\\x63\\x05\\x63\\x94\\x10\\xe9\\xe7\\x74\\x00\\x61\\x37\\xcc\\xba\\x12\\xde\\x19\\x7a\\x15\\x32\\xd6\\x7b\\xc7\\x41\\x36\\x4f\\x17\\x8b\\x4c\\x7a\\xb2\\x6f\\x8b\\x4a\\x02\\xab\\xfa\\xb6\\xb0\\x46\\x36\\xf4\\x4c\\x92\\x16\\x7d\\xcb\\xb6\\x39\\xb0\\x70\\xd6\\x6e\\xbf\\xdc\\x51\\x88\\x60\\x1c\\x4d\\x95\\xb4\\x6a\\x22\\x28\\xf5\\x04\\x0a\\x8b\\x6c\\x78\\xd1\\x30\\x01\\x4c\\xaf\\xe6\\x01\\xb1\\x6a\\x7f\\xd9\\x1f\\xb8\\x3b\\x2b\\x87\\x00\\x17\\xd5\\x06', 1)"
  },
  {
    "path": "environment/render/render_pic2.py",
    "content": "import traceback\nimport pygame\nimport traceback\nimport os\nimport copy\nfrom render.render_pic3 import Render as Render3\n\nclass Render:\n    def __init__(self, size_x, size_y):#, o_detector_num, o_fighter_num, e_detector_num, e_fighter_num):\n        self.render3 = Render3(size_x, size_y)\n        return\n        pygame.init()\n        self.screen = pygame.display.set_mode((size_x, size_y))\n        image_path = os.getcwd() + '/environment/render/resource/'\n        self.detector_red  = pygame.image.load(image_path + 'detector-red-20.png')\n        self.detector_blue = pygame.image.load(image_path + 'detector-blue-20.png')\n        self.fighter_red   = pygame.image.load(image_path + 'fighter-red-20.png')\n        self.fighter_bue   = pygame.image.load(image_path + 'fighter-blue-20.png')\n        self.detector_red_rect = self.detector_red.get_rect()\n        self.detector_blue_rect = self.detector_blue.get_rect()\n        self.fighter_red_rect = self.fighter_red.get_rect()\n        self.fighter_blue_rect = self.fighter_blue.get_rect() \n        self.side1_detector = []\n        self.side1_fighter  = []\n        self.side2_detector = []\n        self.side2_fighter  = []\n\n        for index in range(o_detector_num):\n            detector = {}\n            detector['detector'] = copy.deepcopy(self.detector_red)\n            detector['rect'] = copy.deepcopy(self.detector_red_rect)\n            self.side1_detector.append(detector.copy())\n\n        for index in range(o_fighter_num):\n            fighter = {}\n            fighter['fighter'] = copy.deepcopy(self.fighter_red)\n            fighter['rect'] = copy.deepcopy(self.fighter_red_rect)\n            self.side1_fighter.append(fighter.copy())\n\n        for index in range(e_detector_num):\n            detector = {}\n            detector['detector'] = copy.deepcopy(self.detector_blue)\n            detector['rect'] = copy.deepcopy(self.detector_blue_rect)\n            self.side2_detector.append(detector.copy())\n\n        for index in range(e_fighter_num):\n            fighter = {}\n            fighter['fighter'] = copy.deepcopy(self.fighter_blue)\n            fighter['rect'] = copy.deepcopy(self.fighter_blue_rect)\n            self.side2_fighter.append(fighter.copy())\n\n\n        self.state_time = pygame.time.Clock()\n\n        \n\n    def dis_update(self, done, step, o_detector_data_obs_list, o_fighter_data_obs_list, e_detector_data_obs_list, e_fighter_data_obs_list, o_detector_data_reward_list, o_fighter_data_reward_list, e_detector_data_reward_list, e_fighter_data_reward_list, o_all_reward, e_all_reward):\n        print('update')\n        print((o_detector_data_obs_list))\n        print((o_fighter_data_obs_list))\n        print((o_detector_data_reward_list))\n        print((o_fighter_data_reward_list))\n        print((o_all_reward))\n        # b=a\n        return self.render3.dis_update(done, step, o_detector_data_obs_list, o_fighter_data_obs_list, e_detector_data_obs_list, e_fighter_data_obs_list, o_detector_data_reward_list, o_fighter_data_reward_list, e_detector_data_reward_list, e_fighter_data_reward_list, o_all_reward, e_all_reward)\n        \n        color = 255, 255, 255\n        speed = [5, 5]\n\n        self.detector_red_rect = self.detector_red_rect.move(speed)\n        self.detector_blue_rect = self.detector_blue_rect.move(speed)\n        self.screen.fill(color)\n        self.screen.blit(self.detector_red, self.detector_red_rect)\n        self.screen.blit(self.detector_blue, self.detector_blue_rect)\n        pygame.display.update()\n        self.state_time.tick(30)\n\n        return\n    def dis_update_done_font(self):\n        print('update done font')\n        return self.render3.dis_update_done_font()\n    def dis_update_font(self, step, red_reward, blue_reward, red_detector_num, blue_detector_num, red_fighter_num, blue_fighter_num, red_missile_num, blue_missile_num):\n        print('dis_update_font')\n        return self.render3.dis_update_font(step, red_reward, blue_reward, red_detector_num, blue_detector_num, red_fighter_num, blue_fighter_num, red_missile_num, blue_missile_num)\n    def dis_update_pos(self, o_detector_pos_list, o_fighter_pos_list, e_detector_pos_list, e_fighter_pos_list):\n        print('dis_update_pos')\n        return self.render3.dis_update_pos(o_detector_pos_list, o_fighter_pos_list, e_detector_pos_list, e_fighter_pos_list)\n    def draw_course(self, center_point_x, center_point_y, course, course_r):\n        print('draw_course')\n        return self.render3.draw_course(center_point_x, center_point_y, course, course_r)\n    def draw_fight_rela(self, center_point_x, center_point_y, striking_list, detector_list, fighter_list, line_colour):\n        print('draw_fight_rela')\n        return self.render3.draw_fight_rela(center_point_x, center_point_y, striking_list, detector_list, fighter_list, line_colour)\n"
  },
  {
    "path": "environment/world/__init__.py",
    "content": "__pyarmor__(__name__, __file__, b'\\xec\\x50\\x8c\\x64\\x26\\x42\\xd6\\x01\\x10\\x54\\xca\\x9c\\xb6\\x36\\x84\\x05\\x6a\\x0b\\xf3\\xc4\\x16\\x01\\xb0\\x49\\xdd\\x1c\\xf4\\xf8\\x5a\\xe1\\xe0\\xc4\\xbe\\x1b\\x41\\x5d\\x2c\\x21\\x77\\xb1\\x53\\x58\\xd9\\xeb\\x22\\xb3\\x4c\\x09\\x12\\xdb\\x19\\xce\\x41\\x3b\\xeb\\xb0\\x0d\\x17\\x26\\x12\\xf9\\x51\\x94\\x9e\\xf1\\xf5\\x85\\x77\\xd0\\x70\\xdf\\xce\\x84\\x05\\x76\\x90\\x38\\xf1\\x10\\xd7\\x44\\x53\\x87\\x32\\x78\\xa3\\x65\\xcd\\x08\\xcf\\x45\\x20\\x53\\x90\\x31\\x2c\\x73\\xa3\\x04\\x11\\xfb\\x6f\\xf4\\x36\\xd1\\x62\\xd3\\x8e\\xcd\\x57\\x1f\\xfa\\x46\\xe3\\x9e\\x0a\\x32\\xc9\\x4d\\x7d\\xa1\\x37\\xba\\xe0\\xe3\\x84\\x87\\xb1\\x25\\x00\\x11\\x98\\x1a\\x78\\xdf\\x6f\\x4c\\xd6\\x38\\x0a\\x58\\xb0\\x25\\xee\\xf1\\x9f\\x45\\x5f\\x65\\x92\\xe1\\x38\\x5d\\xe3\\x1d', 1)"
  },
  {
    "path": "environment/world/config.py",
    "content": "\nclass GlobalVar:\n\tapi_raw = 0\n\tapi_spatial = 1\n\tband_L = 0\n\tband_S = 1\n\tband_X = 2\n\tband_fp_num = [20, 20, 10]\n\tdetection_hit_probability = [0.2, 0.3, 0.9, 0.6]\n\thit_detection_source_detector_L = 0\n\thit_detection_source_detector_S = 1\n\thit_detection_source_fighter = 2\n\thit_detection_source_passive = 3\n\timg_obs_reduce_ratio = 10\n\tj_coverage_angle = [45, 30, 10]\n\tj_max_range = [400, 400, 300]\n\tl_missile_dis = 120\n\tl_missile_hit_probability = 0.8\n\tl_missile_op_dec_ratio = 0.05\n\tl_missile_op_req = 10\n\tl_missile_type = 1\n\tl_missile_num = 2\n\tpassive_loc_continuous_detection_req = 5\n\tpassive_loc_fighter_num_req = 4\n\tr_coverage_angle_X = 120\n\t# major lobe\n\tr_jammed_angle_mlob = [10, 10, 4]\n\tr_jammed_range_mlobe = [120, 150, 30]\n\t# side lobe\n\tr_jammed_range_slobe_aim = [220, 260, 80]\n\tr_jammed_range_slobe_block = [300, 320, 120]\n\tr_max_range = [400, 400, 180]\n\ts_missile_dis = 50\n\ts_missile_hit_probability = 0.9\n\ts_missile_op_dec_ratio = 0.05\n\ts_missile_op_req = 4\n\ts_missile_type = 2\n\ts_missile_num = 4\n\ndef get_api_raw():\n\treturn GlobalVar.api_raw\n    \ndef get_api_spatial():\n\treturn GlobalVar.api_spatial\n    \ndef get_band_L():\n\treturn GlobalVar.band_L\n    \ndef get_band_S():\n\treturn GlobalVar.band_S\n    \ndef get_band_X():\n\treturn GlobalVar.band_X\n    \ndef get_band_fp_num(band):\n\treturn GlobalVar.band_fp_num[band]\n    \ndef get_detection_hit_probability(typ):\n\treturn GlobalVar.detection_hit_probability[typ]\n    \ndef get_hit_detection_source_detector_L():\n\treturn GlobalVar.hit_detection_source_detector_L\n    \ndef get_hit_detection_source_detector_S():\n\treturn GlobalVar.hit_detection_source_detector_S\n    \ndef get_hit_detection_source_fighter():\n\treturn GlobalVar.hit_detection_source_fighter\n    \ndef get_hit_detection_source_passive():\n\treturn GlobalVar.hit_detection_source_passive\n    \ndef get_img_obs_redu_ratio():\n\treturn GlobalVar.img_obs_reduce_ratio\n    \ndef get_j_coverage_angle(band):\n\treturn GlobalVar.j_coverage_angle[band]\n    \ndef get_j_max_range(band):\n\treturn GlobalVar.j_max_range[band]\n    \ndef get_l_missile_dis():\n\treturn GlobalVar.l_missile_dis\n    \ndef get_l_missile_hit_probability():\n\treturn GlobalVar.l_missile_hit_probability\n    \ndef get_l_missile_op_dec_ratio():\n\treturn GlobalVar.l_missile_op_dec_ratio\n    \ndef get_l_missile_op_req():\n\treturn GlobalVar.l_missile_op_req\n    \ndef get_l_missile_type():\n\treturn GlobalVar.l_missile_type\n\ndef get_l_missile_num():\n\treturn GlobalVar.l_missile_num\n    \ndef get_passive_loc_continuous_detection_req():\n\treturn GlobalVar.passive_loc_continuous_detection_req\n    \ndef get_passive_loc_fighter_num_req():\n\treturn GlobalVar.passive_loc_fighter_num_req\n    \ndef get_r_coverage_angle_X():\n\treturn GlobalVar.r_coverage_angle_X\n    \ndef get_r_jammed_angle_mlob(band):\n\treturn GlobalVar.r_jammed_angle_mlob[band]\n    \ndef get_r_jammed_range_mlobe(band):\n\treturn GlobalVar.r_jammed_range_mlobe[band]\n    \ndef get_r_jammed_range_slobe_aim(band):\n\treturn GlobalVar.r_jammed_range_slobe_aim[band]\n    \ndef get_r_jammed_range_slobe_block(band):\n\treturn GlobalVar.r_jammed_range_slobe_block[band]\n    \ndef get_r_max_range(band):\n\treturn GlobalVar.r_max_range[band]\n    \ndef get_s_missile_dis():\n\treturn GlobalVar.s_missile_dis\n    \ndef get_s_missile_hit_probability():\n\treturn GlobalVar.s_missile_hit_probability\n    \ndef get_s_missile_op_dec_ratio():\n\treturn GlobalVar.s_missile_op_dec_ratio\n    \ndef get_s_missile_op_req():\n\treturn GlobalVar.s_missile_op_req\n    \ndef get_s_missile_type():\n\treturn GlobalVar.s_missile_type\n\ndef get_s_missile_num():\n\treturn GlobalVar.s_missile_num\n"
  },
  {
    "path": "environment/world/detection_calc.py",
    "content": "import copy\nimport world.config as config\nimport world.position_calc as position_calc\n\n\ndef passive_detection_calc(self_context, enemy_fighter_context_list):\n    '''\n    根据敌方战机干扰机接收情况，更新自身上下文中无源侦测计数器，根据可侦测标准对自身上下文中可侦测指示赋值\n    需确定的问题：干扰机被动侦测雷达信号，能够全向接收雷达信号还是指向性接收？目前认为干扰机接收信号与干扰信号发射的指向性相同\n    :param self_context: ：自身上下文\n    :param enemy_fighter_context_list: 敌方战机上下文列表\n    :return:\n    '''\n\n    for index, enemy in enumerate(enemy_fighter_context_list):\n        exist = False\n        for j_receive in enemy['j_receive_list']:\n            if self_context['id'] == j_receive['id']:\n                exist = True\n        if exist:\n            self_context['detection_count_list'][index] += 1\n        else:\n            self_context['detection_count_list'][index] = 0\n\ndef radar_visible_calc(self_context, enemy_detector_context_list, enemy_fighter_context_list):\n    '''\n    计算自身雷达的可见敌方目标，将自身上下文中雷达可见目标列表更新\n    规则：\n    1. 当一个雷达收到n个干扰机干扰时，在干扰机方向±5°范围内收到主瓣干扰，在其他方向收到副瓣干扰\n    2. 若有n个干扰机对一个雷达进行干扰，只要有瞄准式干扰存在，则雷达整体受到瞄准式副瓣干扰影响，若无瞄准式干扰存在，则雷达受到阻塞式干扰影响\n    3. 预警机雷达为全向探测，战机雷达为扇形方向探测\n    :param self_context:自身上下文\n    :param enemy_detector_context_list:敌方预警机上下文列表\n    :param enemy_fighter_context_list:敌方战机上下文列表\n    :return: 新发现detector数量和fighter数量\n    '''\n\n    radar_list = []\n    r_band = self_context['r_band']\n    o_pos_x = self_context['pos_x']\n    o_pos_y = self_context['pos_y']\n    course = self_context['course']\n    r_max_range = config.get_r_max_range(r_band)\n\n    # 预警机雷达为全向探测\n    if r_band == config.get_band_L() or r_band == config.get_band_S():\n        for unit in (enemy_detector_context_list + enemy_fighter_context_list):\n            # 战机已被摧毁\n            if not unit['alive']:\n                continue\n            e_pos_x = unit['pos_x']\n            e_pos_y = unit['pos_y']\n            distance = position_calc.get_distance(o_pos_x, o_pos_y, e_pos_x, e_pos_y)\n            if distance <= r_max_range:\n                radar_list.append(unit)\n    # 战机雷达为扇形方向探测\n    else:\n        r_coverage_angle_X = config.get_r_coverage_angle_X()\n        r_angle_low_bound = course - r_coverage_angle_X/2\n        r_angle_up_bound  = course + r_coverage_angle_X/2\n\n        for unit in (enemy_detector_context_list + enemy_fighter_context_list):\n            # 战机已被摧毁\n            if not unit['alive']:\n                continue\n\n            e_pos_x = unit['pos_x']\n            e_pos_y = unit['pos_y']\n            distance = position_calc.get_distance(o_pos_x, o_pos_y, e_pos_x, e_pos_y)\n            angle = position_calc.angle_cal(o_pos_x, o_pos_y, e_pos_x, e_pos_y)\n            # the coverage angle cross the horizon line\n            if r_angle_low_bound < 0 and r_angle_up_bound > 0:\n                if distance <= r_max_range and (angle >= (r_angle_low_bound + 360) or angle <= r_angle_up_bound):\n                    radar_list.append(unit)\n            elif r_angle_low_bound < 360 and r_angle_up_bound > 360:\n                if distance <= r_max_range and (angle >= r_angle_low_bound or angle <= (r_angle_up_bound - 360)):\n                    radar_list.append(unit)\n            else:\n                if distance <= r_max_range and angle >= r_angle_low_bound and angle <= r_angle_up_bound:\n                    radar_list.append(unit)\n\n    # 计算雷达新发现目标的数量，用于确定无人机的奖励\n    new_detector_count = 0\n    new_fighter_count  = 0\n    id_list = []\n    for item in self_context['radar_visible_list']:\n        id_list.append(item['id'])\n    for item in radar_list:\n        if not item['id'] in id_list:\n            if item['id'] > len(enemy_detector_context_list):\n                new_fighter_count += 1\n            else:\n                new_detector_count += 1\n\n    self_context['radar_visible_list'].clear()\n    for radar in radar_list:\n        enemy = {}\n        enemy['id'] = radar['id']\n        if radar['r_band'] == config.get_band_L() or radar['r_band'] == config.get_band_S():\n            enemy['type'] = 0\n        else:\n            enemy['type'] = 1\n        enemy['pos_x'] = radar['pos_x']\n        enemy['pos_y'] = radar['pos_y']\n        self_context['radar_visible_list'].append(enemy)\n\n    return new_detector_count, new_fighter_count\n\n# TODO: uncomplete\ndef under_jam_check(rader_x, radar_y, radar_band, jammer_x, jammer_y, jammer_course):\n    '''\n    判断雷达是否处于干扰机的干扰范围内\n    :param rader_x:雷达机横坐标\n    :param radar_y: 雷达机纵坐标\n    :param radar_band: 雷达波段\n    :param jammer_x: 干扰机横坐标\n    :param jammer_y: 干扰机纵坐标\n    :param jammer_course: 干扰机航向\n    :return: True：处于干扰范围, False: 不处于干扰范围\n    '''\n    print('under_jam_check')\n    result = null\n    return result\n"
  },
  {
    "path": "environment/world/em_battle.py",
    "content": "import copy\nimport random\nimport numpy as np\nimport world.config as config\nfrom render.render_pic import Render\nimport configuration.reward as reward\nimport world.strike_calc as strike_calc\nimport world.position_calc as position_calc\nimport world.detection_calc as detection_calc\n\n\nclass BattleField:\n    def __init__(self, size_x, size_y, o_detector_list, o_fighter_list, e_detector_list, e_fighter_list, max_step=5000, render=False, render_interval=1, random_pos=False, log=False, random_seed=-1):\n        '''\n        环境类初始化\n        :param size_x: 横向尺寸\n        :param size_y: 纵向尺寸\n        :param o_detector_list: 势力1预警机配置\n        :param o_fighter_list: 势力1战机配置\n        :param e_detector_list: 势力2预警机配置\n        :param e_fighter_list: 势力2战机配置\n        :param max_step:最大step，0：无限制\n        :param render:显示控制\n        :param render_interval:render显示间隔\n        :param random_pos:初始位置配置(False: 势力1在左，势力2在右；True:上下左右随机初始位置，双方相对)\n        :param log: 日志开启指示，False：无日志，其他值：日志文件夹名称\n        :param random_seed: 随机数种子值，-1：重新生成，其他：种子值\n        '''\n\n        self.battlefield_size_x = size_x\n        self.battlefield_size_y = size_y\n        self.e_detector_num     = len(e_detector_list)\n        self.e_fighter_num      = len(e_fighter_list)\n        self.o_detector_num     = len(o_detector_list)\n        self.o_fighter_num      = len(o_fighter_list)\n        self.step_count         = 0\n        self.max_step           = max_step\n        self.done               = False\n        self.render_flag        = render\n        self.render_interval    = render_interval\n        self.random_seed        = random_seed\n        self.random_pos         = random_pos\n        self.log                = log\n        self.render_obj         = Render(self.battlefield_size_x, self.battlefield_size_y)\n        self.log_obj            = None\n        if random_seed != -1:\n            random.seed(random_seed)\n        self.random_obj         = random\n\n\n        self.e_detector_property_list = e_detector_list\n        self.e_detector_reward = [0] * self.e_detector_num\n        self.e_detector_status_list = []\n        self.e_fighter_property_list = e_fighter_list\n        self.e_fighter_reward = [0] * self.e_fighter_num\n        self.e_fighter_status_list = []\n        self.e_passive_detection_enemy_list = []\n        self.e_strike_list = []\n        self.e_game_reward = 0\n\n        self.o_detector_property_list = o_detector_list\n        self.o_detector_reward = [0] * self.o_detector_num\n        self.o_detector_status_list = []\n        self.o_fighter_property_list = o_fighter_list\n        self.o_fighter_reward = [0] * self.o_fighter_num\n        self.o_fighter_status_list = []\n        self.o_passive_detection_enemy_list = []\n        self.o_strike_list = []\n        self.o_game_reward = 0\n\n        self.side1_detector_action = []\n        self.side1_fighter_action  = []\n        self.side2_detector_action = []\n        self.side2_fighter_action  = []\n\n        pos_x, pos_y, o_course, e_course = position_calc.pos_generate(self.o_detector_num, self.o_fighter_num, self.e_detector_num, self.e_fighter_num, \\\n            self.battlefield_size_x, self.battlefield_size_y, self.random_obj, self.random_pos)\n\n        for index in range(self.o_detector_num + self.o_fighter_num):\n            status = {}\n            status['id'] = index + 1\n            status['alive'] = True\n            status['pos_x'] = pos_x[index]\n            status['pos_y'] = pos_y[index]\n            status['course'] = o_course\n            status['radar_enable'] = True\n            status['radar_fp'] = 1\n            status['radar_visible_list'] = []\n            status['passive_location_ind'] = False\n            status['detection_count_list'] = [0 for i in range(self.e_fighter_num)]\n            if index >= self.o_detector_num:\n                status['radar_enable'] = False\n                status['l_missile_left'] = config.get_l_missile_num()\n                status['s_missile_left'] = config.get_s_missile_num()\n                status['j_enable'] = False\n                status['j_fp'] = 0\n                status['j_receive_list'] = []\n                self.o_fighter_status_list.append(status.copy())\n            else:\n                self.o_detector_status_list.append(status.copy())\n        for index in range(self.e_detector_num + self.e_fighter_num):\n            status = {}\n            status['id'] = index + 1\n            status['alive'] = True\n            status['pos_x'] = pos_x[index+self.o_detector_num+self.o_fighter_num]\n            status['pos_y'] = pos_y[index+self.o_detector_num+self.o_fighter_num]\n            status['course'] = e_course\n            status['radar_enable'] = True\n            status['radar_fp'] = 1\n            status['radar_visible_list'] = []\n            status['passive_location_ind'] = False\n            status['detection_count_list'] = [0 for i in range(self.o_fighter_num)]\n            if index >= self.e_detector_num:\n                status['radar_enable'] = False\n                status['l_missile_left'] = config.get_l_missile_num()\n                status['s_missile_left'] = config.get_s_missile_num()\n                status['j_enable'] = False\n                status['j_fp'] = 0\n                status['j_receive_list'] = []\n                self.e_fighter_status_list.append(status.copy())\n            else:\n                self.e_detector_status_list.append(status.copy())\n\n        for index in range(self.e_detector_num + self.e_fighter_num):\n            action = {}\n            action['course'] = e_course\n            action['r_iswork'] = True\n            action['r_fre_point'] = 1\n            if index >= self.e_detector_num:\n                action['r_iswork'] = False\n                action['j_iswork'] = False\n                action['j_fre_point'] = 0\n                action['hit_target'] = 0\n                action['missile_type'] = 0\n                self.side2_fighter_action.append(action.copy())\n            else:\n                self.side2_detector_action.append(action.copy())\n        for index in range(self.o_detector_num + self.o_fighter_num):\n            action = {}\n            action['course'] = o_course\n            action['r_iswork'] = True\n            action['r_fre_point'] = 1\n            if index >= self.o_detector_num:\n                action['r_iswork'] = False\n                action['j_iswork'] = False\n                action['j_fre_point'] = 0\n                action['hit_target'] = 0\n                action['missile_type'] = 0\n                self.side1_fighter_action.append(action.copy())\n            else:\n                self.side1_detector_action.append(action.copy())\n\n    def get_alive_status(self, o_detector_status_list, o_fighter_status_list, e_detector_status_list, e_fighter_status_list):\n        \n        side1_detector_alive_num = 0\n        side1_fighter_alive_num  = 0\n        side1_l_missile_left     = 0\n        side1_s_missile_left     = 0\n\n        side2_detector_alive_num = 0\n        side2_fighter_alive_num  = 0\n        side2_l_missile_left     = 0\n        side2_s_missile_left     = 0\n\n        for item in o_detector_status_list:\n            if item['alive']:\n                side1_detector_alive_num += 1\n        for item in o_fighter_status_list:\n            if item['alive']:\n                side1_fighter_alive_num += 1\n                side1_l_missile_left += item['l_missile_left']\n                side1_s_missile_left += item['s_missile_left']\n        for item in e_detector_status_list:\n            if item['alive']:\n                side2_detector_alive_num += 1\n        for item in e_fighter_status_list:\n            if item['alive']:\n                side2_fighter_alive_num += 1\n                side2_l_missile_left += item['l_missile_left']\n                side2_s_missile_left += item['s_missile_left']\n\n        return side1_detector_alive_num, side1_fighter_alive_num, side1_l_missile_left, side1_s_missile_left, \\\n        side2_detector_alive_num, side2_fighter_alive_num, side2_l_missile_left, side2_s_missile_left\n\n    def get_done(self):\n        '''\n        获取当前done\n        :return: done: True, False\n        '''\n        return self.done\n\n    def get_obs_raw(self):\n        '''\n        获取当前obs\n        :return:obs\n        detector data obs:{'id':编号, 'alive': 存活, 'pos_x': 横坐标, 'pos_y': 纵坐标, 'course': 航向, 'r_iswork': 雷达开关, 'r_fre_point': 频点,\n              'r_visible_list': 雷达可见敌人}\n        fighter data obs:{'id':编号, 'alive': 存活, 'pos_x': 横坐标, 'pos_y': 纵坐标, 'course': 航向, 'r_iswork': 雷达开关, 'r_fre_point': 频点,\n              'r_visible_list': 雷达可见敌人, 'j_iswork': 干扰机开关, 'j_fre_point': 干扰机频点, 'j_recv_list': 干扰机发现信号源, 'l_missile_left': 远程导弹余量, 's_missile_left': 中程导弹余量}\n        '''\n        side1_detector_obs_list = []\n        side1_fighter_obs_list  = []\n        side2_detector_obs_list = []\n        side2_fighter_obs_list  = []\n\n        dict_key_list = ['id', 'alive', 'pos_x', 'pos_y', 'course', 'r_iswork', 'r_fre_point', 'r_visible_list']\n        list_key_list = ['id', 'alive', 'pos_x', 'pos_y', 'course', 'radar_enable', 'radar_fp', 'radar_visible_list']\n        for index in range(self.o_detector_num):\n            side1_detector_obs_dict = {}\n            for key_index in range(len(dict_key_list)):\n                side1_detector_obs_dict[dict_key_list[key_index]] = self.o_detector_status_list[index][list_key_list[key_index]]  \n            side1_detector_obs_dict['last_reward'] = self.o_detector_reward[index]\n            side1_detector_obs_dict['last_action'] = self.side1_detector_action[index]\n            side1_detector_obs_list.append(side1_detector_obs_dict.copy())\n            \n        for index in range(self.e_detector_num):\n            side2_detector_obs_dict = {}\n            for key_index in range(len(dict_key_list)):\n                side2_detector_obs_dict[dict_key_list[key_index]] = self.e_detector_status_list[index][list_key_list[key_index]]\n            side2_detector_obs_dict['last_reward'] = self.e_detector_reward[index]\n            side2_detector_obs_dict['last_action'] = self.side2_detector_action[index]\n            side2_detector_obs_list.append(side2_detector_obs_dict.copy())\n\n        dict_key_list += ['j_iswork', 'j_fre_point', 'j_recv_list', 'l_missile_left', 's_missile_left']\n        list_key_list += ['j_enable', 'j_fp',     'j_receive_list', 'l_missile_left', 's_missile_left']\n        for index in range(self.o_fighter_num):\n            side1_fighter_obs_dict = {}\n            for key_index in range(len(dict_key_list)):\n                side1_fighter_obs_dict[dict_key_list[key_index]] = self.o_fighter_status_list[index][list_key_list[key_index]]\n            side1_fighter_obs_dict['striking_list'] = []\n            side1_fighter_obs_dict['striking_dict_list'] = []\n            for item in self.o_strike_list:\n                if item['attacker_id'] == self.o_fighter_status_list[index]['id']:\n                    side1_fighter_obs_dict['striking_list'].append(item['target_id'])\n                    striking_dict = {}\n                    striking_dict['target_id'] = item['target_id']\n                    if item['target_id'] > self.e_detector_num:\n                        striking_dict['pos_x'] = self.e_fighter_status_list[item['target_id']-self.e_detector_num-1]['pos_x']\n                        striking_dict['pos_y'] = self.e_fighter_status_list[item['target_id']-self.e_detector_num-1]['pos_y']\n                        striking_dict['type']  = 1\n                    else:\n                        striking_dict['pos_x'] = self.e_detector_status_list[item['target_id']-1]['pos_x']\n                        striking_dict['pos_y'] = self.e_detector_status_list[item['target_id']-1]['pos_y']\n                        striking_dict['type']  = 0\n                    side1_fighter_obs_dict['striking_dict_list'].append(striking_dict.copy())\n            \n            side1_fighter_obs_dict['last_reward'] = self.o_fighter_reward[index]\n            side1_fighter_obs_dict['last_action'] = self.side1_fighter_action[index]\n            side1_fighter_obs_list.append(side1_fighter_obs_dict.copy())\n\n        for index in range(self.e_fighter_num):\n            side2_fighter_obs_dict = {}\n            for key_index in range(len(dict_key_list)):\n                side2_fighter_obs_dict[dict_key_list[key_index]] = self.e_fighter_status_list[index][list_key_list[key_index]]\n            side2_fighter_obs_dict['striking_list'] = []\n            side2_fighter_obs_dict['striking_dict_list'] = []\n            for item in self.e_strike_list:\n                if item['attacker_id'] == self.e_fighter_status_list[index]['id']:\n                    side2_fighter_obs_dict['striking_list'].append(item['target_id'])\n                    striking_dict = {}\n                    striking_dict['target_id'] = item['target_id']\n                    if item['target_id'] > self.o_detector_num:\n                        striking_dict['pos_x'] = self.o_fighter_status_list[item['target_id']-self.o_detector_num-1]['pos_x']\n                        striking_dict['pos_y'] = self.o_fighter_status_list[item['target_id']-self.o_detector_num-1]['pos_y']\n                        striking_dict['type']  = 1\n                    else:\n                        striking_dict['pos_x'] = self.o_detector_status_list[item['target_id']-1]['pos_x']\n                        striking_dict['pos_y'] = self.o_detector_status_list[item['target_id']-1]['pos_y']\n                        striking_dict['type']  = 0\n                    side2_fighter_obs_dict['striking_dict_list'].append(striking_dict.copy())\n            side2_fighter_obs_dict['last_reward'] = self.e_fighter_reward[index]\n            side2_fighter_obs_dict['last_action'] = self.side2_fighter_action[index]\n            side2_fighter_obs_list.append(side2_fighter_obs_dict.copy())\n\n        side1_joint_obs_list = {}\n        side1_joint_obs_list['strike_list'] = self.o_strike_list\n        side1_joint_obs_list['passive_detection_enemy_list'] = []\n        side2_joint_obs_list = {}\n        side2_joint_obs_list['strike_list'] = self.e_strike_list\n        side2_joint_obs_list['passive_detection_enemy_list'] = []\n\n        return (side1_detector_obs_list, side1_fighter_obs_list, side1_joint_obs_list, side2_detector_obs_list, side2_fighter_obs_list, side2_joint_obs_list)\n\n    def get_reward(self):\n        # TODO: uncomplete\n        return self.get_reward_list()\n   \n    def get_reward_list(self):\n        '''\n        获取当前reward\n        :return:o_detector_reward：o方预警机动作回报，o_fighter_reward：o方战机动作回报，o_game_reward，o方输赢回报\n                e_detector_reward：e方预警机动作回报，e_fighter_reward：e方战机动作回报，e_game_reward，e方输赢回报\n        '''\n        return self.o_detector_reward, self.o_fighter_reward, self.o_game_reward, \\\n        self.e_detector_reward, self.e_fighter_reward, self.e_game_reward\n   \n    def reset(self):\n        self.step_count = 0\n        self.done = False\n        self.e_detector_reward = [0] * self.e_detector_num\n        self.e_detector_status_list.clear()\n        self.e_fighter_reward = [0] * self.e_fighter_num\n        self.e_fighter_status_list.clear()\n        self.e_passive_detection_enemy_list.clear()\n        self.e_strike_list.clear()\n        self.e_game_reward = 0\n\n        self.o_detector_reward = [0] * self.o_detector_num\n        self.o_detector_status_list.clear()\n        self.o_fighter_reward = [0] * self.o_fighter_num\n        self.o_fighter_status_list.clear()\n        self.o_passive_detection_enemy_list.clear()\n        self.o_strike_list.clear()\n        self.o_game_reward = 0\n\n        self.side1_detector_action.clear()\n        self.side1_fighter_action.clear()\n        self.side2_detector_action.clear()\n        self.side2_fighter_action.clear()\n\n        pos_x, pos_y, o_course, e_course = position_calc.pos_generate(self.e_detector_num, self.e_fighter_num, self.o_detector_num, self.o_fighter_num, \\\n            self.battlefield_size_x, self.battlefield_size_y, self.random_obj, False)\n        \n        for index in range(self.o_detector_num + self.o_fighter_num):\n            status = {}\n            status['id'] = index + 1\n            status['alive'] = True\n            status['pos_x'] = pos_x[index]\n            status['pos_y'] = pos_y[index]\n            status['course'] = o_course\n            status['radar_enable'] = True\n            status['radar_fp'] = 1\n            status['radar_visible_list'] = []\n            status['passive_location_ind'] = False\n            status['detection_count_list'] = [0 for i in range(self.e_fighter_num)]\n            if index >= self.o_detector_num:\n                status['radar_enable'] = False\n                status['l_missile_left'] = config.get_l_missile_num()\n                status['s_missile_left'] = config.get_s_missile_num()\n                status['j_enable'] = False\n                status['j_fp'] = 0\n                status['j_receive_list'] = []\n                self.o_fighter_status_list.append(status.copy())\n            else:\n                self.o_detector_status_list.append(status.copy())\n\n        for index in range(self.e_detector_num + self.e_fighter_num):\n            status = {}\n            status['id'] = index + 1\n            status['alive'] = True\n            status['pos_x'] = pos_x[index+self.o_detector_num+self.o_fighter_num]\n            status['pos_y'] = pos_y[index+self.o_detector_num+self.o_fighter_num]\n            status['course'] = e_course\n            status['radar_enable'] = True\n            status['radar_fp'] = 1\n            status['radar_visible_list'] = []\n            status['passive_location_ind'] = False\n            status['detection_count_list'] = [0 for i in range(self.o_fighter_num)]\n            if index >= self.e_detector_num:\n                status['radar_enable'] = False\n                status['l_missile_left'] = config.get_l_missile_num()\n                status['s_missile_left'] = config.get_s_missile_num()\n                status['j_enable'] = False\n                status['j_fp'] = 0\n                status['j_receive_list'] = []\n                self.e_fighter_status_list.append(status.copy())\n            else:\n                self.e_detector_status_list.append(status.copy())\n\n        for index in range(self.e_detector_num + self.e_fighter_num):\n            action = {}\n            action['course'] = e_course\n            action['r_iswork'] = True\n            action['r_fre_point'] = 1\n            if index >= self.e_detector_num:\n                action['r_iswork'] = False\n                action['j_iswork'] = False\n                action['j_fre_point'] = 0\n                action['hit_target'] = 0\n                action['missile_type'] = 0\n                self.side2_fighter_action.append(action.copy())\n            else:\n                self.side2_detector_action.append(action.copy())\n        for index in range(self.o_detector_num + self.o_fighter_num):\n            action = {}\n            action['course'] = o_course\n            action['r_iswork'] = True\n            action['r_fre_point'] = 1\n            if index >= self.o_detector_num:\n                action['r_iswork'] = False\n                action['j_iswork'] = False\n                action['j_fre_point'] = 0\n                action['hit_target'] = 0\n                action['missile_type'] = 0\n                self.side1_fighter_action.append(action.copy())\n            else:\n                self.side1_detector_action.append(action.copy())\n        # self.env.reset()\n   \n    def set_surrender(self, side):\n        '''\n        投降\n        :param side: 0: side1, 1:side2, 2: both\n        :return:\n        '''\n        self.done = True\n        if side == 0:\n            self.o_game_reward = reward.get_reward_totally_lose()\n            self.e_game_reward = reward.get_reward_totally_win()\n        if side == 1:\n            self.o_game_reward = reward.get_reward_totally_win()\n            self.e_game_reward = reward.get_reward_totally_lose()\n        if side == 2:\n            self.o_game_reward = reward.get_reward_draw()\n            self.e_game_reward = reward.get_reward_draw()\n\n    def show(self):\n        obs_data = self.get_obs_raw()\n        self.render_obj.dis_update(self.done, self.step_count, obs_data[0], obs_data[1], obs_data[3], obs_data[4], self.o_detector_reward, self.o_fighter_reward, self.e_detector_reward, self.e_fighter_reward, self.o_game_reward, self.e_game_reward)\n\n    def step(self, side1_detector_action, side1_fighter_action, side2_detector_action, side2_fighter_action):\n        '''\n        接收动作信息执行step，可支持array和list两种形式动作\n        :param side1_detector_action:\n        :param side1_fighter_action:\n        :param side2_detector_action:\n        :param side2_fighter_action:\n        :return:\n        '''\n        self.side1_detector_action = copy.deepcopy(side1_detector_action)\n        self.side1_fighter_action  = copy.deepcopy(side1_fighter_action)\n        self.side2_detector_action = copy.deepcopy(side2_detector_action)\n        self.side2_fighter_action  = copy.deepcopy(side2_fighter_action)\n        self.step_count += 1\n        \n        # self.env.step(side1_detector_action, side1_fighter_action, side2_detector_action, side2_fighter_action)\n\n        # generate detector and fighter context\n        e_detector_context_list = []\n        o_detector_context_list = []\n        e_fighter_context_list = []\n        o_fighter_context_list = []\n        for index in range(self.e_detector_num):\n            self_context = {}\n            self_context.update(self.e_detector_property_list[index])\n            self_context.update(self.e_detector_status_list[index])\n            e_detector_context_list.append(self_context.copy())\n        for index in range(self.o_detector_num):\n            self_context = {}\n            self_context.update(self.o_detector_property_list[index])\n            self_context.update(self.o_detector_status_list[index])\n            o_detector_context_list.append(self_context.copy())\n        for index in range(self.e_fighter_num):\n            self_context = {}\n            self_context.update(self.e_fighter_property_list[index])\n            self_context.update(self.e_fighter_status_list[index])\n            e_fighter_context_list.append(self_context.copy())\n        for index in range(self.o_fighter_num):\n            self_context = {}\n            self_context.update(self.o_fighter_property_list[index])\n            self_context.update(self.o_fighter_status_list[index])\n            o_fighter_context_list.append(self_context.copy())\n\n        # update strike list\n        for index in range(self.o_fighter_num):\n            print(side1_fighter_action[index])\n            if self.o_fighter_status_list[index]['alive'] and side1_fighter_action[index]['hit_target']:\n                target_id = side1_fighter_action[index]['hit_target']\n                missile_type = side1_fighter_action[index]['missile_type']\n                enemy_status = None\n                enemy_index = 0\n                if missile_type == config.get_s_missile_type():\n                    if self.o_fighter_status_list[index]['s_missile_left'] <= 0:\n                        continue\n                    self.o_fighter_status_list[index]['s_missile_left'] -= 1\n                if missile_type == config.get_l_missile_type():\n                    if self.o_fighter_status_list[index]['l_missile_left'] <= 0:\n                        continue\n                    self.o_fighter_status_list[index]['l_missile_left'] -= 1\n                if target_id > self.e_detector_num + self.e_fighter_num:\n                    target_id -= self.e_detector_num + self.e_fighter_num\n                if target_id > self.e_detector_num:\n                    enemy_status = self.e_fighter_status_list\n                    enemy_index = target_id - self.e_detector_num - 1\n                else:\n                    enemy_status = self.e_detector_status_list\n                    enemy_index = target_id - 1\n                valid = strike_calc.strike_act_validation_and_initiation(missile_type, o_fighter_context_list[index], o_detector_context_list,\n                                                                         enemy_status[enemy_index], self.o_strike_list)\n                if valid:\n                    self.o_fighter_reward[index] += reward.get_reward_strike_act_valid()\n                else:\n                    self.o_fighter_reward[index] += reward.get_reward_strike_act_invalid()\n        for index in range(self.e_fighter_num):\n            if self.e_fighter_status_list[index]['alive'] and side2_fighter_action[index]['hit_target']:\n                target_id = side2_fighter_action[index]['hit_target']\n                missile_type = side2_fighter_action[index]['missile_type']\n                enemy_status = None\n                enemy_index = 0\n                if missile_type == config.get_s_missile_type():\n                    if self.e_fighter_status_list[index]['s_missile_left'] <= 0:\n                        continue\n                    self.e_fighter_status_list[index]['s_missile_left'] -= 1\n                if missile_type == config.get_l_missile_type():\n                    if self.e_fighter_status_list[index]['l_missile_left'] <= 0:\n                        continue\n                    self.e_fighter_status_list[index]['l_missile_left'] -= 1\n                if target_id > self.o_detector_num + self.o_fighter_num:\n                    target_id -= self.o_detector_num + self.o_fighter_num\n                if target_id > self.o_detector_num:\n                    enemy_status = self.o_fighter_status_list\n                    enemy_index = target_id - self.o_detector_num - 1\n                else:\n                    enemy_status = self.o_detector_status_list\n                    enemy_index = target_id - 1\n                valid = strike_calc.strike_act_validation_and_initiation(missile_type, e_fighter_context_list[index], e_detector_context_list,\n                                                                         enemy_status[enemy_index], self.e_strike_list)\n                if valid:\n                    self.e_fighter_reward[index] += reward.get_reward_strike_act_valid()\n                else:\n                    self.e_fighter_reward[index] += reward.get_reward_strike_act_invalid()\n\n        # strike judge, update the status list, the strike list and the reward\n        for item in reversed(self.o_strike_list):\n            fighter_index = item['attacker_id'] - self.o_detector_num - 1\n            fighter_radar_visible_list = self.o_fighter_status_list[fighter_index]['radar_visible_list']\n            \n            target_index = item['target_id'] - self.e_detector_num - 1 if item['target_id'] > self.e_detector_num \\\n                                                                       else item['target_id'] - 1\n            strike_result = strike_calc.strike_judge(item, fighter_radar_visible_list, self.random_obj)\n            if strike_result == 1:\n                # hit success\n                if item['target_id'] > self.e_detector_num:\n                    # missile hit a fighter\n                    self.o_fighter_reward[fighter_index] += reward.get_reward_strike_fighter_success()\n                    self.e_fighter_status_list[target_index]['alive'] = False\n                    self.e_fighter_reward[target_index] += reward.get_reward_fighter_destroyed()\n                else:\n                    # missile hit a detector\n                    self.o_fighter_reward[fighter_index] += reward.get_reward_strike_detector_success()\n                    self.e_detector_status_list[target_index]['alive'] = False\n                    self.e_detector_reward[target_index] += reward.get_reward_detector_destroyed()\n                self.o_strike_list.remove(item) \n            if strike_result == -1:\n                self.o_strike_list.remove(item)\n                # hit failed\n                if item['target_id'] > self.e_detector_num:\n                    self.o_fighter_reward[fighter_index] += reward.get_reward_strike_fighter_fail()\n                else:\n                    self.o_fighter_reward[fighter_index] += reward.get_reward_strike_detector_fail()     \n        for item in reversed(self.e_strike_list):\n            fighter_index = item['attacker_id'] - self.e_detector_num - 1\n            fighter_radar_visible_list = self.e_fighter_status_list[fighter_index]['radar_visible_list']\n            target_index = item['target_id'] - self.o_detector_num - 1 if item['target_id'] > self.o_detector_num \\\n                                                               else item['target_id'] - 1\n            strike_result = strike_calc.strike_judge(item, fighter_radar_visible_list, self.random_obj)\n            if strike_result == 1:\n                # hit success\n                if item['target_id'] > self.o_detector_num:\n                    # missile hit a fighter\n                    self.e_fighter_reward[fighter_index] += reward.get_reward_strike_fighter_success()\n                    self.o_fighter_status_list[target_index]['alive'] = False\n                    self.o_fighter_reward[target_index] += reward.get_reward_fighter_destroyed()\n                else:\n                    #missile hit a detector\n                    self.e_fighter_reward[fighter_index] += reward.get_reward_strike_detector_success()\n                    self.o_detector_status_list[target_index]['alive'] = False\n                    self.o_detector_reward[target_index] += reward.get_reward_detector_destroyed()\n                self.e_strike_list.remove(item)\n            if strike_result == -1:\n                self.e_strike_list.remove(item)\n                # hit failed\n                if item['target_id'] > self.o_detector_num:\n                    self.e_fighter_reward[fighter_index] += reward.get_reward_strike_fighter_fail()\n                else:\n                    self.e_fighter_reward[fighter_index] += reward.get_reward_strike_detector_fail()\n                \n        # update position and jammer\n        for index in range(self.e_detector_num):\n            if self.e_detector_status_list[index]['alive']:\n                prev_pos_x = self.e_detector_status_list[index]['pos_x']\n                prev_pos_y = self.e_detector_status_list[index]['pos_y']\n                course     = side2_detector_action[index]['course']\n                speed      = self.e_detector_property_list[index]['speed']\n                self.e_detector_status_list[index]['pos_x'], self.e_detector_status_list[index]['pos_y'] = \\\n                position_calc.pos_update(prev_pos_x, prev_pos_y, course, speed, self.battlefield_size_x, self.battlefield_size_y)\n                self.e_detector_status_list[index]['course'] = course\n                self.e_detector_status_list[index]['radar_enable'] = side2_detector_action[index]['r_iswork']\n                self.e_detector_status_list[index]['radar_fp'] = side2_detector_action[index]['r_fre_point']\n        for index in range(self.e_fighter_num):\n            if self.e_fighter_status_list[index]['alive']:\n                prev_pos_x = self.e_fighter_status_list[index]['pos_x']\n                prev_pos_y = self.e_fighter_status_list[index]['pos_y']\n                course     = side2_fighter_action[index]['course']\n                speed      = self.e_fighter_property_list[index]['speed']\n                self.e_fighter_status_list[index]['pos_x'], self.e_fighter_status_list[index]['pos_y'] = \\\n                position_calc.pos_update(prev_pos_x, prev_pos_y, course, speed, self.battlefield_size_x, self.battlefield_size_y)\n                self.e_fighter_status_list[index]['course'] = course\n                self.e_fighter_status_list[index]['radar_enable'] = side2_fighter_action[index]['r_iswork']\n                self.e_fighter_status_list[index]['radar_fp'] = side2_fighter_action[index]['r_fre_point']\n                self.e_fighter_status_list[index]['j_enable'] = side2_fighter_action[index]['j_iswork']\n                self.e_fighter_status_list[index]['j_fp'] = side2_fighter_action[index]['j_fre_point']\n                self.e_fighter_status_list[index]['radar_fp'] = side2_fighter_action[index]['r_fre_point']\n                self.e_fighter_status_list[index]['radar_fp'] = side2_fighter_action[index]['r_fre_point']\n                self.e_fighter_status_list[index]['radar_fp'] = side2_fighter_action[index]['r_fre_point']\n                self.e_fighter_status_list[index]['radar_fp'] = side2_fighter_action[index]['r_fre_point']\n        for index in range(self.o_detector_num):\n            if self.o_detector_status_list[index]['alive']:\n                prev_pos_x = self.o_detector_status_list[index]['pos_x']\n                prev_pos_y = self.o_detector_status_list[index]['pos_y']\n                course     = side1_detector_action[index]['course']\n                speed      = self.o_detector_property_list[index]['speed']\n                self.o_detector_status_list[index]['pos_x'], self.o_detector_status_list[index]['pos_y'] = \\\n                position_calc.pos_update(prev_pos_x, prev_pos_y, course, speed, self.battlefield_size_x, self.battlefield_size_y)\n                self.o_detector_status_list[index]['course'] = course\n                self.o_detector_status_list[index]['radar_enable'] = side1_detector_action[index]['r_iswork']\n                self.o_detector_status_list[index]['radar_fp'] = side1_detector_action[index]['r_fre_point']\n        for index in range(self.o_fighter_num):\n            if self.o_fighter_status_list[index]['alive']:\n                prev_pos_x = self.o_fighter_status_list[index]['pos_x']\n                prev_pos_y = self.o_fighter_status_list[index]['pos_y']\n                course     = side1_fighter_action[index]['course']\n                speed      = self.o_fighter_property_list[index]['speed']\n                self.o_fighter_status_list[index]['pos_x'], self.o_fighter_status_list[index]['pos_y'] = \\\n                position_calc.pos_update(prev_pos_x, prev_pos_y, course, speed, self.battlefield_size_x, self.battlefield_size_y)\n                self.o_fighter_status_list[index]['course'] = side1_fighter_action[index]['course']\n                self.o_fighter_status_list[index]['radar_enable'] = side1_fighter_action[index]['r_iswork']\n                self.o_fighter_status_list[index]['radar_fp'] = side1_fighter_action[index]['r_fre_point']\n                self.o_fighter_status_list[index]['j_enable'] = side1_fighter_action[index]['j_iswork']\n                self.o_fighter_status_list[index]['j_fp'] = side1_fighter_action[index]['j_fre_point']\n                self.o_fighter_status_list[index]['radar_fp'] = side1_fighter_action[index]['r_fre_point']\n                self.o_fighter_status_list[index]['radar_fp'] = side1_fighter_action[index]['r_fre_point']\n                self.o_fighter_status_list[index]['radar_fp'] = side1_fighter_action[index]['r_fre_point']\n                self.o_fighter_status_list[index]['radar_fp'] = side1_fighter_action[index]['r_fre_point']\n\n        # update radar visible list and reward list\n        for index in range(self.e_detector_num):\n            if self.e_detector_status_list[index]['alive']:\n                new_detector_num, new_fighter_num = detection_calc.radar_visible_calc(e_detector_context_list[index],\n                                                                                      o_detector_context_list,\n                                                                                      o_fighter_context_list)\n                self.e_detector_reward[index] += reward.get_reward_radar_detector_detector()*new_detector_num + \\\n                                                 reward.get_reward_radar_detector_fighter() *new_fighter_num\n        for index in range(self.e_fighter_num):\n            if self.e_fighter_status_list[index]['alive']:\n                new_detector_num, new_fighter_num = detection_calc.radar_visible_calc(e_fighter_context_list[index],\n                                                                                      o_detector_context_list,\n                                                                                      o_fighter_context_list)\n                self.e_fighter_reward[index] += reward.get_reward_radar_fighter_detector()*new_detector_num + \\\n                                                reward.get_reward_radar_fighter_fighter()*new_fighter_num\n        for index in range(self.o_detector_num):\n            if self.o_detector_status_list[index]['alive']:\n                new_detector_num, new_fighter_num = detection_calc.radar_visible_calc(o_detector_context_list[index], \n                                                                                      e_detector_context_list,\n                                                                                      e_fighter_context_list)\n                self.o_detector_reward[index] += reward.get_reward_radar_detector_detector()*new_detector_num + \\\n                                                 reward.get_reward_radar_detector_fighter() *new_fighter_num\n        for index in range(self.o_fighter_num):\n            if self.o_fighter_status_list[index]['alive']:\n                new_detector_num, new_fighter_num = detection_calc.radar_visible_calc(o_fighter_context_list[index],\n                                                                                      e_detector_context_list,\n                                                                                      e_fighter_context_list)\n                self.o_fighter_reward[index] += reward.get_reward_radar_fighter_detector()*new_detector_num + \\\n                                                reward.get_reward_radar_fighter_fighter()*new_fighter_num\n\n        # 判断是否仍旧存活，并更新奖励\n        for index in range(self.o_detector_num):\n            if self.o_detector_status_list[index]['alive']:\n                self.o_detector_reward[index] += reward.get_reward_keep_alive_step()\n        for index in range(self.o_fighter_num):\n            if self.o_fighter_status_list[index]['alive']:\n                self.o_fighter_reward[index] += reward.get_reward_keep_alive_step()\n        for index in range(self.e_detector_num):\n            if self.e_detector_status_list[index]['alive']:\n                self.e_detector_reward[index] += reward.get_reward_keep_alive_step()\n        for index in range(self.e_fighter_num):\n            if self.e_fighter_status_list[index]['alive']:\n                self.e_fighter_reward[index] += reward.get_reward_keep_alive_step()\n\n        \n        # 判断是否回合结束\n        if self.render_flag:\n            if not self.step_count % self.render_interval:\n                self.show()\n        side1_detector_alive_num, side1_fighter_alive_num, side1_l_missile_left, side1_s_missile_left, side2_detector_alive_num, side2_fighter_alive_num, side2_l_missile_left, side2_s_missile_left = \\\n        self.get_alive_status(self.o_detector_status_list, self.o_fighter_status_list, self.e_detector_status_list, self.e_fighter_status_list)\n        # 完胜\n        if side1_detector_alive_num == 0 and side1_fighter_alive_num == 0:\n            self.done = True\n            self.e_game_reward = reward.get_reward_totally_win()\n            self.o_game_reward = reward.get_reward_totally_lose()\n        if side2_detector_alive_num == 0 and side2_fighter_alive_num == 0:\n            self.done = True\n            self.o_game_reward = reward.get_reward_totally_win()\n            self.e_game_reward = reward.get_reward_totally_lose()\n        # 导弹余量为0，作战单元多者获胜\n        if side1_l_missile_left == 0 and side1_s_missile_left == 0 and \\\n           side2_l_missile_left == 0 and side2_s_missile_left == 0:\n            self.done = True\n            if side1_fighter_alive_num > side2_fighter_alive_num:\n                self.o_game_reward = reward.get_reward_win()\n                self.e_game_reward = reward.get_reward_lose()\n            elif side1_fighter_alive_num < side2_fighter_alive_num:\n                self.e_game_reward = reward.get_reward_win()\n                self.o_game_reward = reward.get_reward_lose()\n            else:\n                self.o_game_reward = reward.get_reward_draw()\n                self.e_game_reward = reward.get_reward_draw()\n        # 达到最大step,剩余作战单元数量多的获胜\n        if self.step_count >= self.max_step:\n            self.done = True\n            if side1_fighter_alive_num > side2_fighter_alive_num:\n                self.o_game_reward = reward.get_reward_win()\n                self.e_game_reward = reward.get_reward_lose()\n            elif side1_fighter_alive_num < side2_fighter_alive_num:\n                self.e_game_reward = reward.get_reward_win()\n                self.o_game_reward = reward.get_reward_lose()\n            else:\n                self.o_game_reward = reward.get_reward_draw()\n                self.e_game_reward = reward.get_reward_draw()\n\n        return True\n"
  },
  {
    "path": "environment/world/load_map.py",
    "content": "import json\n\nclass Map:\n\tdef __init__(self, map_path):\n\t\twith open(map_path, 'r') as f:\n\t\t\tself.map_info = json.load(f)\n\n\tdef get_map_size(self):\n\t\treturn self.map_info['size_x'], self.map_info['size_y']\n\n\tdef get_unit_num(self):\n\t\treturn self.map_info['side1_detector_num'], self.map_info['side1_fighter_num'], self.map_info['side2_detector_num'], self.map_info['side2_fighter_num']\n\n\tdef get_unit_property_list(self):\n\t\treturn self.map_info['side1_detector_list'], self.map_info['side1_fighter_list'], self.map_info['side2_detector_list'], self.map_info['side2_fighter_list']\n"
  },
  {
    "path": "environment/world/log.py",
    "content": "__pyarmor__(__name__, __file__, b'\\x84\\x50\\x8c\\x64\\x26\\x42\\xd6\\x01\\x9b\\xd2\\x9b\\x61\\xa4\\xcf\\x1b\\xb9\\x58\\x14\\x4e\\xf4\\xc9\\x56\\x7f\\x05\\x09\\x60\\x6c\\x85\\x00\\xce\\x8a\\x18\\xd2\\xea\\x08\\x62\\x16\\x2e\\x37\\x8f\\x4b\\x57\\x68\\xbf\\x3f\\x4a\\x96\\xe6\\x9f\\x2c\\xe2\\x67\\x2b\\xdf\\xa8\\xbf\\xd6\\x62\\x39\\x3c\\x52\\x72\\x59\\x44\\x63\\xf7\\x7d\\x97\\x44\\x15\\x9e\\x36\\x7d\\x0f\\x8d\\xb7\\xf0\\xc7\\x32\\x9e\\xde\\xd1\\xb2\\x24\\x65\\x89\\x00\\x4e\\x49\\xaf\\x7a\\x33\\x28\\x52\\x2c\\xe2\\x38\\xb5\\x8c\\xf7\\x49\\xff\\x97\\xbe\\xc9\\x87\\x34\\xb8\\xc0\\xd2\\xa4\\x2c\\x96\\xc6\\x52\\xf0\\xaf\\x7f\\xc2\\x16\\xe2\\x4a\\xbd\\xf7\\x3d\\xea\\x0c\\x3a\\x5e\\x10\\xe2\\x32\\xf7\\x39\\x24\\x1e\\x67\\xaf\\x22\\xe1\\xa5\\x48\\x4d\\x14\\x8d\\xdc\\x15\\x9e\\x46\\x32\\x84\\x43\\xdc\\x9d\\x19\\x23\\x85\\xba\\xa7\\xf5\\x67\\x9f\\x59\\x78\\x6e\\xc9\\x31\\x69\\x58\\x25\\x16\\x6b\\xf2\\x53\\x25\\x53\\x23\\x62\\x3c\\xa1\\x7e\\x6a\\x1f\\x83\\x14\\xaa\\x97\\x0c\\x18\\x97\\xde\\x94\\x72\\xb2\\xa9\\xc0\\x9e\\xb8\\xdc\\x4c\\xcf\\xad\\x97\\xe9\\xad\\xc4\\x42\\x31\\x63\\x84\\x2c\\x7e\\xdd\\xca\\x06\\xcf\\xa7\\xc4\\x4c\\xd3\\x09\\xa3\\x50\\x0e\\x51\\x44\\x61\\x8f\\xa6\\x1a\\x21\\xe4\\x21\\x89\\x90\\x12\\xd0\\x96\\xd3\\x8e\\xf5\\xc1\\x1f\\x04\\x0e\\x95\\xa3\\xea\\xbd\\x2b\\x2f\\x6f\\xbf\\x21\\x63\\xad\\x0c\\x16\\x99\\xfc\\x27\\xd6\\xe0\\x78\\x25\\x3f\\x0c\\x77\\xe5\\xc7\\x6d\\xe6\\xa7\\xbd\\x12\\x5d\\x07\\x10\\xa5\\xa0\\x0a\\x3d\\xb0\\xcf\\x4d\\xa3\\xaf\\x3d\\x0c\\x08\\x47\\xc1\\xd7\\x97\\x03\\x0a\\xcb\\xe1\\x93\\xdf\\x36\\x07\\x0d\\x9b\\x1d\\x40\\xb3\\x56\\xe1\\x49\\xce\\xff\\x2d\\x98\\x67\\x9e\\x90\\xd7\\xf6\\x98\\x6c\\x86\\x4f\\x76\\x5a\\xfb\\x55\\xe7\\x12\\xfd\\x66\\x5b\\x47\\xd4\\xab\\x24\\x75\\x2c\\x37\\xa8\\x90\\x8b\\x9d\\x2d\\x8f\\x1c\\xa0\\x31\\x87\\xaa\\xa9\\xd0\\x53\\x20\\x75\\x2e\\xf0\\x2a\\xd9\\xbd\\x51\\x35\\xed\\x54\\x97\\x05\\xfa\\xe3\\x40\\x0d\\x33\\x0e\\x5f\\x08\\xdd\\x28\\xff\\x9f\\x6b\\x3b\\x1c\\x6f\\xd2\\x92\\x82\\x6f\\xf2\\xd7\\x2b\\xc2\\xff\\x7a\\xe7\\x37\\x5b\\x2c\\x68\\xf8\\xbe\\x3c\\xeb\\x2c\\x6c\\xa5\\xb5\\x44\\x3d\\x76\\x66\\xaa\\x75\\xbe\\x9a\\xcb\\x68\\x49\\x3c\\x41\\x8b\\x83\\xf8\\x01\\x55\\x37\\x41\\xdd\\x9a\\xea\\xbc\\x28\\xc1\\xb7\\x42\\x48\\x1e\\xa2\\xfc\\x49\\x54\\x5d\\x25\\x2e\\x5d\\x7a\\x62\\xf2\\x4c\\x36\\xdd\\x7c\\x69\\xd9\\x99\\x13\\x7e\\x67\\x36\\x13\\xf0\\x64\\x1c\\xa4\\x04\\xc5\\x34\\x91\\x0b\\x90\\x5c\\x05\\x56\\x0f\\xb4\\xe1\\xfe\\x36\\x10\\x36\\x69\\x7e\\x35\\x8a\\xfd\\xb0\\x2a\\xa1\\x90\\x46\\x81\\x23\\xa9\\x66\\xc2\\xbe\\xae\\xce\\xbe\\x89\\x77\\x74\\x4a\\x53\\xe6\\xf1\\x4b\\x2d\\x60\\x98\\x25\\x01\\xe3\\x6b\\x1a\\x9a\\x40\\xb1\\x0c\\xb8\\x36\\x06\\x05\\x27\\x4f\\xc5\\xef\\xba\\x33\\xd4\\xd5\\x3a\\xc2\\xcc\\xa8\\x2b\\x07\\xf9\\x6c\\x35\\x9d\\x38\\x04\\x47\\x91\\x4a\\x1a\\x9e\\x15\\x14\\x6a\\xd5\\x2a\\x2e\\xd8\\x9a\\xfb\\x55\\xa4\\xb8\\x42\\xbc\\x38\\xf7\\xf2\\x3c\\x8d\\x7d\\x5a\\xb0\\x7c\\x13\\x04\\x46\\x53\\xa2\\x20\\xaf\\xf2\\x32\\xf4\\x21\\x9c\\x5d\\xe8\\x3e\\xb9\\x20\\xad\\x20\\xba\\xa0\\x8b\\x05\\x88\\x84\\xcf\\x8a\\xa2\\xd7\\x0f\\x01\\x2a\\xac\\x0a\\xa5\\xd2\\xad\\x49\\x7e\\xf4\\x7c\\xb1\\xd1\\x16\\x4b\\x81\\x4d\\x36\\x7a\\xa8\\x50\\xc4\\x65\\xbd\\x50\\x4a\\x0b\\x15\\x30\\x14\\xd7\\x9c\\xfa\\x33\\xc2\\xf3\\xc8\\x18\\x7c\\xf4\\x7d\\xa1\\x11\\xe0\\x22\\xe4\\x4f\\x2e\\xb1\\x61\\x15\\x03\\x5f\\xe9\\x6c\\xeb\\x56\\x04\\xab\\xa5\\x95\\x5b\\x37\\x40\\xe7\\x94\\x16\\x4c\\x88\\xf4\\xe9\\x72\\xc1\\x05\\x21\\x30\\xe7\\x68\\x3d\\x24\\x05\\x3e\\x78\\x0a\\xf0\\x44\\xcf\\xb5\\xcd\\x0d\\xc6\\x2a\\xc0\\x6a\\x4d\\x22\\x9c\\xef\\xaa\\x54\\x40\\x2f\\x03\\x81\\x09\\xe6\\xc1\\x10\\x6d\\x5d\\xca\\x3d\\x81\\xaf\\xba\\x07\\xc0\\xcf\\xcb\\x45\\xbb\\x45\\x3a\\x42\\xc6\\xfe\\x99\\x5c\\x4f\\xc9\\x20\\xd7\\x8a\\xef\\xd5\\x4b\\x21\\x1e\\xe6\\x79\\x48\\xb4\\x94\\xc2\\xe8\\x26\\x82\\xf1\\x98\\x2e\\x5e\\xc2\\x9c\\xb7\\xca\\xa1\\x91\\xc1\\x1a\\xfa\\x80\\x2a\\x80\\x2f\\x0b\\x0f\\xab\\xf7\\x39\\x39\\x5e\\x1a\\x6d\\xa8\\x1d\\xe8\\x17\\x8e\\xad\\x0e\\xf9\\x2d\\x5f\\x15\\x5b\\x38\\xa9\\xb0\\x03\\xec\\x17\\x0b\\xe0\\x4e\\x7b\\x9c\\x8c\\x13\\x54\\x51\\xff\\xe3\\xd8\\xd7\\x80\\xc5\\x66\\x15\\xb7\\x18\\x39\\x08\\xe8\\xa8\\x6a\\xf8\\xb3\\x17\\xb5\\x7f\\xef\\x06\\x2f\\x53\\xe8\\x35\\xfe\\xe8\\x9d\\x3f\\x94\\xe2\\xed\\x44\\x36\\xa2\\x83\\x2f\\x23\\x05\\x69\\xa2\\x45\\x63\\x58\\xc6\\x99\\xb5\\xb5\\x84\\x07\\x11\\xce\\x3c\\xfb\\x0a\\xd0\\x2e\\xee\\x5e\\x1c\\x79\\xac\\xe5\\x2d\\xa7\\xa8\\x1f\\x87\\xfb\\xfa\\xb1\\x62\\x7c\\x12\\x90\\x62\\x59\\xa0\\x8c\\x08\\xc3\\x8c\\xca\\xb1\\xee\\x3a\\x3f\\x5c\\x23\\xa9\\xb2\\xe6\\x6f\\xc7\\x53\\xeb\\x66\\x1f\\x6a\\x03\\xba\\x37\\xf0\\xa9\\xb0\\x62\\x46\\x8b\\x2d\\xee\\xe9\\x89\\xa6\\xa7\\x2a\\x2e\\xab\\xfd\\x59\\xc7\\x66\\xc7\\x0e\\x72\\x3a\\xc6\\xc1\\xf6\\x62\\x47\\x45\\xf0\\xa9\\xef\\x4d\\x8c\\x92\\x76\\xc7\\xd5\\xab\\xd1\\x3d\\x20\\x7c\\xd2\\x91\\xde\\x12\\x9f\\x3c\\x5a\\x53\\xf1\\x4a\\x4c\\x3a\\x25\\x86\\x2b\\xd1\\x80\\x4e\\x11\\x90\\x7d\\x08\\x95\\x80\\x85\\x0d\\x2a\\xb6\\x4e\\xf5\\x42\\xae\\x60\\x6c\\x34\\xea\\x8b\\x77\\x7b\\x8d\\xf0\\xf2\\x12\\x7e\\xd7\\x77\\x34\\xb1\\x55\\xb7\\xde\\x1e\\x8b\\xef\\x94\\x22\\x56\\x66\\x8d\\x91\\x06\\x05\\xfc\\xfa\\x81\\x00\\xef\\x88\\x80\\xa6\\x9f\\x60\\x3b\\x6a\\xa8\\x54\\xf7\\x53\\x30\\x3a\\x4c\\xba\\x3f\\xff\\xe0\\x16\\x5e\\x8b\\xca\\xc7\\x35\\x0a\\x0d\\x67\\x21\\xd2\\x82\\x58\\x2d\\xc2\\x59\\x63\\x54\\xe4\\x34\\x8e\\xa2\\xdf\\xcb\\x0c\\xb3\\xd4\\x87\\x40\\xb2\\x23\\x05\\xcd\\x4e\\x15\\xc9\\xd0\\xc6\\xa8\\x22\\x19\\x58\\xff\\xfb\\xf9\\x19\\xdf\\x85\\x60\\x1d\\x8c\\xa7\\x06\\xd5\\x6d\\x0d\\x1e\\x5f\\xec\\x3e\\xfb\\x6c\\x3c\\x01\\x16\\x57\\xb9\\x4d\\xf3\\x2e\\xba\\x0e\\xd6\\x5a\\x5d\\xc9\\xe3\\x52\\xec\\x87\\x0f\\x35\\x31\\xdf\\x37\\xd4\\x7d\\x63\\xfe\\xd2\\xa8\\xa4\\x64\\x1a\\x63\\x22\\x11\\xa9\\x27\\x5d\\xd7\\xe8\\xb1\\x9d\\x1d\\x1e\\x7c\\x05\\x29\\x9f\\x04\\x5d\\x55\\x0b\\x05\\xdb\\x7e\\xf7\\x83\\x73\\x24\\xa6\\x75\\x1f\\x2d\\xea\\x99\\x74\\x5e\\x73\\xdd\\xd8\\x59\\xc8\\x7e\\x11\\xcd\\x46\\x94\\x47\\xee\\x3b\\x65\\x25\\x5a\\x64\\xf1\\xf3\\x30\\x7e\\x24\\xf1\\x0d\\x4c\\x74\\xa0\\x53\\xe1\\x0e\\xc3\\xd0\\xc1\\x3f\\x35\\xa9\\x2d\\x87\\x1b\\x3c\\x9c\\xdb\\x84\\x2c\\x4a\\x0e\\xc3\\x68\\xea\\x3b\\x71\\x56\\x3a\\x45\\xf3\\xe2\\x5f\\xe5\\x54\\x95\\xad\\x0c\\x7c\\xb5\\xe1\\xbd\\xa6\\x07\\xf6\\x36\\x36\\x14\\xd0\\x75\\x7b\\x9d\\x76\\x85\\xc9\\x2e\\x80\\xc7\\x42\\xe7\\xf7\\x07\\xbc\\xfa\\x94\\x3d\\xf4\\x82\\xf2\\x8d\\x89\\xd5\\xca\\xb6\\x23\\xf8\\x4b\\xee\\xd1\\x49\\xe0\\x7f\\x83\\xbf\\xa4\\x43\\x2b\\x8e\\x89\\x05\\xf9\\x9c\\x88\\x2c\\x33\\x0e\\x84\\x17\\x18\\xda\\x07\\x1e\\x15\\xc3\\x30\\xe2\\x10\\x6e\\xc6\\x70\\xdb\\x9a\\x2e\\xf2\\x20\\xfd\\x24\\x34\\x03\\x06\\x87\\xda\\xfe\\xd1\\xa8\\xeb\\x00\\xf3\\x12\\xc8\\x04\\xc5\\x56\\x08\\xe3\\x64\\xe0\\x9f\\x0c\\x3e\\x56\\xf0\\x70\\xac\\x89\\x70\\x9e\\x68\\xd8\\x00\\x92\\x47\\xe2\\xfd\\x14\\x49\\x11\\x06\\xcf\\xbd\\x5c\\xf6\\x56\\xfd\\x05\\xb8\\x91\\x14\\x08\\x19\\x06\\xec\\xc0\\xc1\\x71\\x4e\\x52\\x42\\x3e\\x49\\xe3\\x26\\xa6\\x13\\x47\\x25\\x1e\\xbd\\x11\\xbc\\x54\\xf6\\x15\\x52\\xd7\\x72\\xe4\\xf7\\x14\\x6c\\x75\\x30\\x22\\xcd\\x0c\\x88\\x3e\\x4f\\x75\\x39\\x9c\\xc7\\x37\\xfc\\x29\\x8a\\xff\\x49\\x36\\x70\\x14\\xce\\x1e\\xd2\\x8e\\x1a\\xb7\\xd4\\x53\\x7a\\x30\\x4f\\xe4\\xcd\\xe9\\x05\\x93\\xf4\\x19\\x79\\x91\\xf4\\x98\\x4d\\x20\\xd3\\xfd\\x0e\\xba\\xe0\\x72\\x9d\\x5e\\x3d\\x3d\\x5d\\x53\\x63\\x0c\\x48\\xa8\\x2a\\xea\\xf4\\x2f\\xa9\\xf4\\xb4\\xf6\\x8e\\xfb\\x76\\xa9\\xab\\x96\\x7f\\x79\\x22\\x7d\\x38\\xd2\\xb6\\xe4\\xc2\\x9f\\x0e\\x9e\\xcd\\x13\\x5c\\xdc\\x52\\x5f\\x46\\xab\\x45\\x4e\\x6f\\xf3\\xdd\\x05\\x7d\\xd9\\x3d\\x87\\x62\\x2d\\xa4\\xa6\\xbf\\xc3\\x4b\\x6c\\xc2\\x1c\\xcd\\xf4\\x01\\x83\\x17\\xf3\\xe5\\x4f\\xd0\\xa8\\x50\\x92\\x15\\x7d\\x7a\\x83\\x26\\x6e\\xe0\\x52\\x81\\x32\\xba\\x4d\\x90\\x0f\\x2f\\xfe\\x3e\\x4f\\x32\\x14\\x36\\x91\\x17\\x79\\x03\\x25\\x3b\\x35\\xd8\\x00\\x4b\\x3e\\x70\\x21\\x91\\x1d\\xc3\\x87\\x90\\x34\\x3d\\x3e\\x91\\x09\\x47\\x65\\xbd\\x5e\\x74\\x24\\xa7\\xb4\\xb2\\x77\\x28\\xfe\\xb0\\xde\\xcc\\xcb\\x78\\x66\\x63\\x70\\x86\\xff\\xcb\\x41\\xf9\\x6f\\x2d\\xbd\\xe4\\xfe\\x1f\\x74\\x5a\\x17\\x90\\x03\\x5f\\x48\\xe2\\x7f\\xa6\\xae\\x31\\xa4\\x42\\x42\\xe4\\x6f\\xd6\\xf4\\x69\\xf3\\x0e\\xe3\\x8d\\x49\\x30\\xa4\\xef\\xbd\\x3c\\x44\\x64\\x62\\x98\\xcd\\xd6\\xc2\\x74\\x1a\\xaa\\x8a\\x89\\xaa\\xc7\\x7e\\xd5\\x87\\x1e\\xca\\x37\\xf1\\xf9\\x35\\xca\\x41\\xee\\xe7\\x50\\x49\\x5c\\x35\\xd5\\x1f\\x4b\\x49\\xbf\\x37\\x96\\xea\\x57\\x49\\x79\\x4c\\x78\\xe7\\x6e\\xb1\\x01\\xff\\x4e\\x2f\\x73\\xe5\\x9a\\x50\\x6b\\x4c\\x29\\x40\\xc9\\xf4\\xd8\\x20\\xf4\\x70\\xd4\\x24\\xdb\\x53\\x71\\xb9\\x09\\xc0\\xee\\x37\\xb5\\x08\\xe5\\x32\\x18\\x40\\x22\\xcb\\xe4\\x2c\\x8a\\x6e\\xce\\x21\\x08\\xa7\\xac\\x55\\x86\\x7f\\x19\\xf8\\xd7\\xcf\\x69\\x93\\x2c\\x2a\\x6d\\xb7\\xee\\x2b\\x55\\xe1\\xd6\\xd5\\x59\\xca\\xdc\\x58\\xf1\\x57\\x90\\x3e\\x78\\x72\\xfd\\x4c\\x83\\xfc\\xd0\\x94\\x88\\xc6\\x61\\xc4\\x81\\xbc\\x7a\\x06\\x08\\x25\\x0b\\x37\\xb6\\x11\\x1f\\x15\\xb7\\x00\\x5f\\x6e\\xe8\\x80\\xbc\\x1c\\x92\\xcc\\xa6\\x23\\x31\\x25\\x84\\xb1\\x46\\x2a\\x78\\x95\\x87\\x99\\x58\\xb3\\x48\\x8c\\x5d\\x58\\x26\\x3f\\x48\\xa1\\xce\\x8c\\x9b\\x1a\\xb5\\x63\\x58\\xdc\\x6e\\xd8\\xdc\\xad\\xd3\\xc5\\xda\\x8f\\x6e\\x28\\x96\\xd7\\x56\\x78\\x61\\x1e\\x12\\xc9\\x52\\x16\\x73\\x54\\x04\\xcb\\x6e\\x84\\x82\\x3a\\x8a\\x29\\x51\\xcd\\xa1\\x0e\\xa8\\x00\\x71\\x4f\\xb9\\xff\\xfe\\x5a\\x04\\x6a\\xdf\\x08\\x40\\x32\\x72\\xd1\\xd3\\x01\\x18\\x00\\x9b\\xac\\x13\\x8b\\x7b\\x1d\\x4a\\xb2\\x54\\xa5\\xec\\x88\\x9d\\xd2\\xae\\x1b\\x86\\x2f\\xa5\\x70\\xa8\\x70\\x36\\xc2\\xe5\\x95\\x3d\\x21\\x0f\\xf7\\x49\\x21\\xa6\\x53\\x71\\x62\\x97\\x72\\xdf\\x12\\xa5\\x11\\xa2\\x94\\xde\\xb3\\xab\\x0c\\x27\\x88\\x19\\xe1\\xa4\\xe4\\x62\\x58\\x68\\x82\\xdc\\x13\\xf6\\x03\\xe7\\x27\\x1f\\x97\\x69\\x71\\x62\\x4a\\x4f\\x15\\xda\\xe2\\x41\\x7c\\x99\\x83\\xb1\\x1e\\x38\\x7d\\x7b\\x45\\x32\\x9f\\x6b\\xb9\\x4d\\x02\\xaa\\x56\\x7b\\x76\\xbe\\x02\\xf4\\x08\\x9d\\x93\\x95\\x6c\\xf8\\xbf\\x8d\\xe4\\xe5\\x99\\xf7\\xa8\\x04\\xe4\\x39\\x26\\x6e\\x85\\x17\\x15\\x9e\\x23\\xe8\\x3f\\x65\\xab\\xc1\\x21\\x12\\xee\\xda\\xe0\\xac\\x0e\\xd0\\x26\\x52\\xd4\\x45\\xe6\\x32\\xc0\\x99\\x33\\x43\\x87\\x0b\\xd0\\xe9\\xd8\\x20\\x55\\x6c\\xa4\\x80\\x34\\x2c\\x07\\x8e\\x00\\xf1\\x5f\\x59\\x54\\xb9\\xa7\\x3c\\xb3\\x9d\\xd0\\x30\\xaa\\xce\\x9e\\x5c\\xc8\\x47\\xa0\\xbd\\xf3\\xfa\\x91\\x11\\xb7\\x75\\x30\\xa9\\x35\\x14\\x02\\x69\\xe4\\xa5\\xcd\\xef\\xe0\\x9d\\xb0\\x1d\\xb4\\x21\\x8f\\x64\\x9c\\x51\\x08\\xd1\\x50\\x9e\\x78\\x5d\\x47\\x22\\x47\\x7d\\x72\\xcc\\x64\\xfe\\xb2\\xd0\\x33\\x59\\x07\\x40\\xf0\\x86\\xd1\\xe1\\xe3\\x6d\\x65\\xba\\x29\\x0b\\x21\\x81\\xb4\\xa0\\xee\\x83\\xb3\\x6a\\x63\\xd9\\x7f\\xf6\\xef\\xba\\x9c\\xf3\\x57\\x0e\\xdb\\xf9\\xca\\x66\\x64\\xdd\\xbe\\x02\\xac\\x44\\x74\\x77\\x6a\\x74\\xa5\\x63\\x11\\x1c\\xbf\\xff\\xd5\\x82\\xd7\\xcb\\x5b\\xce\\x24\\x97\\x25\\x70\\xbe\\x7a\\xdd\\x1b\\xc2\\x56\\x4f\\x84\\xc7\\xf0\\x7f\\x18\\x0c\\x63\\x87\\xd8\\xa0\\x90\\x38\\xd5\\x02\\xb0\\xb0\\xdd\\x9f\\x76\\x72\\x92\\x62\\x86\\xd8\\x28\\xfa\\x46\\x88\\x1a\\x0c\\x00\\x25\\xe6\\xec\\xf2\\xb2\\xb2\\xe6\\xa0\\xbb\\x75\\x24\\x57\\x38\\x2c\\x61\\xb4\\x96\\x28\\x9e\\x95\\x57\\x30\\xae\\x16\\x33\\x47\\xdf\\x3f\\xff\\x4e\\x16\\xaa\\xa0\\xaf\\xaf\\x78\\x24\\x86\\xe1\\xff\\x50\\x31\\xd7\\x96\\x36\\x10\\x8b\\x72\\xdf\\xbb\\xd1\\x82\\x01\\xf3\\x66\\x28\\x66\\xd8\\x01\\xbf\\x49\\xce\\xa6\\xe6\\xac\\xc5\\x2c\\x88\\x2d\\xc9\\x6a\\x8c\\x61\\xfa\\x6b\\x2d\\x07\\x9e\\x94\\xdc\\x6f\\x0b\\xf2\\x8d\\x17\\x2e\\x24\\x17\\xa8\\xbb\\x70\\xfa\\x03\\x67\\x72\\x5f\\x76\\xfb\\x69\\x4d\\x41\\xe7\\xe3\\x08\\x15\\xe2\\x40\\x60\\x45\\xc6\\x2c\\xb5\\xdb\\xb5\\xb9\\xd1\\xa6\\x46\\x6a\\x43\\x4e\\xef\\xd4\\x76\\x35\\x43\\x18\\x58\\x98\\x3c\\x94\\x8a\\x00\\x76\\xd8\\xe5\\x9f\\xd5\\x3d\\x8a\\xd6\\x11\\x6b\\x82\\x20\\x62\\x79\\x39\\x75\\x9e\\x8e\\x0c\\x97\\x3e\\x70\\x8a\\xa0\\x5f\\x92\\x53\\x23\\x16\\xdf\\x7d\\xd5\\x4d\\xed\\x48\\x85\\x54\\x09\\x53\\x5d\\x26\\xe2\\x41\\x33\\x6e\\x89\\x1a\\x43\\xe3\\xa9\\x40\\xc5\\xe9\\x5a\\xe1\\x4e\\x54\\xac\\x52\\x04\\x30\\xf0\\x3c\\x1a\\xa4\\x62\\xf5\\x15\\xf9\\x26\\xb1\\xdd\\xda\\x2a\\xf7\\x9a\\x6a\\xe0\\xb5\\x3e\\x6d\\x93\\xe3\\xad\\x4f\\x46\\xa3\\x2e\\xf5\\x61\\x70\\x09\\x00\\x0f\\xe1\\x86\\x60\\xb4\\xa0\\x98\\x5b\\x25\\xee\\x8a\\xfd\\xea\\x19\\x68\\xb8\\xd9\\xc3\\xf5\\x84\\x20\\x74\\x2f\\x4f\\x75\\x21\\xe8\\xd3\\x1e\\x24\\x36\\xf3\\xb9\\xed\\x9e\\xdd\\xb8\\xcd\\x75\\xdc\\xcc\\xa6\\xfd\\x72\\x50\\x22\\xfe\\xb7\\xe5\\x3f\\xfb\\x54\\xdb\\x6c\\x1a\\xd5\\x61\\x25\\x59\\xd9\\xd6\\xd6\\x11\\x4a\\x14\\x24\\xa3\\xb0\\xab\\x9e\\x78\\x73\\x53\\xe0\\x17\\x82\\x17\\x6d\\x0a\\xfb\\x3d\\x08\\x90\\x85\\xfa\\xa8\\x18\\x80\\x3b\\x49\\xff\\x62\\x8c\\xf7\\x7e\\x48\\xc7\\x20\\xbe\\x5e\\x6c\\xec\\x1b\\x7d\\x0e\\x65\\x64\\x40\\x6a\\xf9\\xe9\\x17\\xf6\\x37\\x4f\\xdb\\x77\\x99\\xf7\\x1b\\xe5\\x69\\x2e\\xdb\\x7a\\xd6\\xaf\\xc6\\x73\\x78\\xe3\\xa1\\x37\\x01\\xb4\\x07\\x08\\xaa\\xf6\\xd3\\x8f\\x79\\xdb\\x74\\x7f\\xb9\\x7e\\x9e\\xc5\\xe9\\x51\\x59\\xa5\\x61\\xa0\\xfd\\x1b\\x96\\x50\\x48\\xd5\\x40\\xa9\\x00\\x60\\xcb\\x87\\x40\\x76\\x3e\\x71\\x8e\\x10\\x2d\\xca\\xb7\\x27\\xab\\xc5\\xf4\\xe5\\xc0\\xbf\\x6f\\x8c\\x5d\\xe5\\x02\\x98\\xec\\x9c\\x79\\x2c\\xb9\\x7a\\xaa\\xd2\\x36\\x99\\xb4\\xc6\\x2a\\x7a\\x58\\x5a\\xcb\\x74\\x55\\x98\\x5c\\x03\\x78\\x4c\\x2b\\x65\\xc4\\xdd\\xb9\\x49\\x9a\\x8c\\xa5\\x3e\\xfa\\xdc\\x42\\x3f\\x1a\\x8e\\x94\\x10\\xaa\\x7e\\x6a\\x95\\xab\\x65\\x60\\xef\\x04\\xb1\\x55\\xee\\xe7\\x60\\x8e\\xf4\\xba\\x34\\xee\\x28\\x97\\x4e\\x86\\x58\\x64\\x72\\x3c\\x46\\xda\\x9a\\xd0\\x97\\x53\\x5b\\xe0\\x65\\xdb\\xd2\\xaf\\x54\\x81\\x5a\\x28\\xa6\\xf3\\x18\\x64\\x05\\x01\\x85\\x95\\x60\\x8a\\xd3\\xbb\\x73\\x61\\x8e\\x47\\x9d\\x11\\x17\\xea\\x5b\\x99\\xaf\\x9c\\x4b\\x8d\\xa0\\x36\\xd7\\xe7\\xba\\x89\\x99\\xf6\\x98\\x5c\\xa5\\x15\\x67\\x93\\x25\\x70\\x33\\xb1\\x8f\\x55\\xb3\\x24\\x03\\xa1\\xc1\\x7d\\xcf\\x78\\xb2\\x2c\\x76\\x89\\x64\\x63\\x93\\x7b\\x95\\xf2\\x0a\\x92\\xcd\\x4d\\xe0\\x2b\\x41\\xfa\\x02\\x26\\xc8\\x6e\\xda\\x61\\xa4\\xf7\\xd4\\x4b\\x7a\\x91\\x45\\x26\\x84\\x42\\x2e\\x82\\x9c\\xd5\\xed\\x5a\\xc6\\x46\\xe6\\x8e\\x84\\x61\\x20\\xf4\\xdb\\x33\\x51\\x5e\\xa1\\x87\\x6f\\xbf\\xab\\x12\\xe9\\x59\\x30\\x66\\xde\\x7b\\xa5\\xfe\\x09\\x6b\\xcf\\x21\\x5f\\xb6\\xce\\x7e\\xea\\xa3\\xf3\\x02\\x43\\xa9\\x9a\\x27\\x67\\x2a\\x54\\x8b\\x22\\x44\\x92\\x7f\\x0c\\x3c\\xb2\\xea\\x0d\\xf7\\xcd\\xbe\\x2b\\x0b\\x83\\x64\\x76\\x11\\x57\\x2a\\xee\\xa7\\x98\\x82\\x17\\x88\\x8d\\x25\\x82\\x9d\\x91\\xe6\\xec\\x7f\\xb9\\xb2\\x70\\x0a\\x25\\x18\\x2f\\x66\\x3e\\x97\\x96\\x7b\\xe6\\x70\\x67\\xa7\\xd4\\xe4\\x6b\\x19\\x8f\\xc3\\x21\\xb5\\x5e\\x7a\\x39\\x75\\xdd\\x26\\x0a\\xdd\\x64\\xbf\\x29\\x8c\\xf9\\x07\\x19\\xc4\\x39\\x44\\xec\\x28\\xef\\x30\\x6c\\xe8\\xff\\xa9\\xbf\\xcc\\x99\\x69\\x31\\xfc\\x62\\x36\\x5c\\x33\\x25\\x8e\\x16\\x22\\x4b\\x88\\x76\\x91\\xa6\\x98\\x45\\x76\\xdc\\x35\\xa2\\xad\\x0f\\xcf\\x19\\x11\\xb8\\x0d\\xbd\\x06\\x04\\x27\\xf7\\xc6\\xc4\\x86\\x53\\xd8\\x7e\\xda\\x89\\xf5\\xc1\\x9a\\x9e\\x9f\\x1e\\x34\\x0c\\x51\\x55\\xf2\\xa5\\x42\\x66\\xf8\\xc7\\x01\\xd6\\xc2\\x86\\xf5\\x3b\\xe2\\xf7\\xd6\\x39\\x23\\x17\\x38\\x66\\xb5\\x91\\xb3\\x9e\\xf7\\x67\\x83\\x1e\\x8e\\x96\\x50\\xef\\x9d\\x15\\x78\\x2b\\xb9\\x58\\xd2\\x76\\x5a\\xac\\x2d\\x5f\\x64\\x4e\\xa1\\x53\\x7d\\x9a\\xca\\x1c\\x0f\\x74\\xf3\\x63\\x42\\x35\\x99\\x55\\x6d\\x8c\\xe0\\x10\\xfd\\x90\\x98\\xe0\\x84\\x46\\x71\\x60\\xbc\\x94\\xb3\\x0c\\xbe\\x78\\x85\\x5a\\x74\\x1e\\xb0\\x5d\\xb2\\xb1\\x85\\xfd\\x79\\x49\\x01\\x9f\\xac\\x54\\xb9\\x67\\x6a\\x4c\\x75\\xa5\\x7e\\x8e\\x9d\\x8a\\x59\\x34\\xe0\\xa1\\xd4\\xcf\\x47\\x03\\x6e\\xd1\\x8a\\xc0\\xb9\\x35\\xe1\\x85\\x81\\x3e\\x7a\\xc1\\x45\\x1e\\xad\\x2d\\x62\\xad\\x1a\\xda\\xad\\x7b\\xa1\\x85\\x41\\xb6\\xa0\\x75\\xf7\\x9a\\xe4\\x52\\x6c\\x98\\x8b\\xf3\\xc5\\x8e\\x83\\xe7\\x26\\xab\\xf0\\x4c\\x28\\x33\\xd4\\x5c\\x5a\\x9d\\x11\\xe3\\x70\\xb5\\xf1\\x70\\xa7\\xc3\\x1a\\xac\\xbc\\x7d\\x23\\x44\\x38\\xd6\\x48\\x8f\\x3f\\xa8\\x6c\\x67\\xd6\\x07\\x77\\x7b\\x0e\\x39\\x45\\x85\\xe7\\xc4\\xd4\\xbf\\xdc\\x28\\x77\\xe3\\x69\\xa4\\xe3\\xab\\x95\\x14\\xcd\\x13\\x87\\x09\\x5f\\x0c\\xc1\\x40\\x53\\x0d\\x06\\x4f\\xab\\xed\\xfc\\x9e\\xe8\\x73\\x30\\xe4\\x4d\\x5b\\x6b\\x8d\\xfd\\xf6\\xf0\\x76\\xad\\x0e\\xec\\xe7\\xf4\\x55\\x76\\xdf\\x4c\\x5d\\x86\\x1a\\x05\\x91\\xdc\\x80\\x3f\\xef\\xc6\\x65\\x21\\x44\\xa4\\x57\\x25\\xa6\\x02\\x18\\xc0\\x9e\\x71\\xab\\x3b\\x1c\\xf3\\xba\\xac\\xbb\\x61\\x99\\xdd\\x5b\\xda\\x86\\xcb\\xc5\\xa2\\x06\\xdf\\xc4\\x5b\\x82\\x89\\x01\\x8f\\x72\\x8e\\x1f\\x69\\xf5\\xa8\\xc0\\x7e\\x6e\\x66\\x42\\x83\\xd4\\x05\\x1d\\x2f\\x7e\\xf1\\x26\\x45\\xb7\\xc7\\x12\\x03\\x57\\xd5\\xbd\\x5d\\x8a\\xab\\x24\\x3d\\x91\\x5f\\xc7\\x0b\\xe3\\xbc\\x4a\\xb5\\xcc\\x50\\x21\\xa6\\xf6\\xa5\\xd2\\x1c\\x35\\xe8\\xea\\xbb\\x9f\\x26\\x23\\x95\\x7c\\xfc\\x46\\x0b\\x1a\\x7e\\x40\\x0c\\xf0\\x76\\x1a\\xa8\\x8b\\x2e\\x17\\x6f\\x54\\xaa\\x4c\\x1f\\x66\\xeb\\xc2\\xf8\\x10\\x4d\\x63\\x98\\x0b\\xbd\\x18\\x5d\\x5d\\x10\\xb8\\x43\\x98\\x99\\x19\\x44\\x5f\\x2b\\xf1\\x85\\x97\\x2a\\x62\\x8b\\x35\\xd2\\x43\\x15\\x3f\\x58\\x09\\x51\\xc9\\x84\\x0e\\xe0\\x9c\\x2c\\x13\\x39\\x7a\\x8a\\x81\\xc2\\xc0\\x25\\xb8\\x91\\x78\\xd5\\x74\\xed\\x99\\x47\\x10\\xce\\xdf\\x43\\x49\\x66\\x55\\xe3\\x7c\\xac\\x3c\\x91\\xd6\\x8d\\x94\\x73\\x3c\\xdc\\x7d\\x38\\xfd\\x38\\xab\\x0b\\x25\\xb8\\x40\\x7e\\xd7\\xb4\\x0a\\x53\\x92\\x57\\x27\\xa5\\x7c\\xa0\\xf8\\xfc\\x63\\x49\\x45\\xb6\\xb1\\x5b\\x8f\\x1e\\x47\\x2e\\x94\\x25\\x91\\x95\\xdd\\xa5\\xb6\\x97\\xf7\\x2b\\x40\\x59\\xda\\x68\\x74\\xcd\\xb3\\xcd\\x92\\x96\\xfd\\x4b\\x0f\\x47\\x80\\x98\\x10\\xba\\x86\\xf7\\x4f\\xec\\x4c\\x92\\x6c\\xc4\\x75\\xc8\\xed\\x53\\x4a\\x53\\xff\\xd0\\xfa\\x08\\xde\\x94\\x92\\x0c\\x7c\\x15\\x75\\xd3\\xe0\\xd2\\x2a\\x94\\xfb\\xef\\x3a\\x28\\xde\\xf9\\x7c\\xdb\\x6b\\x9b\\x65\\x2e\\x8f\\xc0\\x9a\\x82\\x33\\xfa\\x40\\xbd\\xf8\\x8d\\x40\\xf5\\x2e\\x20\\xb6\\x77\\x6e\\x21\\xbc\\x79\\xb3\\xb8\\x60\\x82\\xa1\\x0a\\x17\\x37\\xb5\\xe6\\x56\\x54\\x3a\\x20\\x37\\xc5\\x1e\\xa3\\x43\\xb7\\xf0\\x69\\xa9\\x03\\x6a\\x21\\x54\\x94\\x68\\x47\\x8e\\x6c\\x48\\x92\\xc0\\x85\\xea\\x6f\\x65\\x60\\x5e\\x52\\x52\\xec\\x00\\xa1\\x68\\xd5\\x4a\\x46\\xc6\\x18\\xa2\\x3c\\x49\\x50\\x00\\x6c\\xd9\\xff\\xa1\\xcd\\x77\\x3f\\x55\\x5b\\x9b\\x2c\\x10\\xf1\\x5e\\x3b\\xa7\\x75\\x5a\\x15\\x81\\x4f\\xaf\\x91\\xea\\x49\\xd1\\x97\\x45\\x01\\x5f\\x18\\xef\\x3e\\xd3\\xe4\\xef\\xd4\\xda\\xda\\x72\\x26\\xa4\\xa3\\xd4\\xce\\xe2\\x98\\xa8\\x9c\\x23\\xc6\\x8a\\x8c\\x9f\\x2c\\xef\\xf8\\xae\\x62\\x84\\xcc\\x72\\x2b\\x1d\\xac\\xa0\\x70\\x80\\xee\\x80\\x4e\\xdf\\x05\\xc0\\x4c\\xaa\\xe4\\xfd\\x17\\x19\\xa1\\x0e\\xe4\\xc0\\xbc\\x76\\x20\\x63\\xb1\\x84\\x9a\\x9b\\xf4\\x3b\\xff\\xa3\\x31\\x41\\xec\\x35\\x95\\x92\\x9e\\x6e\\x31\\x80\\xb3\\xf4\\xb7\\x39\\x3e\\x7b\\x27\\x51\\xa8\\x9d\\xb2\\x00\\x98\\x78\\x84\\x26\\x17\\x82\\x84\\x2f\\x69\\x5a\\xe1\\xd3\\xb2\\x12\\xf3\\x03\\x52\\xac\\x57\\x2b\\xaf\\xc6\\x87\\xbd\\xc3\\xcf\\x54\\xfe\\xec\\xd6\\xf2\\x58\\x72\\x1c\\xbe\\x2a\\x9f\\xc9\\x6f\\x41\\xde\\xb3\\x06\\x3a\\x32\\x07\\x6d\\x2a\\xd0\\xff\\x37\\xcb\\x3e\\x51\\x8a\\xb1\\x30\\x69\\x86\\x00\\x35\\x01\\xd8\\xb4\\xc4\\xf9\\x60\\x77\\xb0\\x68\\x5b\\x8b\\xc7\\x37\\x35\\x1a\\x00\\x43\\x15\\x9e\\x00\\xcb\\xbc\\x31\\x20\\xea\\x19\\x49\\xf5\\x5f\\x88\\x7a\\x09\\x61\\x69\\xc3\\x04\\xa2\\x4f\\xc0\\xc7\\xdb\\xcc\\x15\\xf7\\xc8\\x13\\x49\\x70\\xef\\x76\\xbe\\xc7\\xe5\\x10\\x29\\x17\\x50\\x69\\x6f\\xff\\x03\\x7e\\x92\\x4a\\x4f\\x58\\xe4\\x67\\x60\\x31\\xc5\\x96\\x96\\x2a\\x26\\x2f\\x72\\x61\\x9b\\x3f\\xe4\\x48\\x04\\x94\\x5b\\x7e\\x47\\x58\\x4c\\x3a\\xa8\\x0b\\xe9\\xbd\\x2c\\xf9\\x6f\\xc0\\xfa\\x23\\xbb\\xb8\\xef\\x1a\\xd9\\x37\\x3f\\xab\\xdb\\xb5\\x7d\\xa4\\xa0\\xee\\xc0\\xe9\\x50\\x83\\xe5\\xbe\\x17\\xbd\\x46\\xca\\xc8\\x6d\\x4b\\xb9\\x71\\x29\\x63\\xd6\\xd2\\xd7\\x40\\x87\\xfa\\xd7\\x61\\xd9\\x5f\\x18\\x31\\x05\\xff\\xcf\\x90\\x43\\x39\\x53\\xd6\\xb8\\x95\\x68\\xc5\\xb2\\xcd\\xc9\\x02\\x52\\xa9\\xa2\\x9e\\x6f\\xf3\\x8c\\x52\\x00\\x93\\x3a\\x24\\x2a\\x20\\x59\\x62\\x35\\xe2\\xf6\\x82\\x3f\\xd3\\x24\\xac\\x94\\xde\\x75\\xea\\x65\\x03\\xae\\xaa\\xa1\\xf6\\x6d\\x20\\x11\\xb4\\x01\\x6f\\x55\\xed\\xf7\\x9e\\x11\\x3a\\xa8\\x48\\x64\\x2f\\xa8\\xad\\x32\\x18\\xff\\xc2\\x17\\x0b\\x95\\x78\\x85\\x09\\xac\\x93\\x40\\x95\\x38\\x10\\x4f\\x91\\x3d\\xf2\\xed\\xe6\\xb2\\xaf\\x15\\x86\\x22\\x6d\\x02\\xf6\\x3f\\x93\\xdc\\x73\\xe2\\xdd\\x8b\\xa1\\x95\\x97\\xe9\\x77\\xa7\\x16\\x13\\xd1\\xa6\\x54\\xfe\\xcd\\xa6\\x8d\\xb8\\xe8\\x83\\x8f\\xad\\x63\\x1e\\x38\\x35\\x32\\x58\\x2f\\xde\\x68\\x59\\x8e\\x24\\xb0\\x30\\x50\\xc4\\x51\\x74\\x24\\x08\\x66\\x25\\xf8\\x79\\x86\\xbc\\x11\\x12\\x15\\x15\\x63\\x7a\\x11\\xdd\\x7a\\x1b\\xec\\x6f\\xde\\xf7\\xcb\\x0f\\xa1\\x77\\x08\\x30\\x3e\\x46\\x10\\x86\\x01\\x71\\x38\\xf0\\xa7\\x95\\xc9\\x1d\\xfd\\x9d\\x58\\x97\\x9f\\x5c\\xfe\\x84\\x6f\\xe7\\x3d\\x51\\x00\\x2c\\xf8\\x0a\\xe3\\xd9\\xdb\\x67\\x5d\\x5c\\xf2\\x26\\xc6\\xb0\\x83\\x38\\x48\\x2d\\xeb\\x51\\xf9\\xaa\\x9b\\x4a\\xbc\\x01\\xff\\x62\\xf3\\x43\\xe2\\x82\\x65\\x95\\xeb\\x65\\xa0\\x56\\xb0\\xea\\x97\\x7c\\xf3\\x52\\x57\\xf8\\x10\\xdf\\xe0\\x9c\\x32\\x44\\xef\\xf7\\x87\\xdf\\x72\\xb0\\xd5\\xb4\\x4e\\x6c\\x95\\x38\\xcb\\x1a\\x47\\x6e\\xbf\\x49\\x19\\xaa\\xfd\\xe6\\xb6\\x71\\x3d\\xe1\\x3c\\x7c\\x1b\\x65\\x75\\xcb\\xb4\\xee\\x27\\x84\\x8d\\x9c\\xc0\\xd6\\xd6\\x5c\\x7e\\x22\\xb8\\x1a\\x91\\xaa\\x8d\\xd4\\x65\\x54\\xa6\\x02\\x50\\xe4\\x96\\x78\\xcc\\xe5\\x8b\\xd9\\xa8\\x8c\\x9f\\xd3\\x05\\xe8\\x6c\\x61\\xfb\\x2b\\xd6\\xd0\\xb5\\x0c\\x92\\x38\\x84\\x9a\\x4f\\x39\\x67\\x49\\x46\\x18\\x26\\x58\\xbc\\x04\\x8d\\x8e\\xa7\\x8e\\x61\\x98\\x00\\xd9\\x90\\xa4\\xf5\\xc2\\xda\\x85\\x39\\x42\\xb6\\x64\\xbc\\xcf\\x25\\x13\\x5e\\x36\\xf7\\xaf\\xff\\x99\\x3a\\xd4\\x18\\x2a\\x63\\x33\\x79\\x2e\\x4e\\xf0\\x8e\\x7a\\x48\\x08\\xed\\x06\\x72\\x06\\x32\\x31\\x81\\x81\\x9d\\x6c\\xe7\\x5f\\xb9\\xe4\\x8e\\xa7\\xcb\\x49\\xbe\\xdf\\x75\\x61\\x26\\x81\\x32\\x77\\x23\\x17\\x01\\x35\\x5f\\xe3\\x70\\x81\\xa5\\x7f\\x69\\x72\\xbe\\xcc\\xc4\\x87\\x5a\\x0e\\x34\\x86\\x03\\xf3\\xf0\\x92\\xa8\\xe7\\x10\\xb9\\x00\\x37\\x1c\\x42\\x93\\x4d\\x10\\xf0\\x53\\x72\\x4c\\xac\\x92\\x80\\x5b\\x82\\xbe\\x9f\\xa7\\x1d\\x5c\\x9e\\xc6\\x4c\\xf5\\x33\\x91\\xd8\\xaf\\x69\\x32\\xbb\\x13\\x5c\\x11\\xd4\\x4c\\x18\\x34\\xb4\\x5b\\x68\\x1a\\x1d\\x12\\xf3\\xe2\\x68\\x7e\\x65\\x24\\xa3\\x6b\\xad\\x5e\\x0b\\x11\\x4c\\x0e\\xd0\\x1a\\x45\\xa6\\xfd\\xf5\\x5a\\x04\\x04\\x2b\\x95\\x2d\\xf3\\xb3\\x36\\xf5\\x46\\x78\\xe3\\xad\\xce\\xf8\\x41\\xe3\\xfd\\x73\\x07\\xe4\\xf9\\x80\\x43\\x24\\x35\\x11\\x80\\x08\\xdd\\x53\\x01\\xe0\\x5f\\x32\\x1e\\x72\\x90\\xcf\\xf8\\x6d\\x93\\x3e\\xb1\\x16\\xe9\\xd8\\x11\\xc1\\x1a\\xb9\\x27\\xfe\\x0e\\x07\\xeb\\x15\\x3d\\x02\\x4a\\x50\\xb7\\x51\\x1d\\x57\\x23\\xc2\\x2f\\x68\\xca\\xb6\\x42\\x5a\\x00\\xf5\\xc7\\x3d\\x72\\xce\\xba\\x46\\xbd\\x4d\\x12\\xec\\x24\\x18\\x7a\\x48\\xb9\\xb1\\x90\\x7f\\xea\\x6f\\x55\\xbe\\x1c\\x51\\x46\\x1d\\x63\\x3e\\xf6\\xf7\\xc3\\x63\\xc9\\xeb\\xd1\\x92\\x20\\x0d\\x60\\x21\\x0b\\x69\\x81\\x00\\xcd\\x71\\xe3\\xdc\\x2b\\x67\\x21\\xb4\\x4d\\x30\\x6b\\x8c\\x3a\\x74\\x6a\\x75\\x6f\\x58\\xc9\\xf5\\xc7\\xb3\\x84\\xa8\\x88\\x59\\xf9\\xb7\\x75\\x13\\xf2\\x1a\\xa0\\x83\\xc0\\x36\\x6b\\x4e\\x30\\x69\\x53\\x0a\\x3c\\xc0\\x62\\x52\\x62\\x21\\x7d\\x29\\x54\\xa3\\xe4\\x9d\\xb2\\x90\\x78\\x5f\\x2f\\x59\\xd2\\x72\\x32\\x90\\x55\\x05\\xa6\\x6f\\xac\\xdc\\x96\\xa5\\xe5\\x78\\x47\\xf3\\xdf\\x62\\xe8\\x29\\xce\\x4b\\x3c\\xea\\x56\\xbf\\xd7\\x16\\xac\\x04\\x98\\x68\\xcb\\x2e\\x39\\x52\\x2f\\x83\\xbb\\x11\\x12\\xab\\xd0\\xea\\x8c\\x7c\\x18\\x07\\x6c\\x4f\\x3a\\xa4\\xf9\\xa3\\x17\\x04\\xc0\\x5a\\x59\\x2b\\x12\\x7c\\xe6\\x0d\\x69\\x9e\\x19\\x35\\x55\\xc2\\x82\\xd7\\xcc\\x4d\\x87\\x6f\\x0c\\x6d\\xa1\\x7f\\xa2\\x1c\\xbf\\x0f\\xc7\\x19\\x4d\\x28\\xe5\\x35\\x92\\x0a\\x84\\x35\\xeb\\x54\\xea\\xca\\xa2\\x93\\xb6\\x93\\x94\\x7a\\xb3\\x60\\x12\\x6b\\xd3\\xff\\x23\\x73\\x58\\xcf\\x9e\\x6b\\x84\\x7d\\x1d\\x8a\\x1f\\x17\\x7a\\x44\\x92\\x86\\xf9\\xb7\\x9f\\x69\\xbb\\x75\\x65\\x61\\x76\\xb9\\x20\\x82\\x7e\\xcd\\xe2\\xec\\xd5\\x88\\x11\\xf8\\xbb\\x36\\x25\\x5e\\x35\\xde\\xa0\\xd2\\x21\\x4f\\xb5\\xdb\\x82\\x9b\\x16\\xaa\\x27\\xf9\\xa9\\x0b\\xe1\\x8e\\xba\\x1f\\x9e\\x6b\\xfc\\x5e\\x5e\\x1d\\xd7\\x88\\x38\\xdd\\xde\\xb2\\x79\\x33\\xe4\\x19\\xf8\\xe5\\x7b\\xb5\\xfd\\x4e\\x06\\x54\\x26\\xb1\\xe8\\xb5\\xc5\\x83\\x74\\xf4\\x45\\x34\\x3e\\xb8\\x3b\\xb0\\xd5\\xd6\\xaf\\x61\\x1b\\xba\\x50\\x77\\x39\\xd4\\x5d\\x21\\x4e\\xc8\\x4f\\x19\\x1d\\x6c\\xc7\\x1e\\xcf\\xd7\\x42\\xad\\xbc\\xe7\\x10\\x78\\x6f\\x3f\\xd1\\x9e\\x57\\x31\\xca\\x3e\\xca\\x41\\xe7\\xc4\\x9d\\x3f\\xba\\xea\\x29\\x3f\\xf2\\xff\\x71\\xd6\\x7d\\x6d\\x7f\\x10\\x77\\xa6\\x8f\\xec\\x70\\x11\\x29\\x51\\x45\\x27\\xe3\\x90\\xb4\\xf1\\x0c\\x27\\xdc\\xf6\\xd2\\xcc\\x47\\x64\\x01\\x21\\x9f\\xec\\xeb\\x53\\x38\\x2c\\x9a\\x59\\x9e\\x6b\\xea\\xfd\\x5d\\x2a\\x3d\\x48\\x96\\x83\\x4c\\xac\\x0e\\xd6\\x5c\\x27\\x93\\x48\\x68\\x2a\\x60\\x12\\x36\\x94\\xce\\xf7\\x62\\x50\\x93\\x57\\xb1\\x49\\x62\\x4f\\xbc\\x32\\x68\\xc2\\xc4\\xb8\\xd7\\x0d\\x86\\xed\\xb6\\xa0\\x5e\\xb1\\x22\\x03\\x88\\x8a\\x79\\x9c\\x8a\\x3e\\x93\\x05\\x3f\\xde\\x0e\\xa8\\x86\\xe9\\x06\\x2d\\x78\\x75\\x8d\\xc6\\x55\\xfb\\x9f\\x98\\x0e\\x21\\x57\\x1f\\xbc\\x17\\xbb\\x4a\\x68\\x23\\x61\\xf4\\x21\\xd3\\x38\\x8f\\xbe\\x4c\\x72\\x5f\\xd9\\x2c\\xf2\\x29\\x52\\x7d\\x9b\\x8b\\xe1\\xd2\\x41\\xab\\xd1\\x75\\x60\\x84\\x71\\x0c\\xb4\\x3d\\xea\\x0b\\xa0\\x80\\xc4\\xa3\\x53\\xca\\x91\\xd7\\xac\\x95\\xbc\\x02\\x39\\x1b\\x5e\\x56\\xff\\x7c\\x46\\x12\\x67\\xfb\\x68\\x5e\\x0d\\xee\\x05\\x9e\\xb2\\x89\\x7a\\xb6\\xa3\\x77\\x95\\x5e\\x1b\\x67\\x16\\x74\\x0f\\x7f\\xed\\x08\\xf7\\x47\\xba\\xa2\\x2d\\xd0\\xc6\\xdd\\xce\\x64\\x8f\\x1f\\xe5\\x62\\x53\\x3a\\x4f\\xa3\\x74\\x5e\\x15\\xcc\\x97\\x1c\\x50\\x3c\\xc7\\x36\\xe3\\xda\\x30\\x8f\\xb0\\xf1\\xb0\\x72\\xe6\\x11\\x51\\xb9\\x8d\\xf4\\xf3\\xa0\\x63\\xa6\\x5a\\x5b\\x46\\xe9\\x66\\x51\\x1a\\x66\\xef\\x60\\xfd\\x66\\x71\\x3e\\x9d\\xda\\xc3\\xc5\\xe2\\xa3\\x28\\x09\\x9d\\x98\\xda\\xe2\\xea\\xd1\\x94\\xdf\\xf3\\xc8\\xd9\\xa3\\xc6\\x53\\x04\\x89\\x3c\\x08\\xed\\x22\\x96\\x9d\\xf7\\xd7\\x25\\x67\\x73\\x06\\xaf\\x39\\x9b\\xca\\xd3\\x6f\\xb3\\x15\\x62\\x4e\\x57\\x7a\\x1c\\x6b\\xe1\\xb6\\xb2\\x40\\xf1\\x69\\x6a\\x43\\x94\\xbb\\xdf\\x4c\\xaa\\xd5\\x9f\\xc0\\xc9\\xc6\\xde\\xb4\\xe9\\x40\\x06\\x54\\xa2\\x1b\\x1a\\x18\\xfa\\x85\\xbd\\xd1\\x2f\\x41\\x34\\xa5\\xc0\\xae\\x88\\xc8\\x45\\x21\\x3a\\x68\\x7e\\x86\\x29\\xea\\x77\\x39\\xf0\\x73\\x57\\x9f\\x66\\x01\\x78\\x6c\\x1c\\x44\\xed\\xfa\\x6a\\xc1\\xe6\\x57\\x8b\\x7b\\xf3\\x86\\x07\\xc8\\x21\\xd8\\x93\\xe5\\xcf\\x21\\x01\\x39\\x52\\xa1\\x8b\\x15\\xe6\\x70\\xce\\x8a\\x8e\\xba\\x5e\\xa5\\xd5\\x17\\x98\\x79\\x69\\x65\\x6d\\x97\\x6d\\xbf\\x62\\xe7\\x44\\xc6\\x75\\xe1\\xea\\xf3\\xde\\x1c\\xca\\xd3\\x22\\x48\\x5e\\x56\\x7a\\x6e\\x32\\x6a\\x01\\x14\\xaf\\xfc\\xf3\\x61\\x66\\x96\\x87\\xee\\x00\\xc8\\x20\\x43\\x07\\x1c\\x3d\\xf9\\xa9\\xda\\x01\\x83\\x40\\x23\\x67\\x8a\\x0d\\x30\\xaa\\x36\\x5d\\x13\\x27\\xf6\\x95\\xa6\\x8d\\x99\\x12\\x17\\x62\\x9e\\xc2\\x77\\x70\\x16\\x24\\xb9\\x0d\\x79\\xaa\\xc7\\xb0\\xaa\\x48\\x38\\x03\\xf5\\xc9\\x59\\xfb\\xa7\\xd9\\x5c\\xd4\\xdc\\xdd\\x5c\\x35\\xdc\\x41\\x41\\x5a\\xe2\\x57\\x82\\x02\\x87\\x20\\x79\\x5e\\xa6\\xc8\\x36\\x18\\xd2\\x0d\\x0c\\xa5\\xd9\\x1f\\x64\\xd6\\x15\\x08\\x3a\\x51\\x13\\xdf\\x51\\xac\\xb1\\x91\\xc6\\x8a\\x07\\xa8\\x1e\\x87\\x41\\xbb\\x1c\\x93\\xc8\\x34\\x01\\x82\\x33\\xa6\\x87\\x3e\\xda\\x3c\\x7c\\xf9\\xa4\\x05\\x28\\x33\\x0a\\x62\\xb0\\x92\\xae\\xa8\\x90\\xfb\\x82\\x05\\xf7\\x2b\\xe1\\xb6\\xbc\\x46\\xf3\\x75\\xe1\\xdf\\xf5\\x90\\xd0\\x6c\\xfa\\xf5\\xd2\\xdd\\xa2\\x3f\\xbc\\x12\\x2a\\x30\\xef\\x7e\\x4d\\x62\\x84\\xb6\\xa5\\x28\\xb6\\xbb\\x9e\\xc0\\xd7\\xb8\\xf7\\x74\\x02\\xff\\x1f\\xf1\\xdd\\x9c\\xe1\\xd2\\xd2\\xa5\\x9b\\x23\\xfe\\x32\\xf5\\x26\\x0d\\x70\\x6b\\x02\\x8e\\x40\\x41\\xde\\x7f\\x9e\\x1f\\x38\\xd4\\xa7\\x2e\\xc9\\x1b\\xf6\\x07\\x84\\x25\\x9c\\x2f\\x8d\\x6d\\x09\\x39\\x88\\xef\\xf9\\xa4\\x01\\xbd\\x12\\x44\\x6f\\x2e\\x56\\x4a\\x63\\x23\\x44\\x97\\xac\\x01\\x39\\x8b\\xb5\\xec\\x30\\xfb\\xc4\\x3b\\xe0\\x3e\\x8f\\xaf\\xed\\x37\\x8f\\x14\\x14\\x38\\x5e\\x49\\x92\\x45\\x59\\x78\\x3d\\xf9\\x1a\\xc0\\xd6\\x3b\\x4f\\xd2\\xc2\\xc9\\x10\\xd8\\x88\\x1e\\x9a\\x9e\\x3e\\x7e\\x1e\\x4a\\x42\\xcd\\x02\\x11\\x13\\x09\\x46\\xe8\\xbc\\x6f\\xc8\\xdb\\xb6\\x5a\\x54\\x55\\xd2\\x69\\xd5\\x39\\xc0\\x5f\\xdc\\x15\\xf2\\x01\\x9b\\x5c\\x0e\\xfe\\x4d\\x8d\\x8e\\xd6\\xa1\\x0f\\xf1\\xc8\\xf4\\x63\\xc3\\x35\\x0b\\xfb\\xaa\\xcc\\xb6\\x06\\x6f\\x2e\\x99\\x7f\\xb7\\xca\\xbb\\x0a\\xca\\x9e\\x75\\x8a\\xf3\\x09\\x85\\xb5\\xec\\x17\\x79\\x9c\\xae\\xa1\\xf0\\xa3\\x31\\x83\\xe1\\xc2\\x2f\\xfc\\x2c\\x73\\x4f\\x63\\x67\\x61\\x79\\x29\\x69\\xb5\\x1a\\xd9\\xdf\\x4b\\x08\\xcb\\x93\\x93\\xcd\\x54\\xfa\\xb2\\x23\\x26\\x78\\x89\\x2c\\x8e\\x78\\x28\\x8c\\x55\\xda\\x5f\\x75\\xec\\xee\\xb8\\x7b\\xfb\\xb5\\xbf\\xb3\\x59\\x62\\x20\\xda\\xef\\xeb\\x15\\xe1\\xff\\xd6\\xff\\x83\\x73\\xed\\xff\\x12\\xd8\\x58\\x8d\\x92\\xef\\x33\\x33\\x81\\x18\\x3a\\xed\\xc6\\x4e\\xfb\\x60\\x94\\x8e\\xcb\\x4e\\x34\\x91\\x2d\\x32\\xfd\\xaa\\x58\\xec\\x18\\xaa\\x4f\\xfe\\x78\\xfe\\x8d\\x5f\\xe3\\xa8\\xb4\\x9c\\x5b\\x63\\x31\\x78\\x04\\x14\\x12\\xad\\x86\\x40\\x4c\\xb7\\x88\\xba\\xe0\\xb2\\x0c\\x58\\x5a\\x0e\\x3f\\x87\\x6f\\x02\\xbb\\x30\\x8b\\x7d\\xfd\\x40\\xf9\\xc3\\x46\\x68\\x7d\\xa1\\x4f\\xc5\\xd1\\x21\\xfe\\x43\\x24\\x79\\x24\\xf8\\x3e\\xdd\\x9f\\x20\\xc8\\x11\\xa7\\x49\\x60\\x8e\\xb3\\x40\\xeb\\x39\\x0c\\x7a\\x52\\x94\\x60\\x3b\\x1a\\xf4\\xe5\\x40\\x2a\\x94\\xcc\\x6f\\x8c\\x2b\\x99\\xaf\\xa3\\x35\\x37\\x6e\\x52\\x5b\\x32\\x50\\xcd\\x8b\\x7c\\x6f\\x3a\\xe6\\x4d\\x9c\\x22\\x68\\x2c\\x41\\xd3\\x61\\xe4\\x52\\x3b\\x66\\x48\\x6b\\x55\\x44\\xb0\\x59\\x50\\x15\\x33\\x1f\\xbc\\xf9\\x6c\\x9b\\x41\\xbb\\xc0\\x87\\x6e\\x48\\x45\\x61\\x33\\x27\\x1e\\xc4\\x5f\\x9e\\x79\\x8d\\x37\\x6d\\x92\\x3b\\xd5\\xa4\\x5b\\xf6\\x93\\xff\\x29\\x30\\xf3\\x31\\x70\\xb7\\x37\\x6c\\x3b\\xe0\\xad\\x01\\x83\\x55\\x0d\\x3b\\x7a\\x5a\\xff\\x5e\\x49\\x05\\x11\\xfe\\xbf\\x64\\xfd\\x24\\x12\\xac\\x82\\x48\\x15\\xc6\\x1d\\xe2\\xba\\x6b\\x01\\x10\\x8c\\x13\\xf2\\xf1\\xf5\\xf6\\xd7\\x2a\\x88\\xbb\\x5a\\x2a\\x0d\\x7d\\x94\\xee\\xc2\\x5e\\xbe\\x94\\x7a\\xa6\\xf5\\xd2\\x62\\xec\\x56\\x57\\x1d\\xf4\\xe7\\x86\\x4e\\x0f\\x5f\\x8c\\x3d\\xf4\\xf0\\x74\\xe2\\xed\\xad\\x7e\\x95\\x9b\\x9c\\xbf\\x94\\xee\\x24\\x1d\\x5d\\x5c\\x0e\\x57\\xc1\\x71\\xe8\\xaf\\x2b\\xc7\\x9d\\xf5\\x18\\x64\\xcf\\xc6\\x1c\\xab\\x6b\\x1d\\x58\\x57\\x42\\x07\\x5f\\x4f\\x3a\\x1a\\x1c\\x08\\x02\\x5a\\x71\\x5c\\x7e\\x6a\\xe8\\xaf\\x0b\\x62\\xa4\\x98\\x29\\x43\\xba\\xcb\\x79\\x4b\\xab\\x49\\x1f\\xb0\\x84\\x92\\x7d\\xf5\\x04\\xd1\\xcf\\xae\\xfc\\x4f\\x13\\xa6\\xed\\x23\\x33\\x7e\\x5e\\x80\\x85\\x52\\x72\\xc8\\xfe\\xb1\\xa7\\x3e\\x08\\x6b\\x23\\x92\\xe7\\xbf\\x32\\xf8\\x97\\x96\\xf7\\xfd\\x43\\xac\\x2c\\x51\\xbe\\xac\\xe1\\x7d\\x5a\\xf8\\xcd\\x66\\x9f\\x63\\x5f\\x4e\\xf4\\x1b\\xbb\\xa8\\x64\\x41\\x96\\x84\\x3e\\xf9\\x5b\\x3e\\xb0\\x4f\\xeb\\xad\\x9f\\xc2\\xb4\\x5c\\xb8\\x1a\\xb2\\x71\\x58\\x0b\\x8c\\xea\\xa1\\x83\\xd5\\x09\\xa5\\xbc\\xd3\\x3a\\x05\\xed\\x3d\\x72\\x9d\\x22\\x74\\xbb\\xeb\\x9e\\x0e\\x1f\\xbd\\x82\\x41\\xf1\\x84\\xc5\\x07\\x30\\xf7\\xe8\\x8d\\xc7\\x4a\\x15\\x66\\x83\\x0c\\x45\\x90\\xee\\x40\\x65\\x9a\\xad\\xc7\\x42\\xb5\\x2a\\xba\\x23\\x94\\x73\\x8c\\x5b\\x31\\xc4\\x61\\xa1\\xc8\\x52\\x4a\\x6d\\x19\\xf6\\x97\\x9b\\x48\\x38\\x5e\\x9d\\x18\\x0e\\x44\\xd2\\xb8\\x28\\xe9\\x7e\\x54\\x68\\xb2\\xe4\\xa7\\x71\\xb9\\x2f\\x78\\x0d\\x2b\\x4e\\x9e\\x1b\\x2e\\x96\\xd4\\xd7\\xba\\x79\\xbc\\x77\\x2b\\x6f\\x76\\x91\\xa1\\xcc\\x04\\xf7\\xf9\\x2f\\x45\\xcd\\x3f\\xd4\\x88\\x27\\x40\\xd6\\x39\\xa6\\x1d\\x6b\\xf1\\xc7\\x7d\\x35\\x27\\x5d\\xcc\\x8a\\x26\\x7b\\x87\\xf5\\x0d\\xd6\\x2b\\xc0\\x31\\x47\\x73\\xde\\x93\\x69\\x54\\x12\\xfd\\xe0\\xfc\\xe3\\xe6\\xba\\x5c\\xa2\\xf5\\x4f\\xef\\x37\\x02\\x8c\\x6d\\x7a\\x68\\x48\\x3a\\x44\\xc4\\x3e\\x46\\x39\\x36\\x07\\x92\\x8e\\x3b\\xcb\\x85\\xbc\\xe9\\xa0\\x78\\xc1\\xde\\x9d\\x58\\x01\\x5b\\x31\\x88\\x48\\xdb\\x2d\\xb7\\x27\\x52\\x7c\\x7e\\x90\\x2f\\x86\\x46\\x78\\xcf\\x41\\xbf\\x0e\\xbf\\x11\\x9e\\x01\\x89\\xff\\x67\\x60\\xd6\\x17\\xea\\xcd\\x3e\\x3f\\x63\\xbf\\xc4\\xae\\x44\\x6d\\x8e\\x48\\x30\\xa5\\x9f\\x4a\\x28\\x0c\\xbb\\x34\\x5a\\xc6\\x88\\x0f\\xd4\\xd7\\x35\\xf1\\x2d\\x02\\x24\\x1d\\xaa\\xf6\\x68\\x26\\xc6\\x03\\x35\\x3b\\x09\\x94\\x64\\xd7\\xc9\\x9a\\x47\\x2b\\x76\\xc1\\x20\\x82\\xbc\\x78\\xc5\\xbf\\x3c\\x73\\x69\\x7d\\x0c\\x10\\x41\\x75\\xb1\\xdc\\x44\\x71\\xb1\\xfa\\x23\\x2d\\xd0\\x81\\xd8\\x75\\xeb\\xe3\\x6d\\x13\\x14\\x62\\x0f\\xaf\\xaf\\x0e\\x81\\xcd\\xba\\xda\\x94\\x83\\x19\\x4f\\x34\\x23\\x6a\\x5d\\xf3\\x61\\xda\\x1f\\x4d\\x09\\x38\\xd9\\xf3\\x35\\x67\\xe3\\x43\\xbf\\xbc\\x87\\xb2\\xbf\\xe1\\xda\\x66\\x8d\\xa2\\xb5\\x50\\x66\\xbf\\x04\\xbd\\x17\\x1e\\x98\\x8f\\xe5\\x67\\xd7\\x7e\\x8d\\x00\\x60\\x6a\\x7e\\x35\\x92\\xf5\\x75\\xd8\\x4d\\x42\\xef\\x84\\x89\\x91\\xc5\\x7b\\xbc\\x93\\xca\\xeb\\xb2\\xda\\x8e\\x08\\x10\\xa0\\x61\\xa4\\x59\\xbb\\x34\\x4a\\x43\\x38\\xc6\\x25\\x87\\x4e\\xa2\\x68\\x49\\x01\\x30\\xee\\x98\\x45\\x48\\xf9\\x92\\x47\\x4e\\xa5\\x4d\\x12\\xe8\\x9b\\xc2\\x0f\\x43\\x1e\\xc1\\xf9\\x76\\xe7\\xcf\\x5e\\x89\\x67\\x7c\\x66\\x2a\\x73\\xac\\xc9\\xc1\\x1b\\xd1\\xaf\\xf0\\x33\\xa3\\x34\\x0d\\x04\\x1e\\xf8\\xb3\\x61\\x08\\xac\\x11\\x6d\\x84\\x4d\\x6b\\x8f\\xc9\\xcd\\x83\\xc3\\x8b\\x95\\x56\\x1b\\x1b\\x7a\\xc9\\xa5\\xc6\\xbc\\x11\\x0e\\x4c\\x05\\x25\\x3e\\x7d\\xc0\\x54\\x93\\x9e\\x42\\x84\\x37\\x00\\x1e\\x2d\\x49\\xd5\\x15\\x5f\\x97\\xfd\\xde\\x5e\\x39\\xc0\\x63\\x91\\x60\\x96\\x07\\x81\\x39\\x64\\x56\\xdc\\x90\\x83\\x91\\x50\\x97\\xd8\\xe4\\x73\\x0e\\xb1\\xc4\\x5a\\x56\\xa8\\xa0\\x1e\\x29\\x0e\\xf4\\x1e\\x1e\\x9d\\x06\\xd9\\x89\\x14\\x00\\x59\\x9d\\x94\\x08\\xc9\\xf2\\x93\\xb4\\x4a\\x08\\x22\\x47\\xf9\\x11\\xa0\\xa0\\x76\\x17\\xd2\\xfd\\x05\\x73\\xd1\\x32\\x3d\\xd0\\x6e\\x15\\x62\\x9a\\xb3\\xc1\\x3e\\x78\\x91\\x5a\\x7b\\xbf\\xf7\\xfe\\x61\\x87\\x12\\xcc\\xed\\xf5\\x75\\xf6\\x39\\x93\\x9e\\xc5\\x77\\xd0\\xc8\\x90\\xac\\x4c\\xe8\\xb1\\xe8\\x28\\xe9\\x76\\x14\\x21\\xba\\x2d\\x85\\xf8\\x1b\\x57\\x8c\\x5e\\x73\\xbd\\x9b\\x30\\xc3\\x62\\xd0\\x3d\\x80\\xc4\\x55\\xcd\\x89\\x87\\xe8\\x8c\\xa3\\xf4\\x70\\x16\\x8f\\x65\\x77\\x67\\xd0\\x87\\x01\\x7b\\x2c\\xbd\\xd7\\xf6\\x93\\xa3\\x58\\x93\\x7c\\xa0\\x01\\x2a\\x47\\xf0\\x24\\xc7\\xd5\\x5a\\x4b\\x83\\x58\\xed\\xaa\\x00\\xbc\\xec\\xeb\\x42\\xd8\\x3d\\x18\\xd7\\x95\\x8f\\x82\\xe9\\x7f\\xcf\\xdc\\xe4\\xd7\\x63\\x03\\x6e\\xff\\x50\\xdb\\x36\\x1c\\x0f\\xc9\\x4f\\x0a\\x0e\\x53\\x17\\x1a\\xa3\\x11\\x35\\xf7\\x97\\x45\\x47\\xe7\\x8f\\x34\\x95\\x46\\xef\\x77\\xd2\\xe1\\xc6\\x49\\x3c\\xd1\\x44\\x5a\\xba\\x66\\x6f\\xb3\\xde\\x48\\x7a\\xc1\\x52\\x3b\\xae\\x5b\\xfb\\x30\\xfb\\x33\\x60\\x5b\\x4a\\x06\\xba\\x40\\xf4\\x34\\xe5\\xd7\\x9e\\x32\\x6f\\x24\\x60\\xc6\\x3e\\x58\\xc4\\x6c\\x6f\\x61\\x49\\x40\\x50\\xe3\\x5d\\x48\\x48\\xd4\\x8c\\x5a\\xda\\x18\\x06\\x52\\xde\\x4f\\x7f\\x87\\x8a\\x76\\xd5\\x56\\xe7\\xa4\\xf8\\x67\\x6b\\x8b\\xf7\\x13\\x8c\\x09\\x32\\xed\\xad\\xe6\\x27\\x93\\x5a\\x7a\\x5a\\x20\\x5c\\xe0\\xbb\\xfc\\x9d\\xb7\\x87\\xe2\\xa4\\xa8\\xe9\\xb3\\x60\\xfd\\x63\\x5f\\x8e\\x23\\x68\\x2f\\xb9\\x28\\xe2\\x1f\\x94\\x99\\x87\\x88\\x2c\\x5e\\x61\\x40\\x1c\\xdf\\xb9\\x99\\xd1\\xa1\\xc4\\x38\\xff\\xa1\\x2d\\xf1\\x53\\xa1\\xd7\\xbe\\xe7\\x69\\xfd\\x95\\xcc\\x34\\x3c\\x7d\\x8a\\x09\\xdc\\x58\\xbd\\xd4\\x8d\\xf3\\x8e\\x58\\xf7\\x30\\x76\\xff\\x6e\\x68\\xdc\\x52\\x9a\\x33\\x8d\\x3b\\x77\\xf7\\xfd\\xac\\xe2\\x70\\xa0\\x1d\\x5f\\xfe\\x85\\x78\\x55\\x02\\xf1\\x39\\x52\\x53\\x9b\\x76\\x2d\\x72\\x46\\x97\\x26\\xa0\\x31\\x4a\\x52\\x67\\x6a\\x7d\\x2a\\xcb\\x81\\x8f\\x41\\xbf\\xab\\x14\\x06\\x80\\xab\\x8f\\x11\\x45\\x31\\x40\\x57\\xc2\\x92\\x2c\\x3b\\x0d\\x99\\x32\\x5f\\x18\\xc1\\xc2\\xed\\x6f\\xd8\\x76\\xdc\\x42\\x88\\x0f\\x26\\x5a\\xaa\\x89\\xcc\\xf2\\x01\\x2a\\x42\\x69\\xa1\\xf8\\x92\\xfc\\x11\\xf6\\xb6\\xca\\xf8\\xb0\\x7a\\x00\\x95\\x71\\xfc\\x81\\xe2\\xcf\\x5a\\x0f\\x8a\\xf7\\xb3\\xc2\\xe0\\xce\\xc6\\x73\\x98\\xcd\\x4e\\x71\\x3c\\x51\\xcb\\xc0\\x03\\x63\\x2e\\xa8\\x52\\x78\\xb1\\xb2\\xfe\\xe3\\x4c\\x48\\xe0\\x1b\\xa4\\xaa\\x83\\x3f\\xd2\\x1d\\x83\\x76\\xb3\\x5b\\xe6\\x3e\\x7b\\xbe\\x20\\xd1\\xd7\\xf6\\x16\\x18\\x80\\x60\\xe6\\x3c\\x13\\xd3\\x01\\x33\\xbb\\x07\\xa1\\x02\\x3f\\x2f\\x48\\x7a\\x96\\x97\\x16\\xf5\\x54\\x86\\x8a\\x1c\\x45\\x91\\x05\\x50\\x79\\xc6\\xf4\\x7e\\x48\\xa6\\xc8\\xfc\\x9e\\xf3\\xbe\\x5f\\x09\\xf0\\x16\\x28\\xaa\\x75\\x0e\\x81\\xca\\x3f\\xc9\\x47\\x19\\xd4\\xb8\\xfb\\x31\\x64\\x1d\\x7b\\x48\\x6b\\xf1\\xde\\x2d\\x17\\x6e\\x8a\\xdf\\x77\\x3f\\x3f\\x99\\x91\\x30\\xed\\xf1\\xc4\\x0d\\x90\\xfc\\x65\\x27\\x58\\x24\\xfd\\x7c\\xfb\\x11\\x88\\x1e\\x44\\xee\\xf6\\xd2\\xe5\\x44\\xa4\\xdd\\xc2\\xd8\\x1a\\x12\\xb0\\x86\\xac\\xc2\\x48\\xb4\\x22\\x9f\\x3b\\x08\\x8f\\xfd\\x90\\x86\\x3e\\x25\\xe0\\x52\\xc8\\x5f\\x8f\\xdf\\x1f\\x09\\x23\\xe5\\x90\\xdf\\xc8\\xb8\\xec\\x85\\xca\\x08\\x77\\x9f\\x08\\x71\\x74\\x2f\\x9d\\x84\\x1f\\x53\\x1c\\x7c\\xb7\\x70\\xea\\x7d\\x5d\\xf4\\x1b\\xbe\\xa8\\x31\\x9f\\x1f\\x2c\\x35\\x9f\\x33\\xa4\\xa3\\x5f\\x54\\x7d\\xa0\\x3f\\xfc\\xbd\\x73\\xfb\\xb9\\xac\\x10\\xe7\\xce\\xba\\x55\\xe5\\x94\\xc6\\xfd\\xc1\\xfa\\x15\\x41\\x0e\\xc1\\x4e\\x4c\\xc8\\x0b\\x1b\\xee\\x37\\x58\\x57\\x17\\x00\\x74\\x06\\x1c\\x51\\xe6\\xbb\\xf3\\xe6\\x43\\x3a\\xd7\\x2b\\xf1\\x1a\\xe2\\xbc\\x02\\x1e\\x5f\\x01\\x78\\x4e\\x28\\x01\\x27\\xe3\\x63\\x4b\\x81\\xac\\xfb\\x51\\x8e\\x96\\x9a\\xd1\\x7a\\xc8\\x51\\x00\\x44\\x35\\xd0\\xde\\x01\\x98\\x0d\\xcb\\xf8\\xe8\\x04\\x70\\x22\\x09\\xa3\\x2d\\xb5\\xba\\x2b\\xe8\\x67\\xff\\x95\\x09\\x1e\\xef\\x14\\x60\\x49\\xb5\\xa0\\x60\\xf2\\xbd\\xc3\\x50\\x81\\xbc\\x47\\xd6\\xdf\\xab\\xbb\\x83\\x50\\x66\\xce\\x95\\x0f\\x4c\\x96\\x27\\xd1\\x58\\x2e\\xe3\\x5d\\x66\\x8c\\xc0\\x20\\x9b\\x64\\xaf\\x9a\\x9f\\x9c\\x71\\xd1\\x2d\\xab\\xa7\\xe8\\xa3\\x59\\xc8\\xaa\\xa5\\x85\\x7a\\x47\\xcd\\x6e\\x1c\\x9d\\xf5\\x51\\x81\\x3e\\x95\\xe2\\x0c\\xac\\xe2\\x5f\\xd9\\xf3\\x1b\\x01\\x18\\x0d\\x92\\xce\\xb8\\x76\\x70\\xa6\\x0d\\x4f\\xa1\\x63\\xe3\\xf5\\x5d\\x7d\\xd9\\xd7\\x16\\x00\\xa8\\x38\\x35\\x5c\\x35\\xfb\\xf9\\x0c\\x17\\x60\\xaa\\xf3\\x12\\x8e\\xb7\\x28\\x55\\xb8\\xe9\\xdd\\x1c\\x92\\xcd\\x9a\\x40\\x78\\x13\\xbc\\xbf\\x23\\xe4\\x23\\x33\\x57\\xfd\\x09\\xe2\\x7c\\x86\\xce\\xae\\x25\\x86\\xd0\\x59\\x4f\\xb5\\x34\\xad\\x67\\xcb\\xc7\\x5e\\xef\\xbc\\xa5\\xf6\\x3e\\xd9\\xc7\\x3a\\xe4\\xc7\\xe7\\xca\\x47\\x4f\\xe9\\xbc\\xa2\\xb8\\x0c\\x6b\\xee\\xdf\\x31\\xff\\xee\\x49\\x0a\\xc8\\xb7\\x84\\x90\\xf3\\xcf\\x93\\x71\\x90\\x42\\x77\\xa3\\xef\\xdc\\x77\\xaa\\x18\\x8c\\x20\\xb3\\x34\\x2d\\x6c\\xa0\\x99\\x11\\xfc\\x41\\x10\\xc9\\xa1\\x3c\\xd4\\xba\\xe5\\xbc\\x8b\\x68\\x9c\\xeb\\xd7\\x55\\xce\\x5b\\xf8\\xfa\\xfa\\x1b\\x9c\\xe0\\x35\\x6b\\xf8\\xd4\\x39\\x2e\\x5d\\xe7\\x8c\\xbb\\xe7\\xa0\\xb4\\xfc\\x21\\x17\\xe1\\xfe\\xb1\\xd5\\x15\\xb5\\xb4\\x0b\\x5c\\x30\\x44\\x93\\x8c\\x90\\x3c\\x88\\x1e\\x5d\\x99\\x84\\x9d\\x8a\\x05\\xbd\\xe5\\xad\\xb5\\x11\\xcd\\xcc\\xbf\\x71\\x87\\xac\\xad\\x17\\x4e\\xaf\\x15\\xb8\\xf4\\x60\\x0c\\x95\\x94\\x2d\\x10\\x2b\\x1f\\xc3\\x64\\x9f\\xe6\\x10\\xc9\\xb5\\x9f\\xaa\\x00\\xb7\\x25\\x44\\xc0\\xf3\\xd0\\x6c\\x85\\xb2\\x99\\x5f\\x70\\xef\\x6d\\x3d\\xeb\\xb0\\x37\\xec\\xaf\\x54\\xc3\\x49\\x28\\x09\\x9d\\xad\\x6b\\xc7\\x28\\x13\\x75\\xbc\\x52\\xb5\\x38\\xb4\\x4f\\xa5\\xa2\\x8e\\xb2\\xdb\\xe7\\x44\\x7a\\xd9\\x7b\\xbd\\x34\\x6e\\xfb\\x73\\x15\\x51\\x07\\xd5\\x11\\x1e\\x1b\\xe2\\x1c\\x56\\xaa\\x0b\\x18\\xa0\\x0e\\x43\\xe0\\x03\\x68\\x23\\x34\\xa7\\xdf\\x2a\\x60\\x59\\x82\\x8b\\x86\\x0f\\x0f\\x5d\\x52\\x72\\x5e\\xae\\x26\\x4a\\x5f\\x6d\\xdb\\xb8\\x57\\x71\\x20\\x94\\x65\\xf9\\x83\\xb9\\x8d\\xc4\\x58\\x69\\xb5\\x15\\x2f\\xe3\\x1e\\x33\\x11\\xd8\\xf0\\xdd\\x65\\x7b\\xfd\\x0c\\xee\\xde\\x6e\\x66\\xaf\\x48\\x13\\xa9\\xd1\\x39\\xce\\xd8\\x7a\\xee\\xb5\\x74\\x00\\x99\\x0f\\x6c\\x57\\xf8\\xcf\\xde\\xeb\\x24\\x8d\\x62\\x6f\\x52\\xcf\\x81\\x0e\\x6f\\xc1\\x75\\xce\\x58\\xfc\\x07\\xa2\\x3c\\xf8\\xca\\xb1\\x3e\\x8e\\xec\\x2f\\xba\\xba\\xe0\\xe2\\xe9\\xd1\\xb2\\x66\\x13\\xdd\\xcd\\xc4\\x7b\\xb2\\x23\\x6e\\x22\\xae\\x17\\x62\\x29\\xf5\\x7f\\x94\\x92\\x0c\\xa0\\x55\\x34\\xc5\\xc2\\x0f\\x34\\xc7\\xb5\\xfd\\xf1\\xc6\\xab\\xda\\x39\\xb6\\xbd\\x7f\\x1f\\x5f\\xa7\\x0e\\x8d\\x96\\x6e\\xee\\xa5\\xfb\\x3c\\x43\\x55\\x31\\x1a\\x81\\xf8\\xab\\x0d\\x6e\\x21\\x99\\x5e\\x09\\x08\\xb6\\x89\\x57\\x53\\x50\\x0e\\xb0\\x01\\x8e\\xcc\\xb7\\x79\\xeb\\x90\\x80\\xcb\\x26\\x81\\x7f\\x5d\\x86\\x85\\xe4\\xf4\\xb4\\xa7\\x90\\x5f\\x75\\x27\\x86\\x8d\\xe8\\x13\\xdb\\x3b\\x68\\x99\\xe6\\x1c\\xd0\\x7e\\x4f\\xa2\\x07\\x70\\x5c\\x45\\x1a\\x9a\\x50\\x17\\x5d\\xbe\\x5e\\xc8\\xbe\\xe3\\x91\\xff\\x2e\\x3e\\x0e\\x2b\\x8b\\xe5\\x50\\xf7\\x02\\xf4\\xe9\\x7b\\x6b\\x28\\x0a\\x44\\x4a\\x98\\xa5\\xc0\\xe0\\xcf\\x40\\x05\\x3c\\xec\\xf1\\x36\\x00\\x8c\\xaf\\x27\\x17\\x05\\x63\\x7e\\xf7\\x8c\\xbf\\xb9\\xb1\\xa6\\x47\\x03\\xe5\\xa3\\x93\\x45\\x44\\x79\\x37\\x07\\xfa\\xc3\\xc3\\xf4\\xfb\\xc6\\x6d\\xf9\\xeb\\x83\\xee\\xd4\\x28\\x9e\\x5f\\x5a\\x71\\x38\\x95\\x0e\\x75\\x7b\\xa4\\xa9\\x07\\xf0\\xee\\x31\\xe4\\xee\\x8f\\xfd\\x01\\xbd\\xdb\\xc7\\xfe\\x63\\x65\\xd9\\x1b\\xd1\\x90\\xed\\xee\\x96\\x78\\xac\\x14\\x4b\\xd7\\x91\\xdf\\xc0\\xad\\xf6\\x94\\x17\\xad\\x0b\\x6b\\x4b\\x5d\\xe7\\x55\\x36\\xd3\\x65\\x42\\x5a\\x94\\xf4\\x97\\xfc\\xa8\\x1c\\x26\\xe1\\x5c\\x78\\x3d\\x62\\x54\\xe1\\x37\\xab\\xbe\\xe5\\x1f\\x5f\\x8b\\x61\\xac\\xd9\\xcf\\xf8\\x32\\x7f\\x41\\x9e\\x0d\\x81\\x77\\xd1\\x42\\xfc\\x65\\x81\\x14\\xa8\\xf8\\xc5\\xfb\\xd9\\x2b\\x56\\xdc\\x83\\x89\\x6a\\x28\\xd8\\xe0\\x4d\\xa8\\xab\\x13\\x5b\\x83\\x7c\\xc6\\xf3\\xb2\\xc1\\xee\\xc7\\xb4\\xc1\\x00\\x23\\xf6\\x95\\xe8\\x4c\\x26\\x49\\x8c\\xd7\\x51\\x54\\x0d\\xce\\xf0\\x04\\x68\\x86\\x12\\x6e\\xb2\\xf7\\x3a\\xc2\\xfc\\xa3\\x48\\xfa\\xa4\\x39\\x88\\x8f\\x8e\\xf7\\xba\\xf6\\x06\\xe3\\x65\\x91\\x96\\x0e\\x5e\\x8e\\x8c\\x92\\x03\\x7c\\x4f\\x81\\xdc\\x42\\xf5\\x01\\xec\\x29\\x4f\\x4c\\x13\\x81\\x2d\\x17\\xb7\\xb8\\x0d\\x45\\x38\\x5c\\x46\\x6e\\x57\\x1c\\x02\\x97\\x2a\\xa3\\xfd\\x61\\x3b\\xa3\\x6e\\xba\\x67\\xff\\x45\\xe7\\xcc\\xc8\\x02\\xbf\\x70\\xe4\\xd5\\x61\\x71\\xa4\\xfa\\x6e\\xdf\\xe4\\x3e\\x22\\x88\\x9f\\x39\\x09\\x14\\xac\\x0a\\x3b\\x2d\\x59\\x62\\x76\\xc5\\x79\\x2e\\x6f\\xfd\\xe1\\x02\\xc6\\x28\\x69\\xbe\\x18\\x4e\\x7c\\x19\\x90\\x1b\\x2a\\xa9\\x14\\x2f\\x5d\\x0a\\x02\\x32\\x29\\xbf\\xd0\\xb8\\x5f\\x60\\x2b\\x5c\\x75\\xb7\\x70\\x5e\\x52\\x7f\\xaa\\x7e\\xf0\\xdb\\x35\\x2f\\x03\\x7c\\x27\\x53\\x5c\\x54\\xa9\\x6e\\xb2\\xc5\\x6f\\x62\\x4a\\xef\\xa2\\x0c\\x20\\x7c\\x82\\x8f\\xeb\\xe6\\x74\\x82\\x5f\\xb8\\xe9\\x6b\\xee\\x7e\\x81\\x4b\\xcf\\xea\\x39\\x37\\x9a\\x4c\\x38\\x82\\xdc\\xfb\\xb5\\x49\\x07\\x4f\\x84\\xf0\\xa8\\xcf\\x16\\xab\\x6c\\x52\\x9e\\xd6\\xaf\\xf2\\x0b\\x26\\xb9\\x75\\x8f\\xf3\\x67\\xf2\\x9a\\xc5\\x77\\x96\\xcb\\x57\\xda\\x42\\x8d\\x8f\\x6f\\x2c\\x7a\\x98\\x2a\\xf2\\x83\\x90\\x64\\xc0\\x94\\xf1\\xbf\\x0e\\x3a\\xe7\\xb3\\xb6\\xce\\x92\\x6d\\x2d\\xc4\\xd7\\x82\\x36\\x9f\\x0c\\x39\\x26\\xcc\\x11\\x4c\\x97\\x75\\x1d\\xc5\\x8b\\x68\\x7e\\xb3\\x6d\\x02\\x0e\\x6a\\x19\\xb2\\x2e\\x13\\x09\\x6d\\x90\\x85\\xca\\xdd\\xa9\\x28\\x0b\\x87\\x0b\\x38\\xf4\\xd0\\x7a\\xf2\\xfc\\xff\\x09\\xff\\x44\\x3f\\x09\\xc6\\x60\\x87\\xd5\\x86\\xc9\\xdd\\x1e\\x7d\\xc5\\x6d\\x3f\\x59\\x9a\\x5d\\xf7\\xf6\\xa1\\xfc\\xde\\x51\\xb8\\xfc\\x82\\xc5\\x57\\xe6\\x37\\xe9\\x7c\\x10\\x12\\x4e\\x70\\x15\\x4f\\x90\\xe3\\x7c\\xc8\\x76\\x9b\\xfd\\x5a\\x32\\xc7\\x1e\\x9d\\xb5\\x32\\xc1\\x13\\x6c\\x5c\\xbc\\x24\\x62\\x90\\xce\\xbf\\x73\\xcf\\x0d\\xef\\x24\\x3a\\xe5\\xd8\\x60\\x4e\\x3c\\x3f\\x13\\x37\\x04\\x14\\x81\\xa0\\xda\\xaf\\xd5\\x36\\x3a\\x7f\\xf3\\x8a\\xbd\\xa0\\xda\\x54\\xca\\xbd\\xa1\\xb5\\x88\\x10\\x07\\x57\\x2f\\xb6\\x07\\x44\\xea\\xda\\xa7\\xd4\\x45\\x6b\\xb9\\xaf\\x41\\x33\\x96\\x8d\\x50\\xa9\\x9e\\xf6\\x02\\xe7\\xa8\\x75\\xd7\\xcb\\xcf\\xcd\\xd6\\x8e\\x93\\x49\\x9b\\x83\\x61\\x26\\x33\\x89\\x37\\xcc\\xc3\\x90\\x83\\x7d\\x48\\x32\\x55\\x1a\\x4e\\x51\\xa8\\x43\\x9b\\x7d\\xf5\\xa7\\xc1\\xf3\\xec\\xcd\\x04\\xe7\\xf7\\x6f\\xb5\\x5c\\x1f\\x3a\\xac\\x3d\\xe7\\x33\\x17\\x0c\\x71\\x9e\\x34\\x06\\xff\\x90\\x08\\xcd\\x67\\xf1\\x91\\xe3\\xec\\x5e\\xda\\x6f\\xe4\\x86\\x63\\xe6\\x10\\x00\\x22\\x8c\\x48\\x8c\\x51\\x26\\xc7\\x89\\x3c\\xf4\\xde\\xa9\\xad\\x01\\x84\\x03\\x9b\\x2b\\x1a\\xa6\\xd6\\x56\\xe9\\x56\\xb4\\x62\\x37\\x70\\x89\\x79\\x8f\\x71\\x7b\\x1d\\x43\\x37\\x75\\xec\\x87\\x0e\\x37\\xab\\x90\\xac\\x55\\xf3\\x9d\\x12\\x47\\x18\\x97\\xb1\\xa2\\x4b\\x33\\xae\\xe3\\x7d\\xc8\\x1a\\xd2\\x59\\x2e\\x44\\xff\\xb2\\x73\\x8e\\x90\\x81\\xdb\\x4a\\xfd\\x1a\\x37\\x35\\x87\\x15\\x34\\xa7\\xbc\\x3d\\xa8\\xf3\\xa9\\x5d\\x61\\x68\\x1c\\xc9\\x07\\xf9\\x62\\x65\\x7f\\xd0\\xbd\\x94\\xf0\\x58\\x88\\xce\\xf4\\x22\\x56\\xe8\\x2b\\x57\\x04\\xeb\\x70\\x50\\x52\\x9f\\x9c\\x3b\\x8b\\x57\\xc4\\x01\\x00\\x48\\xac\\xfe\\x64\\xe8\\xd9\\xeb\\x3e\\x7f\\xaf\\x2a\\x3b\\x2f\\x81\\x54\\x24\\x96\\xbc\\x60\\x4a\\x8c\\x2c\\xca\\xc6\\x8e\\x79\\x19\\x31\\x83\\x34\\x57\\xbb\\x2b\\xc2\\x25\\x33\\x8f\\x02\\xfe\\xf7\\x44\\xce\\xa6\\x17\\x76\\xfb\\x03\\xf6\\x33\\x17\\xc6\\xb1\\x05\\x9c\\x90\\xee\\x58\\x05\\xf8\\xf1\\x6a\\x63\\xa4\\xcf\\x5c\\xba\\x3d\\x13\\x9a\\x2e\\x69\\x87\\xce\\x79\\x57\\x6d\\xd5\\x3e\\xb0\\x9a\\xf1\\xb3\\x95\\xc4\\xc3\\x08\\x7e\\x7a\\xfc\\xc9\\xcd\\xb7\\x6e\\x29\\x40\\x8b\\xc0\\xb6\\x48\\x8a\\xdb\\x99\\x1f\\x3c\\xe5\\x0a\\x4b\\xae\\x30\\x0c\\x03\\x92\\xe0\\xfd\\xd9\\x4a\\xc8\\xaf\\xfd\\x42\\xd8\\x07\\x30\\xef\\x5b\\xb4\\x34\\xd9\\xe3\\x38\\xea\\xba\\x19\\xf1\\x0b\\x23\\x06\\x5f\\x52\\x23\\x7b\\x3d\\x05\\x86\\xd4\\x84\\xd9\\x0d\\x45\\xac\\xc1\\x37\\x62\\xf4\\x33\\x05\\xc9\\xda\\x0b\\xa6\\x17\\x9f\\xdd\\xcf\\x3e\\x90\\xd9\\xf8\\xd4\\xd8\\x7f\\x19\\x92\\x6a\\x49\\xe7\\x63\\x19\\x7f\\xac\\xfc\\x09\\x47\\x45\\x31\\x63\\xac\\xa7\\x33\\x0a\\x52\\x47\\x11\\xb4\\x5b\\x28\\x1c\\x3d\\xe4\\x1c\\xdb\\xf5\\x20\\x27\\x6b\\x44\\x29\\xe8\\xe6\\x00\\x73\\xa6\\x2f\\x6f\\x4a\\x84\\xe1\\xce\\x21\\x02\\xd2\\x28\\xbd\\x73\\x01\\x30\\x78\\x09\\x9b\\xad\\xbb\\x56\\x63\\x4e\\xc2\\xa8\\x2a\\x5e\\x26\\x73\\x9d\\x3b\\x06\\xac\\x58\\xd3\\x62\\xdf\\x61\\x36\\x3a\\x39\\x87\\xd2\\xb4\\x0d\\xa5\\x0d\\xbf\\x3b\\x72\\x27\\xaa\\xad\\xfe\\x40\\x78\\x45\\x98\\x2e\\x26\\xee\\xe3\\x3d\\xc0\\x55\\xfc\\x8b\\x4a\\xe7\\xe2\\x7b\\xc5\\xeb\\x54\\xda\\x4e\\xfa\\xb1\\x2a\\xa3\\xf3\\xdd\\x20\\x37\\x28\\x14\\xa0\\xb6\\x94\\x44\\x38\\x03\\xf4\\x5c\\xdd\\x7f\\xf5\\x9c\\x8c\\x49\\xb2\\xb1\\x10\\x13\\x04\\x01\\xf4\\xc1\\xfa\\x67\\x62\\x03\\xb0\\x2e\\x35\\xe7\\x9b\\x67\\x99\\xe4\\xab\\xbe\\x11\\xf9\\xa6\\xee\\x09\\x03\\x98\\x45\\x8a\\xba\\x85\\x51\\x71\\x15\\x4c\\x77\\x6c\\x78\\xf2\\x43\\x4c\\xff\\xe0\\x09\\x1f\\x87\\xab\\x85\\xc8\\x4a\\x2c\\xe4\\x49\\x2d\\x56\\xd0\\x70\\x29\\xf0\\x8f\\x03\\xaa\\x1f\\xf0\\x4b\\xfc\\x1d\\xbd\\x17\\x5b\\x40\\xd1\\x4f\\x31\\xf7\\x94\\x08\\x6f\\xff\\x8d\\xf8\\xa0\\xfc\\xf8\\xbe\\xba\\xf6\\xe5\\x4b\\x16\\x7c\\x98\\x56\\x2e\\xdc\\xd2\\x25\\x41\\xab\\xd2\\xcb\\x98\\x9e\\xad\\x2e\\x08\\x1c\\xb8\\x5c\\xf2\\xb1\\xa1\\xc7\\x67\\xf1\\x62\\x22\\x64\\xee\\x0f\\x91\\xef\\xbe\\xe5\\x69\\x37\\x19\\x09\\x6a\\xfd\\x9a\\x91\\xc0\\x66\\x6e\\x1c\\x56\\x47\\xdf\\xa0\\x38\\x45\\x1e\\x46\\x4c\\x1e\\x36\\xe4\\x59\\xeb\\x88\\xdd\\xd6\\x7b\\x2e\\x6e\\xc1\\xfb\\xae\\x3a\\x36\\x8f\\xb5\\x14\\x76\\x68\\x57\\x70\\x18\\x5f\\xb0\\x99\\x30\\xc2\\x85\\x2f\\xfe\\x2c\\x74\\x3e\\xb3\\xed\\x47\\x15\\xf9\\x58\\xab\\x5b\\xeb\\xc9\\x00\\xce\\x70\\xea\\xc0\\x5a\\x9d\\xc8\\x1c\\xe4\\xf6\\xd3\\x65\\x1a\\x41\\x03\\x3c\\x14\\x3b\\x82\\x4e\\xf6\\x51\\xb7\\x98\\x62\\xcb\\x1d\\xc2\\x72\\xa5\\xcf\\xb7\\xd8\\x6c\\xb8\\x47\\x98\\xb9\\x8d\\xfc\\x97\\x57\\x60\\x13\\x72\\x92\\xad\\x66\\xa9\\x3b\\x32\\x76\\x2c\\xf4\\x2b\\x44\\xec\\xc0\\x46\\xcd\\x81\\x13\\xa2\\xf2\\x35\\x31\\x82\\x7b\\xa9\\x52\\xa0\\x2a\\xf9\\xe9\\x93\\x05\\x4b\\x79\\x32\\xeb\\xf1\\x99\\x81\\xd8\\x8a\\x42\\x6d\\x0c\\xac\\xec\\x49\\x5c\\x8e\\x92\\xf7\\x9b\\x34\\x11\\x1a\\x70\\x1e\\x79\\x24\\xa5\\x76\\x89\\x87\\xb9\\xab\\x29\\x49\\xb0\\x40\\xd5\\x70\\xc0\\xb1\\x91\\xc2\\x0b\\xfb\\x56\\x0a\\xd9\\x3f\\xa6\\xc2\\xcc\\x66\\x35\\xfe\\x2f\\x26\\x51\\x50\\x5d\\xe3\\x0d\\x98\\x9d\\x14\\x20\\xdb\\x4c\\x3f\\x78\\x38\\xc7\\x2a\\x29\\xad\\xe4\\xf7\\x7a\\x18\\xc0\\xcb\\xb9\\xb3\\x57\\x8c\\x16\\x9b\\x04\\xce\\xa7\\x94\\xe1\\x71\\xb4\\xe7\\xe3\\x8f\\x11\\xef\\xa5\\xbe\\xdf\\xe6\\x73\\xff\\x7b\\x78\\x24\\x89\\xb2\\x37\\x30\\x3e\\x8c\\x7d\\x53\\x31\\x17\\xf6\\x6d\\x09\\x3a\\xd4\\x7e\\xed\\xc0\\x03\\xd9\\x1e\\x93\\x5a\\x4e\\xd1\\xcb\\x8a\\xc4\\x09\\x22\\x55\\x9d\\x8a\\x32\\xff\\x96\\x01\\xf3\\x83\\x42\\x25\\x85\\xf1\\xd0\\x63\\x32\\xb9\\xc3\\x22\\x88\\x07\\x1d\\x0e\\xb4\\x47\\xde\\x91\\xf9\\x64\\x7c\\x32\\xc9\\x2b\\x92\\xf4\\x12\\x6a\\x1b\\x22\\x6c\\xab\\xdc\\xc3\\x06\\x4b\\xab\\xc4\\x20\\x86\\x6f\\xc1\\x91\\x06\\x52\\x6c\\xa5\\x50\\x5b\\x84\\x14\\x53\\x56\\x9d\\xab\\xbb\\xa2\\x10\\xf1\\x03\\x1e\\x82\\x7e\\x58\\xf5\\x85\\x10\\x85\\x47\\x63\\x35\\x23\\x3a\\x47\\xd2\\x72\\x62\\x48\\x01\\xf4\\x84\\xf7\\x1e\\xc5\\x2f\\xfe\\x33\\x1a\\x17\\x4c\\x6d\\x1f\\xd2\\xf7\\xb3\\x2b\\x49\\x0a\\x98\\x22\\xe5\\xa0\\xde\\x3f\\xb3\\xa2\\x91\\x0a\\x87\\xcd\\x7f\\x21\\x54\\x1b\\x67\\xe6\\x36\\x3d\\xfc\\xb6\\xa6\\x2d\\xf0\\xd2\\x9f\\x02\\xff\\x26\\x10\\x39\\xa3\\x2d\\x80\\x33\\x4c\\x22\\x51\\x84\\xef\\x41\\xaa\\xea\\x75\\x63\\x4d\\xe7\\xfb\\x89\\xf3\\xee\\x11\\x06\\x63\\xd2\\x9a\\x41\\x50\\x24\\xc0\\x62\\x98\\x90\\xfd\\x16\\x6b\\x94\\xf1\\xa2\\x39\\xd8\\x37\\xde\\x2b\\x5f\\xfc\\xfa\\xb0\\x2e\\x2b\\x77\\x09\\x9f\\xdb\\x7a\\xf4\\xc6\\xd7\\x03\\xa6\\xbd\\xeb\\x91\\xee\\xee\\xd1\\x2e\\x0f\\x7a\\xdf\\x96\\x2f\\x79\\x17\\x67\\xfe\\xb4\\xc8\\x82\\xb2\\xfe\\x13\\xaa\\x50\\x73\\x3c\\xdc\\x59\\x87\\xf8\\x00\\xb2\\xb9\\x14\\x26\\xe7\\x25\\xcd\\x4e\\x63\\xe0\\x6f\\xbd\\x8d\\x85\\xc6\\xd9\\x36\\x79\\xb8\\xa7\\xa3\\x5b\\x1b\\xc7\\x0f\\x43\\xe7\\x36\\x83\\x3b\\xf8\\xab\\xcf\\xf0\\x5b\\xb0\\x17\\xe5\\x31\\x24\\x49\\x0e\\x0c\\xf3\\x12\\x55\\x58\\xc6\\x31\\x79\\x1c\\x7a\\x5b\\xc0\\x9c\\x6c\\x33\\xfb\\x45\\x77\\x90\\xb4\\x6f\\x24\\x91\\x5c\\xbc\\xf3\\x50\\x9a\\x3c\\x67\\xa4\\x35\\xa3\\x85\\x07\\xab\\xff\\xb1\\x95\\x8a\\x20\\x5a\\x32\\x23\\xaf\\xe5\\x5a\\x92\\x3c\\x1d\\x81\\xc4\\x4a\\xba\\x28\\x8c\\xf6\\x43\\xa0\\x05\\x65\\x4b\\xe1\\xc3\\xdf\\xbe\\xf5\\xed\\x99\\xdf\\xfe\\x4b\\xee\\xba\\xb7\\x1b\\x56\\x92\\xf4\\x77\\x00\\x71\\x5e\\xe1\\xad\\xff\\xb8\\x0b\\x10\\x48\\x46\\xa2\\x79\\xc6\\x31\\x10\\xdd\\x3b\\x18\\xc4\\xf8\\xcd\\x91\\xb9\\xa2\\x83\\x8b\\x81\\x66\\xd1\\x3e\\x03\\xbc\\x5f\\xb4\\x78\\x47\\x64\\x97\\x22\\xa3\\x4d\\x1b\\xfe\\x6e\\xfb\\x06\\x10\\xaf\\x35\\x70\\xc5\\xa9\\x33\\x74\\xa3\\xc0\\x04\\x2a\\xd0\\xe4\\x64\\xd7\\xad\\x4c\\xd9\\x1a\\x05\\xca\\x8d\\x3f\\x80\\x53\\xef\\x8c\\xd1\\xb9\\x28\\x8e\\x34\\xaa\\x9f\\x29\\x23\\x7f\\x4d\\x2c\\xe5\\x62\\x83\\xef\\x52\\xbf\\x08\\xa6\\x70\\x76\\x52\\xe9\\x25\\xb8\\x37\\x76\\x99\\xa2\\xd7\\xe6\\x17\\xc0\\x98\\x42\\x33\\xd5\\x35\\x6c\\x05\\x64\\xb9\\x45\\xb3\\x1a\\x29\\x3e\\x17\\xb6\\xbd\\x10\\x8f\\x6e\\x3c\\x0e\\x50\\x75\\xc0\\x9b\\x81\\x1a\\x0c\\x98\\x2d\\x22\\x64\\xbe\\xfc\\x64\\xac\\x3a\\xfb\\x53\\x3c\\xbd\\xba\\xb1\\xef\\xa8\\x77\\xb0\\x0a\\x50\\xf8\\xa5\\xfc\\xc2\\x39\\xac\\x74\\x5d\\x68\\x57\\x33\\x81\\xab\\xfa\\xf1\\x08\\xe8\\x90\\x2b\\xd5\\xc5\\xa7\\x75\\x71\\xbf\\xca\\x19\\xfc\\x78\\x22\\x6c\\xbf\\x0c\\xcb\\x7f\\xd8\\x71\\x04\\xd4\\x1d\\xfa\\x42\\xab\\x5d\\xf4\\x82\\xc3\\x5c\\xf9\\x9e\\x41\\x8c\\xa1\\xc5\\x8b\\x27\\xd2\\x29\\x7c\\x06\\xdb\\xb0\\xdc\\x98\\xc8\\xf0\\x71\\xf2\\x82\\x9a\\x6e\\x05\\x20\\x1f\\x57\\xcc\\x87\\x4c\\xd4\\x27\\xd3\\xfd\\x39\\x71\\x46\\xc8\\x62\\xae\\xda\\xb6\\x3d\\x21\\xe6\\x4c\\x82\\xde\\x22\\x6d\\x77\\xe6\\x44\\xfa\\x0e\\x56\\x11\\xec\\x61\\x7d\\x35\\x0a\\xcd\\x5e\\x41\\x22\\x04\\x03\\xea\\x13\\xdb\\x31\\xa4\\x21\\x40\\xe4\\x47\\xdb\\xaa\\x1b\\xe2\\x77\\xdd\\xc9\\x30\\x90\\x63\\x64\\xc9\\x0c\\x7a\\x70\\xf8\\x36\\x9b\\x38\\xb8\\x9e\\x90\\x12\\x6a\\x1d\\x4e\\x13\\x24\\x92\\x01\\xcc\\x19\\xd1\\x8c\\xe0\\xfb\\x8d\\x2f\\x92\\xb3\\x99\\xdd\\x2b\\x7a\\x36\\x22\\x35\\x35\\xe3\\x06\\x0a\\x64\\x3d\\xdf\\x7b\\xa3\\x35\\x35\\x24\\x15\\x15\\xf9\\xef\\x0b\\xf7\\x63\\xd5\\x83\\xc8\\x25\\x3d\\x8a\\xff\\xf3\\xd8\\x18\\x7b\\xac\\x91\\xc1\\x27\\x23\\x09\\xbb\\x22\\x9a\\x3d\\x18\\xfc\\x12\\x0a\\x29\\xa5\\xb9\\x13\\x51\\xa4\\x9d\\xdf\\x41\\xb3\\x26\\x24\\x07\\x8d\\x64\\x37\\xf3\\xd9\\x99\\x2e\\x29\\xf8\\x10\\x9a\\x4b\\xbb\\x0f\\x3a\\x78\\x98\\x06\\xe2\\xf6\\x50\\x56\\xf0\\xa6\\xf9\\x23\\x89\\x78\\x50\\x7a\\x4d\\xa6\\x08\\x0f\\x19\\x17\\x21\\x4c\\x4d\\xcf\\xf7\\x2f\\x12\\x7d\\x3e\\xad\\xe3\\xf6\\xb6\\x1a\\x6e\\x32\\xbf\\xba\\x08\\x97\\x4e\\xba\\x10\\xa1\\xdf\\xf0\\x67\\x63\\x01\\x32\\x3f\\xb8\\x6f\\x8d\\xb9\\xf2\\x15\\xcb\\x21\\x32\\xae\\xb7\\x79\\x3a\\xbc\\x30\\x97\\xe7\\x80\\xb7\\xb8\\x8b\\x87\\x85\\x53\\x6b\\x29\\x09\\xb4\\xe5\\x5e\\xc6\\xc8\\xe0\\x2c\\x27\\x91\\x90\\xe2\\xa4\\xca\\x98\\x10\\x9e\\xc1\\x25\\xff\\xbd\\x2b\\xcd\\xa8\\x2d\\x10\\x27\\x17\\x81\\x0d\\x13\\x10\\x91\\x11\\xd2\\x6e\\x67\\xeb\\x62\\x10\\x44\\x41\\x48\\xb6\\xfd\\x89\\x1b\\x17\\x8b\\xff\\x27\\x3d\\x50\\xf4\\x43\\x23\\x08\\xcb\\x5c\\x33\\x53\\xd4\\xa7\\xf8\\x1a\\xd2\\xad\\x0e\\x8d\\xc2\\xff\\x81\\x15\\x49\\x84\\x43\\x8b\\x2b\\xfc\\x25\\x9c\\xa7\\x18\\x3c\\x54\\x5e\\xb5\\xd2\\xaf\\x94\\x47\\x7e\\x54\\xd0\\x80\\x17\\x93\\xb6\\x38\\xe4\\x14\\x66\\x9d\\x29\\xb5\\x87\\xe5\\x5b\\x4f\\x63\\xe0\\x4e\\xf6\\x90\\xb9\\xad\\xa7\\x92\\x27\\x27\\x72\\xcf\\xee\\x8a\\x7b\\xf4\\x9a\\xaf\\x56\\x64\\x1b\\x5c\\x79\\xad\\x24\\xe4\\x65\\xf1\\x3e\\x64\\x87\\xed\\x09\\x16\\x73\\xdd\\xa4\\xb0\\x61\\x40\\xfe\\x92\\xbf\\x55\\x24\\x88\\x15\\xc5\\x0d\\x14\\xdd\\x58\\x07\\xed\\x41\\xe5\\x54\\x64\\xc3\\xd5\\x8b\\x35\\xa6\\xbf\\x22\\x9f\\x7a\\x36\\x85\\xf9\\xbd\\x64\\x5a\\xef\\x30\\xff\\xb4\\x19\\x9a\\x37\\x66\\xe3\\x8e\\xa7\\x2a\\x2b\\x52\\x4c\\x7c\\x9c\\x01\\x52\\xa1\\x66\\x8f\\xd6\\x4b\\x97\\x30\\xa2\\x2b\\xe8\\xd9\\x3a\\x6e\\x57\\x69\\x49\\xbf\\x3f\\x92\\x15\\x64\\x5a\\x0f\\x3c\\x7a\\x24\\x63\\xe6\\xb8\\xda\\xff\\xc4\\x28\\xc4\\x93\\x1c\\xb5\\x9d\\xa3\\xef\\xc6\\x43\\x68\\x48\\x5d\\x3f\\x91\\x12\\x4c\\x96\\xea\\xd0\\x37\\x04\\x2e\\x10\\x04\\x8b\\xdf\\x39\\x34\\x69\\xcc\\x96\\x1e\\xe2\\xef\\x2a\\xe9\\xff\\xf5\\xac\\x93\\x2c\\x4a\\xef\\x89\\x0c\\x24\\x8f\\x87\\x9a\\x3e\\xe8\\x8f\\x78\\x5e\\x5d\\x60\\xe6\\x4f\\xf8\\x2d\\xb7\\x72\\xec\\x04\\x16\\xaa\\x54\\x63\\xf5\\xdf\\x33\\x01\\xa8\\xa4\\xf3\\x78\\xa1\\xbb\\x20\\x74\\xa3\\xe8\\xac\\x82\\x25\\xce\\x60\\x87\\xa8\\xd7\\x52\\x08\\x21\\xf7\\x16\\x0b\\x94\\xe5\\xc7\\xee\\xf6\\xc1\\x64\\x2e\\xa4\\x42\\xc6\\x28\\x38\\x02\\x05\\x95\\xc2\\xa7\\x23\\xfd\\x49\\x86\\x5a\\x0e\\xbb\\x08\\xba\\xc5\\x33\\xfe\\x93\\x74\\xa1\\x1b\\xa5\\x3c\\x30\\x7a\\xe7\\x07\\xfb\\x0d\\x0e\\x1b\\x88\\x01\\x3a\\x68\\xef\\x50\\x7c\\xce\\xfe\\x6f\\xec\\xa3\\x44\\x0f\\x84\\x52\\xe0\\x25\\xbd\\x7e\\xd5\\x3b\\xf2\\x71\\x33\\xd7\\x0a\\xb8\\xe2\\x1e\\x80\\xee\\xba\\x3a\\x78\\xf3\\xf7\\x1c\\xcb\\xcb\\xb1\\xa1\\x3b\\x83\\xc0\\xb5\\xff\\x78\\x36\\x0e\\xf4\\x1f\\x0c\\xa4\\xe9\\xcd\\x18\\xd9\\x4c\\xfc\\x51\\x9f\\x85\\xc1\\xf5\\x0e\\x69\\x59\\x8d\\xcd\\x5a\\xc1\\xf7\\x4c\\x41\\xa2\\xd0\\xf8\\xf6\\xdb\\x06\\x08\\x87\\x6f\\x4a\\x01\\xb9\\xe8\\x73\\xa3\\x51\\xb3\\x91\\xdb\\x11\\xa5\\x78\\xef\\x90\\x2a\\x6b\\xce\\x0b\\xdd\\x73\\xd1\\xed\\xba\\xbf\\x16\\x41\\x6a\\x94\\x71\\xf0\\x0e\\xc4\\x4c\\xdd\\x23\\xa2\\x09\\x29\\x8f\\x72\\x2b\\x59\\xfc\\xe7\\xd9\\xa4\\x90\\x98\\xee\\xa9\\x68\\xbd\\x56\\x66\\xcd\\xd2\\x26\\x49\\xec\\xf0\\xcb\\x59\\xc2\\xca\\x80\\x97\\xd5\\x24\\xd9\\xc2\\x15\\x55\\xd5\\x96\\x14\\x0c\\x5c\\x73\\xef\\xbf\\x56\\xa2\\x1b\\x65\\x70\\xa2\\xad\\xab\\x44\\xf4\\x15\\x0b\\x0c\\x66\\x15\\x35\\x8b\\xe6\\x25\\x08\\xa3\\x14\\xc8\\xf4\\x92\\xc0\\x1f\\xc5\\x5c\\x04\\x69\\xd7\\x45\\x1b\\xec\\xfb\\xcd\\x4f\\x79\\x81\\x2c\\x99\\x9e\\xe6\\xde\\x7b\\x1e\\x89\\x9a\\x16\\x7e\\x3e\\x01\\xd4\\xe4\\x9c\\xa5\\xc3\\xd9\\x5d\\x39\\xcc\\x04\\xc6\\x8e\\x7e\\x1f\\x6d\\xe6\\xc5\\xa1\\xfd\\x17\\x12\\xd2\\x4c\\x67\\xb0\\xf2\\xb5\\xe8\\x97\\x67\\x4d\\x13\\xb9\\xbc\\x12\\xd7\\xa5\\xb8\\x32\\xd0\\xb2\\xfb\\xaa\\xd2\\xec\\x96\\x24\\x11\\x80\\xc7\\xf8\\x13\\x17\\x9a\\x76\\x40\\xce\\x6a\\xef\\x4f\\x9d\\xc0\\x96\\x9d\\x6d\\x42\\x76\\x71\\xa5\\x50\\x83\\x7a\\xf1\\x8b\\x9c\\x23\\x41\\xc8\\xae\\x5b\\x41\\x7d\\xc5\\xb8\\xd4\\xc2\\x93\\xbf\\xa2\\x19\\xab\\xe2\\x75\\xd3\\x9f\\x4d\\x7b\\x75\\x04\\x4d\\xbd\\x5a\\xe0\\x95\\xa5\\x5d\\xac\\x51\\xdc\\x10\\x13\\x15\\x80\\x13\\x0a\\x03\\x53\\x0c\\xb6\\xd7\\xea\\xfc\\x0a\\xf2\\x21\\x66\\x3f\\xfb\\xcf\\x55\\x8b\\x27\\x56\\x12\\xf4\\xe9\\x60\\x29\\xbe\\xb9\\x05\\x1b\\x67\\x60\\x43\\xc9\\x68\\x9c\\x47\\x0e\\xcd\\x78\\x06\\xb5\\xe1\\xc8\\x59\\xd2\\xdb\\x78\\x47\\xa0\\x35\\x77\\x7e\\x16\\xcb\\x20\\x18\\x20\\x5a\\xc2\\x74\\x8a\\x6d\\x39\\xc6\\x6c\\x3c\\xfc\\x93\\xc7\\xea\\x4c\\x62\\x7c\\x38\\x5b\\xfe\\xf1\\xb1\\xb0\\x61\\xb2\\xe4\\x0f\\x8d\\x73\\xf5\\x57\\xf3\\x93\\x0f\\xf9\\xcb\\xfe\\x62\\x3f\\xb2\\xfa\\x58\\x4a\\x3b\\x15\\xb6\\xad\\xab\\x39\\xbc\\x33\\xf1\\x87\\x5a\\x39\\x32\\x98\\xd0\\x7f\\xfb\\x6a\\x53\\xaa\\xc3\\xef\\x6a\\xb3\\x1c\\xac\\xc4\\x1f\\x09\\xc2\\x0e\\x3a\\xf1\\x98\\xbe\\xa1\\x37\\xd9\\xc7\\x64\\xe6\\xe0\\xc6\\xb9\\x18\\x7a\\x47\\xa6\\x06\\x8d\\x0e\\x3a\\xe9\\xe5\\xbe\\x11\\x0d\\x5d\\xac\\x72\\x05\\xfc\\x75\\xd2\\x6d\\x08\\xc0\\xca\\xe1\\xfd\\xab\\xcc\\x68\\xcf\\x1f\\x5d\\x54\\x70\\xd4\\x23\\x21\\x1e\\xf7\\xce\\x33\\x7c\\xf3\\x51\\x26\\x2e\\x63\\x52\\x4a\\xee\\xe2\\xf4\\x09\\x21\\xc5\\x4a\\xba\\x86\\x5b\\x53\\x7c\\xc8\\xaa\\xe5\\x51\\x35\\x1b\\xb0\\xf6\\x67\\xac\\x76\\x1b\\xcb\\x2f\\xa8\\xcb\\x52\\x5b\\xf8\\xe2\\xac\\x45\\x60\\x93\\x10\\x08\\x41\\x6f\\xb2\\xe9\\x5b\\xfd\\xc2\\x0a\\x2e\\x5f\\xa8\\x8d\\x05\\x01\\xb0\\xdd\\x25\\x76\\x3c\\x61\\xef\\x3f\\x97\\xb0\\xb7\\x4c\\x0f\\x1f\\xe6\\x54\\xec\\x1f\\x54\\xc3\\x64\\xde\\x8b\\x16\\xfd\\x1c\\x6d\\x91\\xab\\x6c\\x5f\\x53\\x0c\\x2b\\x82\\xeb\\xf9\\x0b\\x5c\\x9d\\xa2\\xf2\\x3f\\x2c\\x7a\\x3d\\xcf\\x42\\x67\\xb6\\x9b\\x1e\\x1c\\x1c\\x18\\xf4\\xd9\\xb8\\xaa\\xf9\\x85\\x0c\\x83\\x8e\\x51\\x82\\x4a\\x4f\\x24\\x2c\\xc8\\x25\\x64\\x94\\x19\\x54\\x23\\xac\\x46\\xaf\\x80\\xc0\\xd5\\xa1\\xd1\\xc8\\xa2\\x36\\x90\\x50\\xfb\\xd4\\xfd\\x9f\\xb9\\x14\\x01\\x51\\x15\\xf5\\x76\\x15\\x2f\\x9e\\x88\\x45\\xd1\\xcb\\xcd\\x56\\x61\\x27\\x2f\\xd7\\x80\\x95\\xb8\\x57\\xd3\\xc4\\x78\\x42\\x8c\\xb5\\xc8\\xfb\\xff\\x46\\x29\\x29\\x49\\x74\\x29\\x1f\\x02\\xe7\\x9a\\xdd\\x6e\\x97\\x5c\\x62\\x1f\\xef\\xbf\\xac\\x7f\\x33\\x9f\\x52\\x86\\xaf\\x91\\x5f\\x4b\\x69\\x1b\\xc2\\x66\\x9b\\x7c\\xfb\\x5d\\x1a\\xd8\\x64\\xb4\\xd1\\xb5\\x59\\x84\\x16\\xe3\\x02\\x9d\\xb2\\xfc\\x78\\xa0\\xfe\\xf1\\xf5\\x78\\x5d\\xa5\\xed\\x65\\xe1\\x4f\\x64\\x95\\x89\\xbf\\x53\\xbf\\xa4\\x58\\xf5\\x60\\x9a\\x37\\x48\\x97\\x63\\x05\\x93\\x5f\\x59\\x68\\xda\\x22\\xf2\\x48\\x03\\xa8\\xd1\\x70\\x29\\xfa\\x78\\x39\\xa1\\x00\\x27\\x3c\\x46\\xb3\\xc7\\xfc\\x4c\\x5e\\xcc\\x18\\xc9\\x45\\xd1\\x48\\x87\\x13\\xc5\\x99\\x16\\xa4\\x00\\x67\\xeb\\xd7\\x40\\x6a\\x72\\x5c\\x89\\xb4\\xc0\\x9a\\xf5\\xc3\\x55\\x05\\x03\\xd4\\x86\\x76\\xa0\\xfb\\x4c\\x81\\x4e\\x19\\x23\\xbd\\x86\\x58\\x64\\x48\\x13\\x2c\\xa7\\x3b\\xfe\\x90\\x5e\\x5e\\xac\\xeb\\x19\\x06\\xbe\\x18\\x69\\x59\\xbe\\x80\\x00\\x00\\xb7\\x1b\\x51\\x71\\x18\\x71\\x97\\x9a\\x46\\x6e\\x1f\\x7f\\x0f\\xf7\\x70\\x44\\x2d\\x82\\x87\\x34\\xe0\\x13\\xb9\\xd3\\xa1\\x32\\x25\\x61\\x96\\xb6\\xe3\\x34\\xb9\\xae\\xe7\\x4b\\x94\\x50\\x76\\xc9\\x3c\\x35\\x31\\xac\\xf4\\xa8\\x64\\xa6\\x70\\x37\\x52\\xe7\\x2a\\x88\\xf3\\xf6\\xb5\\xa6\\xeb\\x2c\\x1d\\xc2\\x49\\xd3\\x4d\\x9e\\x56\\xbf\\x6f\\xa6\\x40\\xf6\\x01\\x0f\\xde\\x94\\x40\\xe2\\x02\\x56\\xd3\\xba\\xa0\\xe3\\x8a\\xe0\\x9c\\xe2\\xbf\\xb8\\xab\\xcc\\x64\\xf9\\xbc\\x09\\xba\\x97\\x6d\\xd2\\x69\\x8e\\x2c\\xe2\\x20\\xae\\xbd\\x72\\x01\\xcc\\x06\\x94\\x86\\xed\\x6f\\x34\\x9c\\x5f\\x2b\\x74\\xf3\\xb6\\x8c\\x81\\x14\\xb3\\x28\\xbf\\xf4\\xd3\\xb9\\x49\\xf6\\xdf\\x59\\x21\\x9f\\xa0\\x0c\\xb5\\xc9\\xe1\\x57\\x91\\x40\\x25\\x40\\x4b\\x32\\xe8\\xf3\\x36\\xd6\\x9a\\x8e\\x13\\x7d\\x10\\x2f\\x5b\\x1f\\x44\\x1e\\xe9\\xd3\\x77\\x0d\\xaf\\x73\\x18\\x1b\\xf0\\x4e\\x6e\\x37\\x4b\\xbd\\x5a\\x17\\x12\\xf5\\x9d\\x71\\x31\\x82\\x4d\\x42\\x09\\x7b\\xe9\\xa5\\xf5\\x5a\\xbe\\xf7\\x39\\x53\\x8e\\x5d\\xdc\\x9f\\x58\\xaf\\x92\\xa5\\x76\\xee\\xf2\\xc8\\x50\\x88\\xf5\\xf6\\x20\\xa4\\xae\\x52\\x9d\\xfa\\x31\\x18\\x3e\\x49\\x02\\xec\\x1e\\x45\\x53\\x67\\xc9\\x0f\\xae\\x8f\\x16\\x9b\\x6b\\x8d\\x76\\x5b\\x08\\x52\\xed\\x9f\\x27\\xc0\\xdd\\xd2\\x2f\\x0c\\x6b\\xe7\\x1b\\x33\\x47\\x75\\xa3\\x1b\\x8e\\x7d\\x1b\\x93\\xd1\\x8f\\x02\\xac\\xd5\\x82\\x38\\xfe\\xd2\\xec\\x99\\xf8\\xf4\\xc6\\x4d\\x7d\\xd3\\xa6\\x29\\x68\\xd3\\xe2\\x9f\\xbb\\xfc\\xbf\\x89\\xef\\x5d\\x11\\xac\\x9e\\x04\\xd3\\xbe\\x17\\x76\\xcc\\x9f\\x0b\\x13\\x0d\\xf3\\xdb\\x2e\\xa6\\x26\\x1e\\x69\\x43\\x08\\x5a\\x3a\\xc9\\x8f\\x6a\\x38\\x44\\xe7\\x49\\x18\\xd7\\xd8\\x9b\\x34\\x6f\\xe4\\xc4\\xd9\\x5f\\x2c\\xc6\\x2b\\xb9\\xc1\\x8d\\x71\\xd0\\x17\\x93\\x84\\x22\\x1e\\xc1\\x04\\x1a\\xbf\\x79\\x0b\\xfa\\xaa\\x12\\x73\\xeb\\x0a\\xb1\\xb7\\x9e\\xdf\\xbc\\xcf\\xd2\\x3a\\x44\\xcb\\x5b\\x4a\\x5f\\x52\\x67\\x0f\\x09\\x61\\xe3\\x6a\\xe7\\xd1\\xb9\\xa2\\x6a\\xa6\\xfc\\xa0\\x6e\\xfd\\x5d\\x31\\x9b\\x23\\x49\\x14\\x17\\x1a\\xfe\\x6e\\xa7\\x4a\\xd1\\x09\\x42\\xc7\\x74\\x2e\\xfd\\x8e\\xa5\\x66\\x61\\x2e\\x72\\x43\\xb8\\xa6\\x24\\x15\\xec\\x7c\\x5d\\x88\\xcd\\x51\\xfd\\xf7\\xf7\\xc5\\x11\\xd7\\xbe\\x02\\x48\\x92\\x44\\xcc\\xe7\\xf7\\x86\\x39\\x3b\\x1b\\x02\\xb3\\xfe\\xfd\\x17\\x6c\\x7c\\x53\\xf4\\x0f\\xb4\\xb5\\x1d\\xd8\\x1c\\x05\\xea\\xb5\\x7d\\xb5\\x2e\\xc0\\xc0\\x21\\xab\\x59\\x42\\x2e\\x99\\x16\\xba\\x0c\\xe8\\x18\\x76\\x86\\x79\\x68\\xc0\\xff\\x0d\\x45\\xca\\x22\\xbe\\x10\\x21\\x6d\\xdc\\x51\\x90\\x0e\\x7e\\x34\\x16\\x2e\\xdd\\xe8\\x13\\xc9\\x5f\\xf6\\x9e\\x13\\x69\\x4c\\x7c\\xd3\\x85\\x95\\x59\\x99\\x8e\\x26\\x26\\x12\\x04\\x48\\x12\\x05\\x3b\\x8a\\x86\\xab\\x07\\x0a\\xed\\x3c\\xd2\\x5e\\x27\\x58\\x50\\x6a\\x0e\\x54\\x73\\x01\\xc7\\xfe\\x1b\\x9b\\x89\\xc7\\xd1\\x73\\x6c\\x0b\\x72\\x11\\xf1\\xcd\\xf8\\x74\\x92\\xa3\\x06\\x9b\\x89\\x6c\\x88\\xa3\\xb2\\xe7\\x1e\\xf5\\xf0\\x10\\xef\\x9e\\xbe\\xac\\xbb\\xf3\\xa9\\x3f\\x06\\xe5\\x29\\x04\\x29\\x32\\x9b\\xe4\\x27\\xa7\\x43\\xdc\\x9a\\xbf\\xda\\xf3\\x39\\xae\\x01\\x4d\\xfb\\x51\\xd0\\x34\\x7b\\xdb\\xad\\x8a\\x55\\xf0\\x90\\x09\\xd8\\x8d\\x91\\x3b\\x25\\xba\\x4a\\x5e\\xca\\xdd\\x23\\xe7\\x76\\x0b\\x69\\x17\\x40\\x31\\xb9\\x63\\x28\\x16\\xbc\\x19\\x6f\\x79\\x17\\x58\\x19\\x7c\\x82\\x49\\x2e\\x9b\\xb7\\x2d\\xdc\\xdf\\x78\\xd3\\xb0\\x6f\\x2b\\x5e\\x3b\\x14\\xe9\\x17\\x88\\x87\\x57\\x33\\x04\\x7f\\x30\\xa4\\xa2\\xb3\\xe3\\x1a\\xb7\\x64\\x0c\\x94\\x3d\\x09\\x6d\\xaa\\xc8\\x94\\xc6\\xff\\x1a\\x71\\x7b\\x9a\\x4e\\xbf\\xdf\\x5a\\xf2\\x38\\xcb\\x65\\xb0\\x75\\xcc\\x0f\\x33\\xe7\\xf1\\x63\\x40\\x5a\\x6a\\x69\\x71\\xff\\x74\\xac\\xdf\\x75\\x42\\x81\\xb8\\x97\\xe1\\xea\\xf6\\xb4\\x5b\\x4c\\x9c\\x08\\xab\\x94\\x6d\\x21\\xa5\\x56\\x1b\\xb6\\x0f\\x0b\\x16\\x9d\\x37\\x04\\xa0\\x14\\xfe\\x35\\xa1\\x43\\x9e\\x68\\xac\\x04\\x31\\x8d\\x8a\\xe5\\x44\\x1a\\x06\\x11\\xa1\\x17\\x8f\\xea\\xf9\\x02\\xcb\\x60\\x47\\xf6\\xed\\xee\\x4e\\x3f\\x6e\\x77\\x9c\\xed\\xa1\\xa2\\x0f\\xbc\\x42\\x07\\x9f\\xe4\\x61\\x15\\xc3\\x0e\\x93\\x7d\\xbe\\x02\\x4e\\x6e\\xe8\\xac\\x4b\\xbf\\x42\\xa3\\xad\\x93\\x30\\x85\\xdc\\xdc\\xb8\\x59\\x32\\xd9\\xcc\\x1e\\xaa\\xf8\\x19\\xf9\\x35\\x78\\x02\\x56\\x83\\xd6\\x81\\xea\\xdc\\xf9\\x77\\xa0\\x9c\\x35\\xea\\x03\\x46\\x4a\\xd6\\xa2\\xd6\\xf9\\x8d\\x02\\x91\\x70\\x49\\xbe\\x98\\xa0\\x7e\\xb2\\xe6\\x84\\xa4\\x3c\\x43\\xe9\\xee\\x56\\x58\\x5b\\xcc\\x3e\\x49\\x6f\\x03\\xb7\\x68\\x17\\x3e\\x69\\x81\\x88\\x81\\x7c\\x56\\x5b\\xa8\\xea\\x4b\\x9d\\xf4\\xdb\\x10\\x3d\\x75\\xf0\\x16\\x54\\x63\\xb9\\xeb\\xd9\\x57\\x8a\\xba\\xb5\\xbb\\x76\\x36\\x71\\x76\\x75\\xb1\\xa5\\xfe\\x86\\xda\\x55\\x4d\\x2c\\xfc\\x8d\\xf8\\x5f\\x90\\x9e\\x2d\\x5a\\x47\\x12\\xc3\\xbc\\x04\\x9c\\x81\\x6f\\x49\\x64\\x58\\xcc\\x49\\xd5\\x14\\x4b\\x7c\\x51\\x6e\\x3f\\xc8\\x30\\x0d\\x3b\\x82\\x60\\x2a\\x23\\x22\\xc7\\xcf\\x66\\x80\\x3f\\xe3\\x9f\\xd7\\x49\\xc9\\x9e\\xa6\\xee\\x22\\xda\\x6b\\xb2\\x44\\x12\\x82\\x1b\\x02\\x1b\\xa4\\xdd\\x0e\\xfa\\x63\\xfb\\xaa\\xe3\\xbf\\x9c\\x48\\x18\\x52\\x3e\\xba\\x6a\\x50\\xdc\\xf1\\xc9\\x40\\x20\\x9e\\xbb\\xa1\\x0f\\xd5\\xb5\\xbb\\xef\\x37\\xfe\\x9b\\x19\\xa3\\x3d\\x21\\x97\\x3b\\xc0\\x77\\x00\\x47\\xdb\\x72\\xd3\\x96\\x10\\x76\\xbf\\x5a\\x92\\xf9\\x1a\\xa0\\x68\\xb5\\x7a\\xb8\\x5a\\x29\\xff\\x1b\\x59\\xdd\\xdf\\x03\\xe3\\x47\\x0a\\x2f\\xcf\\x77\\x81\\x99\\x77\\x0f\\x08\\x17\\x94\\x6b\\xcb\\x48\\xbc\\x1d\\xd9\\xb3\\x13\\xb7\\x12\\xde\\x9f\\x07\\xf2\\x30\\xcf\\xb7\\x54\\xa2\\x58\\x79\\x7d\\x59\\xef\\x6a\\x0a\\x02\\x5e\\xf9\\x86\\x2d\\x3c\\x09\\xc4\\xce\\x67\\x89\\x4e\\xc5\\xa5\\xf6\\x6f\\xe5\\xc3\\xe3\\x00\\x10\\x67\\x4b\\xb7\\x70\\xb7\\x47\\xfc\\x48\\x4f\\xdd\\xc1\\x4d\\x92\\xb8\\x27\\x80\\xab\\x13\\x7f\\x21\\xeb\\x67\\xd1\\x0d\\x05\\xc5\\xab\\x82\\xf5\\xc8\\x43\\x41\\xc3\\x25\\x30\\x7c\\xfe\\x9e\\x64\\x33\\xc1\\xec\\x91\\x80\\xab\\xd6\\xb6\\xa7\\x40\\xce\\xad\\x8b\\xa4\\xd7\\x8f\\x15\\x68\\xa7\\x99\\xc2\\x27\\x6e\\xa8\\x31\\xdc\\xd4\\xab\\xbf\\x9c\\x90\\x1e\\x03\\x99\\xbb\\x15\\xbb\\xb4\\xe5\\xeb\\x88\\x6b\\x7b\\x18\\x45\\xdc\\x05\\x0f\\x90\\xce\\x61\\x19\\xc2\\xc6\\x11\\xf5\\xd3\\x74\\x11\\x41\\xd7\\xb1\\x43\\x10\\xbe\\xd0\\xc6\\xe5\\x69\\x5e\\x94\\x72\\x87\\x3e\\x85\\xd9\\xc5\\xe0\\x7d\\x98\\xc3\\xd4\\x80\\xd1\\x70\\xba\\x28\\x82\\xd4\\x6f\\x29\\xd5\\xf5\\xe3\\x26\\x87\\x56\\x8e\\x4e\\x98\\xe3\\xfd\\xfa\\xcd\\xc4\\xd4\\x1a\\x5f\\x43\\x3a\\x0e\\x78\\xb8\\xc7\\xe3\\x6e\\x06\\x08\\xf5\\x22\\xc6\\xb3\\xb5\\xa5\\x55\\xc2\\x2a\\x0a\\xb2\\x52\\xcc\\x68\\x3f\\x3d\\xbb\\x58\\x4e\\x18\\xe4\\x66\\x24\\xc4\\xcf\\xa4\\x21\\x33\\x34\\xc7\\xa6\\xb8\\xca\\x36\\xa2\\x7e\\x76\\x3f\\x04\\x17\\x89\\x86\\xbd\\xea\\x55\\xba\\x5d\\x15\\x84\\x2f\\x5c\\xbc\\xb4\\x94\\x85\\x73\\x6b\\x35\\x63\\xb7\\xd2\\xe1\\xb6\\x18\\x1e\\x7f\\x3a\\xde\\x28\\xa5\\xb8\\xff\\x8f\\x4e\\x77\\x83\\x94\\x1d\\xf8\\x15\\x31\\xce\\x08\\xe9\\x68\\xd5\\x4e\\xfa\\x50\\x27\\xbd\\x22\\x36\\x2a\\x54\\xab\\x2e\\xfe\\xcf\\xcc\\x7a\\xbd\\xe1\\x53\\x04\\x7e\\x3d\\x88\\x34\\xdd\\x0c\\x48\\x3f\\x03\\xfd\\x8f\\x13\\xbe\\xee\\x9d\\xbf\\x16\\x08\\xcd\\x77\\x93\\x98\\x44\\x11\\xb0\\x51\\x24\\x75\\xc2\\xea\\xad\\xd7\\x12\\x01\\xbb\\x33\\xe0\\x11\\x12\\x86\\x91\\x22\\x12\\x71\\x71\\x82\\x81\\x42\\x2f\\x5a\\x72\\xcc\\x46\\x3a\\x68\\x7f\\x5d\\xae\\x2f\\x87\\x95\\x46\\xd3\\xf4\\xdf\\x94\\x76\\x31\\xa2\\xdd\\x8f\\x92\\x52\\x19\\xb6\\xc2\\xa2\\x5a\\xa1\\x31\\xcf\\xcd\\x7e\\x2b\\xd7\\xa2\\xa1\\x1f\\x13\\xea\\x04\\x8f\\x89\\xf7\\x5b\\x49\\xda\\x2c\\x82\\x2c\\xdd\\xdb\\xc1\\xc3\\xe3\\xf1\\x1d\\x06\\x79\\x22\\x0a\\x13\\xc4\\x3f\\x01\\x08\\x38\\x2e\\xc8\\xcd\\x17\\xb4\\x37\\x99\\xaf\\xc6\\x45\\x5e\\x24\\xe8\\xdd\\xa3\\x79\\xdd\\xb6\\x8a\\x91\\x60\\xbd\\xb7\\x9e\\x72\\x38\\x68\\x6b\\x44\\x3b\\x82\\x12\\xae\\xaf\\x2e\\x34\\x51\\x98\\x6d\\xa3\\xa0\\x8d\\xd8\\x82\\xe2\\x3c\\x29\\x50\\x44\\xbe\\x11\\x2f\\x7f\\x03\\xed\\x77\\xca\\x6e\\x36\\x96\\xa0\\x6f\\x32\\x80\\xef\\x63\\x94\\x13\\xb7\\xf0\\x1b\\x2a\\xf4\\x08\\x94\\xad\\x1c\\x3c\\x61\\x5a\\xc6\\x41\\x19\\x66\\x64\\xb7\\x96\\x96\\xa7\\xf4\\x0a\\xc3\\xdb\\xde\\xc2\\x23\\xb7\\xf1\\xc2\\xe7\\x7e\\xda\\x05\\x29\\x36\\xab\\x41\\x5e\\x8b\\x22\\x43\\x95\\x9e\\x83\\x4b\\xc7\\x4b\\xcf\\x60\\x2d\\xc5\\x45\\xc2\\xe5\\x25\\xf4\\xd8\\x70\\x3b\\xc8\\xa7\\xfa\\x8e\\xf9\\x61\\xc7\\xe9\\x0c\\x06\\x49\\x15\\x16\\x9c\\x32\\x88\\x59\\x22\\x6b\\xf7\\x00\\x59\\xca\\xaf\\x02\\xf1\\x45\\x16\\x15\\x52\\x80\\x95\\x99\\xa9\\xbb\\x7d\\x2e\\xa6\\x94\\xfa\\x40\\xb4\\x94\\xb2\\x84\\xde\\x42\\x97\\x1e\\x1a\\x05\\x6e\\x53\\xd5\\xe5\\xff\\xac\\xd3\\xc1\\x91', 1)"
  },
  {
    "path": "environment/world/position_calc.py",
    "content": "import math\n\n\ndef get_distance(a_x, a_y, b_x, b_y):\n    return math.sqrt((a_x - b_x) ** 2 + (a_y - b_y) ** 2)\n\n\ndef angle_cal(x1, y1, x2, y2):\n    '''\n    :param x1, y1 the position of start point\n    :param x2, y2 the position of end point\n    '''\n    angle = math.degrees(math.atan2(y2 - y1, x2 - x1))\n    if angle < 0:\n        angle += 360\n\n    return int(angle)\n\n\n# TODO: random position\ndef pos_generate(side1_d_num, side1_f_num, side2_d_num, side2_f_num, size_x, size_y, random, random_pos=False):\n    '''\n    random_pos == True:\n    side1 on the left, side2 on the right\n    random_pos == False:\n    side1 on the right, side2 on the left\n    '''\n    if random_pos:\n        pos_x = [900] * side1_d_num + [800] * side1_f_num + [100] * side2_d_num + [200] * side2_f_num\n        side1_course = 180\n        side2_course = 0\n    else:\n        pos_x = [100] * side1_d_num + [200] * side1_f_num + [900] * side2_d_num + [800] * side2_f_num\n        side1_course = 0\n        side2_course = 180\n    side1_d_pos_y = [int(float(size_y) / (side1_d_num + 1) * (index + 1)) for index in range(side1_d_num)]\n    side1_f_pos_y = [int(float(size_y) / (side1_f_num + 1) * (index + 1)) for index in range(side1_f_num)]\n    side2_d_pos_y = [int(float(size_y) / (side2_d_num + 1) * (index + 1)) for index in range(side2_d_num)]\n    side2_f_pos_y = [int(float(size_y) / (side2_f_num + 1) * (index + 1)) for index in range(side2_f_num)]\n    pos_y = side1_d_pos_y + side1_f_pos_y + side2_d_pos_y + side2_f_pos_y\n\n    return pos_x, pos_y, side1_course, side2_course\n\n\ndef pos_update(pos_x, pos_y, course, step, size_x, size_y):\n    pos_x += int(math.cos(math.radians(course)) * step)\n    pos_y += int(math.sin(math.radians(course)) * step)\n    if pos_x < 0:\n        pos_x = 0\n    if pos_x > size_x:\n        pos_x = size_x\n    if pos_y < 0:\n        pos_y = 0\n    if pos_y > size_y:\n        pos_y = size_y\n        \n    return pos_x, pos_y\n"
  },
  {
    "path": "environment/world/replay.py",
    "content": "__pyarmor__(__name__, __file__, b'\\xe7\\x50\\x8c\\x64\\x26\\x42\\xd6\\x01\\xb9\\x4e\\x3f\\xdf\\x40\\x9b\\x76\\xef\\x72\\x6c\\x30\\x53\\x5b\\x51\\x0e\\xf9\\x7d\\x9a\\x1f\\x95\\x7a\\x32\\xda\\x47\\xc0\\x21\\x4e\\x84\\xc2\\x3c\\xf0\\x83\\x93\\x7e\\x7e\\x7e\\x94\\x24\\x9f\\xb7\\xc2\\x25\\xee\\xbc\\xad\\x52\\x4c\\x9a\\xd9\\x9e\\x8a\\xbb\\x31\\xb9\\x38\\x87\\x31\\xc3\\x27\\x4d\\x4a\\xd7\\xd9\\x9f\\xe9\\xb4\\xa4\\x99\\xa3\\x3c\\xf3\\x83\\xa4\\xc0\\x13\\xcf\\x7f\\x58\\x09\\x60\\xa2\\xa1\\x15\\x51\\x95\\x47\\xb1\\x01\\x5e\\xef\\xcf\\xde\\xa0\\xc6\\xc7\\x4a\\xeb\\xf4\\xeb\\xff\\x74\\x92\\x4a\\x45\\xbf\\xdb\\x6b\\xdf\\x05\\xb7\\xa0\\x3b\\x26\\x8a\\x06\\x85\\xa0\\x64\\xbd\\xa7\\x13\\x52\\xdb\\x8d\\xda\\x06\\x03\\xa4\\xa7\\x4d\\x8c\\xce\\x7e\\x0e\\x21\\x92\\x75\\x80\\xb9\\x18\\xc3\\xf9\\xd8\\x32\\x6a\\x99\\x83\\x06\\x71\\xdd\\x7f\\x74\\xfa\\x01\\xec\\xfa\\xe7\\x73\\xfb\\xce\\xd7\\x39\\xfe\\x82\\xac\\x9e\\x5c\\xcc\\x01\\x71\\xdb\\x16\\xe6\\x3d\\x5d\\x67\\x58\\x8c\\x5b\\x7c\\xd7\\x39\\x98\\x79\\x5f\\xf8\\x5f\\x9b\\x75\\xd1\\x39\\xc5\\x46\\xee\\x73\\x25\\x53\\xde\\x11\\xe6\\xa6\\x1a\\x15\\x87\\x0c\\x74\\xa8\\x15\\x69\\xfd\\x97\\x0a\\x75\\x26\\xb5\\xda\\x5c\\x92\\x8f\\x92\\x4e\\x2d\\xf8\\x04\\xaf\\xa9\\x9c\\x98\\x3d\\x4b\\x05\\x87\\x41\\x65\\x5b\\x94\\xc5\\x3e\\x08\\x2f\\x71\\x99\\xe6\\xdd\\xe3\\x05\\x0d\\x4c\\x8e\\x2e\\x17\\xe3\\x4d\\xa6\\x6c\\x09\\x98\\xc7\\x9b\\x98\\x9c\\xc4\\x01\\x6a\\x58\\x60\\xe3\\x0a\\x05\\x0a\\xed\\x20\\x80\\x26\\x79\\x6f\\x4f\\x5e\\x6a\\xed\\x63\\xe7\\x6f\\x84\\x5c\\xab\\xc1\\x76\\xa9\\x6f\\xcb\\x16\\x0d\\x46\\x93\\x6e\\x66\\xda\\x6a\\x13\\xca\\x77\\x42\\xba\\xc5\\x66\\x6d\\x96\\x2a\\x0b\\x49\\x83\\x35\\xee\\x8a\\x17\\x3e\\x82\\xc2\\x1d\\x7f\\xbb\\x3c\\x5f\\xdc\\xba\\xe8\\xf7\\x68\\x25\\x0d\\x03\\xea\\x74\\xb0\\x2c\\x24\\xec\\x8d\\x13\\x37\\xcb\\x5a\\x5d\\xd0\\x9a\\x82\\x50\\x67\\x36\\x10\\x6b\\xcf\\x82\\xaf\\xcf\\xed\\x42\\xd3\\x41\\xae\\x0d\\x0b\\x65\\x4e\\x62\\x3d\\x83\\x98\\x4e\\x25\\xe7\\xcf\\x76\\x1f\\x1e\\x5f\\xb5\\x4d\\x3b\\x52\\x04\\x15\\xf6\\xff\\x39\\x24\\x0c\\x5e\\x22\\x78\\x83\\x60\\xad\\xca\\xbb\\xfb\\x8b\\x26\\xa3\\x08\\x6a\\xc3\\xc9\\xf2\\xf3\\xf3\\xcc\\x8d\\x71\\xf4\\x1d\\x0c\\x94\\x90\\x1a\\x38\\x3e\\xf4\\x32\\xee\\xf0\\x1d\\xa7\\x74\\x07\\xf9\\xa0\\xdd\\xa1\\xce\\x7d\\x61\\x88\\x08\\xc7\\x29\\xf5\\xa1\\x28\\x0a\\x69\\xbb\\xca\\x5a\\xd7\\x2d\\x4d\\xf9\\xea\\xd9\\xc7\\x23\\xf9\\xbf\\xba\\x89\\xd3\\x6b\\xf2\\x85\\xf3\\x2a\\x28\\x72\\x78\\x2d\\x20\\x9f\\x69\\xe7\\x27\\xf7\\xf0\\xb9\\xc9\\xb7\\x31\\xd4\\xf9\\xfc\\xce\\x58\\xe5\\x2c\\xb9\\xee\\x73\\xae\\xe0\\x36\\xaf\\xe6\\xc5\\xcd\\x67\\xbd\\xad\\x0e\\x79\\xd6\\xa2\\x27\\xd0\\x4d\\x1b\\x90\\x13\\xb0\\xa6\\xc5\\x1d\\x5f\\x79\\x91\\xf7\\x5e\\x9b\\xbd\\x4c\\xaf\\x41\\x5c\\x1c\\x53\\x4e\\x0e\\xe3\\xdc\\x7b\\x57\\x05\\x7d\\x90\\x56\\x6e\\x7b\\x22\\xe3\\x57\\x5c\\x4e\\x5c\\x24\\xaf\\xa6\\x04\\xf1\\x5a\\x9a\\x5f\\xbd\\x7e\\x4a\\x2b\\x5d\\x12\\x6f\\x07\\xd1\\x47\\x21\\x24\\xce\\x93\\x74\\x71\\xdd\\xd9\\xf6\\xdd\\xa8\\x5f\\x66\\xe1\\xfe\\x29\\x9b\\x60\\xf3\\xbf\\xb6\\xaa\\xc5\\x96\\x28\\xf5\\x82\\xef\\x4a\\x82\\x25\\xb6\\x33\\xf2\\xfc\\x0e\\x1a\\x64\\x41\\xb8\\xf5\\x00\\xe6\\x15\\x56\\x78\\x83\\xfc\\x50\\x92\\x14\\xad\\xbf\\xde\\x0f\\x02\\x7d\\x70\\x03\\xd0\\x72\\x14\\xf7\\x52\\x48\\xfb\\x41\\x4a\\xe8\\x8c\\x76\\x39\\xbb\\x77\\x32\\x14\\xe6\\x52\\x42\\x8f\\x1b\\x4a\\x00\\x94\\x52\\x5f\\x14\\x6c\\x19\\x4a\\xa5\\xc3\\x9e\\x02\\x2e\\x0f\\x56\\x15\\x13\\x5f\\x21\\x2a\\x31\\x4c\\x17\\x39\\x6c\\xce\\xc0\\xc6\\xc5\\x5b\\x69\\xf9\\x6b\\x4f\\xcf\\xe6\\x7d\\x44\\x65\\x6c\\x4e\\x3f\\x67\\x06\\x53\\x9b\\x54\\x34\\x04\\x28\\xea\\x5c\\x8a\\x05\\x1a\\xd1\\x1a\\x26\\xf9\\x86\\x2f\\xde\\xe1\\xf5\\x1f\\x1c\\x01\\xbc\\xc9\\x04\\x5f\\x3a\\x41\\x3d\\xa7\\x48\\xe2\\xd8\\x78\\x96\\x1a\\x60\\x28\\x4d\\x08\\x52\\xce\\x7f\\x19\\x5c\\x52\\x35\\x09\\xbd\\xda\\x53\\x19\\x1f\\x41\\x72\\x60\\xa7\\xc5\\x5f\\x35\\x5b\\xa7\\x37\\x3d\\xba\\x23\\xde\\xcc\\xa6\\x0f\\xa7\\x7b\\x26\\xb7\\x83\\x70\\x33\\xed\\x72\\xec\\x83\\x93\\xba\\x6e\\xa5\\x52\\x63\\xfa\\xb0\\x1d\\x30\\xa8\\xa3\\x23\\x30\\xa1\\x13\\xde\\x3b\\x0f\\x2a\\x05\\x49\\xa0\\x7b\\x49\\x6d\\x09\\x60\\x2a\\x97\\x95\\x4d\\x65\\xcd\\x7a\\x7f\\x54\\x6e\\xb0\\xd3\\x52\\xad\\x21\\x10\\xdf\\xff\\x3b\\xe2\\xb5\\x0e\\x23\\xab\\xb4\\xc6\\xf6\\x25\\x48\\x41\\x99\\xec\\x53\\x3c\\x5a\\xb9\\x22\\xd6\\x54\\x1d\\x70\\xa0\\xf8\\x98\\x78\\xe4\\x25\\xd5\\x29\\x77\\xf2\\x4d\\xd4\\x8b\\x4e\\x11\\xb0\\xbe\\xfc\\xbb\\xe8\\xbe\\xc9\\xbd\\xf8\\x67\\xb9\\xf7\\xc3\\x32\\x3b\\x41\\xea\\xe6\\xa5\\x73\\x94\\x1d\\xa3\\x75\\x41\\xd5\\x5b\\x73\\x2c\\x38\\x00\\x37\\x3a\\x44\\xd3\\xe0\\xe8\\xe9\\x41\\x1b\\xb6\\x67\\x2b\\x16\\x73\\xf6\\x0f\\x1f\\xcf\\xcb\\x84\\x1e\\x4c\\x52\\xb6\\xec\\x7e\\xd2\\x73\\x51\\x41\\x5c\\x19\\xdc\\x73\\x03\\xd7\\xd0\\x49\\x91\\x43\\x68\\x90\\x5e\\x74\\xc7\\xd3\\x1d\\x56\\xdb\\x6f\\xf0\\x67\\x0b\\x7a\\x48\\x8d\\x7e\\xde\\xe8\\x0f\\x24\\x00\\xda\\x04\\xe0\\x9a\\xb5\\x51\\x7c\\x30\\x88\\xaa\\xe3\\x92\\x8f\\x9a\\xbb\\x46\\xd1\\xd2\\x48\\xc1\\xac\\xb6\\xb4\\x2f\\xe1\\xd2\\x25\\x1d\\x42\\x39\\xcc\\xfa\\x81\\x53\\xf8\\x18\\xef\\x64\\x36\\xd8\\xe5\\xe3\\xc4\\xd4\\x50\\xf4\\x22\\x2b\\x55\\xc3\\x8f\\xe3\\xd5\\x8e\\xab\\x01\\xc0\\xcd\\x36\\x00\\x00\\xcc\\xa3\\x12\\x9e\\x85\\x0c\\x9d\\xe5\\x0a\\xc0\\x39\\xe6\\xe9\\x20\\xa7\\x87\\x1b\\xfc\\x26\\x64\\x79\\x1f\\xec\\x8f\\x9b\\xd8\\xfc\\xb0\\x74\\x15\\x3d\\x4c\\x64\\x58\\x9f\\x98\\xa6\\xb9\\xc2\\xa2\\x5c\\x9e\\x78\\x7d\\x1a\\xb2\\x2e\\x04\\x40\\x4a\\x43\\xc8\\xe4\\x75\\x97\\x20\\x49\\x07\\x53\\x0a\\xf7\\x4f\\xae\\x21\\xee\\xb2\\x11\\x68\\xa1\\xfe\\x2b\\x14\\xbc\\xd6\\x91\\x43\\x26\\x00\\x26\\x50\\x81\\xc2\\xe6\\x4c\\x7d\\xd3\\xf5\\x33\\x39\\x28\\x60\\x70\\xfa\\xc4\\x6f\\x9e\\x71\\x4d\\xbc\\xf6\\x9c\\x73\\x47\\xea\\x13\\x86\\x5f\\x90\\xa6\\x52\\x93\\xd7\\x8f\\xfe\\x22\\x12\\x4f\\xdf\\x91\\x72\\xe5\\x9b\\xed\\x90\\x20\\x87\\x6d\\x0e\\x5e\\x46\\xb1\\x5e\\xab\\xea\\x99\\x65\\xa8\\x94\\x8c\\x67\\x2e\\x0b\\xa8\\x4f\\x08\\xac\\x39\\xcb\\x22\\x16\\x78\\x76\\x03\\xbc\\x17\\x20\\x86\\x56\\xc6\\x2f\\x14\\xdf\\x68\\x45\\x51\\x1c\\xca\\x0e\\x56\\xd1\\x12\\xeb\\xa3\\xd7\\xa3\\x46\\xa1\\x7f\\xc4\\xc2\\x16\\xb1\\xe1\\xa7\\xfa\\x25\\x25\\xda\\x9a\\x7b\\xbf\\xa5\\x4d\\xe6\\x75\\x52\\x65\\xd0\\x50\\x64\\x06\\xbd\\x99\\xe6\\x37\\xa7\\xe5\\x60\\xc1\\x24\\x3a\\x85\\xbc\\xe3\\x4c\\x66\\x11\\xfd\\x57\\x7d\\x5a\\x3f\\xec\\x53\\x67\\x32\\xe8\\xf8\\x34\\xcc\\xc1\\x01\\x20\\xc7\\xac\\xa9\\x00\\xc0\\x31\\xe3\\xfc\\x65\\x1e\\xd4\\x02\\x12\\xe5\\xa6\\x67\\x42\\x64\\xbd\\x20\\xd7\\x06\\x7f\\xfa\\xfa\\xc4\\x46\\x97\\x39\\x07\\x10\\x3e\\x1a\\x25\\x2f\\x9d\\x70\\x24\\x4f\\x9a\\x69\\x55\\x0d\\x43\\xd5\\x65\\xa2\\xa9\\x36\\x27\\x55\\xaf\\x3f\\x65\\xb2\\x69\\xd4\\x86\\x9a\\x6c\\xfd\\x6e\\xd7\\xe8\\x71\\xbf\\xeb\\xda\\x10\\x97\\x42\\x66\\x5a\\x6a\\xc4\\xbd\\xf6\\xd4\\x74\\x2c\\xca\\xd2\\x17\\x02\\xf9\\xfe\\xd3\\xb8\\x07\\x0f\\x1d\\x2e\\x3e\\xe8\\x6a\\xd7\\xf3\\xdc\\x31\\x07\\x2a\\xc4\\xbb\\x1d\\xcd\\x63\\xa4\\xb6\\xc8\\x9a\\x80\\xde\\xa4\\x44\\xaa\\xf3\\xb8\\xda\\x25\\x45\\x77\\x31\\x0f\\x36\\xe8\\x0d\\x85\\xdd\\x26\\x1f\\x95\\xfe\\xd7\\x1a\\xbb\\x43\\xed\\x4f\\xc1\\x8f\\x78\\x44\\x20\\x68\\x45\\x1b\\x03\\xe0\\x78\\x3d\\x9a\\x89\\xbb\\x67\\x47\\x1f\\x91\\x4a\\xc1\\x13\\xe7\\xa2\\x3f\\x42\\x70\\xc9\\x0d\\x02\\xcc\\xcd\\x3b\\xe3\\x6e\\x69\\x64\\x5e\\xf5\\x00\\x83\\x2d\\x7e\\x88\\xf9\\x7c\\x8a\\x70\\x28\\x4a\\x1a\\xaf\\x3a\\xe1\\xdb\\x60\\xcf\\xfc\\xa7\\xda\\x63\\x7b\\xa8\\x6e\\xd8\\xeb\\xfe\\x86\\x24\\xcb\\xf4\\xe7\\xbc\\x11\\x6d\\x49\\x29\\x69\\x27\\x8b\\x9f\\xbb\\xef\\x1f\\xf6\\x98\\x2e\\x10\\x76\\xb4\\xb1\\x5a\\x03\\xe6\\x25\\x6e\\x11\\xb7\\x14\\xc6\\x82\\x81\\x01\\x75\\xb0\\x69\\x3a\\xef\\xec\\x88\\xf9\\x8e\\xd9\\x80\\x67\\x39\\xb2\\x68\\xc5\\x13\\xf3\\xd3\\x22\\x83\\xda\\xa5\\xa5\\x07\\x5c\\x8b\\xf2\\x01\\x04\\x3f\\x66\\x3d\\xeb\\x7c\\x3f\\xb4\\x2c\\x38\\xa1\\x20\\x92\\x24\\x90\\x3c\\x29\\xb8\\x02\\xa9\\x49\\xf8\\x51\\x51\\x15\\x08\\xa0\\x38\\xe4\\x61\\x97\\xa9\\x8a\\x27\\xc3\\x1f\\x17\\xb0\\x39\\x47\\x5e\\x8e\\xf1\\xef\\x0a\\x84\\xe0\\xd5\\xda\\x7d\\xa4\\x3e\\xe0\\x11\\x49\\xe2\\x4e\\xa9\\x36\\xf4\\x4b\\x2d\\xb1\\xa3\\x28\\x9d\\x39\\xa3\\x1d\\x2a\\x45\\xc5\\x9d\\xa4\\x5d\\x2a\\x8d\\x01\\xfd\\xd3\\x59\\xd7\\x32\\xc0\\xf3\\xb3\\xec\\x07\\x3d\\x82\\x86\\xa2\\x56\\xf7\\xd1\\x96\\x3b\\xb7\\x82\\xbb\\x06\\xcc\\x73\\xe1\\xfb\\x56\\x31\\x56\\xd4\\xa8\\xe7\\xdb\\xde\\xe4\\x84\\x73\\xc1\\xd1\\xd4\\x2f\\x50\\x18\\x55\\x71\\x1a\\xe9\\x45\\xbe\\xd9\\xba\\x6b\\x17\\x20\\x32\\x73\\x57\\xa3\\x8a\\xef\\x8b\\x76\\x4a\\x93\\x59\\x9c\\xf9\\xaa\\x47\\x79\\xd5\\x5f\\x8b\\xe4\\x65\\x71\\xef\\x70\\x66\\x43\\x11\\x7a\\xf6\\xfe\\x61\\x3c\\xee\\xdc\\x35\\x1a\\xc9\\x2b\\x86\\x87\\x78\\x02\\xda\\x21\\x2c\\xb3\\x42\\xaf\\x6e\\x0a\\x8b\\x92\\x24\\xed\\x6e\\x88\\x91\\x51\\xf9\\xb8\\x2d\\x37\\x40\\x03\\xd7\\x1c\\xcd\\xa9\\x33\\xf5\\x53\\x65\\x85\\x88\\x4f\\x35\\xf7\\xa1\\xef\\xf9\\xbe\\x32\\x38\\x7c\\xbf\\xfb\\xa1\\x58\\xdd\\xc1\\x65\\x86\\x62\\x34\\x75\\x80\\xbe\\x57\\xd4\\x35\\x75\\x02\\x3a\\x93\\x61\\x11\\x26\\x3c\\x08\\xa2\\x19\\xf6\\xcd\\xcf\\x9d\\xa4\\xeb\\xbc\\x1f\\xa1\\x77\\x75\\x06\\x00\\xf4\\x15\\x34\\xc4\\x25\\xba\\xfe\\x65\\xfa\\x80\\x6b\\xba\\x1e\\x68\\x86\\x2d\\x74\\xe5\\xc7\\x12\\x48\\xdb\\x35\\xee\\x9a\\x36\\x7f\\x87\\xba\\x64\\xee\\xc6\\x72\\xc4\\xf5\\x83\\xb4\\xc7\\xe2\\xfd\\xee\\x8d\\xa2\\xe7\\xb5\\x36\\x61\\xc8\\x8f\\x95\\x94\\xf5\\x27\\xbe\\x96\\x7a\\x39\\x00\\xf5\\x84\\x13\\xd9\\x39\\x17\\x86\\xa2\\x28\\xc7\\x74\\x39\\x51\\xa5\\x5f\\xc2\\x54\\xf5\\x18\\x9b\\xd0\\x43\\xfe\\xb4\\x62\\xee\\x47\\x5c\\x31\\x29\\xa0\\xcf\\x62\\xa9\\x30\\x20\\x28\\x82\\xfc\\xa1\\x75\\x13\\xf8\\x89\\x8f\\x0f\\xe5\\xac\\x5a\\x37\\x46\\x5b\\xe9\\x56\\xed\\xd0\\x97\\xbe\\x23\\xce\\x09\\xcd\\xde\\x08\\x89\\x5b\\xfe\\x95\\x34\\xa1\\x18\\x5c\\x8c\\x5b\\xea\\xef\\x54\\x3a\\xdc\\x4c\\x16\\x0b\\x1c\\x6a\\xc5\\xfa\\x8e\\xc8\\x56\\x6d\\x92\\x0a\\xcd\\x27\\x57\\xa1\\xad\\xce\\x79\\x2e\\x74\\x5e\\xf0\\xd0\\x79\\xd4\\x2e\\xfe\\xd7\\xd7\\x9a\\x91\\x53\\xb3\\x5e\\x80\\xf8\\xff\\x81\\x22\\x02\\x57\\x69\\x6a\\xb7\\x55\\xe8\\x76\\x3f\\x24\\x53\\x4e\\xf1\\xba\\x99\\x30\\xc3\\xe9\\x20\\xf6\\x5f\\x80\\x2b\\x12\\xda\\x14\\xfa\\xdd\\xb5\\x6a\\x55\\xf4\\x37\\xcb\\x84\\xc3\\x71\\xbb\\x02\\x07\\x90\\x0a\\xa5\\xfa\\xb0\\x9a\\x83\\x10\\xba\\x0e\\x41\\xa6\\xd2\\x1d\\x29\\xd9\\x59\\x67\\xb3\\xce\\x5b\\x68\\x8c\\xc7\\xc3\\x69\\xc6\\x3e\\x0c\\xbc\\x47\\x06\\x32\\x29\\x40\\x0e\\xb9\\x80\\xa1\\x2c\\x19\\x77\\x68\\x5d\\x58\\xdc\\x6a\\x19\\xcf\\x32\\x29\\x2e\\xe0\\xc3\\x9c\\x5d\\x9a\\x35\\xdd\\x5b\\x7b\\x78\\xfa\\xf8\\xda\\x54\\x1e\\xa0\\x27\\x60\\xda\\x04\\x8f\\x75\\x44\\x5d\\xc4\\x7a\\x53\\x28\\x86\\xfc\\xfe\\x24\\xb3\\xf3\\x3d\\xb2\\x25\\xda\\x44\\x1e\\x29\\x8f\\x4a\\x01\\x44\\x76\\x09\\x38\\x8f\\xff\\x82\\x04\\xd5\\x33\\xd8\\xa2\\x66\\xb1\\x2e\\x7a\\xca\\x84\\x97\\x80\\xd3\\x23\\x80\\xe0\\x23\\xc5\\x9d\\x9e\\x10\\x4f\\x27\\xfb\\xee\\xab\\xda\\x29\\x5f\\x79\\xa6\\x4d\\x52\\xbf\\x87\\x6f\\x34\\xe2\\x3f\\xfc\\x3d\\xd1\\x17\\x21\\x21\\x2a\\xd3\\x69\\xaa\\x2a\\x32\\x59\\x56\\xbe\\x95\\x14\\x6e\\x02\\x24\\xf5\\x13\\x1c\\x50\\x2f\\xaf\\x51\\xc9\\xbd\\x97\\x07\\xfd\\xf6\\x9a\\xe0\\xee\\x14\\x92\\x84\\xac\\xb1\\x08\\x65\\x8e\\x63\\xf3\\x53\\x76\\xaf\\x4b\\x99\\x90\\x3c\\xb0\\x79\\xeb\\x4e\\x1e\\xab\\x49\\x94\\x79\\x6f\\xde\\xd8\\xb6\\x62\\xaf\\xec\\x56\\xc6\\x6d\\x8c\\xf3\\xfa\\x68\\x2a\\x88\\xc9\\x80\\xab\\xc9\\x49\\x6d\\x15\\x4b\\xc1\\x2c\\x32\\x4f\\x0f\\xf8\\xbd\\x40\\xee\\x2f\\x2d\\x39\\xb9\\x6e\\xec\\x7a\\x2c\\x24\\x42\\x66\\x11\\xef\\x65\\x74\\x41\\xd7\\x6a\\xd1\\xdb\\x0d\\xe8\\x2a\\xcf\\xd2\\x09\\x75\\xd6\\x72\\xe6\\xb3\\xc2\\xcf\\xb6\\x3c\\x1b\\xac\\xc1\\xf6\\x96\\x01\\xdb\\x3f\\x24\\x2d\\xe8\\x4f\\xab\\x5f\\x48\\x89\\x90\\x8d\\x56\\x83\\xe0\\x75\\x8f\\xc7\\xb5\\xe9\\x30\\x74\\x42\\xe4\\x69\\x2f\\xf2\\xb3\\x3f\\x96\\x2d\\xa9\\xbe\\x25\\xba\\x06\\x5c\\x3f\\xb9\\x69\\x4a\\x98\\x01\\xe9\\xf7\\xec\\x0a\\x3f\\xe6\\xef\\x4f\\xce\\xa4\\x53\\xfe\\x58\\xe7\\x20\\x58\\x26\\xc6\\xcc\\xbd\\xb8\\x15\\xa2\\x4e\\xdf\\x26\\xac\\x30\\x34\\xb6\\x23\\x87\\x3e\\x6c\\x2d\\xb0\\x51\\xed\\x39\\xce\\x33\\x10\\x91\\x88\\xba\\x84\\x49\\xd7\\xbe\\xe5\\x7c\\x93\\xf1\\x6c\\x68\\xf1\\xa8\\x77\\x3a\\x86\\x95\\x95\\x6a\\x86\\x5c\\x7c\\x0b\\xc5\\xe3\\x31\\x8a\\x28\\x2e\\xe4\\xc6\\xea\\xc2\\x4b\\x9c\\x83\\x06\\xda\\xe7\\xfd\\xd1\\x43\\x74\\x7f\\x78\\x78\\x98\\x15\\x06\\xf2\\x0c\\x66\\xcb\\x24\\x69\\xf9\\xd8\\x25\\x82\\xbd\\x6c\\xa4\\x0e\\xfa\\x96\\xbf\\x92\\xc6\\x13\\x2a\\xb9\\xe9\\x07\\x37\\x3e\\x95\\x51\\x35\\xcc\\xc4\\xab\\x30\\x26\\x50\\x6e\\x03\\x4f\\x71\\xed\\x18\\x3e\\x9f\\xc8\\x45\\x91\\x24\\x12\\xcc\\x8f\\xb7\\x8c\\xac\\xe4\\x1d\\x99\\x47\\x44\\x59\\x5c\\x14\\x81\\x36\\xee\\x94\\x32\\xf4\\xc3\\x2e\\x36\\xf3\\xc9\\x12\\x39\\x1d\\x69\\xe9\\xcb\\x7b\\xdc\\x34\\x38\\x0a\\xbb\\xe4\\x6e\\xf5\\x8e\\x65\\x2d\\xfc\\x7d\\x9e\\x93\\x12\\xaf\\x1d\\x96\\x3b\\x7f\\xaa\\x23\\x0c\\x95\\x3d\\xf5\\x59\\x8f\\x02\\xc9\\x9b\\xdb\\x51\\x7b\\xae\\x18\\xa9\\x97\\x20\\x53\\x64\\x10\\x42\\x7e\\x7d\\x36\\x75\\x33\\x39\\xbe\\x74\\x11\\xfa\\x83\\x12\\x0a\\x66\\xb6\\xf0\\xbf\\xc6\\x4b\\x63\\x21\\x28\\xe2\\xb1\\x1c\\x4e\\xa8\\xf0\\xed\\xb9\\x0c\\xf6\\x22\\xa7\\x9e\\xf6\\x5c\\x43\\xb5\\x09\\x3a\\x9c\\xcc\\xb1\\x79\\xe6\\xa4\\x36\\x52\\x98\\x39\\x92\\x66\\x38\\x0a\\x50\\x80\\x6d\\x2d\\xe4\\xc8\\x01\\x54\\x47\\x06\\x3a\\xe8\\x38\\x2d\\x91\\xfc\\xcb\\x90\\x8b\\xaa\\xc8\\xcf\\xdc\\xba\\xe7\\x2d\\x5d\\x46\\x9f\\x2a\\x2b\\x82\\x1d\\x62\\xe3\\x90\\xe4\\xf5\\x2b\\x42\\x73\\x20\\x7e\\xb6\\x66\\xd0\\x80\\x81\\x51\\x5b\\xa4\\x44\\xff\\x31\\x60\\x48\\x17\\xf6\\x76\\x6e\\xa5\\xf2\\xa3\\xee\\xb8\\xee\\x77\\x44\\xa4\\xe1\\x35\\x50\\xed\\x4a\\x92\\xd4\\x82\\xf0\\x45\\xfc\\x50\\xd8\\xe7\\xd5\\xe4\\xd3\\x64\\x6e\\x93\\x82\\xe0\\x73\\xb3\\x04\\xa9\\x10\\x7f\\x7c\\x15\\xa2\\x56\\x92\\x7c\\x8d\\x7d\\x36\\x19\\x0f\\x93\\xfc\\x3d\\x43\\x64\\x43\\x9d\\x5e\\xa9\\xdd\\xaa\\x1a\\xba\\xba\\xde\\xec\\x30\\x83\\xe9\\x84\\x24\\x7d\\xfa\\x5d\\x7a\\x88\\xf2\\xa7\\xbb\\x82\\x04\\xcb\\x65\\x6c\\xb6\\x3d\\x18\\xe6\\xe6\\xd9\\x2c\\x8c\\xe8\\x81\\x69\\x8e\\xb4\\xfa\\x41\\xd9\\x45\\xce\\xcf\\xa3\\x4f\\x3e\\xc6\\x1b\\x38\\x07\\x55\\x07\\x3b\\xe5\\xad\\x39\\xd2\\x9b\\x00\\x0d\\x85\\x92\\xcb\\xff\\x29\\xf0\\xff\\x8e\\x0f\\x47\\x57\\x8d\\xf7\\x64\\x68\\x19\\xa3\\x8d\\x78\\x41\\x59\\xa2\\x1a\\x8c\\x8f\\xcc\\x15\\x01\\x37\\xea\\xc7\\x9b\\x33\\x2a\\xf5\\xbe\\x25\\x70\\x7c\\xe8\\xd3\\x17\\x5e\\xba\\x8f\\x53\\xa6\\xb5\\xaa\\x50\\x49\\x88\\x5a\\x36\\xaf\\xb8\\xfa\\xd5\\x1c\\x6a\\x6f\\xbb\\xdc\\x0d\\x8f\\x7d\\xae\\xdc\\x57\\x1d\\xe8\\x18\\x5f\\xc0\\x78\\x49\\x9c\\xa7\\xd9\\xe4\\x72\\xfb\\x9b\\xbd\\x9a\\x8e\\x93\\xa6\\xac\\x0c\\xed\\x1a\\xa0\\xcb\\xea\\x86\\x93\\x9f\\x92\\xf5\\x55\\x12\\xe7\\x19\\x0e\\xe0\\xb1\\xd3\\xd4\\x13\\x31\\x6a\\x18\\x14\\xf5\\x66\\xe1\\x47\\x7f\\x67\\x78\\x48\\x9a\\x2a\\x5f\\x4d\\x4d\\xa5\\xe1\\x38\\x4f\\xed\\xa4\\x4f\\x5c\\x36\\x0e\\x2f\\xd2\\xbe\\x1e\\x15\\x70\\x53\\xee\\x38\\xaa\\xb3\\x8e\\x1b\\x51\\x9c\\x37\\xf3\\x27\\x0c\\x41\\x54\\x1f\\x85\\x99\\x9a\\x5e\\x16\\x22\\x26\\x20\\xc5\\xbf\\x9b\\x77\\xb7\\xf9\\x6a\\x07\\xae\\x89\\x68\\x69\\xf8\\x7f\\x90\\x0b\\xf8\\xa1\\xeb\\xb9\\x8a\\xa7\\x77\\x3d\\xbf\\x4c\\x63\\xe5\\xcd\\x26\\x02\\x30\\x28\\xa4\\x73\\x07\\x09\\x87\\x82\\x85\\x89\\x1a\\xba\\x29\\x04\\xc4\\xe6\\x35\\xd2\\xc7\\x55\\x2a\\x79\\x7a\\x63\\xac\\xa8\\x5f\\x32\\xb7\\x36\\xc1\\xdf\\x11\\x2a\\x1b\\x38\\xb6\\xd3\\x33\\x86\\x6e\\x7a\\xa5\\xc9\\x96\\x46\\xd3\\x16\\x23\\x3e\\x45\\x42\\x58\\x6b\\x58\\xd4\\xc4\\x41\\x01\\x7c\\xc6\\x95\\x61\\xfd\\x47\\xf7\\x75\\xfe\\x9a\\x9e\\x77\\x91\\x01\\x23\\x58\\x63\\xc7\\x7f\\x2a\\x20\\x01\\xb5\\xe3\\x74\\xb6\\xcd\\x52\\x61\\x53\\x22\\x1a\\xb9\\x58\\xdd\\xcc\\xce\\x3e\\xc2\\x9e\\xe8\\x64\\xfa\\x7f\\x6b\\x3f\\x7d\\xb2\\x2c\\xda\\x33\\x74\\x56\\x0b\\x05\\x21\\xa4\\xef\\xa6\\xe7\\xa7\\x25\\xd1\\x46\\xc9\\x6d\\x99\\x3c\\xf9\\x31\\x16\\x37\\x4b\\xbe\\x5a\\x70\\x75\\x94\\xbd\\xa2\\x86\\x5c\\x1b\\x9e\\xd6\\x2e\\x9a\\xbb\\x09\\x3d\\xd3\\x72\\x6b\\xbf\\xae\\x5f\\x06\\x7b\\x91\\xd0\\x9c\\x8f\\x6a\\x18\\x2a\\x25\\xce\\x50\\xfd\\x69\\x66\\xb5\\xab\\x56\\x52\\x75\\xb6\\x66\\x54\\xe3\\x9e\\xd6\\xc5\\x63\\xc5\\x92\\x2c\\xc3\\x7c\\x28\\xb8\\x01\\x4e\\x0f\\xe2\\x0d\\x89\\xf0\\xd8\\xed\\x79\\xd2\\xeb\\x80\\x0f\\xae\\xee\\xf8\\xd3\\x16\\x79\\xc6\\x66\\xf4\\xf8\\x9b\\x82\\x6c\\x78\\xbc\\x72\\x48\\xe9\\x78\\x42\\x19\\xb2\\x5a\\xa3\\x0b\\xc5\\x4e\\xdc\\x93\\x39\\x0f\\x35\\x22\\x43\\xcd\\x5e\\x4b\\x43\\xeb\\x93\\xfe\\x5b\\x94\\xee\\xc3\\x29\\x99\\xfc\\xc3\\x99\\x2a\\x4a\\xbc\\x48\\x9a\\xf8\\xd5\\xeb\\x52\\xd6\\xe3\\x6c\\x9d\\x3a\\x3b\\xd0\\xcb\\x8b\\x5b\\x0d\\x47\\x4c\\x01\\x20\\x74\\xf4\\xdd\\xdd\\xae\\x68\\xf3\\xda\\xfc\\x2b\\x06\\xac\\xba\\xee\\xd9\\x17\\x87\\x32\\x59\\x42\\x22\\xb6\\x28\\x40\\x6b\\x7b\\x2c\\x35\\xb1\\x65\\xc2\\xe8\\x41\\xe8\\xbf\\xf5\\x46\\x71\\x14\\xd7\\x31\\x03\\xff\\xaf\\xec\\x66\\x41\\xa6\\x60\\x01\\x96\\xdd\\x56\\xdd\\xc4\\x4e\\x2d\\xad\\xdf\\x53\\xe5\\x80\\x2f\\xe5\\x0a\\x95\\x13\\x3a\\x56\\xc7\\x4d\\xa0\\x0e\\x32\\xcf\\x6e\\xd8\\xab\\xaf\\xeb\\xbd\\xdd\\x53\\x3c\\x0a\\xe6\\xb2\\x81\\x59\\xf4\\x88\\xc9\\xf2\\x59\\x53\\x31\\xe0\\x98\\xee\\x63\\xe4\\xb8\\x05\\x2d\\xe9\\x3d\\x6d\\x4f\\x6d\\x6b\\x89\\xd2\\x4f\\xa7\\x12\\xc3\\x25\\x07\\x1a\\x08\\x16\\xfc\\x84\\xe3\\x68\\xce\\x41\\x85', 1)"
  },
  {
    "path": "environment/world/strike_calc.py",
    "content": "import random\nimport copy\nimport world.position_calc\nimport configuration.system as system_config\nimport world.position_calc as position_calc\nimport world.config as config\n\n\ndef get_strike_result_by_ratio(strike_ratio, random_obj):\n    result = True\n    if system_config.get_hit_prob_enable():\n        if random_obj.random() > strike_ratio:\n            result = False\n    return result\n\ndef strike_act_validation_and_initiation(missile_type, fighter_context, detector_context_list, enemy_status, strike_list):\n    '''\n    打击有效性判断，更新打击列表内容，同时返回该打击动作的有效性指示\n    :param missile_type: 导弹类型\n    :param fighter_context: 发起攻击的战机上下文\n    :param detector_context_list: 己方预警机上下文列表\n    :param enemy_status: 目标状态\n    :param strike_list: 打击列表[{'attacker_id': 攻击者编号, 'target_id': 目标编号, 'missile_type': 导弹类型(1：远程，2：中程), information_source_type: 信息来源类型（0：L预警机，1:S预警机，2：战机，3：被动侦测） step_count: step计数, op_count: 观测点计数, del_ind: 删除指示(默认false)}]\n    :return: valid：打击动作是否有效(False，无效；True，有效)\n    '''\n\n    # print(missile_type,'\\n')\n    # print(fighter_context,'\\n')\n    # print(detector_context_list,'\\n')\n    # print(enemy_status,'\\n')\n    # print(strike_list)\n    # b = a\n\n    # 判断是否超出打击距离\n    fighter_pos_x = fighter_context['pos_x']\n    fighter_pos_y = fighter_context['pos_y']\n    enemy_pos_x   = enemy_status['pos_x']\n    enemy_pos_y   = enemy_status['pos_y']\n    distance = position_calc.get_distance(fighter_pos_x, fighter_pos_y, enemy_pos_x, enemy_pos_y)\n    if missile_type == config.get_s_missile_type():\n        effective_strike_distance = config.get_s_missile_dis()\n    if missile_type == config.get_l_missile_type():\n        effective_strike_distance = config.get_l_missile_dis()\n    if distance > effective_strike_distance:\n        return False\n\n    # 判断enemy是否存活\n    if not enemy_status['alive']:\n        return False\n\n    sublist_of_strike = {}\n    sublist_of_strike['attacker_id'] = fighter_context['id']\n    sublist_of_strike['target_id']   = enemy_status['id']\n    sublist_of_strike['missile_type'] = missile_type\n\n    if fighter_context['j_enable']:\n        for jammed in fighter_context['j_receive_list']:\n            if enemy_status['id'] == jammed['id']:\n                sublist_of_strike['information_source_type'] = config.get_hit_detection_source_passive()\n\n    for detector in detector_context_list:\n        if detector['alive'] and detector['radar_enable']:\n            for radar in detector['radar_visible_list']:\n                if enemy_status['id'] == radar['id']:\n                    sublist_of_strike['information_source_type'] = detector['r_band']\n\t\n    if fighter_context['radar_enable']:\n        for radar in fighter_context['radar_visible_list']:\n            if enemy_status['id'] == radar['id']:\n                sublist_of_strike['information_source_type'] = fighter_context['r_band']\n    if not 'information_source_type' in sublist_of_strike:\n        print(\"cannot found information source type\")\n        print(fighter_context)\n        print(detector_context_list)\n        print(enemy_status)\n        return False\n\n    sublist_of_strike['step_count'] = 0\n    sublist_of_strike['op_count'] = 0\n    sublist_of_strike['del_ind'] = False\n    strike_list.append(sublist_of_strike.copy())\n\n    return True\n\ndef strike_judge(strike_context, fighter_radar_visible_list, random_obj):\n    '''\n    在途打击处理，更新打击上下文内容，判断打击成败\n    规则：\n    1. 如果是远程导弹，10个step后按概率判断是否打中\n    2. 如果是近程导弹，4个step后按概率判断是否打中\n    3. 杀伤概率（信息来源杀伤概率×观测点杀伤概率×导弹杀伤概率）\n    修正版--杀伤概率（信息来源杀伤概率x导弹杀伤概率-op_countx0.01)\n    :param strike_context:打击列表中项目\n    :param fighter_radar_visible_list:攻击者雷达可见目标列表\n    :param random_obj:随机数对象\n    :return: strike_success, 1，打击成功，-1，打击失败，0，打击依然在途\n    '''\n    # print(strike_context)\n    # print(fighter_radar_visible_list)\n    # b = a\n    strike_context['step_count'] += 1\n    for radar in fighter_radar_visible_list:\n        if strike_context['target_id'] == radar['id']:\n            strike_context['op_count'] += 1\n\n    try:\n        missile_type = strike_context['missile_type']\n        information_source_type = strike_context['information_source_type']\n        op_count = strike_context['op_count']\n        step_count = strike_context['step_count']\n    except KeyError:\n        print('strike_context: ', strike_context)\n\n    strike_success = 0\n    kill_prob = 0\n    if missile_type == config.get_l_missile_type() and step_count >= 10:\n        # kill_prob = config.get_detection_hit_probability(information_source_type) * config.get_l_missile_hit_probability() - \\\n        # (config.get_l_missile_op_req() - strike_context['op_count']) * 0.01\n        kill_prob = (0.06 + 0.01 * op_count) * (config.get_detection_hit_probability(information_source_type)/config.get_detection_hit_probability(0))\n        strike = get_strike_result_by_ratio(kill_prob, random_obj)\n        if strike:\n            strike_success = 1\n        else:\n            strike_success = -1\n\n    if missile_type == config.get_s_missile_type() and step_count >= 4:\n\t\t# kill_prob = config.get_detection_hit_probability(information_source_type) * config.get_s_missile_hit_probability() - \\\n\t\t# (config.get_s_missile_op_req() - strike_context['op_count']) * 0.01\n        kill_prob = (0.14 + 0.01 * op_count) * (config.get_detection_hit_probability(information_source_type)/config.get_detection_hit_probability(0))\n        strike = get_strike_result_by_ratio(kill_prob, random_obj)\n        if strike:\n            strike_success = 1\n        else:\n            strike_success = -1\n\n    return strike_success\n\n\n\n\n# TODO: uncomplete\ndef strike_judge_no_delay(strike_context, random_obj):\n    print(\"strike_judge_no_delay\")\n    return\n\n\n"
  },
  {
    "path": "fight.py",
    "content": "#! /usr/bin/env python\n# -*- coding: utf-8 -*-\n\"\"\"\n@author: Gao Fang\n@contact: gaofang@cetc.com.cn\n@software: PyCharm\n@file: fight.py\n@time: 2018/3/9 0009 16:41\n@desc: execution battle between two agents\n\"\"\"\nimport argparse\nimport importlib\nimport os\nimport sys\nimport time\nimport pygame\nfrom interface import Environment\n\nsys.path.append(\"/home/boris/MaCA/environment\")\n\nif __name__ == \"__main__\":\n    parser = argparse.ArgumentParser()\n    parser.add_argument(\"--map\", type=str, default=\"1000_1000_fighter10v10\", help='map name, only name, not file path')\n    parser.add_argument(\"--agent1\", type=str, default=\"fix_rule\", help='agent 1 name, only name, not path')\n    parser.add_argument(\"--agent2\", type=str, default=\"fix_rule\", help='agent 2 name, only name, not path')\n    parser.add_argument(\"--round\", type=int, default=1, help='play rounds')\n    parser.add_argument(\"--fps\", type=float, default=0, help='display fps')\n    parser.add_argument(\"--max_step\", type=int, default=5000, help='max step in a round')\n    parser.add_argument(\"--random_pos\", action=\"store_true\", help='if the initial positions are random or fix')\n    parser.add_argument(\"--log\", action=\"store_true\", help='saving log')\n    parser.add_argument(\"--log_path\", type=str, default=\"default_log\", help='log folder name')\n    args = parser.parse_args()\n\n    print('Map:', args.map)\n    print('Side1 agent:', args.agent1)\n    print('Side2 agent:', args.agent2)\n    print('Round number:', args.round)\n\n    side1_win_times = 0\n    side2_win_times = 0\n    draw_times = 0\n\n    # file path constructing\n    map_path = 'maps/' + args.map + '.map'\n    agent1_path = 'agent/' + args.agent1 + '/agent.py'\n    agent2_path = 'agent/' + args.agent2 + '/agent.py'\n    agent1_import_path = 'agent.' + args.agent1 + '.agent'\n    agent2_import_path = 'agent.' + args.agent2 + '.agent'\n\n    if not os.path.exists(map_path):\n        print('Error: map file not exist!')\n        exit(1)\n    if not os.path.exists(agent1_path):\n        print('Error: agent1 file not exist!')\n        exit(1)\n    if not os.path.exists(agent2_path):\n        print('Error: agent2 file not exist!')\n        exit(1)\n    # delay calc\n    if args.fps == 0:\n        step_delay = 0\n    else:\n        step_delay = 1 / args.fps\n\n    # laad agents\n    agent1_module = importlib.import_module(agent1_import_path)\n    agent2_module = importlib.import_module(agent2_import_path)\n    agent1 = agent1_module.Agent()\n    agent2 = agent2_module.Agent()\n    agent1_obs_ind = agent1.get_obs_ind()\n    agent2_obs_ind = agent2.get_obs_ind()\n    # environment initiation\n    if args.log:\n        if args.log_path == 'default_log':\n            log_flag = args.agent1 + '_vs_' + args.agent2\n        else:\n            log_flag = args.log_path\n    else:\n        log_flag = False\n    env = Environment(map_path, agent1_obs_ind, agent2_obs_ind, max_step=args.max_step, render=True,\n                      random_pos=args.random_pos, log=log_flag)\n    # get map info\n    size_x, size_y = env.get_map_size()\n    side1_detector_num, side1_fighter_num, side2_detector_num, side2_fighter_num = env.get_unit_num()\n    agent1.set_map_info(size_x, size_y, side1_detector_num, side1_fighter_num)\n    agent2.set_map_info(size_x, size_y, side2_detector_num, side2_fighter_num)\n\n    # execution\n    step_cnt = 0\n    round_cnt = 0\n    agent1_crash_list = []\n    agent2_crash_list = []\n    # input(\"Press the <ENTER> key to continue...\")\n    for x in range(args.round):\n        side1_total_reward = 0\n        side2_total_reward = 0\n        if x != 0:\n            env.reset()\n        step_cnt = 0\n        round_cnt += 1\n        while True:\n            time.sleep(step_delay)\n            step_cnt += 1\n            # get obs\n            side1_obs_dict, side2_obs_dict = env.get_obs()\n            # get action\n            try:\n                side1_detector_action, side1_fighter_action = agent1.get_action(side1_obs_dict, step_cnt)\n            except:\n                env.set_surrender(0)\n                # reward\n                o_detector_reward, o_fighter_reward, o_game_reward, e_detector_reward, e_fighter_reward, e_game_reward = env.get_reward()\n                agent1_crash_list.append(round_cnt)\n                print('Side 1 crashed!')\n                side1_obs_raw, side2_obs_raw = env.get_obs_raw()\n                side1_detector_obs_raw_list = side1_obs_raw['detector_obs_list']\n                side1_fighter_obs_raw_list = side1_obs_raw['fighter_obs_list']\n                side1_joint_obs_raw_dict = side1_obs_raw['joint_obs_dict']\n                side2_detector_obs_raw_list = side2_obs_raw['detector_obs_list']\n                side2_fighter_obs_raw_list = side2_obs_raw['fighter_obs_list']\n                side2_joint_obs_raw_dict = side2_obs_raw['joint_obs_dict']\n            else:\n                try:\n                    side2_detector_action, side2_fighter_action = agent2.get_action(side2_obs_dict, step_cnt)\n                except:\n                    env.set_surrender(1)\n                    # reward\n                    o_detector_reward, o_fighter_reward, o_game_reward, e_detector_reward, e_fighter_reward, e_game_reward = env.get_reward()\n                    agent2_crash_list.append(round_cnt)\n                    print('Side 2 crashed!')\n                    side1_obs_raw, side2_obs_raw = env.get_obs_raw()\n                    side1_detector_obs_raw_list = side1_obs_raw['detector_obs_list']\n                    side1_fighter_obs_raw_list = side1_obs_raw['fighter_obs_list']\n                    side1_joint_obs_raw_dict = side1_obs_raw['joint_obs_dict']\n                    side2_detector_obs_raw_list = side2_obs_raw['detector_obs_list']\n                    side2_fighter_obs_raw_list = side2_obs_raw['fighter_obs_list']\n                    side2_joint_obs_raw_dict = side2_obs_raw['joint_obs_dict']\n                else:\n                    # execution\n                    env.step(side1_detector_action, side1_fighter_action, side2_detector_action, side2_fighter_action)\n                    # obs\n                    side1_obs_raw, side2_obs_raw = env.get_obs_raw()\n                    side1_detector_obs_raw_list = side1_obs_raw['detector_obs_list']\n                    side1_fighter_obs_raw_list = side1_obs_raw['fighter_obs_list']\n                    side1_joint_obs_raw_dict = side1_obs_raw['joint_obs_dict']\n                    side2_detector_obs_raw_list = side2_obs_raw['detector_obs_list']\n                    side2_fighter_obs_raw_list = side2_obs_raw['fighter_obs_list']\n                    side2_joint_obs_raw_dict = side2_obs_raw['joint_obs_dict']\n                    # reward\n                    o_detector_reward, o_fighter_reward, o_game_reward, e_detector_reward, e_fighter_reward, e_game_reward = env.get_reward()\n\n                    side1_step_reward = 0\n                    side2_step_reward = 0\n                    for y in range(side1_detector_num):\n                        side1_step_reward += o_detector_reward[y]\n                    for y in range(side1_fighter_num):\n                        side1_step_reward += o_fighter_reward[y]\n                    for y in range(side2_detector_num):\n                        side2_step_reward += e_detector_reward[y]\n                    for y in range(side2_fighter_num):\n                        side2_step_reward += e_fighter_reward[y]\n                    side1_total_reward += side1_step_reward\n                    side2_total_reward += side2_step_reward\n            # print('Round %d, Step %d:' % (round_cnt, step_cnt))\n            # print('Side 1 reward: %d, Side 2 reward: %d' % (side1_step_reward, side2_step_reward))\n            if env.get_done():\n                print('Round %d done at step %d!' % (round_cnt, step_cnt))\n                if o_game_reward > e_game_reward:\n                    print('Side 1 WIN!!!')\n                    side1_win_times += 1\n                elif o_game_reward < e_game_reward:\n                    print('Side 2 WIN!!!')\n                    side2_win_times += 1\n                else:\n                    print('DRAW!!!')\n                    draw_times += 1\n                print('Side 1 total step reward: %d, Side 2 total step reward: %d' % (side1_total_reward, side2_total_reward))\n                print('Side 1 round reward: %d, Side 2 round reward: %d' % (o_game_reward, e_game_reward))\n                side1_detector_alive_num = 0\n                side1_fighter_alive_num = 0\n                side2_detector_alive_num = 0\n                side2_fighter_alive_num = 0\n                side1_missile_left = 0\n                side2_missile_left = 0\n                for y in range(side1_detector_num):\n                    if side1_detector_obs_raw_list[y]['alive']:\n                        side1_detector_alive_num += 1\n                for y in range(side1_fighter_num):\n                    if side1_fighter_obs_raw_list[y]['alive']:\n                        side1_fighter_alive_num += 1\n                        side1_missile_left += side1_fighter_obs_raw_list[y]['l_missile_left']\n                        side1_missile_left += side1_fighter_obs_raw_list[y]['s_missile_left']\n                for y in range(side2_detector_num):\n                    if side2_detector_obs_raw_list[y]['alive']:\n                        side2_detector_alive_num += 1\n                for y in range(side2_fighter_num):\n                    if side2_fighter_obs_raw_list[y]['alive']:\n                        side2_fighter_alive_num += 1\n                        side2_missile_left += side2_fighter_obs_raw_list[y]['l_missile_left']\n                        side2_missile_left += side2_fighter_obs_raw_list[y]['s_missile_left']\n                print('Side 1: alive detector: %d, alive fighter: %d, missile left: %d' % (side1_detector_alive_num, side1_fighter_alive_num, side1_missile_left))\n                print('Side 2: alive detector: %d, alive fighter: %d, missile left: %d' % (side2_detector_alive_num, side2_fighter_alive_num, side2_missile_left))\n                time.sleep(2)\n                break\n\n    print('FIGHT RESULT:')\n    print('Total rounds: %d. Side1 win: %d. Side2 win: %d. Draw: %d' % (round_cnt, side1_win_times, side2_win_times, draw_times))\n    print('Side 1 win rate: %.1f%%, Side 2 win rate: %.1f%%.' % (side1_win_times/round_cnt*100, side2_win_times/round_cnt*100))\n    if len(agent1_crash_list) != 0:\n        print('Side 1 crashed %d times:' % len(agent1_crash_list))\n        print(agent1_crash_list)\n    if len(agent2_crash_list) != 0:\n        print('Side 2 crashed %d times:' % len(agent2_crash_list))\n        print(agent2_crash_list)\n    # input(\"Press the <ENTER> key to continue...\")\n"
  },
  {
    "path": "fight_mp.py",
    "content": "#! /usr/bin/env python\n# -*- coding: utf-8 -*-\n\"\"\"\n@author: Gao Fang\n@contact: gaofang@cetc.com.cn\n@software: PyCharm\n@file: fight.py\n@time: 2018/3/9 0009 16:41\n@desc: execution battle between two agents\n\"\"\"\nimport argparse\nimport os\nimport time\nfrom interface import Environment\nfrom common.agent_process import AgentCtrl\n\n\nif __name__ == \"__main__\":\n    parser = argparse.ArgumentParser()\n    parser.add_argument(\"--map\", type=str, default=\"1000_1000_2_10_vs_2_10\", help='map name, only name, not file path')\n    parser.add_argument(\"--agent1\", type=str, default=\"fix_rule\", help='agent 1 name, only name, not path')\n    parser.add_argument(\"--agent2\", type=str, default=\"fix_rule\", help='agent 2 name, only name, not path')\n    parser.add_argument(\"--round\", type=int, default=1, help='play rounds')\n    parser.add_argument(\"--fps\", type=float, default=0, help='display fps')\n    parser.add_argument(\"--max_step\", type=int, default=5000, help='max step in a round')\n    parser.add_argument(\"--random_pos\", action=\"store_true\", help='if the initial positions are random or fix')\n    parser.add_argument(\"--log\", action=\"store_true\", help='saving log')\n    parser.add_argument(\"--log_path\", type=str, default=\"default_log\", help='log folder name')\n    args = parser.parse_args()\n\n    print('Map:', args.map)\n    print('Side1 agent:', args.agent1)\n    print('Side2 agent:', args.agent2)\n    print('Round number:', args.round)\n\n    side1_win_times = 0\n    side2_win_times = 0\n    draw_times = 0\n\n    # file path constructing\n    map_path = 'maps/' + args.map + '.map'\n    agent1_path = 'agent/' + args.agent1 + '/agent.py'\n    agent2_path = 'agent/' + args.agent2 + '/agent.py'\n\n    if not os.path.exists(map_path):\n        print('Error: map file not exist!')\n        exit(-1)\n    if not os.path.exists(agent1_path):\n        print('Error: agent1 file not exist!')\n        exit(-1)\n    if not os.path.exists(agent2_path):\n        print('Error: agent2 file not exist!')\n        exit(-1)\n    # delay calc\n    if args.fps == 0:\n        step_delay = 0\n    else:\n        step_delay = 1 / args.fps\n\n    # environment initiation\n    if args.log:\n        if args.log_path == 'default_log':\n            log_flag = args.agent1 + '_vs_' + args.agent2\n        else:\n            log_flag = args.log_path\n    else:\n        log_flag = False\n    env = Environment(map_path, 'raw', 'raw', max_step=args.max_step, render=True,\n                      random_pos=args.random_pos, log=log_flag)\n    # get map info\n    size_x, size_y = env.get_map_size()\n    side1_detector_num, side1_fighter_num, side2_detector_num, side2_fighter_num = env.get_unit_num()\n\n    # create agent\n    agent1 = AgentCtrl(args.agent1, size_x, size_y, side1_detector_num, side1_fighter_num)\n    agent2 = AgentCtrl(args.agent2, size_x, size_y, side2_detector_num, side2_fighter_num)\n    if not agent1.agent_init():\n        print('ERROR: Agent1 init failed!')\n        agent1.terminate()\n        agent2.terminate()\n        exit(-1)\n    else:\n        print('Agent1 init success!')\n    if not agent2.agent_init():\n        print('ERROR: Agent2 init failed!')\n        agent1.terminate()\n        agent2.terminate()\n        exit(-1)\n    else:\n        print('Agent2 init success!')\n\n    # execution\n    step_cnt = 0\n    round_cnt = 0\n    agent1_crash_list = []\n    agent2_crash_list = []\n    agent1_timeout_list = []\n    agent2_timeout_list = []\n    # input(\"Press the <ENTER> key to continue...\")\n    for x in range(args.round):\n        side1_total_reward = 0\n        side2_total_reward = 0\n        if x != 0:\n            env.reset()\n        step_cnt = 0\n        round_cnt += 1\n        while True:\n            time.sleep(step_delay)\n            step_cnt += 1\n            # get obs\n            side1_obs_dict, side2_obs_dict = env.get_obs()\n            # get action\n            agent1_action, agent1_result = agent1.get_action(side1_obs_dict, step_cnt)\n            if agent1_result == 0:\n                side1_detector_action = agent1_action['detector_action']\n                side1_fighter_action = agent1_action['fighter_action']\n            elif agent1_result == 1:\n                agent1_crash_list.append(round_cnt)\n                print('agent1 crashed!')\n            elif agent1_result == 2:\n                agent1_timeout_list.append(round_cnt)\n                print('agent1 timeout!')\n            agent2_action, agent2_result = agent2.get_action(side2_obs_dict, step_cnt)\n            if agent2_result == 0:\n                side2_detector_action = agent2_action['detector_action']\n                side2_fighter_action = agent2_action['fighter_action']\n            elif agent2_result == 1:\n                agent2_crash_list.append(round_cnt)\n                print('agent2 crashed!')\n            elif agent2_result == 2:\n                agent2_timeout_list.append(round_cnt)\n                print('agent2 timeout!')\n\n            # execution\n            if agent1_result == 0 and agent2_result == 0:\n                env.step(side1_detector_action, side1_fighter_action, side2_detector_action, side2_fighter_action)\n            elif agent1_result != 0 and agent2_result != 0:\n                env.set_surrender(2)\n            elif agent1_result != 0:\n                env.set_surrender(0)\n            else:\n                env.set_surrender(1)\n            # obs\n            side1_obs_raw, side2_obs_raw = env.get_obs_raw()\n            side1_detector_obs_raw_list = side1_obs_raw['detector_obs_list']\n            side1_fighter_obs_raw_list = side1_obs_raw['fighter_obs_list']\n            side1_joint_obs_raw_dict = side1_obs_raw['joint_obs_dict']\n            side2_detector_obs_raw_list = side2_obs_raw['detector_obs_list']\n            side2_fighter_obs_raw_list = side2_obs_raw['fighter_obs_list']\n            side2_joint_obs_raw_dict = side2_obs_raw['joint_obs_dict']\n            # reward\n            o_detector_reward, o_fighter_reward, o_game_reward, e_detector_reward, e_fighter_reward, e_game_reward = env.get_reward()\n\n            side1_step_reward = 0\n            side2_step_reward = 0\n            for y in range(side1_detector_num):\n                side1_step_reward += o_detector_reward[y]\n            for y in range(side1_fighter_num):\n                side1_step_reward += o_fighter_reward[y]\n            for y in range(side2_detector_num):\n                side2_step_reward += e_detector_reward[y]\n            for y in range(side2_fighter_num):\n                side2_step_reward += e_fighter_reward[y]\n            side1_total_reward += side1_step_reward\n            side2_total_reward += side2_step_reward\n            # print('Round %d, Step %d:' % (round_cnt, step_cnt))\n            # print('Side 1 reward: %d, Side 2 reward: %d' % (side1_step_reward, side2_step_reward))\n            if env.get_done():\n                print('Round %d done at step %d!' % (round_cnt, step_cnt))\n                if o_game_reward > e_game_reward:\n                    print('Side 1 WIN!!!')\n                    side1_win_times += 1\n                elif o_game_reward < e_game_reward:\n                    print('Side 2 WIN!!!')\n                    side2_win_times += 1\n                else:\n                    print('DRAW!!!')\n                    draw_times += 1\n                print('Side 1 total step reward: %d, Side 2 total step reward: %d' % (side1_total_reward, side2_total_reward))\n                print('Side 1 round reward: %d, Side 2 round reward: %d' % (o_game_reward, e_game_reward))\n                side1_detector_alive_num = 0\n                side1_fighter_alive_num = 0\n                side2_detector_alive_num = 0\n                side2_fighter_alive_num = 0\n                for y in range(side1_detector_num):\n                    if side1_detector_obs_raw_list[y]['alive']:\n                        side1_detector_alive_num += 1\n                for y in range(side1_fighter_num):\n                    if side1_fighter_obs_raw_list[y]['alive']:\n                        side1_fighter_alive_num += 1\n                for y in range(side2_detector_num):\n                    if side2_detector_obs_raw_list[y]['alive']:\n                        side2_detector_alive_num += 1\n                for y in range(side2_fighter_num):\n                    if side2_fighter_obs_raw_list[y]['alive']:\n                        side2_fighter_alive_num += 1\n                print('Side 1 alive detector: %d, Side 1 alive fighter: %d, Side 2 alive detector: %d, Side 2 alive fighter: %d' % (side1_detector_alive_num, side1_fighter_alive_num, side2_detector_alive_num, side2_fighter_alive_num))\n                time.sleep(2)\n                break\n    agent1.terminate()\n    agent2.terminate()\n    print('FIGHT RESULT:')\n    print('Total rounds: %d. Side1 win: %d. Side2 win: %d. Draw: %d' % (round_cnt, side1_win_times, side2_win_times, draw_times))\n    print('Side 1 win rate: %.1f%%, Side 2 win rate: %.1f%%.' % (side1_win_times/round_cnt*100, side2_win_times/round_cnt*100))\n    if len(agent1_crash_list) != 0:\n        print('Side 1 crashed %d times:' % len(agent1_crash_list))\n        print(agent1_crash_list)\n    if len(agent2_crash_list) != 0:\n        print('Side 2 crashed %d times:' % len(agent2_crash_list))\n        print(agent2_crash_list)\n    if len(agent1_timeout_list) != 0:\n        print('Side 1 timeout %d times:' % len(agent1_timeout_list))\n        print(agent1_timeout_list)\n    if len(agent2_timeout_list) != 0:\n        print('Side 2 timeout %d times:' % len(agent2_timeout_list))\n        print(agent2_timeout_list)\n    input(\"Press the <ENTER> key to continue...\")\n"
  },
  {
    "path": "log/readme",
    "content": ""
  },
  {
    "path": "model/README",
    "content": ""
  },
  {
    "path": "obs_construct/airc_homo_rule/construct.py",
    "content": "import numpy as np\nimport copy\nimport utility as ut\n\n\nclass ObsConstruct:\n    def __init__(self, size_x, size_y, detector_num, fighter_num):\n        self.battlefield_size_x = size_x\n        self.battlefield_size_y = size_y\n        self.detector_num = detector_num\n        self.fighter_num = fighter_num\n        self.img_obs_reduce_ratio = 10\n        self.obs_dict = {}\n\n    def obs_construct(self, obs_raw_dict):\n        # self.obs_dict = copy.deepcopy(obs_raw_dict)\n        for i in range(self.fighter_num):\n            self.obs_dict[i] = obs_raw_dict['fighter_obs_list'][i]\n            self.obs_dict['strike_list'] = obs_raw_dict['joint_obs_dict']['strike_list']\n            # continue if the fighter is dead\n            if not self.obs_dict[i]['alive']:\n                continue\n            detected_enemy_list = []\n            myself_pos_x = self.obs_dict[i]['pos_x']\n            myself_pos_y = self.obs_dict[i]['pos_y']\n            for j in range(len(self.obs_dict[i]['r_visible_list'])):\n                enemy_dict = self.obs_dict[i]['r_visible_list'][j]\n                enemy_pos_x = enemy_dict['pos_x']\n                enemy_pos_y = enemy_dict['pos_y']\n                enemy_dict['distance'] = ut.distance(myself_pos_x, myself_pos_y, enemy_pos_x, enemy_pos_y)\n                enemy_dict['angle'] = ut.angle(myself_pos_x, myself_pos_y, enemy_pos_x, enemy_pos_y)\n                detected_enemy_list.append(enemy_dict)\n            \n            ####commented by liyuan. \n            '''\n            for j in range(len(self.obs_dict[i]['j_recv_list'])):\n                enemy_dict = self.obs_dict[i]['j_recv_list'][j]\n                enemy_pos_x = enemy_dict['pos_x']\n                enemy_pos_y = enemy_dict['pos_y']\n                enemy_dict['distance'] = ut.distance(myself_pos_x, myself_pos_y, enemy_pos_x, enemy_pos_y)\n                enemy_dict['angle'] = ut.angle(myself_pos_x, myself_pos_y, enemy_pos_x, enemy_pos_y)\n                detected_enemy_list.append(enemy_dict)\n            '''\n            if len(detected_enemy_list) > 0:\n                detected_enemy_list = sorted(detected_enemy_list, key=lambda k: k['distance'])\n                self.obs_dict[i]['target_list'] = detected_enemy_list\n        return self.obs_dict\n\n    @staticmethod\n    def distance_key(ele):\n        return ele['distance']\n\n    def obs_construct_old(self, obs_raw_dict):\n        obs_dict = {}\n        detector_obs_list = []\n        fighter_obs_list = []\n        detector_data_obs_list = obs_raw_dict['detector_obs_list']\n        fighter_data_obs_list = obs_raw_dict['fighter_obs_list']\n        joint_data_obs_dict = obs_raw_dict['joint_obs_dict']\n        detector_img, fighter_img, joint_img = self.__get_img_obs(detector_data_obs_list, fighter_data_obs_list,\n                                                                  joint_data_obs_dict)\n        detector_data, fighter_data = self.__get_data_obs(detector_data_obs_list, fighter_data_obs_list,\n                                                          joint_data_obs_dict)\n        alive_status = self.__get_alive_status(detector_data_obs_list, fighter_data_obs_list)\n        # o方\n        # 预警机\n        for x in range(self.detector_num):\n            img_context = detector_img[x, :, :, :]\n            img_context = np.concatenate((img_context, joint_img[0, :, :, :]), axis=2)\n            data_context = detector_data[x, :]\n            detector_obs_list.append({'info': copy.deepcopy(data_context), 'screen': copy.deepcopy(img_context),\n                                      'alive': alive_status[x][0]})\n        # 战机\n        for x in range(self.fighter_num):\n            img_context = fighter_img[x, :, :, :]\n            img_context = np.concatenate((img_context, joint_img[0, :, :, :]), axis=2)\n            data_context = fighter_data[x, :]\n            fighter_obs_list.append({'info': copy.deepcopy(data_context), 'screen': copy.deepcopy(img_context),\n                                     'alive': alive_status[x + self.detector_num][0]})\n        obs_dict['detector'] = detector_obs_list\n        obs_dict['fighter'] = fighter_obs_list\n        return obs_dict\n\n    def __get_alive_status(self, detector_data_obs_list, fighter_data_obs_list):\n        alive_status = np.full((self.detector_num + self.fighter_num, 1), True)\n        for x in range(self.detector_num):\n            if not detector_data_obs_list[x]['alive']:\n                alive_status[x][0] = False\n        for x in range(self.fighter_num):\n            if not fighter_data_obs_list[x]['alive']:\n                alive_status[x + self.detector_num][0] = False\n        return alive_status\n\n    def __get_img_obs(self, detector_data_obs_list, fighter_data_obs_list, joint_data_obs_dict):\n        img_obs_size_x = int(self.battlefield_size_y / self.img_obs_reduce_ratio)\n        img_obs_size_y = int(self.battlefield_size_x / self.img_obs_reduce_ratio)\n        # 个体img：所有己方单位位置\n        detector_img = np.full((self.detector_num, img_obs_size_x, img_obs_size_y, 3), 0, dtype=np.int32)\n        fighter_img = np.full((self.fighter_num, img_obs_size_x, img_obs_size_y, 3), 0, dtype=np.int32)\n        # 全局img：所有可见敌方单元位置和类型\n        joint_img = np.full((1, img_obs_size_x, img_obs_size_y, 2), 0, dtype=np.int32)\n\n        # set all self unit pos, detector: 1, fighter: 2, self: 255\n        tmp_pos_obs = np.full((img_obs_size_x, img_obs_size_y), 0, dtype=np.int32)\n        for x in range(self.detector_num):\n            if not detector_data_obs_list[x]['alive']:\n                continue\n            self.__set_value_in_img(tmp_pos_obs, int(detector_data_obs_list[x]['pos_y'] / self.img_obs_reduce_ratio),\n                                    int(detector_data_obs_list[x]['pos_x'] / self.img_obs_reduce_ratio), 1)\n        for x in range(self.fighter_num):\n            if not fighter_data_obs_list[x]['alive']:\n                continue\n            self.__set_value_in_img(tmp_pos_obs, int(fighter_data_obs_list[x]['pos_y'] / self.img_obs_reduce_ratio),\n                                    int(fighter_data_obs_list[x]['pos_x'] / self.img_obs_reduce_ratio), 2)\n        # Detector obs\n        for x in range(self.detector_num):\n            # if not alive, skip\n            if not detector_data_obs_list[x]['alive']:\n                continue\n            # self detection target. target: id\n            for y in range(len(detector_data_obs_list[x]['r_visible_list'])):\n                self.__set_value_in_img(detector_img[x, :, :, 0],\n                                        int(detector_data_obs_list[x]['r_visible_list'][y][\n                                                'pos_y'] / self.img_obs_reduce_ratio),\n                                        int(detector_data_obs_list[x]['r_visible_list'][y][\n                                                'pos_x'] / self.img_obs_reduce_ratio),\n                                        detector_data_obs_list[x]['r_visible_list'][y]['id'])\n            # self detection target. target: type (detector: 1, fighter 2)\n            for y in range(len(detector_data_obs_list[x]['r_visible_list'])):\n                self.__set_value_in_img(detector_img[x, :, :, 1],\n                                        int(detector_data_obs_list[x]['r_visible_list'][y][\n                                                'pos_y'] / self.img_obs_reduce_ratio),\n                                        int(detector_data_obs_list[x]['r_visible_list'][y][\n                                                'pos_x'] / self.img_obs_reduce_ratio),\n                                        detector_data_obs_list[x]['r_visible_list'][y]['type'] + 1)\n            # friendly pos. self: 255, other: type (detector: 1, fighter 2)\n            detector_img[x, :, :, 2] = copy.deepcopy(tmp_pos_obs)\n            self.__set_value_in_img(detector_img[x, :, :, 2],\n                                    int(detector_data_obs_list[x]['pos_y'] / self.img_obs_reduce_ratio),\n                                    int(detector_data_obs_list[x]['pos_x'] / self.img_obs_reduce_ratio), 255)\n\n        # Fighter obs\n        for x in range(self.fighter_num):\n            # if not alive, skip\n            if not fighter_data_obs_list[x]['alive']:\n                continue\n            # self detection target. target: id\n            for y in range(len(fighter_data_obs_list[x]['r_visible_list'])):\n                self.__set_value_in_img(fighter_img[x, :, :, 0],\n                                        int(fighter_data_obs_list[x]['r_visible_list'][y][\n                                                'pos_y'] / self.img_obs_reduce_ratio),\n                                        int(fighter_data_obs_list[x]['r_visible_list'][y][\n                                                'pos_x'] / self.img_obs_reduce_ratio),\n                                        fighter_data_obs_list[x]['r_visible_list'][y]['id'])\n            # self detection target. target: type (detector: 1, fighter 2)\n            for y in range(len(fighter_data_obs_list[x]['r_visible_list'])):\n                self.__set_value_in_img(fighter_img[x, :, :, 1],\n                                        int(fighter_data_obs_list[x]['r_visible_list'][y][\n                                                'pos_y'] / self.img_obs_reduce_ratio),\n                                        int(fighter_data_obs_list[x]['r_visible_list'][y][\n                                                'pos_x'] / self.img_obs_reduce_ratio),\n                                        fighter_data_obs_list[x]['r_visible_list'][y]['type'] + 1)\n            # friendly pos. self: 255, other: type (detector: 1, fighter 2)\n            fighter_img[x, :, :, 2] = copy.deepcopy(tmp_pos_obs)\n            self.__set_value_in_img(fighter_img[x, :, :, 2],\n                                    int(fighter_data_obs_list[x]['pos_y'] / self.img_obs_reduce_ratio),\n                                    int(fighter_data_obs_list[x]['pos_x'] / self.img_obs_reduce_ratio), 255)\n\n        # Global obs\n        # Passive detection\n        for x in range(len(joint_data_obs_dict['passive_detection_enemy_list'])):\n            # Channel: detected enemy pos. value=enemy id\n            self.__set_value_in_img(joint_img[0, :, :, 0], int(\n                joint_data_obs_dict['passive_detection_enemy_list'][x]['pos_y'] / self.img_obs_reduce_ratio),\n                                    int(joint_data_obs_dict['passive_detection_enemy_list'][x][\n                                            'pos_x'] / self.img_obs_reduce_ratio),\n                                    joint_data_obs_dict['passive_detection_enemy_list'][x]['id'])\n            # Channe2: detected enemy pos. value=enemy type\n            self.__set_value_in_img(joint_img[0, :, :, 1], int(\n                joint_data_obs_dict['passive_detection_enemy_list'][x]['pos_y'] / self.img_obs_reduce_ratio),\n                                    int(joint_data_obs_dict['passive_detection_enemy_list'][x][\n                                            'pos_x'] / self.img_obs_reduce_ratio),\n                                    joint_data_obs_dict['passive_detection_enemy_list'][x]['type'] + 1)\n        # detector\n        for x in range(self.detector_num):\n            for y in range(len(detector_data_obs_list[x]['r_visible_list'])):\n                # Channel: detected enemy pos. value=enemy id\n                self.__set_value_in_img(joint_img[0, :, :, 0],\n                                        int(detector_data_obs_list[x]['r_visible_list'][y][\n                                                'pos_y'] / self.img_obs_reduce_ratio),\n                                        int(detector_data_obs_list[x]['r_visible_list'][y][\n                                                'pos_x'] / self.img_obs_reduce_ratio),\n                                        detector_data_obs_list[x]['r_visible_list'][y]['id'])\n                # Channe2: detected enemy pos. value=enemy type\n                self.__set_value_in_img(joint_img[0, :, :, 1],\n                                        int(detector_data_obs_list[x]['r_visible_list'][y][\n                                                'pos_y'] / self.img_obs_reduce_ratio),\n                                        int(detector_data_obs_list[x]['r_visible_list'][y][\n                                                'pos_x'] / self.img_obs_reduce_ratio),\n                                        detector_data_obs_list[x]['r_visible_list'][y]['type'] + 1)\n        # fighter\n        for x in range(self.fighter_num):\n            for y in range(len(fighter_data_obs_list[x]['r_visible_list'])):\n                # Channel: detected enemy pos. value=enemy id\n                self.__set_value_in_img(joint_img[0, :, :, 0],\n                                        int(fighter_data_obs_list[x]['r_visible_list'][y][\n                                                'pos_y'] / self.img_obs_reduce_ratio),\n                                        int(fighter_data_obs_list[x]['r_visible_list'][y][\n                                                'pos_x'] / self.img_obs_reduce_ratio),\n                                        fighter_data_obs_list[x]['r_visible_list'][y]['id'])\n                # Channe2: detected enemy pos. value=enemy type\n                self.__set_value_in_img(joint_img[0, :, :, 1],\n                                        int(fighter_data_obs_list[x]['r_visible_list'][y][\n                                                'pos_y'] / self.img_obs_reduce_ratio),\n                                        int(fighter_data_obs_list[x]['r_visible_list'][y][\n                                                'pos_x'] / self.img_obs_reduce_ratio),\n                                        fighter_data_obs_list[x]['r_visible_list'][y]['type'] + 1)\n        return detector_img, fighter_img, joint_img\n\n    def __set_value_in_img(self, img, pos_x, pos_y, value):\n        \"\"\"\n        draw 3*3 rectangle in img\n        :param img:\n        :param pos_x:\n        :param pos_y:\n        :param value:\n        :return:\n        \"\"\"\n        img_obs_size_x = int(self.battlefield_size_y / self.img_obs_reduce_ratio)\n        img_obs_size_y = int(self.battlefield_size_x / self.img_obs_reduce_ratio)\n        # 左上角\n        if pos_x == 0 and pos_y == 0:\n            img[pos_x: pos_x + 2, pos_y: pos_y + 2] = value\n        # 左下角\n        elif pos_x == 0 and pos_y == (img_obs_size_y - 1):\n            img[pos_x: pos_x + 2, pos_y - 1: pos_y + 1] = value\n        # 右上角\n        elif pos_x == (img_obs_size_x - 1) and pos_y == 0:\n            img[pos_x - 1: pos_x + 1, pos_y: pos_y + 2] = value\n        # 右下角\n        elif pos_x == (img_obs_size_x - 1) and pos_y == (img_obs_size_y - 1):\n            img[pos_x - 1: pos_x + 1, pos_y - 1: pos_y + 1] = value\n        # 左边\n        elif pos_x == 0:\n            img[pos_x: pos_x + 2, pos_y - 1: pos_y + 2] = value\n        # 右边\n        elif pos_x == img_obs_size_x - 1:\n            img[pos_x - 1: pos_x + 1, pos_y - 1: pos_y + 2] = value\n        # 上边\n        elif pos_y == 0:\n            img[pos_x - 1: pos_x + 2, pos_y: pos_y + 2] = value\n        # 下边\n        elif pos_y == img_obs_size_y - 1:\n            img[pos_x - 1: pos_x + 2, pos_y - 1: pos_y + 1] = value\n        # 其他位置\n        else:\n            img[pos_x - 1: pos_x + 2, pos_y - 1: pos_y + 2] = value\n\n    def __get_data_obs(self, detector_data_obs_list, fighter_data_obs_list, joint_data_obs_dict):\n        detector_data = np.full((self.detector_num, 1), -1, dtype=np.int32)\n        fighter_data = np.full((self.fighter_num, 3), -1, dtype=np.int32)\n\n        # Detector info\n        for x in range(self.detector_num):\n            if detector_data_obs_list[x]['alive']:\n                detector_data[x, 0] = detector_data_obs_list[x]['course']\n        # Fighter info\n        for x in range(self.fighter_num):\n            if fighter_data_obs_list[x]['alive']:\n                fighter_data[x, 0] = fighter_data_obs_list[x]['course']\n                fighter_data[x, 1] = fighter_data_obs_list[x]['l_missile_left']\n                fighter_data[x, 2] = fighter_data_obs_list[x]['s_missile_left']\n\n        return detector_data, fighter_data\n"
  },
  {
    "path": "obs_construct/simple/construct.py",
    "content": "import numpy as np\nimport copy\n\nclass ObsConstruct:\n    def __init__(self, size_x, size_y, detector_num, fighter_num):\n        self.battlefield_size_x = size_x\n        self.battlefield_size_y = size_y\n        self.detector_num = detector_num\n        self.fighter_num = fighter_num\n        self.img_obs_reduce_ratio = 10\n\n    def obs_construct(self, obs_raw_dict):\n        print(\"obs_construct\")\n        obs_dict = {}\n        detector_obs_list = []\n        fighter_obs_list = []\n        detector_data_obs_list = obs_raw_dict['detector_obs_list']\n        fighter_data_obs_list = obs_raw_dict['fighter_obs_list']\n        joint_data_obs_dict = obs_raw_dict['joint_obs_dict']\n        detector_img, fighter_img, joint_img = self.__get_img_obs(detector_data_obs_list, fighter_data_obs_list, joint_data_obs_dict)\n        detector_data, fighter_data = self.__get_data_obs(detector_data_obs_list, fighter_data_obs_list, joint_data_obs_dict)\n        alive_status = self.__get_alive_status(detector_data_obs_list, fighter_data_obs_list)\n        # o方\n        # 预警机\n        for x in range(self.detector_num):\n            img_context = detector_img[x, :, :, :]\n            img_context = np.concatenate((img_context, joint_img[0, :, :, :]), axis=2)\n            data_context = detector_data[x, :]\n            detector_obs_list.append({'info': copy.deepcopy(data_context), 'screen': copy.deepcopy(img_context),\n                             'alive': alive_status[x][0]})\n        # 战机\n        for x in range(self.fighter_num):\n            img_context = fighter_img[x, :, :, :]\n            img_context = np.concatenate((img_context, joint_img[0, :, :, :]), axis=2)\n            data_context = fighter_data[x, :]\n            fighter_obs_list.append({'info': copy.deepcopy(data_context), 'screen': copy.deepcopy(img_context),\n                             'alive': alive_status[x + self.detector_num][0]})\n        obs_dict['detector'] = detector_obs_list\n        obs_dict['fighter'] = fighter_obs_list\n        return obs_dict\n\n    def __get_alive_status(self,detector_data_obs_list,fighter_data_obs_list):\n        print(\"__get_alive_status\")\n        alive_status = np.full((self.detector_num+self.fighter_num,1),True)\n        for x in range(self.detector_num):\n            if not detector_data_obs_list[x]['alive']:\n                alive_status[x][0] = False\n        for x in range(self.fighter_num):\n            if not fighter_data_obs_list[x]['alive']:\n                alive_status[x+self.detector_num][0] = False\n        return alive_status\n\n    def __get_img_obs(self, detector_data_obs_list, fighter_data_obs_list, joint_data_obs_dict):\n        print(\"__get_img_obs\")\n        img_obs_size_x = int(self.battlefield_size_y / self.img_obs_reduce_ratio)\n        img_obs_size_y = int(self.battlefield_size_x / self.img_obs_reduce_ratio)\n        # 个体img：所有己方单位位置\n        detector_img = np.full((self.detector_num, img_obs_size_x, img_obs_size_y, 3), 0, dtype=np.int32)\n        fighter_img = np.full((self.fighter_num, img_obs_size_x, img_obs_size_y, 3), 0, dtype=np.int32)\n        # 企鹅据img：所有可见敌方单元位置和类型\n        joint_img = np.full((1, img_obs_size_x, img_obs_size_y, 2), 0, dtype=np.int32)\n\n        # set all self unit pos, detector: 1, fighter: 2, self: 255\n        tmp_pos_obs = np.full((img_obs_size_x, img_obs_size_y), 0, dtype=np.int32)\n        for x in range(self.detector_num):\n            if not detector_data_obs_list[x]['alive']:\n                continue\n            self.__set_value_in_img(tmp_pos_obs, int(detector_data_obs_list[x]['pos_y'] / self.img_obs_reduce_ratio),\n                                    int(detector_data_obs_list[x]['pos_x'] / self.img_obs_reduce_ratio), 1)\n        for x in range(self.fighter_num):\n            if not fighter_data_obs_list[x]['alive']:\n                continue\n            self.__set_value_in_img(tmp_pos_obs, int(fighter_data_obs_list[x]['pos_y'] / self.img_obs_reduce_ratio),\n                                    int(fighter_data_obs_list[x]['pos_x'] / self.img_obs_reduce_ratio), 2)\n        # Detector obs\n        for x in range(self.detector_num):\n            # if not alive, skip\n            if not detector_data_obs_list[x]['alive']:\n                continue\n            # self detection target. target: id\n            for y in range(len(detector_data_obs_list[x]['r_visible_list'])):\n                self.__set_value_in_img(detector_img[x, :, :, 0],\n                                        int(detector_data_obs_list[x]['r_visible_list'][y][\n                                                'pos_y'] / self.img_obs_reduce_ratio),\n                                        int(detector_data_obs_list[x]['r_visible_list'][y][\n                                                'pos_x'] / self.img_obs_reduce_ratio),\n                                        detector_data_obs_list[x]['r_visible_list'][y]['id'])\n            # self detection target. target: type (detector: 1, fighter 2)\n            for y in range(len(detector_data_obs_list[x]['r_visible_list'])):\n                self.__set_value_in_img(detector_img[x, :, :, 1],\n                                        int(detector_data_obs_list[x]['r_visible_list'][y][\n                                                'pos_y'] / self.img_obs_reduce_ratio),\n                                        int(detector_data_obs_list[x]['r_visible_list'][y][\n                                                'pos_x'] / self.img_obs_reduce_ratio),\n                                        detector_data_obs_list[x]['r_visible_list'][y]['type'] + 1)\n            # friendly pos. self: 255, other: type (detector: 1, fighter 2)\n            detector_img[x, :, :, 2] = copy.deepcopy(tmp_pos_obs)\n            self.__set_value_in_img(detector_img[x, :, :, 2],\n                                    int(detector_data_obs_list[x]['pos_y'] / self.img_obs_reduce_ratio),\n                                    int(detector_data_obs_list[x]['pos_x'] / self.img_obs_reduce_ratio), 255)\n\n        # Fighter obs\n        for x in range(self.fighter_num):\n            # if not alive, skip\n            if not fighter_data_obs_list[x]['alive']:\n                continue\n            # self detection target. target: id\n            for y in range(len(fighter_data_obs_list[x]['r_visible_list'])):\n                self.__set_value_in_img(fighter_img[x, :, :, 0],\n                                        int(fighter_data_obs_list[x]['r_visible_list'][y][\n                                                'pos_y'] / self.img_obs_reduce_ratio),\n                                        int(fighter_data_obs_list[x]['r_visible_list'][y][\n                                                'pos_x'] / self.img_obs_reduce_ratio),\n                                        fighter_data_obs_list[x]['r_visible_list'][y]['id'])\n            # self detection target. target: type (detector: 1, fighter 2)\n            for y in range(len(fighter_data_obs_list[x]['r_visible_list'])):\n                self.__set_value_in_img(fighter_img[x, :, :, 1],\n                                        int(fighter_data_obs_list[x]['r_visible_list'][y][\n                                                'pos_y'] / self.img_obs_reduce_ratio),\n                                        int(fighter_data_obs_list[x]['r_visible_list'][y][\n                                                'pos_x'] / self.img_obs_reduce_ratio),\n                                        fighter_data_obs_list[x]['r_visible_list'][y]['type'] + 1)\n            # friendly pos. self: 255, other: type (detector: 1, fighter 2)\n            fighter_img[x, :, :, 2] = copy.deepcopy(tmp_pos_obs)\n            self.__set_value_in_img(fighter_img[x, :, :, 2],\n                                    int(fighter_data_obs_list[x]['pos_y'] / self.img_obs_reduce_ratio),\n                                    int(fighter_data_obs_list[x]['pos_x'] / self.img_obs_reduce_ratio), 255)\n\n        # Global obs\n        # Passive detection\n        for x in range(len(joint_data_obs_dict['passive_detection_enemy_list'])):\n            # Channel: detected enemy pos. value=enemy id\n            self.__set_value_in_img(joint_img[0, :, :, 0], int(joint_data_obs_dict['passive_detection_enemy_list'][x]['pos_y'] / self.img_obs_reduce_ratio),\n                                    int(joint_data_obs_dict['passive_detection_enemy_list'][x]['pos_x'] / self.img_obs_reduce_ratio),\n                                    joint_data_obs_dict['passive_detection_enemy_list'][x]['id'])\n            # Channe2: detected enemy pos. value=enemy type\n            self.__set_value_in_img(joint_img[0, :, :, 1], int(joint_data_obs_dict['passive_detection_enemy_list'][x]['pos_y'] / self.img_obs_reduce_ratio),\n                                    int(joint_data_obs_dict['passive_detection_enemy_list'][x]['pos_x'] / self.img_obs_reduce_ratio),\n                                    joint_data_obs_dict['passive_detection_enemy_list'][x]['type'] + 1)\n        # detector\n        for x in range(self.detector_num):\n            for y in range(len(detector_data_obs_list[x]['r_visible_list'])):\n                # Channel: detected enemy pos. value=enemy id\n                self.__set_value_in_img(joint_img[0, :, :, 0],\n                                        int(detector_data_obs_list[x]['r_visible_list'][y]['pos_y'] / self.img_obs_reduce_ratio),\n                                        int(detector_data_obs_list[x]['r_visible_list'][y]['pos_x'] / self.img_obs_reduce_ratio),\n                                        detector_data_obs_list[x]['r_visible_list'][y]['id'])\n                # Channe2: detected enemy pos. value=enemy type\n                self.__set_value_in_img(joint_img[0, :, :, 1],\n                                        int(detector_data_obs_list[x]['r_visible_list'][y]['pos_y'] / self.img_obs_reduce_ratio),\n                                        int(detector_data_obs_list[x]['r_visible_list'][y]['pos_x'] / self.img_obs_reduce_ratio),\n                                        detector_data_obs_list[x]['r_visible_list'][y]['type'] + 1)\n        # fighter\n        for x in range(self.fighter_num):\n            for y in range(len(fighter_data_obs_list[x]['r_visible_list'])):\n                # Channel: detected enemy pos. value=enemy id\n                self.__set_value_in_img(joint_img[0, :, :, 0],\n                                        int(fighter_data_obs_list[x]['r_visible_list'][y][\n                                                'pos_y'] / self.img_obs_reduce_ratio),\n                                        int(fighter_data_obs_list[x]['r_visible_list'][y][\n                                                'pos_x'] / self.img_obs_reduce_ratio),\n                                        fighter_data_obs_list[x]['r_visible_list'][y]['id'])\n                # Channe2: detected enemy pos. value=enemy type\n                self.__set_value_in_img(joint_img[0, :, :, 1],\n                                        int(fighter_data_obs_list[x]['r_visible_list'][y][\n                                                'pos_y'] / self.img_obs_reduce_ratio),\n                                        int(fighter_data_obs_list[x]['r_visible_list'][y][\n                                                'pos_x'] / self.img_obs_reduce_ratio),\n                                        fighter_data_obs_list[x]['r_visible_list'][y]['type'] + 1)\n        return detector_img, fighter_img, joint_img\n\n    def __set_value_in_img(self, img, pos_x, pos_y, value):\n        print(\"__set_value_in_img\")\n        \"\"\"\n        draw 3*3 rectangle in img\n        :param img:\n        :param pos_x:\n        :param pos_y:\n        :param value:\n        :return:\n        \"\"\"\n        img_obs_size_x = int(self.battlefield_size_y / self.img_obs_reduce_ratio)\n        img_obs_size_y = int(self.battlefield_size_x / self.img_obs_reduce_ratio)\n        # 左上角\n        if pos_x == 0 and pos_y == 0:\n            img[pos_x: pos_x + 2, pos_y: pos_y + 2] = value\n        # 左下角\n        elif pos_x == 0 and pos_y == (img_obs_size_y - 1):\n            img[pos_x: pos_x + 2, pos_y - 1: pos_y + 1] = value\n        # 右上角\n        elif pos_x == (img_obs_size_x - 1) and pos_y == 0:\n            img[pos_x - 1: pos_x + 1, pos_y: pos_y + 2] = value\n        # 右下角\n        elif pos_x == (img_obs_size_x - 1) and pos_y == (img_obs_size_y - 1):\n            img[pos_x - 1: pos_x + 1, pos_y - 1: pos_y + 1] = value\n        # 左边\n        elif pos_x == 0:\n            img[pos_x: pos_x + 2, pos_y - 1: pos_y + 2] = value\n        # 右边\n        elif pos_x == img_obs_size_x - 1:\n            img[pos_x - 1: pos_x + 1, pos_y - 1: pos_y + 2] = value\n        # 上边\n        elif pos_y == 0:\n            img[pos_x - 1: pos_x + 2, pos_y: pos_y + 2] = value\n        # 下边\n        elif pos_y == img_obs_size_y - 1:\n            img[pos_x - 1: pos_x + 2, pos_y - 1: pos_y + 1] = value\n        # 其他位置\n        else:\n            img[pos_x - 1: pos_x + 2, pos_y - 1: pos_y + 2] = value\n\n    def __get_data_obs(self, detector_data_obs_list, fighter_data_obs_list, joint_data_obs_dict):\n        print(\"__get_data_obs\")\n        detector_data = np.full((self.detector_num, 1), -1, dtype=np.int32)\n        fighter_data = np.full((self.fighter_num, 3), -1, dtype=np.int32)\n\n        # Detector info\n        for x in range(self.detector_num):\n            if detector_data_obs_list[x]['alive']:\n                detector_data[x,0] = detector_data_obs_list[x]['course']\n        # Fighter info\n        for x in range(self.fighter_num):\n            if fighter_data_obs_list[x]['alive']:\n                fighter_data[x, 0] = fighter_data_obs_list[x]['course']\n                fighter_data[x, 1] = fighter_data_obs_list[x]['l_missile_left']\n                fighter_data[x, 2] = fighter_data_obs_list[x]['s_missile_left']\n\n        return detector_data, fighter_data\n"
  },
  {
    "path": "replay.py",
    "content": "#! /usr/bin/env python\n# -*- coding: utf-8 -*-\n\"\"\"\n@author: Gao Fang\n@contact: gaofang@cetc.com.cn\n@software: PyCharm\n@file: replay_test.py\n@time: 2018/3/8 0008 17:24\n@desc: load a log and replay\n\"\"\"\n\nfrom interface import PlayBack\nimport argparse\n\nif __name__ == \"__main__\":\n    parser = argparse.ArgumentParser()\n    parser.add_argument(\"log\", type=str, help='log name')\n    args = parser.parse_args()\n\n    replay_obj = PlayBack(args.log)\n    replay_obj.start()\n    input(\"Press the <ENTER> key to continue...\")\n"
  },
  {
    "path": "tournament/config.ini",
    "content": "{\"map_name\": \"1000_1000_fighter10v10\", \"round_num\": 2, \"max_step\": 1500, \"agent_list\": [\"simple\", \"fix_rule\", \"fix_rule_no_att\"]}"
  },
  {
    "path": "tournament/config_gen.py",
    "content": "#! /usr/bin/env python\n# -*- coding: utf-8 -*-\n\"\"\"\n@author: Gao Fang\n@contact: gaofang@cetc.com.cn\n@software: PyCharm\n@file: config_gen.py\n@time: 2019/2/26 0026 15:17\n@desc: \n\"\"\"\n\nimport json\n\nif __name__ == \"__main__\":\n    config_dict = {}\n    map_name = '1000_1000_fighter10v10'\n    round_num = 6   # 必须为偶数\n    max_step = 1500\n    agent_list = ['fix_rule', 'fix_rule_no_att', 'simple']\n    config_dict.update({'map_name': map_name})\n    config_dict.update({'round_num': round_num})\n    config_dict.update({'max_step': max_step})\n    config_dict.update({'agent_list': agent_list})\n    with open('tournament/config.ini', 'w') as f:\n        json.dump(config_dict, f)\n"
  },
  {
    "path": "tournament/tournament_mp.py",
    "content": "#! /usr/bin/env python\n# -*- coding: utf-8 -*-\n\"\"\"\n@author: Gao Fang\n@contact: gaofang@cetc.com.cn\n@software: PyCharm\n@file: tournament.py\n@time: 2019/2/26 0026 9:13\n@desc: \n\"\"\"\n\nimport importlib\nimport os\nimport time\nimport json\nimport numpy as np\nimport pandas as pd\nfrom interface import Environment\nfrom common.agent_process import AgentCtrl\n\nSCORE_WIN = 3\nSCORE_DRAW = 1\nSCORE_LOSS = 0\n\n\ndef run(agent1_name, agent2_name, map_name, round_num, max_step, random_pos=False):\n    '''\n\n    :param agent1_name: 红方名称\n    :param agent2_name: 蓝方名称\n    :param map_name: 地图名称\n    :param round_num: 对战局数\n    :param max_step: 单局最大step\n    :param random_pos: 随机起始位置\n    :return: agent1_win_times, agent2_win_times, draw_times, agent1_crash_times, agent2_crash_times, agent1_timeout_times, agent2_timeout_times, agent1_launch_failure_times, agent2_launch_failure_times\n    '''\n    side1_win_times = 0\n    side2_win_times = 0\n    draw_times = 0\n    log_flag = agent1_name + '_vs_' + agent2_name\n    agent1_launch_failed = False\n    agent2_launch_failed = False\n    round_cnt = 0\n    agent1_crash_list = []\n    agent2_crash_list = []\n    agent1_timeout_list = []\n    agent2_timeout_list = []\n\n    # file path constructing\n    map_path = 'maps/' + map_name + '.map'\n    agent1_path = 'agent/' + agent1_name + '/agent.py'\n    agent2_path = 'agent/' + agent2_name + '/agent.py'\n\n    if not os.path.exists(map_path):\n        print('Error: map file not exist!')\n        exit(-1)\n    if not os.path.exists(agent1_path):\n        print('Error: agent1 file not exist!')\n        exit(-1)\n    if not os.path.exists(agent2_path):\n        print('Error: agent2 file not exist!')\n        exit(-1)\n    # make env\n    env = Environment(map_path, 'raw', 'raw', max_step=max_step, render=True, random_pos=random_pos, log=log_flag)\n    # get map info\n    size_x, size_y = env.get_map_size()\n    side1_detector_num, side1_fighter_num, side2_detector_num, side2_fighter_num = env.get_unit_num()\n    # create agent\n    agent1 = AgentCtrl(agent1_name, size_x, size_y, side1_detector_num, side1_fighter_num)\n    agent2 = AgentCtrl(agent2_name, size_x, size_y, side2_detector_num, side2_fighter_num)\n    if not agent1.agent_init():\n        print('ERROR: Agent1 ' + agent1_name + ' init failed!')\n        agent1.terminate()\n        agent2.terminate()\n        agent1_launch_failed = True\n    if not agent2.agent_init():\n        print('ERROR: Agent2 ' + agent2_name + ' init failed!')\n        agent1.terminate()\n        agent2.terminate()\n        agent2_launch_failed = True\n    # 若此处一方启动失败，则认为该方全败，启动失败计round_num次，若双方启动失败，则认为双方平局round_num次，其他与前述相同。\n    if agent1_launch_failed and agent2_launch_failed:\n        return 0, 0, round_num, 0, 0, 0, 0, round_num, round_num\n    elif agent1_launch_failed:\n        return 0, round_num, 0, 0, 0, 0, 0, round_num, 0\n    elif agent2_launch_failed:\n        return round_num, 0, 0, 0, 0, 0, 0, 0, round_num\n    # execution\n    # input(\"Press the <ENTER> key to continue...\")\n    for x in range(round_num):\n        if x != 0:\n            env.reset()\n        step_cnt = 0\n        round_cnt += 1\n        while True:\n            step_cnt += 1\n            # get obs\n            side1_obs_dict, side2_obs_dict = env.get_obs()\n            # get action\n            agent1_action, agent1_result = agent1.get_action(side1_obs_dict, step_cnt)\n            if agent1_result == 0:\n                side1_detector_action = agent1_action['detector_action']\n                side1_fighter_action = agent1_action['fighter_action']\n            elif agent1_result == 1:\n                agent1_crash_list.append(round_cnt)\n            elif agent1_result == 2:\n                agent1_timeout_list.append(round_cnt)\n            agent2_action, agent2_result = agent2.get_action(side2_obs_dict, step_cnt)\n            if agent2_result == 0:\n                side2_detector_action = agent2_action['detector_action']\n                side2_fighter_action = agent2_action['fighter_action']\n            elif agent2_result == 1:\n                agent2_crash_list.append(round_cnt)\n            elif agent2_result == 2:\n                agent2_timeout_list.append(round_cnt)\n            # execution\n            if agent1_result == 0 and agent2_result == 0:\n                env.step(side1_detector_action, side1_fighter_action, side2_detector_action, side2_fighter_action)\n            elif agent1_result != 0 and agent2_result != 0:\n                env.set_surrender(2)\n            elif agent1_result != 0:\n                env.set_surrender(0)\n            else:\n                env.set_surrender(1)\n            # get done\n            if env.get_done():\n                # reward\n                o_detector_reward, o_fighter_reward, o_game_reward, e_detector_reward, e_fighter_reward, e_game_reward = env.get_reward()\n                if o_game_reward > e_game_reward:\n                    side1_win_times += 1\n                elif o_game_reward < e_game_reward:\n                    side2_win_times += 1\n                else:\n                    draw_times += 1\n                break\n    agent1.terminate()\n    agent2.terminate()\n    return side1_win_times, side2_win_times, draw_times, len(agent1_crash_list), len(agent2_crash_list), len(agent1_timeout_list), len(agent2_timeout_list),0, 0\n\n\nif __name__ == \"__main__\":\n    map_name = ''\n    round_num = 0\n    max_step = 0\n    agent_list = []\n    summary_table = []\n    # load config\n    with open('tournament/config.ini', 'r') as f:\n        config_dict = json.load(f)\n        map_name = config_dict['map_name']\n        round_num = config_dict['round_num']\n        max_step = config_dict['max_step']\n        agent_list = config_dict['agent_list']\n\n    print('map_name: %s' % map_name)\n    print('round_num: %d' % round_num)\n    print('max_step: %d' % max_step)\n    print('agent_list: ')\n    print(agent_list)\n\n    if round_num % 2 != 0:\n        print('Error: round_num must be even number')\n        exit(-1)\n\n    win_rounds_per_agent = [0] * len(agent_list)\n    draw_rounds_per_agent = [0] * len(agent_list)\n    total_rounds_per_agent = [0] * len(agent_list)\n    crash_rounds_per_agent = [0] * len(agent_list)\n    timeout_rounds_per_agent = [0] * len(agent_list)\n    launch_failed_rounds_per_agent = [0] * len(agent_list)\n    win_rounds_against_each_other = np.zeros((len(agent_list), len(agent_list)), dtype='int32')\n    draw_rounds_against_each_other = np.zeros((len(agent_list), len(agent_list)), dtype='int32')\n    crash_rounds_against_each_other = np.zeros((len(agent_list), len(agent_list)), dtype='int32')\n    timeout_rounds_against_each_other = np.zeros((len(agent_list), len(agent_list)), dtype='int32')\n    launch_failed_rounds_against_each_other = np.zeros((len(agent_list), len(agent_list)), dtype='int32')\n\n    for x in range(len(agent_list)):\n        for y in range(len(agent_list)):\n            if y == x:\n                continue\n            agent1 = agent_list[x]\n            agent2 = agent_list[y]\n            print(agent1 + ' vs ' + agent2)\n            agent1_win_rounds, agent2_win_rounds, draw_rounds, agent1_crash_rounds, agent2_crash_rounds, agent1_timeout_rounds, agent2_timeout_rounds, agent1_launch_failure_rounds, agent2_launch_failure_rounds = run(agent1, agent2, map_name, int(round_num / 2), max_step)\n            # record\n            total_rounds = agent1_win_rounds + agent2_win_rounds + draw_rounds\n            win_rounds_per_agent[x] += agent1_win_rounds\n            win_rounds_per_agent[y] += agent2_win_rounds\n            draw_rounds_per_agent[x] += draw_rounds\n            draw_rounds_per_agent[y] += draw_rounds\n            total_rounds_per_agent[x] += total_rounds\n            total_rounds_per_agent[y] += total_rounds\n            crash_rounds_per_agent[x] += agent1_crash_rounds\n            crash_rounds_per_agent[y] += agent2_crash_rounds\n            timeout_rounds_per_agent[x] += agent1_timeout_rounds\n            timeout_rounds_per_agent[y] += agent1_timeout_rounds\n            launch_failed_rounds_per_agent[x] += agent1_launch_failure_rounds\n            launch_failed_rounds_per_agent[y] += agent2_launch_failure_rounds\n            win_rounds_against_each_other[x][y] += agent1_win_rounds\n            win_rounds_against_each_other[y][x] += agent2_win_rounds\n            draw_rounds_against_each_other[x][y] += draw_rounds\n            draw_rounds_against_each_other[y][x] += draw_rounds\n            crash_rounds_against_each_other[x][y] += agent1_crash_rounds\n            crash_rounds_against_each_other[y][x] += agent2_crash_rounds\n            timeout_rounds_against_each_other[x][y] += agent1_timeout_rounds\n            timeout_rounds_against_each_other[y][x] += agent2_timeout_rounds\n            launch_failed_rounds_against_each_other[x][y] += agent1_launch_failure_rounds\n            launch_failed_rounds_against_each_other[y][x] += agent2_launch_failure_rounds\n\n            # write file\n            # win detail\n            win_detail_table = pd.DataFrame(win_rounds_against_each_other)\n            win_detail_table.columns = agent_list\n            win_detail_table.index = agent_list\n            win_detail_table.to_html('tournament/result/win_detail.html')\n            # draw detail\n            draw_detail_table = pd.DataFrame(draw_rounds_against_each_other)\n            draw_detail_table.columns = agent_list\n            draw_detail_table.index = agent_list\n            draw_detail_table.to_html('tournament/result/draw_detail.html')\n            # crash detail\n            crash_detail_table = pd.DataFrame(crash_rounds_against_each_other)\n            crash_detail_table.columns = agent_list\n            crash_detail_table.index = agent_list\n            crash_detail_table.to_html('tournament/result/crash_detail.html')\n            # timeout detail\n            timeout_detail_table = pd.DataFrame(timeout_rounds_against_each_other)\n            timeout_detail_table.columns = agent_list\n            timeout_detail_table.index = agent_list\n            timeout_detail_table.to_html('tournament/result/timeout_detail.html')\n            # launch failure detail\n            launch_failure_detail_table = pd.DataFrame(launch_failed_rounds_against_each_other)\n            launch_failure_detail_table.columns = agent_list\n            launch_failure_detail_table.index = agent_list\n            launch_failure_detail_table.to_html('tournament/result/launch_failure_detail.html')\n            # summary\n            summary_table = pd.DataFrame(columns=['agent', 'score', 'win_rate', 'total_rounds', 'win_rounds', 'draw_rounds', 'loss_rounds', 'crash_rounds', 'timeout_rounds', 'launch_failure_rounds'])\n            for z in range(len(agent_list)):\n                if total_rounds_per_agent[z] == 0:\n                    win_rate = 0\n                else:\n                    win_rate = win_rounds_per_agent[z] / total_rounds_per_agent[z]\n                score = SCORE_WIN * win_rounds_per_agent[z] + SCORE_DRAW * draw_rounds_per_agent[z] + SCORE_LOSS * (total_rounds_per_agent[z] - win_rounds_per_agent[z] - draw_rounds_per_agent[z])\n                summary_table = summary_table.append(pd.DataFrame({'agent': [agent_list[z]],\n                                                                   'score': [score],\n                                                                   'win_rate': [win_rate],\n                                                                   'total_rounds': [total_rounds_per_agent[z]],\n                                                                   'win_rounds': [win_rounds_per_agent[z]],\n                                                                   'draw_rounds': [draw_rounds_per_agent[z]],\n                                                                   'loss_rounds': [total_rounds_per_agent[z] - win_rounds_per_agent[z] - draw_rounds_per_agent[z]],\n                                                                   'crash_rounds': [crash_rounds_per_agent[z]],\n                                                                   'timeout_rounds': [timeout_rounds_per_agent[z]],\n                                                                   'launch_failure_rounds': [launch_failed_rounds_per_agent[z]]}))\n            summary_table = summary_table.sort_values(by='score', ascending=False)\n            summary_table.to_html('tournament/result/summary.html', index=False)\n    print('tournament completed!, result:')\n    print(summary_table)"
  },
  {
    "path": "train/simple/dqn.py",
    "content": "#! /usr/bin/env python\n# -*- coding: utf-8 -*-\n\"\"\"\n@author: Gao Fang\n@contact: gaofang@cetc.com.cn\n@software: PyCharm\n@file: dqn.py\n@time: 2018/7/25 0025 13:38\n@desc: \n\"\"\"\nimport torch\nimport torch.nn as nn\nimport numpy as np\n\n\nclass NetFighter(nn.Module):\n    def __init__(self, n_actions):\n        super(NetFighter, self).__init__()\n        self.conv1 = nn.Sequential(     # 100 * 100 * 3\n            nn.Conv2d(\n                in_channels=5,\n                out_channels=16,\n                kernel_size=5,\n                stride=1,\n                padding=2,\n            ),\n            nn.ReLU(),\n            nn.MaxPool2d(2),\n        )\n        self.conv2 = nn.Sequential(     # 50 * 50 * 16\n            nn.Conv2d(16, 32, 5, 1, 2),\n            nn.ReLU(),\n            nn.MaxPool2d(2),            # 25 * 25 * 32\n        )\n        self.info_fc = nn.Sequential(\n            nn.Linear(3, 256),\n            nn.Tanh(),\n        )\n        self.feature_fc = nn.Sequential(    # 25 * 25 * 32 + 256\n            nn.Linear((25 * 25 * 32 + 256), 512),\n            nn.ReLU(),\n        )\n        self.decision_fc = nn.Linear(512, n_actions)\n\n    def forward(self, img, info):\n        img_feature = self.conv1(img)\n        img_feature = self.conv2(img_feature)\n        info_feature = self.info_fc(info)\n        combined = torch.cat((img_feature.view(img_feature.size(0), -1), info_feature.view(info_feature.size(0), -1)),\n                             dim=1)\n        feature = self.feature_fc(combined)\n        action = self.decision_fc(feature)\n        return action\n\n# Deep Q Network off-policy\nclass RLFighter:\n    def __init__(\n            self,\n            n_actions,\n            learning_rate=0.01,\n            reward_decay=0.9,\n            e_greedy=0.9,\n            replace_target_iter=100,\n            memory_size=500,\n            batch_size=32,\n            e_greedy_increment=None,\n            output_graph=False,\n    ):\n        self.n_actions = n_actions\n        self.lr = learning_rate\n        self.gamma = reward_decay\n        self.epsilon_max = e_greedy\n        self.replace_target_iter = replace_target_iter\n        self.memory_size = memory_size\n        self.batch_size = batch_size\n        self.epsilon_increment = e_greedy_increment\n        self.epsilon = 0 if e_greedy_increment is not None else self.epsilon_max\n        self.s_screen_memory = []\n        self.s_info_memory = []\n        self.a_memory = []\n        self.r_memory = []\n        self.s__screen_memory = []\n        self.s__info_memory = []\n        self.memory_counter = 0\n\n        self.gpu_enable = torch.cuda.is_available()\n\n        # total learning step\n        self.learn_step_counter = 0\n\n        self.cost_his = []\n        self.eval_net, self.target_net = NetFighter(self.n_actions), NetFighter(self.n_actions)\n        if self.gpu_enable:\n            print('GPU Available!!')\n            self.eval_net = self.eval_net.cuda()\n            self.target_net = self.target_net.cuda()\n        self.loss_func = nn.MSELoss()\n        # self.optimizer = torch.optim.Adam(self.eval_net.parameters(), lr=self.lr)\n        self.optimizer = torch.optim.RMSprop(self.eval_net.parameters(), lr=self.lr)\n\n\n    def store_transition(self, s, a, r, s_):\n        self.s_screen_memory.append(s['screen'])\n        self.s_info_memory.append(s['info'])\n        self.a_memory.append(a)\n        self.r_memory.append(r)\n        self.s__screen_memory.append(s_['screen'])\n        self.s__info_memory.append(s_['info'])\n        self.memory_counter += 1\n\n    def __clear_memory(self):\n        self.s_screen_memory.clear()\n        self.s_info_memory.clear()\n        self.a_memory.clear()\n        self.r_memory.clear()\n        self.s__screen_memory.clear()\n        self.s__info_memory.clear()\n        self.memory_counter = 0\n\n    def choose_action(self, img_obs, info_obs):\n        img_obs = torch.unsqueeze(torch.FloatTensor(img_obs), 0)\n        info_obs = torch.unsqueeze(torch.FloatTensor(info_obs), 0)\n        if self.gpu_enable:\n            img_obs = img_obs.cuda()\n            info_obs = info_obs.cuda()\n        if np.random.uniform() < self.epsilon:\n            actions_value = self.eval_net(img_obs, info_obs)\n            action = torch.max(actions_value, 1)[1]\n            if self.gpu_enable:\n                action = action.cpu()\n            action = action.numpy()\n        else:\n            action = np.zeros(1, dtype=np.int32)\n            action[0] = np.random.randint(0, self.n_actions)\n        return action\n\n    def learn(self):\n        # check to replace target parameters\n        if self.learn_step_counter % self.replace_target_iter == 0:\n            self.target_net.load_state_dict(self.eval_net.state_dict())\n            print('\\ntarget_params_replaced\\n')\n            step_counter_str = '%09d' % self.learn_step_counter\n            torch.save(self.target_net.state_dict(), 'model/simple/model_' + step_counter_str + '.pkl')\n        # pre possess mem\n        s_screen_mem = torch.FloatTensor(np.array(self.s_screen_memory))\n        s_info_mem = torch.FloatTensor(np.array(self.s_info_memory))\n        a_mem = torch.LongTensor(np.array(self.a_memory))\n        r_mem = torch.FloatTensor(np.array(self.r_memory))\n        r_mem = r_mem.view(self.memory_counter, 1)\n        s__screen_mem = torch.FloatTensor(np.array(self.s__screen_memory))\n        s__info_mem = torch.FloatTensor(np.array(self.s__info_memory))\n        if self.gpu_enable:\n            s_screen_mem = s_screen_mem.cuda()\n            s_info_mem = s_info_mem.cuda()\n            a_mem = a_mem.cuda()\n            r_mem = r_mem.cuda()\n            s__screen_mem = s__screen_mem.cuda()\n            s__info_mem = s__info_mem.cuda()\n\n        # sample batch memory from all memory\n\n        # q_eval w.r.t the action in experience\n        q_eval = self.eval_net(s_screen_mem, s_info_mem).gather(1, a_mem)  # shape (batch, 1)\n        q_next = self.target_net(s__screen_mem, s__info_mem).detach()  # detach from graph, don't backpropagate\n        q_target = r_mem + self.gamma * q_next.max(1)[0].view(self.memory_counter, 1)  # shape (batch, 1)\n        loss = self.loss_func(q_eval, q_target)\n\n        self.optimizer.zero_grad()\n        loss.backward()\n        self.optimizer.step()\n\n        self.cost_his.append(loss)\n\n        # increasing epsilon\n        self.epsilon = self.epsilon + self.epsilon_increment if self.epsilon < self.epsilon_max else self.epsilon_max\n        self.learn_step_counter += 1\n        self.__clear_memory()\n\n\nclass NetDetector(nn.Module):\n    def __init__(self, n_actions):\n        super(NetDetector, self).__init__()\n        self.conv1 = nn.Sequential(     # 100 * 100 * 3\n            nn.Conv2d(\n                in_channels=3,\n                out_channels=16,\n                kernel_size=5,\n                stride=1,\n                padding=2,\n            ),\n            nn.ReLU(),\n            nn.MaxPool2d(2),\n        )\n        self.conv2 = nn.Sequential(     # 50 * 50 * 16\n            nn.Conv2d(16, 32, 5, 1, 2),\n            nn.ReLU(),\n            nn.MaxPool2d(2),            # 25 * 25 * 32\n        )\n        self.info_fc = nn.Sequential(\n            nn.Linear(3, 256),\n            nn.Tanh(),\n        )\n        self.feature_fc = nn.Sequential(    # 25 * 25 * 32 + 256\n            nn.Linear((25 * 25 * 32 + 256), 512),\n            nn.ReLU(),\n        )\n        self.decision_fc = nn.Linear(512, n_actions)\n\n    def forward(self, img, info):\n        img_feature = self.conv1(img)\n        img_feature = self.conv2(img_feature)\n        info_feature = self.info_fc(info)\n        combined = torch.cat((img_feature.view(img_feature.size(0), -1), info_feature.view(info_feature.size(0), -1)),\n                             dim=1)\n        feature = self.feature_fc(combined)\n        action = self.decision_fc(feature)\n        return action\n\n"
  },
  {
    "path": "train/simple/main.py",
    "content": "#! /usr/bin/env python\n# -*- coding: utf-8 -*-\n\"\"\"\n@author: Gao Fang\n@contact: gaofang@cetc.com.cn\n@software: PyCharm\n@file: main.py\n@time: 2018/7/25 0025 10:01\n@desc: \n\"\"\"\n\nimport os\nimport copy\nimport numpy as np\nfrom agent.fix_rule_no_att.agent import Agent\nfrom interface import Environment\nfrom train.simple import dqn\nMAP_PATH = 'maps/1000_1000_fighter10v10.map'\n\nRENDER = True\nMAX_EPOCH = 1000\nBATCH_SIZE = 200\nLR = 0.01                   # learning rate\nEPSILON = 0.9               # greedy policy\nGAMMA = 0.9                 # reward discount\nTARGET_REPLACE_ITER = 100   # target update frequency\nDETECTOR_NUM = 0\nFIGHTER_NUM = 10\nCOURSE_NUM = 16\nATTACK_IND_NUM = (DETECTOR_NUM + FIGHTER_NUM) * 2 + 1 # long missile attack + short missile attack + no attack\nACTION_NUM = COURSE_NUM * ATTACK_IND_NUM\nLEARN_INTERVAL = 100\n\nif __name__ == \"__main__\":\n    # create blue agent\n    blue_agent = Agent()\n    # get agent obs type\n    red_agent_obs_ind = 'simple'\n    blue_agent_obs_ind = blue_agent.get_obs_ind()\n    # make env\n    env = Environment(MAP_PATH, red_agent_obs_ind, blue_agent_obs_ind, render=RENDER)\n    # get map info\n    size_x, size_y = env.get_map_size()\n    red_detector_num, red_fighter_num, blue_detector_num, blue_fighter_num = env.get_unit_num()\n    # set map info to blue agent\n    blue_agent.set_map_info(size_x, size_y, blue_detector_num, blue_fighter_num)\n\n    red_detector_action = []\n    fighter_model = dqn.RLFighter(ACTION_NUM)\n\n    # execution\n    for x in range(MAX_EPOCH):\n        step_cnt = 0\n        env.reset()\n        while True:\n            obs_list = []\n            action_list = []\n            red_fighter_action = []\n            # get obs\n            if step_cnt == 0:\n                red_obs_dict, blue_obs_dict = env.get_obs()\n            # get action\n            # get blue action\n            blue_detector_action, blue_fighter_action = blue_agent.get_action(blue_obs_dict, step_cnt)\n            # get red action\n            obs_got_ind = [False] * red_fighter_num\n            for y in range(red_fighter_num):\n                true_action = np.array([0, 1, 0, 0], dtype=np.int32)\n                if red_obs_dict['fighter'][y]['alive']:\n                    obs_got_ind[y] = True\n                    tmp_img_obs = red_obs_dict['fighter'][y]['screen']\n                    tmp_img_obs = tmp_img_obs.transpose(2, 0, 1)\n                    tmp_info_obs = red_obs_dict['fighter'][y]['info']\n                    tmp_action = fighter_model.choose_action(tmp_img_obs, tmp_info_obs)\n                    obs_list.append({'screen': copy.deepcopy(tmp_img_obs), 'info': copy.deepcopy(tmp_info_obs)})\n                    action_list.append(tmp_action)\n                    # action formation\n                    true_action[0] = int(360 / COURSE_NUM * int(tmp_action[0] / ATTACK_IND_NUM))\n                    true_action[3] = int(tmp_action[0] % ATTACK_IND_NUM)\n                red_fighter_action.append(true_action)\n            red_fighter_action = np.array(red_fighter_action)\n            # step\n            env.step(red_detector_action, red_fighter_action, blue_detector_action, blue_fighter_action)\n            # get reward\n            red_detector_reward, red_fighter_reward, red_game_reward, blue_detector_reward, blue_fighter_reward, blue_game_reward = env.get_reward()\n            detector_reward = red_detector_reward + red_game_reward\n            fighter_reward = red_fighter_reward + red_game_reward\n            # save repaly\n            red_obs_dict, blue_obs_dict = env.get_obs()\n            for y in range(red_fighter_num):\n                if obs_got_ind[y]:\n                    tmp_img_obs = red_obs_dict['fighter'][y]['screen']\n                    tmp_img_obs = tmp_img_obs.transpose(2, 0, 1)\n                    tmp_info_obs = red_obs_dict['fighter'][y]['info']\n                    fighter_model.store_transition(obs_list[y], action_list[y], fighter_reward[y],\n                                                   {'screen': copy.deepcopy(tmp_img_obs), 'info': copy.deepcopy(tmp_info_obs)})\n\n            # if done, perform a learn\n            if env.get_done():\n                # detector_model.learn()\n                fighter_model.learn()\n                break\n            # if not done learn when learn interval\n            if (step_cnt > 0) and (step_cnt % LEARN_INTERVAL == 0):\n                # detector_model.learn()\n                fighter_model.learn()\n            step_cnt += 1\n\n"
  },
  {
    "path": "utility.py",
    "content": "# utility.py\nimport math\n\n\ndef distance(x1, y1, x2, y2):\n    return math.sqrt((x2 - x1) ** 2 + (y2 - y1) ** 2)\n\n\ndef angle(x1, y1, x2, y2):\n    angle = math.degrees(math.atan2(y2 - y1, x2 - x1))\n    if angle < 0:\n        angle += 360\n    return int(angle)\n"
  }
]