Add: Planner result scanner on GUI

This commit is contained in:
LmeSzinc 2024-05-19 19:26:20 +08:00
parent 82f4f255ad
commit 9795103f4d
14 changed files with 166 additions and 6 deletions

View File

@ -272,5 +272,10 @@
"Enable": true,
"AimClicker": "do_not_click"
}
},
"PlannerScan": {
"PlannerScan": {
"ResultAdd": false
}
}
}

View File

@ -1865,5 +1865,13 @@
]
}
}
},
"PlannerScan": {
"PlannerScan": {
"ResultAdd": {
"type": "checkbox",
"value": false
}
}
}
}

View File

@ -307,3 +307,5 @@ Daemon:
AimClicker:
value: do_not_click
option: [ item_enemy, item, enemy, do_not_click ]
PlannerScan:
ResultAdd: false

View File

@ -31,7 +31,8 @@
"menu": "list",
"page": "tool",
"tasks": [
"Daemon"
"Daemon",
"PlannerScan"
]
}
}

View File

@ -71,3 +71,5 @@ Tool:
tasks:
Daemon:
- Daemon
PlannerScan:
- PlannerScan

View File

@ -208,3 +208,6 @@ class GeneratedConfig:
# Group `Daemon`
Daemon_Enable = True # True
Daemon_AimClicker = 'do_not_click' # item_enemy, item, enemy, do_not_click
# Group `PlannerScan`
PlannerScan_ResultAdd = False

View File

