ango commited on
Commit
8cd632a
1 Parent(s): 7132222

:bug:(bugfix): fix merge conflict

Browse files
Files changed (1) hide show
  1. utils/parser.py +150 -100
utils/parser.py CHANGED
@@ -4,19 +4,17 @@ from base.constant import FRAME_PER_SECOND
4
  from schools import *
5
  from utils.lua import parse
6
 
7
- FRAME_TYPE, PLAYER_ID_TYPE, PLAYER_NAME_TYPE, PET_ID_TYPE = int, int, int, int
8
  CASTER_ID_TYPE = PLAYER_ID_TYPE | PET_ID_TYPE
9
  SKILL_ID_TYPE, SKILL_LEVEL_TYPE, SKILL_STACK_TYPE, SKILL_CRITICAL_TYPE = int, int, int, bool
10
- SKILL_BUFFER_TYPE = Tuple[SKILL_ID_TYPE, SKILL_LEVEL_TYPE, SKILL_CRITICAL_TYPE]
11
  SKILL_TYPE = Tuple[SKILL_ID_TYPE, SKILL_LEVEL_TYPE, SKILL_STACK_TYPE]
12
  BUFF_ID_TYPE, BUFF_LEVEL_TYPE, BUFF_STACK_TYPE = int, int, int
13
  BUFF_TYPE = Tuple[BUFF_ID_TYPE, BUFF_LEVEL_TYPE]
14
- STATUS_TYPE = Tuple[BUFF_ID_TYPE, BUFF_LEVEL_TYPE, BUFF_STACK_TYPE]
15
 
16
- SNAPSHOT_TYPE = Dict[SKILL_ID_TYPE | PET_ID_TYPE, Dict[BUFF_TYPE, BUFF_STACK_TYPE]]
17
-
18
- TIMELINE_TYPE = List[Tuple[FRAME_TYPE, SKILL_CRITICAL_TYPE]]
19
- SUB_RECORD_TYPE = Dict[Tuple[tuple, tuple], TIMELINE_TYPE]
20
  RECORD_TYPE = Dict[SKILL_TYPE, SUB_RECORD_TYPE]
21
 
