From 252fb5cd0fed52aebe1834d9261886734db128d7 Mon Sep 17 00:00:00 2001 From: infstellar <98541813+infstellar@users.noreply.github.com> Date: Tue, 6 Jun 2023 23:40:26 +0800 Subject: [PATCH 01/40] Update README.md --- README.md | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 0db2f069..458cd358 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ # Genshin Impact Assistant 原神小助手 -**|[Chinese](https://github.com/GenshinImpactAssistant/GIA-Document/tree/main/zh_CN/README.md)|[English](https://github.com/GenshinImpactAssistant/GIA-Document/tree/main/en_US/README.md)|** +**|[Chinese](https://genshinimpactassistant.github.io/GIA-Document/#/)|[English](https://genshinimpactassistant.github.io/GIA-Document/#/en_US/)|**
A multi-functional auto-assist based on image recognition and keystroke simulation, including auto combat, auto domain and auto claim materials in Teyvat world. @@ -25,8 +25,8 @@ To没用过github的小伙伴: 描述文档中的蓝色文字是链接,可以打 ## Complete Documentation 详细信息 -**[中文文档](https://github.com/GenshinImpactAssistant/GIA-Document/tree/main/zh_CN/README.md)** **如果喜欢,点个星星~** ⭐ -**[English Document](https://github.com/GenshinImpactAssistant/GIA-Document/tree/main/en_US/README.md)** **star~** ⭐ +**[中文文档](https://genshinimpactassistant.github.io/GIA-Document/#/)** **如果喜欢,点个星星~** ⭐ +**[English Document](https://genshinimpactassistant.github.io/GIA-Document/#/en_US/)** **star~** ⭐ ## Demo Video 演示视频 @@ -43,8 +43,8 @@ Functions currently available ### 4. Auto Daily Commission Assist 每日委托(仅部分委托) ### 5. Claim Daily Reward 领取日常奖励 ### 6. Auto Lay Line Outcrop Assist 自动地脉衍出辅助 -For more details, see **[English Document](https://github.com/GenshinImpactAssistant/GIA-Document/tree/main/en_US/README.md)** -更多信息,查阅 **[中文文档](https://github.com/GenshinImpactAssistant/GIA-Document/tree/main/zh_CN/README.md)** +For more details, see **[English Document](https://genshinimpactassistant.github.io/GIA-Document/#/en_US/)** +更多信息,查阅 **[中文文档](https://genshinimpactassistant.github.io/GIA-Document/#/)** ## LICENSE 许可证 This project is licensed under the GNU General Public License v3.0. @@ -53,3 +53,10 @@ This project is licensed under the GNU General Public License v3.0. This software is open source, free of charge and for learning and exchange purposes only. The developer team has the final right to interpret this project. All problems arising from the use of this software are not related to this project and the developer team. If you encounter a merchant using this software to practice on your behalf and charging for it, it may be the cost of equipment and time, etc. The problems and consequences arising from this software have nothing to do with it. 本软件开源、免费,仅供学习交流使用。开发者团队拥有本项目的最终解释权。使用本软件产生的所有问题与本项目与开发者团队无关。若您遇到商家使用本软件进行代练并收费,可能是设备与时间等费用,产生的问题及后果与本软件无关。 + +## Acknowledgements 鸣谢 + +Thanks to all the friends who participated in the development/testing (\*´▽ ')ノノ +感谢所有参与到开发/测试中的朋友们 (\*´▽`)ノノ + +[![Contributors](https://contributors-img.web.app/image?repo=infstellar/genshin_impact_assistant)](https://github.com/infstellar/genshin_impact_assistant/graphs/contributors) From 25b670c23b87e3daf6219e24c0bc60db3e18ddf6 Mon Sep 17 00:00:00 2001 From: infstellar <98541813+infstellar@users.noreply.github.com> Date: Sat, 10 Jun 2023 19:15:14 +0800 Subject: [PATCH 02/40] add: ui&config&version id --- config/json_template/General.jsontemplate | 5 ++--- source/config/config.py | 6 +++--- source/config/config_generated.py | 8 ++++---- source/config/config_updater.py | 3 ++- source/config/util.py | 15 +++++++++++---- source/cvars.py | 2 +- source/webio/advance_page.py | 3 +-- source/webio/pages.py | 6 +++++- 8 files changed, 29 insertions(+), 19 deletions(-) diff --git a/config/json_template/General.jsontemplate b/config/json_template/General.jsontemplate index 5679269f..65d7fcdc 100644 --- a/config/json_template/General.jsontemplate +++ b/config/json_template/General.jsontemplate @@ -2,16 +2,15 @@ "BorderlessWindow": false, "UsingAlphaChannel": true, "DEBUG": false, - "CorrDegree": 0.95, + "Lang":"$locale$", "DevicePaddle": "cpu", "DeviceTorch": "auto", "CheckImport": false, - "Lang":"$locale$", "CloudGenshin": false, "CaptureMode":"fast", + "CorrDegree": 0.95, "DeterminingStrictWeight":0.9, "InteractionMode": "Desktop", "Python32Path": "", - "MissionGroup":"AutoCollectorMission.json", "Version":"v0.7.3.900" } \ No newline at end of file diff --git a/source/config/config.py b/source/config/config.py index 81c67178..dda094c8 100644 --- a/source/config/config.py +++ b/source/config/config.py @@ -25,7 +25,7 @@ def __setattr__(self, key, value, read_only=True): def load(self): for jsonname in CONFIG_FILE_NAMES: - j = load_json(json_name=f"{jsonname}.json", default_path=fr"{CONFIG_PATH}/settings") + j = load_json(json_name=f"{jsonname}.json", folder_path=fr"{CONFIG_PATH}/settings") for k in j: # if f"{jsonname}_{k}" in self.__dict__: self.__setattr__(f"{jsonname}_{k}", j[k], read_only=False) @@ -34,11 +34,11 @@ def load(self): def merge(self): for jsonname in CONFIG_FILE_NAMES: - j_template = load_json(json_name=f"{jsonname}.jsontemplate", default_path=fr"{CONFIG_PATH}/json_template") + j_template = load_json(json_name=f"{jsonname}.jsontemplate", folder_path=fr"{CONFIG_PATH}/json_template") if not os.path.exists(os.path.join(fr"{CONFIG_PATH}/settings", f"{jsonname}.json")): j_config = {} else: - j_config = load_json(json_name=f"{jsonname}.json", default_path=fr"{CONFIG_PATH}/settings") + j_config = load_json(json_name=f"{jsonname}.json", folder_path=fr"{CONFIG_PATH}/settings") j_template.update(j_config) # for k in j_template: # if k in j_config: diff --git a/source/config/config_generated.py b/source/config/config_generated.py index 1ca3df81..85c2107d 100644 --- a/source/config/config_generated.py +++ b/source/config/config_generated.py @@ -1,20 +1,20 @@ +# coding:utf-8 """This file is generated automatically. Do not manually modify it.""" class GeneratedConfig: General_BorderlessWindow = False General_UsingAlphaChannel = True General_DEBUG = False - General_CorrDegree = 0.95 + General_Lang = '$locale$' General_DevicePaddle = 'cpu' General_DeviceTorch = 'auto' General_CheckImport = False - General_Lang = '$locale$' General_CloudGenshin = False General_CaptureMode = 'fast' + General_CorrDegree = 0.95 General_DeterminingStrictWeight = 0.9 General_InteractionMode = 'Desktop' General_Python32Path = '' - General_MissionGroup = 'AutoCollectorMission.json' - General_Version = 'v0.7.2.779' + General_Version = 'v0.7.3.900' Collector_CollectionName = '史莱姆' Collector_CollectionType = 'ENEMY' Collector_CollectionArea = 'ALL' diff --git a/source/config/config_updater.py b/source/config/config_updater.py index b8f42677..1f00182c 100644 --- a/source/config/config_updater.py +++ b/source/config/config_updater.py @@ -10,7 +10,8 @@ commission_list = [] commission_dict = {} -with open(os.path.join(ROOT_PATH,r"source/config/config_generated.py"), "w") as f: +with open(os.path.join(ROOT_PATH,r"source/config/config_generated.py"), "w", encoding='utf-8') as f: + f.write(f'# coding:utf-8\n') f.write("\"\"\"This file is generated automatically. Do not manually modify it.\"\"\"\n") f.write("class GeneratedConfig:\n") for jsonname in CONFIG_FILE_NAMES: diff --git a/source/config/util.py b/source/config/util.py index dedc7f3a..1b84a296 100644 --- a/source/config/util.py +++ b/source/config/util.py @@ -1,11 +1,18 @@ from source.path_lib import * from source.config.cvars import * import json +from collections import OrderedDict - -def load_json(json_name='config.json', default_path='config\\settings') -> dict: - all_path = os.path.join(ROOT_PATH, default_path, json_name) - return json.load(open(all_path, 'r', encoding='utf-8')) +def load_json(json_name='General.json', folder_path='config\\settings', auto_create = False) -> dict: + all_path = os.path.join(ROOT_PATH, folder_path, json_name) + try: + return json.load(open(all_path, 'r', encoding='utf-8'), object_pairs_hook=OrderedDict) + except: + if not auto_create: + raise FileNotFoundError(all_path) + else: + json.dump({}, open(all_path, 'w', encoding='utf-8')) + return json.load(open(all_path, 'r', encoding='utf-8')) def save_json(x, json_name='config.json', default_path='config\\settings', sort_keys=True): if not os.path.exists(default_path): diff --git a/source/cvars.py b/source/cvars.py index 30cf3acd..257b7aa8 100644 --- a/source/cvars.py +++ b/source/cvars.py @@ -17,4 +17,4 @@ PROCESS_NAME = ["YuanShen.exe", "GenshinImpact.exe"] SCREEN_CENTER_X = 1920/2 SCREEN_CENTER_Y = 1080/2 -GIA_VERSION = "v0.8.4.987" +GIA_VERSION = "v0.8.5.1039" diff --git a/source/webio/advance_page.py b/source/webio/advance_page.py index ed74d983..83facbac 100644 --- a/source/webio/advance_page.py +++ b/source/webio/advance_page.py @@ -19,8 +19,7 @@ def _on_load(self): output.put_markdown(t2t('# GIA DEBUG') + f" {GIA_VERSION}"), else: output.put_markdown(t2t('# GIA GUI') + f" {GIA_VERSION}"), - # document - output.put_link(t2t('View Document'), url='https://genshinimpactassistant.github.io/GIA-Document', new_window = True).style('font-size: 25px') + # 页面切换按钮 output.put_buttons(self._value_list2buttons_type(list(manager.page_dict)), onclick=webio.manager.load_page, scope=self.main_scope) super()._on_load() diff --git a/source/webio/pages.py b/source/webio/pages.py index 58fbc64f..574ab65a 100644 --- a/source/webio/pages.py +++ b/source/webio/pages.py @@ -99,7 +99,11 @@ def _load(self): # 标题 # 获得链接按钮 with output.use_scope(self.main_scope): - output.put_button(label=t2t("Get IP address"), onclick=self.on_click_ip_address, scope=self.main_scope) + output.put_row([ + output.put_button(label=t2t("Get IP address"), onclick=self.on_click_ip_address, scope=self.main_scope), + output.put_link(t2t('View Document'), url='https://genshinimpactassistant.github.io/GIA-Document', new_window = True).style('font-size: 20px') + ]) + task_options = [ { From 4e9346b60a4c2215baad55db95bd180218d94b91 Mon Sep 17 00:00:00 2001 From: infstellar <98541813+infstellar@users.noreply.github.com> Date: Sat, 10 Jun 2023 19:28:15 +0800 Subject: [PATCH 03/40] i18n: zh_CN --- translation/locale/zh_CN/LC_MESSAGES/zh_CN.po | 270 ++++++++++++++---- 1 file changed, 222 insertions(+), 48 deletions(-) diff --git a/translation/locale/zh_CN/LC_MESSAGES/zh_CN.po b/translation/locale/zh_CN/LC_MESSAGES/zh_CN.po index 78b55623..2013c970 100644 --- a/translation/locale/zh_CN/LC_MESSAGES/zh_CN.po +++ b/translation/locale/zh_CN/LC_MESSAGES/zh_CN.po @@ -5,8 +5,8 @@ msgid "" msgstr "" "Project-Id-Version: \n" -"POT-Creation-Date: 2023-06-04 19:40+0800\n" -"PO-Revision-Date: 2023-06-04 19:41+0800\n" +"POT-Creation-Date: 2023-06-10 19:15+0800\n" +"PO-Revision-Date: 2023-06-10 19:24+0800\n" "Last-Translator: \n" "Language-Team: \n" "Language: zh_CN\n" @@ -48,7 +48,7 @@ msgstr "正在创建OCR对象" msgid "导入paddleocr时错误; err code: 001" msgstr "" -#: source\api\pdocr_api.py:208 +#: source\api\pdocr_api.py:209 msgid "ocr device: " msgstr "OCR 运行设备:" @@ -70,15 +70,15 @@ msgstr "" #: source\commission\commission_executor.py:36 msgid "Commission(s) Failed, Commission Task end." -msgstr "" +msgstr "委托失败。委托任务结束。" #: source\commission\commission_executor.py:39 msgid "Cannot find any commissions, Commission Task end." -msgstr "" +msgstr "无法找到任何委托,委托任务结束。" #: source\commission\commission_executor.py:42 msgid "Number of executions exceeding the limit, Commission Task end." -msgstr "" +msgstr "超过限制的执行次数,委托任务结束。" #: source\common\flow_state.py:99 msgid "空闲" @@ -414,7 +414,7 @@ msgstr "" #: source\mission\missions\MissionSakuraBloom1.py:10 msgid "Need Lisa" -msgstr "" +msgstr "需要Lisa" #: source\pickup\pickup_operator.py:55 msgid "正在设置时间为夜晚" @@ -492,9 +492,13 @@ msgstr "任务结束" msgid "未知Page, 重新检测" msgstr "" -#: source\webio\advance_page.py:17 -msgid "# Config" -msgstr "# 设置" +#: source\webio\advance_page.py:19 +msgid "# GIA DEBUG" +msgstr "" + +#: source\webio\advance_page.py:21 +msgid "# GIA GUI" +msgstr "" #: source\webio\page.py:45 msgid "Main" @@ -532,73 +536,81 @@ msgstr "" msgid "在导入完成前,请不要切换页面。" msgstr "" -#: source\webio\pages.py:101 +#: source\webio\pages.py:103 msgid "Get IP address" msgstr "获取IP地址" -#: source\webio\pages.py:105 +#: source\webio\pages.py:104 +msgid "View Document" +msgstr "查看文档" + +#: source\webio\pages.py:110 msgid "Launch genshin" msgstr "进入原神" -#: source\webio\pages.py:109 +#: source\webio\pages.py:114 msgid "Domain Task" msgstr "秘境任务" -#: source\webio\pages.py:113 +#: source\webio\pages.py:118 msgid "Daily Commission" msgstr "每日委托" -#: source\webio\pages.py:117 +#: source\webio\pages.py:122 msgid "Claim Reward" msgstr "领取日常奖励" -#: source\webio\pages.py:121 +#: source\webio\pages.py:126 msgid "Ley Line Outcrop" msgstr "地脉衍出" -#: source\webio\pages.py:125 source\webio\webpages\missiondownload.py:160 +#: source\webio\pages.py:130 source\webio\webpages\missiondownload.py:160 #: source\webio\webpages\missiondownload.py:239 msgid "Mission" msgstr "自定义任务" -#: source\webio\pages.py:131 +#: source\webio\pages.py:136 msgid "Task List" msgstr "任务列表" -#: source\webio\pages.py:132 +#: source\webio\pages.py:137 msgid "Can only be activated from the button" msgstr "只能通过按钮启动" -#: source\webio\pages.py:134 +#: source\webio\pages.py:139 msgid "启动/停止Task" msgstr "" -#: source\webio\pages.py:135 +#: source\webio\pages.py:141 msgid "## Statement" msgstr "## 状态" -#: source\webio\pages.py:136 +#: source\webio\pages.py:142 msgid "任务状态" msgstr "" -#: source\webio\pages.py:146 -msgid "## Function" -msgstr "## 功能" +#: source\webio\pages.py:143 +msgid "## Semi-automatic Functions" +msgstr "## 半自动功能" -#: source\webio\pages.py:147 +#: source\webio\pages.py:144 msgid "Can only be activated from the hotkey '['" msgstr "只能通过快捷键启动(默认为‘[')" -#: source\webio\pages.py:149 -msgid "FlowMode" -msgstr "流程模式" +#: source\webio\pages.py:145 +msgid "Do not enable semi-automatic functions and tasks at the same time" +msgstr "不要同时启用半自动功能和任务" -#: source\webio\pages.py:151 +#: source\webio\pages.py:147 +msgid "Semi-automatic Functions" +msgstr "半自动功能" + +#: source\webio\pages.py:150 msgid "Idle" msgstr "空闲" -#: source\webio\pages.py:152 -msgid "AutoCombat" +#: source\webio\pages.py:151 +msgid "Auto Combat" msgstr "自动战斗" #: source\webio\pages.py:168 @@ -621,8 +633,8 @@ msgstr "局域网IP" msgid "WAN IP" msgstr "以太网IP" -#: source\webio\pages.py:255 source\webio\pages.py:596 -#: source\webio\pages.py:670 source\webio\pages.py:709 +#: source\webio\pages.py:255 source\webio\pages.py:597 +#: source\webio\pages.py:671 source\webio\pages.py:710 msgid "## config:" msgstr "## 设置:" @@ -662,19 +674,19 @@ msgstr "自动采集设置" msgid "LeyLineOutcrop.json" msgstr "地脉衍出" -#: source\webio\pages.py:315 source\webio\pages.py:825 +#: source\webio\pages.py:315 source\webio\pages.py:826 msgid "Verified!" msgstr "验证通过!" -#: source\webio\pages.py:324 source\webio\pages.py:834 +#: source\webio\pages.py:324 source\webio\pages.py:835 msgid "Waiting..." msgstr "等待中..." -#: source\webio\pages.py:329 source\webio\pages.py:839 +#: source\webio\pages.py:329 source\webio\pages.py:840 msgid "You may want to enter: " msgstr "你可能想输入:" -#: source\webio\pages.py:334 source\webio\pages.py:844 +#: source\webio\pages.py:334 source\webio\pages.py:845 msgid "Not a valid name" msgstr "不是一个有效的名称" @@ -682,39 +694,43 @@ msgstr "不是一个有效的名称" msgid "saved!" msgstr "保存成功!" -#: source\webio\pages.py:420 +#: source\webio\pages.py:378 +msgid "You may need to restart to apply changes." +msgstr "你可能需要重启以应用更改。" + +#: source\webio\pages.py:421 msgid "Do you need to save changes?" msgstr "你要保存设置吗?" -#: source\webio\pages.py:421 +#: source\webio\pages.py:422 msgid "No" msgstr "否" -#: source\webio\pages.py:421 +#: source\webio\pages.py:422 msgid "Yes" msgstr "是" -#: source\webio\pages.py:660 +#: source\webio\pages.py:661 msgid "# Add team" msgstr "# 增加队伍" -#: source\webio\pages.py:664 +#: source\webio\pages.py:665 msgid "Add team" msgstr "增加队伍" -#: source\webio\pages.py:666 +#: source\webio\pages.py:667 msgid "自动填充" msgstr "" -#: source\webio\pages.py:770 +#: source\webio\pages.py:771 msgid "Add to blacklist" msgstr "添加到黑名单" -#: source\webio\pages.py:778 +#: source\webio\pages.py:779 msgid "展开/收起" msgstr "" -#: source\webio\pages.py:813 +#: source\webio\pages.py:814 msgid "clean list" msgstr "清空列表" @@ -722,7 +738,7 @@ msgstr "清空列表" msgid "GIA 已升级到" msgstr "" -#: source\webio\webio.py:39 +#: source\webio\webio.py:42 msgid "webio启动完成" msgstr "" @@ -1027,6 +1043,164 @@ msgstr "检查更新中..." msgid "Finished checking updates" msgstr "检查更新完成" +#: source\webio\webpages\video2path.py:60 +msgid "Path does not exist!" +msgstr "路径不存在!" + +#: source\webio\webpages\video2path.py:70 +msgid "Please waiting..." +msgstr "请等待..." + +#: source\webio\webpages\video2path.py:83 +msgid "press any key in GIA PathToVideo window to continue." +msgstr "在GIA PathToVideo窗口中按任何一个键来继续。" + +#: source\webio\webpages\video2path.py:93 +msgid "Path Recorder start!" +msgstr "Path Recorder 启动!" + +#: source\webio\webpages\video2path.py:95 +msgid "Path Recorder stop!" +msgstr "Path Recorder 结束!" + +#: source\webio\webpages\video2path.py:106 +msgid "" +"警告:您已经切换到开发模式页面,所有主页功能均不可用。如需使用,请重启程序。" +msgstr "" + +#: source\webio\webpages\video2path.py:108 +msgid "DEV MODE ENABLED." +msgstr "DEV模式启动。" + +#: source\webio\webpages\video2path.py:112 +msgid "Tutorial" +msgstr "教程" + +#: source\webio\webpages\video2path.py:113 +msgid "" +"## 食用教程:\n" +"1. 输入视频路径\n" +"2. 加载视频\n" +"3. 加载完成后点击播放视频\n" +"4. 等待视频播放到你要开始记录的位置时,(暂停)点击分析坐标按钮\n" +"5. 等待分析完成,日志区将显示可能的坐标id,坐标位置,区域,名称,匹配度, 选" +"择你认为可能的**坐标id**输入初始化坐标输入框\n" +"6. 点击预览初始坐标按钮,将显示该坐标的区域预览图\n" +"7. 重复5-6步骤,确认无误后,点击确认初始坐标按钮\n" +"8. 点击启停路径记录器按钮,开始记录\n" +"9. 等待视频播放到你要结束记录的位置时, 点击启停路径记录器按钮,停止记录\n" +"10. 重复4-9步骤,直到完成。\n" +"11. TLPP文件将储存在dev_assets/tlpp目录下\n" +"## 快捷键\n" +"快捷键只能在GIA VideoToPath窗口使用\n" +"|快捷键|用法|\n" +"|----|----|\n" +"| 空格 | 暂停/播放 |\n" +"| `,` | 减小播放速度,记录路径时必须为现实速度 |\n" +"| `.` | 增大播放速度,记录路径时必须为现实速度 |\n" +"| `[` | 启动/停止记录 |\n" +"| `a` | 分析初始坐标 |\n" +"## 注意\n" +"**必须在加载视频前填写所有参数!(除初始坐标id外)**\n" +msgstr "" + +#: source\webio\webpages\video2path.py:160 +msgid "load/reload video" +msgstr "加载/重载视频" + +#: source\webio\webpages\video2path.py:161 +msgid "Play video" +msgstr "播放视频" + +#: source\webio\webpages\video2path.py:162 +msgid "Analyze init position" +msgstr "分析初始坐标" + +#: source\webio\webpages\video2path.py:163 +msgid "Preview init position" +msgstr "展示初始坐标" + +#: source\webio\webpages\video2path.py:164 +msgid "Confirm init position" +msgstr "确认初始坐标" + +#: source\webio\webpages\video2path.py:165 +msgid "Start/Stop path recorder" +msgstr "启动/停止路径记录" + +#: source\webio\webpages\video2path.py:166 +msgid "Cancel video" +msgstr "取消视频" + +#: source\webio\webpages\video2path.py:169 +msgid "Video path" +msgstr "视频路径" + +#: source\webio\webpages\video2path.py:170 +msgid "init position id" +msgstr "初始坐标id" + +#: source\webio\webpages\video2path.py:171 +msgid "File head name" +msgstr "TLPP文件名前缀" + +#: source\webio\webpages\video2path.py:172 +msgid "is pickup mode" +msgstr "是否为拾取模式" + +#: source\webio\webpages\video2path.py:173 +msgid "Collection name" +msgstr "采集物名称" + +#: source\webio\webpages\video2path.py:174 +msgid "Frame to start" +msgstr "开始帧" + +#: source\webio\webpages\video2path.py:175 +msgid "Collect area" +msgstr "采集区域" + +#: source\webio\webpages\video2path.py:176 +msgid "Video size" +msgstr "视频窗口大小" + +#: source\webio\webpages\video2path.py:204 +msgid "Video is not available" +msgstr "视频不可用" + +#: source\webio\webpages\video2path.py:209 +msgid "Load over." +msgstr "加载完成。" + +#: source\webio\webpages\video2path.py:210 +msgid "ready to start." +msgstr "准备开始。" + +#: source\webio\webpages\video2path.py:229 +msgid "不在主界面/画质过低/错误的视频大小/不完整的录屏" +msgstr "" + +#: source\webio\webpages\video2path.py:234 +msgid "Analysis completion: " +msgstr "分析完成:" + +#: source\webio\webpages\video2path.py:238 +msgid "" +"Please enter the possible ID into `init position id`, then press `Preview " +"init position` button or `Confirm init position` button." +msgstr "" +"请在 `初始坐标id` 中输入可能的ID,然后按 \"展示初始坐标\"按钮或 \"确认初始坐" +"标\"按钮。" + +#~ msgid "# Config" +#~ msgstr "# 设置" + +#~ msgid "## Function" +#~ msgstr "## 功能" + +#~ msgid "FlowMode" +#~ msgstr "流程模式" + #~ msgid "Mission installed, please apply and save." #~ msgstr "自定义任务已安装,请应用并保存。" From 573251f1ab73a513367b63b23ef2e3aa0bc8b6b8 Mon Sep 17 00:00:00 2001 From: infstellar <98541813+infstellar@users.noreply.github.com> Date: Sat, 10 Jun 2023 22:18:44 +0800 Subject: [PATCH 04/40] fix: auto switch channels --- source/map/detection/minimap.py | 38 ++++++++++++++++++++++--------- source/map/map.py | 29 +++++++++++++++++++++-- source/mission/mission_manager.py | 2 +- 3 files changed, 55 insertions(+), 14 deletions(-) diff --git a/source/map/detection/minimap.py b/source/map/detection/minimap.py index 653c9ef8..be7cc61a 100644 --- a/source/map/detection/minimap.py +++ b/source/map/detection/minimap.py @@ -12,7 +12,7 @@ THREE_CHANNEL = 3 class MiniMap(MiniMapResource): - COLOR_CHANNEL = THREE_CHANNEL + def init_position(self, position: t.Tuple[int, int]): # logger.info(f"init_position:{position}") self.position = position @@ -40,7 +40,7 @@ def get_img_near_posi(self, image, posi): search_image = crop(self.TChannelGIMAP, search_area) return search_image - def _predict_position(self, image, scale): + def _predict_position(self, image, scale, channel=ONE_CHANNEL): """ Args: image: @@ -60,9 +60,9 @@ def _predict_position(self, image, scale): search_area = area_offset((0, 0, *search_size), offset=(-search_size // 2).astype(np.int64)) search_area = area_offset(search_area, offset=np.multiply(search_position, self.POSITION_SEARCH_SCALE)) search_area = np.array(search_area).astype(np.int64) - if self.COLOR_CHANNEL == ONE_CHANNEL: + if channel == ONE_CHANNEL: search_image = crop(self.GIMAP, search_area) - elif self.COLOR_CHANNEL == THREE_CHANNEL: + elif channel == THREE_CHANNEL: search_image = crop(self.TChannelGIMAP, search_area) result = cv2.matchTemplate(search_image, local, cv2.TM_CCOEFF_NORMED) @@ -124,29 +124,39 @@ def update_position(self, origin_image): else: image = origin_image image = self._get_minimap(image, self.MINIMAP_POSITION_RADIUS) - if self.COLOR_CHANNEL == ONE_CHANNEL: - image = rgb2luma(image) - image &= self._minimap_mask - else: - image &= np.expand_dims(self._minimap_mask,axis=2).repeat(3,axis=2) + + image_one = image.copy() + image_one = rgb2luma(image) + image_one &= self._minimap_mask + + image_three = image.copy() + image_three &= np.expand_dims(self._minimap_mask,axis=2).repeat(3,axis=2) best_sim = -1. best_local_sim = -1. best_loca = (0, 0) best_scene = 'wild' for scene, scale in self._position_scale_dict.items(): - similarity, local_sim, location = self._predict_position(image, scale) + if scene == 'wild': + inp_img = image_one + channel = ONE_CHANNEL + else: + inp_img = image_three + channel = THREE_CHANNEL + similarity, local_sim, location = self._predict_position(inp_img, scale, channel=channel) # print(scene, scale, similarity, location) if similarity > best_sim: best_sim = similarity best_local_sim = local_sim best_loca = location best_scene = scene + best_channel = channel self.position_similarity = round(best_sim, 5) self.position_similarity_local = round(best_local_sim, 5) self.position = tuple(np.round(best_loca, 1)) self.scene = best_scene + self.channel = best_channel # logger.trace(f'P:({float2str(self.position[0], 4)}, {float2str(self.position[1], 4)}) ') return self.position @@ -392,14 +402,20 @@ def update_minimap(self, image): self.update_rotation(image, layer=MapConverter.LAYER_Teyvat, update_position=False) # MiniMap P:(4451.5, 3113.0) (0.184|0.050), S:wild, D:259.5 (0.949), R:180 (0.498) + + self.minimap_print_log() + + def minimap_print_log(self): logger.trace( f'MiniMap ' f'P:({float2str(self.position[0], 4)}, {float2str(self.position[1], 4)}) ' f'({float2str(self.position_similarity, 3)}|{float2str(self.position_similarity_local, 3)}), ' f'S:{self.scene}, ' f'D:{float2str(self.direction, 3)} ({float2str(self.direction_similarity, 3)}), ' + f'C:{self.channel}, ' f'R:{self.rotation} ({float2str(self.rotation_confidence)})') + def update_minimap_domain(self, image): """ Args: @@ -461,7 +477,7 @@ def is_rotation_near(self, rotation, threshold=10) -> bool: device = WindowsCapture() minimap = MiniMap(MiniMap.DETECT_Desktop_1080p) # 坐标位置是 GIMAP 的图片坐标 - minimap.init_position((5454,758)) + minimap.init_position(MapConverter.convert_cvAutoTrack_to_GIMAP([1334,-4057])) # 你可以移动人物,GIA会持续监听小地图位置和角色朝向 while 1: image = itt.capture() diff --git a/source/map/map.py b/source/map/map.py index 7bd4a34b..44a1a5c0 100644 --- a/source/map/map.py +++ b/source/map/map.py @@ -41,7 +41,7 @@ def __init__(self): self.TP_RANGE = 350 # 在该像素范围内可tp self.MINIMAP_UPDATE_LIMIT = 0.1 # minimap更新最短时间 self.MINIMAP_ERROR_BASE_LIMIT = 20 # minimap基本更新误差 - self.METER_PER_SECOND = 10+5 # 移动速度,m/s + self.METER_PER_SECOND = 25 # 移动速度,m/s self.smallmap_upd_timer = timer_module.Timer(10) self.small_map_init_flag = False @@ -49,6 +49,7 @@ def __init__(self): self.check_bigmap_timer = timer_module.Timer(5) self.init_timer = timer_module.AdvanceTimer(5) self.last_valid_position = [0,0] + self.history_position_list = [] @@ -105,6 +106,24 @@ def get_and_verify_position(self): # print(self.check_bigmap_timer.get_diff_time()) return curr_posi + def _is_reset_position(self, curr_posi, threshold=0.8): + """如果有threshold%的数据超过150,则返回True。 + + Args: + curr_posi (_type_): _description_ + threshold (float, optional): _description_. Defaults to 0.8. + + Returns: + _type_: _description_ + """ + if len(self.history_position_list) >= 20: + over_times = 0 + for i in self.history_position_list: + if euclidean_distance(i, curr_posi) >= 150: + over_times += 1 + return over_times/20 > threshold + return False + def get_position(self, is_verify_position = True): """get current character position @@ -115,17 +134,23 @@ def get_position(self, is_verify_position = True): self.reinit_smallmap() self.small_map_init_flag = True self._upd_smallmap() + self.history_position_list.append(self.position) if is_verify_position: - if self.smallmap_upd_timer.get_diff_time() <= 8: + if self._is_reset_position(self.position): + self.history_position_list = [] + else: last_dist = euclidean_distance(self.last_valid_position,self.convert_GIMAP_to_cvAutoTrack(self.position)) error_limit = self.MINIMAP_ERROR_BASE_LIMIT + self.smallmap_upd_timer.get_diff_time()*self.METER_PER_SECOND if last_dist > error_limit: logger.warning(f"migration of position {round(last_dist,2)} over limit {round(error_limit,2)}, give up position") + self.minimap_print_log() return self.last_valid_position self.smallmap_upd_timer.reset() r_posi = self.convert_GIMAP_to_cvAutoTrack(self.position) self.last_valid_position = r_posi + if len(self.history_position_list)>20: + self.history_position_list.pop(0) return r_posi def is_similarity_qualified(self, offset_rate=1): diff --git a/source/mission/mission_manager.py b/source/mission/mission_manager.py index 6b1fcc4e..00d8417e 100644 --- a/source/mission/mission_manager.py +++ b/source/mission/mission_manager.py @@ -16,7 +16,7 @@ def set_mission_list(self,mission_list:list): self.missions_list = mission_list def exec_mission(self, mission_name): - mission = missions.mission_index .get_mission_object(mission_name) + mission = missions.mission_index.get_mission_object(mission_name) self._add_sub_threading(mission, start=False) self.blocking_startup(mission) mission.stop_threading() From ecb3dc763d8d0fb1589d95f5369f3ddf48fcde0a Mon Sep 17 00:00:00 2001 From: infstellar <2644641825@qq.com> Date: Wed, 14 Jun 2023 12:30:00 +0800 Subject: [PATCH 05/40] fix: click posi --- source/manager/img_manager.py | 15 +++++++++++++-- source/task/domain_task.py | 2 ++ 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/source/manager/img_manager.py b/source/manager/img_manager.py index 62e400af..fa25328c 100644 --- a/source/manager/img_manager.py +++ b/source/manager/img_manager.py @@ -21,8 +21,19 @@ def qshow(img1): cv2.imshow('123', img1) cv2.waitKey(0) class ImgIcon(AssetBase): - def __init__(self, path=None, name=None, is_bbg=None, alpha=None, bbg_posi=None, cap_posi = None, - jpgmode=2, threshold=0.91, win_page = 'all', win_text = None, offset = 0, print_log = LOG_NONE): + def __init__(self, + path=None, + name=None, + is_bbg=None, + alpha=None, + bbg_posi=None, + cap_posi = None, + jpgmode=2, + threshold=0.91, + win_page = 'all', + win_text = None, + offset = 0, + print_log = LOG_NONE): """创建一个img对象,用于图片识别等。 Args: diff --git a/source/task/domain_task.py b/source/task/domain_task.py index 3dc44632..9e1db3fc 100644 --- a/source/task/domain_task.py +++ b/source/task/domain_task.py @@ -67,6 +67,8 @@ def _enter_domain(self): mode=CONTAIN_MATCHING, extract_white_threshold=254) if p1 != -1: + if len(p1)>1: + p1 = p1[0] itt.move_and_click([p1[0] + 5, p1[1] + 5], delay=1) else: texts = ocr.get_all_texts(itt.capture(jpgmode=0, posi=cap_area)) From 3f7bcccc17fc7faec165c52984780d9d9e8b9d3f Mon Sep 17 00:00:00 2001 From: infstellar <2644641825@qq.com> Date: Wed, 14 Jun 2023 18:21:35 +0800 Subject: [PATCH 06/40] fix: minimap_print_log error --- source/api/pdocr_api.py | 12 ++++++------ source/map/map.py | 4 ++++ 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/source/api/pdocr_api.py b/source/api/pdocr_api.py index 7f3e09cb..4711cf4f 100644 --- a/source/api/pdocr_api.py +++ b/source/api/pdocr_api.py @@ -188,12 +188,12 @@ def is_img_num_plus(self, im_src): if __name__ == '__main__': ocr = PaddleOcrFastDeploy() - imsrc = cv2.imread("D:\\test2.jpg") - r = ocr.get_text_position(imsrc, "VsCode") - print(r)# boxes, rec_scores, text - imsrc = cv2.imread("D:\\test.jpg") - r = ocr.get_text_position(imsrc, "VsCode") - print(r)# boxes, rec_scores, text + # imsrc = cv2.imread("D:\\test2.jpg") + # r = ocr.get_text_position(imsrc, "VsCode") + # print(r)# boxes, rec_scores, text + # imsrc = cv2.imread("D:\\test.jpg") + # r = ocr.get_text_position(imsrc, "VsCode") + print(ocr._replace_texts('纳西姐'))# boxes, rec_scores, text diff --git a/source/map/map.py b/source/map/map.py index 44a1a5c0..638fb2a7 100644 --- a/source/map/map.py +++ b/source/map/map.py @@ -130,6 +130,10 @@ def get_position(self, is_verify_position = True): Returns: list: TianLiPosition format """ + if not itt.get_img_existence(asset.IconUIEmergencyFood, is_log=False): + logger.warning(t2t("不在大世界,无法获取坐标")) + logger.warning(f"return (0,0)") + return [0,0] if not self.small_map_init_flag: self.reinit_smallmap() self.small_map_init_flag = True From c27983f77ac4fc649739eb81a7f5a8c30932e27c Mon Sep 17 00:00:00 2001 From: infstellar <2644641825@qq.com> Date: Wed, 14 Jun 2023 18:24:27 +0800 Subject: [PATCH 07/40] fix: replace text in get_all_texts --- source/api/pdocr_api.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/api/pdocr_api.py b/source/api/pdocr_api.py index 4711cf4f..b667bc65 100644 --- a/source/api/pdocr_api.py +++ b/source/api/pdocr_api.py @@ -158,8 +158,8 @@ def get_text_position(self, def get_all_texts(self, img, mode=0): res = self.analyze(img) if mode==1: - return ','.join(str(i) for i in res.text).replace(',','') - return res.text + return ','.join(str(i) for i in self._replace_texts(res.text)).replace(',','') + return [i for i in self._replace_texts(res.text)] def is_img_num(self, im_src): pdocr_timer_performance.reset() From 36b937a1f06d54546839f00820961a8ce8e7a812 Mon Sep 17 00:00:00 2001 From: infstellar <98541813+infstellar@users.noreply.github.com> Date: Wed, 14 Jun 2023 23:21:12 +0800 Subject: [PATCH 08/40] fix: ensure main page when commission start --- source/commission/commission_executor.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/source/commission/commission_executor.py b/source/commission/commission_executor.py index 88856da8..613905e7 100644 --- a/source/commission/commission_executor.py +++ b/source/commission/commission_executor.py @@ -2,6 +2,8 @@ from source.task.task_template import TaskTemplate from source.commission.commission_parser import CommissionParser from source.commission.commission_acquisition import get_commission_object +from source.ui.ui import ui_control +from source.ui import page as UIPage class CommissionExecutor(TaskTemplate, CommissionParser): def __init__(self): @@ -20,6 +22,7 @@ def loop(self): if i["done"]: # this commission obj has been done. logger.info(f"{i['type']} has been done.") continue + ui_control.ensure_page(UIPage.page_main) self._add_sub_threading(co) co.continue_threading() # start commission obj while 1: From a0cc3486057f38b05d9f7e6b90efadb6383925ee Mon Sep 17 00:00:00 2001 From: infstellar <2644641825@qq.com> Date: Thu, 15 Jun 2023 15:38:11 +0800 Subject: [PATCH 09/40] fix: commission parser --- source/commission/commission_parser.py | 10 +++++++--- source/map/map.py | 4 ++-- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/source/commission/commission_parser.py b/source/commission/commission_parser.py index d4eaf6e0..1b245a72 100644 --- a/source/commission/commission_parser.py +++ b/source/commission/commission_parser.py @@ -60,10 +60,14 @@ def traverse_mondstant(self): itt.move_and_click(list(i)) itt.delay("animation") + for i in range(3): + com_type = self._detect_commission_type() + if com_type != None: + break + else: + itt.delay("2animation") itt.delay("animation") - itt.delay("animation") - com_type = self._detect_commission_type() - itt.delay("animation") + while 1: itt.key_press('esc') itt.delay("2animation") diff --git a/source/map/map.py b/source/map/map.py index 638fb2a7..263c1a4e 100644 --- a/source/map/map.py +++ b/source/map/map.py @@ -132,8 +132,8 @@ def get_position(self, is_verify_position = True): """ if not itt.get_img_existence(asset.IconUIEmergencyFood, is_log=False): logger.warning(t2t("不在大世界,无法获取坐标")) - logger.warning(f"return (0,0)") - return [0,0] + logger.warning(f"return {self.convert_GIMAP_to_cvAutoTrack(self.position)}") + return self.convert_GIMAP_to_cvAutoTrack(self.position) if not self.small_map_init_flag: self.reinit_smallmap() self.small_map_init_flag = True From 3410c66ffab795e08ad7985803444c6bfc2318af Mon Sep 17 00:00:00 2001 From: infstellar <2644641825@qq.com> Date: Thu, 15 Jun 2023 21:13:44 +0800 Subject: [PATCH 10/40] fix: mission: tmf: return err code --- source/flow/flow_template.py | 8 ++++++++ source/mission/mission_template.py | 3 ++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/source/flow/flow_template.py b/source/flow/flow_template.py index 553a1210..35cdae50 100644 --- a/source/flow/flow_template.py +++ b/source/flow/flow_template.py @@ -141,6 +141,14 @@ def _err_code_exec(self) -> bool: """ return True + def get_and_reset_err_code(self): + errc = self.last_err_code + self.reset_err_code() + return errc + + def reset_err_code(self): + self.last_err_code = ERR_NONE + def loop(self): rcode = self.flow_dict[self.current_flow_id].enter_flow() if "$END$" in rcode: diff --git a/source/mission/mission_template.py b/source/mission/mission_template.py index 6a02c08f..356f733d 100644 --- a/source/mission/mission_template.py +++ b/source/mission/mission_template.py @@ -176,7 +176,8 @@ def move(self, MODE:str = None, if self.PUO_initialized: if puo_start_flag: self.PUO.continue_threading() - return self._handle_exception() + self._handle_exception() + return self.TMCF.get_and_reset_err_code() def move_straight(self, position, is_tp = False, is_precise_arrival=None, stop_rule=None): if isinstance(position[0], int) or isinstance(position[0], float): From 89f549c7f1a173a0c90e76b5134c9cb4bdd3d2f3 Mon Sep 17 00:00:00 2001 From: infstellar <2644641825@qq.com> Date: Fri, 16 Jun 2023 20:51:25 +0800 Subject: [PATCH 11/40] feat: prf: add json name in pydict --- source/flow/path_recorder_flow.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/flow/path_recorder_flow.py b/source/flow/path_recorder_flow.py index aec3e0fb..ace4a4cc 100644 --- a/source/flow/path_recorder_flow.py +++ b/source/flow/path_recorder_flow.py @@ -257,7 +257,7 @@ def state_after(self): # if self.upper.is_pickup_mode: # self._fix_bps() # 这个功能好像与is_end=True功能冲突... with open(fr"{ROOT_PATH}/dev_assets/tlpp/{jsonname}.pydict", 'w') as f: - f.write(str(self.upper.collection_path_dict)) + f.write(f"{jsonname} = "+str(self.upper.collection_path_dict)) # save_json(self.upper.collection_path_dict,json_name=jsonname,default_path=f"assets\\TeyvatMovePath") logger.info(f"recording save as {jsonname}") self.rfc = FC.INIT From 65f40acc95c057da4e3c41a44f9b75adbf92e650 Mon Sep 17 00:00:00 2001 From: infstellar <98541813+infstellar@users.noreply.github.com> Date: Fri, 16 Jun 2023 23:13:47 +0800 Subject: [PATCH 12/40] fix: ocr get_all_texts --- source/api/pdocr_api.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/api/pdocr_api.py b/source/api/pdocr_api.py index b667bc65..c58203ec 100644 --- a/source/api/pdocr_api.py +++ b/source/api/pdocr_api.py @@ -158,8 +158,8 @@ def get_text_position(self, def get_all_texts(self, img, mode=0): res = self.analyze(img) if mode==1: - return ','.join(str(i) for i in self._replace_texts(res.text)).replace(',','') - return [i for i in self._replace_texts(res.text)] + return ','.join(str(self._replace_texts(i)) for i in res.text).replace(',','') + return [self._replace_texts(i) for i in res.text] def is_img_num(self, im_src): pdocr_timer_performance.reset() From ac65ea6690b27b99451b454c8565759d0ffa97bc Mon Sep 17 00:00:00 2001 From: infstellar <98541813+infstellar@users.noreply.github.com> Date: Sat, 17 Jun 2023 13:06:38 +0800 Subject: [PATCH 13/40] opt: ui: combat settings --- config/json_doc/Combat.zh_CN.yaml | 4 ++++ source/webio/pages.py | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/config/json_doc/Combat.zh_CN.yaml b/config/json_doc/Combat.zh_CN.yaml index ce0e1a4b..d2435e53 100644 --- a/config/json_doc/Combat.zh_CN.yaml +++ b/config/json_doc/Combat.zh_CN.yaml @@ -1,3 +1,7 @@ +AdaptiveTeamSetup: + doc: 自动识别角色并生成队伍 + annotation: 启用后,优先寻找tactic文件夹中适合的战斗策略,如果没有,则自动生成策略。如果希望强制使用自定义的战斗策略请关闭此项。 + E_long_cd_time: annotation: 长Ecd时间,没有则为0 doc: 长元素战技cd时间 diff --git a/source/webio/pages.py b/source/webio/pages.py index 574ab65a..00271a90 100644 --- a/source/webio/pages.py +++ b/source/webio/pages.py @@ -670,7 +670,7 @@ def _load(self): # 配置页 output.put_markdown(t2t('## config:'), scope=self.main_scope) output.put_scope("select_scope", scope=self.main_scope) - pin.put_select('file', self._config_file2lableAfile(self.config_files), scope="select_scope", value="config\\settings\\auto_combat.json") + pin.put_select('file', self._config_file2lableAfile(self.config_files), scope="select_scope", value="config/settings/Combat.json") def onclick_add_teamjson(self): n = input.input('team name') From 64c378f363a93151cdc08e18792a1b589d73658e Mon Sep 17 00:00:00 2001 From: infstellar <98541813+infstellar@users.noreply.github.com> Date: Sat, 17 Jun 2023 20:00:31 +0800 Subject: [PATCH 14/40] opt: claim reward: add STOP_RULE_F --- source/mission/mission.py | 8 ++++++-- source/task/claim_reward/claim_reward.py | 4 ++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/source/mission/mission.py b/source/mission/mission.py index 87499219..03e58656 100644 --- a/source/mission/mission.py +++ b/source/mission/mission.py @@ -64,7 +64,7 @@ def move_straight(self, position, is_tp=False, is_precise_arrival=None, stop_rul """ return super().move_straight(position, is_tp, is_precise_arrival, stop_rule) - def move_along(self, path, is_tp=None, is_precise_arrival=None): + def move_along(self, path, is_tp=None, is_precise_arrival=None, stop_rule = None): """沿着TLPP行走。 阻塞式任务. @@ -72,13 +72,17 @@ def move_along(self, path, is_tp=None, is_precise_arrival=None): path (dict): TLPP格式字典。 is_tp (bool, optional): 是否传送. Defaults to None. is_precise_arrival (bool, optional): 是否精确到达目的地(误差小于1m). Defaults to None. + stop_rule (_type_, optional): 停止条件. 可选: + STOP_RULE_ARRIVE: 到达后停止 + STOP_RULE_F: 在目的地附近看到f后停止. + STOP_RULE_COMBAT: 发现敌人或进入战斗后停止。 注: 在某些Mission中,path可能会是字符串.这是旧版本所使用的存储TLPP文件的方法,现已弃用. 目前所有的TLPP文件与Mission放在同一个py文件中. Returns: _type_: _description_ """ - return super().move_along(path, is_tp, is_precise_arrival) + return super().move_along(path, is_tp, is_precise_arrival, stop_rule) def start_combat(self, mode="Normal"): """开始战斗。 diff --git a/source/task/claim_reward/claim_reward.py b/source/task/claim_reward/claim_reward.py index d08661d6..017923b9 100644 --- a/source/task/claim_reward/claim_reward.py +++ b/source/task/claim_reward/claim_reward.py @@ -1,5 +1,5 @@ from source.task.claim_reward.util import * -from source.mission.mission_template import MissionExecutor +from source.mission.mission_template import MissionExecutor, STOP_RULE_F from source.task.task_template import TaskTemplate from source.talk.talk import Talk from source.manager import asset @@ -60,7 +60,7 @@ def reset_character(): def exec_mission(self): self.available_rewards = self.get_available_reward() if "Expedition" in self.available_rewards or "Commission" in self.available_rewards: - self.move_along("Katheryne20230408124320i0", is_precise_arrival=True) + self.move_along("Katheryne20230408124320i0", is_precise_arrival=True, stop_rule = STOP_RULE_F) if "Commission" in self.available_rewards: self.talk_with_npc() self.talk_until_switch(self.checkup_stop_func) From b8084d19d098dc2264677539e69e8888424de28c Mon Sep 17 00:00:00 2001 From: infstellar <98541813+infstellar@users.noreply.github.com> Date: Sat, 17 Jun 2023 21:47:01 +0800 Subject: [PATCH 15/40] add: base part of the CollectionMine --- source/controller/combat_controller.py | 1 + source/flow/collector_flow_upgrad.py | 50 ++++++++++++++++++++------ source/flow/flow_state.py | 1 + 3 files changed, 41 insertions(+), 11 deletions(-) diff --git a/source/controller/combat_controller.py b/source/controller/combat_controller.py index dbe9813e..ffe204bf 100644 --- a/source/controller/combat_controller.py +++ b/source/controller/combat_controller.py @@ -14,6 +14,7 @@ MODE_NORMAL = 'Normal' MODE_SHIELD = 'Shield' MODE_CORE = "Core" +MODE_RECOVER = 'Recover' diff --git a/source/flow/collector_flow_upgrad.py b/source/flow/collector_flow_upgrad.py index db3f78a6..49505b13 100644 --- a/source/flow/collector_flow_upgrad.py +++ b/source/flow/collector_flow_upgrad.py @@ -83,6 +83,12 @@ def stop_all(self): time.sleep(2) class CollectionCombat(FlowTemplate): + """这个类执行拾取中的战斗部分。 + 如果有战斗会切换到该流程。 + + Args: + FlowTemplate (_type_): _description_ + """ def __init__(self, upper: CollectorFlowConnector): super().__init__(upper, flow_id=ST.COLLECTION_COMBAT, next_flow_id=ST.COLLECTION_PICKUP, flow_timeout_time=300) self.upper=upper @@ -107,30 +113,50 @@ def state_in(self): self.upper.stop_combat() self._next_rfc() +class CollectionMine(FlowTemplate): + """采矿FLOW。 + + Args: + FlowTemplate (_type_): _description_ + """ + def __init__(self, upper: CollectorFlowConnector): + super().__init__(upper, flow_id=ST.COLLECTION_MINE, next_flow_id=ST.COLLECTION_PICKUP, flow_timeout_time=300) + self.upper=upper + + + class PickUpCollection(FlowTemplate): + """拾取掉落物。 + + 工作原理:识别闪光点(rgb=255,255,255)的方向前进。 + 具体原理请查看pickup_operator.py。 + + Args: + FlowTemplate (_type_): _description_ + """ def __init__(self, upper: CollectorFlowConnector): self.upper = upper self.IN_PICKUP_COLLECTOR_timeout = timer_module.TimeoutTimer(45) + # 根据不同的采集类型设置超时时间。 if self.upper.collector_type == COLLECTION: timeout_time = 150 elif self.upper.collector_type == ENEMY: self.upper.puo.max_distance_from_target = 60 timeout_time = 300 elif self.upper.collector_type == MINERAL: - pass + timeout_time = 150 super().__init__(upper, flow_id=ST.COLLECTION_PICKUP, next_flow_id=ST.END_COLLECTOR, flow_timeout_time=timeout_time) def state_before(self): - - if len(self.upper.pickup_points) > self.upper.pickup_points_index: - movement.move_to_position(self.upper.pickup_points[self.upper.pickup_points_index]) - r = self.upper.puo.pickup_recognize() + if len(self.upper.pickup_points) > self.upper.pickup_points_index: # 如果有采集点 + movement.move_to_position(self.upper.pickup_points[self.upper.pickup_points_index]) # 移动到目标位置 + r = self.upper.puo.pickup_recognize() # 识别并采集 self.upper.pickup_points_index += 1 logger.debug(f"pickup point:{self.upper.pickup_points[self.upper.pickup_points_index]}, {r}") else: - if self.upper.is_activate_pickup: - self.upper.puo.set_search_mode(1) - self.upper.start_pickup() + if self.upper.is_activate_pickup: # 如果启动主动采集模式 + self.upper.puo.set_search_mode(1) # 设置PUO为Search模式 + self.upper.start_pickup() # 开始采集 self.upper.puo.reset_err_code() self.flow_timeout.reset() # IMPORTANT self.IN_PICKUP_COLLECTOR_timeout.reset() @@ -140,16 +166,18 @@ def state_before(self): self._set_rfc(FC.END) def state_in(self): - if self.upper.puo.pause_threading_flag: + """主要负责等待PUO完成。 + """ + if self.upper.puo.pause_threading_flag: # PUO结束时结束。 self._next_rfc() - if self.IN_PICKUP_COLLECTOR_timeout.istimeout(): + if self.IN_PICKUP_COLLECTOR_timeout.istimeout(): # 超时结束 logger.info(f"IN_PICKUP_COLLECTOR timeout: {self.IN_PICKUP_COLLECTOR_timeout.timeout_limit}") logger.info(f"collect in xxx failed.") self._next_rfc() self._set_nfid(ST.END_COLLECTOR) self.upper.stop_pickup() - if combat_lib.CSDL.get_combat_state(): + if combat_lib.CSDL.get_combat_state(): # 如果有战斗,回退到战斗FLOW。 self.upper.stop_pickup() self._set_nfid(ST.COLLECTION_COMBAT) self._set_rfc(FC.END) diff --git a/source/flow/flow_state.py b/source/flow/flow_state.py index 5ff28e33..2c33edba 100644 --- a/source/flow/flow_state.py +++ b/source/flow/flow_state.py @@ -8,6 +8,7 @@ INIT_MOVETO_COLLECTOR = "INIT_MOVETO_COLLECTOR" INIT_PICKUP_COLLECTOR = "INIT_PICKUP_COLLECTOR" COLLECTION_COMBAT = "COLLECTION_COMBAT" +COLLECTION_MINE = "COLLECTION_MINE" COLLECTION_PICKUP = "COLLECTION_PICKUP_POINT" END_COLLECTOR = "$END$COLLECTOR" INIT_TEYVAT_TELEPORT = "INIT_TEYVAT_TELEPORT" From 16820c4f610bf7d47c1e7c7c542009127efa9fb0 Mon Sep 17 00:00:00 2001 From: infstellar <98541813+infstellar@users.noreply.github.com> Date: Sat, 17 Jun 2023 23:21:30 +0800 Subject: [PATCH 16/40] fix: v2p --- source/webio/webpages/video2path.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/source/webio/webpages/video2path.py b/source/webio/webpages/video2path.py index 19c227ce..1e84c5ed 100644 --- a/source/webio/webpages/video2path.py +++ b/source/webio/webpages/video2path.py @@ -189,7 +189,7 @@ def _load_video(self): self.PRF = PathRecorderController() self.PRF.flow_connector.path_name = pin.pin[self.INPUT_PATH_FILE_HEAD_NAME] self.PRF.flow_connector.is_pickup_mode = bool(pin.pin[self.INPUT_IS_PICKUP_MODE]) - self.PRF.flow_connector.coll_name = pin.pin[self.INPUT_PATH_FILE_HEAD_NAME] + self.PRF.flow_connector.coll_name = pin.pin[self.INPUT_COLL_NAME] self.frame_index = int(pin.pin[self.INPUT_FRAME_TO_START]) self.target_fps = 30 @@ -293,13 +293,13 @@ def run_once(self): elif k & 0xFF == ord('b'): self.set_init_position() elif k & 0xFF == ord('.'): - fps+=5 - self._show_log(f"fps set as {fps}") + self.target_fps+=5 + self._show_log(f"fps set as {self.target_fps}") elif k & 0xFF == ord(','): - fps-=5 - if fps <= 0: - fps = 1 - self._show_log(f"fps set as {fps}") + self.target_fps-=5 + if self.target_fps <= 0: + self.target_fps = 1 + self._show_log(f"fps set as {self.target_fps}") elif k & 0xFF == ord(']'): self.PRF.pc._start_stop_recording() self._show_log(f"press any key to continue.") From f9b19415cf0ee0d76838791388aa1d3087e6599a Mon Sep 17 00:00:00 2001 From: infstellar <98541813+infstellar@users.noreply.github.com> Date: Sat, 17 Jun 2023 23:49:35 +0800 Subject: [PATCH 17/40] fix: llo: raise exception when move stuck --- source/task/ley_line_outcrop/ley_line_outcrop.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/source/task/ley_line_outcrop/ley_line_outcrop.py b/source/task/ley_line_outcrop/ley_line_outcrop.py index 93018ac8..2edc9dda 100644 --- a/source/task/ley_line_outcrop/ley_line_outcrop.py +++ b/source/task/ley_line_outcrop/ley_line_outcrop.py @@ -1,7 +1,7 @@ from source.util import * from source.assets.ley_line_outcrop import * from source.task.ley_line_outcrop.util import * -from source.mission.mission_template import MissionExecutor +from source.mission.mission_template import MissionExecutor, EXCEPTION_RAISE from source.task.task_template import TaskTemplate from source.map.position.position import * from source.funclib import movement @@ -84,7 +84,8 @@ def exec_mission(self): for i in range(self.collection_times): try: self.target_posi = self.traverse_mondstant() - self.move(MODE='AUTO', stop_rule=0, target_posi=list(self.target_posi), is_tp=True, is_precise_arrival=True) + r = self.move(MODE='AUTO', stop_rule=0, target_posi=list(self.target_posi), is_tp=True, is_precise_arrival=True) + self.handle_tmf_stuck_then_raise(r) self.circle_search(self.target_posi) itt.key_press('f') # self.collect(is_combat=True) From 2e4ca924898ffe1e6105fee6fd094d18806163de Mon Sep 17 00:00:00 2001 From: infstellar <98541813+infstellar@users.noreply.github.com> Date: Sun, 18 Jun 2023 10:27:45 +0800 Subject: [PATCH 18/40] fix: list index out of range in sco --- source/operator/switch_character_operator.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/operator/switch_character_operator.py b/source/operator/switch_character_operator.py index 88133ec2..e0ae1989 100644 --- a/source/operator/switch_character_operator.py +++ b/source/operator/switch_character_operator.py @@ -216,7 +216,7 @@ def _switch_character(self, x: int) -> bool: movement.jump_timer_reset() movement.jump_in_loop(jump_dt=3) if i > 45: - movement.move([movement.AHEAD,movement.LEFT,movement.RIGHT,movement.BACK][i], distance=3) + movement.move([movement.AHEAD,movement.LEFT,movement.RIGHT,movement.BACK][i%4], distance=3) if i > 55: logger.warning('角色切换失败') logger.trace(f"sco loop cost: {time.time()-pt}") From ca35a1e7f333dddb246c337539b70311cb4c6ff5 Mon Sep 17 00:00:00 2001 From: infstellar <98541813+infstellar@users.noreply.github.com> Date: Sun, 18 Jun 2023 23:24:10 +0800 Subject: [PATCH 19/40] docs: base threading --- source/common/base_threading.py | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/source/common/base_threading.py b/source/common/base_threading.py index 5d29b200..c264b280 100644 --- a/source/common/base_threading.py +++ b/source/common/base_threading.py @@ -48,6 +48,16 @@ def get_working_statement(self): return not self.pause_threading_flag def checkup_stop_func(self): + """检查是否要退出。会检查暂停flag和停止flag。 + 使用方法: + 在函数中使用: + if self.checkup_stop_func(): return 适当的返回值 + 在循环中: + if self.checkup_stop_func(): break + + Returns: + _type_: _description_ + """ pt = time.time() def output_log(t): if t<0.05: @@ -81,6 +91,12 @@ def reset_err_code(self): self.last_err_code = ERR_NONE def _add_sub_threading(self, threading_obj, start=True): + """添加子线程。 + + Args: + threading_obj (_type_): 子线程对象 + start (bool, optional): 是否开启子线程. Defaults to True. + """ threading_obj.setDaemon(True) threading_obj.add_stop_func(self.checkup_stop_func) threading_obj.pause_threading() @@ -90,12 +106,17 @@ def _add_sub_threading(self, threading_obj, start=True): logger.debug(f"sub threading {threading_obj.name} has been add.") def _clean_sub_threading(self): + """移除所有子线程。 + """ for thread_obj in self.sub_threading_list: logger.debug(f"{self.name} stop {thread_obj.name}") thread_obj.stop_threading() self.sub_threading_list = [] def loop(self): + """ + 在这里写要循环执行的代码。 + """ pass def run(self): From f7095458bb7b4661f4950a5d60dadb7e538770f0 Mon Sep 17 00:00:00 2001 From: infstellar <2644641825@qq.com> Date: Mon, 19 Jun 2023 17:48:28 +0800 Subject: [PATCH 20/40] docs: base_threading & task --- source/common/base_threading.py | 35 +++++++++++++++++++++------- source/task/mission_generate_task.py | 4 ++++ 2 files changed, 30 insertions(+), 9 deletions(-) diff --git a/source/common/base_threading.py b/source/common/base_threading.py index c264b280..473ba6be 100644 --- a/source/common/base_threading.py +++ b/source/common/base_threading.py @@ -13,14 +13,14 @@ class BaseThreading(threading.Thread): """ def __init__(self, thread_name = None): super().__init__() - self._init_succ_flag = False # Use in init slow threads - self.pause_threading_flag = False - self.stop_threading_flag = False - self.working_flag = False - self.while_sleep = 0.2 - self.last_err_code = ERR_NONE - self.stop_func_list = [] - self.sub_threading_list = [] + self._init_succ_flag = False # 在初始化很慢的线程中使用 + self.pause_threading_flag = False # 暂停线程标记 + self.stop_threading_flag = False # 线程停止标记 + self.working_flag = False # 废物 + self.while_sleep = 0.2 # 每次循环间隔 + self.last_err_code = ERR_NONE # 错误码 + self.stop_func_list = [] # 停止函数列表。check_up_stop_func时循环执行里面的函数,如果有返回值为true的函数即停止。 + self.sub_threading_list = [] # 子线程列表 if thread_name != None: self.setName(thread_name) @@ -146,17 +146,32 @@ def __init__(self, thread_name=None): super().__init__(thread_name) def blocking_startup(self, threading_obj:BaseThreading): + """阻塞启动模式。 + 使用该模式启动线程时,会阻塞当前线程,循环执行threading_obj的loop函数。 + 此时,threading_obj不会作为线程启动。使用此方法可以避免启动过多线程。 + + Args: + threading_obj (BaseThreading): _description_ + + Returns: + _type_: _description_ + """ if threading_obj.is_alive(): threading_obj.stop_threading() threading_obj.continue_threading() while 1: - time.sleep(self.while_sleep) + time.sleep(threading_obj.while_sleep) threading_obj.loop() if threading_obj.pause_threading_flag: break return threading_obj.get_last_err_code() class FunctionThreading(AdvanceThreading): + """目前没啥用 + + Args: + AdvanceThreading (_type_): _description_ + """ def __init__(self, target, thread_name=None): super().__init__(thread_name) self.target = target @@ -166,6 +181,8 @@ def loop(self): self.target() class ThreadBlockingRequest(): + """线程阻塞请求 + """ def __init__(self) -> None: self.blocking_request_flag = False self.reply_request_flag = False diff --git a/source/task/mission_generate_task.py b/source/task/mission_generate_task.py index 150c6891..16ffa212 100644 --- a/source/task/mission_generate_task.py +++ b/source/task/mission_generate_task.py @@ -5,6 +5,10 @@ from source.flow.collector_flow_upgrad import CollectorFlowController from source.map.map import genshin_map +""" +已废弃。不要使用。 +""" + """ json格式: { From 736b642b48704b4195e29904ba24a81a299d5b76 Mon Sep 17 00:00:00 2001 From: infstellar <2644641825@qq.com> Date: Mon, 19 Jun 2023 21:04:05 +0800 Subject: [PATCH 21/40] feat: add exception basic classes --- .vscode/settings.json | 1 + source/exceptions/common.py | 2 ++ source/exceptions/mission.py | 16 ++++++----- source/exceptions/util.py | 11 ++++++++ source/listening.py | 3 ++- source/task/launch_genshin/launch_genshin.py | 3 +++ source/task/task_manager.py | 24 ++++++++++++++++- source/test/test_threading.py | 28 ++++++++++++++++++++ 8 files changed, 80 insertions(+), 8 deletions(-) create mode 100644 source/exceptions/util.py create mode 100644 source/test/test_threading.py diff --git a/.vscode/settings.json b/.vscode/settings.json index bb033a62..b67b7862 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -70,6 +70,7 @@ "dtype", "Elast", "Epress", + "excepthook", "fastdeploy", "fromarray", "funclib", diff --git a/source/exceptions/common.py b/source/exceptions/common.py index e69de29b..15a66a15 100644 --- a/source/exceptions/common.py +++ b/source/exceptions/common.py @@ -0,0 +1,2 @@ +from source.exceptions.util import * + diff --git a/source/exceptions/mission.py b/source/exceptions/mission.py index d3b27093..335f3844 100644 --- a/source/exceptions/mission.py +++ b/source/exceptions/mission.py @@ -1,6 +1,10 @@ -class MissionEnd(Exception):pass -class CollectError(Exception):pass -class TeyvatMoveError(Exception):pass -class PickUpOperatorError(Exception):pass -class HandleExceptionInMission(Exception):pass -class CharacterNotFound(Exception):pass \ No newline at end of file +from source.exceptions.util import * + +class MissionException(GIABaseException): pass + +class MissionEnd(MissionException):pass +class CollectError(MissionException):pass +class TeyvatMoveError(MissionException):pass +class PickUpOperatorError(MissionException):pass +class HandleExceptionInMission(MissionException):pass +class CharacterNotFound(MissionException):pass \ No newline at end of file diff --git a/source/exceptions/util.py b/source/exceptions/util.py new file mode 100644 index 00000000..8c9b70ee --- /dev/null +++ b/source/exceptions/util.py @@ -0,0 +1,11 @@ +class GIABaseException(Exception): + def __init__(self, *args: object) -> None: + super().__init__(*args) + self.stop_task_flag = False + self.possible_reasons = [] + + +class TaskException(GIABaseException): + def __init__(self, *args: object) -> None: + super().__init__(*args) + self.stop_task_flag = True diff --git a/source/listening.py b/source/listening.py index 53778f14..a2e396eb 100644 --- a/source/listening.py +++ b/source/listening.py @@ -5,12 +5,13 @@ import time import keyboard from source.task import task_manager -from source.mission import mission_manager +import threading combat_flag = False collector_flag = False startstop_flag = False TASK_MANAGER = task_manager.TASK_MANAGER +threading.excepthook = TASK_MANAGER.task_excepthook TASK_MANAGER.setDaemon(True) # TASK_MANAGER.pause_threading() TASK_MANAGER.start() diff --git a/source/task/launch_genshin/launch_genshin.py b/source/task/launch_genshin/launch_genshin.py index 8501369f..ea5cd031 100644 --- a/source/task/launch_genshin/launch_genshin.py +++ b/source/task/launch_genshin/launch_genshin.py @@ -11,6 +11,9 @@ def __init__(self): self.name = "LaunchGenshin" def loop(self): + # time.sleep(2) + # print('exception test') + # raise TaskException() while 1: time.sleep(2) itt.appear_then_click(ClickToEnter) diff --git a/source/task/task_manager.py b/source/task/task_manager.py index 700f99c4..a30cd45d 100644 --- a/source/task/task_manager.py +++ b/source/task/task_manager.py @@ -2,7 +2,7 @@ import keyboard from source.task.task_template import TaskTemplate, TaskEndException from source.common.base_threading import BaseThreading - +from source.exceptions.util import * COLLECTION_PATH_TASK = "CollectionPathTask" DOMAIN_TASK = "DomainTask" @@ -21,6 +21,22 @@ def __init__(self) -> None: self.get_task_list = lambda:[] self.start_tasklist_flag = False + def task_excepthook(self, args): + # if 'stop_task_flag' in args.exc_value.__dict__: + exception_instance = args.exc_value + logger.exception(exception_instance) + if isinstance(GIABaseException, exception_instance): + if args.exc_value.stop_task_flag: + self.stop_tasklist() + if len(exception_instance.possible_reasons) > 0: + i = 0 + for pr in exception_instance.possible_reasons: + i+=1 + logger.error(f'{t2t("Possible Reason")} {i}: {pr}') + + + + def append_task(self, task_name): self.task_list.append(task_name) @@ -52,6 +68,12 @@ def start_stop_tasklist(self): self.start_tasklist_flag = not self.start_tasklist_flag self.curr_task.stop_threading() + def stop_tasklist(self): + if self.start_tasklist_flag: + logger.info(t2t('stopping tasks')) + self.start_tasklist_flag = False + self.curr_task.stop_threading() + def start_stop_task(self, task_name): if not self.reg_task_flag: diff --git a/source/test/test_threading.py b/source/test/test_threading.py new file mode 100644 index 00000000..537a8be1 --- /dev/null +++ b/source/test/test_threading.py @@ -0,0 +1,28 @@ +import threading, time +from loguru import logger + +class CustomException(Exception): + def __init__(self, *args: object) -> None: + super().__init__(*args) + self.stop_manager_flag = True + +def excepthook(args): + print(args.exc_value) + logger.exception(args.exc_value) + +threading.excepthook = excepthook + +def func1(): + for i in range(10): + print(i) + time.sleep(0.2) + if i==3: + raise CustomException + + +t1 = threading.Thread(target=func1) +t1.start() + +while 1: + time.sleep(1) + print('...') \ No newline at end of file From 3849a247585fc11ba6b12a05d7790ef831a02d5b Mon Sep 17 00:00:00 2001 From: infstellar <98541813+infstellar@users.noreply.github.com> Date: Mon, 19 Jun 2023 23:45:31 +0800 Subject: [PATCH 22/40] refactor: tasks --- .../assets.py => assets/claim_rewards.py} | 0 source/exceptions/util.py | 4 +-- .../{ => abandoned}/collection_path_task.py | 0 source/task/{ => abandoned}/collector_task.py | 0 .../{ => abandoned}/mission_generate_task.py | 0 source/task/claim_reward/claim_reward.py | 17 +++++++--- source/task/{ => domain}/domain_task.py | 2 +- source/task/launch_genshin/launch_genshin.py | 6 +--- .../task/ley_line_outcrop/ley_line_outcrop.py | 20 +++++++++-- source/task/{ => mission}/mission_task.py | 0 source/task/task_manager.py | 9 ++--- source/task/task_template.py | 33 +++++++++++++++---- source/util.py | 6 +++- 13 files changed, 68 insertions(+), 29 deletions(-) rename source/{task/claim_reward/assets.py => assets/claim_rewards.py} (100%) rename source/task/{ => abandoned}/collection_path_task.py (100%) rename source/task/{ => abandoned}/collector_task.py (100%) rename source/task/{ => abandoned}/mission_generate_task.py (100%) rename source/task/{ => domain}/domain_task.py (99%) rename source/task/{ => mission}/mission_task.py (100%) diff --git a/source/task/claim_reward/assets.py b/source/assets/claim_rewards.py similarity index 100% rename from source/task/claim_reward/assets.py rename to source/assets/claim_rewards.py diff --git a/source/exceptions/util.py b/source/exceptions/util.py index 8c9b70ee..7b96336a 100644 --- a/source/exceptions/util.py +++ b/source/exceptions/util.py @@ -1,8 +1,8 @@ class GIABaseException(Exception): + possible_reasons = [] def __init__(self, *args: object) -> None: super().__init__(*args) - self.stop_task_flag = False - self.possible_reasons = [] + self.stop_task_flag = False # 当发生该异常时,是否结束所有Task。 class TaskException(GIABaseException): diff --git a/source/task/collection_path_task.py b/source/task/abandoned/collection_path_task.py similarity index 100% rename from source/task/collection_path_task.py rename to source/task/abandoned/collection_path_task.py diff --git a/source/task/collector_task.py b/source/task/abandoned/collector_task.py similarity index 100% rename from source/task/collector_task.py rename to source/task/abandoned/collector_task.py diff --git a/source/task/mission_generate_task.py b/source/task/abandoned/mission_generate_task.py similarity index 100% rename from source/task/mission_generate_task.py rename to source/task/abandoned/mission_generate_task.py diff --git a/source/task/claim_reward/claim_reward.py b/source/task/claim_reward/claim_reward.py index 017923b9..89c21b74 100644 --- a/source/task/claim_reward/claim_reward.py +++ b/source/task/claim_reward/claim_reward.py @@ -3,10 +3,20 @@ from source.task.task_template import TaskTemplate from source.talk.talk import Talk from source.manager import asset -from source.task.claim_reward.assets import * +from source.assets.claim_rewards import * class ClaimRewardMission(MissionExecutor, Talk): + """这个类以MissionExecutor的方式执行任务,因为Mission中已有许多适合该任务的函数可以直接调用。 + + 有关更多这样的Mission型任务的信息,可以参考source.task.ley_line_outcrop,该文件下有更多注释。 + + Args: + MissionExecutor (_type_): _description_ + + Returns: + _type_: _description_ + """ def __init__(self): MissionExecutor.__init__(self, is_TMCF=True) Talk.__init__(self) @@ -78,10 +88,9 @@ def __init__(self): super().__init__() self.CRM = ClaimRewardMission() self._add_sub_threading(self.CRM, start=False) - - def loop(self): + + def task_run(self): self.blocking_startup(self.CRM) - self.pause_threading() if __name__ == '__main__': crm = ClaimRewardMission() diff --git a/source/task/domain_task.py b/source/task/domain/domain_task.py similarity index 99% rename from source/task/domain_task.py rename to source/task/domain/domain_task.py index 9e1db3fc..159a4386 100644 --- a/source/task/domain_task.py +++ b/source/task/domain/domain_task.py @@ -7,7 +7,7 @@ from source.ui.ui import ui_control import source.ui.page as UIPage from source.interaction.interaction_core import itt -from source.manager import asset, scene_manager +from source.manager import asset from source.task import task_id as TI from source.funclib.err_code_lib import ERR_NONE, ERR_STUCK, ERR_PASS from source.common import timer_module diff --git a/source/task/launch_genshin/launch_genshin.py b/source/task/launch_genshin/launch_genshin.py index ea5cd031..d8aba711 100644 --- a/source/task/launch_genshin/launch_genshin.py +++ b/source/task/launch_genshin/launch_genshin.py @@ -10,13 +10,9 @@ def __init__(self): super().__init__() self.name = "LaunchGenshin" - def loop(self): - # time.sleep(2) - # print('exception test') - # raise TaskException() + def task_run(self): while 1: time.sleep(2) itt.appear_then_click(ClickToEnter) if ui_control.verify_page(UIPage.page_main): break - self.pause_threading() diff --git a/source/task/ley_line_outcrop/ley_line_outcrop.py b/source/task/ley_line_outcrop/ley_line_outcrop.py index 2edc9dda..e86283d5 100644 --- a/source/task/ley_line_outcrop/ley_line_outcrop.py +++ b/source/task/ley_line_outcrop/ley_line_outcrop.py @@ -10,6 +10,15 @@ class LeyLineOutcropMission(MissionExecutor): + """这个类以MissionExecutor的方式执行任务,因为Mission中已有许多适合该任务的函数可以直接调用。 + (如果你愿意,可以将这个类修改为符合自定义任务规范的格式,打包成自定义任务(当然没有必要)) + + Args: + MissionExecutor (_type_): _description_ + + Returns: + _type_: _description_ + """ TRAVERSE_MONDSTADT_POSITION=[TianLiPosition([783.450352, -6943.497652]), TianLiPosition([2489.331552, -6101.094052]), TianLiPosition([3101.988752, -6431.458452]), @@ -109,14 +118,19 @@ def exec_mission(self): logger.error(str(e)) class LeyLineOutcropTask(TaskTemplate): + """这个类将一个MissionExecutor类套壳成为TaskTemplate类。 + + Args: + TaskTemplate (_type_): _description_ + """ def __init__(self): super().__init__() self.LLOM = LeyLineOutcropMission() self._add_sub_threading(self.LLOM, start=False) - - def loop(self): + + def task_run(self): + # 阻塞式执行子线程。 self.blocking_startup(self.LLOM) - self.pause_threading() if __name__ == '__main__': # llom = LeyLineOutcropMission() diff --git a/source/task/mission_task.py b/source/task/mission/mission_task.py similarity index 100% rename from source/task/mission_task.py rename to source/task/mission/mission_task.py diff --git a/source/task/task_manager.py b/source/task/task_manager.py index a30cd45d..e37ce6d6 100644 --- a/source/task/task_manager.py +++ b/source/task/task_manager.py @@ -1,6 +1,6 @@ from source.util import * import keyboard -from source.task.task_template import TaskTemplate, TaskEndException +from source.task.task_template import TaskTemplate from source.common.base_threading import BaseThreading from source.exceptions.util import * @@ -33,9 +33,6 @@ def task_excepthook(self, args): for pr in exception_instance.possible_reasons: i+=1 logger.error(f'{t2t("Possible Reason")} {i}: {pr}') - - - def append_task(self, task_name): self.task_list.append(task_name) @@ -82,11 +79,11 @@ def start_stop_task(self, task_name): # self.curr_task.end_task() # self.reg_task_flag = not self.reg_task_flag if task_name == DOMAIN_TASK: - from source.task.domain_task import DomainTask + from source.task.domain.domain_task import DomainTask self.curr_task = DomainTask() elif task_name == MISSION_TASK: - from source.task.mission_task import MissionTask + from source.task.mission.mission_task import MissionTask self.curr_task = MissionTask() elif task_name == COMMISSION_TASK: from source.commission.commission_executor import CommissionExecutor diff --git a/source/task/task_template.py b/source/task/task_template.py index 5471d243..cb557113 100644 --- a/source/task/task_template.py +++ b/source/task/task_template.py @@ -1,11 +1,9 @@ from source.util import * -from source.common.base_threading import AdvanceThreading, BaseThreading -from source.flow.flow_template import FlowController -import threading +from source.common.base_threading import AdvanceThreading -class TaskEndException(Exception): - pass +# class TaskEndException(Exception): +# pass class TaskTemplate(AdvanceThreading): def __init__(self): @@ -15,10 +13,31 @@ def __init__(self): self.name = "" def terminate_task(self): + """强制终止任务。 + """ logger.info(f"terminate task {self.name}") self.stop_threading() def get_statement(self): + """可以重写此方法,用于在GUI中显示当前任务执行情况。 + + Returns: + _type_: _description_ + """ return "Statement Not Register Yet" - - \ No newline at end of file + + def task_run(self): + """ + 使用task时,重写此方法。 + 该函数只会运行一次。函数结束后任务结束。 + """ + pass + + def loop(self): + """ + 如果你已经了解了GIA的线程架构,你可以重写此方法以执行任务。 + 当然,在task_run中写个while 1也不费事( + """ + self.task_run() + self.pause_threading() + \ No newline at end of file diff --git a/source/util.py b/source/util.py index bd7e607f..13d80144 100644 --- a/source/util.py +++ b/source/util.py @@ -5,11 +5,14 @@ import cv2, yaml from PIL import Image, ImageDraw, ImageFont from collections import OrderedDict +from typing import Union + ROOT_PATH = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) SOURCE_PATH = ROOT_PATH + '\\source' ASSETS_PATH = ROOT_PATH + '\\assets' if sys.path[0] != ROOT_PATH: sys.path.insert(0, ROOT_PATH) if sys.path[1] != SOURCE_PATH: sys.path.insert(1, SOURCE_PATH) + from source.logger import logger from source.config.config import GIAconfig from source.i18n import t2t, GLOBAL_LANG @@ -21,6 +24,7 @@ shutil pickle traceback +Union DEBUG_MODE = GIAconfig.General_DEBUG DEMO_MODE = False @@ -28,7 +32,7 @@ IS_DEVICE_PC = True # load config file -def load_json(json_name='General.json', folder_path='config\\settings', auto_create = False) -> dict: +def load_json(json_name='General.json', folder_path='config\\settings', auto_create = False) -> Union[dict,list]: """加载json. Args: From a5efc9cd593adcb04ac5c1b0bf14adf396618deb Mon Sep 17 00:00:00 2001 From: infstellar <98541813+infstellar@users.noreply.github.com> Date: Mon, 19 Jun 2023 23:48:58 +0800 Subject: [PATCH 23/40] refactor: move files --- genshin_assistant.py | 2 +- source/{common => }/generic_event.py | 0 source/{ => test}/bing_code/code1.py | 0 source/{ => test}/bing_code/code2.py | 0 source/{ => test}/bing_code/code3.py | 0 5 files changed, 1 insertion(+), 1 deletion(-) rename source/{common => }/generic_event.py (100%) rename source/{ => test}/bing_code/code1.py (100%) rename source/{ => test}/bing_code/code2.py (100%) rename source/{ => test}/bing_code/code3.py (100%) diff --git a/genshin_assistant.py b/genshin_assistant.py index d9297169..20b34099 100644 --- a/genshin_assistant.py +++ b/genshin_assistant.py @@ -36,7 +36,7 @@ def server_thread(): input(source.util.t2t('程序暂停。按任意键退出')) try: - import source.common.generic_event + import source.generic_event except Exception as error: source.util.logger.critical(source.util.t2t("导入依赖时错误")) IMPORT_ERROR_2.log() diff --git a/source/common/generic_event.py b/source/generic_event.py similarity index 100% rename from source/common/generic_event.py rename to source/generic_event.py diff --git a/source/bing_code/code1.py b/source/test/bing_code/code1.py similarity index 100% rename from source/bing_code/code1.py rename to source/test/bing_code/code1.py diff --git a/source/bing_code/code2.py b/source/test/bing_code/code2.py similarity index 100% rename from source/bing_code/code2.py rename to source/test/bing_code/code2.py diff --git a/source/bing_code/code3.py b/source/test/bing_code/code3.py similarity index 100% rename from source/bing_code/code3.py rename to source/test/bing_code/code3.py From 18f9c25892746144854588f0eeda0988955f8bce Mon Sep 17 00:00:00 2001 From: infstellar <98541813+infstellar@users.noreply.github.com> Date: Tue, 20 Jun 2023 00:01:28 +0800 Subject: [PATCH 24/40] docs: base_threading --- source/common/base_threading.py | 59 +++++++++++++++++++++++++++------ 1 file changed, 49 insertions(+), 10 deletions(-) diff --git a/source/common/base_threading.py b/source/common/base_threading.py index 473ba6be..26307a8f 100644 --- a/source/common/base_threading.py +++ b/source/common/base_threading.py @@ -25,30 +25,39 @@ def __init__(self, thread_name = None): self.setName(thread_name) def pause_threading(self): + """ + 暂停线程执行。线程会进行等待。 + + 如果不是想要线程彻底结束,而是暂时停止,使用此方法。 + + 需要在内部使用checkup_stop_func退出到run函数中,才能有效停止。 + """ if self.pause_threading_flag != True: logger.debug(f"{self.name} pause threading") self.pause_threading_flag = True def continue_threading(self): + """ + 继续线程执行。 + """ if self.pause_threading_flag != False: logger.debug(f"{self.name} continue threading") self.pause_threading_flag = False def stop_threading(self): + """ + 终止线程。 + + 需要在内部使用checkup_stop_threading或checkup_stop_func(推荐)退出到run函数中,才能有效停止。 + """ logger.debug(f"{self.name} stopping.") self.stop_threading_flag = True self.pause_threading_flag = True self._clean_sub_threading() - def checkup_stop_threading(self): - if self.stop_threading_flag: - return True - - def get_working_statement(self): - return not self.pause_threading_flag - def checkup_stop_func(self): - """检查是否要退出。会检查暂停flag和停止flag。 + """ + 检查是否要退出。会检查暂停flag和停止flag。 使用方法: 在函数中使用: if self.checkup_stop_func(): return 适当的返回值 @@ -75,19 +84,38 @@ def output_log(t): return True output_log(time.time()-pt) return False + + def checkup_stop_threading(self): + """ + 检查是否要结束线程。只检查停止flag。 - def add_stop_func(self, x): - self.stop_func_list.append(x) + Returns: + _type_: _description_ + """ + if self.stop_threading_flag: + return True def get_last_err_code(self): + """获得最后的错误代码。 + + Returns: + _type_: _description_ + """ return self.last_err_code def get_and_reset_err_code(self): + """获得并重置错误代码。 + + Returns: + _type_: _description_ + """ erc = self.last_err_code self.reset_err_code() return erc def reset_err_code(self): + """重置错误代码。 + """ self.last_err_code = ERR_NONE def _add_sub_threading(self, threading_obj, start=True): @@ -140,8 +168,19 @@ def run(self): continue self.loop() + + def get_working_statement(self): + return not self.pause_threading_flag + + def add_stop_func(self, x): + self.stop_func_list.append(x) class AdvanceThreading(BaseThreading): + """升级版线程。推荐使用这个。 + + Args: + BaseThreading (_type_): _description_ + """ def __init__(self, thread_name=None): super().__init__(thread_name) From 04882dfc3ae71824ec9729b5d4528246f18ece52 Mon Sep 17 00:00:00 2001 From: infstellar <2644641825@qq.com> Date: Tue, 20 Jun 2023 20:26:33 +0800 Subject: [PATCH 25/40] refactor: move files --- source/{operator => combat}/aim_operator.py | 0 source/{controller => combat}/combat_controller.py | 2 +- source/{operator => combat}/switch_character_operator.py | 4 ++-- source/{operator => combat}/tactic_operator.py | 0 source/flow/alpha_loop.py | 2 +- source/flow/collector_flow.py | 2 +- source/flow/collector_flow_upgrad.py | 2 +- source/flow/domain_flow_upgrad.py | 2 +- source/listening.py | 2 +- source/mission/mission_template.py | 2 +- 10 files changed, 9 insertions(+), 9 deletions(-) rename source/{operator => combat}/aim_operator.py (100%) rename source/{controller => combat}/combat_controller.py (96%) rename source/{operator => combat}/switch_character_operator.py (99%) rename source/{operator => combat}/tactic_operator.py (100%) diff --git a/source/operator/aim_operator.py b/source/combat/aim_operator.py similarity index 100% rename from source/operator/aim_operator.py rename to source/combat/aim_operator.py diff --git a/source/controller/combat_controller.py b/source/combat/combat_controller.py similarity index 96% rename from source/controller/combat_controller.py rename to source/combat/combat_controller.py index ffe204bf..48ad8d56 100644 --- a/source/controller/combat_controller.py +++ b/source/combat/combat_controller.py @@ -7,7 +7,7 @@ from source.manager import asset from source.common.base_threading import AdvanceThreading from source.interaction.interaction_core import itt -from source.operator.switch_character_operator import SwitchCharacterOperator +from source.combat.switch_character_operator import SwitchCharacterOperator from source.path_lib import CONFIG_PATH_SETTING CHARACTER_DIED = 1 diff --git a/source/operator/switch_character_operator.py b/source/combat/switch_character_operator.py similarity index 99% rename from source/operator/switch_character_operator.py rename to source/combat/switch_character_operator.py index e0ae1989..3b1e04a1 100644 --- a/source/operator/switch_character_operator.py +++ b/source/combat/switch_character_operator.py @@ -1,12 +1,12 @@ from source.common import character from source.funclib import combat_lib -from source.operator import tactic_operator +from source.combat import tactic_operator from source.common.base_threading import BaseThreading from source.interaction.interaction_core import itt from common.timer_module import Timer, AdvanceTimer from source.util import * from source.manager import asset -from source.operator.aim_operator import AimOperator +from source.combat.aim_operator import AimOperator from source.api.pdocr_complete import ocr from source.funclib import movement from source.ui.ui import ui_control diff --git a/source/operator/tactic_operator.py b/source/combat/tactic_operator.py similarity index 100% rename from source/operator/tactic_operator.py rename to source/combat/tactic_operator.py diff --git a/source/flow/alpha_loop.py b/source/flow/alpha_loop.py index 89540405..bf1f1aaa 100644 --- a/source/flow/alpha_loop.py +++ b/source/flow/alpha_loop.py @@ -1,4 +1,4 @@ -from source.controller import combat_controller +from source.combat import combat_controller from source.common.base_threading import BaseThreading from source.funclib import combat_lib from source.util import * diff --git a/source/flow/collector_flow.py b/source/flow/collector_flow.py index ce96f935..8487f784 100644 --- a/source/flow/collector_flow.py +++ b/source/flow/collector_flow.py @@ -4,7 +4,7 @@ from source.pickup import pickup_operator from source.flow import teyvat_move_flow from source.interaction.minimap_tracker import tracker -from source.controller import combat_controller +from source.combat import combat_controller from source.common.base_threading import BaseThreading from source.funclib import collector_lib, generic_lib, combat_lib import numpy as np diff --git a/source/flow/collector_flow_upgrad.py b/source/flow/collector_flow_upgrad.py index 49505b13..966df711 100644 --- a/source/flow/collector_flow_upgrad.py +++ b/source/flow/collector_flow_upgrad.py @@ -4,7 +4,7 @@ from source.interaction.interaction_core import itt from source.pickup import pickup_operator from source.interaction.minimap_tracker import tracker -from source.controller import combat_controller +from source.combat import combat_controller from funclib.err_code_lib import ERR_PASS, ERR_STUCK, ERR_COLLECTOR_FLOW_TIMEOUT from source.util import * from source.flow.flow_template import FlowController, FlowTemplate, FlowConnector, EndFlowTemplate diff --git a/source/flow/domain_flow_upgrad.py b/source/flow/domain_flow_upgrad.py index 65da1c78..d1630e0d 100644 --- a/source/flow/domain_flow_upgrad.py +++ b/source/flow/domain_flow_upgrad.py @@ -1,7 +1,7 @@ from source.util import * from source.flow.flow_template import FlowController, FlowTemplate, FlowConnector, EndFlowTemplate import source.flow.flow_code as FC -from source.controller import combat_controller +from source.combat import combat_controller from common import timer_module from source.funclib import generic_lib, movement from source.funclib.err_code_lib import * diff --git a/source/listening.py b/source/listening.py index a2e396eb..8444f3f3 100644 --- a/source/listening.py +++ b/source/listening.py @@ -76,7 +76,7 @@ def switch_combat_loop(): logger.info(t2t('正在停止自动战斗')) t1.stop_threading() else: - from source.controller.combat_controller import CombatController + from source.combat.combat_controller import CombatController logger.info(t2t('启动自动战斗')) t1 = CombatController() t1.setDaemon(True) diff --git a/source/mission/mission_template.py b/source/mission/mission_template.py index 356f733d..cd50523b 100644 --- a/source/mission/mission_template.py +++ b/source/mission/mission_template.py @@ -7,7 +7,7 @@ from source.interaction.interaction_core import itt from source.funclib.err_code_lib import ERR_PASS, ERR_STUCK from source.common.timer_module import AdvanceTimer -from source.controller.combat_controller import CombatController +from source.combat.combat_controller import CombatController from source.map.map import genshin_map from source.exceptions.mission import * from source.mission.cvars import * From 949c5a838b48d6e0707d4decf9c4ae35d3c93a46 Mon Sep 17 00:00:00 2001 From: infstellar <98541813+infstellar@users.noreply.github.com> Date: Tue, 20 Jun 2023 23:10:50 +0800 Subject: [PATCH 26/40] refactor: flows --- source/combat/__init__.py | 0 source/commission/commission.py | 2 +- source/flow/{ => abandoned}/alpha_loop.py | 0 source/flow/{ => abandoned}/collector_flow.py | 0 ...collector_flow_upgrad.py => collector_flow_upgrade.py} | 8 ++++---- source/flow/path_recorder_flow.py | 4 ++-- ...at_move_flow_upgrad.py => teyvat_move_flow_upgrade.py} | 8 ++++---- source/flow/utils/__init__.py | 0 source/flow/{ => utils}/cvars.py | 0 source/flow/{ => utils}/flow_code.py | 0 source/flow/{ => utils}/flow_state.py | 0 source/flow/{ => utils}/flow_template.py | 2 +- source/listening.py | 6 +++--- source/mission/cvars.py | 2 +- source/mission/mission.py | 2 +- source/mission/mission/collector.py | 4 ++-- source/mission/mission_template.py | 6 +++--- source/pickup/__init__.py | 0 source/task/abandoned/collector_task.py | 2 +- source/task/abandoned/mission_generate_task.py | 2 +- .../domain/domain_flow_upgrade.py} | 6 +++--- source/task/domain/domain_task.py | 4 ++-- 22 files changed, 29 insertions(+), 29 deletions(-) create mode 100644 source/combat/__init__.py rename source/flow/{ => abandoned}/alpha_loop.py (100%) rename source/flow/{ => abandoned}/collector_flow.py (100%) rename source/flow/{collector_flow_upgrad.py => collector_flow_upgrade.py} (97%) rename source/flow/{teyvat_move_flow_upgrad.py => teyvat_move_flow_upgrade.py} (99%) create mode 100644 source/flow/utils/__init__.py rename source/flow/{ => utils}/cvars.py (100%) rename source/flow/{ => utils}/flow_code.py (100%) rename source/flow/{ => utils}/flow_state.py (100%) rename source/flow/{ => utils}/flow_template.py (99%) create mode 100644 source/pickup/__init__.py rename source/{flow/domain_flow_upgrad.py => task/domain/domain_flow_upgrade.py} (97%) diff --git a/source/combat/__init__.py b/source/combat/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/source/commission/commission.py b/source/commission/commission.py index f9b4a784..0d6aba70 100644 --- a/source/commission/commission.py +++ b/source/commission/commission.py @@ -2,7 +2,7 @@ from source.manager.asset import Text from source.commission.assets import * from source.commission.util import * -from source.flow.cvars import * +from source.flow.utils.cvars import * class Commission(CommissionTemplate): """ diff --git a/source/flow/alpha_loop.py b/source/flow/abandoned/alpha_loop.py similarity index 100% rename from source/flow/alpha_loop.py rename to source/flow/abandoned/alpha_loop.py diff --git a/source/flow/collector_flow.py b/source/flow/abandoned/collector_flow.py similarity index 100% rename from source/flow/collector_flow.py rename to source/flow/abandoned/collector_flow.py diff --git a/source/flow/collector_flow_upgrad.py b/source/flow/collector_flow_upgrade.py similarity index 97% rename from source/flow/collector_flow_upgrad.py rename to source/flow/collector_flow_upgrade.py index 966df711..485eb6c8 100644 --- a/source/flow/collector_flow_upgrad.py +++ b/source/flow/collector_flow_upgrade.py @@ -1,14 +1,14 @@ from source.util import * -from common import timer_module -from source.flow import flow_state as ST +from source.common import timer_module +from source.flow.utils import flow_state as ST from source.interaction.interaction_core import itt from source.pickup import pickup_operator from source.interaction.minimap_tracker import tracker from source.combat import combat_controller from funclib.err_code_lib import ERR_PASS, ERR_STUCK, ERR_COLLECTOR_FLOW_TIMEOUT from source.util import * -from source.flow.flow_template import FlowController, FlowTemplate, FlowConnector, EndFlowTemplate -import source.flow.flow_code as FC +from source.flow.utils.flow_template import FlowController, FlowTemplate, FlowConnector, EndFlowTemplate +import source.flow.utils.flow_code as FC from source.common import timer_module from source.funclib import movement from source.funclib import combat_lib diff --git a/source/flow/path_recorder_flow.py b/source/flow/path_recorder_flow.py index ace4a4cc..5c9a64e4 100644 --- a/source/flow/path_recorder_flow.py +++ b/source/flow/path_recorder_flow.py @@ -1,7 +1,7 @@ from source.util import * import keyboard -from source.flow.flow_template import FlowController, FlowTemplate, FlowConnector, EndFlowTemplate -import source.flow.flow_code as FC, source.flow.flow_state as ST +from source.flow.utils.flow_template import FlowController, FlowTemplate, FlowConnector, EndFlowTemplate +import source.flow.utils.flow_code as FC, source.flow.utils.flow_state as ST from source.interaction.minimap_tracker import tracker from source.funclib import movement, generic_lib, collector_lib from source.funclib.err_code_lib import * diff --git a/source/flow/teyvat_move_flow_upgrad.py b/source/flow/teyvat_move_flow_upgrade.py similarity index 99% rename from source/flow/teyvat_move_flow_upgrad.py rename to source/flow/teyvat_move_flow_upgrade.py index ff7f8312..9d249d6f 100644 --- a/source/flow/teyvat_move_flow_upgrad.py +++ b/source/flow/teyvat_move_flow_upgrade.py @@ -7,14 +7,14 @@ from source.ui.ui import ui_control import source.ui.page as UIPage from source.map.map import genshin_map -from source.flow.flow_template import FlowConnector, FlowController, FlowTemplate, EndFlowTemplate -from source.flow import flow_state as ST -from source.flow import flow_code as FC +from source.flow.utils.flow_template import FlowConnector, FlowController, FlowTemplate, EndFlowTemplate +from source.flow.utils import flow_state as ST +from source.flow.utils import flow_code as FC from source.ui.ui import ui_control import source.ui.page as UIPage from source.dev_tool.tianli_navigator import TianliNavigator from source.funclib import combat_lib -from source.flow.cvars import * +from source.flow.utils.cvars import * diff --git a/source/flow/utils/__init__.py b/source/flow/utils/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/source/flow/cvars.py b/source/flow/utils/cvars.py similarity index 100% rename from source/flow/cvars.py rename to source/flow/utils/cvars.py diff --git a/source/flow/flow_code.py b/source/flow/utils/flow_code.py similarity index 100% rename from source/flow/flow_code.py rename to source/flow/utils/flow_code.py diff --git a/source/flow/flow_state.py b/source/flow/utils/flow_state.py similarity index 100% rename from source/flow/flow_state.py rename to source/flow/utils/flow_state.py diff --git a/source/flow/flow_template.py b/source/flow/utils/flow_template.py similarity index 99% rename from source/flow/flow_template.py rename to source/flow/utils/flow_template.py index 35cdae50..d65c17bc 100644 --- a/source/flow/flow_template.py +++ b/source/flow/utils/flow_template.py @@ -1,5 +1,5 @@ from source.util import * -import source.flow.flow_code as FC +import source.flow.utils.flow_code as FC from common import flow_state as FlowState, flow_state as ST from source.common import base_threading, timer_module from source.funclib.err_code_lib import * diff --git a/source/listening.py b/source/listening.py index 8444f3f3..3ed7553b 100644 --- a/source/listening.py +++ b/source/listening.py @@ -48,7 +48,7 @@ def import_current_module(): pass elif current_flow == FLOW_COMBAT: # logger.info("正在导入 FLOW_COMBAT 模块,可能需要一些时间。") - from source.flow import alpha_loop + from source.flow.abandoned import alpha_loop elif current_flow == FLOW_DOMAIN: # logger.info("正在导入 FLOW_DOMAIN 模块,可能需要一些时间。") from source.flow import domain_flow @@ -61,7 +61,7 @@ def import_current_module(): pass elif current_flow == FLOW_COMBAT: # logger.info("正在导入 FLOW_COMBAT 模块,可能需要一些时间。") - from source.flow import alpha_loop + from source.flow.abandoned import alpha_loop # elif current_flow == FLOW_COLLECTOR: # # logger.info("正在导入 FLOW_COLLECTOR 模块,可能需要一些时间。") # from source.flow import collector_flow @@ -92,7 +92,7 @@ def switch_collector_loop(): t3.stop_threading() else: logger.info(t2t('启动自动采集')) - from source.flow import collector_flow + from source.flow.abandoned import collector_flow t3 = collector_flow.CollectorFlow() t3.setDaemon(True) t3.start() diff --git a/source/mission/cvars.py b/source/mission/cvars.py index 2825babf..dc9c8986 100644 --- a/source/mission/cvars.py +++ b/source/mission/cvars.py @@ -1,4 +1,4 @@ -from source.flow.cvars import * +from source.flow.utils.cvars import * ERR_FAIL = "FAIL" EXCEPTION_RECOVER = 'recover' EXCEPTION_SKIP = 'skip' diff --git a/source/mission/mission.py b/source/mission/mission.py index 03e58656..0756ac70 100644 --- a/source/mission/mission.py +++ b/source/mission/mission.py @@ -1,6 +1,6 @@ from source.mission.mission_template import MissionExecutor from source.mission.cvars import * -from source.flow.cvars import * +from source.flow.utils.cvars import * """ 这里是Mission的标准类.编写你的mission时,请继承该类. diff --git a/source/mission/mission/collector.py b/source/mission/mission/collector.py index 91d6fd51..7bd48983 100644 --- a/source/mission/mission/collector.py +++ b/source/mission/mission/collector.py @@ -1,10 +1,10 @@ from source.mission.mission.util import * from source.mission.mission.base import MissionBase -from source.flow import collector_flow_upgrad +from source.flow import collector_flow_upgrade class MissionCollector(): def __init__(self) -> None: - self.CFCF = collector_flow_upgrad.CollectorFlowController() + self.CFCF = collector_flow_upgrade.CollectorFlowController() self._add_sub_threading(self.CFCF, start=False) self.CFCF_initialized = True self.CFCF.start() \ No newline at end of file diff --git a/source/mission/mission_template.py b/source/mission/mission_template.py index cd50523b..8f812c77 100644 --- a/source/mission/mission_template.py +++ b/source/mission/mission_template.py @@ -1,5 +1,5 @@ from source.util import * -from source.flow import collector_flow_upgrad, teyvat_move_flow_upgrad +from source.flow import collector_flow_upgrade, teyvat_move_flow_upgrade from source.common.base_threading import BaseThreading from source.pickup.pickup_operator import PickupOperator from source.interaction.minimap_tracker import tracker @@ -53,13 +53,13 @@ def __init__(self, is_CFCF=False, is_TMCF=False, is_PUO=False, is_CCT=False): def _init_sub_threading(self, feat_name=""): if feat_name == "CFCF": if not self.CFCF_initialized: - self.CFCF = collector_flow_upgrad.CollectorFlowController() + self.CFCF = collector_flow_upgrade.CollectorFlowController() self._add_sub_threading(self.CFCF, start=False) self.CFCF_initialized = True self.CFCF.start() if feat_name == "TMCF": if not self.TMCF_initialized: - self.TMCF = teyvat_move_flow_upgrad.TeyvatMoveFlowController() + self.TMCF = teyvat_move_flow_upgrade.TeyvatMoveFlowController() self._add_sub_threading(self.TMCF, start=False) self.TMCF_initialized = True self.TMCF.start() diff --git a/source/pickup/__init__.py b/source/pickup/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/source/task/abandoned/collector_task.py b/source/task/abandoned/collector_task.py index 5f0cf76d..f63094b8 100644 --- a/source/task/abandoned/collector_task.py +++ b/source/task/abandoned/collector_task.py @@ -1,5 +1,5 @@ from source.task.task_template import TaskTemplate -from source.flow.domain_flow_upgrad import DomainFlowController +from source.task.domain.domain_flow_upgrade import DomainFlowController class CollectorTask(TaskTemplate): diff --git a/source/task/abandoned/mission_generate_task.py b/source/task/abandoned/mission_generate_task.py index 16ffa212..4d16a23a 100644 --- a/source/task/abandoned/mission_generate_task.py +++ b/source/task/abandoned/mission_generate_task.py @@ -2,7 +2,7 @@ from source.task.task_template import TaskTemplate from source.flow.path_recorder_flow import PathRecorderController -from source.flow.collector_flow_upgrad import CollectorFlowController +from source.flow.collector_flow_upgrade import CollectorFlowController from source.map.map import genshin_map """ diff --git a/source/flow/domain_flow_upgrad.py b/source/task/domain/domain_flow_upgrade.py similarity index 97% rename from source/flow/domain_flow_upgrad.py rename to source/task/domain/domain_flow_upgrade.py index d1630e0d..5462e971 100644 --- a/source/flow/domain_flow_upgrad.py +++ b/source/task/domain/domain_flow_upgrade.py @@ -1,6 +1,6 @@ from source.util import * -from source.flow.flow_template import FlowController, FlowTemplate, FlowConnector, EndFlowTemplate -import source.flow.flow_code as FC +from source.flow.utils.flow_template import FlowController, FlowTemplate, FlowConnector, EndFlowTemplate +import source.flow.utils.flow_code as FC from source.combat import combat_controller from common import timer_module from source.funclib import generic_lib, movement @@ -8,7 +8,7 @@ from source.manager import posi_manager as PosiM, asset from source.interaction.interaction_core import itt from source.api import yolox_api -from source.flow import flow_state as ST +from source.flow.utils import flow_state as ST from source.assets.domain import * from source.common.timer_module import AdvanceTimer from source.ui import page as UIPage diff --git a/source/task/domain/domain_task.py b/source/task/domain/domain_task.py index 159a4386..3570d4aa 100644 --- a/source/task/domain/domain_task.py +++ b/source/task/domain/domain_task.py @@ -1,6 +1,6 @@ from source.util import * -from source.flow.domain_flow_upgrad import DomainFlowController -from source.flow.teyvat_move_flow_upgrad import TeyvatMoveFlowController +from source.task.domain.domain_flow_upgrade import DomainFlowController +from source.flow.teyvat_move_flow_upgrade import TeyvatMoveFlowController from source.task.task_template import TaskTemplate from source.funclib.collector_lib import load_items_position from source.funclib.generic_lib import f_recognition From 9e99ccd18a7c5c97c8fb51c0b65b6eec40641d08 Mon Sep 17 00:00:00 2001 From: infstellar <98541813+infstellar@users.noreply.github.com> Date: Tue, 20 Jun 2023 23:40:51 +0800 Subject: [PATCH 27/40] refactor: log: store log files in folder --- source/exceptions/advance.py | 17 +++++++++++++++++ source/exceptions/util.py | 6 ++++-- source/logger.py | 2 +- 3 files changed, 22 insertions(+), 3 deletions(-) create mode 100644 source/exceptions/advance.py diff --git a/source/exceptions/advance.py b/source/exceptions/advance.py new file mode 100644 index 00000000..4ff594b0 --- /dev/null +++ b/source/exceptions/advance.py @@ -0,0 +1,17 @@ +from source.exceptions.util import * + +# 这个类可以调用itt。请注意避免调用循环。 + +from source.interaction.interaction_core import itt +from source.util import * + +class SnapShotException(GIABaseException): + def __init__(self, *args: object, reason: str = None) -> None: + super().__init__(*args, reason=reason) + + def save_snapshot(self): + cap = itt.capture(jpgmode=0) + cv2.imwrite(os.path.join(ROOT_PATH, "Logs/{time:YYYY-MM-DD}", f"{round(time.time(),2)}-.jpg"), cap) + +if __name__ == '__main__': + pass \ No newline at end of file diff --git a/source/exceptions/util.py b/source/exceptions/util.py index 7b96336a..e70e4d10 100644 --- a/source/exceptions/util.py +++ b/source/exceptions/util.py @@ -1,11 +1,13 @@ class GIABaseException(Exception): possible_reasons = [] - def __init__(self, *args: object) -> None: + def __init__(self, *args: object, reason:str = None) -> None: super().__init__(*args) self.stop_task_flag = False # 当发生该异常时,是否结束所有Task。 - + self.reason = reason class TaskException(GIABaseException): def __init__(self, *args: object) -> None: super().__init__(*args) self.stop_task_flag = True + + diff --git a/source/logger.py b/source/logger.py index c65d3b5d..329e275e 100644 --- a/source/logger.py +++ b/source/logger.py @@ -28,7 +28,7 @@ def demo(self, message): # configure loguru logger.remove(handler_id=None) -logger.add(os.path.join(ROOT_PATH, os.path.join(ROOT_PATH, 'Logs', "{time:YYYY-MM-DD}.log")), level="TRACE", backtrace=True, retention='15 days') +logger.add(os.path.join(ROOT_PATH, os.path.join(ROOT_PATH, 'Logs', "{time:YYYY-MM-DD}/{time:YYYY-MM-DD}.log")), level="TRACE", backtrace=True, retention='15 days') if DEBUG_MODE: logger.add(sys.stdout, level="TRACE", backtrace=True) else: From 2a7a3163326b4e6683ea715a29850695b125b664 Mon Sep 17 00:00:00 2001 From: infstellar <98541813+infstellar@users.noreply.github.com> Date: Wed, 21 Jun 2023 19:40:23 +0800 Subject: [PATCH 28/40] feat: _cover_privacy --- source/exceptions/advance.py | 12 ------------ source/exceptions/common.py | 1 + source/exceptions/mission.py | 18 +++++++++++++----- source/exceptions/util.py | 14 ++++++++++---- source/interaction/capture.py | 11 +++++++++-- source/util.py | 1 + 6 files changed, 34 insertions(+), 23 deletions(-) diff --git a/source/exceptions/advance.py b/source/exceptions/advance.py index 4ff594b0..cffe0f68 100644 --- a/source/exceptions/advance.py +++ b/source/exceptions/advance.py @@ -1,17 +1,5 @@ from source.exceptions.util import * -# 这个类可以调用itt。请注意避免调用循环。 - -from source.interaction.interaction_core import itt -from source.util import * - -class SnapShotException(GIABaseException): - def __init__(self, *args: object, reason: str = None) -> None: - super().__init__(*args, reason=reason) - - def save_snapshot(self): - cap = itt.capture(jpgmode=0) - cv2.imwrite(os.path.join(ROOT_PATH, "Logs/{time:YYYY-MM-DD}", f"{round(time.time(),2)}-.jpg"), cap) if __name__ == '__main__': pass \ No newline at end of file diff --git a/source/exceptions/common.py b/source/exceptions/common.py index 15a66a15..a08d1479 100644 --- a/source/exceptions/common.py +++ b/source/exceptions/common.py @@ -1,2 +1,3 @@ from source.exceptions.util import * +from source.util import * diff --git a/source/exceptions/mission.py b/source/exceptions/mission.py index 335f3844..67a37694 100644 --- a/source/exceptions/mission.py +++ b/source/exceptions/mission.py @@ -3,8 +3,16 @@ class MissionException(GIABaseException): pass class MissionEnd(MissionException):pass -class CollectError(MissionException):pass -class TeyvatMoveError(MissionException):pass -class PickUpOperatorError(MissionException):pass -class HandleExceptionInMission(MissionException):pass -class CharacterNotFound(MissionException):pass \ No newline at end of file +class CollectError(MissionException): + POSSIBLE_REASONS = [] +class TeyvatMoveError(MissionException): + POSSIBLE_REASONS = [] +class PickUpOperatorError(MissionException): + POSSIBLE_REASONS = [] +class HandleExceptionInMission(MissionException): + POSSIBLE_REASONS = [] +class CharacterNotFound(MissionException): + POSSIBLE_REASONS = [ + t2t("The character is not on the team"), + t2t("The character name is incorrectly identified. Please submit a log.") + ] \ No newline at end of file diff --git a/source/exceptions/util.py b/source/exceptions/util.py index e70e4d10..ca2190bf 100644 --- a/source/exceptions/util.py +++ b/source/exceptions/util.py @@ -1,13 +1,19 @@ +from source.util import * + class GIABaseException(Exception): - possible_reasons = [] - def __init__(self, *args: object, reason:str = None) -> None: + POSSIBLE_REASONS = [] + def __init__(self, *args: object) -> None: super().__init__(*args) self.stop_task_flag = False # 当发生该异常时,是否结束所有Task。 - self.reason = reason class TaskException(GIABaseException): def __init__(self, *args: object) -> None: super().__init__(*args) self.stop_task_flag = True - +class SnapshotException(GIABaseException): + def __init__(self, *args: object) -> None: + super().__init__(*args) + + def save_snapshot(self, img): + cv2.imwrite(os.path.join(ROOT_PATH, "Logs/{time:YYYY-MM-DD}", f"{round(time.time(),2)}-{self.__str__()}.jpg"), img) diff --git a/source/interaction/capture.py b/source/interaction/capture.py index 3b00eeb8..3f4354a4 100644 --- a/source/interaction/capture.py +++ b/source/interaction/capture.py @@ -18,6 +18,9 @@ def __init__(self): self.cap_per_sec = timer_module.CyclicCounter(limit=3).start() self.last_cap_times = 0 + def _cover_privacy(self, img: ndarray) -> ndarray: + return img + def _get_capture(self) -> np.ndarray: """ 需要根据不同设备实现该函数。 @@ -60,9 +63,9 @@ def _capture(self, is_next_img) -> None: self.fps_timer.reset() self.capture_cache_lock.acquire() self.capture_times+=1 - self.capture_cache = self._get_capture() + self.capture_cache = self._cover_privacy(self._get_capture()) while 1: - self.capture_cache = self._get_capture() + self.capture_cache = self._cover_privacy(self._get_capture()) if not self._check_shape(self.capture_cache): logger.warning( t2t("Fail to get capture: ")+ @@ -169,6 +172,10 @@ def _get_capture(self): ret = np.frombuffer(buffer, dtype=np.uint8).reshape(height, width, 4) return ret + def _cover_privacy(self, img) -> ndarray: + img[1056 : 1075, 1770 : 1863, :3] = 0 + return img + class CloudCapture(Capture): def __init__(self): super().__init__() diff --git a/source/util.py b/source/util.py index 13d80144..a0cd8cdc 100644 --- a/source/util.py +++ b/source/util.py @@ -2,6 +2,7 @@ import time, math, shutil, sys, os, json import win32gui, win32process, psutil, ctypes, pickle, traceback import numpy as np +from numpy import ndarray import cv2, yaml from PIL import Image, ImageDraw, ImageFont from collections import OrderedDict From d856e49849128578f70bcb0d4510622e8ad4b8c2 Mon Sep 17 00:00:00 2001 From: infstellar <98541813+infstellar@users.noreply.github.com> Date: Wed, 21 Jun 2023 20:01:37 +0800 Subject: [PATCH 29/40] feat: SnapshotException --- .gitignore | 21 ++++----------------- source/exceptions/test.py | 9 +++++++++ source/exceptions/util.py | 8 ++++++-- source/interaction/capture.py | 3 ++- source/logger.py | 10 +++++++++- source/util.py | 2 +- 6 files changed, 31 insertions(+), 22 deletions(-) create mode 100644 source/exceptions/test.py diff --git a/.gitignore b/.gitignore index d26f00e0..9b02cdd6 100644 --- a/.gitignore +++ b/.gitignore @@ -147,21 +147,6 @@ source/cvAutoTrack_5.7z source/CVAUTOTRACK732.dll source/cvAutoTrack_7.7z source/cvAutoTrack_7.2.3/CVAUTOTRACK.dll -.idea/genshin_impact_assistant.iml -.idea/misc.xml -.idea/modules.xml -.idea/vcs.xml -.idea/inspectionProfiles/Project_Default.xml -.idea/libraries/base_library.xml -.idea/libraries/base_library1.xml -.idea/libraries/base_library2.xml -.idea/libraries/base_library3.xml -.idea/libraries/base_library4.xml -.idea/libraries/base_library5.xml -.idea/libraries/base_library6.xml -.idea/libraries/base_library7.xml -.idea/libraries/gui.xml -.idea/libraries/jpg_0928.xml config/tastic/*.json config/settings/*.json config/auto_collector/*.json @@ -182,6 +167,7 @@ source/test235.py source/test236.py +# config config/tactic/*.json !config/tactic/team_example_1.json !config/tactic/team_example_3.json @@ -202,14 +188,15 @@ out/* assets/dm/* config/settings/damo.json config/settings/dm.json - - config/collection_path/* !config/collection_path/.gitkeep # Mission groups config/mission/*.json +# Logs +Logs/* + # test file source/test/test242.py source/test/test251.py diff --git a/source/exceptions/test.py b/source/exceptions/test.py new file mode 100644 index 00000000..74741cf3 --- /dev/null +++ b/source/exceptions/test.py @@ -0,0 +1,9 @@ +from source.exceptions.util import * +from source.interaction.interaction_core import itt + +if __name__ == "__main__": + try: + raise SnapshotException('123') + except GIABaseException as e: + if isinstance(e, SnapshotException): + e.save_snapshot(itt.capture()) \ No newline at end of file diff --git a/source/exceptions/util.py b/source/exceptions/util.py index ca2190bf..d338f17e 100644 --- a/source/exceptions/util.py +++ b/source/exceptions/util.py @@ -15,5 +15,9 @@ class SnapshotException(GIABaseException): def __init__(self, *args: object) -> None: super().__init__(*args) - def save_snapshot(self, img): - cv2.imwrite(os.path.join(ROOT_PATH, "Logs/{time:YYYY-MM-DD}", f"{round(time.time(),2)}-{self.__str__()}.jpg"), img) + def save_snapshot(self, img:ndarray): + if img.shape[2] == 4: + img = img[:,:,:3] + img_path = os.path.join(ROOT_PATH, "Logs", get_logger_format_date(), f"{self.__str__()}---{time.strftime('%H-%M-%S', time.localtime())}.jpg") + logger.warning(f"Snapshot saved to {img_path}") + cv2.imwrite(img_path, img) diff --git a/source/interaction/capture.py b/source/interaction/capture.py index 3f4354a4..96a1de77 100644 --- a/source/interaction/capture.py +++ b/source/interaction/capture.py @@ -148,6 +148,7 @@ def _get_capture(self): height=int(height) if height in list(map(int, [1080/0.75, 1080/1.25, 1080/1.5, 1080/1.75, 1080/2, 1080/2.25, 1080/2.5, 1080/2.75, 1080/3])): logger.warning_once(t2t("You seem to have monitor scaling set? It is automatically recognized and this does not affect usage.")) + logger.warning_once(f"scale: {height}") width = 1920 height = 1080 # 计算实际截屏区域大小 @@ -173,7 +174,7 @@ def _get_capture(self): return ret def _cover_privacy(self, img) -> ndarray: - img[1056 : 1075, 1770 : 1863, :3] = 0 + img[1053 : 1075, 1770 : 1863, :3] = 128 return img class CloudCapture(Capture): diff --git a/source/logger.py b/source/logger.py index 329e275e..5e787875 100644 --- a/source/logger.py +++ b/source/logger.py @@ -1,12 +1,20 @@ from loguru import logger import types -import os, json +import os +import json +import time from source.path_lib import * def load_json(json_name='General.json', default_path='config\\settings') -> dict: all_path = os.path.join(ROOT_PATH, default_path, json_name) return json.load(open(all_path, 'r', encoding='utf-8')) +def get_logger_format_time(): + return time.strftime('%Y-%m-%d %H:%M:%S', time.localtime()) + +def get_logger_format_date(): + return time.strftime('%Y-%m-%d', time.localtime()) + jpath = fr"{ROOT_PATH}/config/settings/General.json" if os.path.exists(jpath): j = json.load(open(jpath, 'r', encoding='utf-8')) diff --git a/source/util.py b/source/util.py index a0cd8cdc..00f40e42 100644 --- a/source/util.py +++ b/source/util.py @@ -14,7 +14,7 @@ if sys.path[0] != ROOT_PATH: sys.path.insert(0, ROOT_PATH) if sys.path[1] != SOURCE_PATH: sys.path.insert(1, SOURCE_PATH) -from source.logger import logger +from source.logger import logger, get_logger_format_time, get_logger_format_date from source.config.config import GIAconfig from source.i18n import t2t, GLOBAL_LANG from source.path_lib import * From 7681665920ae45d2bee81cc2b43ae0c94b5539b4 Mon Sep 17 00:00:00 2001 From: infstellar <98541813+infstellar@users.noreply.github.com> Date: Wed, 21 Jun 2023 21:59:30 +0800 Subject: [PATCH 30/40] feat: delete files that over time; ... feat: add an exception --- source/exceptions/combat.py | 6 ++++++ source/exceptions/util.py | 2 +- source/funclib/combat_lib.py | 5 ++++- source/interaction/interaction_core.py | 9 +++++++++ source/logger.py | 19 ++++++++++++++++--- source/task/task_manager.py | 4 +++- 6 files changed, 39 insertions(+), 6 deletions(-) create mode 100644 source/exceptions/combat.py diff --git a/source/exceptions/combat.py b/source/exceptions/combat.py new file mode 100644 index 00000000..87bb71f0 --- /dev/null +++ b/source/exceptions/combat.py @@ -0,0 +1,6 @@ +from source.exceptions.util import * + +class RecognizeCharacterNameError(SnapshotException): + POSSIBLE_REASONS = [ + t2t("The character name is incorrectly identified. Please submit the log.") + ] \ No newline at end of file diff --git a/source/exceptions/util.py b/source/exceptions/util.py index d338f17e..7cbca539 100644 --- a/source/exceptions/util.py +++ b/source/exceptions/util.py @@ -18,6 +18,6 @@ def __init__(self, *args: object) -> None: def save_snapshot(self, img:ndarray): if img.shape[2] == 4: img = img[:,:,:3] - img_path = os.path.join(ROOT_PATH, "Logs", get_logger_format_date(), f"{self.__str__()}---{time.strftime('%H-%M-%S', time.localtime())}.jpg") + img_path = os.path.join(ROOT_PATH, "Logs", get_logger_format_date(), f"{self.__str__()} | {time.strftime('%H-%M-%S', time.localtime())}.jpg") logger.warning(f"Snapshot saved to {img_path}") cv2.imwrite(img_path, img) diff --git a/source/funclib/combat_lib.py b/source/funclib/combat_lib.py index fe1e3d93..5d52be34 100644 --- a/source/funclib/combat_lib.py +++ b/source/funclib/combat_lib.py @@ -5,7 +5,7 @@ from common import timer_module from source.common import character from source.interaction.interaction_core import itt -from source.interaction import interaction_core +from source.exceptions.combat import * from source.api.pdocr_light import ocr_light from source.api.pdocr_complete import ocr from source.ui.ui import ui_control @@ -384,6 +384,9 @@ def get_characters_name(max_retry = 50): ret_list.append(None) if len(ret_list)==4: return ret_list + else: + itt.save_snapshot('RecognizeCharacterNameError') + raise RecognizeCharacterNameError('Recognize fail') return ret_list def get_team_chara_names_in_party_setup(): diff --git a/source/interaction/interaction_core.py b/source/interaction/interaction_core.py index 854938ed..af9fb008 100644 --- a/source/interaction/interaction_core.py +++ b/source/interaction/interaction_core.py @@ -807,6 +807,15 @@ def unfreeze_key(self, key): itt.key_down(key) else: itt.key_up(key) + + def save_snapshot(self, reason:str = ''): + img = self.capture() + if img.shape[2] == 4: + img = img[:,:,:3] + img_path = os.path.join(ROOT_PATH, "Logs", get_logger_format_date(), f"{reason} | {time.strftime('%H-%M-%S', time.localtime())}.jpg") + logger.warning(f"Snapshot saved to {img_path}") + cv2.imwrite(img_path, img) + def itt_test(itt: InteractionBGD): pass diff --git a/source/logger.py b/source/logger.py index 5e787875..12c48ddc 100644 --- a/source/logger.py +++ b/source/logger.py @@ -31,12 +31,25 @@ def warning_once(self, message): def demo(self, message): self.info(f"DEMO: {message}") -logger.warning_once = types.MethodType(warning_once, logger) -logger.demo = types.MethodType(demo, logger) +import datetime + +def delete_files(path, days): + now = datetime.datetime.now() + for root, dirs, files in os.walk(path): + for file in files: + file_path = os.path.join(root, file) + modified_time = datetime.datetime.fromtimestamp(os.path.getmtime(file_path)) + if (now - modified_time).days > days: + os.remove(file_path) + +delete_files(f"{ROOT_PATH}/Logs", 30) + # configure loguru logger.remove(handler_id=None) -logger.add(os.path.join(ROOT_PATH, os.path.join(ROOT_PATH, 'Logs', "{time:YYYY-MM-DD}/{time:YYYY-MM-DD}.log")), level="TRACE", backtrace=True, retention='15 days') +logger.warning_once = types.MethodType(warning_once, logger) +logger.demo = types.MethodType(demo, logger) +logger.add(os.path.join(ROOT_PATH, os.path.join(ROOT_PATH, 'Logs', "{time:YYYY-MM-DD}/{time:YYYY-MM-DD}.log")), level="TRACE", backtrace=True) if DEBUG_MODE: logger.add(sys.stdout, level="TRACE", backtrace=True) else: diff --git a/source/task/task_manager.py b/source/task/task_manager.py index e37ce6d6..7400e70f 100644 --- a/source/task/task_manager.py +++ b/source/task/task_manager.py @@ -1,5 +1,5 @@ from source.util import * -import keyboard +from source.interaction.interaction_core import itt from source.task.task_template import TaskTemplate from source.common.base_threading import BaseThreading from source.exceptions.util import * @@ -33,6 +33,8 @@ def task_excepthook(self, args): for pr in exception_instance.possible_reasons: i+=1 logger.error(f'{t2t("Possible Reason")} {i}: {pr}') + if isinstance(SnapshotException, exception_instance): + exception_instance.save_snapshot(itt.capture()) def append_task(self, task_name): self.task_list.append(task_name) From 89d730ef05a29dee7726d58686444760d7a3f196 Mon Sep 17 00:00:00 2001 From: infstellar <98541813+infstellar@users.noreply.github.com> Date: Wed, 21 Jun 2023 22:09:30 +0800 Subject: [PATCH 31/40] feat: add mandatory type to json_doc Added support for mandatory type settings to the config page --- config/json_doc/Combat.yaml | 4 ++++ source/webio/pages.py | 42 +++++++++++++++++++++++++------------ 2 files changed, 33 insertions(+), 13 deletions(-) diff --git a/config/json_doc/Combat.yaml b/config/json_doc/Combat.yaml index 56ad6e47..ce6bba80 100644 --- a/config/json_doc/Combat.yaml +++ b/config/json_doc/Combat.yaml @@ -19,3 +19,7 @@ vision: - Dendro - Anemo - '' +n: + type: int +priority: + type: int \ No newline at end of file diff --git a/source/webio/pages.py b/source/webio/pages.py index 00271a90..d1fae961 100644 --- a/source/webio/pages.py +++ b/source/webio/pages.py @@ -544,6 +544,7 @@ def put_json(self, j: dict, doc: dict, scope_name, add_name='', level=1): doc_items = None doc_special = None doc_annotation = None + doc_type = None if k in doc: # 判断doc的类型 if type(doc[k]) == dict: @@ -557,6 +558,8 @@ def put_json(self, j: dict, doc: dict, scope_name, add_name='', level=1): doc_special = doc[k]['special_index'] if "annotation" in doc[k]: doc_annotation = doc[k]['annotation'] + if 'type' in doc[k]: + doc_type = doc[k]['type'] if type(doc[k]) == str: doc_now = doc[k] # 取显示名称 @@ -565,19 +568,32 @@ def put_json(self, j: dict, doc: dict, scope_name, add_name='', level=1): k_sha1 = hashlib.sha1(k.encode('utf8')).hexdigest() component_name = '{}-{}'.format(add_name, k_sha1) - - if type(v) == str or v is None: - self._show_str(doc_items, component_name, display_name, scope_name, v, doc_special) - elif type(v) == int: - self._show_int(doc_items, component_name, display_name, scope_name, v, doc_special) - elif type(v) == float: - self._show_float(doc_items, component_name, display_name, scope_name, v, doc_special) - elif type(v) == bool: - self._show_bool(component_name, display_name, scope_name, v, doc_special) - elif type(v) == dict: - self._show_dict(level, component_name, display_name, scope_name, doc, v, doc_special) - elif type(v) == list: - self._show_list(level, display_name, scope_name, component_name, doc, v, doc_special) + if doc_type != None: + if doc_type == 'int': + self._show_int(doc_items, component_name, display_name, scope_name, v, doc_special) + elif doc_type == 'float': + self._show_float(doc_items, component_name, display_name, scope_name, v, doc_special) + elif doc_type == 'bool': + self._show_bool(component_name, display_name, scope_name, v, doc_special) + elif doc_type == 'dict': + self._show_dict(level, component_name, display_name, scope_name, doc, v, doc_special) + elif doc_type == 'list': + self._show_list(level, display_name, scope_name, component_name, doc, v, doc_special) + elif doc_type == 'str': + self._show_str(doc_items, component_name, display_name, scope_name, v, doc_special) + else: + if type(v) == str or v is None: + self._show_str(doc_items, component_name, display_name, scope_name, v, doc_special) + elif type(v) == int: + self._show_int(doc_items, component_name, display_name, scope_name, v, doc_special) + elif type(v) == float: + self._show_float(doc_items, component_name, display_name, scope_name, v, doc_special) + elif type(v) == bool: + self._show_bool(component_name, display_name, scope_name, v, doc_special) + elif type(v) == dict: + self._show_dict(level, component_name, display_name, scope_name, doc, v, doc_special) + elif type(v) == list: + self._show_list(level, display_name, scope_name, component_name, doc, v, doc_special) if doc_annotation != None: output.put_text(doc_annotation, scope=scope_name) output.put_text("\n", scope=scope_name).style("font-size: 1px") From 980d6c58ff708099b2fd6fab0d6351aeb4d5a2da Mon Sep 17 00:00:00 2001 From: infstellar <98541813+infstellar@users.noreply.github.com> Date: Wed, 21 Jun 2023 22:14:59 +0800 Subject: [PATCH 32/40] opt: delete logs: print info --- source/logger.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/source/logger.py b/source/logger.py index 12c48ddc..e47e608d 100644 --- a/source/logger.py +++ b/source/logger.py @@ -40,9 +40,11 @@ def delete_files(path, days): file_path = os.path.join(root, file) modified_time = datetime.datetime.fromtimestamp(os.path.getmtime(file_path)) if (now - modified_time).days > days: + if DEBUG_MODE: + print(f"Log File Delete: Deleting file {file_path} Last modified {modified_time} Days since modified {(now - modified_time).days} Days to delete {days}") os.remove(file_path) -delete_files(f"{ROOT_PATH}/Logs", 30) +delete_files(f"{ROOT_PATH}/Logs", 15) # configure loguru From 5ff5a655a53c2128539868ec03ae9831c9ed7842 Mon Sep 17 00:00:00 2001 From: infstellar <98541813+infstellar@users.noreply.github.com> Date: Thu, 22 Jun 2023 11:09:14 +0800 Subject: [PATCH 33/40] feat: add rec_commission_complete refactor: stop rules --- assets/imgs | 2 +- source/commission/assets.py | 4 +++- source/commission/commission_template.py | 17 +++++++++++++---- source/commission/general/DangerousHaul.py | 3 +++ source/commission/general/IncreasingDanger.py | 2 +- source/commission/general/OnlyFight.py | 19 ++++++++++++------- source/cvars.py | 18 ++++++++++++++++-- source/flow/utils/cvars.py | 4 +--- source/interaction/interaction_core.py | 2 ++ source/mission/mission.py | 6 +++--- source/mission/mission_template.py | 10 +++++----- source/task/domain/domain_task.py | 3 ++- 12 files changed, 62 insertions(+), 28 deletions(-) diff --git a/assets/imgs b/assets/imgs index 2e738c30..b839ae84 160000 --- a/assets/imgs +++ b/assets/imgs @@ -1 +1 @@ -Subproject commit 2e738c30dce2e2a4597da82945f9e511f5f9f57a +Subproject commit b839ae8405041c07d2ad628b491218dcc8d5d1fa diff --git a/source/commission/assets.py b/source/commission/assets.py index 87938798..ca465517 100644 --- a/source/commission/assets.py +++ b/source/commission/assets.py @@ -1,4 +1,6 @@ -from source.manager.asset import Text +from source.manager.asset import Text, ImgIcon + +IconCommissionCommissionComplete = ImgIcon() BasicKnowledgeOfTheKnights = Text(zh="西风骑士的基础知识",en="Basic Knowledge of the Knights") CrisisOfShields = Text(zh="持盾的危机", en="Crisis of Shields") diff --git a/source/commission/commission_template.py b/source/commission/commission_template.py index 5d5d6c50..2b8c85bc 100644 --- a/source/commission/commission_template.py +++ b/source/commission/commission_template.py @@ -1,4 +1,4 @@ -from source.util import * +from source.commission.util import * from source.mission.mission_template import MissionExecutor from source.map.position.position import * from source.interaction.interaction_core import itt @@ -30,10 +30,19 @@ def talk_until_switch(self, stop_func=None): if stop_func is None:stop_func=self.checkup_stop_func return super().talk_until_switch(stop_func) - def is_mission_succ(self): - pass - # itt.capture() + def rec_commission_complete(self): + r = itt.appear(IconCommissionCommissionComplete) + if r: + logger.info(t2t('commission complete')) + return r + def fight_until_commission_complete(self): + self.start_combat() + while 1: + time.sleep(0.2) + if self.rec_commission_complete(): break + self.stop_combat() + def is_commission_complete(self): if self.is_commission_start == False: if self.is_in_commission(): diff --git a/source/commission/general/DangerousHaul.py b/source/commission/general/DangerousHaul.py index 2b40ad94..ac1da199 100644 --- a/source/commission/general/DangerousHaul.py +++ b/source/commission/general/DangerousHaul.py @@ -59,6 +59,9 @@ def exec_mission(self): if not combat_lib.CSDL.get_combat_state(): self.stop_combat() break + if self.rec_commission_complete(): + self.stop_combat() + break self.commission_succ() # self.pause_threading() diff --git a/source/commission/general/IncreasingDanger.py b/source/commission/general/IncreasingDanger.py index b482430e..f36fc6bc 100644 --- a/source/commission/general/IncreasingDanger.py +++ b/source/commission/general/IncreasingDanger.py @@ -55,7 +55,7 @@ def exec_mission(self): movement.jump_in_loop(6) if self._aim_to_commission_icon(): if attack_timer.reached_and_reset():itt.left_click() - if self.is_commission_complete(): + if self.rec_commission_complete(): self.stop_combat() break self.commission_succ() diff --git a/source/commission/general/OnlyFight.py b/source/commission/general/OnlyFight.py index 13a2531e..3c8623b6 100644 --- a/source/commission/general/OnlyFight.py +++ b/source/commission/general/OnlyFight.py @@ -1,17 +1,22 @@ -from source.commission.commission_template import CommissionTemplate +from source.commission.commission import * from source.mission.mission_template import ERR_FAIL -class FightOnlyGeneral(CommissionTemplate): +class FightOnlyGeneral(Commission): def __init__(self, commission_type, commission_position): super().__init__(commission_type, commission_position) def exec_mission(self): - r = self.move_straight(self.commission_position, is_tp=True) - if r == ERR_FAIL:return - self.circle_search(self.commission_position, stop_rule="Combat") - r = self.collect(is_combat=True, is_activate_pickup=self.is_pickup_spoils) - if r == ERR_FAIL:return + r = self.move_straight(self.commission_position, is_tp=True, stop_rule=STOP_RULE_COMBAT) + self.handle_tmf_stuck_then_raise(r) + + self.circle_search(self.commission_position, stop_rule=STOP_RULE_COMBAT) + + self.fight_until_commission_complete() + + if self.is_pickup_spoils: + r = self.collect(is_activate_pickup=self.is_pickup_spoils) + if r == ERR_FAIL:return self.commission_succ() diff --git a/source/cvars.py b/source/cvars.py index 257b7aa8..31434baa 100644 --- a/source/cvars.py +++ b/source/cvars.py @@ -1,20 +1,34 @@ -"""Constant vars.""" +GIA_VERSION = "v0.8.5.1039" +"""Constants.""" +# Devices DESKTOP_CN = "Desktop_CN" DESKTOP_EN = "Desktop_EN" MOBILE_CN = "Mobile_CN" MOBILE_EN = "Mobile_EN" DEVICE = DESKTOP_CN + +# Interaction modes INTERACTION_DESKTOP = "Desktop" INTERACTION_EMULATOR = "Emulator" INTERACTION_DESKTOP_BACKGROUND = "DesktopBackground" INTERACTION_MODE = INTERACTION_DESKTOP # Normal, Adb, Dm BBG = 100001 + +# Angle modes ANGLE_NORMAL = 0 ANGLE_NEGATIVE_Y = 1 ANGLE_NEGATIVE_X = 2 ANGLE_NEGATIVE_XY = 3 + +# Process name PROCESS_NAME = ["YuanShen.exe", "GenshinImpact.exe"] + +# Screen center points SCREEN_CENTER_X = 1920/2 SCREEN_CENTER_Y = 1080/2 -GIA_VERSION = "v0.8.5.1039" + +# stop rules +STOP_RULE_ARRIVE = "ARRIVE" +STOP_RULE_F = 'F_APPEAR' +STOP_RULE_COMBAT = 'COMBAT' diff --git a/source/flow/utils/cvars.py b/source/flow/utils/cvars.py index 8ac3936b..72143f14 100644 --- a/source/flow/utils/cvars.py +++ b/source/flow/utils/cvars.py @@ -1,9 +1,7 @@ from source.funclib.cvars import WALKING, FLYING, SWIMMING, CLIMBING +from source.cvars import * IN_MOVE = WALKING IN_FLY = FLYING IN_WATER = SWIMMING IN_CLIMB = CLIMBING -STOP_RULE_ARRIVE = 0 -STOP_RULE_F = 1 -STOP_RULE_COMBAT = 2 \ No newline at end of file diff --git a/source/interaction/interaction_core.py b/source/interaction/interaction_core.py index af9fb008..dad049c4 100644 --- a/source/interaction/interaction_core.py +++ b/source/interaction/interaction_core.py @@ -321,6 +321,8 @@ def get_img_existence(self, imgicon: img_manager.ImgIcon, is_gray=False, is_log= return False elif ret_mode == IMG_RATE: return matching_rate + + appear = get_img_existence def get_text_existence(self, textobj: text_manager.TextTemplate, is_gray=False, is_log = True, ret_mode = IMG_BOOL, show_res = False): from source.api.pdocr_complete import ocr diff --git a/source/mission/mission.py b/source/mission/mission.py index 0756ac70..724e963d 100644 --- a/source/mission/mission.py +++ b/source/mission/mission.py @@ -132,13 +132,13 @@ def collect(self, MODE=None, collection_name=None, collector_type=None, is_comba """ return super().collect(MODE, collection_name, collector_type, is_combat, is_activate_pickup, pickup_points) - def circle_search(self, center_posi, stop_rule='F'): + def circle_search(self, center_posi, stop_rule=STOP_RULE_F): """进入一个循环,以中心坐标为圆心向外移动搜索。当符合stop_rule时退出。 阻塞式任务. Args: center_posi (_type_): 中心坐标 - stop_rule (str, optional): 停止条件。可选F或Combat。 Defaults to 'F'. + stop_rule (str, optional): 停止条件。可选 STOP_RULE_F 或 STOP_RULE_COMBAT 。 Defaults to STOP_RULE_F. Returns: _type_: _description_ @@ -289,7 +289,7 @@ def handle_tmf_stuck_then_recover(self, k) -> bool: Returns: bool: _description_ """ - return super()._tmf_handle_stuck_then_recover(k) + return super().handle_tmf_stuck_then_recover(k) def handle_tmf_stuck_then_raise(self, k) -> bool: """传入TMF的错误码,如果出错则抛出异常,退出任务。 diff --git a/source/mission/mission_template.py b/source/mission/mission_template.py index 8f812c77..402234b1 100644 --- a/source/mission/mission_template.py +++ b/source/mission/mission_template.py @@ -102,7 +102,7 @@ def _recover(self): curr_posi = list(tracker.get_position()) target_posi = list(tracker.bigmap_tp(posi=curr_posi, tp_type=["Statue"], csf=self.checkup_stop_func).tianli) self.TMCF.reset() - self.TMCF.set_parameter(MODE="AUTO",stop_rule=1,target_posi=target_posi,is_tp=False) + self.TMCF.set_parameter(MODE="AUTO",stop_rule=STOP_RULE_F,target_posi=target_posi,is_tp=False) self.TMCF.start_flow() while 1: time.sleep(0.2) @@ -251,7 +251,7 @@ def collect(self, MODE = None, self.CFCF.flow_connector.puo.reset_pickup_item_list() return self._handle_exception() - def circle_search(self, center_posi, stop_rule='F'): + def circle_search(self, center_posi, stop_rule=STOP_RULE_F): points = get_circle_points(center_posi[0],center_posi[1]) itt.key_down('w') jil = movement.JumpInLoop(8) @@ -262,11 +262,11 @@ def circle_search(self, center_posi, stop_rule='F'): if euclidean_distance(p, genshin_map.get_position())<=2.2: logger.debug(f"circle_search: {p} arrived") break - if stop_rule == 'F': + if stop_rule == STOP_RULE_F: if generic_lib.f_recognition(): itt.key_up('w') return True - elif stop_rule == "Combat": + elif stop_rule == STOP_RULE_COMBAT: if combat_lib.CSDL.get_combat_state(): itt.key_up('w') return True @@ -320,7 +320,7 @@ def handle_tmf_stuck_then_skip(self,k) -> bool: return True return False - def _tmf_handle_stuck_then_recover(self,k) -> bool: + def handle_tmf_stuck_then_recover(self,k) -> bool: if k == ERR_STUCK: self._recover() return True diff --git a/source/task/domain/domain_task.py b/source/task/domain/domain_task.py index 3570d4aa..df8e5c77 100644 --- a/source/task/domain/domain_task.py +++ b/source/task/domain/domain_task.py @@ -11,6 +11,7 @@ from source.task import task_id as TI from source.funclib.err_code_lib import ERR_NONE, ERR_STUCK, ERR_PASS from source.common import timer_module +from source.flow.utils.cvars import * class DomainTask(TaskTemplate): @@ -26,7 +27,7 @@ def __init__(self): self.domain_name = GIAconfig.Domain_DomainName self.domain_stage_name = GIAconfig.Domain_DomainStageName self.domain_posi = load_items_position(self.domain_name,mode=1, ret_mode=1)[0] - self.TMFCF.set_parameter(stop_rule = 1, MODE = "AUTO", target_posi = self.domain_posi, is_tp=True, tp_type=["Domain"]) + self.TMFCF.set_parameter(stop_rule = STOP_RULE_F, MODE = "AUTO", target_posi = self.domain_posi, is_tp=True, tp_type=["Domain"]) self.TMFCF.set_target_posi(self.domain_posi) self.last_domain_times = int(GIAconfig.Domain_ChallengeTimes) From d69cf540c4aacbd43b3516674457f71fc368033c Mon Sep 17 00:00:00 2001 From: infstellar <98541813+infstellar@users.noreply.github.com> Date: Thu, 22 Jun 2023 11:20:17 +0800 Subject: [PATCH 34/40] feat: exception: add possible reason to __str__ --- source/exceptions/test.py | 18 +++++++++++++++--- source/exceptions/util.py | 13 ++++++++++++- source/funclib/combat_lib.py | 18 ++++++++++-------- source/task/task_manager.py | 4 ++-- 4 files changed, 39 insertions(+), 14 deletions(-) diff --git a/source/exceptions/test.py b/source/exceptions/test.py index 74741cf3..2c60f681 100644 --- a/source/exceptions/test.py +++ b/source/exceptions/test.py @@ -1,9 +1,21 @@ from source.exceptions.util import * from source.interaction.interaction_core import itt +class TestException(GIABaseException): + POSSIBLE_REASONS = [ + 'test1', + 'test2' + ] + if __name__ == "__main__": + try: - raise SnapshotException('123') + raise TestException('123') except GIABaseException as e: - if isinstance(e, SnapshotException): - e.save_snapshot(itt.capture()) \ No newline at end of file + logger.exception(e) + + # try: + # raise SnapshotException('123') + # except GIABaseException as e: + # if isinstance(e, SnapshotException): + # e.save_snapshot(itt.capture()) \ No newline at end of file diff --git a/source/exceptions/util.py b/source/exceptions/util.py index 7cbca539..ad3649ac 100644 --- a/source/exceptions/util.py +++ b/source/exceptions/util.py @@ -5,7 +5,18 @@ class GIABaseException(Exception): def __init__(self, *args: object) -> None: super().__init__(*args) self.stop_task_flag = False # 当发生该异常时,是否结束所有Task。 - + + def __str__(self) -> str: + r = '\x1b[31m' + r += super().__str__() + r+='\n' + if len(self.POSSIBLE_REASONS) > 0: + i = 0 + for pr in self.POSSIBLE_REASONS: + i+=1 + r+='\x1b[31m' + r+=(f'{t2t("Possible Reason")} {i}: {pr} \n') + return r class TaskException(GIABaseException): def __init__(self, *args: object) -> None: super().__init__(*args) diff --git a/source/funclib/combat_lib.py b/source/funclib/combat_lib.py index 5d52be34..e8417f34 100644 --- a/source/funclib/combat_lib.py +++ b/source/funclib/combat_lib.py @@ -24,13 +24,15 @@ def default_stop_func(): return False -class TacticKeyNotFoundError(RuntimeError): - def __init__(self, arg): - self.args = [arg] +class TacticKeyNotFoundError(GIABaseException): + POSSIBLE_REASONS = [ + t2t('No corresponding parameters filled in') + ] -class TacticKeyEmptyError(RuntimeError): - def __init__(self, arg): - self.args = [arg] +class TacticKeyEmptyError(GIABaseException): + POSSIBLE_REASONS = [ + t2t('No corresponding parameters filled in') + ] CREATE_WHEN_NOTFOUND = 0 RAISE_WHEN_NOTFOUND = 1 @@ -452,7 +454,7 @@ def get_curr_team_file(): return i["label"] return False -class CharacterNameNotInCharacterParametersError(Exception):pass +class CharacterNameNotInCharacterParametersError(GIABaseException):pass def generate_teamfile_automatic(): if not (ui_control.verify_page(UIPage.page_main) or ui_control.verify_page(UIPage.page_domain)): ui_control.ui_goto(UIPage.page_main) @@ -575,7 +577,7 @@ def get_chara_list(): ) ) if load_err_times>0: - raise TacticKeyEmptyError(t2t("Character Key Empty Error")) + raise TacticKeyEmptyError("Character Key Empty Error") return chara_list diff --git a/source/task/task_manager.py b/source/task/task_manager.py index 7400e70f..5cb1deb1 100644 --- a/source/task/task_manager.py +++ b/source/task/task_manager.py @@ -28,9 +28,9 @@ def task_excepthook(self, args): if isinstance(GIABaseException, exception_instance): if args.exc_value.stop_task_flag: self.stop_tasklist() - if len(exception_instance.possible_reasons) > 0: + if len(exception_instance.POSSIBLE_REASONS) > 0: i = 0 - for pr in exception_instance.possible_reasons: + for pr in exception_instance.POSSIBLE_REASONS: i+=1 logger.error(f'{t2t("Possible Reason")} {i}: {pr}') if isinstance(SnapshotException, exception_instance): From 748d974054afdd0c390a753dd8e0aa2ef1a16898 Mon Sep 17 00:00:00 2001 From: infstellar <98541813+infstellar@users.noreply.github.com> Date: Thu, 22 Jun 2023 11:28:34 +0800 Subject: [PATCH 35/40] refactor: webpages --- source/webio/pages.py | 860 -------------------- source/webio/webio.py | 8 +- source/webio/webpages/collector_settings.py | 199 +++++ source/webio/webpages/combat_settings.py | 83 ++ source/webio/webpages/config.py | 391 +++++++++ source/webio/webpages/general_settings.py | 33 + source/webio/webpages/main.py | 210 +++++ 7 files changed, 923 insertions(+), 861 deletions(-) create mode 100644 source/webio/webpages/collector_settings.py create mode 100644 source/webio/webpages/combat_settings.py create mode 100644 source/webio/webpages/config.py create mode 100644 source/webio/webpages/general_settings.py create mode 100644 source/webio/webpages/main.py diff --git a/source/webio/pages.py b/source/webio/pages.py index d1fae961..9f7831cd 100644 --- a/source/webio/pages.py +++ b/source/webio/pages.py @@ -22,875 +22,15 @@ # from source.webio.log_handler import webio_poster -class MainPage(AdvancePage): - def __init__(self): - super().__init__() - self.log_list = [] - self.log_history = [] - self.log_list_lock = threading.Lock() - self.ui_statement = -1 - self.refresh_flow_info_timer = timer_module.Timer() - self.ui_mission_select = "" - self.is_task_start = False - # todo:多语言支持 - def _on_load(self): # 加载事件 - super()._on_load() - pin.pin['FlowMode'] = listening.current_flow - def _event_thread(self): - while self.loaded: # 当界面被加载时循环运行 - try: - pin.pin['isSessionExist'] - except SessionNotFoundException: - logger.info(t2t("未找到会话,可能由于窗口关闭。请刷新页面重试。")) - return - except SessionClosedException: - logger.info(t2t("未找到会话,可能由于窗口关闭。请刷新页面重试。")) - return - if pin.pin['FlowMode'] != listening.current_flow: # 比较变更是否被应用 - listening.current_flow = pin.pin['FlowMode'] # 应用变更 - self.log_list_lock.acquire() - output.put_text(t2t("正在导入模块, 可能需要一些时间。"), scope='LogArea').style( - f'color: black; font_size: 20px') - output.put_text(t2t("在导入完成前,请不要切换页面。"), scope='LogArea').style( - f'color: black; font_size: 20px') - self.log_list_lock.release() - listening.call_you_import_module() - # if pin.pin["MissionSelect"] != self.ui_mission_select: - # self.ui_mission_select = pin.pin["MissionSelect"] - # output.clear_scope("SCOPEMissionIntroduction") - # if self.ui_mission_select is None: - # continue - # output.put_text(self._get_mission_groups_dict()["introduction"][GLOBAL_LANG],scope="SCOPEMissionIntroduction") - - self.log_list_lock.acquire() - for text, color in self.log_list: - if text == "$$end$$": - output.put_text("", scope='LogArea') - else: - output.put_text(text, scope='LogArea', inline=True).style(f'color: {color}; font_size: 20px') # ; background: aqua - - self.log_list.clear() - self.log_list_lock.release() - if self.refresh_flow_info_timer.get_diff_time() >= 0.2: - self.refresh_flow_info_timer.reset() - if listening.TASK_MANAGER.get_task_statement() != self.ui_statement: - self.ui_statement = listening.TASK_MANAGER.get_task_statement() - output.clear(scope="StateArea") - # if isinstance(self.ui_statement, list): - # for i in self.ui_statement: - # output.put_text(f'{i["name"]}: {i["statement"]}: {i["rfc"]}', scope="StateArea") - # elif isinstance(self.ui_statement, str): - output.put_text(f'{self.ui_statement}', scope="StateArea") - - if listening.TASK_MANAGER.start_tasklist_flag != self.is_task_start: - self.is_task_start = listening.TASK_MANAGER.start_tasklist_flag - output.clear('Button_StartStop') - output.put_button(label=str(listening.TASK_MANAGER.start_tasklist_flag), onclick=self.on_click_startstop, - scope='Button_StartStop') - - - time.sleep(0.1) - - def _load(self): - # 标题 - # 获得链接按钮 - with output.use_scope(self.main_scope): - output.put_row([ - output.put_button(label=t2t("Get IP address"), onclick=self.on_click_ip_address, scope=self.main_scope), - output.put_link(t2t('View Document'), url='https://genshinimpactassistant.github.io/GIA-Document', new_window = True).style('font-size: 20px') - ]) - - - task_options = [ - { - "label":t2t("Launch genshin"), - "value":"LaunchGenshinTask" - }, - { - "label":t2t("Domain Task"), - "value":"DomainTask" - }, - { - "label":t2t("Daily Commission"), - "value":"CommissionTask" - }, - { - "label":t2t("Claim Reward"), - "value":"ClaimRewardTask" - }, - { - "label":t2t("Ley Line Outcrop"), - "value":"LeyLineOutcropTask" - }, - { - "label":t2t("Mission"), - "value":"MissionTask" - } - ] - output.put_row([ # 横列 - output.put_column([ # 左竖列 - output.put_markdown('## '+t2t("Task List")), - output.put_markdown(t2t("Can only be activated from the button")), - pin.put_checkbox(name="task_list", options=task_options), - output.put_row([output.put_text(t2t('启动/停止Task')), None, output.put_scope('Button_StartStop')],size='40% 10px 60%'), - - output.put_markdown(t2t('## Statement')), - output.put_row([output.put_text(t2t('任务状态')), None, output.put_scope('StateArea')],size='40% 10px 60%'), - output.put_markdown(t2t('## Semi-automatic Functions')), # 左竖列标题 - output.put_markdown(t2t("Can only be activated from the hotkey \'[\'")), - output.put_text(t2t('Do not enable semi-automatic functions and tasks at the same time')), - output.put_row([ # FlowMode - output.put_text(t2t('Semi-automatic Functions')), - - pin.put_select(('FlowMode'), [ - {'label': t2t('Idle'), 'value': listening.FLOW_IDLE}, - {'label': t2t('Auto Combat'), 'value': listening.FLOW_COMBAT} - ]), - ], - - ) - ], size='auto'), None, - output.put_scope('Log') - - ], scope=self.main_scope, size='40% 10px 60%') - - # PickUpButton - output.put_button(label=str(listening.FEAT_PICKUP), onclick=self.on_click_pickup, scope='Button_PickUp') - # Button_StartStop - output.put_button(label=str(listening.startstop_flag), onclick=self.on_click_startstop, - scope='Button_StartStop') - - # Log - output.put_markdown(t2t('## Log'), scope='Log') - output.put_scrollable(output.put_scope('LogArea'), height=600, keep_bottom=True, scope='Log') - '''self.main_pin_change_thread = threading.Thread(target=self._main_pin_change_thread, daemon=False) - self.main_pin_change_thread.start()''' - - m = upd_message() - if m!="": - output.popup(t2t('更新提示'), m) - - # def _get_mission_groups_config(self): - # jsons = load_json_from_folder(f"{CONFIG_PATH}\\mission_groups") - # r = [i["label"] for i in jsons] - # return r - - # def _get_mission_groups_dict(self): - # jsonname = pin.pin["MissionSelect"] - # if jsonname is None: - # raise FileNotFoundError - # return load_json(str(jsonname),default_path=f"{CONFIG_PATH}\\mission_groups") - - def on_click_pickup(self): - output.clear('Button_PickUp') - listening.FEAT_PICKUP = not listening.FEAT_PICKUP - output.put_button(label=str(listening.FEAT_PICKUP), onclick=self.on_click_pickup, scope='Button_PickUp') - - def on_click_startstop(self): - # listening.MISSION_MANAGER.set_mission_list(list(pin.pin["MissionSelect"])) - listening.TASK_MANAGER.set_tasklist(pin.pin["task_list"]) - listening.TASK_MANAGER.start_stop_tasklist() - # if pin.pin["MissionSelect"] != None and pin.pin["MissionSelect"] != "": - # cj = load_json() - # cj["MissionGroup"] = pin.pin["MissionSelect"] - # save_json(cj) - # GIAconfig.update() - - time.sleep(0.2) - output.clear('Button_StartStop') - output.put_button(label=str(listening.TASK_MANAGER.start_tasklist_flag), onclick=self.on_click_startstop, - scope='Button_StartStop') - - def on_click_ip_address(self): - LAN_ip = f"{socket.gethostbyname(socket.gethostname())}{session.info.server_host[session.info.server_host.index(':'):]}" - WAN_ip = t2t("Not Enabled") - output_text = t2t('LAN IP') + " : " + LAN_ip + '\n' + t2t("WAN IP") + ' : ' + WAN_ip - output.popup(f'ip address', output_text, size=output.PopupSize.SMALL) - - def logout(self, text: str, color='black'): - if self.loaded: - self.log_list_lock.acquire() - self.log_list.append((text, color)) - self.log_list_lock.release() - - -class ConfigPage(AdvancePage): - def __init__(self, config_file_name): - super().__init__() - - # self.main_scope = "SettingPage" - - self.exit_popup = None - self.last_file = None - self.file_name = '' - self.config_file_name = config_file_name - - self.config_files = [] - self.config_files_name = [] - self._load_config_files() - self.can_check_select = True - self.can_remove_last_scope = False - # 注释显示模式在这改 - self.mode = True - self.read_only = False - - self.input_verify={ - "test":lambda x:x - } - - def _load_config_files(self): - for root, dirs, files in os.walk('config'): - for f in files: - if f[f.index('.') + 1:] == "json": - self.config_files.append({"label": f, "value": os.path.join(root, f)}) - - def _load(self): - self.last_file = None - - # 配置页 - output.put_markdown(t2t('## config:'), scope=self.main_scope) - - output.put_scope("select_scope", scope=self.main_scope) - pin.put_select('file', self._config_file2lableAfile(self.config_files), scope="select_scope") - - def _config_file2lableAfile(self, l1): - replace_dict = { - "Combat.json": t2t("Combat.json"), - "Domain.json": t2t("Domain.json"), - "General.json": t2t("General.json"), - "Keymap.json": t2t("Keymap.json"), - "collected.json": t2t("collected.json"), - "collection_blacklist.json": t2t("collection_blacklist.json"), - "collection_log.json": t2t("collection_log.json"), - "Collector.json": t2t("Collector.json"), - "LeyLineOutcrop.json": t2t("LeyLineOutcrop.json") - } - - for i in range(len(l1)): - l1[i]["label"] = replace_dict.setdefault(l1[i]["label"], l1[i]["label"]) - return l1 - - # 重新加载选项 - def _reload_select(self): - self.can_check_select = False - self._load_config_files() - output.clear("select_scope") - pin.put_select('file', self._config_file2lableAfile(self.config_files), scope="select_scope") - self.can_check_select = True - - # 循环线程 - def _event_thread(self): - while self.loaded: - if not self.can_check_select: - time.sleep(1) - continue - try: - pin.pin['isSessionExist'] - except SessionNotFoundException: - logger.info(t2t("未找到会话,可能由于窗口关闭。请刷新页面重试。")) - return - - if pin.pin['file'] != self.last_file: # 当下拉框被更改时 - self.last_file = pin.pin['file'] - - if self.can_remove_last_scope: # 判断是否可以移除 - output.remove('now') - else: - self.can_remove_last_scope = True - - output.put_scope('now', scope=self.main_scope) # 创建配置页scope - - - self.put_setting(pin.pin['file']) # 配置配置页 - - time.sleep(1) - - def _str_verify(self, x, verify_list, scope_name): - if x in verify_list: - output.clear_scope(scope_name) - output.put_text(t2t("Verified!"), scope=scope_name).style(f'color: green; font_size: 20px') - return - else: - f1 = False - sl = [] - for i in verify_list: - if x in i: - f1 = True - output.clear_scope(scope_name) - output.put_text(t2t("Waiting..."), scope=scope_name).style(f'color: black; font_size: 20px') - if len(sl)<=15: - sl.append(i) - - if f1: - output.put_text(t2t("You may want to enter: "), scope=scope_name).style(f'color: black; font_size: 20px') - for i in sl: - output.put_text(i, scope=scope_name).style(f'color: black; font_size: 12px; font-style:italic') - else: - output.clear_scope(scope_name) - output.put_text(t2t("Not a valid name"), scope=scope_name).style(f'color: red; font_size: 20px') - - def _before_load_json(self): - pass - - def put_setting(self, name='', j=None): - self.file_name = name - self._before_load_json() - output.put_markdown('## {}'.format(name), scope='now') # 标题 - if j is None: - with open(name, 'r', encoding='utf8') as f: - j = json.load(f) - - # with open(os.path.join(root_path, "config", "settings", "config.json"), 'r', encoding='utf8') as f: - # lang = json.load(f)["lang"] - doc_name = f'config\\json_doc\\{self.config_file_name}.yaml' - lang_doc_name = f'config\\json_doc\\{self.config_file_name}.{GLOBAL_LANG}.yaml' - - if os.path.exists(doc_name): - with open(doc_name, 'r', encoding='utf8') as f: - doc = yaml.load(f, Loader=yaml.FullLoader) - if os.path.exists(lang_doc_name): - with open(lang_doc_name, 'r', encoding='utf8') as f: - doc_addi = yaml.load(f, Loader=yaml.FullLoader) - for k1 in doc_addi: - for k2 in doc_addi[k1]: - if k1 not in doc: - doc[k1] = doc_addi[k1] - doc[k1][k2] = doc_addi[k1][k2] - else: - doc = {} - self.put_json(j, doc, 'now', level=3) # 载入json - if not self.read_only: - output.put_button('save', scope='now', onclick=self.save) - - # 保存json文件 - def save(self): - j = json.load(open(self.file_name, 'r', encoding='utf8')) - json.dump(self.get_json(j), open(self.file_name, 'w', encoding='utf8'), ensure_ascii=False, indent=4) - # output.put_text('saved!', scope='now') - output.toast(t2t('saved!'), color='success', duration=4) - output.toast(t2t('You may need to restart to apply changes.'), duration=4) - GIAconfig.update() - # - def get_json(self, j: dict, add_name=''): - rt_json = {} - for k in j: - k_sha1 = hashlib.sha1(k.encode('utf8')).hexdigest() - v = j[k] - if type(v) == dict: - rt_json[k] = self.get_json(v, add_name='{}-{}'.format(add_name, k_sha1)) - - elif type(v) == list: - - # 判断是否为dict列表 - is_dict_list = True - for i in v: - is_dict_list = is_dict_list and (type(i) == dict) - - if is_dict_list: - # 这个是dict的id,是在列表的位置,从1开始,当然也可以改成从0开始,都一样 - dict_id = 0 - # 在当前dict列表里循环,取出每一个dict - rt_list = [] - for i in v: - # 计次+1 - dict_id += 1 - rt_list.append( - self.get_json(v[dict_id - 1], add_name='{}-{}-{}'.format(add_name, k_sha1, str(dict_id)))) - rt_json[k] = rt_list - else: - rt_json[k] = list_text2list(pin.pin['{}-{}'.format(add_name, k_sha1)]) - else: - rt_json[k] = pin.pin['{}-{}'.format(add_name, k_sha1)] - - return rt_json - - def _on_unload(self): - if not self.read_only: - j = json.load(open(self.file_name, 'r', encoding='utf8')) - self.exit_popup = True - if not is_json_equal(json.dumps(self.get_json(j)), json.dumps(j)): - self.exit_popup = False - output.popup(t2t('Do you need to save changes?'), [ - output.put_buttons([(t2t('No'), 'No'), (t2t('Yes'), 'Yes')], onclick=self.popup_button) - ]) - while not self.exit_popup: - time.sleep(0.1) - - def popup_button(self, val): - if val == 'No': - self.close_popup() - elif val == 'Yes': - self.save_and_exit_popup() - - def save_and_exit_popup(self): - self.save() - output.close_popup() - self.exit_popup = True - - def close_popup(self): - output.close_popup() - self.exit_popup = True - - # 展示str型项 - def _show_str(self, doc_items, component_name, display_name, scope_name, v, doc_special): - if doc_items: - pin.put_select(component_name, - [{"label": i, "value": i} for i in doc_items], value=v, - label=display_name, - scope=scope_name) - elif doc_special: - doc_special = doc_special.split('#') - if doc_special[0] == "$FILE_IN_FOLDER$": - - json_dict = load_json_from_folder(os.path.join(ROOT_PATH, doc_special[1]), black_file=["character","character_dist",""]) - sl = [] - for i in json_dict: - sl.append({"label": i["label"], "value": i["label"]}) - pin.put_select(component_name, - sl, value=v, - label=display_name, - scope=scope_name) - elif doc_special[0] == "$INPUT_VERIFY$": - pin.put_input(component_name, label=display_name, value=v, scope=scope_name) - output.put_scope(name=component_name, content=[ - output.put_text("") - ], scope=scope_name) - def onchange(x): - self._str_verify(x, verify_list=self.input_verify[doc_special[1]], scope_name=component_name) - pin.pin_on_change(component_name, onchange=onchange, clear=False, init_run=True) - else: - pin.put_input(component_name, label=display_name, value=v, scope=scope_name) - - # 展示inf型项 - def _show_int(self, doc_items, component_name, display_name, scope_name, v, doc_special): - if doc_items: - pin.put_select(component_name, - [{"label": i, "value": i} for i in doc_items], value=v, - label=display_name, - scope=scope_name) - else: - pin.put_input(component_name, label=display_name, value=v, scope=scope_name, type='number') - - # 展示float型项 - def _show_float(self, doc_items, component_name, display_name, scope_name, v, doc_special): - if doc_items: - pin.put_select(component_name, - [{"label": i, "value": i} for i in doc_items], value=v, - label=display_name, - scope=scope_name) - else: - pin.put_input(component_name, label=display_name, value=v, scope=scope_name, type='float') - - # 展示bool型项 - def _show_bool(self, component_name, display_name, scope_name, v, doc_special): - pin.put_select(component_name, - [{"label": 'True', "value": True}, {"label": 'False', "value": False}], value=v, - label=display_name, - scope=scope_name) - - # 展示dict型项 - def _show_dict(self, level, component_name, display_name, scope_name, doc, v, doc_special): - output.put_scope(component_name, scope=scope_name) - output.put_markdown('#' * level + ' ' + display_name, scope=component_name) - self.put_json(v, doc, component_name, add_name=component_name, - level=level + 1) - - # 展示list/list&dict型项 - def _show_list(self, level, display_name, scope_name, component_name, doc, v, doc_special): - # 判断是否为dict列表 - is_dict_list = True - for i in v: - is_dict_list = is_dict_list and (type(i) == dict) - - if is_dict_list: - output.put_markdown('#' * level + ' ' + display_name, - scope=scope_name) - # 差点把我绕晕.... - # 这个是dict的id,是在列表的位置,从1开始,当然也可以改成从0开始,都一样 - dict_id = 0 - # 在当前dict列表里循环,取出每一个dict - for i in v: - # 计次+1 - dict_id += 1 - - # 创建一个容器以容纳接下来的dict,第一个是控件名称,为了防止重复,加上了dict id,后面那个是当前容器id - output.put_scope(component_name + '-' + str(dict_id), scope=scope_name) - # 写标题,第一项是标题文本,遵守markdown语法,第二项是当前容器名称 - output.put_markdown('#' * (level + 1) + ' ' + str(dict_id), - scope=component_name + '-' + str(dict_id)) - # 写dict,第一项为输入的dict,第二项为doc,第三项为当前容器名称,第四项为控件名称前缀,最后是缩进等级 - self.put_json(i, doc, component_name + '-' + str(dict_id), - component_name + '-' + str(dict_id), - level=level + 2) - else: - pin.put_textarea(component_name, label=display_name, value=list2format_list_text(v), - scope=scope_name) - - # 显示json - def put_json(self, j: dict, doc: dict, scope_name, add_name='', level=1): - for k in j: - v = j[k] - # 获取注释 - doc_now = '' - doc_now_data = {} - doc_items = None - doc_special = None - doc_annotation = None - doc_type = None - if k in doc: - # 判断doc的类型 - if type(doc[k]) == dict: - if 'doc' in doc[k]: - doc_now = doc[k]['doc'] - if 'data' in doc[k]: - doc_now_data = doc[k]['data'] - if 'select_items' in doc[k]: - doc_items = doc[k]['select_items'] - if 'special_index' in doc[k]: - doc_special = doc[k]['special_index'] - if "annotation" in doc[k]: - doc_annotation = doc[k]['annotation'] - if 'type' in doc[k]: - doc_type = doc[k]['type'] - if type(doc[k]) == str: - doc_now = doc[k] - # 取显示名称 - display_name = doc_now if doc_now else k if self.mode else '{} {}'.format(k, doc_now) - - k_sha1 = hashlib.sha1(k.encode('utf8')).hexdigest() - component_name = '{}-{}'.format(add_name, k_sha1) - - if doc_type != None: - if doc_type == 'int': - self._show_int(doc_items, component_name, display_name, scope_name, v, doc_special) - elif doc_type == 'float': - self._show_float(doc_items, component_name, display_name, scope_name, v, doc_special) - elif doc_type == 'bool': - self._show_bool(component_name, display_name, scope_name, v, doc_special) - elif doc_type == 'dict': - self._show_dict(level, component_name, display_name, scope_name, doc, v, doc_special) - elif doc_type == 'list': - self._show_list(level, display_name, scope_name, component_name, doc, v, doc_special) - elif doc_type == 'str': - self._show_str(doc_items, component_name, display_name, scope_name, v, doc_special) - else: - if type(v) == str or v is None: - self._show_str(doc_items, component_name, display_name, scope_name, v, doc_special) - elif type(v) == int: - self._show_int(doc_items, component_name, display_name, scope_name, v, doc_special) - elif type(v) == float: - self._show_float(doc_items, component_name, display_name, scope_name, v, doc_special) - elif type(v) == bool: - self._show_bool(component_name, display_name, scope_name, v, doc_special) - elif type(v) == dict: - self._show_dict(level, component_name, display_name, scope_name, doc, v, doc_special) - elif type(v) == list: - self._show_list(level, display_name, scope_name, component_name, doc, v, doc_special) - if doc_annotation != None: - output.put_text(doc_annotation, scope=scope_name) - output.put_text("\n", scope=scope_name).style("font-size: 1px") - -class SettingPage(ConfigPage): - def __init__(self): - super().__init__(config_file_name = CONFIGNAME_GENERAL) - self.domain_name = load_json(f"Domain_Names_{GLOBAL_LANG}.json", fr"{ASSETS_PATH}/domain_names") - self.input_verify={ - "domain_name":self.domain_name - } - - def _load(self): - self.last_file = None - - # 配置页 - output.put_markdown(t2t('## config:'), scope=self.main_scope) - output.put_scope("select_scope", scope=self.main_scope) - - pin.put_select('file', self._config_file2lableAfile(self.config_files), scope="select_scope", value="config\\settings\\config.json") - - def _load_config_files(self): - # for root, dirs, files in os.walk('config\\settings'): - # for f in files: - # if f[:f.index('.')] in ["auto_combat", "auto_collector", "auto_pickup_default_blacklist"]: - # continue - # if f[f.index('.') + 1:] == "json": - # self.config_files.append({"label": f, "value": os.path.join(root, f)}) - for i in [CONFIGNAME_GENERAL, CONFIGNAME_DOMAIN, CONFIGNAME_KEYMAP, CONFIGNAME_LEY_LINE_OUTCROP]: - self.config_files.append({"label": f"{i}.json", "value": os.path.join(fr"{CONFIG_PATH_SETTING}", f"{i}.json")}) - - -class CombatSettingPage(ConfigPage): - def __init__(self): - super().__init__(config_file_name = CONFIGNAME_COMBAT) - from source.common.lang_data import get_all_characters_name - self.character_names = get_all_characters_name() - self.input_verify={ - "character_name":self.character_names - } - - def _autofill(self): - j = self.get_json(json.load(open(self.file_name, 'r', encoding='utf8'))) - autofill_j = load_json("characters_parameters.json", f"{ASSETS_PATH}\\characters_data") - not_found = [] - - from source.common.lang_data import translate_character_auto - for i in j: - cname = translate_character_auto(j[i]["name"]) - if cname is None: - not_found.append(j[i]["name"]) - continue - if cname in autofill_j: - for k in ["position", "E_short_cd_time", "E_long_cd_time", "Elast_time", "Epress_time", "tactic_group", "trigger", "Qlast_time", "Qcd_time", "vision"]: - if j[i][k] == "" or j[i][k] == -1: - j[i][k] = autofill_j[cname][k] - else: - not_found.append(cname) - output.clear_scope('now') - if len(not_found)==0: - output.popup("自动填充", "自动填充成功\n以下选项不会自动填充:\n优先级,角色在队伍中的位置。\n记得保存( ̄▽ ̄)~*") - else: - output.popup("自动填充", - "自动填充部分失败\n"+ - str(not_found)+"\n"+ - "以下选项不会自动填充:\n优先级,角色在队伍中的位置。\n记得保存( ̄▽ ̄)~*") - self.put_setting(name=self.file_name, j=j) - - def _load_config_files(self): - self.config_files = [] - for root, dirs, files in os.walk('config\\tactic'): - for f in files: - if f[f.index('.') + 1:] == "json": - self.config_files.append({"label": f, "value": os.path.join(root, f)}) - self.config_files.append({"label": f"{CONFIGNAME_COMBAT}.json", "value": fr"config/settings/{CONFIGNAME_COMBAT}.json"}) - - def _load(self): - self.last_file = None - - # 添加team.json - output.put_markdown(t2t('# Add team'), scope=self.main_scope) - - # 添加team.json按钮 - output.put_row([ - output.put_button(t2t("Add team"), onclick=self.onclick_add_teamjson), - None, - output.put_button(t2t("自动填充"), onclick=self._autofill)], - scope=self.main_scope, size="10% 10px 20%") - - # 配置页 - output.put_markdown(t2t('## config:'), scope=self.main_scope) - output.put_scope("select_scope", scope=self.main_scope) - pin.put_select('file', self._config_file2lableAfile(self.config_files), scope="select_scope", value="config/settings/Combat.json") - - def onclick_add_teamjson(self): - n = input.input('team name') - shutil.copy(os.path.join(ROOT_PATH, "config\\tactic\\team.uijsontemplate"), - os.path.join(ROOT_PATH, "config\\tactic", n + '.json')) - self._reload_select() - - def onclick_add_teamjson_withcharacters(self): - n = input.input('team name') - shutil.copy(os.path.join(ROOT_PATH, "config\\tactic\\team_with_characters.uijsontemplate"), - os.path.join(ROOT_PATH, "config\\tactic", n + '.json')) - self._reload_select() - pass - -class CollectorSettingPage(ConfigPage): - def __init__(self): - super().__init__(config_file_name = CONFIGNAME_COLLECTOR) - self.collection_names = load_json("ITEM_NAME.json", f"assets\\POI_JSON_API\\{GLOBAL_LANG}") - - def _load_config_files(self): - self.config_files = [] - for root, dirs, files in os.walk('config\\auto_collector'): - for f in files: - if f[f.index('.') + 1:] == "json": - self.config_files.append({"label": f, "value": os.path.join(root, f)}) - self.config_files.append({"label": f"{CONFIGNAME_COLLECTOR}.json", "value": os.path.join(fr"config/settings/{CONFIGNAME_COLLECTOR}.json")}) - - # 重置列表 - @staticmethod - def _reset_list_textarea(x): - pin.pin[x] = "[\n\n]" - - def _load(self): - self.last_file = None - - # 配置页 - output.put_markdown(t2t('## config:'), scope=self.main_scope) - output.put_scope("select_scope", scope=self.main_scope) - pin.put_select('file', self._config_file2lableAfile(self.config_files), scope="select_scope", value="config\\settings\\auto_collector.json") - - def _clean_textarea(self, set_value): - set_value("") - - def _onclick_col_log_operate(self, btn_value:str): - if btn_value == "$COLLECTED$": - collector_lib.generate_collected_from_log() - toast_succ() - elif btn_value == "$BLACKLIST$": - collector_lib.generate_masked_col_from_log() - toast_succ() - - def _before_load_json(self): - if "collection_log.json" in self.file_name: - self.read_only = True - # output.put_buttons([ - - # (_("Automatic generate a list of collected items"), "$COLLECTED$"), - # (_("Automatic generate a list of blacklist items"), "$BLACKLIST$") - # ], - # onclick=self._onclick_col_log_operate, - # scope="now" - # ) - else: - self.read_only = False - return super()._before_load_json() - - def _on_click_collectionlog(self, btn_value:str): - # btn value: $AddToBlackList$#KEY#ID - collect_key = btn_value.split('#')[1] - collect_id = int(btn_value.split('#')[2]) - if "$AddToBlackList$" in btn_value: - collector_lib.add_to_blacklist(collect_key, collect_id) - toast_succ() - elif "$AddToCollected$" in btn_value: - collector_lib.add_to_collected(collect_key, collect_id) - toast_succ() - - - def _show_list(self, level, display_name, scope_name, component_name, doc, v, doc_special): - # 判断是否为dict列表 - is_dict_list = True - for i in v: - is_dict_list = is_dict_list and (type(i) == dict) - if is_dict_list: - - output.put_markdown('#' * level + ' ' + display_name, - scope=scope_name) - if "collection_log.json" in self.file_name: - for iii in range(len(v)): - v[iii]["picked item"] = str(v[iii]["picked item"]) - v = v[::-1] - show_list = [] - for iii in range(len(v)): - ctime = v[iii]["time"][:v[iii]["time"].index('.')] - show_list.append( [v[iii]["error_code"], v[iii]["id"], v[iii]["picked item"], ctime, - output.put_buttons([ - (t2t("Add to blacklist"), f"$AddToBlackList$#{display_name}#{v[iii]['id']}"), - # (_("Add to collected"), f"$AddToCollected$#{display_name}#{v[iii]['id']}") - ], - onclick=self._on_click_collectionlog, small=True)]) - a1,a2,a3,a4 = collector_lib.col_succ_times_from_log(display_name, day=1) - b1,b2,b3,b4 = collector_lib.col_succ_times_from_log(display_name, day=7) - c1,c2,c3,c4 = collector_lib.col_succ_times_from_log(display_name, day=15) - d1,d2,d3,d4 = collector_lib.col_succ_times_from_log(display_name, day=900) - output.put_collapse(t2t("展开/收起"), [ - - output.put_text(f"{t2t('Within')} 1 {t2t('day(s)')} {t2t('success rate')}:{a1} {t2t('total num')}:{a2} {t2t('success num')}:{a3} {t2t('fail num')}:{a4}"), - output.put_text(f"{t2t('Within')} 7 {t2t('day(s)')} {t2t('success rate')}:{b1} {t2t('total num')}:{b2} {t2t('success num')}:{b3} {t2t('fail num')}:{b4}"), - output.put_text(f"{t2t('Within')} 15 {t2t('day(s)')} {t2t('success rate')}:{c1} {t2t('total num')}:{c2} {t2t('success num')}:{c3} {t2t('fail num')}:{c4}"), - output.put_text(f"{t2t('Within')} 900 {t2t('day(s)')} {t2t('success rate')}:{d1} {t2t('total num')}:{d2} {t2t('success num')}:{d3} {t2t('fail num')}:{d4}"), - output.put_table(show_list, header=["error_code", "id", "picked item", "time", "buttons"]) - ], scope=scope_name) - - - else: - # 差点把我绕晕.... - # 这个是dict的id,是在列表的位置,从1开始,当然也可以改成从0开始,都一样 - dict_id = 0 - # 在当前dict列表里循环,取出每一个dict - for i in v: - # 计次+1 - dict_id += 1 - - - # 创建一个容器以容纳接下来的dict,第一个是控件名称,为了防止重复,加上了dict id,后面那个是当前容器id - output.put_scope(component_name + '-' + str(dict_id), scope=scope_name) - # 写标题,第一项是标题文本,遵守markdown语法,第二项是当前容器名称 - output.put_markdown('#' * (level + 1) + ' ' + str(dict_id), - scope=component_name + '-' + str(dict_id)) - # 写dict,第一项为输入的dict,第二项为doc,第三项为当前容器名称,第四项为控件名称前缀,最后是缩进等级 - self.put_json(i, doc, component_name + '-' + str(dict_id), - component_name + '-' + str(dict_id), - level=level + 2) - else: - # 清除按钮 - if "collected.json" in self.file_name: - output.put_row([ - pin.put_textarea(component_name, label=display_name, value=list2format_list_text(v)), - None, - output.put_button(t2t("clean list"), onclick=lambda:self._reset_list_textarea(component_name)) - ] - , scope=scope_name,size="85% 5% 10%") - elif "collection_log.json" in self.file_name: - # output.put_table() - output.put_text(f"{display_name} : {list2format_list_text(v, inline=True)}", scope=scope_name) - else: - pin.put_textarea(component_name, label=display_name, value=list2format_list_text(v), scope=scope_name) - - def _onchange_collection_name(self, x): - if x in self.collection_names: - output.clear_scope("PREDICT_AND_VERIFY_01_scope") - output.put_text(t2t("Verified!"), scope="PREDICT_AND_VERIFY_01_scope").style(f'color: green; font_size: 20px') - return - else: - f1 = False - sl = [] - for i in self.collection_names: - if x in i: - f1 = True - output.clear_scope("PREDICT_AND_VERIFY_01_scope") - output.put_text(t2t("Waiting..."), scope="PREDICT_AND_VERIFY_01_scope").style(f'color: black; font_size: 20px') - if len(sl)<=15: - sl.append(i) - - if f1: - output.put_text(t2t("You may want to enter: "), scope="PREDICT_AND_VERIFY_01_scope").style(f'color: black; font_size: 20px') - for i in sl: - output.put_text(i, scope="PREDICT_AND_VERIFY_01_scope").style(f'color: black; font_size: 12px; font-style:italic') - else: - output.clear_scope("PREDICT_AND_VERIFY_01_scope") - output.put_text(t2t("Not a valid name"), scope="PREDICT_AND_VERIFY_01_scope").style(f'color: red; font_size: 20px') - - def _show_str(self, doc_items, component_name, display_name, scope_name, v, doc_special): - if doc_items: - pin.put_select(component_name, - [{"label": i, "value": i} for i in doc_items], value=v, - label=display_name, - scope=scope_name) - elif doc_special: - if doc_special == "$PREDICT_AND_VERIFY_01$": - pin.put_input(component_name, label=display_name, value=v, scope=scope_name) - output.put_scope(name="PREDICT_AND_VERIFY_01_scope", content=[ - output.put_text("") - ], scope=scope_name) - pin.pin_on_change(component_name, onchange=self._onchange_collection_name, clear=False, init_run=True) - else: - if "collection_log.json" in self.file_name: - output.put_text(f"{display_name} : {v}", scope=scope_name) - else: - pin.put_input(component_name, label=display_name, value=v, scope=scope_name) - - # 展示inf型项 - def _show_int(self, doc_items, component_name, display_name, scope_name, v, doc_special): - if doc_items: - pin.put_select(component_name, - [{"label": i, "value": i} for i in doc_items], value=v, - label=display_name, - scope=scope_name) - else: - if "collection_log.json" in self.file_name: - output.put_text(f"{display_name} : {v}", scope=scope_name) - else: - pin.put_input(component_name, label=display_name, value=v, scope=scope_name, type='number') diff --git a/source/webio/webio.py b/source/webio/webio.py index 8c778eda..13c932a8 100644 --- a/source/webio/webio.py +++ b/source/webio/webio.py @@ -1,9 +1,15 @@ from source.util import * -from source.webio.pages import * +from pywebio import * +from source.webio.util import * +from source import webio import subprocess import pywebio import source.webio.log_handler from source.logger import add_logger_to_GUI +from source.webio.webpages.main import MainPage +from source.webio.webpages.general_settings import SettingPage +from source.webio.webpages.combat_settings import CombatSettingPage +from source.webio.webpages.collector_settings import CollectorSettingPage from source.webio.webpages.mission import MissionPage from source.webio.webpages.missiondownload import MissionDownloadPage from source.webio.webpages.video2path import VideoToPathPage diff --git a/source/webio/webpages/collector_settings.py b/source/webio/webpages/collector_settings.py new file mode 100644 index 00000000..2706b480 --- /dev/null +++ b/source/webio/webpages/collector_settings.py @@ -0,0 +1,199 @@ +from source.util import * +from pywebio import * +from source.webio.util import * +from source.webio.webpages.config import ConfigPage +from source.config.cvars import * +from source.funclib import collector_lib + + + +class CollectorSettingPage(ConfigPage): + def __init__(self): + super().__init__(config_file_name = CONFIGNAME_COLLECTOR) + self.collection_names = load_json("ITEM_NAME.json", f"assets\\POI_JSON_API\\{GLOBAL_LANG}") + + def _load_config_files(self): + self.config_files = [] + for root, dirs, files in os.walk('config\\auto_collector'): + for f in files: + if f[f.index('.') + 1:] == "json": + self.config_files.append({"label": f, "value": os.path.join(root, f)}) + self.config_files.append({"label": f"{CONFIGNAME_COLLECTOR}.json", "value": os.path.join(fr"config/settings/{CONFIGNAME_COLLECTOR}.json")}) + + # 重置列表 + @staticmethod + def _reset_list_textarea(x): + pin.pin[x] = "[\n\n]" + + def _load(self): + self.last_file = None + + # 配置页 + output.put_markdown(t2t('## config:'), scope=self.main_scope) + output.put_scope("select_scope", scope=self.main_scope) + pin.put_select('file', self._config_file2lableAfile(self.config_files), scope="select_scope", value="config\\settings\\auto_collector.json") + + def _clean_textarea(self, set_value): + set_value("") + + def _onclick_col_log_operate(self, btn_value:str): + if btn_value == "$COLLECTED$": + collector_lib.generate_collected_from_log() + toast_succ() + elif btn_value == "$BLACKLIST$": + collector_lib.generate_masked_col_from_log() + toast_succ() + + def _before_load_json(self): + if "collection_log.json" in self.file_name: + self.read_only = True + # output.put_buttons([ + + # (_("Automatic generate a list of collected items"), "$COLLECTED$"), + # (_("Automatic generate a list of blacklist items"), "$BLACKLIST$") + # ], + # onclick=self._onclick_col_log_operate, + # scope="now" + # ) + else: + self.read_only = False + return super()._before_load_json() + + def _on_click_collectionlog(self, btn_value:str): + # btn value: $AddToBlackList$#KEY#ID + collect_key = btn_value.split('#')[1] + collect_id = int(btn_value.split('#')[2]) + if "$AddToBlackList$" in btn_value: + collector_lib.add_to_blacklist(collect_key, collect_id) + toast_succ() + elif "$AddToCollected$" in btn_value: + collector_lib.add_to_collected(collect_key, collect_id) + toast_succ() + + + def _show_list(self, level, display_name, scope_name, component_name, doc, v, doc_special): + # 判断是否为dict列表 + is_dict_list = True + for i in v: + is_dict_list = is_dict_list and (type(i) == dict) + + if is_dict_list: + + output.put_markdown('#' * level + ' ' + display_name, + scope=scope_name) + if "collection_log.json" in self.file_name: + for iii in range(len(v)): + v[iii]["picked item"] = str(v[iii]["picked item"]) + v = v[::-1] + show_list = [] + for iii in range(len(v)): + ctime = v[iii]["time"][:v[iii]["time"].index('.')] + show_list.append( [v[iii]["error_code"], v[iii]["id"], v[iii]["picked item"], ctime, + output.put_buttons([ + (t2t("Add to blacklist"), f"$AddToBlackList$#{display_name}#{v[iii]['id']}"), + # (_("Add to collected"), f"$AddToCollected$#{display_name}#{v[iii]['id']}") + ], + onclick=self._on_click_collectionlog, small=True)]) + a1,a2,a3,a4 = collector_lib.col_succ_times_from_log(display_name, day=1) + b1,b2,b3,b4 = collector_lib.col_succ_times_from_log(display_name, day=7) + c1,c2,c3,c4 = collector_lib.col_succ_times_from_log(display_name, day=15) + d1,d2,d3,d4 = collector_lib.col_succ_times_from_log(display_name, day=900) + output.put_collapse(t2t("展开/收起"), [ + + output.put_text(f"{t2t('Within')} 1 {t2t('day(s)')} {t2t('success rate')}:{a1} {t2t('total num')}:{a2} {t2t('success num')}:{a3} {t2t('fail num')}:{a4}"), + output.put_text(f"{t2t('Within')} 7 {t2t('day(s)')} {t2t('success rate')}:{b1} {t2t('total num')}:{b2} {t2t('success num')}:{b3} {t2t('fail num')}:{b4}"), + output.put_text(f"{t2t('Within')} 15 {t2t('day(s)')} {t2t('success rate')}:{c1} {t2t('total num')}:{c2} {t2t('success num')}:{c3} {t2t('fail num')}:{c4}"), + output.put_text(f"{t2t('Within')} 900 {t2t('day(s)')} {t2t('success rate')}:{d1} {t2t('total num')}:{d2} {t2t('success num')}:{d3} {t2t('fail num')}:{d4}"), + output.put_table(show_list, header=["error_code", "id", "picked item", "time", "buttons"]) + ], scope=scope_name) + + + else: + # 差点把我绕晕.... + # 这个是dict的id,是在列表的位置,从1开始,当然也可以改成从0开始,都一样 + dict_id = 0 + # 在当前dict列表里循环,取出每一个dict + for i in v: + # 计次+1 + dict_id += 1 + + + # 创建一个容器以容纳接下来的dict,第一个是控件名称,为了防止重复,加上了dict id,后面那个是当前容器id + output.put_scope(component_name + '-' + str(dict_id), scope=scope_name) + # 写标题,第一项是标题文本,遵守markdown语法,第二项是当前容器名称 + output.put_markdown('#' * (level + 1) + ' ' + str(dict_id), + scope=component_name + '-' + str(dict_id)) + # 写dict,第一项为输入的dict,第二项为doc,第三项为当前容器名称,第四项为控件名称前缀,最后是缩进等级 + self.put_json(i, doc, component_name + '-' + str(dict_id), + component_name + '-' + str(dict_id), + level=level + 2) + else: + # 清除按钮 + if "collected.json" in self.file_name: + output.put_row([ + pin.put_textarea(component_name, label=display_name, value=list2format_list_text(v)), + None, + output.put_button(t2t("clean list"), onclick=lambda:self._reset_list_textarea(component_name)) + ] + , scope=scope_name,size="85% 5% 10%") + elif "collection_log.json" in self.file_name: + # output.put_table() + output.put_text(f"{display_name} : {list2format_list_text(v, inline=True)}", scope=scope_name) + else: + pin.put_textarea(component_name, label=display_name, value=list2format_list_text(v), scope=scope_name) + + def _onchange_collection_name(self, x): + if x in self.collection_names: + output.clear_scope("PREDICT_AND_VERIFY_01_scope") + output.put_text(t2t("Verified!"), scope="PREDICT_AND_VERIFY_01_scope").style(f'color: green; font_size: 20px') + return + else: + f1 = False + sl = [] + for i in self.collection_names: + if x in i: + f1 = True + output.clear_scope("PREDICT_AND_VERIFY_01_scope") + output.put_text(t2t("Waiting..."), scope="PREDICT_AND_VERIFY_01_scope").style(f'color: black; font_size: 20px') + if len(sl)<=15: + sl.append(i) + + if f1: + output.put_text(t2t("You may want to enter: "), scope="PREDICT_AND_VERIFY_01_scope").style(f'color: black; font_size: 20px') + for i in sl: + output.put_text(i, scope="PREDICT_AND_VERIFY_01_scope").style(f'color: black; font_size: 12px; font-style:italic') + else: + output.clear_scope("PREDICT_AND_VERIFY_01_scope") + output.put_text(t2t("Not a valid name"), scope="PREDICT_AND_VERIFY_01_scope").style(f'color: red; font_size: 20px') + + def _show_str(self, doc_items, component_name, display_name, scope_name, v, doc_special): + if doc_items: + pin.put_select(component_name, + [{"label": i, "value": i} for i in doc_items], value=v, + label=display_name, + scope=scope_name) + elif doc_special: + if doc_special == "$PREDICT_AND_VERIFY_01$": + pin.put_input(component_name, label=display_name, value=v, scope=scope_name) + output.put_scope(name="PREDICT_AND_VERIFY_01_scope", content=[ + output.put_text("") + ], scope=scope_name) + pin.pin_on_change(component_name, onchange=self._onchange_collection_name, clear=False, init_run=True) + else: + if "collection_log.json" in self.file_name: + output.put_text(f"{display_name} : {v}", scope=scope_name) + else: + pin.put_input(component_name, label=display_name, value=v, scope=scope_name) + + # 展示inf型项 + def _show_int(self, doc_items, component_name, display_name, scope_name, v, doc_special): + if doc_items: + pin.put_select(component_name, + [{"label": i, "value": i} for i in doc_items], value=v, + label=display_name, + scope=scope_name) + else: + if "collection_log.json" in self.file_name: + output.put_text(f"{display_name} : {v}", scope=scope_name) + else: + pin.put_input(component_name, label=display_name, value=v, scope=scope_name, type='number') \ No newline at end of file diff --git a/source/webio/webpages/combat_settings.py b/source/webio/webpages/combat_settings.py new file mode 100644 index 00000000..3715805b --- /dev/null +++ b/source/webio/webpages/combat_settings.py @@ -0,0 +1,83 @@ +from source.util import * +from pywebio import * +from source.webio.util import * +from source.webio.webpages.config import ConfigPage +from source.config.cvars import * + + + + +class CombatSettingPage(ConfigPage): + def __init__(self): + super().__init__(config_file_name = CONFIGNAME_COMBAT) + from source.common.lang_data import get_all_characters_name + self.character_names = get_all_characters_name() + self.input_verify={ + "character_name":self.character_names + } + + def _autofill(self): + j = self.get_json(json.load(open(self.file_name, 'r', encoding='utf8'))) + autofill_j = load_json("characters_parameters.json", f"{ASSETS_PATH}\\characters_data") + not_found = [] + + from source.common.lang_data import translate_character_auto + for i in j: + cname = translate_character_auto(j[i]["name"]) + if cname is None: + not_found.append(j[i]["name"]) + continue + if cname in autofill_j: + for k in ["position", "E_short_cd_time", "E_long_cd_time", "Elast_time", "Epress_time", "tactic_group", "trigger", "Qlast_time", "Qcd_time", "vision"]: + if j[i][k] == "" or j[i][k] == -1: + j[i][k] = autofill_j[cname][k] + else: + not_found.append(cname) + output.clear_scope('now') + if len(not_found)==0: + output.popup("自动填充", "自动填充成功\n以下选项不会自动填充:\n优先级,角色在队伍中的位置。\n记得保存( ̄▽ ̄)~*") + else: + output.popup("自动填充", + "自动填充部分失败\n"+ + str(not_found)+"\n"+ + "以下选项不会自动填充:\n优先级,角色在队伍中的位置。\n记得保存( ̄▽ ̄)~*") + self.put_setting(name=self.file_name, j=j) + + def _load_config_files(self): + self.config_files = [] + for root, dirs, files in os.walk('config\\tactic'): + for f in files: + if f[f.index('.') + 1:] == "json": + self.config_files.append({"label": f, "value": os.path.join(root, f)}) + self.config_files.append({"label": f"{CONFIGNAME_COMBAT}.json", "value": fr"config/settings/{CONFIGNAME_COMBAT}.json"}) + + def _load(self): + self.last_file = None + + # 添加team.json + output.put_markdown(t2t('# Add team'), scope=self.main_scope) + + # 添加team.json按钮 + output.put_row([ + output.put_button(t2t("Add team"), onclick=self.onclick_add_teamjson), + None, + output.put_button(t2t("自动填充"), onclick=self._autofill)], + scope=self.main_scope, size="10% 10px 20%") + + # 配置页 + output.put_markdown(t2t('## config:'), scope=self.main_scope) + output.put_scope("select_scope", scope=self.main_scope) + pin.put_select('file', self._config_file2lableAfile(self.config_files), scope="select_scope", value="config/settings/Combat.json") + + def onclick_add_teamjson(self): + n = input.input('team name') + shutil.copy(os.path.join(ROOT_PATH, "config\\tactic\\team.uijsontemplate"), + os.path.join(ROOT_PATH, "config\\tactic", n + '.json')) + self._reload_select() + + def onclick_add_teamjson_withcharacters(self): + n = input.input('team name') + shutil.copy(os.path.join(ROOT_PATH, "config\\tactic\\team_with_characters.uijsontemplate"), + os.path.join(ROOT_PATH, "config\\tactic", n + '.json')) + self._reload_select() + pass \ No newline at end of file diff --git a/source/webio/webpages/config.py b/source/webio/webpages/config.py new file mode 100644 index 00000000..ca3e7a55 --- /dev/null +++ b/source/webio/webpages/config.py @@ -0,0 +1,391 @@ +from source.util import * +from pywebio import * +from source.webio.util import * +import hashlib +import json +import os +import time +from source.webio.advance_page import AdvancePage +from source.config.cvars import * + + +class ConfigPage(AdvancePage): + def __init__(self, config_file_name): + super().__init__() + + # self.main_scope = "SettingPage" + + self.exit_popup = None + self.last_file = None + self.file_name = '' + self.config_file_name = config_file_name + + self.config_files = [] + self.config_files_name = [] + self._load_config_files() + self.can_check_select = True + self.can_remove_last_scope = False + # 注释显示模式在这改 + self.mode = True + self.read_only = False + + self.input_verify={ + "test":lambda x:x + } + + def _load_config_files(self): + for root, dirs, files in os.walk('config'): + for f in files: + if f[f.index('.') + 1:] == "json": + self.config_files.append({"label": f, "value": os.path.join(root, f)}) + + def _load(self): + self.last_file = None + + # 配置页 + output.put_markdown(t2t('## config:'), scope=self.main_scope) + + output.put_scope("select_scope", scope=self.main_scope) + pin.put_select('file', self._config_file2lableAfile(self.config_files), scope="select_scope") + + def _config_file2lableAfile(self, l1): + replace_dict = { + "Combat.json": t2t("Combat.json"), + "Domain.json": t2t("Domain.json"), + "General.json": t2t("General.json"), + "Keymap.json": t2t("Keymap.json"), + "collected.json": t2t("collected.json"), + "collection_blacklist.json": t2t("collection_blacklist.json"), + "collection_log.json": t2t("collection_log.json"), + "Collector.json": t2t("Collector.json"), + "LeyLineOutcrop.json": t2t("LeyLineOutcrop.json") + } + + for i in range(len(l1)): + l1[i]["label"] = replace_dict.setdefault(l1[i]["label"], l1[i]["label"]) + return l1 + + # 重新加载选项 + def _reload_select(self): + self.can_check_select = False + self._load_config_files() + output.clear("select_scope") + pin.put_select('file', self._config_file2lableAfile(self.config_files), scope="select_scope") + self.can_check_select = True + + # 循环线程 + def _event_thread(self): + while self.loaded: + if not self.can_check_select: + time.sleep(1) + continue + try: + pin.pin['isSessionExist'] + except SessionNotFoundException: + logger.info(t2t("未找到会话,可能由于窗口关闭。请刷新页面重试。")) + return + + if pin.pin['file'] != self.last_file: # 当下拉框被更改时 + self.last_file = pin.pin['file'] + + if self.can_remove_last_scope: # 判断是否可以移除 + output.remove('now') + else: + self.can_remove_last_scope = True + + output.put_scope('now', scope=self.main_scope) # 创建配置页scope + + + self.put_setting(pin.pin['file']) # 配置配置页 + + time.sleep(1) + + def _str_verify(self, x, verify_list, scope_name): + if x in verify_list: + output.clear_scope(scope_name) + output.put_text(t2t("Verified!"), scope=scope_name).style(f'color: green; font_size: 20px') + return + else: + f1 = False + sl = [] + for i in verify_list: + if x in i: + f1 = True + output.clear_scope(scope_name) + output.put_text(t2t("Waiting..."), scope=scope_name).style(f'color: black; font_size: 20px') + if len(sl)<=15: + sl.append(i) + + if f1: + output.put_text(t2t("You may want to enter: "), scope=scope_name).style(f'color: black; font_size: 20px') + for i in sl: + output.put_text(i, scope=scope_name).style(f'color: black; font_size: 12px; font-style:italic') + else: + output.clear_scope(scope_name) + output.put_text(t2t("Not a valid name"), scope=scope_name).style(f'color: red; font_size: 20px') + + def _before_load_json(self): + pass + + def put_setting(self, name='', j=None): + self.file_name = name + self._before_load_json() + output.put_markdown('## {}'.format(name), scope='now') # 标题 + if j is None: + with open(name, 'r', encoding='utf8') as f: + j = json.load(f) + + # with open(os.path.join(root_path, "config", "settings", "config.json"), 'r', encoding='utf8') as f: + # lang = json.load(f)["lang"] + doc_name = f'config\\json_doc\\{self.config_file_name}.yaml' + lang_doc_name = f'config\\json_doc\\{self.config_file_name}.{GLOBAL_LANG}.yaml' + + if os.path.exists(doc_name): + with open(doc_name, 'r', encoding='utf8') as f: + doc = yaml.load(f, Loader=yaml.FullLoader) + if os.path.exists(lang_doc_name): + with open(lang_doc_name, 'r', encoding='utf8') as f: + doc_addi = yaml.load(f, Loader=yaml.FullLoader) + for k1 in doc_addi: + for k2 in doc_addi[k1]: + if k1 not in doc: + doc[k1] = doc_addi[k1] + doc[k1][k2] = doc_addi[k1][k2] + else: + doc = {} + self.put_json(j, doc, 'now', level=3) # 载入json + + if not self.read_only: + output.put_button('save', scope='now', onclick=self.save) + + # 保存json文件 + def save(self): + + j = json.load(open(self.file_name, 'r', encoding='utf8')) + + json.dump(self.get_json(j), open(self.file_name, 'w', encoding='utf8'), ensure_ascii=False, indent=4) + # output.put_text('saved!', scope='now') + output.toast(t2t('saved!'), color='success', duration=4) + output.toast(t2t('You may need to restart to apply changes.'), duration=4) + GIAconfig.update() + + # + def get_json(self, j: dict, add_name=''): + rt_json = {} + for k in j: + k_sha1 = hashlib.sha1(k.encode('utf8')).hexdigest() + v = j[k] + if type(v) == dict: + rt_json[k] = self.get_json(v, add_name='{}-{}'.format(add_name, k_sha1)) + + elif type(v) == list: + + # 判断是否为dict列表 + is_dict_list = True + for i in v: + is_dict_list = is_dict_list and (type(i) == dict) + + if is_dict_list: + # 这个是dict的id,是在列表的位置,从1开始,当然也可以改成从0开始,都一样 + dict_id = 0 + # 在当前dict列表里循环,取出每一个dict + rt_list = [] + for i in v: + # 计次+1 + dict_id += 1 + rt_list.append( + self.get_json(v[dict_id - 1], add_name='{}-{}-{}'.format(add_name, k_sha1, str(dict_id)))) + rt_json[k] = rt_list + else: + rt_json[k] = list_text2list(pin.pin['{}-{}'.format(add_name, k_sha1)]) + else: + rt_json[k] = pin.pin['{}-{}'.format(add_name, k_sha1)] + + return rt_json + + def _on_unload(self): + if not self.read_only: + j = json.load(open(self.file_name, 'r', encoding='utf8')) + self.exit_popup = True + if not is_json_equal(json.dumps(self.get_json(j)), json.dumps(j)): + self.exit_popup = False + output.popup(t2t('Do you need to save changes?'), [ + output.put_buttons([(t2t('No'), 'No'), (t2t('Yes'), 'Yes')], onclick=self.popup_button) + ]) + while not self.exit_popup: + time.sleep(0.1) + + def popup_button(self, val): + if val == 'No': + self.close_popup() + elif val == 'Yes': + self.save_and_exit_popup() + + def save_and_exit_popup(self): + self.save() + output.close_popup() + self.exit_popup = True + + def close_popup(self): + output.close_popup() + self.exit_popup = True + + # 展示str型项 + def _show_str(self, doc_items, component_name, display_name, scope_name, v, doc_special): + if doc_items: + pin.put_select(component_name, + [{"label": i, "value": i} for i in doc_items], value=v, + label=display_name, + scope=scope_name) + elif doc_special: + doc_special = doc_special.split('#') + if doc_special[0] == "$FILE_IN_FOLDER$": + + json_dict = load_json_from_folder(os.path.join(ROOT_PATH, doc_special[1]), black_file=["character","character_dist",""]) + sl = [] + for i in json_dict: + sl.append({"label": i["label"], "value": i["label"]}) + pin.put_select(component_name, + sl, value=v, + label=display_name, + scope=scope_name) + elif doc_special[0] == "$INPUT_VERIFY$": + pin.put_input(component_name, label=display_name, value=v, scope=scope_name) + output.put_scope(name=component_name, content=[ + output.put_text("") + ], scope=scope_name) + def onchange(x): + self._str_verify(x, verify_list=self.input_verify[doc_special[1]], scope_name=component_name) + pin.pin_on_change(component_name, onchange=onchange, clear=False, init_run=True) + else: + pin.put_input(component_name, label=display_name, value=v, scope=scope_name) + + # 展示inf型项 + def _show_int(self, doc_items, component_name, display_name, scope_name, v, doc_special): + if doc_items: + pin.put_select(component_name, + [{"label": i, "value": i} for i in doc_items], value=v, + label=display_name, + scope=scope_name) + else: + pin.put_input(component_name, label=display_name, value=v, scope=scope_name, type='number') + + # 展示float型项 + def _show_float(self, doc_items, component_name, display_name, scope_name, v, doc_special): + if doc_items: + pin.put_select(component_name, + [{"label": i, "value": i} for i in doc_items], value=v, + label=display_name, + scope=scope_name) + else: + pin.put_input(component_name, label=display_name, value=v, scope=scope_name, type='float') + + # 展示bool型项 + def _show_bool(self, component_name, display_name, scope_name, v, doc_special): + pin.put_select(component_name, + [{"label": 'True', "value": True}, {"label": 'False', "value": False}], value=v, + label=display_name, + scope=scope_name) + + # 展示dict型项 + def _show_dict(self, level, component_name, display_name, scope_name, doc, v, doc_special): + output.put_scope(component_name, scope=scope_name) + output.put_markdown('#' * level + ' ' + display_name, scope=component_name) + self.put_json(v, doc, component_name, add_name=component_name, + level=level + 1) + + # 展示list/list&dict型项 + def _show_list(self, level, display_name, scope_name, component_name, doc, v, doc_special): + # 判断是否为dict列表 + is_dict_list = True + for i in v: + is_dict_list = is_dict_list and (type(i) == dict) + + if is_dict_list: + output.put_markdown('#' * level + ' ' + display_name, + scope=scope_name) + # 差点把我绕晕.... + # 这个是dict的id,是在列表的位置,从1开始,当然也可以改成从0开始,都一样 + dict_id = 0 + # 在当前dict列表里循环,取出每一个dict + for i in v: + # 计次+1 + dict_id += 1 + + # 创建一个容器以容纳接下来的dict,第一个是控件名称,为了防止重复,加上了dict id,后面那个是当前容器id + output.put_scope(component_name + '-' + str(dict_id), scope=scope_name) + # 写标题,第一项是标题文本,遵守markdown语法,第二项是当前容器名称 + output.put_markdown('#' * (level + 1) + ' ' + str(dict_id), + scope=component_name + '-' + str(dict_id)) + # 写dict,第一项为输入的dict,第二项为doc,第三项为当前容器名称,第四项为控件名称前缀,最后是缩进等级 + self.put_json(i, doc, component_name + '-' + str(dict_id), + component_name + '-' + str(dict_id), + level=level + 2) + else: + pin.put_textarea(component_name, label=display_name, value=list2format_list_text(v), + scope=scope_name) + + # 显示json + def put_json(self, j: dict, doc: dict, scope_name, add_name='', level=1): + for k in j: + v = j[k] + # 获取注释 + doc_now = '' + doc_now_data = {} + doc_items = None + doc_special = None + doc_annotation = None + doc_type = None + if k in doc: + # 判断doc的类型 + if type(doc[k]) == dict: + if 'doc' in doc[k]: + doc_now = doc[k]['doc'] + if 'data' in doc[k]: + doc_now_data = doc[k]['data'] + if 'select_items' in doc[k]: + doc_items = doc[k]['select_items'] + if 'special_index' in doc[k]: + doc_special = doc[k]['special_index'] + if "annotation" in doc[k]: + doc_annotation = doc[k]['annotation'] + if 'type' in doc[k]: + doc_type = doc[k]['type'] + if type(doc[k]) == str: + doc_now = doc[k] + # 取显示名称 + display_name = doc_now if doc_now else k if self.mode else '{} {}'.format(k, doc_now) + + k_sha1 = hashlib.sha1(k.encode('utf8')).hexdigest() + component_name = '{}-{}'.format(add_name, k_sha1) + + if doc_type != None: + if doc_type == 'int': + self._show_int(doc_items, component_name, display_name, scope_name, v, doc_special) + elif doc_type == 'float': + self._show_float(doc_items, component_name, display_name, scope_name, v, doc_special) + elif doc_type == 'bool': + self._show_bool(component_name, display_name, scope_name, v, doc_special) + elif doc_type == 'dict': + self._show_dict(level, component_name, display_name, scope_name, doc, v, doc_special) + elif doc_type == 'list': + self._show_list(level, display_name, scope_name, component_name, doc, v, doc_special) + elif doc_type == 'str': + self._show_str(doc_items, component_name, display_name, scope_name, v, doc_special) + else: + if type(v) == str or v is None: + self._show_str(doc_items, component_name, display_name, scope_name, v, doc_special) + elif type(v) == int: + self._show_int(doc_items, component_name, display_name, scope_name, v, doc_special) + elif type(v) == float: + self._show_float(doc_items, component_name, display_name, scope_name, v, doc_special) + elif type(v) == bool: + self._show_bool(component_name, display_name, scope_name, v, doc_special) + elif type(v) == dict: + self._show_dict(level, component_name, display_name, scope_name, doc, v, doc_special) + elif type(v) == list: + self._show_list(level, display_name, scope_name, component_name, doc, v, doc_special) + if doc_annotation != None: + output.put_text(doc_annotation, scope=scope_name) + output.put_text("\n", scope=scope_name).style("font-size: 1px") + diff --git a/source/webio/webpages/general_settings.py b/source/webio/webpages/general_settings.py new file mode 100644 index 00000000..fb65a666 --- /dev/null +++ b/source/webio/webpages/general_settings.py @@ -0,0 +1,33 @@ +from source.util import * +from pywebio import * +from source.webio.util import * +from source.webio.webpages.config import ConfigPage +from source.config.cvars import * + + +class SettingPage(ConfigPage): + def __init__(self): + super().__init__(config_file_name = CONFIGNAME_GENERAL) + self.domain_name = load_json(f"Domain_Names_{GLOBAL_LANG}.json", fr"{ASSETS_PATH}/domain_names") + self.input_verify={ + "domain_name":self.domain_name + } + + def _load(self): + self.last_file = None + + # 配置页 + output.put_markdown(t2t('## config:'), scope=self.main_scope) + output.put_scope("select_scope", scope=self.main_scope) + + pin.put_select('file', self._config_file2lableAfile(self.config_files), scope="select_scope", value="config\\settings\\config.json") + + def _load_config_files(self): + # for root, dirs, files in os.walk('config\\settings'): + # for f in files: + # if f[:f.index('.')] in ["auto_combat", "auto_collector", "auto_pickup_default_blacklist"]: + # continue + # if f[f.index('.') + 1:] == "json": + # self.config_files.append({"label": f, "value": os.path.join(root, f)}) + for i in [CONFIGNAME_GENERAL, CONFIGNAME_DOMAIN, CONFIGNAME_KEYMAP, CONFIGNAME_LEY_LINE_OUTCROP]: + self.config_files.append({"label": f"{i}.json", "value": os.path.join(fr"{CONFIG_PATH_SETTING}", f"{i}.json")}) \ No newline at end of file diff --git a/source/webio/webpages/main.py b/source/webio/webpages/main.py new file mode 100644 index 00000000..07e78ac5 --- /dev/null +++ b/source/webio/webpages/main.py @@ -0,0 +1,210 @@ +from source.util import * +from pywebio import * +from source.webio.util import * + +import socket +import threading +import time + +from source import listening +from source.webio.advance_page import AdvancePage +from source.common import timer_module +from source.webio.update_notice import upd_message +from source.config.cvars import * + + + +class MainPage(AdvancePage): + def __init__(self): + super().__init__() + self.log_list = [] + self.log_history = [] + self.log_list_lock = threading.Lock() + self.ui_statement = -1 + self.refresh_flow_info_timer = timer_module.Timer() + self.ui_mission_select = "" + self.is_task_start = False + + # todo:多语言支持 + + def _on_load(self): # 加载事件 + super()._on_load() + pin.pin['FlowMode'] = listening.current_flow + + def _event_thread(self): + while self.loaded: # 当界面被加载时循环运行 + try: + pin.pin['isSessionExist'] + except SessionNotFoundException: + logger.info(t2t("未找到会话,可能由于窗口关闭。请刷新页面重试。")) + return + except SessionClosedException: + logger.info(t2t("未找到会话,可能由于窗口关闭。请刷新页面重试。")) + return + if pin.pin['FlowMode'] != listening.current_flow: # 比较变更是否被应用 + listening.current_flow = pin.pin['FlowMode'] # 应用变更 + self.log_list_lock.acquire() + output.put_text(t2t("正在导入模块, 可能需要一些时间。"), scope='LogArea').style( + f'color: black; font_size: 20px') + output.put_text(t2t("在导入完成前,请不要切换页面。"), scope='LogArea').style( + f'color: black; font_size: 20px') + self.log_list_lock.release() + listening.call_you_import_module() + # if pin.pin["MissionSelect"] != self.ui_mission_select: + # self.ui_mission_select = pin.pin["MissionSelect"] + # output.clear_scope("SCOPEMissionIntroduction") + # if self.ui_mission_select is None: + # continue + # output.put_text(self._get_mission_groups_dict()["introduction"][GLOBAL_LANG],scope="SCOPEMissionIntroduction") + + self.log_list_lock.acquire() + for text, color in self.log_list: + if text == "$$end$$": + output.put_text("", scope='LogArea') + else: + output.put_text(text, scope='LogArea', inline=True).style(f'color: {color}; font_size: 20px') # ; background: aqua + + self.log_list.clear() + self.log_list_lock.release() + + if self.refresh_flow_info_timer.get_diff_time() >= 0.2: + self.refresh_flow_info_timer.reset() + if listening.TASK_MANAGER.get_task_statement() != self.ui_statement: + self.ui_statement = listening.TASK_MANAGER.get_task_statement() + output.clear(scope="StateArea") + # if isinstance(self.ui_statement, list): + # for i in self.ui_statement: + # output.put_text(f'{i["name"]}: {i["statement"]}: {i["rfc"]}', scope="StateArea") + # elif isinstance(self.ui_statement, str): + output.put_text(f'{self.ui_statement}', scope="StateArea") + + if listening.TASK_MANAGER.start_tasklist_flag != self.is_task_start: + self.is_task_start = listening.TASK_MANAGER.start_tasklist_flag + output.clear('Button_StartStop') + output.put_button(label=str(listening.TASK_MANAGER.start_tasklist_flag), onclick=self.on_click_startstop, + scope='Button_StartStop') + + + time.sleep(0.1) + + def _load(self): + # 标题 + # 获得链接按钮 + with output.use_scope(self.main_scope): + output.put_row([ + output.put_button(label=t2t("Get IP address"), onclick=self.on_click_ip_address, scope=self.main_scope), + output.put_link(t2t('View Document'), url='https://genshinimpactassistant.github.io/GIA-Document', new_window = True).style('font-size: 20px') + ]) + + + task_options = [ + { + "label":t2t("Launch genshin"), + "value":"LaunchGenshinTask" + }, + { + "label":t2t("Domain Task"), + "value":"DomainTask" + }, + { + "label":t2t("Daily Commission"), + "value":"CommissionTask" + }, + { + "label":t2t("Claim Reward"), + "value":"ClaimRewardTask" + }, + { + "label":t2t("Ley Line Outcrop"), + "value":"LeyLineOutcropTask" + }, + { + "label":t2t("Mission"), + "value":"MissionTask" + } + ] + output.put_row([ # 横列 + output.put_column([ # 左竖列 + output.put_markdown('## '+t2t("Task List")), + output.put_markdown(t2t("Can only be activated from the button")), + pin.put_checkbox(name="task_list", options=task_options), + output.put_row([output.put_text(t2t('启动/停止Task')), None, output.put_scope('Button_StartStop')],size='40% 10px 60%'), + + output.put_markdown(t2t('## Statement')), + output.put_row([output.put_text(t2t('任务状态')), None, output.put_scope('StateArea')],size='40% 10px 60%'), + output.put_markdown(t2t('## Semi-automatic Functions')), # 左竖列标题 + output.put_markdown(t2t("Can only be activated from the hotkey \'[\'")), + output.put_text(t2t('Do not enable semi-automatic functions and tasks at the same time')), + output.put_row([ # FlowMode + output.put_text(t2t('Semi-automatic Functions')), + + pin.put_select(('FlowMode'), [ + {'label': t2t('Idle'), 'value': listening.FLOW_IDLE}, + {'label': t2t('Auto Combat'), 'value': listening.FLOW_COMBAT} + ]), + ], + + ) + ], size='auto'), None, + output.put_scope('Log') + + ], scope=self.main_scope, size='40% 10px 60%') + + # PickUpButton + output.put_button(label=str(listening.FEAT_PICKUP), onclick=self.on_click_pickup, scope='Button_PickUp') + # Button_StartStop + output.put_button(label=str(listening.startstop_flag), onclick=self.on_click_startstop, + scope='Button_StartStop') + + # Log + output.put_markdown(t2t('## Log'), scope='Log') + output.put_scrollable(output.put_scope('LogArea'), height=600, keep_bottom=True, scope='Log') + '''self.main_pin_change_thread = threading.Thread(target=self._main_pin_change_thread, daemon=False) + self.main_pin_change_thread.start()''' + + m = upd_message() + if m!="": + output.popup(t2t('更新提示'), m) + + # def _get_mission_groups_config(self): + # jsons = load_json_from_folder(f"{CONFIG_PATH}\\mission_groups") + # r = [i["label"] for i in jsons] + # return r + + # def _get_mission_groups_dict(self): + # jsonname = pin.pin["MissionSelect"] + # if jsonname is None: + # raise FileNotFoundError + # return load_json(str(jsonname),default_path=f"{CONFIG_PATH}\\mission_groups") + + def on_click_pickup(self): + output.clear('Button_PickUp') + listening.FEAT_PICKUP = not listening.FEAT_PICKUP + output.put_button(label=str(listening.FEAT_PICKUP), onclick=self.on_click_pickup, scope='Button_PickUp') + + def on_click_startstop(self): + # listening.MISSION_MANAGER.set_mission_list(list(pin.pin["MissionSelect"])) + listening.TASK_MANAGER.set_tasklist(pin.pin["task_list"]) + listening.TASK_MANAGER.start_stop_tasklist() + # if pin.pin["MissionSelect"] != None and pin.pin["MissionSelect"] != "": + # cj = load_json() + # cj["MissionGroup"] = pin.pin["MissionSelect"] + # save_json(cj) + # GIAconfig.update() + + time.sleep(0.2) + output.clear('Button_StartStop') + output.put_button(label=str(listening.TASK_MANAGER.start_tasklist_flag), onclick=self.on_click_startstop, + scope='Button_StartStop') + + def on_click_ip_address(self): + LAN_ip = f"{socket.gethostbyname(socket.gethostname())}{session.info.server_host[session.info.server_host.index(':'):]}" + WAN_ip = t2t("Not Enabled") + output_text = t2t('LAN IP') + " : " + LAN_ip + '\n' + t2t("WAN IP") + ' : ' + WAN_ip + output.popup(f'ip address', output_text, size=output.PopupSize.SMALL) + + def logout(self, text: str, color='black'): + if self.loaded: + self.log_list_lock.acquire() + self.log_list.append((text, color)) + self.log_list_lock.release() \ No newline at end of file From 5bbbfaec5e16b534802c7a75d7ef44de3dc254e1 Mon Sep 17 00:00:00 2001 From: infstellar <98541813+infstellar@users.noreply.github.com> Date: Thu, 22 Jun 2023 11:40:29 +0800 Subject: [PATCH 36/40] fix: Incorrect view recognition #65 --- source/map/detection/minimap.py | 9 ++++++--- source/map/map.py | 3 ++- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/source/map/detection/minimap.py b/source/map/detection/minimap.py index be7cc61a..912622d9 100644 --- a/source/map/detection/minimap.py +++ b/source/map/detection/minimap.py @@ -272,8 +272,8 @@ def _get_minimap_subtract(self, image, update_position=True): image = image.astype(np.uint8) return image - def _predict_rotation(self, image): - if not GIAconfig.General_UsingAlphaChannel: + def _predict_rotation(self, image, use_alpha = False): + if not use_alpha: d = self.MINIMAP_RADIUS * 2 # Upscale image and apply Gaussian filter for smother results scale = 2 @@ -364,6 +364,9 @@ def _predict_rotation(self, image): def update_rotation(self, image, layer=MapConverter.LAYER_Teyvat, update_position=True): if image.shape[2]==4: image = image[:,:,:3] + use_alpha = (self.scene == 'city') + else: + use_alpha = False # minimap = self._get_minimap(image, radius=self.MINIMAP_RADIUS) # minimap = rgb2luma(minimap) if layer == MapConverter.LAYER_Domain: @@ -372,7 +375,7 @@ def update_rotation(self, image, layer=MapConverter.LAYER_Teyvat, update_positio else: minimap = self._get_minimap_subtract(image, update_position=update_position) - self.rotation = self._predict_rotation(minimap) + self.rotation = self._predict_rotation(minimap, use_alpha=use_alpha) # Uncomment this to debug # self.show_rotation(minimap, self.degree) diff --git a/source/map/map.py b/source/map/map.py index 263c1a4e..ff6cec95 100644 --- a/source/map/map.py +++ b/source/map/map.py @@ -455,7 +455,8 @@ def bigmap_tp(self, posi: list, tp_mode=0, tp_type: list = None, csf=lambda:Fals genshin_map.reinit_smallmap() while 1: time.sleep(0.2) + # print(genshin_map.get_rotation()) # input() # itt.key_down('w') - print(genshin_map.get_and_verify_position()) + # print(genshin_map.get_and_verify_position()) From 08de65741855dc788863ad231e9d16d3f715966b Mon Sep 17 00:00:00 2001 From: infstellar <98541813+infstellar@users.noreply.github.com> Date: Thu, 22 Jun 2023 12:00:36 +0800 Subject: [PATCH 37/40] opt: update notice --- config/json_template/General.jsontemplate | 2 +- source/webio/update_notice.py | 34 ++++++++++++++--------- source/webio/webpages/main.py | 2 +- 3 files changed, 23 insertions(+), 15 deletions(-) diff --git a/config/json_template/General.jsontemplate b/config/json_template/General.jsontemplate index 65d7fcdc..0fa3fcff 100644 --- a/config/json_template/General.jsontemplate +++ b/config/json_template/General.jsontemplate @@ -12,5 +12,5 @@ "DeterminingStrictWeight":0.9, "InteractionMode": "Desktop", "Python32Path": "", - "Version":"v0.7.3.900" + "Version":"v0.8.5.0" } \ No newline at end of file diff --git a/source/webio/update_notice.py b/source/webio/update_notice.py index 2498bec5..9a4eb670 100644 --- a/source/webio/update_notice.py +++ b/source/webio/update_notice.py @@ -5,19 +5,27 @@ def upd_message(): version_num = int(GIAconfig.General_Version.split('.')[-1]) if version_num!=int(GIA_VERSION.split(".")[-1]): ret_message+=t2t("GIA 已升级到")+f"{GIA_VERSION}. \n" - if version_num <= 500: - ret_message+=f"推荐删除tactic中的team.json和team_example_3.json,然后重启GIA。\n" - if version_num < 753: - ret_message+=f"战斗策略自动填充已经可用。\n可以删除tactic中的team.json和team_example_3.json,然后重启GIA。\n" - if version_num < 779: - ret_message+=f"现已支持多显示器多缩放设置。可能存在问题,欢迎反馈。\n" - if version_num < 874: - ret_message+=f"config设置已重置,请重新设置config。\n"\ - "tactic, collector等设置可以继续使用。\n"\ - "注意:队伍设置现在默认为自适应,如果需要使用你自己的设置,请将AdaptiveTeamSetup(自适应队伍设置)设置为false。" - if version_num < 933: - ret_message+=f"升级自定义任务的UI界面\n\ - 提升自定义任务采集成功率" + + if version_num==0: + ret_message = t2t("Welcome to GIA!") + '\n\n' + ret_message += t2t('This software is open source, free of charge and for learning and exchange purposes only. The developer team has the final right to interpret this project. All problems arising from the use of this software are not related to this project and the developer team. If you encounter a merchant using this software to practice on your behalf and charging for it, it may be the cost of equipment and time, etc. The problems and consequences arising from this software have nothing to do with it.') + '\n\n' + ret_message += t2t('By using this software, you acknowledge that you have fully read and agree to the GIA License, User Agreement and the above statements.') + '\n\n' + ret_message += t2t('GIA is free and open source software on Github and Gitee. If you have purchased GIA from any source, you have been scammed.') + '\n\n' + else: + + if version_num <= 500: + ret_message+=f"推荐删除tactic中的team.json和team_example_3.json,然后重启GIA。\n" + if version_num < 753: + ret_message+=f"战斗策略自动填充已经可用。\n可以删除tactic中的team.json和team_example_3.json,然后重启GIA。\n" + if version_num < 779: + ret_message+=f"现已支持多显示器多缩放设置。可能存在问题,欢迎反馈。\n" + if version_num < 874: + ret_message+=f"config设置已重置,请重新设置config。\n"\ + "tactic, collector等设置可以继续使用。\n"\ + "注意:队伍设置现在默认为自适应,如果需要使用你自己的设置,请将AdaptiveTeamSetup(自适应队伍设置)设置为false。" + if version_num < 933: + ret_message+=f"升级自定义任务的UI界面\n\ + 提升自定义任务采集成功率" x=load_json() x["Version"]=GIA_VERSION diff --git a/source/webio/webpages/main.py b/source/webio/webpages/main.py index 07e78ac5..ee4e798c 100644 --- a/source/webio/webpages/main.py +++ b/source/webio/webpages/main.py @@ -164,7 +164,7 @@ def _load(self): m = upd_message() if m!="": - output.popup(t2t('更新提示'), m) + output.popup(t2t('Update Notice'), m, implicit_close=False) # def _get_mission_groups_config(self): # jsons = load_json_from_folder(f"{CONFIG_PATH}\\mission_groups") From 4711576d13b477d17fabdd67b7fef67223f8c87a Mon Sep 17 00:00:00 2001 From: infstellar <98541813+infstellar@users.noreply.github.com> Date: Thu, 22 Jun 2023 16:37:51 +0800 Subject: [PATCH 38/40] fix: get_characters_name: raise exception --- source/funclib/combat_lib.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/source/funclib/combat_lib.py b/source/funclib/combat_lib.py index e8417f34..3a91347a 100644 --- a/source/funclib/combat_lib.py +++ b/source/funclib/combat_lib.py @@ -386,9 +386,9 @@ def get_characters_name(max_retry = 50): ret_list.append(None) if len(ret_list)==4: return ret_list - else: - itt.save_snapshot('RecognizeCharacterNameError') - raise RecognizeCharacterNameError('Recognize fail') + + itt.save_snapshot('RecognizeCharacterNameError') + raise RecognizeCharacterNameError('Recognize fail') return ret_list def get_team_chara_names_in_party_setup(): From 48800dbbaa5cb6921680601368bf3621017eb7e4 Mon Sep 17 00:00:00 2001 From: infstellar <98541813+infstellar@users.noreply.github.com> Date: Thu, 22 Jun 2023 16:45:02 +0800 Subject: [PATCH 39/40] add: commission: LanguageExchange_P960N6796 --- source/commission/commission_index.py | 23 ++++++---- .../commissions/BigPudgyProblem_P2469N4886.py | 22 ---------- .../commissions/BigPudgyProblem_P2526N5796.py | 22 ---------- .../LanguageExchange_P3060N5078.py | 4 +- .../commissions/LanguageExchange_P960N6796.py | 42 +++++++++++++++++++ 5 files changed, 60 insertions(+), 53 deletions(-) delete mode 100644 source/commission/commissions/BigPudgyProblem_P2469N4886.py delete mode 100644 source/commission/commissions/BigPudgyProblem_P2526N5796.py create mode 100644 source/commission/commissions/LanguageExchange_P960N6796.py diff --git a/source/commission/commission_index.py b/source/commission/commission_index.py index c4d5ce56..ffaaa293 100644 --- a/source/commission/commission_index.py +++ b/source/commission/commission_index.py @@ -1,21 +1,30 @@ """This file is generated automatically. Do not manually modify it.""" -COMMISSION_INDEX = {'ASmallStepForHilichurls_N1000P1000': {'type': 'ASmallStepForHilichurls', 'position': [-1000, 1000]}, 'BasicKnowledgeOfTheKnights_P2682N5673': {'type': 'BasicKnowledgeOfTheKnights', 'position': [2682, -5673]}, 'BigPudgyProblem_P2469N4886': {'type': 'BigPudgyProblem', 'position': [2469, -4886]}, 'BigPudgyProblem_P2526N5796': {'type': 'BigPudgyProblem', 'position': [2526, -5796]}, 'LanguageExchange_P3060N5078': {'type': 'LanguageExchange', 'position': [3060, -5078]}, 'PigeonsGoAWOL_P2671N5095': {'type': 'PigeonsGoAWOL', 'position': [2671, -5095]}, 'TheUnnoticedGuy_P2568N5889': {'type': 'TheUnnoticedGuy', 'position': [2568, -5889]}} +COMMISSION_INDEX = {'BasicKnowledgeOfTheKnights_P2682N5673': {'type': 'BasicKnowledgeOfTheKnights', 'position': [2682, -5673]}, 'FloralFresh_P2556N5813': {'type': 'FloralFresh', 'position': [2556, -5813]}, 'FreshFlora_P2648N5726': {'type': 'FreshFlora', 'position': [2648, -5726]}, 'LanguageExchange_P3060N5078': {'type': 'LanguageExchange', 'position': [3060, -5078]}, 'LanguageExchange_P960N6796': {'type': 'LanguageExchange', 'position': [960, -6796]}, 'PigeonsGoAWOL_P2671N5095': {'type': 'PigeonsGoAWOL', 'position': [2671, -5095]}, 'ReliableHelper_P2966N4774': {'type': 'ReliableHelper', 'position': [2966, -4774]}, 'TheUnnoticedGuy_P2568N5889': {'type': 'TheUnnoticedGuy', 'position': [2568, -5889]}, 'TheWannabeKnight_P2251N5771': {'type': 'TheWannabeKnight', 'position': [2251, -5771]}} def get_commission_object(commission_name:str): if commission_name == 'BasicKnowledgeOfTheKnights_P2682N5673': import source.commission.commissions.BasicKnowledgeOfTheKnights_P2682N5673 return source.commission.commissions.BasicKnowledgeOfTheKnights_P2682N5673.BasicKnowledgeOfTheKnights_P2682N5673() - if commission_name == 'BigPudgyProblem_P2469N4886': - import source.commission.commissions.BigPudgyProblem_P2469N4886 - return source.commission.commissions.BigPudgyProblem_P2469N4886.BigPudgyProblem_P2469N4886() - if commission_name == 'BigPudgyProblem_P2526N5796': - import source.commission.commissions.BigPudgyProblem_P2526N5796 - return source.commission.commissions.BigPudgyProblem_P2526N5796.BigPudgyProblem_P2526N5796() + if commission_name == 'FloralFresh_P2556N5813': + import source.commission.commissions.FloralFresh_P2556N5813 + return source.commission.commissions.FloralFresh_P2556N5813.FloralFresh_P2556N5813() + if commission_name == 'FreshFlora_P2648N5726': + import source.commission.commissions.FreshFlora_P2648N5726 + return source.commission.commissions.FreshFlora_P2648N5726.FreshFlora_P2648N5726() if commission_name == 'LanguageExchange_P3060N5078': import source.commission.commissions.LanguageExchange_P3060N5078 return source.commission.commissions.LanguageExchange_P3060N5078.LanguageExchange_P3060N5078() + if commission_name == 'LanguageExchange_P960N6796': + import source.commission.commissions.LanguageExchange_P960N6796 + return source.commission.commissions.LanguageExchange_P960N6796.LanguageExchange_P960N6796() if commission_name == 'PigeonsGoAWOL_P2671N5095': import source.commission.commissions.PigeonsGoAWOL_P2671N5095 return source.commission.commissions.PigeonsGoAWOL_P2671N5095.PigeonsGoAWOL_P2671N5095() + if commission_name == 'ReliableHelper_P2966N4774': + import source.commission.commissions.ReliableHelper_P2966N4774 + return source.commission.commissions.ReliableHelper_P2966N4774.ReliableHelper_P2966N4774() if commission_name == 'TheUnnoticedGuy_P2568N5889': import source.commission.commissions.TheUnnoticedGuy_P2568N5889 return source.commission.commissions.TheUnnoticedGuy_P2568N5889.TheUnnoticedGuy_P2568N5889() + if commission_name == 'TheWannabeKnight_P2251N5771': + import source.commission.commissions.TheWannabeKnight_P2251N5771 + return source.commission.commissions.TheWannabeKnight_P2251N5771.TheWannabeKnight_P2251N5771() diff --git a/source/commission/commissions/BigPudgyProblem_P2469N4886.py b/source/commission/commissions/BigPudgyProblem_P2469N4886.py deleted file mode 100644 index b8ab4c83..00000000 --- a/source/commission/commissions/BigPudgyProblem_P2469N4886.py +++ /dev/null @@ -1,22 +0,0 @@ -from source.commission.commission import * - -class BigPudgyProblem_P2469N4886(CommissionTemplate): - def __init__(self): - CommissionTemplate.__init__(self, "BigPudgyProblem", [2469,-4886], is_CFCF=True, is_TMCF=True) - - def exec_mission(self): - self.move_along("BigPudgyProblem20230409110116i0") - self.collect(is_combat=True) - self.move_straight(["BigPudgyProblem20230409110140i1", "end_position"], is_tp=False) - self.talk_with_npc() - self.talk_skip() - self.move_along("BigPudgyProblem20230409110225i2", is_tp=True) - # self.switch_character_to("Sucrose") - # self.itt.key_press('e') - # self.collect(is_combat=True) - self.commission_succ() - -if __name__ == '__main__': - execc = BigPudgyProblem_P2469N4886() - execc.start() - \ No newline at end of file diff --git a/source/commission/commissions/BigPudgyProblem_P2526N5796.py b/source/commission/commissions/BigPudgyProblem_P2526N5796.py deleted file mode 100644 index 35d07454..00000000 --- a/source/commission/commissions/BigPudgyProblem_P2526N5796.py +++ /dev/null @@ -1,22 +0,0 @@ -from source.commission.commission import * - -class BigPudgyProblem_P2526N5796(CommissionTemplate): - def __init__(self): - CommissionTemplate.__init__(self, "BigPudgyProblem", [2526,-5796], is_CFCF=True, is_TMCF=True) - - def exec_mission(self): - self.move_along("BigPudgyProblemP2526N5796t20230405122438i0") - self.collect(is_combat=True) - self.move_straight([2609,-5950], is_tp=False) - self.talk_with_npc() - self.talk_skip() - self.move_along("BigPudgyProblemP2526N5796t20230405122622i2", is_tp=True) - self.switch_character_to("Sucrose") - self.itt.key_press('e') - self.collect(is_combat=True) - self.commission_succ() - -if __name__ == '__main__': - execc = BigPudgyProblem_P2526N5796() - execc.start() - \ No newline at end of file diff --git a/source/commission/commissions/LanguageExchange_P3060N5078.py b/source/commission/commissions/LanguageExchange_P3060N5078.py index 0fd2be9e..8bc8ec10 100644 --- a/source/commission/commissions/LanguageExchange_P3060N5078.py +++ b/source/commission/commissions/LanguageExchange_P3060N5078.py @@ -1,8 +1,8 @@ from source.commission.commission import * -class LanguageExchange_P3060N5078(CommissionTemplate): +class LanguageExchange_P3060N5078(Commission): def __init__(self): - CommissionTemplate.__init__(self, "LanguageExchange", [3060,-5078], is_CFCF=True, is_TMCF=True) + super().__init__("LanguageExchange", [3060,-5078], is_CFCF=True, is_TMCF=True) def exec_mission(self): self.move_along("LanguageExchange20230414230230i0", is_precise_arrival=True) diff --git a/source/commission/commissions/LanguageExchange_P960N6796.py b/source/commission/commissions/LanguageExchange_P960N6796.py new file mode 100644 index 00000000..bf69b33a --- /dev/null +++ b/source/commission/commissions/LanguageExchange_P960N6796.py @@ -0,0 +1,42 @@ +from source.commission.commission import * + +class LanguageExchange_P960N6796(Commission): + def __init__(self): + CommissionTemplate.__init__(self, "LanguageExchange", [960,-6796], is_CFCF=True, is_TMCF=True) + + def exec_mission(self): + self.move_along(TLPP20230622163443i0, is_precise_arrival=True) + self.talk_with_npc() + self.talk_skip() + self.talk_wait(15) + self.move_along(TLPP20230622163551i0, is_precise_arrival=True) + self.talk_with_npc() + self.talk_skip() + self.talk_wait(2) + self.move_straight([TLPP20230622163619i0,"end_position"], is_precise_arrival=False) + self.talk_with_npc() + self.talk_skip() + time.sleep(1) + self.start_combat() + while 1: + time.sleep(1) + if self.is_combat_end(): + break + self.stop_combat() + self.move_straight([TLPP20230622163710i0,"end_position"], is_precise_arrival=True) + self.talk_with_npc() + self.talk_skip() + self.commission_succ() + +if __name__ == '__main__': + execc = LanguageExchange_P960N6796() + execc.start() + + +TLPP20230622163443i0 = {'name': '', 'time': '', 'start_position': [960.1535, -6796.2503], 'break_position': [[960.154, -6796.25], [955.04, -6798.296], [936.885, -6803.666], [931.004, -6805.711], [925.634, -6807.245], [919.753, -6809.035], [914.383, -6810.57], [894.95, -6816.451], [889.325, -6817.985], [873.983, -6822.843], [867.334, -6825.144], [862.22, -6826.167], [841.253, -6823.099], [834.15616836933, -6815.975967979501], [830.769, -6822.076], [824.377, -6821.82], [816.1519188898951, -6826.476385409101], [812.87, -6838.441]], 'end_position': [812.6146000000005, -6839.974999999999], 'position_list': [{'position': [960.154, -6796.25], 'motion': 'WALKING', 'id': 1, 'special_key': None}, {'position': [959.131, -6796.506], 'motion': 'WALKING', 'id': 2, 'special_key': None}, {'position': [957.852, -6797.017], 'motion': 'WALKING', 'id': 3, 'special_key': None}, {'position': [956.829, -6797.273], 'motion': 'WALKING', 'id': 4, 'special_key': None}, {'position': [955.807, -6797.784], 'motion': 'WALKING', 'id': 5, 'special_key': None}, {'position': [954.784, -6798.296], 'motion': 'WALKING', 'id': 6, 'special_key': None}, {'position': [953.505, -6798.807], 'motion': 'WALKING', 'id': 7, 'special_key': None}, {'position': [952.227, -6799.319], 'motion': 'WALKING', 'id': 8, 'special_key': None}, {'position': [951.204, -6799.574], 'motion': 'WALKING', 'id': 9, 'special_key': None}, {'position': [949.926, -6800.086], 'motion': 'WALKING', 'id': 10, 'special_key': None}, {'position': [948.647, -6800.342], 'motion': 'WALKING', 'id': 11, 'special_key': None}, {'position': [948.391, -6800.597], 'motion': 'WALKING', 'id': 12, 'special_key': None}, {'position': [947.624, -6800.597], 'motion': 'WALKING', 'id': 13, 'special_key': None}, {'position': [947.368, -6800.597], 'motion': 'WALKING', 'id': 14, 'special_key': None}, {'position': [946.601, -6800.853], 'motion': 'WALKING', 'id': 15, 'special_key': None}, {'position': [946.346, -6800.853], 'motion': 'WALKING', 'id': 16, 'special_key': None}, {'position': [945.323, -6801.109], 'motion': 'WALKING', 'id': 17, 'special_key': None}, {'position': [945.067, -6801.109], 'motion': 'WALKING', 'id': 18, 'special_key': None}, {'position': [944.044, -6801.364], 'motion': 'WALKING', 'id': 19, 'special_key': None}, {'position': [943.533, -6801.364], 'motion': 'WALKING', 'id': 20, 'special_key': None}, {'position': [943.022, -6801.62], 'motion': 'WALKING', 'id': 21, 'special_key': None}, {'position': [942.51, -6801.62], 'motion': 'WALKING', 'id': 22, 'special_key': None}, {'position': [941.999, -6801.876], 'motion': 'WALKING', 'id': 23, 'special_key': None}, {'position': [941.487, -6802.131], 'motion': 'WALKING', 'id': 24, 'special_key': None}, {'position': [940.976, -6802.131], 'motion': 'WALKING', 'id': 25, 'special_key': None}, {'position': [940.209, -6802.387], 'motion': 'WALKING', 'id': 26, 'special_key': None}, {'position': [939.953, -6802.643], 'motion': 'WALKING', 'id': 27, 'special_key': None}, {'position': [938.93, -6802.898], 'motion': 'WALKING', 'id': 28, 'special_key': None}, {'position': [938.419, -6803.154], 'motion': 'WALKING', 'id': 29, 'special_key': None}, {'position': [937.908, -6803.154], 'motion': 'WALKING', 'id': 30, 'special_key': None}, {'position': [937.14, -6803.666], 'motion': 'WALKING', 'id': 31, 'special_key': None}, {'position': [936.885, -6803.666], 'motion': 'WALKING', 'id': 32, 'special_key': None}, {'position': [936.118, -6803.921], 'motion': 'WALKING', 'id': 33, 'special_key': None}, {'position': [935.862, -6804.177], 'motion': 'WALKING', 'id': 34, 'special_key': None}, {'position': [935.095, -6804.433], 'motion': 'WALKING', 'id': 35, 'special_key': None}, {'position': [934.839, -6804.433], 'motion': 'WALKING', 'id': 36, 'special_key': None}, {'position': [934.072, -6804.688], 'motion': 'WALKING', 'id': 37, 'special_key': None}, {'position': [933.816, -6804.688], 'motion': 'WALKING', 'id': 38, 'special_key': None}, {'position': [932.794, -6804.944], 'motion': 'WALKING', 'id': 39, 'special_key': None}, {'position': [932.538, -6805.2], 'motion': 'WALKING', 'id': 40, 'special_key': None}, {'position': [931.515, -6805.456], 'motion': 'WALKING', 'id': 41, 'special_key': None}, {'position': [931.259, -6805.456], 'motion': 'WALKING', 'id': 42, 'special_key': None}, {'position': [930.492, -6805.967], 'motion': 'WALKING', 'id': 43, 'special_key': None}, {'position': [930.237, -6805.967], 'motion': 'WALKING', 'id': 44, 'special_key': None}, {'position': [929.214, -6806.223], 'motion': 'WALKING', 'id': 45, 'special_key': None}, {'position': [928.958, -6806.223], 'motion': 'WALKING', 'id': 46, 'special_key': None}, {'position': [927.935, -6806.478], 'motion': 'WALKING', 'id': 47, 'special_key': None}, {'position': [927.424, -6806.734], 'motion': 'WALKING', 'id': 48, 'special_key': None}, {'position': [926.912, -6806.734], 'motion': 'WALKING', 'id': 49, 'special_key': None}, {'position': [926.401, -6806.99], 'motion': 'WALKING', 'id': 50, 'special_key': None}, {'position': [925.89, -6806.99], 'motion': 'WALKING', 'id': 51, 'special_key': None}, {'position': [924.867, -6807.245], 'motion': 'WALKING', 'id': 52, 'special_key': None}, {'position': [924.1, -6807.501], 'motion': 'WALKING', 'id': 53, 'special_key': None}, {'position': [922.821, -6808.012], 'motion': 'WALKING', 'id': 54, 'special_key': None}, {'position': [921.798, -6808.268], 'motion': 'WALKING', 'id': 55, 'special_key': None}, {'position': [921.031, -6808.524], 'motion': 'WALKING', 'id': 56, 'special_key': None}, {'position': [920.52, -6808.78], 'motion': 'WALKING', 'id': 57, 'special_key': None}, {'position': [919.753, -6809.035], 'motion': 'WALKING', 'id': 58, 'special_key': None}, {'position': [918.986, -6809.035], 'motion': 'WALKING', 'id': 59, 'special_key': None}, {'position': [917.963, -6809.291], 'motion': 'WALKING', 'id': 60, 'special_key': None}, {'position': [917.196, -6809.547], 'motion': 'WALKING', 'id': 61, 'special_key': None}, {'position': [916.684, -6809.802], 'motion': 'WALKING', 'id': 62, 'special_key': None}, {'position': [915.917, -6810.058], 'motion': 'WALKING', 'id': 63, 'special_key': None}, {'position': [915.662, -6810.058], 'motion': 'WALKING', 'id': 64, 'special_key': None}, {'position': [914.895, -6810.314], 'motion': 'WALKING', 'id': 65, 'special_key': None}, {'position': [914.383, -6810.57], 'motion': 'WALKING', 'id': 66, 'special_key': None}, {'position': [913.872, -6810.57], 'motion': 'WALKING', 'id': 67, 'special_key': None}, {'position': [913.36, -6810.57], 'motion': 'WALKING', 'id': 68, 'special_key': None}, {'position': [912.593, -6810.825], 'motion': 'WALKING', 'id': 69, 'special_key': None}, {'position': [912.082, -6811.081], 'motion': 'WALKING', 'id': 70, 'special_key': None}, {'position': [911.57, -6811.081], 'motion': 'WALKING', 'id': 71, 'special_key': None}, {'position': [911.059, -6811.081], 'motion': 'WALKING', 'id': 72, 'special_key': None}, {'position': [910.548, -6811.337], 'motion': 'WALKING', 'id': 73, 'special_key': None}, {'position': [910.036, -6811.337], 'motion': 'WALKING', 'id': 74, 'special_key': None}, {'position': [909.269, -6811.592], 'motion': 'WALKING', 'id': 75, 'special_key': None}, {'position': [908.758, -6811.848], 'motion': 'WALKING', 'id': 76, 'special_key': None}, {'position': [908.246, -6811.848], 'motion': 'WALKING', 'id': 77, 'special_key': None}, {'position': [907.479, -6812.104], 'motion': 'WALKING', 'id': 78, 'special_key': None}, {'position': [906.968, -6812.359], 'motion': 'WALKING', 'id': 79, 'special_key': None}, {'position': [906.201, -6812.615], 'motion': 'WALKING', 'id': 80, 'special_key': None}, {'position': [905.689, -6812.615], 'motion': 'WALKING', 'id': 81, 'special_key': None}, {'position': [905.178, -6813.126], 'motion': 'WALKING', 'id': 82, 'special_key': None}, {'position': [904.667, -6813.382], 'motion': 'WALKING', 'id': 83, 'special_key': None}, {'position': [904.155, -6813.382], 'motion': 'WALKING', 'id': 84, 'special_key': None}, {'position': [903.132, -6813.894], 'motion': 'WALKING', 'id': 85, 'special_key': None}, {'position': [902.621, -6813.894], 'motion': 'WALKING', 'id': 86, 'special_key': None}, {'position': [902.11, -6814.149], 'motion': 'WALKING', 'id': 87, 'special_key': None}, {'position': [901.598, -6814.405], 'motion': 'WALKING', 'id': 88, 'special_key': None}, {'position': [901.087, -6814.661], 'motion': 'WALKING', 'id': 89, 'special_key': None}, {'position': [900.575, -6814.916], 'motion': 'WALKING', 'id': 90, 'special_key': None}, {'position': [900.064, -6814.916], 'motion': 'WALKING', 'id': 91, 'special_key': None}, {'position': [899.297, -6815.172], 'motion': 'WALKING', 'id': 92, 'special_key': None}, {'position': [898.786, -6815.428], 'motion': 'WALKING', 'id': 93, 'special_key': None}, {'position': [898.018, -6815.684], 'motion': 'WALKING', 'id': 94, 'special_key': None}, {'position': [897.251, -6815.939], 'motion': 'WALKING', 'id': 95, 'special_key': None}, {'position': [896.74, -6815.939], 'motion': 'WALKING', 'id': 96, 'special_key': None}, {'position': [896.228, -6816.195], 'motion': 'WALKING', 'id': 97, 'special_key': None}, {'position': [895.717, -6816.195], 'motion': 'WALKING', 'id': 98, 'special_key': None}, {'position': [895.206, -6816.451], 'motion': 'WALKING', 'id': 99, 'special_key': None}, {'position': [894.694, -6816.451], 'motion': 'WALKING', 'id': 100, 'special_key': None}, {'position': [894.183, -6816.706], 'motion': 'WALKING', 'id': 101, 'special_key': None}, {'position': [893.416, -6816.962], 'motion': 'WALKING', 'id': 102, 'special_key': None}, {'position': [892.904, -6816.962], 'motion': 'WALKING', 'id': 103, 'special_key': None}, {'position': [892.137, -6817.218], 'motion': 'WALKING', 'id': 104, 'special_key': None}, {'position': [891.626, -6817.473], 'motion': 'WALKING', 'id': 105, 'special_key': None}, {'position': [891.114, -6817.473], 'motion': 'WALKING', 'id': 106, 'special_key': None}, {'position': [890.603, -6817.729], 'motion': 'WALKING', 'id': 107, 'special_key': None}, {'position': [890.092, -6817.985], 'motion': 'WALKING', 'id': 108, 'special_key': None}, {'position': [889.325, -6817.985], 'motion': 'WALKING', 'id': 109, 'special_key': None}, {'position': [889.069, -6818.24], 'motion': 'WALKING', 'id': 110, 'special_key': None}, {'position': [888.046, -6818.752], 'motion': 'WALKING', 'id': 111, 'special_key': None}, {'position': [887.79, -6818.752], 'motion': 'WALKING', 'id': 112, 'special_key': None}, {'position': [886.512, -6819.263], 'motion': 'WALKING', 'id': 113, 'special_key': None}, {'position': [886.0, -6819.519], 'motion': 'WALKING', 'id': 114, 'special_key': None}, {'position': [885.489, -6819.775], 'motion': 'WALKING', 'id': 115, 'special_key': None}, {'position': [884.466, -6820.03], 'motion': 'WALKING', 'id': 116, 'special_key': None}, {'position': [884.211, -6820.286], 'motion': 'WALKING', 'id': 117, 'special_key': None}, {'position': [882.165, -6820.798], 'motion': 'WALKING', 'id': 118, 'special_key': None}, {'position': [881.654, -6821.053], 'motion': 'WALKING', 'id': 119, 'special_key': None}, {'position': [881.142, -6821.053], 'motion': 'WALKING', 'id': 120, 'special_key': None}, {'position': [880.375, -6821.309], 'motion': 'WALKING', 'id': 121, 'special_key': None}, {'position': [879.864, -6821.309], 'motion': 'WALKING', 'id': 122, 'special_key': None}, {'position': [879.352, -6821.565], 'motion': 'WALKING', 'id': 123, 'special_key': None}, {'position': [878.841, -6821.565], 'motion': 'WALKING', 'id': 124, 'special_key': None}, {'position': [878.329, -6821.82], 'motion': 'WALKING', 'id': 125, 'special_key': None}, {'position': [877.562, -6822.076], 'motion': 'WALKING', 'id': 126, 'special_key': None}, {'position': [876.795, -6822.076], 'motion': 'WALKING', 'id': 127, 'special_key': None}, {'position': [876.284, -6822.332], 'motion': 'WALKING', 'id': 128, 'special_key': None}, {'position': [875.517, -6822.332], 'motion': 'WALKING', 'id': 129, 'special_key': None}, {'position': [875.261, -6822.332], 'motion': 'WALKING', 'id': 130, 'special_key': None}, {'position': [873.983, -6822.843], 'motion': 'WALKING', 'id': 131, 'special_key': None}, {'position': [873.727, -6823.099], 'motion': 'WALKING', 'id': 132, 'special_key': None}, {'position': [872.96, -6823.61], 'motion': 'WALKING', 'id': 133, 'special_key': None}, {'position': [872.448, -6823.61], 'motion': 'WALKING', 'id': 134, 'special_key': None}, {'position': [871.681, -6823.866], 'motion': 'WALKING', 'id': 135, 'special_key': None}, {'position': [871.17, -6823.866], 'motion': 'WALKING', 'id': 136, 'special_key': None}, {'position': [870.658, -6824.122], 'motion': 'WALKING', 'id': 137, 'special_key': None}, {'position': [870.147, -6824.122], 'motion': 'WALKING', 'id': 138, 'special_key': None}, {'position': [869.636, -6824.377], 'motion': 'WALKING', 'id': 139, 'special_key': None}, {'position': [869.124, -6824.633], 'motion': 'WALKING', 'id': 140, 'special_key': None}, {'position': [868.613, -6824.633], 'motion': 'WALKING', 'id': 141, 'special_key': None}, {'position': [867.846, -6825.144], 'motion': 'WALKING', 'id': 142, 'special_key': None}, {'position': [867.334, -6825.144], 'motion': 'WALKING', 'id': 143, 'special_key': None}, {'position': [866.823, -6825.656], 'motion': 'WALKING', 'id': 144, 'special_key': None}, {'position': [866.312, -6825.912], 'motion': 'WALKING', 'id': 145, 'special_key': None}, {'position': [865.544, -6825.912], 'motion': 'WALKING', 'id': 146, 'special_key': None}, {'position': [865.289, -6826.167], 'motion': 'WALKING', 'id': 147, 'special_key': None}, {'position': [864.266, -6826.167], 'motion': 'WALKING', 'id': 148, 'special_key': None}, {'position': [864.01, -6826.167], 'motion': 'WALKING', 'id': 149, 'special_key': None}, {'position': [863.243, -6826.167], 'motion': 'WALKING', 'id': 150, 'special_key': None}, {'position': [862.732, -6826.167], 'motion': 'WALKING', 'id': 151, 'special_key': None}, {'position': [862.22, -6826.167], 'motion': 'WALKING', 'id': 152, 'special_key': None}, {'position': [861.198, -6826.167], 'motion': 'WALKING', 'id': 153, 'special_key': None}, {'position': [860.686, -6826.167], 'motion': 'WALKING', 'id': 154, 'special_key': None}, {'position': [860.175, -6825.912], 'motion': 'WALKING', 'id': 155, 'special_key': None}, {'position': [859.663, -6825.912], 'motion': 'WALKING', 'id': 156, 'special_key': None}, {'position': [859.152, -6825.912], 'motion': 'WALKING', 'id': 157, 'special_key': None}, {'position': [858.641, -6825.656], 'motion': 'WALKING', 'id': 158, 'special_key': None}, {'position': [857.874, -6825.656], 'motion': 'WALKING', 'id': 159, 'special_key': None}, {'position': [857.618, -6825.4], 'motion': 'WALKING', 'id': 160, 'special_key': None}, {'position': [856.339, -6825.4], 'motion': 'WALKING', 'id': 161, 'special_key': None}, {'position': [855.828, -6825.144], 'motion': 'WALKING', 'id': 162, 'special_key': None}, {'position': [855.316, -6825.144], 'motion': 'WALKING', 'id': 163, 'special_key': None}, {'position': [854.805, -6825.144], 'motion': 'WALKING', 'id': 164, 'special_key': None}, {'position': [854.038, -6824.889], 'motion': 'WALKING', 'id': 165, 'special_key': None}, {'position': [853.782, -6824.889], 'motion': 'WALKING', 'id': 166, 'special_key': None}, {'position': [852.76, -6824.633], 'motion': 'WALKING', 'id': 167, 'special_key': None}, {'position': [852.248, -6824.633], 'motion': 'WALKING', 'id': 168, 'special_key': None}, {'position': [851.737, -6824.633], 'motion': 'WALKING', 'id': 169, 'special_key': None}, {'position': [850.97, -6824.633], 'motion': 'WALKING', 'id': 170, 'special_key': None}, {'position': [850.458, -6824.377], 'motion': 'WALKING', 'id': 171, 'special_key': None}, {'position': [849.691, -6824.122], 'motion': 'WALKING', 'id': 172, 'special_key': None}, {'position': [849.18, -6824.122], 'motion': 'WALKING', 'id': 173, 'special_key': None}, {'position': [848.668, -6824.122], 'motion': 'WALKING', 'id': 174, 'special_key': None}, {'position': [848.157, -6823.866], 'motion': 'WALKING', 'id': 175, 'special_key': None}, {'position': [847.39, -6823.866], 'motion': 'WALKING', 'id': 176, 'special_key': None}, {'position': [846.878, -6823.866], 'motion': 'WALKING', 'id': 177, 'special_key': None}, {'position': [846.111, -6823.866], 'motion': 'WALKING', 'id': 178, 'special_key': None}, {'position': [845.6, -6823.866], 'motion': 'WALKING', 'id': 179, 'special_key': None}, {'position': [845.088, -6823.866], 'motion': 'WALKING', 'id': 180, 'special_key': None}, {'position': [844.321, -6823.61], 'motion': 'WALKING', 'id': 181, 'special_key': None}, {'position': [844.066, -6823.61], 'motion': 'WALKING', 'id': 182, 'special_key': None}, {'position': [843.043, -6823.354], 'motion': 'WALKING', 'id': 183, 'special_key': None}, {'position': [842.787, -6823.354], 'motion': 'WALKING', 'id': 184, 'special_key': None}, {'position': [841.764, -6823.099], 'motion': 'WALKING', 'id': 185, 'special_key': None}, {'position': [841.253, -6823.099], 'motion': 'WALKING', 'id': 186, 'special_key': None}, {'position': [840.486, -6823.099], 'motion': 'WALKING', 'id': 187, 'special_key': None}, {'position': [839.974, -6822.843], 'motion': 'WALKING', 'id': 188, 'special_key': None}, {'position': [839.463, -6822.843], 'motion': 'WALKING', 'id': 189, 'special_key': None}, {'position': [838.696, -6822.843], 'motion': 'WALKING', 'id': 190, 'special_key': None}, {'position': [838.44, -6822.587], 'motion': 'WALKING', 'id': 191, 'special_key': None}, {'position': [837.418, -6822.587], 'motion': 'WALKING', 'id': 192, 'special_key': None}, {'position': [836.906, -6822.587], 'motion': 'WALKING', 'id': 193, 'special_key': None}, {'position': [836.139, -6822.332], 'motion': 'WALKING', 'id': 194, 'special_key': None}, {'position': [835.628, -6822.332], 'motion': 'WALKING', 'id': 195, 'special_key': None}, {'position': [835.116, -6822.332], 'motion': 'WALKING', 'id': 196, 'special_key': None}, {'position': [834.605, -6822.332], 'motion': 'WALKING', 'id': 197, 'special_key': None}, {'position': [834.093, -6822.332], 'motion': 'WALKING', 'id': 198, 'special_key': None}, {'position': [833.326, -6822.076], 'motion': 'WALKING', 'id': 199, 'special_key': None}, {'position': [833.071, -6822.076], 'motion': 'WALKING', 'id': 200, 'special_key': None}, {'position': [832.048, -6822.076], 'motion': 'WALKING', 'id': 201, 'special_key': None}, {'position': [831.281, -6822.076], 'motion': 'WALKING', 'id': 202, 'special_key': None}, {'position': [830.769, -6822.076], 'motion': 'WALKING', 'id': 203, 'special_key': None}, {'position': [830.002, -6822.076], 'motion': 'WALKING', 'id': 204, 'special_key': None}, {'position': [829.491, -6822.076], 'motion': 'WALKING', 'id': 205, 'special_key': None}, {'position': [828.724, -6821.82], 'motion': 'WALKING', 'id': 206, 'special_key': None}, {'position': [828.212, -6821.82], 'motion': 'WALKING', 'id': 207, 'special_key': None}, {'position': [827.445, -6821.565], 'motion': 'WALKING', 'id': 208, 'special_key': None}, {'position': [826.934, -6821.82], 'motion': 'WALKING', 'id': 209, 'special_key': None}, {'position': [826.167, -6821.82], 'motion': 'WALKING', 'id': 210, 'special_key': None}, {'position': [825.4, -6821.82], 'motion': 'WALKING', 'id': 211, 'special_key': None}, {'position': [824.888, -6821.565], 'motion': 'WALKING', 'id': 212, 'special_key': None}, {'position': [824.377, -6821.82], 'motion': 'WALKING', 'id': 213, 'special_key': None}, {'position': [823.865, -6821.82], 'motion': 'WALKING', 'id': 214, 'special_key': None}, {'position': [823.354, -6822.076], 'motion': 'WALKING', 'id': 215, 'special_key': None}, {'position': [822.587, -6822.332], 'motion': 'WALKING', 'id': 216, 'special_key': None}, {'position': [822.331, -6822.332], 'motion': 'WALKING', 'id': 217, 'special_key': None}, {'position': [821.308, -6822.843], 'motion': 'WALKING', 'id': 218, 'special_key': None}, {'position': [820.541, -6823.099], 'motion': 'WALKING', 'id': 219, 'special_key': None}, {'position': [820.03, -6823.61], 'motion': 'WALKING', 'id': 220, 'special_key': None}, {'position': [819.774, -6823.866], 'motion': 'WALKING', 'id': 221, 'special_key': None}, {'position': [819.263, -6824.633], 'motion': 'WALKING', 'id': 222, 'special_key': None}, {'position': [819.007, -6824.889], 'motion': 'WALKING', 'id': 223, 'special_key': None}, {'position': [818.496, -6825.912], 'motion': 'WALKING', 'id': 224, 'special_key': None}, {'position': [817.984, -6826.167], 'motion': 'WALKING', 'id': 225, 'special_key': None}, {'position': [817.729, -6826.934], 'motion': 'WALKING', 'id': 226, 'special_key': None}, {'position': [817.473, -6827.19], 'motion': 'WALKING', 'id': 227, 'special_key': None}, {'position': [817.217, -6827.957], 'motion': 'WALKING', 'id': 228, 'special_key': None}, {'position': [816.962, -6828.468], 'motion': 'WALKING', 'id': 229, 'special_key': None}, {'position': [816.706, -6828.98], 'motion': 'WALKING', 'id': 230, 'special_key': None}, {'position': [816.194, -6830.003], 'motion': 'WALKING', 'id': 231, 'special_key': None}, {'position': [815.939, -6830.77], 'motion': 'WALKING', 'id': 232, 'special_key': None}, {'position': [815.683, -6831.281], 'motion': 'WALKING', 'id': 233, 'special_key': None}, {'position': [815.172, -6832.048], 'motion': 'WALKING', 'id': 234, 'special_key': None}, {'position': [814.916, -6832.56], 'motion': 'WALKING', 'id': 235, 'special_key': None}, {'position': [814.66, -6833.071], 'motion': 'WALKING', 'id': 236, 'special_key': None}, {'position': [814.404, -6833.838], 'motion': 'WALKING', 'id': 237, 'special_key': None}, {'position': [814.149, -6834.605], 'motion': 'WALKING', 'id': 238, 'special_key': None}, {'position': [813.893, -6835.117], 'motion': 'WALKING', 'id': 239, 'special_key': None}, {'position': [813.893, -6835.628], 'motion': 'WALKING', 'id': 240, 'special_key': None}, {'position': [813.637, -6836.14], 'motion': 'WALKING', 'id': 241, 'special_key': None}, {'position': [813.382, -6836.651], 'motion': 'WALKING', 'id': 242, 'special_key': None}, {'position': [813.126, -6837.162], 'motion': 'WALKING', 'id': 243, 'special_key': None}, {'position': [813.126, -6837.674], 'motion': 'WALKING', 'id': 244, 'special_key': None}, {'position': [812.87, -6838.441], 'motion': 'WALKING', 'id': 245, 'special_key': None}, {'position': [812.87, -6838.696], 'motion': 'WALKING', 'id': 246, 'special_key': None}, {'position': [812.615, -6839.464], 'motion': 'WALKING', 'id': 247, 'special_key': None}, {'position': [812.615, -6839.719], 'motion': 'WALKING', 'id': 248, 'special_key': None}], 'additional_info': {'pickup_points': [17]}, 'adsorptive_position': [[834.15616836933, -6815.975967979501], [816.1519188898951, -6826.476385409101]]} + +TLPP20230622163551i0 = {'name': '', 'time': '', 'start_position': [803.9207999999991, -6836.6509], 'break_position': [[803.921, -6836.651], [793.181, -6830.258], [791.647, -6824.377], [787.045, -6806.478], [781.419, -6799.574], [776.817, -6792.926], [770.424, -6783.21], [761.219, -6770.936], [759.94, -6765.822], [754.826, -6758.151], [746.133, -6757.128], [740.252, -6756.617], [730.024, -6755.594], [718.006, -6751.758], [712.636, -6752.27], [706.243, -6751.247]], 'end_position': [705.476299999999, -6752.0142], 'position_list': [{'position': [803.921, -6836.651], 'motion': 'WALKING', 'id': 1, 'special_key': None}, {'position': [802.898, -6836.395], 'motion': 'WALKING', 'id': 2, 'special_key': None}, {'position': [802.131, -6835.628], 'motion': 'WALKING', 'id': 3, 'special_key': None}, {'position': [801.364, -6834.861], 'motion': 'WALKING', 'id': 4, 'special_key': None}, {'position': [800.085, -6834.35], 'motion': 'WALKING', 'id': 5, 'special_key': None}, {'position': [798.807, -6833.582], 'motion': 'WALKING', 'id': 6, 'special_key': None}, {'position': [798.04, -6832.815], 'motion': 'WALKING', 'id': 7, 'special_key': None}, {'position': [797.017, -6832.304], 'motion': 'WALKING', 'id': 8, 'special_key': None}, {'position': [795.994, -6831.793], 'motion': 'WALKING', 'id': 9, 'special_key': None}, {'position': [794.971, -6831.537], 'motion': 'WALKING', 'id': 10, 'special_key': None}, {'position': [793.693, -6831.026], 'motion': 'WALKING', 'id': 11, 'special_key': None}, {'position': [793.437, -6830.514], 'motion': 'WALKING', 'id': 12, 'special_key': None}, {'position': [792.926, -6829.747], 'motion': 'WALKING', 'id': 13, 'special_key': None}, {'position': [792.926, -6829.491], 'motion': 'WALKING', 'id': 14, 'special_key': None}, {'position': [792.926, -6828.724], 'motion': 'WALKING', 'id': 15, 'special_key': None}, {'position': [792.67, -6828.213], 'motion': 'WALKING', 'id': 16, 'special_key': None}, {'position': [792.159, -6827.446], 'motion': 'WALKING', 'id': 17, 'special_key': None}, {'position': [791.903, -6827.19], 'motion': 'WALKING', 'id': 18, 'special_key': None}, {'position': [791.903, -6826.423], 'motion': 'WALKING', 'id': 19, 'special_key': None}, {'position': [791.903, -6826.167], 'motion': 'WALKING', 'id': 20, 'special_key': None}, {'position': [791.903, -6825.4], 'motion': 'WALKING', 'id': 21, 'special_key': None}, {'position': [791.903, -6824.889], 'motion': 'WALKING', 'id': 22, 'special_key': None}, {'position': [791.647, -6824.377], 'motion': 'WALKING', 'id': 23, 'special_key': None}, {'position': [791.647, -6823.866], 'motion': 'WALKING', 'id': 24, 'special_key': None}, {'position': [791.647, -6823.099], 'motion': 'WALKING', 'id': 25, 'special_key': None}, {'position': [791.647, -6822.843], 'motion': 'WALKING', 'id': 26, 'special_key': None}, {'position': [791.392, -6822.076], 'motion': 'WALKING', 'id': 27, 'special_key': None}, {'position': [791.392, -6821.82], 'motion': 'WALKING', 'id': 28, 'special_key': None}, {'position': [791.392, -6820.798], 'motion': 'WALKING', 'id': 29, 'special_key': None}, {'position': [791.136, -6820.542], 'motion': 'WALKING', 'id': 30, 'special_key': None}, {'position': [790.88, -6819.775], 'motion': 'WALKING', 'id': 31, 'special_key': None}, {'position': [790.88, -6819.263], 'motion': 'WALKING', 'id': 32, 'special_key': None}, {'position': [790.88, -6818.752], 'motion': 'WALKING', 'id': 33, 'special_key': None}, {'position': [790.624, -6818.24], 'motion': 'WALKING', 'id': 34, 'special_key': None}, {'position': [790.624, -6817.729], 'motion': 'WALKING', 'id': 35, 'special_key': None}, {'position': [790.624, -6817.218], 'motion': 'WALKING', 'id': 36, 'special_key': None}, {'position': [790.624, -6816.706], 'motion': 'WALKING', 'id': 37, 'special_key': None}, {'position': [790.369, -6816.195], 'motion': 'WALKING', 'id': 38, 'special_key': None}, {'position': [789.857, -6815.684], 'motion': 'WALKING', 'id': 39, 'special_key': None}, {'position': [789.857, -6815.172], 'motion': 'WALKING', 'id': 40, 'special_key': None}, {'position': [789.602, -6814.405], 'motion': 'WALKING', 'id': 41, 'special_key': None}, {'position': [789.602, -6813.894], 'motion': 'WALKING', 'id': 42, 'special_key': None}, {'position': [789.346, -6813.126], 'motion': 'WALKING', 'id': 43, 'special_key': None}, {'position': [789.09, -6812.615], 'motion': 'WALKING', 'id': 44, 'special_key': None}, {'position': [788.834, -6811.848], 'motion': 'WALKING', 'id': 45, 'special_key': None}, {'position': [788.579, -6811.592], 'motion': 'WALKING', 'id': 46, 'special_key': None}, {'position': [788.067, -6810.825], 'motion': 'WALKING', 'id': 47, 'special_key': None}, {'position': [787.812, -6810.57], 'motion': 'WALKING', 'id': 48, 'special_key': None}, {'position': [787.3, -6809.802], 'motion': 'WALKING', 'id': 49, 'special_key': None}, {'position': [787.3, -6809.547], 'motion': 'WALKING', 'id': 50, 'special_key': None}, {'position': [787.3, -6808.78], 'motion': 'WALKING', 'id': 51, 'special_key': None}, {'position': [787.3, -6808.268], 'motion': 'WALKING', 'id': 52, 'special_key': None}, {'position': [787.3, -6807.757], 'motion': 'WALKING', 'id': 53, 'special_key': None}, {'position': [787.3, -6807.245], 'motion': 'WALKING', 'id': 54, 'special_key': None}, {'position': [787.045, -6806.478], 'motion': 'WALKING', 'id': 55, 'special_key': None}, {'position': [786.789, -6806.223], 'motion': 'WALKING', 'id': 56, 'special_key': None}, {'position': [786.789, -6805.456], 'motion': 'WALKING', 'id': 57, 'special_key': None}, {'position': [786.533, -6805.2], 'motion': 'WALKING', 'id': 58, 'special_key': None}, {'position': [786.278, -6804.433], 'motion': 'WALKING', 'id': 59, 'special_key': None}, {'position': [786.278, -6804.177], 'motion': 'WALKING', 'id': 60, 'special_key': None}, {'position': [786.022, -6803.41], 'motion': 'WALKING', 'id': 61, 'special_key': None}, {'position': [785.255, -6803.154], 'motion': 'WALKING', 'id': 62, 'special_key': None}, {'position': [784.999, -6802.643], 'motion': 'WALKING', 'id': 63, 'special_key': None}, {'position': [784.743, -6802.131], 'motion': 'WALKING', 'id': 64, 'special_key': None}, {'position': [784.232, -6801.876], 'motion': 'WALKING', 'id': 65, 'special_key': None}, {'position': [783.72, -6801.364], 'motion': 'WALKING', 'id': 66, 'special_key': None}, {'position': [783.209, -6801.364], 'motion': 'WALKING', 'id': 67, 'special_key': None}, {'position': [782.698, -6801.109], 'motion': 'WALKING', 'id': 68, 'special_key': None}, {'position': [782.186, -6800.853], 'motion': 'WALKING', 'id': 69, 'special_key': None}, {'position': [781.675, -6800.342], 'motion': 'WALKING', 'id': 70, 'special_key': None}, {'position': [781.675, -6799.83], 'motion': 'WALKING', 'id': 71, 'special_key': None}, {'position': [781.419, -6799.319], 'motion': 'WALKING', 'id': 72, 'special_key': None}, {'position': [780.908, -6799.063], 'motion': 'WALKING', 'id': 73, 'special_key': None}, {'position': [780.652, -6798.04], 'motion': 'WALKING', 'id': 74, 'special_key': None}, {'position': [780.652, -6797.529], 'motion': 'WALKING', 'id': 75, 'special_key': None}, {'position': [780.141, -6797.017], 'motion': 'WALKING', 'id': 76, 'special_key': None}, {'position': [779.885, -6796.506], 'motion': 'WALKING', 'id': 77, 'special_key': None}, {'position': [779.629, -6795.739], 'motion': 'WALKING', 'id': 78, 'special_key': None}, {'position': [779.118, -6795.483], 'motion': 'WALKING', 'id': 79, 'special_key': None}, {'position': [778.351, -6794.972], 'motion': 'WALKING', 'id': 80, 'special_key': None}, {'position': [778.351, -6794.716], 'motion': 'WALKING', 'id': 81, 'special_key': None}, {'position': [777.584, -6793.949], 'motion': 'WALKING', 'id': 82, 'special_key': None}, {'position': [777.328, -6793.693], 'motion': 'WALKING', 'id': 83, 'special_key': None}, {'position': [776.817, -6792.926], 'motion': 'WALKING', 'id': 84, 'special_key': None}, {'position': [776.817, -6792.67], 'motion': 'WALKING', 'id': 85, 'special_key': None}, {'position': [776.561, -6791.648], 'motion': 'WALKING', 'id': 86, 'special_key': None}, {'position': [776.305, -6791.392], 'motion': 'WALKING', 'id': 87, 'special_key': None}, {'position': [776.05, -6790.625], 'motion': 'WALKING', 'id': 88, 'special_key': None}, {'position': [775.794, -6790.369], 'motion': 'WALKING', 'id': 89, 'special_key': None}, {'position': [775.282, -6789.858], 'motion': 'WALKING', 'id': 90, 'special_key': None}, {'position': [775.027, -6789.602], 'motion': 'WALKING', 'id': 91, 'special_key': None}, {'position': [774.771, -6788.835], 'motion': 'WALKING', 'id': 92, 'special_key': None}, {'position': [774.26, -6788.835], 'motion': 'WALKING', 'id': 93, 'special_key': None}, {'position': [773.748, -6788.579], 'motion': 'WALKING', 'id': 94, 'special_key': None}, {'position': [773.492, -6788.068], 'motion': 'WALKING', 'id': 95, 'special_key': None}, {'position': [772.981, -6787.812], 'motion': 'WALKING', 'id': 96, 'special_key': None}, {'position': [772.47, -6787.045], 'motion': 'WALKING', 'id': 97, 'special_key': None}, {'position': [772.214, -6786.789], 'motion': 'WALKING', 'id': 98, 'special_key': None}, {'position': [771.703, -6786.022], 'motion': 'WALKING', 'id': 99, 'special_key': None}, {'position': [771.703, -6785.767], 'motion': 'WALKING', 'id': 100, 'special_key': None}, {'position': [771.447, -6785.0], 'motion': 'WALKING', 'id': 101, 'special_key': None}, {'position': [771.191, -6784.744], 'motion': 'WALKING', 'id': 102, 'special_key': None}, {'position': [770.68, -6783.721], 'motion': 'WALKING', 'id': 103, 'special_key': None}, {'position': [770.68, -6783.465], 'motion': 'WALKING', 'id': 104, 'special_key': None}, {'position': [770.424, -6782.698], 'motion': 'WALKING', 'id': 105, 'special_key': None}, {'position': [770.168, -6782.442], 'motion': 'WALKING', 'id': 106, 'special_key': None}, {'position': [769.657, -6781.675], 'motion': 'WALKING', 'id': 107, 'special_key': None}, {'position': [769.657, -6781.42], 'motion': 'WALKING', 'id': 108, 'special_key': None}, {'position': [768.89, -6780.653], 'motion': 'WALKING', 'id': 109, 'special_key': None}, {'position': [768.634, -6780.397], 'motion': 'WALKING', 'id': 110, 'special_key': None}, {'position': [767.867, -6780.141], 'motion': 'WALKING', 'id': 111, 'special_key': None}, {'position': [767.611, -6779.885], 'motion': 'WALKING', 'id': 112, 'special_key': None}, {'position': [767.1, -6779.374], 'motion': 'WALKING', 'id': 113, 'special_key': None}, {'position': [766.844, -6778.863], 'motion': 'WALKING', 'id': 114, 'special_key': None}, {'position': [766.589, -6778.096], 'motion': 'WALKING', 'id': 115, 'special_key': None}, {'position': [766.333, -6777.84], 'motion': 'WALKING', 'id': 116, 'special_key': None}, {'position': [766.077, -6777.073], 'motion': 'WALKING', 'id': 117, 'special_key': None}, {'position': [766.077, -6776.817], 'motion': 'WALKING', 'id': 118, 'special_key': None}, {'position': [765.566, -6776.05], 'motion': 'WALKING', 'id': 119, 'special_key': None}, {'position': [765.566, -6775.794], 'motion': 'WALKING', 'id': 120, 'special_key': None}, {'position': [765.054, -6775.027], 'motion': 'WALKING', 'id': 121, 'special_key': None}, {'position': [765.054, -6774.772], 'motion': 'WALKING', 'id': 122, 'special_key': None}, {'position': [764.287, -6774.26], 'motion': 'WALKING', 'id': 123, 'special_key': None}, {'position': [764.032, -6774.26], 'motion': 'WALKING', 'id': 124, 'special_key': None}, {'position': [763.264, -6773.493], 'motion': 'WALKING', 'id': 125, 'special_key': None}, {'position': [763.009, -6773.493], 'motion': 'WALKING', 'id': 126, 'special_key': None}, {'position': [762.242, -6772.726], 'motion': 'WALKING', 'id': 127, 'special_key': None}, {'position': [761.986, -6772.47], 'motion': 'WALKING', 'id': 128, 'special_key': None}, {'position': [761.475, -6771.703], 'motion': 'WALKING', 'id': 129, 'special_key': None}, {'position': [761.475, -6771.447], 'motion': 'WALKING', 'id': 130, 'special_key': None}, {'position': [761.219, -6770.68], 'motion': 'WALKING', 'id': 131, 'special_key': None}, {'position': [760.963, -6770.425], 'motion': 'WALKING', 'id': 132, 'special_key': None}, {'position': [760.708, -6769.658], 'motion': 'WALKING', 'id': 133, 'special_key': None}, {'position': [760.452, -6769.402], 'motion': 'WALKING', 'id': 134, 'special_key': None}, {'position': [759.94, -6768.635], 'motion': 'WALKING', 'id': 135, 'special_key': None}, {'position': [759.94, -6768.379], 'motion': 'WALKING', 'id': 136, 'special_key': None}, {'position': [759.94, -6767.612], 'motion': 'WALKING', 'id': 137, 'special_key': None}, {'position': [759.94, -6767.1], 'motion': 'WALKING', 'id': 138, 'special_key': None}, {'position': [759.94, -6766.589], 'motion': 'WALKING', 'id': 139, 'special_key': None}, {'position': [759.94, -6766.078], 'motion': 'WALKING', 'id': 140, 'special_key': None}, {'position': [759.94, -6765.566], 'motion': 'WALKING', 'id': 141, 'special_key': None}, {'position': [759.94, -6765.055], 'motion': 'WALKING', 'id': 142, 'special_key': None}, {'position': [759.429, -6764.544], 'motion': 'WALKING', 'id': 143, 'special_key': None}, {'position': [759.173, -6764.288], 'motion': 'WALKING', 'id': 144, 'special_key': None}, {'position': [758.15, -6763.776], 'motion': 'WALKING', 'id': 145, 'special_key': None}, {'position': [757.895, -6763.521], 'motion': 'WALKING', 'id': 146, 'special_key': None}, {'position': [757.128, -6763.009], 'motion': 'WALKING', 'id': 147, 'special_key': None}, {'position': [756.872, -6762.754], 'motion': 'WALKING', 'id': 148, 'special_key': None}, {'position': [756.361, -6761.731], 'motion': 'WALKING', 'id': 149, 'special_key': None}, {'position': [756.105, -6761.475], 'motion': 'WALKING', 'id': 150, 'special_key': None}, {'position': [756.105, -6760.708], 'motion': 'WALKING', 'id': 151, 'special_key': None}, {'position': [756.105, -6760.452], 'motion': 'WALKING', 'id': 152, 'special_key': None}, {'position': [755.849, -6759.685], 'motion': 'WALKING', 'id': 153, 'special_key': None}, {'position': [755.594, -6759.43], 'motion': 'WALKING', 'id': 154, 'special_key': None}, {'position': [755.082, -6758.662], 'motion': 'WALKING', 'id': 155, 'special_key': None}, {'position': [755.082, -6758.407], 'motion': 'WALKING', 'id': 156, 'special_key': None}, {'position': [754.315, -6757.64], 'motion': 'WALKING', 'id': 157, 'special_key': None}, {'position': [754.315, -6757.64], 'motion': 'WALKING', 'id': 158, 'special_key': None}, {'position': [753.036, -6757.64], 'motion': 'WALKING', 'id': 159, 'special_key': None}, {'position': [752.525, -6757.64], 'motion': 'WALKING', 'id': 160, 'special_key': None}, {'position': [752.014, -6757.64], 'motion': 'WALKING', 'id': 161, 'special_key': None}, {'position': [751.502, -6757.64], 'motion': 'WALKING', 'id': 162, 'special_key': None}, {'position': [750.991, -6757.64], 'motion': 'WALKING', 'id': 163, 'special_key': None}, {'position': [750.48, -6757.384], 'motion': 'WALKING', 'id': 164, 'special_key': None}, {'position': [749.968, -6757.384], 'motion': 'WALKING', 'id': 165, 'special_key': None}, {'position': [749.457, -6757.384], 'motion': 'WALKING', 'id': 166, 'special_key': None}, {'position': [748.945, -6757.128], 'motion': 'WALKING', 'id': 167, 'special_key': None}, {'position': [748.434, -6757.128], 'motion': 'WALKING', 'id': 168, 'special_key': None}, {'position': [747.922, -6757.128], 'motion': 'WALKING', 'id': 169, 'special_key': None}, {'position': [747.411, -6757.128], 'motion': 'WALKING', 'id': 170, 'special_key': None}, {'position': [746.644, -6757.128], 'motion': 'WALKING', 'id': 171, 'special_key': None}, {'position': [746.133, -6757.128], 'motion': 'WALKING', 'id': 172, 'special_key': None}, {'position': [745.621, -6756.872], 'motion': 'WALKING', 'id': 173, 'special_key': None}, {'position': [745.11, -6756.872], 'motion': 'WALKING', 'id': 174, 'special_key': None}, {'position': [744.343, -6756.872], 'motion': 'WALKING', 'id': 175, 'special_key': None}, {'position': [744.087, -6756.872], 'motion': 'WALKING', 'id': 176, 'special_key': None}, {'position': [743.064, -6756.872], 'motion': 'WALKING', 'id': 177, 'special_key': None}, {'position': [742.553, -6756.872], 'motion': 'WALKING', 'id': 178, 'special_key': None}, {'position': [742.041, -6756.872], 'motion': 'WALKING', 'id': 179, 'special_key': None}, {'position': [741.53, -6756.872], 'motion': 'WALKING', 'id': 180, 'special_key': None}, {'position': [741.019, -6756.872], 'motion': 'WALKING', 'id': 181, 'special_key': None}, {'position': [740.507, -6756.872], 'motion': 'WALKING', 'id': 182, 'special_key': None}, {'position': [739.996, -6756.617], 'motion': 'WALKING', 'id': 183, 'special_key': None}, {'position': [739.484, -6756.617], 'motion': 'WALKING', 'id': 184, 'special_key': None}, {'position': [738.973, -6756.617], 'motion': 'WALKING', 'id': 185, 'special_key': None}, {'position': [738.206, -6756.617], 'motion': 'WALKING', 'id': 186, 'special_key': None}, {'position': [737.694, -6756.617], 'motion': 'WALKING', 'id': 187, 'special_key': None}, {'position': [737.183, -6756.617], 'motion': 'WALKING', 'id': 188, 'special_key': None}, {'position': [736.672, -6756.361], 'motion': 'WALKING', 'id': 189, 'special_key': None}, {'position': [736.16, -6756.361], 'motion': 'WALKING', 'id': 190, 'special_key': None}, {'position': [735.649, -6756.361], 'motion': 'WALKING', 'id': 191, 'special_key': None}, {'position': [735.137, -6756.105], 'motion': 'WALKING', 'id': 192, 'special_key': None}, {'position': [734.626, -6756.105], 'motion': 'WALKING', 'id': 193, 'special_key': None}, {'position': [733.859, -6756.105], 'motion': 'WALKING', 'id': 194, 'special_key': None}, {'position': [733.348, -6756.105], 'motion': 'WALKING', 'id': 195, 'special_key': None}, {'position': [732.836, -6756.105], 'motion': 'WALKING', 'id': 196, 'special_key': None}, {'position': [732.069, -6756.105], 'motion': 'WALKING', 'id': 197, 'special_key': None}, {'position': [731.558, -6756.105], 'motion': 'WALKING', 'id': 198, 'special_key': None}, {'position': [731.046, -6755.85], 'motion': 'WALKING', 'id': 199, 'special_key': None}, {'position': [730.535, -6755.594], 'motion': 'WALKING', 'id': 200, 'special_key': None}, {'position': [730.024, -6755.594], 'motion': 'WALKING', 'id': 201, 'special_key': None}, {'position': [729.512, -6755.338], 'motion': 'WALKING', 'id': 202, 'special_key': None}, {'position': [728.745, -6755.083], 'motion': 'WALKING', 'id': 203, 'special_key': None}, {'position': [728.489, -6754.827], 'motion': 'WALKING', 'id': 204, 'special_key': None}, {'position': [727.466, -6754.316], 'motion': 'WALKING', 'id': 205, 'special_key': None}, {'position': [727.211, -6754.316], 'motion': 'WALKING', 'id': 206, 'special_key': None}, {'position': [726.444, -6754.06], 'motion': 'WALKING', 'id': 207, 'special_key': None}, {'position': [726.188, -6754.06], 'motion': 'WALKING', 'id': 208, 'special_key': None}, {'position': [725.421, -6753.804], 'motion': 'WALKING', 'id': 209, 'special_key': None}, {'position': [725.165, -6753.804], 'motion': 'WALKING', 'id': 210, 'special_key': None}, {'position': [724.398, -6753.548], 'motion': 'WALKING', 'id': 211, 'special_key': None}, {'position': [724.142, -6753.548], 'motion': 'WALKING', 'id': 212, 'special_key': None}, {'position': [723.375, -6753.293], 'motion': 'WALKING', 'id': 213, 'special_key': None}, {'position': [722.864, -6753.293], 'motion': 'WALKING', 'id': 214, 'special_key': None}, {'position': [722.352, -6753.293], 'motion': 'WALKING', 'id': 215, 'special_key': None}, {'position': [721.585, -6753.037], 'motion': 'WALKING', 'id': 216, 'special_key': None}, {'position': [721.33, -6753.037], 'motion': 'WALKING', 'id': 217, 'special_key': None}, {'position': [720.563, -6752.781], 'motion': 'WALKING', 'id': 218, 'special_key': None}, {'position': [720.307, -6752.781], 'motion': 'WALKING', 'id': 219, 'special_key': None}, {'position': [719.284, -6752.526], 'motion': 'WALKING', 'id': 220, 'special_key': None}, {'position': [719.028, -6752.27], 'motion': 'WALKING', 'id': 221, 'special_key': None}, {'position': [718.261, -6751.758], 'motion': 'WALKING', 'id': 222, 'special_key': None}, {'position': [718.006, -6751.758], 'motion': 'WALKING', 'id': 223, 'special_key': None}, {'position': [717.238, -6752.014], 'motion': 'WALKING', 'id': 224, 'special_key': None}, {'position': [716.983, -6752.27], 'motion': 'WALKING', 'id': 225, 'special_key': None}, {'position': [716.216, -6752.27], 'motion': 'WALKING', 'id': 226, 'special_key': None}, {'position': [715.96, -6752.27], 'motion': 'WALKING', 'id': 227, 'special_key': None}, {'position': [715.193, -6752.27], 'motion': 'WALKING', 'id': 228, 'special_key': None}, {'position': [714.937, -6752.27], 'motion': 'WALKING', 'id': 229, 'special_key': None}, {'position': [713.914, -6752.27], 'motion': 'WALKING', 'id': 230, 'special_key': None}, {'position': [713.403, -6752.27], 'motion': 'WALKING', 'id': 231, 'special_key': None}, {'position': [712.636, -6752.27], 'motion': 'WALKING', 'id': 232, 'special_key': None}, {'position': [712.38, -6752.27], 'motion': 'WALKING', 'id': 233, 'special_key': None}, {'position': [711.613, -6752.27], 'motion': 'WALKING', 'id': 234, 'special_key': None}, {'position': [711.357, -6752.014], 'motion': 'WALKING', 'id': 235, 'special_key': None}, {'position': [710.59, -6752.014], 'motion': 'WALKING', 'id': 236, 'special_key': None}, {'position': [710.335, -6752.014], 'motion': 'WALKING', 'id': 237, 'special_key': None}, {'position': [709.568, -6751.758], 'motion': 'WALKING', 'id': 238, 'special_key': None}, {'position': [709.312, -6751.758], 'motion': 'WALKING', 'id': 239, 'special_key': None}, {'position': [708.545, -6751.758], 'motion': 'WALKING', 'id': 240, 'special_key': None}, {'position': [706.243, -6751.247], 'motion': 'WALKING', 'id': 241, 'special_key': None}, {'position': [706.243, -6751.247], 'motion': 'WALKING', 'id': 242, 'special_key': None}, {'position': [705.476, -6752.014], 'motion': 'WALKING', 'id': 243, 'special_key': None}, {'position': [705.476, -6752.014], 'motion': 'WALKING', 'id': 244, 'special_key': None}], 'additional_info': {'pickup_points': [15]}, 'adsorptive_position': []} + +TLPP20230622163619i0 = {'name': '', 'time': '', 'start_position': [703.4307000000009, -6752.5256], 'break_position': [[703.431, -6752.526], [649.989, -6764.032]], 'end_position': [649.2222999999991, -6763.0093], 'position_list': [{'position': [703.431, -6752.526], 'motion': 'WALKING', 'id': 1, 'special_key': None}, {'position': [702.408, -6752.526], 'motion': 'WALKING', 'id': 2, 'special_key': None}, {'position': [701.385, -6752.781], 'motion': 'WALKING', 'id': 3, 'special_key': None}, {'position': [700.362, -6753.037], 'motion': 'WALKING', 'id': 4, 'special_key': None}, {'position': [699.339, -6753.293], 'motion': 'WALKING', 'id': 5, 'special_key': None}, {'position': [698.061, -6753.548], 'motion': 'WALKING', 'id': 6, 'special_key': None}, {'position': [697.038, -6753.548], 'motion': 'WALKING', 'id': 7, 'special_key': None}, {'position': [696.015, -6753.804], 'motion': 'WALKING', 'id': 8, 'special_key': None}, {'position': [694.993, -6753.804], 'motion': 'WALKING', 'id': 9, 'special_key': None}, {'position': [693.97, -6754.06], 'motion': 'WALKING', 'id': 10, 'special_key': None}, {'position': [692.947, -6754.06], 'motion': 'WALKING', 'id': 11, 'special_key': None}, {'position': [692.436, -6754.06], 'motion': 'WALKING', 'id': 12, 'special_key': None}, {'position': [691.924, -6754.06], 'motion': 'WALKING', 'id': 13, 'special_key': None}, {'position': [691.157, -6754.316], 'motion': 'WALKING', 'id': 14, 'special_key': None}, {'position': [690.901, -6754.316], 'motion': 'WALKING', 'id': 15, 'special_key': None}, {'position': [690.134, -6754.571], 'motion': 'WALKING', 'id': 16, 'special_key': None}, {'position': [689.879, -6754.827], 'motion': 'WALKING', 'id': 17, 'special_key': None}, {'position': [689.112, -6755.083], 'motion': 'WALKING', 'id': 18, 'special_key': None}, {'position': [688.6, -6755.083], 'motion': 'WALKING', 'id': 19, 'special_key': None}, {'position': [687.833, -6755.594], 'motion': 'WALKING', 'id': 20, 'special_key': None}, {'position': [687.322, -6755.594], 'motion': 'WALKING', 'id': 21, 'special_key': None}, {'position': [686.81, -6755.85], 'motion': 'WALKING', 'id': 22, 'special_key': None}, {'position': [686.299, -6755.85], 'motion': 'WALKING', 'id': 23, 'special_key': None}, {'position': [685.532, -6756.105], 'motion': 'WALKING', 'id': 24, 'special_key': None}, {'position': [685.276, -6756.105], 'motion': 'WALKING', 'id': 25, 'special_key': None}, {'position': [684.509, -6756.617], 'motion': 'WALKING', 'id': 26, 'special_key': None}, {'position': [684.253, -6756.617], 'motion': 'WALKING', 'id': 27, 'special_key': None}, {'position': [683.486, -6756.872], 'motion': 'WALKING', 'id': 28, 'special_key': None}, {'position': [683.23, -6756.872], 'motion': 'WALKING', 'id': 29, 'special_key': None}, {'position': [682.208, -6757.128], 'motion': 'WALKING', 'id': 30, 'special_key': None}, {'position': [681.696, -6757.128], 'motion': 'WALKING', 'id': 31, 'special_key': None}, {'position': [681.185, -6757.384], 'motion': 'WALKING', 'id': 32, 'special_key': None}, {'position': [680.418, -6757.64], 'motion': 'WALKING', 'id': 33, 'special_key': None}, {'position': [680.162, -6757.64], 'motion': 'WALKING', 'id': 34, 'special_key': None}, {'position': [679.395, -6757.895], 'motion': 'WALKING', 'id': 35, 'special_key': None}, {'position': [679.139, -6758.151], 'motion': 'WALKING', 'id': 36, 'special_key': None}, {'position': [678.116, -6758.151], 'motion': 'WALKING', 'id': 37, 'special_key': None}, {'position': [677.605, -6758.151], 'motion': 'WALKING', 'id': 38, 'special_key': None}, {'position': [677.094, -6758.407], 'motion': 'WALKING', 'id': 39, 'special_key': None}, {'position': [676.582, -6758.407], 'motion': 'WALKING', 'id': 40, 'special_key': None}, {'position': [676.071, -6758.407], 'motion': 'WALKING', 'id': 41, 'special_key': None}, {'position': [675.304, -6758.662], 'motion': 'WALKING', 'id': 42, 'special_key': None}, {'position': [675.048, -6758.662], 'motion': 'WALKING', 'id': 43, 'special_key': None}, {'position': [674.281, -6758.918], 'motion': 'WALKING', 'id': 44, 'special_key': None}, {'position': [674.025, -6758.918], 'motion': 'WALKING', 'id': 45, 'special_key': None}, {'position': [673.258, -6758.918], 'motion': 'WALKING', 'id': 46, 'special_key': None}, {'position': [673.002, -6758.918], 'motion': 'WALKING', 'id': 47, 'special_key': None}, {'position': [671.98, -6758.918], 'motion': 'WALKING', 'id': 48, 'special_key': None}, {'position': [671.468, -6758.918], 'motion': 'WALKING', 'id': 49, 'special_key': None}, {'position': [670.701, -6759.174], 'motion': 'WALKING', 'id': 50, 'special_key': None}, {'position': [670.19, -6759.174], 'motion': 'WALKING', 'id': 51, 'special_key': None}, {'position': [669.678, -6759.43], 'motion': 'WALKING', 'id': 52, 'special_key': None}, {'position': [669.167, -6759.43], 'motion': 'WALKING', 'id': 53, 'special_key': None}, {'position': [668.656, -6759.685], 'motion': 'WALKING', 'id': 54, 'special_key': None}, {'position': [668.144, -6759.685], 'motion': 'WALKING', 'id': 55, 'special_key': None}, {'position': [667.377, -6759.941], 'motion': 'WALKING', 'id': 56, 'special_key': None}, {'position': [666.866, -6760.197], 'motion': 'WALKING', 'id': 57, 'special_key': None}, {'position': [666.098, -6760.197], 'motion': 'WALKING', 'id': 58, 'special_key': None}, {'position': [665.587, -6760.197], 'motion': 'WALKING', 'id': 59, 'special_key': None}, {'position': [665.076, -6760.452], 'motion': 'WALKING', 'id': 60, 'special_key': None}, {'position': [664.564, -6760.452], 'motion': 'WALKING', 'id': 61, 'special_key': None}, {'position': [664.053, -6760.708], 'motion': 'WALKING', 'id': 62, 'special_key': None}, {'position': [663.541, -6760.964], 'motion': 'WALKING', 'id': 63, 'special_key': None}, {'position': [662.774, -6761.219], 'motion': 'WALKING', 'id': 64, 'special_key': None}, {'position': [662.519, -6761.475], 'motion': 'WALKING', 'id': 65, 'special_key': None}, {'position': [661.496, -6761.475], 'motion': 'WALKING', 'id': 66, 'special_key': None}, {'position': [661.24, -6761.475], 'motion': 'WALKING', 'id': 67, 'special_key': None}, {'position': [660.473, -6761.731], 'motion': 'WALKING', 'id': 68, 'special_key': None}, {'position': [660.217, -6761.986], 'motion': 'WALKING', 'id': 69, 'special_key': None}, {'position': [659.45, -6762.242], 'motion': 'WALKING', 'id': 70, 'special_key': None}, {'position': [658.939, -6762.498], 'motion': 'WALKING', 'id': 71, 'special_key': None}, {'position': [658.428, -6762.754], 'motion': 'WALKING', 'id': 72, 'special_key': None}, {'position': [657.916, -6762.754], 'motion': 'WALKING', 'id': 73, 'special_key': None}, {'position': [657.405, -6762.754], 'motion': 'WALKING', 'id': 74, 'special_key': None}, {'position': [656.893, -6762.754], 'motion': 'WALKING', 'id': 75, 'special_key': None}, {'position': [656.382, -6763.009], 'motion': 'WALKING', 'id': 76, 'special_key': None}, {'position': [655.103, -6763.265], 'motion': 'WALKING', 'id': 77, 'special_key': None}, {'position': [654.848, -6763.265], 'motion': 'WALKING', 'id': 78, 'special_key': None}, {'position': [654.081, -6763.521], 'motion': 'WALKING', 'id': 79, 'special_key': None}, {'position': [653.825, -6763.521], 'motion': 'WALKING', 'id': 80, 'special_key': None}, {'position': [653.058, -6763.776], 'motion': 'WALKING', 'id': 81, 'special_key': None}, {'position': [652.802, -6763.776], 'motion': 'WALKING', 'id': 82, 'special_key': None}, {'position': [651.779, -6763.776], 'motion': 'WALKING', 'id': 83, 'special_key': None}, {'position': [651.268, -6763.776], 'motion': 'WALKING', 'id': 84, 'special_key': None}, {'position': [650.756, -6763.776], 'motion': 'WALKING', 'id': 85, 'special_key': None}, {'position': [649.989, -6764.032], 'motion': 'WALKING', 'id': 86, 'special_key': None}, {'position': [649.734, -6764.032], 'motion': 'WALKING', 'id': 87, 'special_key': None}, {'position': [649.222, -6763.265], 'motion': 'WALKING', 'id': 88, 'special_key': None}, {'position': [649.222, -6763.009], 'motion': 'WALKING', 'id': 89, 'special_key': None}], 'additional_info': {'pickup_points': [1]}, 'adsorptive_position': []} + +TLPP20230622163710i0 = {'name': '', 'time': '', 'start_position': [600.3836000000005, -6789.6021], 'break_position': [[600.384, -6789.602], [607.543, -6792.415], [612.913, -6793.182], [624.164, -6789.346], [627.999, -6784.232], [632.346, -6774.772], [635.926, -6766.078], [641.551, -6758.151], [646.665, -6757.128], [649.478, -6762.498]], 'end_position': [649.7337000000009, -6762.497899999999], 'position_list': [{'position': [600.384, -6789.602], 'motion': 'WALKING', 'id': 1, 'special_key': None}, {'position': [602.174, -6790.113], 'motion': 'WALKING', 'id': 2, 'special_key': None}, {'position': [603.452, -6790.369], 'motion': 'WALKING', 'id': 3, 'special_key': None}, {'position': [604.986, -6790.881], 'motion': 'WALKING', 'id': 4, 'special_key': None}, {'position': [607.288, -6791.903], 'motion': 'WALKING', 'id': 5, 'special_key': None}, {'position': [608.566, -6792.926], 'motion': 'WALKING', 'id': 6, 'special_key': None}, {'position': [610.356, -6793.182], 'motion': 'WALKING', 'id': 7, 'special_key': None}, {'position': [611.634, -6793.182], 'motion': 'WALKING', 'id': 8, 'special_key': None}, {'position': [612.657, -6793.182], 'motion': 'WALKING', 'id': 9, 'special_key': None}, {'position': [613.68, -6792.926], 'motion': 'WALKING', 'id': 10, 'special_key': None}, {'position': [614.703, -6792.926], 'motion': 'WALKING', 'id': 11, 'special_key': None}, {'position': [615.214, -6792.67], 'motion': 'WALKING', 'id': 12, 'special_key': None}, {'position': [615.981, -6792.415], 'motion': 'WALKING', 'id': 13, 'special_key': None}, {'position': [616.493, -6792.159], 'motion': 'WALKING', 'id': 14, 'special_key': None}, {'position': [617.004, -6791.903], 'motion': 'WALKING', 'id': 15, 'special_key': None}, {'position': [617.771, -6791.648], 'motion': 'WALKING', 'id': 16, 'special_key': None}, {'position': [618.027, -6791.392], 'motion': 'WALKING', 'id': 17, 'special_key': None}, {'position': [619.05, -6790.881], 'motion': 'WALKING', 'id': 18, 'special_key': None}, {'position': [619.561, -6790.881], 'motion': 'WALKING', 'id': 19, 'special_key': None}, {'position': [620.328, -6790.369], 'motion': 'WALKING', 'id': 20, 'special_key': None}, {'position': [620.84, -6790.369], 'motion': 'WALKING', 'id': 21, 'special_key': None}, {'position': [621.607, -6790.369], 'motion': 'WALKING', 'id': 22, 'special_key': None}, {'position': [622.118, -6790.113], 'motion': 'WALKING', 'id': 23, 'special_key': None}, {'position': [622.885, -6790.113], 'motion': 'WALKING', 'id': 24, 'special_key': None}, {'position': [623.141, -6789.858], 'motion': 'WALKING', 'id': 25, 'special_key': None}, {'position': [623.908, -6789.602], 'motion': 'WALKING', 'id': 26, 'special_key': None}, {'position': [624.164, -6789.346], 'motion': 'WALKING', 'id': 27, 'special_key': None}, {'position': [624.931, -6789.091], 'motion': 'WALKING', 'id': 28, 'special_key': None}, {'position': [625.186, -6788.835], 'motion': 'WALKING', 'id': 29, 'special_key': None}, {'position': [625.698, -6788.324], 'motion': 'WALKING', 'id': 30, 'special_key': None}, {'position': [625.954, -6787.812], 'motion': 'WALKING', 'id': 31, 'special_key': None}, {'position': [626.209, -6787.301], 'motion': 'WALKING', 'id': 32, 'special_key': None}, {'position': [626.465, -6786.789], 'motion': 'WALKING', 'id': 33, 'special_key': None}, {'position': [626.721, -6786.278], 'motion': 'WALKING', 'id': 34, 'special_key': None}, {'position': [626.976, -6785.767], 'motion': 'WALKING', 'id': 35, 'special_key': None}, {'position': [627.488, -6785.0], 'motion': 'WALKING', 'id': 36, 'special_key': None}, {'position': [627.744, -6784.744], 'motion': 'WALKING', 'id': 37, 'special_key': None}, {'position': [628.255, -6783.977], 'motion': 'WALKING', 'id': 38, 'special_key': None}, {'position': [628.255, -6783.465], 'motion': 'WALKING', 'id': 39, 'special_key': None}, {'position': [628.511, -6782.954], 'motion': 'WALKING', 'id': 40, 'special_key': None}, {'position': [628.766, -6782.187], 'motion': 'WALKING', 'id': 41, 'special_key': None}, {'position': [628.766, -6781.675], 'motion': 'WALKING', 'id': 42, 'special_key': None}, {'position': [629.022, -6780.908], 'motion': 'WALKING', 'id': 43, 'special_key': None}, {'position': [629.022, -6780.397], 'motion': 'WALKING', 'id': 44, 'special_key': None}, {'position': [629.533, -6779.885], 'motion': 'WALKING', 'id': 45, 'special_key': None}, {'position': [629.789, -6779.63], 'motion': 'WALKING', 'id': 46, 'special_key': None}, {'position': [630.3, -6778.863], 'motion': 'WALKING', 'id': 47, 'special_key': None}, {'position': [630.556, -6778.351], 'motion': 'WALKING', 'id': 48, 'special_key': None}, {'position': [631.068, -6777.584], 'motion': 'WALKING', 'id': 49, 'special_key': None}, {'position': [631.323, -6777.073], 'motion': 'WALKING', 'id': 50, 'special_key': None}, {'position': [631.323, -6776.561], 'motion': 'WALKING', 'id': 51, 'special_key': None}, {'position': [631.835, -6776.05], 'motion': 'WALKING', 'id': 52, 'special_key': None}, {'position': [631.835, -6775.539], 'motion': 'WALKING', 'id': 53, 'special_key': None}, {'position': [632.09, -6775.027], 'motion': 'WALKING', 'id': 54, 'special_key': None}, {'position': [632.602, -6774.516], 'motion': 'WALKING', 'id': 55, 'special_key': None}, {'position': [632.858, -6774.004], 'motion': 'WALKING', 'id': 56, 'special_key': None}, {'position': [633.369, -6773.237], 'motion': 'WALKING', 'id': 57, 'special_key': None}, {'position': [633.369, -6772.982], 'motion': 'WALKING', 'id': 58, 'special_key': None}, {'position': [633.625, -6771.703], 'motion': 'WALKING', 'id': 59, 'special_key': None}, {'position': [633.88, -6771.192], 'motion': 'WALKING', 'id': 60, 'special_key': None}, {'position': [633.88, -6770.425], 'motion': 'WALKING', 'id': 61, 'special_key': None}, {'position': [633.88, -6769.913], 'motion': 'WALKING', 'id': 62, 'special_key': None}, {'position': [634.136, -6769.402], 'motion': 'WALKING', 'id': 63, 'special_key': None}, {'position': [634.647, -6768.89], 'motion': 'WALKING', 'id': 64, 'special_key': None}, {'position': [634.903, -6768.379], 'motion': 'WALKING', 'id': 65, 'special_key': None}, {'position': [635.159, -6767.868], 'motion': 'WALKING', 'id': 66, 'special_key': None}, {'position': [635.414, -6767.1], 'motion': 'WALKING', 'id': 67, 'special_key': None}, {'position': [635.67, -6766.589], 'motion': 'WALKING', 'id': 68, 'special_key': None}, {'position': [635.926, -6766.078], 'motion': 'WALKING', 'id': 69, 'special_key': None}, {'position': [636.437, -6765.311], 'motion': 'WALKING', 'id': 70, 'special_key': None}, {'position': [636.693, -6765.055], 'motion': 'WALKING', 'id': 71, 'special_key': None}, {'position': [637.204, -6764.032], 'motion': 'WALKING', 'id': 72, 'special_key': None}, {'position': [637.716, -6763.776], 'motion': 'WALKING', 'id': 73, 'special_key': None}, {'position': [637.972, -6762.754], 'motion': 'WALKING', 'id': 74, 'special_key': None}, {'position': [638.483, -6761.731], 'motion': 'WALKING', 'id': 75, 'special_key': None}, {'position': [638.994, -6760.708], 'motion': 'WALKING', 'id': 76, 'special_key': None}, {'position': [639.25, -6759.685], 'motion': 'WALKING', 'id': 77, 'special_key': None}, {'position': [639.506, -6759.174], 'motion': 'WALKING', 'id': 78, 'special_key': None}, {'position': [640.273, -6758.918], 'motion': 'WALKING', 'id': 79, 'special_key': None}, {'position': [640.784, -6758.407], 'motion': 'WALKING', 'id': 80, 'special_key': None}, {'position': [641.551, -6758.151], 'motion': 'WALKING', 'id': 81, 'special_key': None}, {'position': [642.318, -6757.64], 'motion': 'WALKING', 'id': 82, 'special_key': None}, {'position': [642.83, -6757.384], 'motion': 'WALKING', 'id': 83, 'special_key': None}, {'position': [643.341, -6756.872], 'motion': 'WALKING', 'id': 84, 'special_key': None}, {'position': [644.108, -6756.872], 'motion': 'WALKING', 'id': 85, 'special_key': None}, {'position': [644.364, -6756.617], 'motion': 'WALKING', 'id': 86, 'special_key': None}, {'position': [645.387, -6756.617], 'motion': 'WALKING', 'id': 87, 'special_key': None}, {'position': [645.898, -6756.872], 'motion': 'WALKING', 'id': 88, 'special_key': None}, {'position': [646.41, -6756.872], 'motion': 'WALKING', 'id': 89, 'special_key': None}, {'position': [647.432, -6757.64], 'motion': 'WALKING', 'id': 90, 'special_key': None}, {'position': [647.688, -6757.895], 'motion': 'WALKING', 'id': 91, 'special_key': None}, {'position': [648.2, -6758.662], 'motion': 'WALKING', 'id': 92, 'special_key': None}, {'position': [648.455, -6758.662], 'motion': 'WALKING', 'id': 93, 'special_key': None}, {'position': [648.967, -6759.43], 'motion': 'WALKING', 'id': 94, 'special_key': None}, {'position': [648.967, -6759.941], 'motion': 'WALKING', 'id': 95, 'special_key': None}, {'position': [648.967, -6760.452], 'motion': 'WALKING', 'id': 96, 'special_key': None}, {'position': [648.967, -6760.964], 'motion': 'WALKING', 'id': 97, 'special_key': None}, {'position': [649.222, -6761.475], 'motion': 'WALKING', 'id': 98, 'special_key': None}, {'position': [649.222, -6761.986], 'motion': 'WALKING', 'id': 99, 'special_key': None}, {'position': [649.222, -6762.498], 'motion': 'WALKING', 'id': 100, 'special_key': None}], 'additional_info': {'pickup_points': [9]}, 'adsorptive_position': [[612.49952709975, -6780.75]]} \ No newline at end of file From a225cbb91c28c16cf3e0b7d778eba9b902685d9b Mon Sep 17 00:00:00 2001 From: infstellar <2644641825@qq.com> Date: Sun, 25 Jun 2023 12:48:16 +0800 Subject: [PATCH 40/40] upd: version --- source/cvars.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/cvars.py b/source/cvars.py index 31434baa..47c201e5 100644 --- a/source/cvars.py +++ b/source/cvars.py @@ -1,4 +1,4 @@ -GIA_VERSION = "v0.8.5.1039" +GIA_VERSION = "v0.8.6.1087" """Constants.""" # Devices