ango commited on
Commit
0ed027c
·
1 Parent(s): b76daae

04.18 commit

Browse files
README.md ADDED
@@ -0,0 +1,28 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Comprehensive Damage Formulator with JCL Parser
2
+
3
+ ## User Guide
4
+ ### In Progress
5
+
6
+ ## Contributing to This Project
7
+ ### Add Your School
8
+ To add your school to the application, follow the steps below:
9
+ Under the schools directory, create a new python directory name it after your school (Please use snake_case for the name).
10
+ and add the following files to your directory:
11
+
12
+ - **\_\_init__.py**: this file will import all detail a school needed
13
+ - **attribute.py**: define your school attribute, like extra attribute from school
14
+ - **buffs.py**: define the buffs of your school
15
+ - **gains.py**: define the gains from your school equipment, like divine and tier set activate
16
+ - **recipes.py**: define the recipes for skill of your school
17
+ - **skills.py**: define the skills of your school, include all damage skill and dot trigger skill
18
+ - **talents.py**: define the talents of your school
19
+
20
+ ### Integrate Your School into UI
21
+ Once the school framework is ready, make your school data available on our QT-UI:
22
+
23
+ Open the **parser.py** under **utils** dir, and add your school into **SUPPORT_SCHOOL** dictionary like below:
24
+
25
+ - key: the school id you can find in LUA or ask me
26
+ - value: a School instance set by the details import from **schools/<YOUR_SCHOOL>**
27
+
28
+ Feel free to contribute to this exciting project! Your collaboration will make our tool more comprehensive and valuable to all users.
general/buffs.py CHANGED
@@ -17,8 +17,8 @@ GENERAL_BUFFS = {
17
  6360: {
18
  "buff_name": "风特效",
19
  "gain_attributes": {
20
- "physical_overcome_base": [0] * 99 + sum([[0] + [0, v] + [0] * 5 for v in [6408, 8330, 9291, 10573]], []),
21
- "magical_overcome_base": [0] * 99 + sum([[0] + [v, 0] + [0] * 5 for v in [6408, 8330, 9291, 10573]], [])
22
  }
23
  }
24
  }
 
17
  6360: {
18
  "buff_name": "风特效",
19
  "gain_attributes": {
20
+ "physical_overcome_base": [0] * 99 + sum([[0] + [0, v] + [0] * 4 for v in [6408, 8330, 9291, 10573]], []),
21
+ "magical_overcome_base": [0] * 99 + sum([[0] + [v, 0] + [0] * 4 for v in [6408, 8330, 9291, 10573]], [])
22
  }
23
  }
24
  }
general/gains/formation.py CHANGED
@@ -70,7 +70,7 @@ class 北斗七星阵(FormationGain):
70
  "strain_gain": 20,
71
  "physical_critical_power_gain": 150
72
  }
73
- rate_gain_attributes = {"physical_critical_strike_gain": 100}
74
 
75
 
76
  class 九宫八卦阵(FormationGain):
@@ -79,7 +79,7 @@ class 九宫八卦阵(FormationGain):
79
  "strain_gain": 20,
80
  "magical_critical_power_gain": 154
81
  }
82
- rate_gain_attributes = {"magical_critical_strike_gain": 100}
83
 
84
 
85
  class 依山观澜阵(FormationGain):
 
70
  "strain_gain": 20,
71
  "physical_critical_power_gain": 150
72
  }
73
+ rate_gain_attributes = {"physical_critical_strike_gain": 100 * 5}
74
 
75
 
76
  class 九宫八卦阵(FormationGain):
 
79
  "strain_gain": 20,
80
  "magical_critical_power_gain": 154
81
  }
82
+ rate_gain_attributes = {"magical_critical_strike_gain": 100 * 5}
83
 
84
 
85
  class 依山观澜阵(FormationGain):
general/gains/team.py CHANGED
@@ -55,7 +55,7 @@ class 乘龙箭(TeamGain):
55
 
56
 
57
  class 号令三军(TeamGain):
58
- gain_attributes = {"strain_base": 470}
59
 
60
 
61
  class 激雷(TeamGain):
@@ -118,7 +118,7 @@ class 戒火(TeamGain):
118
 
119
  class 朝圣言(TeamGain):
120
  gain_attributes = {"strain_base": 470}
121
- variety_values = {"圣浴明心": 705 - 470}
122
 
123
 
124
  """ 丐帮 """
@@ -147,7 +147,7 @@ class 寒啸千军(TeamGain):
147
 
148
 
149
  class 庄周梦(TeamGain):
150
- gain_attributes = {"strain_base": 60}
151
 
152
 
153
  """ 霸刀 """
@@ -168,6 +168,26 @@ class 配伍(TeamGain):
168
  gain_attributes = {"all_major_gain": 10 * 5}
169
 
170
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
171
  TEAM_GAINS = {
172
  "袖气": 袖气,
173
  "左旋右转": 左旋右转,
 
55
 
56
 
57
  class 号令三军(TeamGain):
58
+ gain_attributes = {"strain_base": (470 + 470 / 2) / 2}
59
 
60
 
61
  class 激雷(TeamGain):
 
118
 
119
  class 朝圣言(TeamGain):
120
  gain_attributes = {"strain_base": 470}
121
+ variety_values = {"圣浴明心": 820 - 470}
122
 
123
 
124
  """ 丐帮 """
 
147
 
148
 
149
  class 庄周梦(TeamGain):
150
+ gain_attributes = {"strain_base": 50}
151
 
152
 
153
  """ 霸刀 """
 
168
  gain_attributes = {"all_major_gain": 10 * 5}
169
 
170
 
171
+ TEAM_GAIN_LIMIT = {
172
+ "左旋右转": {
173
+ "stack": 150
174
+ },
175
+ "号令三军": {
176
+ "stack": 48
177
+ },
178
+ "舍身弘法": {
179
+ "stack": 36
180
+ },
181
+ "朝圣言": {
182
+ "stack": 24
183
+ },
184
+ "振奋": {
185
+ "stack": 100
186
+ },
187
+ "庄周梦": {
188
+ "stack": 150
189
+ }
190
+ }
191
  TEAM_GAINS = {
192
  "袖气": 袖气,
193
  "左旋右转": 左旋右转,
qt/app.py CHANGED
@@ -72,7 +72,10 @@ class MainWindow(QMainWindow):
72
  self.dashboard_widget, self.talents_widget, self.recipes_widget,
73
  self.equipments_widget, self.consumable_widget, self.bonus_widget
74
  )
75
- config_script(parser, self.config_widget, self.equipments_widget)
 
 
 
76
  talents = talents_script(self.talents_widget)
77
  recipes = recipes_script(self.recipes_widget)
78
  equipments = equipments_script(self.equipments_widget)
 
72
  self.dashboard_widget, self.talents_widget, self.recipes_widget,
73
  self.equipments_widget, self.consumable_widget, self.bonus_widget
74
  )