@ -61,6 +61,10 @@
"Daemon": {
"name": "Dialogue Clicker",
"help": ""
},
"PlannerScan": {
"name": "Character Planner",
"help": ""
}
},
"Scheduler": {
@ -1265,6 +1269,16 @@
"do_not_click": "Don't click"
}
},
"PlannerScan": {
"_info": {
"name": "Scan Character Planner Results",
"help": "Tools need to stop the scheduler and then run independently\nBefore use, set planner goal in the in-game planner, calculate the results, and start scanning from the result page. Detailed usage see: https://github.com/LmeSzinc/StarRailCopilot/wiki/planner_cn"
},
"ResultAdd": {
"name": "Accumulate multiple scan results",
"help": "Turn on when planning multiple characters, will raise multiple characters all together\nTurn off when planning one character, planning goal will be refreshed at every scan"
}
},
"Gui": {
"Aside": {
"Install": "Install",

View File

@ -61,6 +61,10 @@
"Daemon": {
"name": "Clic de diálogo",
"help": ""
},
"PlannerScan": {
"name": "Planificador de personajes",
"help": ""
}
},
"Scheduler": {
@ -1265,6 +1269,16 @@
"do_not_click": "No hacer clic"
}
},
"PlannerScan": {
"_info": {
"name": "Escanear resultados del planificador de caracteres",
"help": "Las herramientas deben detener el programador y luego ejecutarse de forma independiente\nAntes de usarlo, establezca el objetivo del planificador en el planificador del juego, calcule los resultados y comience a escanear desde la página de resultados. Para uso detallado, consulte: https://github .com/LmeSzinc/StarRailCopilot/wiki/planner_cn"
},
"ResultAdd": {
"name": "Acumular múltiples resultados de escaneo",
"help": "Activar cuando se planifican varios personajes, generará varios personajes todos juntos\nDesactivar cuando se planifica un personaje, el objetivo de planificación se actualizará en cada escaneo"
}
},
"Gui": {
"Aside": {
"Install": "Instalar",

View File

@ -61,6 +61,10 @@
"Daemon": {
"name": "Task.Daemon.name",
"help": "Task.Daemon.help"
},
"PlannerScan": {
"name": "Task.PlannerScan.name",
"help": "Task.PlannerScan.help"
}
},
"Scheduler": {
@ -1265,6 +1269,16 @@
"do_not_click": "do_not_click"
}
},
"PlannerScan": {
"_info": {
"name": "PlannerScan._info.name",
"help": "PlannerScan._info.help"
},
"ResultAdd": {
"name": "PlannerScan.ResultAdd.name",
"help": "PlannerScan.ResultAdd.help"
}
},
"Gui": {
"Aside": {
"Install": "インストール",

View File

@ -61,6 +61,10 @@
"Daemon": {
"name": "剧情连点器",
"help": ""
},
"PlannerScan": {
"name": "角色养成规划",
"help": ""
}
},
"Scheduler": {
@ -1265,6 +1269,16 @@
"do_not_click": "不点击"
}
},
"PlannerScan": {
"_info": {
"name": "识别角色养成规划计算结果",
"help": "工具需要停止调度器再单独运行\n使用前需要在游戏内养成计算器中设定养成目标并计算出结果在计算结果页面启动养成规划识别。详细使用教程见\nhttps://github.com/LmeSzinc/StarRailCopilot/wiki/planner_cn"
},
"ResultAdd": {
"name": "累加多次扫描结果",
"help": "需要养成多个角色时勾选,同时养成多个角色\n仅养成一个角色不勾选每次扫描时刷新养成目标"
}
},
"Gui": {
"Aside": {
"Install": "安装",

View File

@ -61,6 +61,10 @@
"Daemon": {
"name": "劇情連點器",
"help": ""
},
"PlannerScan": {
"name": "角色養成規劃",
"help": ""
}
},
"Scheduler": {
@ -1265,6 +1269,16 @@
"do_not_click": "不點擊"
}
},
"PlannerScan": {
"_info": {
"name": "辨識角色養成規劃計算結果",
"help": "工具需要停止調度器再單獨運行\n使用前需要在遊戲內養成計算器中設定養成目標併計算出結果在計算結果頁面啟動養成規劃識別。詳細使用教程 請參閱:\nhttps://github.com/LmeSzinc/StarRailCopilot/wiki/planner_cn"
},
"ResultAdd": {
"name": "累加多次掃描結果",
"help": "需要養成多個角色時勾選,同時養成多個角色\n只養成一個角色不勾選每次掃描時刷新養成目標"
}
},
"Gui": {
"Aside": {
"Install": "安裝",

View File

@ -151,6 +151,10 @@ class ProcessManager:
from tasks.base.daemon import Daemon
Daemon(config=config_name, task="Daemon").run()
elif func == "PlannerScan":
from tasks.planner.scan import PlannerScan
PlannerScan(config=config_name, task="PlannerScan").run()
else:
logger.critical(f"No function matched: {func}")
logger.info(f"[{config_name}] exited. Reason: Finish\n")

View File

@ -69,6 +69,11 @@ class MultiValue(BaseModelWithFallback):
blue: int = 0
purple: int = 0
def add(self, other: "MultiValue"):
self.green += other.green
self.blue += other.blue
self.purple += other.purple
class StoredPlannerProxy(BaseModelWithFallback):
item: ITEM_TYPES
@ -178,8 +183,10 @@ class StoredPlannerProxy(BaseModelWithFallback):
self.value.green = value
if total is not None:
self.total.green = total
# Cannot synthesize green
# if synthesize is not None:
# self.synthesize.green = synthesize
self.synthesize.green = 0
elif item.is_rarity_blue:
if value is not None:
self.value.blue = value
@ -198,11 +205,39 @@ class StoredPlannerProxy(BaseModelWithFallback):
raise ScriptError(
f'load_value_total: Trying to load {item} in to {self} but item is in invalid rarity')
else:
# Cannot synthesize if item doesn't have multiple rarity
self.synthesize = 0
if value is not None:
self.value = value
if total is not None:
self.total = total
def add_planner_result(self, row: "StoredPlannerProxy"):
"""
Add data from another StoredPlannerProxy to self
"""
item = row.item
if self.item.has_group_base:
if item.group_base != self.item:
raise ScriptError(
f'load_value_total: Trying to load {item} into {self} but they are different items')
else:
if item != self.item:
raise ScriptError(
f'load_value_total: Trying to load {item} into {self} but they are different items')
if self.item.has_group_base:
if not self.item.is_rarity_purple:
raise ScriptError(
f'load_value_total: Trying to load {item} into {self} but self is not in rarity purple')
# Add `total` only
# `synthesize` will be updated later
# `value` remains unchanged since you still having that many items
self.total.add(row.total)
else:
self.value += row.value
self.total += row.total
self.synthesize += row.synthesize
def need_farm(self):
return self.progress < 100
@ -289,6 +324,20 @@ class PlannerProgressParser:
self.rows[row.item.name] = row
return self
def add_planner_result(self, planner: "PlannerProgressParser"):
"""
Add another planner result to self
"""
for name, row in planner.rows.items():
if name in self.rows:
self_row = self.rows[name]
self_row.add_planner_result(row)
else:
self.rows[name] = row
for row in self.rows.values():
row.update()
def to_config(self) -> dict:
data = {}
for row in self.rows.values():
@ -383,7 +432,13 @@ class PlannerMixin(UI):
"""
Write planner detection results info user config
"""
add = self.config.PlannerScan_ResultAdd
logger.attr('ResultAdd', add)
planner = PlannerProgressParser().from_planner_results(results)
if add:
planner.add_planner_result(self.planner)
self.planner_write(planner)
@cached_property
@ -405,6 +460,15 @@ class PlannerMixin(UI):
data = planner.to_config()
with self.config.multi_set():
# Set value
for key, value in data.items():
self.config.cross_set(f'Dungeon.Planner.{key}', value)
# Remove other value
remove = []
for key, value in self.config.cross_get('Dungeon.Planner', default={}).items():
if value != {} and key not in data:
remove.append(key)
for key in remove:
self.config.cross_set(f'Dungeon.Planner.{key}', {})
del_cached_property(self, 'planner')

View File

@ -18,9 +18,6 @@ MATERIAL_TITLE.load_search(RESULT_CHECK.search)
DETAIL_TITLE.load_search(RESULT_CHECK.search)
class OcrItemName(Ocr):
def after_process(self, result):
result = result.replace('念火之心', '忿火之心')
@ -75,7 +72,7 @@ class OcrPlannerResult(OcrWhiteLetterOnComplexBackground, OcrItemName):
return image
class PlannerResult(SynthesizeUI, PlannerMixin):
class PlannerScan(SynthesizeUI, PlannerMixin):
def is_in_planner_result(self):
if self.appear(RESULT_CHECK):
return True
@ -216,8 +213,12 @@ class PlannerResult(SynthesizeUI, PlannerMixin):
self.planner_write_results(out)
return out
if __name__ == '__main__':
self = PlannerResult('src')
def run(self):
self.device.screenshot()
self.parse_planner_result()
if __name__ == '__main__':
self = PlannerScan('src', task='PlannerScan')
self.device.screenshot()
self.parse_planner_result()