22
  LABEL_MAPPING = {
@@ -35,30 +33,33 @@ LABEL_MAPPING = {
35
  }
36
  EMBED_MAPPING: Dict[tuple, int] = {(5, 24449 - i): 8 - i for i in range(8)}
37
 
38
- BUFFER_DELAY = 0
39
-
40
 
41
  class Parser:
42
  current_player: PLAYER_ID_TYPE
43
  current_caster: CASTER_ID_TYPE
 
 
44
  current_frame: FRAME_TYPE
45
- frames: List[FRAME_TYPE]
46
 
47
- id2name: Dict[PLAYER_ID_TYPE, PLAYER_NAME_TYPE]
48
- name2id: Dict[PLAYER_NAME_TYPE, PLAYER_ID_TYPE]
49
  pets: Dict[PET_ID_TYPE, PLAYER_ID_TYPE]
50
- records: Dict[PLAYER_ID_TYPE, RECORD_TYPE]
 
 
 
51
 
52
- hidden_buffs: Dict[PLAYER_ID_TYPE, Dict[BUFF_TYPE, FRAME_TYPE]]
53
- shift_status: Dict[FRAME_TYPE, Dict[PLAYER_ID_TYPE, Dict[BUFF_TYPE, BUFF_STACK_TYPE]]]
54
- status: Dict[PLAYER_ID_TYPE, Dict[BUFF_TYPE, BUFF_STACK_TYPE]]
55
 
56
- stacks: Dict[PLAYER_ID_TYPE, Dict[SKILL_ID_TYPE, int]]
57
- ticks: Dict[PLAYER_ID_TYPE, Dict[SKILL_ID_TYPE, int]]
58
 
59
- snapshot: Dict[PLAYER_ID_TYPE, SNAPSHOT_TYPE]
60
- last_dot: Dict[PLAYER_ID_TYPE, Dict[SKILL_ID_TYPE, Tuple[SKILL_TYPE, Tuple[tuple, tuple]]]]
61
- next_dot: Dict[PLAYER_ID_TYPE, Dict[SKILL_ID_TYPE, int]]
 
 
62
 
63
  start_frame: FRAME_TYPE
64
  end_frame: FRAME_TYPE
@@ -66,43 +67,59 @@ class Parser:
66
  select_talents: Dict[PLAYER_ID_TYPE, List[int]]
67
  select_equipments: Dict[PLAYER_ID_TYPE, Dict[int, Dict[str, int | list]]]
68
 
69
- school: Dict[PLAYER_ID_TYPE, School]
 
70
 
71
  @property
72
  def current_school(self):
73
- return self.school[self.current_player]
 
 
 
 
74
 
75
  @property
76
  def current_records(self):
77
- return self.records[self.current_player]
78
 
79
  @property
80
  def current_hidden_buffs(self):
81
- return self.hidden_buffs[self.current_player]
 
 
 
 
82
 
83
  @property
84
- def current_status(self):
85
- return self.status[self.current_player]
86
 
87
  @property
88
  def current_snapshot(self):
89
- return self.snapshot[self.current_player]
 
 
 
 
 
 
 
90
 
91
  @property
92
  def current_stacks(self):
93
- return self.stacks[self.current_player]
94
 
95
  @property
96
  def current_ticks(self):
97
- return self.ticks[self.current_player]
98
 
99
  @property
100
  def current_last_dot(self):
101
- return self.last_dot[self.current_player]
102
 
103
  @property
104
  def current_next_dot(self):
105
- return self.next_dot[self.current_player]
106
 
107
  @property
108
  def duration(self):
@@ -111,29 +128,33 @@ class Parser:
111
  def reset(self):
112
  self.current_frame = 0
113
 
114
- self.frames = []
115
-
116
  self.id2name = {}
117
  self.name2id = {}
118
  self.pets = {}
119
 
120
- self.records = defaultdict(lambda: defaultdict(lambda: defaultdict(list)))
 
 
 
 
 
 
121
 
122
- self.hidden_buffs = defaultdict(dict)
123
- self.shift_status = defaultdict(lambda: defaultdict(dict))
124
- self.status = defaultdict(lambda: defaultdict(int))
125
 
126
- self.stacks = defaultdict(lambda: defaultdict(lambda: 1))
127
- self.ticks = defaultdict(lambda: defaultdict(lambda: 0))
128
- self.snapshot = defaultdict(dict)
129
- self.last_dot = defaultdict(dict)
130
- self.next_dot = defaultdict(dict)
131
 
132
  self.start_frame = 0
133
 
134
  self.select_talents = {}
135
  self.select_equipments = {}
136
- self.school = {}
 
 
137
 
138
  @staticmethod
139
  def parse_equipments(detail):
@@ -155,70 +176,90 @@ class Parser:
155
  def parse_talents(detail):
156
  return [row[1] for row in detail]
157
 
158
- def parse_info(self, row):
159
  detail = row.strip("{}").split(",")
160
  player_id, school_id = int(detail[0]), int(detail[3])
161
  if player_id in self.id2name or school_id not in SUPPORT_SCHOOL:
162
  return
163
- if isinstance(detail := parse(row), list):
 
164
  player_name = detail[1]
165
  self.id2name[player_id] = player_name
166
  self.name2id[player_name] = player_id
167
- if school := SUPPORT_SCHOOL.get(detail[3]):
168
- self.select_equipments[player_id] = self.parse_equipments(detail[5])
169
- self.select_talents[player_id] = self.parse_talents(detail[6])
170
- if any(talent not in school.talent_gains for talent in self.select_talents[player_id]):
171
- return
172
- self.school[player_id] = school
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
173
 
174
  def parse_shift_buff(self, row):
175
  detail = row.strip("{}").split(",")
176
  player_id = int(detail[0])
177
- if player_id not in self.school:
178
  return
 
179
  buff_id, buff_stack, buff_level = int(detail[4]), int(detail[5]), int(detail[8])
180
- if buff_id not in self.school[player_id].buffs:
181
  return
182
 
183
- frame_shift = self.school[player_id].buffs[buff_id].frame_shift
184
  if frame_shift:
185
- self.shift_status[self.current_frame + frame_shift][player_id][(buff_id, buff_level)] = buff_stack
186
 
187
  def parse_shift_status(self):
188
- for frame in list(self.shift_status):
189
  if frame > self.current_frame:
190
  break
191
- for player_id, status_buffer in self.shift_status.pop(frame).items():
192
- for buff, buff_stack in status_buffer.items():
193
  if buff_stack:
194
- self.status[player_id][buff] = buff_stack
195
  else:
196
- self.status[player_id].pop(buff, None)
197
 
198
  def parse_hidden_buffs(self):
199
- for player_id, hidden_buffs in self.hidden_buffs.items():
200
- for buff, end_frame in hidden_buffs.items():
201
- if end_frame < self.current_frame:
202
- self.status[player_id].pop(buff, None)
 
203
 
204
- def parse_status(self, row):
205
  detail = row.strip("{}").split(",")
206
  player_id = int(detail[0])
207
- if player_id not in self.school:
208
  return
209
 
210
  buff_id, buff_stack, buff_level = int(detail[4]), int(detail[5]), int(detail[8])
211
- if buff_id not in self.school[player_id].buffs:
212
  return
213
 
214
- frame_shift = self.school[player_id].buffs[buff_id].frame_shift
215
  if frame_shift:
216
  return
217
 
218
  if buff_stack:
219
- self.status[player_id][(buff_id, buff_level)] = buff_stack
220
  else:
221
- self.status[player_id].pop((buff_id, buff_level), None)
222
 
223
  def parse_skill(self, row):
224
  detail = row.strip("{}").split(",")
@@ -228,51 +269,56 @@ class Parser:
228
  else:
229
  player_id = caster_id
230
 
231
- if player_id not in self.school:
232
  return
233
 
234
  react, skill_id, skill_level, critical = int(detail[2]), int(detail[4]), int(detail[5]), detail[6] == "true"
235
- if react or skill_id not in self.school[player_id].skills:
236
  return
237
 
238
  if not self.start_frame:
239
- self.start_frame = self.current_frame - 1
240
 
241
  self.current_player = player_id
242
  self.current_caster = caster_id
243
- skill = self.school[player_id].skills[skill_id]
244
- skill.record(skill_level, critical, self)
245
-
246
- def parse_pet(self, row):
247
- detail = row.strip("{}").split(",")
248
- pet_id, player_id = int(detail[0]), int(detail[3])
249
- if player_id in self.school:
250
- self.pets[pet_id] = player_id
251
- self.snapshot[player_id][pet_id] = self.status[player_id].copy()
252
-
253
- def available_status(self, skill_id, snapshot_id=None):
254
- if not snapshot_id:
255
- snapshot_id = skill_id
256
-
257
  current_status = []
258
- for (buff_id, buff_level), buff_stack in self.current_status.items():
259
  buff = self.current_school.buffs[buff_id]
260
  if buff.gain_attributes:
261
  current_status.append((buff_id, buff_level, buff_stack))
262
  elif buff.gain_skills and skill_id in buff.gain_skills:
263
  current_status.append((buff_id, buff_level, buff_stack))
264
 
 
265
  snapshot_status = []
266
- for (buff_id, buff_level), buff_stack in self.current_snapshot.get(snapshot_id, {}).items():
267
  buff = self.current_school.buffs[buff_id]
268
  if buff.gain_attributes:
269
  snapshot_status.append((buff_id, buff_level, buff_stack))
270
  elif buff.gain_skills and skill_id in buff.gain_skills:
271
  snapshot_status.append((buff_id, buff_level, buff_stack))
272
 
273
- return tuple(current_status), tuple(snapshot_status)
 
 
 
 
 
 
 
 
274
 
275
  def __call__(self, file_name):
 
276
  self.reset()
277
  lines = open(file_name).readlines()
278
  rows = []
@@ -280,9 +326,11 @@ class Parser:
280
  row = line.split("\t")
281
  rows.append(row)
282
  if row[4] == "4":
283
- self.parse_info(row[-1])
 
 
284
 
285
- for player_id, school in self.school.items():
286
  school.prepare(self, player_id)
287
  for talent_id in self.select_talents[player_id]:
288
  school.talent_gains[talent_id].add_skills(school.skills)
@@ -299,18 +347,20 @@ class Parser:
299
  if row[4] == "8":
300
  self.parse_pet(row[-1])
301
  elif row[4] == "13":
302
- self.parse_status(row[-1])
303
  elif row[4] == "21":
304
  self.parse_skill(row[-1])
305
 
306
  self.end_frame = self.current_frame
307
 
308
- for player_id, school in self.school.items():
309
  for talent_id in self.select_talents[player_id]:
310
  school.talent_gains[talent_id].sub_skills(school.skills)
311
 
312
-
313
- if __name__ == '__main__':
314
- parser = Parser()
315
- parser("../dao_zong.jcl")
316
- print(1)
 
 
 
4
  from schools import *
5
  from utils.lua import parse
6
 
7
+ FRAME_TYPE, PLAYER_ID_TYPE, PLAYER_NAME_TYPE, TARGET_ID_TYPE, PET_ID_TYPE = int, int, int, int, int
8
  CASTER_ID_TYPE = PLAYER_ID_TYPE | PET_ID_TYPE
9
  SKILL_ID_TYPE, SKILL_LEVEL_TYPE, SKILL_STACK_TYPE, SKILL_CRITICAL_TYPE = int, int, int, bool
 
10
  SKILL_TYPE = Tuple[SKILL_ID_TYPE, SKILL_LEVEL_TYPE, SKILL_STACK_TYPE]
11
  BUFF_ID_TYPE, BUFF_LEVEL_TYPE, BUFF_STACK_TYPE = int, int, int
12
  BUFF_TYPE = Tuple[BUFF_ID_TYPE, BUFF_LEVEL_TYPE]
 
13
 
14
+ CURRENT_STATUS_TYPE, SNAPSHOT_STATUS_TYPE, TARGET_STATUS_TYPE = tuple, tuple, tuple
15
+ STATUS_TUPLE = Tuple[CURRENT_STATUS_TYPE, SNAPSHOT_STATUS_TYPE, TARGET_STATUS_TYPE]
16
+ TIMELINE_TYPE = Tuple[FRAME_TYPE, SKILL_CRITICAL_TYPE]
17
+ SUB_RECORD_TYPE = Dict[STATUS_TUPLE, List[TIMELINE_TYPE]]
18
  RECORD_TYPE = Dict[SKILL_TYPE, SUB_RECORD_TYPE]
19
 
20
  LABEL_MAPPING = {
 
33
  }
34
  EMBED_MAPPING: Dict[tuple, int] = {(5, 24449 - i): 8 - i for i in range(8)}
35
 
 
 
36
 
37
  class Parser:
38
  current_player: PLAYER_ID_TYPE
39
  current_caster: CASTER_ID_TYPE
40
+ current_target: TARGET_ID_TYPE
41
+ current_skill: SKILL_ID_TYPE
42
  current_frame: FRAME_TYPE
 
43
 
44
+ id2name: Dict[PLAYER_ID_TYPE | TARGET_ID_TYPE, PLAYER_NAME_TYPE]
45
+ name2id: Dict[PLAYER_NAME_TYPE, PLAYER_ID_TYPE | TARGET_ID_TYPE]
46
  pets: Dict[PET_ID_TYPE, PLAYER_ID_TYPE]
47
+ records: Dict[PLAYER_ID_TYPE, Dict[TARGET_ID_TYPE, RECORD_TYPE]]
48
+
49
+ shift_buffs: Dict[FRAME_TYPE, Dict[PLAYER_ID_TYPE, Dict[BUFF_TYPE, BUFF_STACK_TYPE]]]
50
+ hidden_buffs: Dict[TARGET_ID_TYPE, Dict[PLAYER_ID_TYPE, Dict[BUFF_TYPE, FRAME_TYPE]]]
51
 
52
+ player_buffs: Dict[PLAYER_ID_TYPE, Dict[BUFF_TYPE, BUFF_STACK_TYPE]]
53
+ target_buffs: Dict[TARGET_ID_TYPE, Dict[PLAYER_ID_TYPE, Dict[BUFF_TYPE, BUFF_STACK_TYPE]]]
 
54
 
55
+ stacks: Dict[TARGET_ID_TYPE, Dict[PLAYER_ID_TYPE, Dict[SKILL_ID_TYPE, int]]]
56
+ ticks: Dict[TARGET_ID_TYPE, Dict[PLAYER_ID_TYPE, Dict[SKILL_ID_TYPE, int]]]
57
 
58
+ pet_snapshot: Dict[PET_ID_TYPE, Dict[BUFF_TYPE, BUFF_STACK_TYPE]]
59
+ dot_snapshot: Dict[TARGET_ID_TYPE, Dict[PLAYER_ID_TYPE, Dict[SKILL_ID_TYPE, Dict[BUFF_TYPE, BUFF_STACK_TYPE]]]]
60
+
61
+ last_dot: Dict[TARGET_ID_TYPE, Dict[PLAYER_ID_TYPE, Dict[SKILL_ID_TYPE, Tuple[SKILL_TYPE, Tuple[tuple, tuple]]]]]
62
+ next_dot: Dict[TARGET_ID_TYPE, Dict[PLAYER_ID_TYPE, Dict[SKILL_ID_TYPE, int]]]
63
 
64
  start_frame: FRAME_TYPE
65
  end_frame: FRAME_TYPE
 
67
  select_talents: Dict[PLAYER_ID_TYPE, List[int]]
68
  select_equipments: Dict[PLAYER_ID_TYPE, Dict[int, Dict[str, int | list]]]
69
 
70
+ players: Dict[PLAYER_ID_TYPE, School]
71
+ targets: Dict[PLAYER_ID_TYPE, List[TARGET_ID_TYPE]]
72
 
73
  @property
74
  def current_school(self):
75
+ return self.players[self.current_player]
76
+
77
+ @property
78
+ def current_targets(self):
79
+ return self.targets[self.current_player]
80
 
81
  @property
82
  def current_records(self):
83
+ return self.records[self.current_player][self.current_target]
84
 
85
  @property
86
  def current_hidden_buffs(self):
87
+ return self.hidden_buffs[self.current_target][self.current_player]
88
+
89
+ @property
90
+ def current_player_buffs(self):
91
+ return self.player_buffs[self.current_player]
92
 
93
  @property
94
+ def current_target_buffs(self):
95
+ return self.target_buffs[self.current_target][self.current_player]
96
 
97
  @property
98
  def current_snapshot(self):
99
+ if self.current_caster in self.pet_snapshot:
100
+ return self.pet_snapshot[self.current_caster]
101
+ else:
102
+ return self.dot_snapshot[self.current_target][self.current_player].get(self.current_skill, {})
103
+
104
+ @property
105
+ def current_dot_snapshot(self):
106
+ return self.dot_snapshot[self.current_target][self.current_player]
107
 
108
  @property
109
  def current_stacks(self):
110
+ return self.stacks[self.current_target][self.current_player]
111
 
112
  @property
113
  def current_ticks(self):
114
+ return self.ticks[self.current_target][self.current_player]
115
 
116
  @property
117
  def current_last_dot(self):
118
+ return self.last_dot[self.current_target][self.current_player]
119
 
120
  @property
121
  def current_next_dot(self):
122
+ return self.next_dot[self.current_target][self.current_player]
123
 
124
  @property
125
  def duration(self):
 
128
  def reset(self):
129
  self.current_frame = 0
130
 
 
 
131
  self.id2name = {}
132
  self.name2id = {}
133
  self.pets = {}
134
 
135
+ self.records = defaultdict(lambda: defaultdict(lambda: defaultdict(lambda: defaultdict(list))))
136
+
137
+ self.hidden_buffs = defaultdict(lambda: defaultdict(dict))
138
+ self.shift_buffs = defaultdict(lambda: defaultdict(dict))
139
+
140
+ self.player_buffs = defaultdict(dict)
141
+ self.target_buffs = defaultdict(lambda: defaultdict(dict))
142
 
143
+ self.stacks = defaultdict(lambda: defaultdict(lambda: defaultdict(lambda: 1)))
144
+ self.ticks = defaultdict(lambda: defaultdict(lambda: defaultdict(lambda: 0)))
 
145
 
146
+ self.pet_snapshot = dict()
147
+ self.dot_snapshot = defaultdict(lambda: defaultdict(dict))
148
+ self.last_dot = defaultdict(lambda: defaultdict(dict))
149
+ self.next_dot = defaultdict(lambda: defaultdict(dict))
 
150
 
151
  self.start_frame = 0
152
 
153
  self.select_talents = {}
154
  self.select_equipments = {}
155
+
156
+ self.players = {}
157
+ self.targets = defaultdict(list)
158
 
159
  @staticmethod
160
  def parse_equipments(detail):
 
176
  def parse_talents(detail):
177
  return [row[1] for row in detail]
178
 
179
+ def parse_player(self, row):
180
  detail = row.strip("{}").split(",")
181
  player_id, school_id = int(detail[0]), int(detail[3])
182
  if player_id in self.id2name or school_id not in SUPPORT_SCHOOL:
183
  return
184
+
185
+ if isinstance(detail := parse(row), list) and (school := SUPPORT_SCHOOL.get(detail[3])):
186
  player_name = detail[1]
187
  self.id2name[player_id] = player_name
188
  self.name2id[player_name] = player_id
189
+ self.select_equipments[player_id] = self.parse_equipments(detail[5])
190
+ self.select_talents[player_id] = self.parse_talents(detail[6])
191
+ if any(talent not in school.talent_gains for talent in self.select_talents[player_id]):
192
+ return
193
+ self.players[player_id] = school
194
+
195
+ def parse_npc(self, row):
196
+ detail = row.strip("{}").split(",")
197
+ npc_id, player_id = int(detail[0]), int(detail[3])
198
+ if npc_id in self.id2name:
199
+ return
200
+
201
+ npc_name = detail[1]
202
+ self.id2name[npc_id] = npc_name
203
+ self.name2id[npc_name] = npc_id
204
+ if player_id:
205
+ self.pets[npc_id] = player_id
206
+
207
+ def parse_pet(self, row):
208
+ detail = row.strip("{}").split(",")
209
+ pet_id, player_id = int(detail[0]), int(detail[3])
210
+ if pet_id in self.pets:
211
+ self.pet_snapshot[pet_id] = self.player_buffs[player_id].copy()
212
 
213
  def parse_shift_buff(self, row):
214
  detail = row.strip("{}").split(",")
215
  player_id = int(detail[0])
216
+ if player_id not in self.players:
217
  return
218
+
219
  buff_id, buff_stack, buff_level = int(detail[4]), int(detail[5]), int(detail[8])
220
+ if buff_id not in self.players[player_id].buffs:
221
  return
222
 
223
+ frame_shift = self.players[player_id].buffs[buff_id].frame_shift
224
  if frame_shift:
225
+ self.shift_buffs[self.current_frame + frame_shift][player_id][(buff_id, buff_level)] = buff_stack
226
 
227
  def parse_shift_status(self):
228
+ for frame in list(self.shift_buffs):
229
  if frame > self.current_frame:
230
  break
231
+ for player_id, shift_buffs in self.shift_buffs.pop(frame).items():
232
+ for buff, buff_stack in shift_buffs.items():
233
  if buff_stack:
234
+ self.player_buffs[player_id][buff] = buff_stack
235
  else:
236
+ self.player_buffs[player_id].pop(buff, None)
237
 
238
  def parse_hidden_buffs(self):
239
+ for target_id in self.hidden_buffs:
240
+ for player_id, hidden_buffs in self.hidden_buffs[target_id].items():
241
+ for buff, end_frame in hidden_buffs.items():
242
+ if end_frame < self.current_frame:
243
+ self.target_buffs[target_id][player_id].pop(buff, None)
244
 
245
+ def parse_buff(self, row):
246
  detail = row.strip("{}").split(",")
247
  player_id = int(detail[0])
248
+ if player_id not in self.players:
249
  return
250
 
251
  buff_id, buff_stack, buff_level = int(detail[4]), int(detail[5]), int(detail[8])
252
+ if buff_id not in self.players[player_id].buffs:
253
  return
254
 
255
+ frame_shift = self.players[player_id].buffs[buff_id].frame_shift
256
  if frame_shift:
257
  return
258
 
259
  if buff_stack:
260
+ self.player_buffs[player_id][(buff_id, buff_level)] = buff_stack
261
  else:
262
+ self.player_buffs[player_id].pop((buff_id, buff_level), None)
263
 
264
  def parse_skill(self, row):
265
  detail = row.strip("{}").split(",")
 
269
  else:
270
  player_id = caster_id
271
 
272
+ if player_id not in self.players:
273
  return
274
 
275
  react, skill_id, skill_level, critical = int(detail[2]), int(detail[4]), int(detail[5]), detail[6] == "true"
276
+ if react or skill_id not in self.players[player_id].skills:
277
  return
278
 
279
  if not self.start_frame:
280
+ self.start_frame = self.current_frame
281
 
282
  self.current_player = player_id
283
  self.current_caster = caster_id
284
+ if target_id not in self.current_targets:
285
+ self.current_targets.append(target_id)
286
+ self.current_target = target_id
287
+ self.current_skill = skill_id
288
+ skill = self.players[player_id].skills[skill_id]
289
+ skill.skill_level = skill_level
290
+ skill.record(critical, self)
291
+
292
+ def status(self, skill_id):
 
 
 
 
 
293
  current_status = []
294
+ for (buff_id, buff_level), buff_stack in self.current_player_buffs.items():
295
  buff = self.current_school.buffs[buff_id]
296
  if buff.gain_attributes:
297
  current_status.append((buff_id, buff_level, buff_stack))
298
  elif buff.gain_skills and skill_id in buff.gain_skills:
299
  current_status.append((buff_id, buff_level, buff_stack))
300
 
301
+ self.current_skill = skill_id
302
  snapshot_status = []
303
+ for (buff_id, buff_level), buff_stack in self.current_snapshot.items():
304
  buff = self.current_school.buffs[buff_id]
305
  if buff.gain_attributes:
306
  snapshot_status.append((buff_id, buff_level, buff_stack))
307
  elif buff.gain_skills and skill_id in buff.gain_skills:
308
  snapshot_status.append((buff_id, buff_level, buff_stack))
309
 
310
+ target_status = []
311
+ for (buff_id, buff_level), buff_stack in self.current_target_buffs.items():
312
+ buff = self.current_school.buffs[buff_id]
313
+ if buff.gain_attributes:
314
+ target_status.append((buff_id, buff_level, buff_stack))
315
+ elif buff.gain_skills and skill_id in buff.gain_skills:
316
+ target_status.append((buff_id, buff_level, buff_stack))
317
+
318
+ return tuple(current_status), tuple(snapshot_status), tuple(target_status)
319
 
320
  def __call__(self, file_name):
321
+ self.file_name = file_name
322
  self.reset()
323
  lines = open(file_name).readlines()
324
  rows = []
 
326
  row = line.split("\t")
327
  rows.append(row)
328
  if row[4] == "4":
329
+ self.parse_player(row[-1])
330
+ elif row[4] == "8":
331
+ self.parse_npc(row[-1])
332
 
333
+ for player_id, school in self.players.items():
334
  school.prepare(self, player_id)
335
  for talent_id in self.select_talents[player_id]:
336
  school.talent_gains[talent_id].add_skills(school.skills)
 
347
  if row[4] == "8":
348
  self.parse_pet(row[-1])
349
  elif row[4] == "13":
350
+ self.parse_buff(row[-1])
351
  elif row[4] == "21":
352
  self.parse_skill(row[-1])
353
 
354
  self.end_frame = self.current_frame
355
 
356
+ for player_id, school in self.players.items():
357
  for talent_id in self.select_talents[player_id]:
358
  school.talent_gains[talent_id].sub_skills(school.skills)
359
 
360
+ for player_id in self.records:
361
+ player_record = defaultdict(lambda: defaultdict(list))
362
+ for target_id, records in self.records[player_id].items():
363
+ for skill_tuple, status in records.items():
364
+ for status_tuple, timeline in status.items():
365
+ player_record[skill_tuple][status_tuple] += timeline
366
+ self.records[player_id][0] = player_record