75
+ config_script(
76
+ parser, self.config_widget, self.talents_widget, self.recipes_widget,
77
+ self.equipments_widget, self.consumable_widget, self.bonus_widget
78
+ )
79
  talents = talents_script(self.talents_widget)
80
  recipes = recipes_script(self.recipes_widget)
81
  equipments = equipments_script(self.equipments_widget)
qt/components/__init__.py CHANGED
@@ -77,8 +77,9 @@ class ComboWithLabel(LabelWidget):
77
  self.setLayout(layout)
78
 
79
  self.combo_box = QComboBox()
 
80
  if items:
81
- self.combo_box.addItems(items)
82
  if index:
83
  self.combo_box.setCurrentIndex(index)
84
 
@@ -87,12 +88,17 @@ class ComboWithLabel(LabelWidget):
87
 
88
  layout.addStretch()
89
 
90
- def set_items(self, items, default_index=0):
 
91
  self.combo_box.blockSignals(True)
 
92
  self.combo_box.clear()
93
  self.combo_box.addItems(items)
94
  self.combo_box.blockSignals(False)
95
- self.combo_box.setCurrentIndex(default_index)
 
 
 
96
 
97
 
98
  class RadioWithLabel(LabelWidget):
 
77
  self.setLayout(layout)
78
 
79
  self.combo_box = QComboBox()
80
+ self.items = []
81
  if items:
82
+ self.set_items(items)
83
  if index:
84
  self.combo_box.setCurrentIndex(index)
85
 
 
88
 
89
  layout.addStretch()
90
 
91
+ def set_items(self, items, keep_index=False, default_index=0):
92
+ self.items = items
93
  self.combo_box.blockSignals(True)
94
+ current_text = self.combo_box.currentText()
95
  self.combo_box.clear()
96
  self.combo_box.addItems(items)
97
  self.combo_box.blockSignals(False)
98
+ if keep_index and current_text and current_text in items:
99
+ self.combo_box.setCurrentIndex(items.index(current_text))
100
+ else:
101
+ self.combo_box.setCurrentIndex(default_index)
102
 
103
 
104
  class RadioWithLabel(LabelWidget):
qt/components/bonuses.py CHANGED
@@ -1,3 +1,4 @@
 
1
  from qt.components import ComboWithLabel, SpinWithLabel, RadioWithLabel
2
  from PySide6.QtWidgets import QWidget, QVBoxLayout, QHBoxLayout, QGridLayout, QTabWidget
3
 
@@ -12,8 +13,8 @@ class FormationWidget(QWidget):
12
  layout.addWidget(self.formation)
13
  self.core_rate = SpinWithLabel("四重覆盖(%)", maximum=100)
14
  layout.addWidget(self.core_rate)
15
- self.formation_rate = SpinWithLabel("五重覆盖(%)", maximum=100)
16
- layout.addWidget(self.formation_rate)
17
 
18
 
19
  class TeamGainsWidget(QWidget):
@@ -34,7 +35,7 @@ class TeamGainsWidget(QWidget):
34
  tab_layout.addWidget(self.team_gains["袖气"], 0, 0)
35
 
36
  self.team_gains["左旋右转"] = {
37
- "stack": SpinWithLabel("左旋右转", "层数", maximum=133)
38
  }
39
  tab_layout.addWidget(self.team_gains["左旋右转"]["stack"], 1, 0)
