mirror of
https://github.com/LmeSzinc/StarRailCopilot.git
synced 2024-11-22 00:35:34 +00:00
Add: Display overall progress of character planner
This commit is contained in:
parent
d6d61bb6fc
commit
33eedc2c63
@ -47,6 +47,7 @@
|
||||
"ServerUpdate": "04:00"
|
||||
},
|
||||
"Planner": {
|
||||
"PlannerOverall": {},
|
||||
"Item_Credit": {},
|
||||
"Item_Trailblaze_EXP": {},
|
||||
"Item_Traveler_Guide": {},
|
||||
|
@ -220,6 +220,14 @@
|
||||
}
|
||||
},
|
||||
"Planner": {
|
||||
"PlannerOverall": {
|
||||
"type": "stored",
|
||||
"value": {},
|
||||
"display": true,
|
||||
"stored": "StoredPlannerOverall",
|
||||
"order": 4,
|
||||
"color": "#85e7f2"
|
||||
},
|
||||
"Item_Credit": {
|
||||
"type": "planner",
|
||||
"value": {},
|
||||
@ -729,9 +737,7 @@
|
||||
"type": "stored",
|
||||
"value": {},
|
||||
"display": "hide",
|
||||
"stored": "StoredEchoOfWar",
|
||||
"order": 4,
|
||||
"color": "#85e7f2"
|
||||
"stored": "StoredEchoOfWar"
|
||||
},
|
||||
"SimulatedUniverse": {
|
||||
"type": "stored",
|
||||
|
@ -129,15 +129,18 @@ DungeonStorage:
|
||||
stored: StoredDungeonDouble
|
||||
EchoOfWar:
|
||||
stored: StoredEchoOfWar
|
||||
order: 4
|
||||
color: "#85e7f2"
|
||||
SimulatedUniverse:
|
||||
stored: StoredSimulatedUniverse
|
||||
order: 6
|
||||
color: "#8fb5fe"
|
||||
SupportReward:
|
||||
Collect: true
|
||||
Planner: {}
|
||||
Planner:
|
||||
PlannerOverall:
|
||||
stored: StoredPlannerOverall
|
||||
display: true
|
||||
order: 4
|
||||
color: "#85e7f2"
|
||||
# Items will be injected in config updater
|
||||
|
||||
Weekly:
|
||||
|
@ -61,6 +61,8 @@ Dashboard:
|
||||
HoursAgo:
|
||||
DaysAgo:
|
||||
LongTimeAgo:
|
||||
# Planner
|
||||
EtaDays:
|
||||
|
||||
AddAlas:
|
||||
PopupTitle:
|
||||
|
@ -38,15 +38,15 @@
|
||||
"order": 3,
|
||||
"color": "#79dbc4"
|
||||
},
|
||||
"EchoOfWar": {
|
||||
"name": "EchoOfWar",
|
||||
"path": "Dungeon.DungeonStorage.EchoOfWar",
|
||||
"i18n": "DungeonStorage.EchoOfWar.name",
|
||||
"stored": "StoredEchoOfWar",
|
||||
"PlannerOverall": {
|
||||
"name": "PlannerOverall",
|
||||
"path": "Dungeon.Planner.PlannerOverall",
|
||||
"i18n": "Planner.PlannerOverall.name",
|
||||
"stored": "StoredPlannerOverall",
|
||||
"attrs": {
|
||||
"time": "2020-01-01 00:00:00",
|
||||
"total": 3,
|
||||
"value": 0
|
||||
"comment": "<??d",
|
||||
"value": "??%"
|
||||
},
|
||||
"order": 4,
|
||||
"color": "#85e7f2"
|
||||
@ -714,6 +714,19 @@
|
||||
"order": 0,
|
||||
"color": "#777777"
|
||||
},
|
||||
"EchoOfWar": {
|
||||
"name": "EchoOfWar",
|
||||
"path": "Dungeon.DungeonStorage.EchoOfWar",
|
||||
"i18n": "DungeonStorage.EchoOfWar.name",
|
||||
"stored": "StoredEchoOfWar",
|
||||
"attrs": {
|
||||
"time": "2020-01-01 00:00:00",
|
||||
"total": 3,
|
||||
"value": 0
|
||||
},
|
||||
"order": 0,
|
||||
"color": "#777777"
|
||||
},
|
||||
"DailyQuest": {
|
||||
"name": "DailyQuest",
|
||||
"path": "DailyQuest.DailyStorage.DailyQuest",
|
||||
|
@ -53,7 +53,7 @@ class GeneratedConfig:
|
||||
|
||||
# Group `DungeonSupport`
|
||||
DungeonSupport_Use = 'when_daily' # always_use, when_daily, do_not_use
|
||||
DungeonSupport_Character = 'FirstCharacter' # FirstCharacter, Acheron, Argenti, Arlan, Asta, Aventurine, Bailu, BlackSwan, Blade, Boothill, Bronya, Clara, DanHeng, DanHengImbibitorLunae, DrRatio, FuXuan, Gallagher, Gepard, Guinaifen, Hanya, Herta, Himeko, Hook, Huohuo, JingYuan, Jingliu, Kafka, Luka, Luocha, Lynx, March7th, Misha, Natasha, Pela, Qingque, Robin, RuanMei, Sampo, Seele, Serval, SilverWolf, Sparkle, Sushang, Tingyun, TopazNumby, TrailblazerDestruction, TrailblazerPreservation, Welt, Xueyi, Yanqing, Yukong
|
||||
DungeonSupport_Character = 'FirstCharacter' # FirstCharacter, Acheron, Argenti, Arlan, Asta, Aventurine, Bailu, BlackSwan, Blade, Boothill, Bronya, Clara, DanHeng, DanHengImbibitorLunae, DrRatio, FuXuan, Gallagher, Gepard, Guinaifen, Hanya, Herta, Himeko, Hook, Huohuo, JingYuan, Jingliu, Kafka, Luka, Luocha, Lynx, March7th, Misha, Natasha, Pela, Qingque, Robin, RuanMei, Sampo, Seele, Serval, SilverWolf, Sparkle, Sushang, Tingyun, TopazNumby, TrailblazerDestruction, TrailblazerHarmony, TrailblazerPreservation, Welt, Xueyi, Yanqing, Yukong
|
||||
|
||||
# Group `DungeonStorage`
|
||||
DungeonStorage_TrailblazePower = {}
|
||||
@ -66,6 +66,7 @@ class GeneratedConfig:
|
||||
SupportReward_Collect = True
|
||||
|
||||
# Group `Planner`
|
||||
Planner_PlannerOverall = {}
|
||||
Planner_Item_Credit = {}
|
||||
Planner_Item_Trailblaze_EXP = {}
|
||||
Planner_Item_Traveler_Guide = {}
|
||||
|
@ -465,6 +465,10 @@
|
||||
"name": "Character Planner Progress",
|
||||
"help": "Character planner is prioritized. After completed, \"Dungeon Settings\" will be executed."
|
||||
},
|
||||
"PlannerOverall": {
|
||||
"name": "Planner",
|
||||
"help": "Overall progress of character planner"
|
||||
},
|
||||
"Item_Credit": {
|
||||
"name": "Credit",
|
||||
"help": ""
|
||||
@ -1269,7 +1273,8 @@
|
||||
"MinutesAgo": "{time}min ago",
|
||||
"HoursAgo": "{time}h ago",
|
||||
"DaysAgo": "{time}d ago",
|
||||
"LongTimeAgo": "long time ago"
|
||||
"LongTimeAgo": "long time ago",
|
||||
"EtaDays": "ETA {time}d"
|
||||
},
|
||||
"AddAlas": {
|
||||
"PopupTitle": "Add new config",
|
||||
|
@ -465,6 +465,10 @@
|
||||
"name": "Progreso del planificador de personajes",
|
||||
"help": "Se prioriza el planificador de personajes. Una vez completado, se ejecutará la \"Ajustes de Mazmorra\"."
|
||||
},
|
||||
"PlannerOverall": {
|
||||
"name": "Plan.",
|
||||
"help": "Progreso general del planificador de personajes"
|
||||
},
|
||||
"Item_Credit": {
|
||||
"name": "Crédito",
|
||||
"help": ""
|
||||
@ -1269,7 +1273,8 @@
|
||||
"MinutesAgo": "hace {time}m",
|
||||
"HoursAgo": "hace {time}h",
|
||||
"DaysAgo": "hace {time}d",
|
||||
"LongTimeAgo": "hace mucho tiempo"
|
||||
"LongTimeAgo": "hace mucho tiempo",
|
||||
"EtaDays": "ETA {time}d"
|
||||
},
|
||||
"AddAlas": {
|
||||
"PopupTitle": "Añadir nueva configuración",
|
||||
|
@ -465,6 +465,10 @@
|
||||
"name": "Planner._info.name",
|
||||
"help": "Planner._info.help"
|
||||
},
|
||||
"PlannerOverall": {
|
||||
"name": "Planner.PlannerOverall.name",
|
||||
"help": "Planner.PlannerOverall.help"
|
||||
},
|
||||
"Item_Credit": {
|
||||
"name": "信用ポイント",
|
||||
"help": ""
|
||||
@ -1269,7 +1273,8 @@
|
||||
"MinutesAgo": "Gui.Dashboard.MinutesAgo",
|
||||
"HoursAgo": "Gui.Dashboard.HoursAgo",
|
||||
"DaysAgo": "Gui.Dashboard.DaysAgo",
|
||||
"LongTimeAgo": "Gui.Dashboard.LongTimeAgo"
|
||||
"LongTimeAgo": "Gui.Dashboard.LongTimeAgo",
|
||||
"EtaDays": "Gui.Dashboard.EtaDays"
|
||||
},
|
||||
"AddAlas": {
|
||||
"PopupTitle": "新しいコンフィグを追加",
|
||||
|
@ -465,6 +465,10 @@
|
||||
"name": "养成规划进度",
|
||||
"help": "优先执行养成规划,养成规划完成后,执行 \"每日副本设置\""
|
||||
},
|
||||
"PlannerOverall": {
|
||||
"name": "养成规划",
|
||||
"help": "角色养成规划总体进度"
|
||||
},
|
||||
"Item_Credit": {
|
||||
"name": "信用点",
|
||||
"help": ""
|
||||
@ -1269,7 +1273,8 @@
|
||||
"MinutesAgo": "{time}分钟前",
|
||||
"HoursAgo": "{time}小时前",
|
||||
"DaysAgo": "{time}天前",
|
||||
"LongTimeAgo": "很久以前"
|
||||
"LongTimeAgo": "很久以前",
|
||||
"EtaDays": "剩余{time}天"
|
||||
},
|
||||
"AddAlas": {
|
||||
"PopupTitle": "添加新配置",
|
||||
|
@ -465,6 +465,10 @@
|
||||
"name": "養成規劃進度",
|
||||
"help": "優先執行養成規劃,養成規劃完成後,執行 \"每日副本設定\""
|
||||
},
|
||||
"PlannerOverall": {
|
||||
"name": "養成規劃",
|
||||
"help": "角色養成規劃總體進度"
|
||||
},
|
||||
"Item_Credit": {
|
||||
"name": "信用點",
|
||||
"help": ""
|
||||
@ -1269,7 +1273,8 @@
|
||||
"MinutesAgo": "{time}分鐘前",
|
||||
"HoursAgo": "{time}小時前",
|
||||
"DaysAgo": "{time}天前",
|
||||
"LongTimeAgo": "很久以前"
|
||||
"LongTimeAgo": "很久以前",
|
||||
"EtaDays": "剩餘{time}日"
|
||||
},
|
||||
"AddAlas": {
|
||||
"PopupTitle": "添加新的設定",
|
||||
|
@ -404,3 +404,8 @@ class StoredPlanner(StoredBase):
|
||||
value: int
|
||||
total: int
|
||||
synthesize: int
|
||||
|
||||
|
||||
class StoredPlannerOverall(StoredBase):
|
||||
value: str = '??%'
|
||||
comment: str = '<??d'
|
||||
|
@ -20,6 +20,7 @@ from module.config.stored.classes import (
|
||||
StoredImmersifier,
|
||||
StoredInt,
|
||||
StoredPlanner,
|
||||
StoredPlannerOverall,
|
||||
StoredSimulatedUniverse,
|
||||
StoredSimulatedUniverseElite,
|
||||
StoredTrailblazePower,
|
||||
@ -33,6 +34,7 @@ class StoredGenerated:
|
||||
CloudRemainSeasonPass = StoredInt("Alas.CloudStorage.CloudRemainSeasonPass")
|
||||
CloudRemainPaid = StoredInt("Alas.CloudStorage.CloudRemainPaid")
|
||||
CloudRemainFree = StoredInt("Alas.CloudStorage.CloudRemainFree")
|
||||
PlannerOverall = StoredPlannerOverall("Dungeon.Planner.PlannerOverall")
|
||||
Item_Credit = StoredPlanner("Dungeon.Planner.Item_Credit")
|
||||
Item_Trailblaze_EXP = StoredPlanner("Dungeon.Planner.Item_Trailblaze_EXP")
|
||||
Item_Traveler_Guide = StoredPlanner("Dungeon.Planner.Item_Traveler_Guide")
|
||||
|
@ -341,6 +341,11 @@ class AlasGUI(Frame):
|
||||
put_text(config.get("value", nodata)).style("--dashboard-value--"),
|
||||
put_text(f' / {config.get("total", "")}').style("--dashboard-time--"),
|
||||
]
|
||||
elif "comment" in dic.get("attrs", []) and config.get("comment") is not None:
|
||||
return [
|
||||
put_text(config.get("value", nodata)).style("--dashboard-value--"),
|
||||
put_text(f' {config.get("comment", "")}').style("--dashboard-time--"),
|
||||
]
|
||||
else:
|
||||
return [
|
||||
put_text(config.get("value", nodata)).style("--dashboard-value--"),
|
||||
|
@ -346,6 +346,7 @@ def put_arg_stored(kwargs: T_Output_Kwargs) -> Output:
|
||||
value = values.pop("value", "")
|
||||
total = values.pop("total", "")
|
||||
time_ = values.pop("time", "")
|
||||
comment = values.pop("comment", "")
|
||||
|
||||
if value != "" and total != "":
|
||||
# 0 / 100
|
||||
@ -353,6 +354,12 @@ def put_arg_stored(kwargs: T_Output_Kwargs) -> Output:
|
||||
put_text(value).style("--dashboard-value--"),
|
||||
put_text(f" / {total}").style("--dashboard-time--"),
|
||||
])]
|
||||
elif value != "" and comment != "":
|
||||
# 88% <1.2d
|
||||
rows = [put_scope(f"dashboard-value-{name}", [
|
||||
put_text(value).style("--dashboard-value--"),
|
||||
put_text(f" {comment}").style("--dashboard-time--"),
|
||||
])]
|
||||
elif value != "":
|
||||
# 100
|
||||
rows = [put_scope(f"dashboard-value-{name}", [
|
||||
@ -393,6 +400,11 @@ def put_arg_planner(kwargs: T_Output_Kwargs) -> Output | None:
|
||||
except KeyError:
|
||||
# Hide items not needed by the planner
|
||||
return None
|
||||
eta = values.get("eta", 0)
|
||||
if eta > 0:
|
||||
eta = f" - {t('Gui.Dashboard.EtaDays', time=eta)}"
|
||||
else:
|
||||
eta = ""
|
||||
|
||||
value = values.pop('value', 0)
|
||||
if isinstance(value, dict):
|
||||
@ -402,7 +414,7 @@ def put_arg_planner(kwargs: T_Output_Kwargs) -> Output | None:
|
||||
total = tuple(total.values())
|
||||
|
||||
row = put_scope(f"arg_stored-stored-value-{name}", [
|
||||
put_text(f"{progress:.2f}%").style("--dashboard-bold--"),
|
||||
put_text(f"{progress:.2f}%{eta}").style("--dashboard-bold--"),
|
||||
put_text(f"{value} / {total}").style("--dashboard-time--"),
|
||||
])
|
||||
|
||||
|
@ -1,8 +1,9 @@
|
||||
import math
|
||||
import typing as t
|
||||
from datetime import datetime
|
||||
from functools import partial
|
||||
from functools import cached_property as functools_cached_property, partial
|
||||
|
||||
from pydantic import BaseModel, ValidationError, WrapValidator, field_validator, model_validator
|
||||
from pydantic import BaseModel, ValidationError, WrapValidator, computed_field, field_validator, model_validator
|
||||
|
||||
from module.base.decorator import cached_property, del_cached_property
|
||||
from module.config.stored.classes import now
|
||||
@ -74,16 +75,37 @@ class MultiValue(BaseModelWithFallback):
|
||||
self.blue += other.blue
|
||||
self.purple += other.purple
|
||||
|
||||
def __sub__(self, other):
|
||||
green = max(self.green - other.green, 0)
|
||||
blue = max(self.blue - other.blue, 0)
|
||||
purple = max(self.purple - other.purple, 0)
|
||||
return MultiValue(green=green, blue=blue, purple=purple)
|
||||
|
||||
def equivalent_green(self):
|
||||
return self.green + self.blue * 3 + self.purple * 9
|
||||
|
||||
def clear(self):
|
||||
self.green = 0
|
||||
self.blue = 0
|
||||
self.purple = 0
|
||||
|
||||
|
||||
SET_ROW_EXCLUDE = {
|
||||
'drop_equivalent_green',
|
||||
'combat_cost',
|
||||
'progress_remain',
|
||||
'progress_total',
|
||||
'progress_current',
|
||||
}
|
||||
|
||||
|
||||
class StoredPlannerProxy(BaseModelWithFallback):
|
||||
item: ITEM_TYPES
|
||||
value: int | MultiValue = 0
|
||||
total: int | MultiValue = 0
|
||||
synthesize: int | MultiValue = 0
|
||||
progress: float = 0.
|
||||
# progress: float = 0.
|
||||
# eta: float = 0.
|
||||
time: datetime = DEFAULT_TIME
|
||||
|
||||
@field_validator('item', mode='before')
|
||||
@ -110,6 +132,12 @@ class StoredPlannerProxy(BaseModelWithFallback):
|
||||
self.synthesize = 0
|
||||
return self
|
||||
|
||||
def clear(self):
|
||||
if self.item.has_group_base:
|
||||
self.value.clear()
|
||||
else:
|
||||
self.value = 0
|
||||
|
||||
def update_synthesize(self):
|
||||
if self.item.has_group_base:
|
||||
green = self.value.green - self.total.green
|
||||
@ -147,6 +175,82 @@ class StoredPlannerProxy(BaseModelWithFallback):
|
||||
else:
|
||||
self.value.blue += self.synthesize.purple * 3
|
||||
|
||||
@computed_field(repr=False)
|
||||
@functools_cached_property
|
||||
def drop_equivalent_green(self) -> float:
|
||||
# Tracks_of_Destiny
|
||||
if self.item.dungeon is None:
|
||||
return 1
|
||||
if self.item.dungeon.is_Calyx_Golden_Treasures:
|
||||
return 24000
|
||||
if self.item.dungeon.is_Calyx_Golden_Memories:
|
||||
# purple, blue, green = 5, 1, 0
|
||||
return 48
|
||||
if self.item.dungeon.is_Calyx_Golden_Aether:
|
||||
# purple, blue, green = 1, 2, 2.5
|
||||
return 17.5
|
||||
if self.item.is_ItemAscension:
|
||||
return 3
|
||||
if self.item.is_ItemTrace:
|
||||
# purple, blue, green = 0.155, 1, 1.25
|
||||
return 5.645
|
||||
if self.item.is_ItemWeekly:
|
||||
return 3
|
||||
raise ScriptError(f'{self} has no drop_equivalent_green defined')
|
||||
|
||||
@computed_field(repr=False)
|
||||
@functools_cached_property
|
||||
def combat_cost(self) -> int:
|
||||
# Tracks_of_Destiny
|
||||
if self.item.dungeon is None:
|
||||
return 30
|
||||
if self.item.dungeon.is_Calyx_Golden:
|
||||
return 10
|
||||
if self.item.is_ItemAscension:
|
||||
return 30
|
||||
if self.item.is_ItemTrace:
|
||||
return 10
|
||||
if self.item.is_ItemWeekly:
|
||||
return 30
|
||||
raise ScriptError(f'{self} has no stamina_pre_combat defined')
|
||||
|
||||
@computed_field(repr=False)
|
||||
@functools_cached_property
|
||||
def progress_remain(self) -> float:
|
||||
if self.item.has_group_base:
|
||||
remain = self.total - self.value - self.synthesize
|
||||
return remain.equivalent_green()
|
||||
else:
|
||||
remain = max(self.total - self.value, 0)
|
||||
return remain
|
||||
|
||||
@computed_field(repr=False)
|
||||
@functools_cached_property
|
||||
def progress_total(self) -> float:
|
||||
if self.item.has_group_base:
|
||||
return self.total.equivalent_green()
|
||||
else:
|
||||
return self.total
|
||||
|
||||
@computed_field(repr=False)
|
||||
@functools_cached_property
|
||||
def progress_current(self) -> float:
|
||||
if self.item.has_group_base:
|
||||
current = self.progress_total - self.progress_remain
|
||||
current = min(max(current, 0), self.progress_total)
|
||||
return current
|
||||
else:
|
||||
current = self.value
|
||||
current = min(max(current, 0), self.total)
|
||||
return current
|
||||
|
||||
@computed_field
|
||||
@functools_cached_property
|
||||
def progress(self) -> float:
|
||||
# 0 to 100
|
||||
progress = self.progress_current / self.progress_total * 100
|
||||
return round(min(max(progress, 0), 100), 2)
|
||||
|
||||
def is_approaching_total(self, wave_done: int = 0):
|
||||
"""
|
||||
Args:
|
||||
@ -157,45 +261,46 @@ class StoredPlannerProxy(BaseModelWithFallback):
|
||||
"""
|
||||
wave_done = max(wave_done, 0)
|
||||
# Items with a static drop rate will have `AVG * (wave_done + 1)
|
||||
if self.item.dungeon.is_Calyx_Golden_Treasures:
|
||||
return self.value + 24000 * (wave_done + 12) >= self.total
|
||||
if self.item.dungeon.is_Calyx_Golden_Memories:
|
||||
# purple, blue, green = 5, 1, 0
|
||||
value = self.value.equivalent_green()
|
||||
total = self.total.equivalent_green()
|
||||
return value + 48 * (wave_done + 12) >= total
|
||||
if self.item.dungeon.is_Calyx_Golden_Aether:
|
||||
# purple, blue, green = 1, 2, 2.5
|
||||
value = self.value.equivalent_green()
|
||||
total = self.total.equivalent_green()
|
||||
return value + 17.5 * (wave_done + 12) >= total
|
||||
if self.item.is_ItemAscension:
|
||||
return self.value + 3 * (wave_done + 1) >= self.total
|
||||
if self.item.is_ItemTrace:
|
||||
# purple, blue, green = 0.155, 1, 1.25
|
||||
value = self.value.equivalent_green()
|
||||
total = self.total.equivalent_green()
|
||||
return value + 5.645 * (wave_done + 12) >= total
|
||||
if self.item.is_ItemWeekly:
|
||||
return self.value + 3 * (wave_done + 1) >= self.total
|
||||
return False
|
||||
|
||||
def update_progress(self):
|
||||
if self.item.has_group_base:
|
||||
total = self.total.equivalent_green()
|
||||
green = min(self.value.green, self.total.green)
|
||||
blue = min(self.value.blue + self.synthesize.blue, self.total.blue)
|
||||
purple = min(self.value.purple + self.synthesize.purple, self.total.purple)
|
||||
value = green + blue * 3 + purple * 9
|
||||
progress = value / total * 100
|
||||
self.progress = round(min(max(progress, 0), 100), 2)
|
||||
remain = self.progress_remain
|
||||
cost = self.combat_cost
|
||||
drop = self.drop_equivalent_green
|
||||
if cost == 10:
|
||||
return remain <= drop * (wave_done + 12)
|
||||
else:
|
||||
progress = self.value / self.total * 100
|
||||
self.progress = round(min(max(progress, 0), 100), 2)
|
||||
return remain <= drop * (wave_done + 1)
|
||||
|
||||
@computed_field
|
||||
@functools_cached_property
|
||||
def eta(self) -> float:
|
||||
"""
|
||||
Estimate remaining days to farm
|
||||
"""
|
||||
if not self.need_farm():
|
||||
return 0.
|
||||
if self.item.dungeon is None:
|
||||
return 0.
|
||||
|
||||
remain = self.progress_remain
|
||||
cost = self.combat_cost
|
||||
drop = self.drop_equivalent_green
|
||||
|
||||
if self.item.is_ItemWeekly:
|
||||
weeks = math.ceil(remain / drop / 3)
|
||||
return weeks * 7
|
||||
else:
|
||||
stamina = math.ceil(remain / drop) * cost
|
||||
return round(stamina / 240, 1)
|
||||
|
||||
def update(self, time=False):
|
||||
for attr in SET_ROW_EXCLUDE:
|
||||
del_cached_property(self, attr)
|
||||
del_cached_property(self, 'progress')
|
||||
del_cached_property(self, 'eta')
|
||||
|
||||
def update(self):
|
||||
self.update_synthesize()
|
||||
self.update_progress()
|
||||
_ = self.progress
|
||||
_ = self.eta
|
||||
if time:
|
||||
self.time = now()
|
||||
|
||||
def load_value_total(self, item: ItemBase, value=None, total=None, synthesize=None):
|
||||
@ -344,9 +449,11 @@ class PlannerProgressParser:
|
||||
|
||||
def from_config(self, data):
|
||||
self.rows = {}
|
||||
for row in data.values():
|
||||
for name, row in data.items():
|
||||
if not row:
|
||||
continue
|
||||
if name == 'PlannerOverall':
|
||||
continue
|
||||
try:
|
||||
row = StoredPlannerProxy(**row)
|
||||
except (ScriptError, ValidationError) as e:
|
||||
@ -355,8 +462,7 @@ class PlannerProgressParser:
|
||||
if not row.item.is_group_base:
|
||||
logger.error(f'from_config: item is not group base {row}')
|
||||
continue
|
||||
row.update_synthesize()
|
||||
row.update_progress()
|
||||
row.update(time=False)
|
||||
self.rows[row.item.name] = row
|
||||
return self
|
||||
|
||||
@ -372,17 +478,37 @@ class PlannerProgressParser:
|
||||
self.rows[name] = row
|
||||
|
||||
for row in self.rows.values():
|
||||
row.update()
|
||||
row.update(time=True)
|
||||
|
||||
def to_config(self) -> dict:
|
||||
data = {}
|
||||
for row in self.rows.values():
|
||||
name = f'Item_{row.item.name}'
|
||||
dic = row.model_dump()
|
||||
dic = row.model_dump(exclude=SET_ROW_EXCLUDE)
|
||||
dic['item'] = row.item.name
|
||||
data[name] = dic
|
||||
return data
|
||||
|
||||
def get_overall(self):
|
||||
"""
|
||||
Calculate overall progress
|
||||
Note that this method will clear all values
|
||||
|
||||
Returns:
|
||||
float: Progress percentage
|
||||
float: ETA in days
|
||||
"""
|
||||
eta = 0.
|
||||
progress_current = 0.
|
||||
progress_total = 0.
|
||||
for row in self.rows.values():
|
||||
eta += row.eta
|
||||
progress_current += row.progress_current
|
||||
progress_total += row.progress_total
|
||||
|
||||
progress = round(progress_current / progress_total * 100, 2)
|
||||
return progress, eta
|
||||
|
||||
def iter_row_to_farm(self, need_farm=True) -> t.Iterable[StoredPlannerProxy]:
|
||||
"""
|
||||
Args:
|
||||
@ -494,6 +620,7 @@ class PlannerMixin(UI):
|
||||
planner = self.planner
|
||||
|
||||
data = planner.to_config()
|
||||
progress, eta = planner.get_overall()
|
||||
|
||||
with self.config.multi_set():
|
||||
# Set value
|
||||
@ -506,5 +633,14 @@ class PlannerMixin(UI):
|
||||
remove.append(key)
|
||||
for key in remove:
|
||||
self.config.cross_set(f'Dungeon.Planner.{key}', {})
|
||||
print(progress, eta)
|
||||
# Set overall
|
||||
self.config.stored.PlannerOverall.value = f'{progress:.2f}%'
|
||||
self.config.stored.PlannerOverall.comment = f'<{eta:.1f}d'
|
||||
|
||||
del_cached_property(self, 'planner')
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
self = PlannerMixin('src')
|
||||
self.planner_write(self.planner)
|
||||
|
@ -22,6 +22,7 @@ DETAIL_TITLE.load_search(RESULT_CHECK.search)
|
||||
class OcrItemName(Ocr):
|
||||
def after_process(self, result):
|
||||
result = result.replace('念火之心', '忿火之心')
|
||||
result = re.sub('^火之心', '忿火之心', result)
|
||||
result = re.sub('工造机$', '工造机杼', result)
|
||||
result = re.sub('工造迥?轮', '工造迴轮', result)
|
||||
result = re.sub('月狂[療撩]?牙', '月狂獠牙', result)
|
||||
|
Loading…
Reference in New Issue
Block a user