40
  self.team_gains["泠风解怀"] = {
@@ -60,7 +61,7 @@ class TeamGainsWidget(QWidget):
60
  tab_layout.addWidget(self.team_gains["乘龙箭"]["rate"], 2, 0)
61
 
62
  self.team_gains["号令三军"] = {
63
- "stack": SpinWithLabel("号令三军", "层数", maximum=48),
64
  "rate": SpinWithLabel("号令三军", "覆盖(%)", maximum=100)
65
  }
66
  tab_layout.addWidget(self.team_gains["号令三军"]["stack"], 3, 0)
@@ -81,7 +82,7 @@ class TeamGainsWidget(QWidget):
81
  tab_layout.addWidget(self.team_gains["立地成佛"]["rate"], 0, 0)
82
 
83
  self.team_gains["舍身弘法"] = {
84
- "stack": SpinWithLabel("舍身弘法", "层数", maximum=36),
85
  "rate": SpinWithLabel("舍身弘法", "覆盖(%)", maximum=100)
86
  }
87
  tab_layout.addWidget(self.team_gains["舍身弘法"]["stack"], 1, 0)
@@ -114,7 +115,7 @@ class TeamGainsWidget(QWidget):
114
  tabs.addTab(tab, "藏剑")
115
 
116
  self.team_gains["剑锋百锻"] = {
117
- "rate": SpinWithLabel("剑锋百锻", "覆盖(%)", maximum=int(100 / 6))
118
  }
119
  tab_layout.addWidget(self.team_gains["剑锋百锻"]["rate"], 0, 0)
120
 
@@ -135,7 +136,7 @@ class TeamGainsWidget(QWidget):
135
  tab_layout.addWidget(self.team_gains["戒火"], 0, 0)
136
 
137
  self.team_gains["朝圣言"] = {
138
- "stack": SpinWithLabel("朝圣言", "层数", maximum=24),
139
  "rate": SpinWithLabel("朝圣言", "覆盖(%)", maximum=100),
140
  "variety": ComboWithLabel("朝圣言", "种类", ["", "朝圣言", "圣浴明心"])
141
  }
@@ -163,7 +164,7 @@ class TeamGainsWidget(QWidget):
163
  tab_layout.addWidget(self.team_gains["寒啸千军"]["rate"], 1, 0)
164
 
165
  self.team_gains["振奋"] = {
166
- "stack": SpinWithLabel("振奋", "层数"),
167
  "rate": SpinWithLabel("振奋", "覆盖(%)", maximum=100)
168
  }
169
  tab_layout.addWidget(self.team_gains["振奋"]["stack"], 2, 0)
@@ -174,7 +175,7 @@ class TeamGainsWidget(QWidget):
174
  tabs.addTab(tab, "长歌")
175
 
176
  self.team_gains["庄周梦"] = {
177
- "stack": SpinWithLabel("庄周梦", "层数", maximum=133),
178
  "rate": SpinWithLabel("庄周梦", "覆盖(%)", maximum=100)
179
  }
180
  tab_layout.addWidget(self.team_gains["庄周梦"]["stack"], 0, 0)
@@ -199,7 +200,7 @@ class TeamGainsWidget(QWidget):
199
  tab_layout.addWidget(self.team_gains["配伍"]["rate"], 0, 0)
200
 
201
  # self.team_gains["飘黄"] = {
202
- # "rate": SpinWithLabel("飘黄", "覆盖", maximum=int(100 / 6))
203
  # }
204
  # tab_layout.addWidget(self.team_gains["飘黄"]["rate"], 1, 0)
205
 
 
1
+ from general.gains.team import TEAM_GAIN_LIMIT
2
  from qt.components import ComboWithLabel, SpinWithLabel, RadioWithLabel
3
  from PySide6.QtWidgets import QWidget, QVBoxLayout, QHBoxLayout, QGridLayout, QTabWidget
4
 
 
13
  layout.addWidget(self.formation)
14
  self.core_rate = SpinWithLabel("四重覆盖(%)", maximum=100)
15
  layout.addWidget(self.core_rate)
16
+ self.rate = SpinWithLabel("五重覆盖(%)", maximum=100)
17
+ layout.addWidget(self.rate)
18
 
19
 
20
  class TeamGainsWidget(QWidget):
 
35
  tab_layout.addWidget(self.team_gains["袖气"], 0, 0)
36
 
37
  self.team_gains["左旋右转"] = {
38
+ "stack": SpinWithLabel("左旋右转", "层数", maximum=TEAM_GAIN_LIMIT["左旋右转"]["stack"])
39
  }
40
  tab_layout.addWidget(self.team_gains["左旋右转"]["stack"], 1, 0)
41
  self.team_gains["泠风解怀"] = {
 
61
  tab_layout.addWidget(self.team_gains["乘龙箭"]["rate"], 2, 0)
62
 
63
  self.team_gains["号令三军"] = {
64
+ "stack": SpinWithLabel("号令三军", "层数", maximum=TEAM_GAIN_LIMIT["号令三军"]["stack"]),
65
  "rate": SpinWithLabel("号令三军", "覆盖(%)", maximum=100)
66
  }
67
  tab_layout.addWidget(self.team_gains["号令三军"]["stack"], 3, 0)
 
82
  tab_layout.addWidget(self.team_gains["立地成佛"]["rate"], 0, 0)
83
 
84
  self.team_gains["舍身弘法"] = {
85
+ "stack": SpinWithLabel("舍身弘法", "层数", maximum=TEAM_GAIN_LIMIT["舍身弘法"]["stack"]),
86
  "rate": SpinWithLabel("舍身弘法", "覆盖(%)", maximum=100)
87
  }
88
  tab_layout.addWidget(self.team_gains["舍身弘法"]["stack"], 1, 0)
 
115
  tabs.addTab(tab, "藏剑")
116
 
117
  self.team_gains["剑锋百锻"] = {
118
+ "rate": SpinWithLabel("剑锋百锻", "覆盖(%)", maximum=100)
119
  }
120
  tab_layout.addWidget(self.team_gains["剑锋百锻"]["rate"], 0, 0)
121
 
 
136
  tab_layout.addWidget(self.team_gains["戒火"], 0, 0)
137
 
138
  self.team_gains["朝圣言"] = {
139
+ "stack": SpinWithLabel("朝圣言", "层数", maximum=TEAM_GAIN_LIMIT["朝圣言"]["stack"]),
140
  "rate": SpinWithLabel("朝圣言", "覆盖(%)", maximum=100),
141
  "variety": ComboWithLabel("朝圣言", "种类", ["", "朝圣言", "圣浴明心"])
142
  }
 
164
  tab_layout.addWidget(self.team_gains["寒啸千军"]["rate"], 1, 0)
165
 
166
  self.team_gains["振奋"] = {
167
+ "stack": SpinWithLabel("振奋", "层数", maximum=TEAM_GAIN_LIMIT["振奋"]["stack"]),
168
  "rate": SpinWithLabel("振奋", "覆盖(%)", maximum=100)
169
  }
170
  tab_layout.addWidget(self.team_gains["振奋"]["stack"], 2, 0)
 
175
  tabs.addTab(tab, "长歌")
176
 
177
  self.team_gains["庄周梦"] = {
178
+ "stack": SpinWithLabel("庄周梦", "层数", maximum=TEAM_GAIN_LIMIT["庄周梦"]["stack"]),
179
  "rate": SpinWithLabel("庄周梦", "覆盖(%)", maximum=100)
180
  }
181
  tab_layout.addWidget(self.team_gains["庄周梦"]["stack"], 0, 0)
 
200
  tab_layout.addWidget(self.team_gains["配伍"]["rate"], 0, 0)
201
 
202
  # self.team_gains["飘黄"] = {
203
+ # "rate": SpinWithLabel("飘黄", "覆盖", maximum=100)
204
  # }
205
  # tab_layout.addWidget(self.team_gains["飘黄"]["rate"], 1, 0)
206
 
qt/components/config.py CHANGED
@@ -14,9 +14,13 @@ class ConfigWidget(QWidget):
14
 
15
  self.config_select = ComboWithLabel("选择预设方案")
16
  top_layout.addWidget(self.config_select, 1)
17
- self.load_config = QPushButton("加载预设方案")
18
- bottom_layout.addWidget(self.load_config, 1)
 
 
19
  self.config_name = TextWithLabel("设置预设方案")
20
- top_layout.addWidget(self.config_name, 1)
21
  self.save_config = QPushButton("保存预设方案")
22
  bottom_layout.addWidget(self.save_config, 1)
 
 
 
14
 
15
  self.config_select = ComboWithLabel("选择预设方案")
16
  top_layout.addWidget(self.config_select, 1)
17
+ self.config_category = ComboWithLabel("选择导入类别", items=["全部", "装备", "消耗品", "增益"])
18
+ top_layout.addWidget(self.config_category, 1)
19
+ self.load_config = QPushButton("导入预设方案")
20
+ bottom_layout.addWidget(self.load_config, 2)
21
  self.config_name = TextWithLabel("设置预设方案")
22
+ top_layout.addWidget(self.config_name, 2)
23
  self.save_config = QPushButton("保存预设方案")
24
  bottom_layout.addWidget(self.save_config, 1)
25
+ self.delete_config = QPushButton("删除预设方案")
26
+ bottom_layout.addWidget(self.delete_config, 1)
qt/components/consumables.py CHANGED
@@ -34,10 +34,10 @@ class ConsumablesWidget(QWidget):
34
  self.consumables['home_wine'] = self.home_wine
35
  layout.addWidget(self.home_wine, 1, 2)
36
 
37
- self.guild_spread = RadioWithLabel("同泽宴", GUILD_FOOD)
38
  self.consumables['guild_spread'] = self.guild_spread
39
  layout.addWidget(self.guild_spread, 2, 0)
40
- self.guild_food = RadioWithLabel("蒸鱼餐盘", GUILD_SPREAD)
41
  self.consumables['guild_food'] = self.guild_food
42
  layout.addWidget(self.guild_food, 2, 1)
43
  self.spread = ComboWithLabel("宴席")
 
34
  self.consumables['home_wine'] = self.home_wine
35
  layout.addWidget(self.home_wine, 1, 2)
36
 
37
+ self.guild_spread = RadioWithLabel("同泽宴", GUILD_SPREAD)
38
  self.consumables['guild_spread'] = self.guild_spread
39
  layout.addWidget(self.guild_spread, 2, 0)
40
+ self.guild_food = RadioWithLabel("蒸鱼餐盘", GUILD_FOOD)
41
  self.consumables['guild_food'] = self.guild_food
42
  layout.addWidget(self.guild_food, 2, 1)
43
  self.spread = ComboWithLabel("宴席")
qt/components/dashboard.py CHANGED
@@ -9,9 +9,9 @@ class DetailWidget(QWidget):
9
  super().__init__()
10
  layout = QVBoxLayout(self)
11
  self.details = {}
12
- self.skill_combo = ComboWithLabel("选择技能")
13
  layout.addWidget(self.skill_combo)
14
- self.status_combo = ComboWithLabel("选择增益")
15
  layout.addWidget(self.status_combo)
16
  detail_table = QWidget()
17
  detail_table_layout = QHBoxLayout(detail_table)
 
9
  super().__init__()
10
  layout = QVBoxLayout(self)
11
  self.details = {}
12
+ self.skill_combo = ComboWithLabel("选择技能", info="技能名字/技能ID-技能等级-技能层数")
13
  layout.addWidget(self.skill_combo)
14
+ self.status_combo = ComboWithLabel("选择增益", info="增益名字/增益ID-增益等级-增益层数")
15
  layout.addWidget(self.status_combo)
16
  detail_table = QWidget()
17
  detail_table_layout = QHBoxLayout(detail_table)
qt/components/equipments.py CHANGED
@@ -16,6 +16,7 @@ class EquipmentWidget(QWidget):
16
  self.equipment_json = json.load(open(os.path.join(EQUIPMENTS_DIR, self.position), encoding="utf-8"))
17
  self.equipment_mapping = {v['id']: k for k, v in self.equipment_json.items()}
18
  self.enchant_json = json.load(open(os.path.join(ENCHANTS_DIR, self.position), encoding="utf-8"))
 
19
  self.equipment = ComboWithLabel("装备")
20
  layout.addWidget(self.equipment)
21
 
@@ -32,7 +33,7 @@ class EquipmentWidget(QWidget):
32
  self.enchant = None
33
  else:
34
  self.enchant = ComboWithLabel("附魔")
35
- self.enchant.combo_box.addItems([""] + list(self.enchant_json))
36
  input_layout.addWidget(self.enchant, 0, 0, 1, 2)
37
 
38
  if self.position not in SPECIAL_ENCHANT_POSITIONS:
@@ -61,7 +62,8 @@ class EquipmentWidget(QWidget):
61
  self.stones_json = json.load(open(STONES_DIR, encoding="utf-8"))
62
 
63
  self.stone_level = ComboWithLabel(
64
- "五彩石等级", items=[str(i) for i in range(MAX_STONE_LEVEL + 1)])
 
65
  self.stone_attrs = []
66
  input_layout.addWidget(self.stone_level, 2, 0)
67
  for i in range(MAX_STONE_ATTR):
 
16
  self.equipment_json = json.load(open(os.path.join(EQUIPMENTS_DIR, self.position), encoding="utf-8"))
17
  self.equipment_mapping = {v['id']: k for k, v in self.equipment_json.items()}
18
  self.enchant_json = json.load(open(os.path.join(ENCHANTS_DIR, self.position), encoding="utf-8"))
19
+ self.enchant_mapping = {v['id']: k for k, v in self.enchant_json.items()}
20
  self.equipment = ComboWithLabel("装备")
21
  layout.addWidget(self.equipment)
22
 
 
33
  self.enchant = None
34
  else:
35
  self.enchant = ComboWithLabel("附魔")
36
+ self.enchant.set_items([""] + list(self.enchant_json))
37
  input_layout.addWidget(self.enchant, 0, 0, 1, 2)
38
 
39
  if self.position not in SPECIAL_ENCHANT_POSITIONS:
 
62
  self.stones_json = json.load(open(STONES_DIR, encoding="utf-8"))
63
 
64
  self.stone_level = ComboWithLabel(
65
+ "五彩石等级", items=[str(i) for i in range(MAX_STONE_LEVEL + 1)]
66
+ )
67
  self.stone_attrs = []
68
  input_layout.addWidget(self.stone_level, 2, 0)
69
  for i in range(MAX_STONE_ATTR):
qt/scripts/bonuses.py CHANGED
@@ -24,7 +24,7 @@ def bonuses_script(parser: Parser, bonuses_widget: BonusesWidget):
24
  widget = bonuses_widget.formation
25
  formation = widget.formation.combo_box.currentText()
26
  core_rate = widget.core_rate.spin_box.value()
27
- formation_rate = widget.formation_rate.spin_box.value()
28
 
29
  if formation == parser.school.formation:
30
  widget.core_rate.show()
@@ -37,9 +37,9 @@ def bonuses_script(parser: Parser, bonuses_widget: BonusesWidget):
37
  else:
38
  bonuses.pop("formation", None)
39
 
40
- bonuses_widget.formation.formation.combo_box.currentIndexChanged.connect(formation_update)
41
  bonuses_widget.formation.core_rate.spin_box.valueChanged.connect(formation_update)
42
- bonuses_widget.formation.formation_rate.spin_box.valueChanged.connect(formation_update)
43
 
44
  def radio_update(label):
45
  widget = bonuses_widget.team_gains[label]
@@ -75,7 +75,7 @@ def bonuses_script(parser: Parser, bonuses_widget: BonusesWidget):
75
  elif isinstance(bonus_widget, dict):
76
  for sub_bonus_widget in bonus_widget.values():
77
  if isinstance(sub_bonus_widget, ComboWithLabel):
78
- sub_bonus_widget.combo_box.currentIndexChanged.connect(combine_update(bonus_label))
79
  elif isinstance(sub_bonus_widget, SpinWithLabel):
80
  sub_bonus_widget.spin_box.valueChanged.connect(combine_update(bonus_label))
81
  else:
 
24
  widget = bonuses_widget.formation
25
  formation = widget.formation.combo_box.currentText()
26
  core_rate = widget.core_rate.spin_box.value()
27
+ formation_rate = widget.rate.spin_box.value()
28
 
29
  if formation == parser.school.formation:
30
  widget.core_rate.show()
 
37
  else:
38
  bonuses.pop("formation", None)
39
 
40
+ bonuses_widget.formation.formation.combo_box.currentTextChanged.connect(formation_update)
41
  bonuses_widget.formation.core_rate.spin_box.valueChanged.connect(formation_update)
42
+ bonuses_widget.formation.rate.spin_box.valueChanged.connect(formation_update)
43
 
44
  def radio_update(label):
45
  widget = bonuses_widget.team_gains[label]
 
75
  elif isinstance(bonus_widget, dict):
76
  for sub_bonus_widget in bonus_widget.values():
77
  if isinstance(sub_bonus_widget, ComboWithLabel):
78
+ sub_bonus_widget.combo_box.currentTextChanged.connect(combine_update(bonus_label))
79
  elif isinstance(sub_bonus_widget, SpinWithLabel):
80
  sub_bonus_widget.spin_box.valueChanged.connect(combine_update(bonus_label))
81
  else:
qt/scripts/config.py CHANGED
@@ -1,21 +1,26 @@
1
  import json
2
  import os
3
 
 
 
4
  from qt.components.config import ConfigWidget
5
  from qt.components.equipments import EquipmentsWidget
 
 
 
6
  from utils.parser import Parser
7
 
8
-
9
  if not os.path.exists("config"):
10
  CONFIG = {}
11
  else:
12
  CONFIG = json.load(open("config", encoding="utf-8"))
13
 
14
 
15
- def config_script(parser: Parser, config_widget: ConfigWidget, equipments_widget: EquipmentsWidget):
16
- def load_config():
17
- config_name = config_widget.config_select.combo_box.currentText()
18
- config = CONFIG.get(parser.school.school, {}).get(config_name, {})
 
19
  if not config:
20
  return
21
 
@@ -43,18 +48,56 @@ def config_script(parser: Parser, config_widget: ConfigWidget, equipments_widget
43
  index = equipment.stone_attrs[i].combo_box.findText(config[label]['stone_attrs'][i])
44
  stone_attr.combo_box.setCurrentIndex(index)
45
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
46
  config_widget.config_name.text_browser.setText(config_name)
47
 
48
  config_widget.load_config.clicked.connect(load_config)
49
 
50
- def save_config():
51
- config_name = config_widget.config_name.text_browser.text()
52
- if parser.school.school not in CONFIG:
53
- CONFIG[parser.school.school] = {}
54
- if config_name not in CONFIG[parser.school.school]:
55
- CONFIG[parser.school.school][config_name] = {}
56
- config = CONFIG[parser.school.school][config_name]
57
-
58
  for label, equipment in equipments_widget.items():
59
  config[label] = {}
60
  if not (text := equipment.equipment.combo_box.currentText()):
@@ -76,13 +119,69 @@ def config_script(parser: Parser, config_widget: ConfigWidget, equipments_widget
76
  config[label]['stone_attrs'] = [
77
  stone_attr.combo_box.currentText() for stone_attr in equipment.stone_attrs
78
  ]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
79
  json.dump(CONFIG, open("config", "w", encoding="utf-8"), ensure_ascii=False)
80
 
81
- config_choices = list(CONFIG.get(parser.school.school, {}))
82
- if current_select := config_widget.config_select.combo_box.currentText():
83
- default_index = config_choices.index(current_select)
84
- else:
85
- default_index = -1
86
- config_widget.config_select.set_items(config_choices, default_index=default_index)
87
 
88
  config_widget.save_config.clicked.connect(save_config)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  import json
2
  import os
3
 
4
+ from qt.components import ComboWithLabel, RadioWithLabel, SpinWithLabel
5
+ from qt.components.bonuses import BonusesWidget
6
  from qt.components.config import ConfigWidget
7
  from qt.components.equipments import EquipmentsWidget
8
+ from qt.components.consumables import ConsumablesWidget
9
+ from qt.components.recipes import RecipesWidget
10
+ from qt.components.talents import TalentsWidget
11
  from utils.parser import Parser
12
 
 
13
  if not os.path.exists("config"):
14
  CONFIG = {}
15
  else:
16
  CONFIG = json.load(open("config", encoding="utf-8"))
17
 
18
 
19
+ def config_script(
20
+ parser: Parser, config_widget: ConfigWidget,
21
+ talent_widget: TalentsWidget, recipe_widget: RecipesWidget,
22
+ equipments_widget: EquipmentsWidget, consumable_widget: ConsumablesWidget, bonus_widget: BonusesWidget):
23
+ def load_equipments(config):
24
  if not config:
25
  return
26
 
 
48
  index = equipment.stone_attrs[i].combo_box.findText(config[label]['stone_attrs'][i])
49
  stone_attr.combo_box.setCurrentIndex(index)
50
 
51
+ def load_consumables(config):
52
+ for label, consumable in consumable_widget.items():
53
+ if isinstance(consumable, ComboWithLabel):
54
+ consumable.combo_box.setCurrentText(config[label])
55
+ elif isinstance(consumable, RadioWithLabel):
56
+ if consumable.radio_button.isChecked() != config[label]:
57
+ consumable.radio_button.click()
58
+
59
+ def load_bonuses(config):
60
+ bonus_widget.formation.formation.combo_box.setCurrentText(config['formation']['formation'])
61
+ bonus_widget.formation.core_rate.spin_box.setValue(config['formation']['core_rate'])
62
+ bonus_widget.formation.rate.spin_box.setValue(config['formation']['rate'])
63
+ for label, team_gain in bonus_widget.team_gains.items():
64
+ if isinstance(team_gain, RadioWithLabel):
65
+ if team_gain.radio_button.isChecked() != config['team_gains'][label]:
66
+ team_gain.radio_button.click()
67
+ elif isinstance(team_gain, dict):
68
+ for sub_label, sub_team_gain in team_gain.items():
69
+ if isinstance(sub_team_gain, ComboWithLabel):
70
+ sub_team_gain.combo_box.setCurrentText(config['team_gains'][label][sub_label])
71
+ elif isinstance(sub_team_gain, SpinWithLabel):
72
+ sub_team_gain.spin_box.setValue(config['team_gains'][label][sub_label])
73
+
74
+ def load_recipes(config):
75
+ for i, recipes in enumerate(config):
76
+ for selected_item in recipe_widget.recipes[i].list.selectedItems():
77
+ selected_item.setSelected(False)
78
+
79
+ def load_config():
80
+ config_name = config_widget.config_select.combo_box.currentText()
81
+ config = CONFIG.get(parser.school.school, {}).get(config_name, {})
82
+ if not config:
83
+ return
84
+ category = config_widget.config_category.combo_box.currentText()
85
+ if category == "全部":
86
+ load_equipments(config.get("equipments"))
87
+ load_consumables(config.get("consumables"))
88
+ load_bonuses(config.get("bonuses"))
89
+ elif category == "装备":
90
+ load_equipments(config.get("equipments"))
91
+ elif category == "消耗品":
92
+ load_consumables(config.get("consumables"))
93
+ elif category == "增益":
94
+ load_bonuses(config.get("bonuses"))
95
+
96
  config_widget.config_name.text_browser.setText(config_name)
97
 
98
  config_widget.load_config.clicked.connect(load_config)
99
 
100
+ def save_equipments(config):
 
 
 
 
 
 
 
101
  for label, equipment in equipments_widget.items():
102
  config[label] = {}
103
  if not (text := equipment.equipment.combo_box.currentText()):
 
119
  config[label]['stone_attrs'] = [
120
  stone_attr.combo_box.currentText() for stone_attr in equipment.stone_attrs
121
  ]
122
+
123
+ def save_consumables(config):
124
+ for label, consumable in consumable_widget.items():
125
+ if isinstance(consumable, ComboWithLabel):
126
+ config[label] = consumable.combo_box.currentText()
127
+ elif isinstance(consumable, RadioWithLabel):
128
+ config[label] = consumable.radio_button.isChecked()
129
+
130
+ def save_bonuses(config):
131
+ config['formation']['formation'] = bonus_widget.formation.formation.combo_box.currentText()
132
+ config['formation']['core_rate'] = bonus_widget.formation.core_rate.spin_box.value()
133
+ config['formation']['rate'] = bonus_widget.formation.rate.spin_box.value()
134
+ for label, team_gain in bonus_widget.team_gains.items():
135
+ if isinstance(team_gain, RadioWithLabel):
136
+ config['team_gains'][label] = team_gain.radio_button.isChecked()
137
+ elif isinstance(team_gain, dict):
138
+ config['team_gains'][label] = {}
139
+ for sub_label, sub_team_gain in team_gain.items():
140
+ if isinstance(sub_team_gain, ComboWithLabel):
141
+ config['team_gains'][label][sub_label] = sub_team_gain.combo_box.currentText()
142
+ elif isinstance(sub_team_gain, SpinWithLabel):
143
+ config['team_gains'][label][sub_label] = sub_team_gain.spin_box.value()
144
+
145
+ def save_recipes(config):
146
+ for recipe in recipe_widget.values():
147
+ if selected_items := recipe.list.selectedItems():
148
+ config.append(selected_items)
149
+
150
+ def save_config():
151
+ config_name = config_widget.config_name.text_browser.text()
152
+ if parser.school.school not in CONFIG:
153
+ CONFIG[parser.school.school] = {}
154
+ if config_name not in CONFIG[parser.school.school]:
155
+ CONFIG[parser.school.school][config_name] = {
156
+ "equipments": {},
157
+ "consumables": {},
158
+ "bonuses": {"formation": {}, "team_gains": {}},
159
+ "talents": [],
160
+ "recipes": []
161
+ }
162
+
163
+ save_equipments(CONFIG[parser.school.school][config_name]['equipments'])
164
+ save_consumables(CONFIG[parser.school.school][config_name]['consumables'])
165
+ save_bonuses(CONFIG[parser.school.school][config_name]['bonuses'])
166
+ # save_recipes(CONFIG[parser.school.school][config_name]['recipes'])
167
  json.dump(CONFIG, open("config", "w", encoding="utf-8"), ensure_ascii=False)
168
 
169
+ config_widget.config_select.set_items(
170
+ list(CONFIG.get(parser.school.school, {})), keep_index=True, default_index=-1
171
+ )
 
 
 
172
 
173
  config_widget.save_config.clicked.connect(save_config)
174
+
175
+ def delete_config():
176
+ config_name = config_widget.config_name.text_browser.text()
177
+ if config_name not in CONFIG.get(parser.school.school, {}):
178
+ return
179
+
180
+ CONFIG[parser.school.school].pop(config_name)
181
+
182
+ json.dump(CONFIG, open("config", "w", encoding="utf-8"), ensure_ascii=False)
183
+
184
+ config_widget.config_select.set_items(list(CONFIG.get(parser.school.school, {})), default_index=-1)
185
+ config_widget.config_name.text_browser.clear()
186
+
187
+ config_widget.delete_config.clicked.connect(delete_config)
qt/scripts/consumables.py CHANGED
@@ -45,7 +45,7 @@ def consumables_script(consumables_widget: ConsumablesWidget):
45
  for consumable_label, consumable_widget in consumables_widget.items():
46
 
47
  if isinstance(consumable_widget, ComboWithLabel):
48
- consumable_widget.combo_box.currentIndexChanged.connect(consumable_combo_update(consumable_label))
49
  elif isinstance(consumable_widget, RadioWithLabel):
50
  consumable_widget.radio_button.clicked.connect(consumable_radio_update(consumable_label))
51
 
 
45
  for consumable_label, consumable_widget in consumables_widget.items():
46
 
47
  if isinstance(consumable_widget, ComboWithLabel):
48
+ consumable_widget.combo_box.currentTextChanged.connect(consumable_combo_update(consumable_label))
49
  elif isinstance(consumable_widget, RadioWithLabel):
50
  consumable_widget.radio_button.clicked.connect(consumable_radio_update(consumable_label))
51
 
qt/scripts/dashboard.py CHANGED
@@ -99,25 +99,15 @@ def dashboard_script(parser: Parser,
99
 
100
  def set_skills():
101
  detail_widget = dashboard_widget.detail_widget
102
- skill = detail_widget.skill_combo.combo_box.currentText()
103
- skill_choices = list(detail_widget.details)
104
- if skill in skill_choices:
105
- default_index = skill_choices.index(skill)
106
- else:
107
- default_index = -1
108
- detail_widget.skill_combo.set_items(skill_choices, default_index=default_index)
109
  set_status(None)
110
 
111
  def set_status(_):
112
  detail_widget = dashboard_widget.detail_widget
113
  skill = detail_widget.skill_combo.combo_box.currentText()
114
- status = detail_widget.status_combo.combo_box.currentText()
115
- status_choices = list(detail_widget.details.get(skill, {}))
116
- if status in status_choices:
117
- default_index = status_choices.index(status)
118
- else:
119
- default_index = -1
120
- detail_widget.status_combo.set_items(status_choices, default_index=default_index)
121
  set_detail(None)
122
 
123
  dashboard_widget.detail_widget.skill_combo.combo_box.currentTextChanged.connect(set_status)
 
99
 
100
  def set_skills():
101
  detail_widget = dashboard_widget.detail_widget
102
+ detail_widget.skill_combo.set_items(list(detail_widget.details), keep_index=True, default_index=-1)
 
 
 
 
 
 
103
  set_status(None)
104
 
105
  def set_status(_):
106
  detail_widget = dashboard_widget.detail_widget
107
  skill = detail_widget.skill_combo.combo_box.currentText()
108
+ detail_widget.status_combo.set_items(
109
+ list(detail_widget.details.get(skill, {})), keep_index=True, default_index=-1
110
+ )
 
 
 
 
111
  set_detail(None)
112
 
113
  dashboard_widget.detail_widget.skill_combo.combo_box.currentTextChanged.connect(set_status)
qt/scripts/top.py CHANGED
@@ -10,8 +10,6 @@ from qt.components.equipments import EquipmentsWidget
10
  from qt.components.recipes import RecipesWidget
11
  from qt.components.talents import TalentsWidget
12
  from qt.components.top import TopWidget
13
- # from general.consumables import FOODS, POTIONS, WEAPON_ENCHANTS, SPREADS, SNACKS, WINES
14
- # from general.gains.formation import FORMATIONS
15
  from qt.constant import MAX_RECIPES, MAX_STONE_LEVEL
16
  from qt.scripts.config import CONFIG
17
  from utils.parser import Parser
@@ -42,8 +40,10 @@ def top_script(
42
  for i, talent_widget in enumerate(talents_widget.values()):
43
  talents = school.talents[i]
44
  default_index = talents.index(parser.select_talents[i]) + 1
45
- talent_widget.set_items([""] + [school.talent_decoder[talent] for talent in talents],
46
- default_index=default_index)
 
 
47
 
48
  """ Update recipe options """
49
  for recipe_widget in recipes_widget.values():
@@ -58,7 +58,7 @@ def top_script(
58
  recipes_widget[i].show()
59
 
60
  """ Update equipment options """
61
- for equipment_widget in equipments_widget.values():
62
  choices = [""]
63
  for name, detail in equipment_widget.equipment_json.items():
64
  if detail['kind'] not in (school.kind, school.major):
@@ -66,28 +66,34 @@ def top_script(
66
  if detail['school'] not in ("精简", "通用", school.school):
67
  continue
68
  choices.append(name)
69
- current_equipment = equipment_widget.equipment.combo_box.currentText()
70
- if current_equipment in choices:
71
- default_index = choices.index(current_equipment)
72
- else:
73
- default_index = -1
74
- equipment_widget.equipment.set_items(choices, default_index=default_index)
75
-
76
  if equipment_widget.stones_json:
77
- equipment_widget.stone_level.combo_box.setCurrentIndex(MAX_STONE_LEVEL)
 
 
 
 
 
 
 
 
 
 
 
 
78
 
79
  """ Update consumable options """
80
- consumables_widget.major_food.set_items([""] + FOODS[school.major])
81
- consumables_widget.minor_food.set_items([""] + FOODS[school.kind] + FOODS[""])
82
- consumables_widget.major_potion.set_items([""] + POTIONS[school.major])
83
- consumables_widget.minor_potion.set_items([""] + POTIONS[school.kind] + POTIONS[""])
84
- consumables_widget.weapon_enchant.set_items([""] + WEAPON_ENCHANTS[school.kind])
85
- consumables_widget.home_snack.set_items([""] + SNACKS[school.kind] + SNACKS[""])
86
- consumables_widget.home_wine.set_items([""] + WINES[school.major] + WINES[""])
87
- consumables_widget.spread.set_items([""] + SPREADS[school.major] + SPREADS[school.kind])
88
 
89
  """ Update bonus options """
90
- bonus_widget.formation.formation.set_items([""] + FORMATIONS[school.kind] + FORMATIONS[""])
91
  config_widget.show()
92
  bottom_widget.show()
93
 
 
10
  from qt.components.recipes import RecipesWidget
11
  from qt.components.talents import TalentsWidget
12
  from qt.components.top import TopWidget
 
 
13
  from qt.constant import MAX_RECIPES, MAX_STONE_LEVEL
14
  from qt.scripts.config import CONFIG
15
  from utils.parser import Parser
 
40
  for i, talent_widget in enumerate(talents_widget.values()):
41
  talents = school.talents[i]
42
  default_index = talents.index(parser.select_talents[i]) + 1
43
+ talent_widget.set_items(
44
+ [""] + [school.talent_decoder[talent] for talent in talents],
45
+ keep_index=True, default_index=default_index
46
+ )
47
 
48
  """ Update recipe options """
49
  for recipe_widget in recipes_widget.values():
 
58
  recipes_widget[i].show()
59
 
60
  """ Update equipment options """
61
+ for label, equipment_widget in equipments_widget.items():
62
  choices = [""]
63
  for name, detail in equipment_widget.equipment_json.items():
64
  if detail['kind'] not in (school.kind, school.major):
 
66
  if detail['school'] not in ("精简", "通用", school.school):
67
  continue
68
  choices.append(name)
69
+ equipment_widget.equipment.set_items(choices, keep_index=True)
 
 
 
 
 
 
70
  if equipment_widget.stones_json:
71
+ if not (current_index := equipment_widget.stone_level.combo_box.currentIndex()):
72
+ current_index = MAX_STONE_LEVEL
73
+ equipment_widget.stone_level.combo_box.setCurrentIndex(current_index)
74
+ if select_equipment := parser.select_equipments.get(label, {}):
75
+ if equipment := equipment_widget.equipment_mapping.get(select_equipment['equipment']):
76
+ if equipment in equipment_widget.equipment.items:
77
+ equipment_widget.equipment.combo_box.setCurrentText(equipment)
78
+ if enchant := equipment_widget.enchant_mapping.get(select_equipment['enchant']):
79
+ if enchant in equipment_widget.enchant.items:
80
+ equipment_widget.enchant.combo_box.setCurrentText(enchant)
81
+ equipment_widget.strength_level.combo_box.setCurrentIndex(select_equipment['strength_level'])
82
+ for i, embed_level in enumerate(select_equipment['embed_levels']):
83
+ equipment_widget.embed_levels[i].combo_box.setCurrentIndex(embed_level)
84
 
85
  """ Update consumable options """
86
+ consumables_widget.major_food.set_items([""] + FOODS[school.major], keep_index=True)
87
+ consumables_widget.minor_food.set_items([""] + FOODS[school.kind] + FOODS[""], keep_index=True)
88
+ consumables_widget.major_potion.set_items([""] + POTIONS[school.major], keep_index=True)
89
+ consumables_widget.minor_potion.set_items([""] + POTIONS[school.kind] + POTIONS[""], keep_index=True)
90
+ consumables_widget.weapon_enchant.set_items([""] + WEAPON_ENCHANTS[school.kind], keep_index=True)
91
+ consumables_widget.home_snack.set_items([""] + SNACKS[school.kind] + SNACKS[""], keep_index=True)
92
+ consumables_widget.home_wine.set_items([""] + WINES[school.major] + WINES[""], keep_index=True)
93
+ consumables_widget.spread.set_items([""] + SPREADS[school.major] + SPREADS[school.kind], keep_index=True)
94
 
95
  """ Update bonus options """
96
+ bonus_widget.formation.formation.set_items([""] + FORMATIONS[school.kind] + FORMATIONS[""], keep_index=True)
97
  config_widget.show()
98
  bottom_widget.show()
99
 
requirements.txt ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ pyside6==6.7.0
2
+ tqdm==4.66.2
3
+ requests==2.31.0
schools/bei_ao_jue/skills.py CHANGED
@@ -343,7 +343,7 @@ SKILLS: Dict[int, Skill | dict] = {
343
  "attack_power_cof": [60 * 1.45 * 1.1 * 0.7] +
344
  [(60 + (i - 1) * 10) * 1.45 * 1.1 * 0.7 for i in range(2, 10)] +
345
  [160 * 1.45 * 0.9 * 1.1 * 0.7],
346
- "weapon_damage_cof": 1024 * 1.45 * 0.25
347
  },
348
  37458: {
349
  "skill_class": PhysicalDamage,
 
343
  "attack_power_cof": [60 * 1.45 * 1.1 * 0.7] +
344
  [(60 + (i - 1) * 10) * 1.45 * 1.1 * 0.7 for i in range(2, 10)] +
345
  [160 * 1.45 * 0.9 * 1.1 * 0.7],
346
+ # "weapon_damage_cof": 1024 * 1.45 * 0.25
347
  },
348
  37458: {
349
  "skill_class": PhysicalDamage,
schools/bei_ao_jue/talents.py CHANGED
@@ -10,13 +10,15 @@ class 冥鼓(Gain):
10
  for skill_id in (16760, 16382, 20991):
11
  skills[skill_id].skill_damage_addition += 205
12
  skills[skill_id].skill_shield_gain -= 512
13
- skills[32823].skill_shield_gain = [0, 0, -512, -512]
 
14
 
15
  def sub_skills(self, skills: Dict[int, Skill]):
16
  for skill_id in [16760, 16382, 20991]:
17
  skills[skill_id].skill_damage_addition -= 205
18
  skills[skill_id].skill_shield_gain += 512
19
  skills[32823].skill_shield_gain = 0
 
20
 
21
 
22
  class 阳关(Gain):
 
10
  for skill_id in (16760, 16382, 20991):
11
  skills[skill_id].skill_damage_addition += 205
12
  skills[skill_id].skill_shield_gain -= 512
13
+ skills[32823].skill_shield_gain = [-512, 0, 0, -512]
14
+ skills[37458].skill_shield_gain -= 512
15
 
16
  def sub_skills(self, skills: Dict[int, Skill]):
17
  for skill_id in [16760, 16382, 20991]:
18
  skills[skill_id].skill_damage_addition -= 205
19
  skills[skill_id].skill_shield_gain += 512
20
  skills[32823].skill_shield_gain = 0
21
+ skills[37458].skill_shield_gain += 512
22
 
23
 
24
  class 阳关(Gain):
utils/analyzer.py CHANGED
@@ -118,7 +118,6 @@ def analyze_details(record, duration: int, attribute: Attribute, school: School)
118
  skill_total.gradients[attr] += residual_damage * len(timeline)
119
 
120
  total.expected_damage += skill_total.expected_damage
121
- total.count += skill_total.count
122
  skill_summary.expected_damage += skill_total.expected_damage
123
  skill_summary.critical_count += skill_total.critical_strike
124
  skill_summary.count += skill_total.count
 
118
  skill_total.gradients[attr] += residual_damage * len(timeline)
119
 
120
  total.expected_damage += skill_total.expected_damage
 
121
  skill_summary.expected_damage += skill_total.expected_damage
122
  skill_summary.critical_count += skill_total.critical_strike
123
  skill_summary.count += skill_total.count
utils/parser.py CHANGED
@@ -76,6 +76,23 @@ SUPPORT_SCHOOL = {
76
  }
77
 
78
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
79
  class Parser:
80
  records: list
81
  status: dict
@@ -90,6 +107,7 @@ class Parser:
90
  fight_flag: bool
91
 
92
  select_talents: List[int]
 
93
 
94
  school: School | None
95
 
@@ -135,11 +153,23 @@ class Parser:
135
 
136
  self.school = None
137
 
 
 
 
 
 
 
 
 
 
 
 
138
  def parse_info(self, detail):
139
  if isinstance(detail, list):
140
  self.school = SUPPORT_SCHOOL.get(detail[3])
141
  if not self.school:
142
  raise AttributeError(f"Cannot support {detail[3]} now")
 
143
  self.select_talents = [row[1] for row in detail[6]]
144
  return self.school
145
 
 
76
  }
77
 
78
 
79
+ LABEL_MAPPING = {
80
+ 2: "远程武器",
81
+ 3: "上衣",
82
+ 4: "帽子",
83
+ 5: "项链",
84
+ 6: "戒指1",
85
+ 7: "戒指2",
86
+ 8: "腰带",
87
+ 9: "腰坠",
88
+ 10: "下装",
89
+ 11: "鞋子",
90
+ 12: "护腕",
91
+ 0: "近战武器"
92
+ }
93
+ EMBED_MAPPING = {(5, 24449 - i): 8 - i for i in range(8)}
94
+
95
+
96
  class Parser:
97
  records: list
98
  status: dict
 
107
  fight_flag: bool
108
 
109
  select_talents: List[int]
110
+ select_equipments: Dict[int, Dict[str, int | list]]
111
 
112
  school: School | None
113
 
 
153
 
154
  self.school = None
155
 
156
+ def parse_equipments(self, detail):
157
+ self.select_equipments = {}
158
+ for row in detail:
159
+ if not (label := LABEL_MAPPING.get(row[0])):
160
+ continue
161
+ select_equipment = self.select_equipments[label] = {}
162
+ select_equipment['equipment'] = row[2]
163
+ select_equipment['strength_level'] = row[3]
164
+ select_equipment['embed_levels'] = [EMBED_MAPPING.get(tuple(e), 0) for e in row[4]]
165
+ select_equipment['enchant'] = row[5]
166
+
167
  def parse_info(self, detail):
168
  if isinstance(detail, list):
169
  self.school = SUPPORT_SCHOOL.get(detail[3])
170
  if not self.school:
171
  raise AttributeError(f"Cannot support {detail[3]} now")
172
+ self.parse_equipments(detail[5])
173
  self.select_talents = [row[1] for row in detail[6]]
174
  return self.school
175