def impl(self, options): for combat in conn_execute(self.conn, '''select * from combat order by start_event_id''').fetchall(): print datetime.datetime.now(), "Combat %d: %s - %s" % (combat['id'], combat['instance'], combat['encounter']) cast_manager = DurationManager(self.conn, 'cast', [('combat_id', 'int'), ('sourceType', 'str'), ('sourceName', 'str')], [('spellName', 'str'), ('spellId', 'int'), ('destType', 'str'), ('destName', 'str')]) for event in basicparse.getEventData(self.conn, orderBy='id', suffix=('_CAST_START', '_CAST_SUCCESS', '_CAST_FAILED')).fetchall(): if event['suffix'] == '_CAST_START': cast_manager.add(event) elif event['suffix'] == '_CAST_SUCCESS' or event['suffix'] == '_CAST_FAILED': cast_manager.remove(event) event = basicparse.getEventData(self.conn, id=combat['end_event_id']).fetchone() cast_manager.close(event)
def getAllPresent(conn, combat): where_list = [] start_event = basicparse.getEventData(conn, id=combat['start_event_id']).fetchone() end_event = basicparse.getEventData(conn, id=combat['end_event_id']).fetchone() where_list.append(('''time >= ?''', start_event['time'])) where_list.append(('''time <= ?''', end_event['time'])) where_list.append(('''combat_id = ?''', combat['id'])) where_list.append(('''wipe = ?''', 0)) present_dict = {} for row in basicparse.getEventData(conn, 'distinct sourceName', where_list, sourceType='PC'): present_dict[row['sourceName']] = 0 return present_dict, where_list
def avoidableDamage(conn, combat, damageSpellId=0, ignoredSeconds=0, ignoredDamage=0, binary=False, **kwargs): fail_dict, where_list = getAllPresent(conn, combat) application_dict = {} current = None for event in basicparse.getEventData(conn, '*', where_list, 'time', suffix='_DAMAGE', spellId=damageSpellId, destType='PC'): application_dict.setdefault(event['destName'], []) if application_dict[event['destName']] and application_dict[event['destName']][-1][0]['time'] + datetime.timedelta(seconds=4) > event['time']: application_dict[event['destName']][-1][1].append(event) else: application_dict[event['destName']].append((event, [event])) #print application_dict ignored_td = datetime.timedelta(seconds=ignoredSeconds) for destName_str, application_list in application_dict.items(): #print destName_str, damageSpellId fail_dict[destName_str] = 0 for event, damage_list in application_list: #print [x['amount'] for x in damage_list], damageSpellId while damage_list and event['time'] + ignored_td > damage_list[0]['time']: damage_list.pop(0) if binary: fail_dict[destName_str] += len([x['amount'] - ignoredDamage for x in damage_list if x['amount'] and x['amount'] - ignoredDamage > 0]) else: fail_dict[destName_str] += sum([x['amount'] - ignoredDamage for x in damage_list if x['amount'] and x['amount'] - ignoredDamage > 0]) return fail_dict
def impl(self, options): #print datetime.datetime.now(), "Flagging fake deaths..." #flagFakeDeaths(self.conn) sqlite_insureColumns(self.conn, 'event', [('fakeDeath', 'int default 0')]) update_list = [] for event in basicparse.getEventData(self.conn, orderBy='time', eventType='UNIT_DIED', destType='PC'): where_list = [] where_list.append(('time >= ?', event['time'] - datetime.timedelta(seconds=0.5))) where_list.append(('time <= ?', event['time'] + datetime.timedelta(seconds=0.5))) buffsLost_int = basicparse.getEventData(self.conn, 'count(*)', where_list, destType='PC', destName=event['destName'], eventType='SPELL_AURA_REMOVED').fetchone()[0] if buffsLost_int < 10: update_list.append(('''update event set fakeDeath = 1 where id = ?''', (event['id'],))) for sql_str, values_tup in update_list: conn_execute(self.conn, sql_str, values_tup) self.conn.commit()
def impl(self, options): for combat in conn_execute(self.conn, '''select * from combat order by start_event_id''').fetchall(): print datetime.datetime.now(), "Combat %d: %s - %s" % (combat['id'], combat['instance'], combat['encounter']) aura_manager = DurationManager(self.conn, 'aura', [('combat_id', 'int'), ('spellName', 'str'), ('destType', 'str'), ('destName', 'str'), ('spellId', 'str')], [('sourceType', 'str'), ('sourceName', 'str')]) cast_set = set([x['spellName'] for x in basicparse.getEventData(self.conn, 'distinct spellName', combat_id=combat['id'], suffix='_CAST_SUCCESS').fetchall()]) event_list = [] lastSpell_str = None for event in basicparse.getEventData(self.conn, orderBy='id', suffix=('_AURA_APPLIED', '_AURA_REMOVED'), spellName=tuple(cast_set)).fetchall(): #if event_list and lastSpell_str and event['spellName'] != lastSpell_str: # if len(event_list) < 6: or '_CAST_SUCCESS' in [x['suffix'] for x in event_list]: # for old_event in event_list: # if old_event['eventType'] == 'SPELL_AURA_APPLIED': # aura_manager.add(old_event) # # #if event['eventType'] == 'SPELL_AURA_REMOVED': # aura_manager.remove(event) #if event_list and event_list[-1]['spellName'] != event['spellName']: # # This wonky bit is to screen out raid-wide auras from procs. Too many inserts, and generally not interesting. # if len(event_list) < 6 or '_CAST_SUCCESS' in [x['suffix'] for x in event_list]: # for old_event in event_list: # if old_event['eventType'] == 'SPELL_AURA_APPLIED': # aura_manager.add(old_event) # #elif old_event['eventType'] == 'SPELL_AURA_REMOVED': # # aura_manager.remove(old_event) # event_list = [event] #else: # event_list.append(event) if event['eventType'] == 'SPELL_AURA_APPLIED': aura_manager.add(event) elif event['eventType'] == 'SPELL_AURA_REMOVED': aura_manager.remove(event) event = basicparse.getEventData(self.conn, id=combat['end_event_id']).fetchone() aura_manager.close(event)
def avoidableAttack(conn, combat, attackSpellId=0, eventType='SPELL_DAMAGE', requireOverkill=False, **kwargs): fail_dict, where_list = getAllPresent(conn, combat) if requireOverkill: where_list.append(('extra > ?', 0)) application_dict = {} current = None for event in basicparse.getEventData(conn, '*', where_list, 'time', eventType=eventType, spellId=attackSpellId, destType='PC'): fail_dict.setdefault(event['destName'], 0) fail_dict[event['destName']] += 1 return fail_dict
def getEventData(self, index, select_str='*', where_list=None, orderBy=None, **kwargs): """ Examples of use: Total healing done to PCs: lambda timeline, index: timeline.getEventData(index, 'sum(amount) - sum(extra)', suffix='_HEAL', destType='PC').fetchone()[0] Total healing done to Bosses (like at Vezax): lambda timeline, index: timeline.getEventData(index, 'sum(amount) - sum(extra)', suffix='_HEAL', destType='NPC').fetchone()[0] If a given player cast something: lambda timeline, index: timeline.getEventData(index, 'count(*)', suffix=('_CAST_START', '_CAST_SUCCESS'), sourceName='Tantryst').fetchone()[0] != 0 """ if where_list is None: where_list = [] where_list.append(('''time >= ?''', self.start_dt + (self.width_td * index))) where_list.append(('''time < ?''', self.start_dt + (self.width_td * (index+1)))) return basicparse.getEventData(self.conn, select_str, where_list, orderBy, **kwargs)
def clumpDebuff(conn, combat, debuffSpellId, ignoredTargets=2, **kwargs): fail_dict, where_list = getAllPresent(conn, combat) fail_list = [] process_list = [] for event in basicparse.getEventData(conn, '*', where_list, spellId=debuffSpellId, eventType='SPELL_AURA_APPLIED', destType='PC'): if not fail_list or fail_list[-1][-1]['time'] + datetime.timedelta(seconds=0.5) > event['time']: fail_list.append([event]) else: fail_list[-1].append(event) #fail_dict = {} for process_list in fail_list: if len(process_list) > ignoredTargets: for event in process_list: fail_dict.setdefault(event['destName'], 0) fail_dict[event['destName']] += len(process_list) - ignoredTargets return fail_dict
def chainLightning(conn, combat, damageSpellId, ignoredTargets=2, **kwargs): fail_dict, where_list = getAllPresent(conn, combat) fail_list = [] process_list = [] for event in basicparse.getEventData(conn, '*', where_list, 'time', spellId=damageSpellId, suffix='_DAMAGE', destType='PC'): if not fail_list or fail_list[-1][-1]['time'] + datetime.timedelta(seconds=0.5) > event['time']: fail_list.append([event]) else: fail_list[-1].append(event) #fail_dict = {} for process_list in fail_list: if len(process_list) > ignoredTargets: for event in process_list: fail_dict.setdefault(event['destName'], 0) fail_dict[event['destName']] += len(process_list) - ignoredTargets return fail_dict
def runAwayDebuff(conn, combat, debuffSpellId, damageSpellId, ignoredSeconds=0, **kwargs): fail_dict, where_list = getAllPresent(conn, combat) application_dict = {} current = None for event in basicparse.getEventData(conn, '*', where_list, 'time', spellId=(debuffSpellId, damageSpellId), destType='PC'): if event['eventType'] == 'SPELL_AURA_APPLIED': current = event application_dict.setdefault(event['destName'], []) application_dict[current['destName']].append((current, [])) elif not current: pass #elif event['eventType'] == 'SPELL_AURA_REMOVED' and event['destGUID'] == current['destGUID']: # process_list = fail_list # fail_list = [] elif event['eventType'] == 'SPELL_DAMAGE': application_dict[current['destName']][-1][1].append(event) #fail_list.append(event) ignored_td = datetime.timedelta(seconds=ignoredSeconds) #fail_dict = {} for destName_str, application_list in application_dict.items(): fail_dict[destName_str] = 0 for event, damage_list in application_list: #print destName_str, len(damage_list), '\t', event['time'] #print '\t' + '\n\t'.join([str(x['time']) for x in damage_list]) while damage_list and event['time'] + ignored_td > damage_list[0]['time']: damage_list.pop(0) #print destName_str, len(damage_list) fail_dict[destName_str] += len(damage_list) if application_list: fail_dict[destName_str] /= len(application_list) return fail_dict
def impl(self, options): wound_manager = DurationManager(self.conn, 'wound', [('combat_id', 'int'), ('destType', 'str'), ('destName', 'str')], [('amount', 'int default 0'), ('delta', 'int default 0'), ('direction', 'int default 0'), ('dead', 'int default 0'), ('spellName', 'str')]) count = 1 for combat in conn_execute(self.conn, '''select * from combat order by start_event_id''').fetchall(): print datetime.datetime.now(), "Combat %d: %s - %s" % (combat['id'], combat['instance'], combat['encounter']) hot_dict = collections.defaultdict(int) #for event in basicparse.getEventData(self.conn, orderBy='id', destType='PC', suffix=('_DAMAGE', '_HEAL', '_DIED', '_RESURRECT'), fetchall=True):#.fetchall(): for event in basicparse.getEventData(self.conn, orderBy='id', destType='PC', suffix=('_DAMAGE', '_HEAL', '_DIED', '_RESURRECT')).fetchall(): if event['destType'] == 'PC': key = wound_manager.eventKey(event) direction = 0 if event['suffix'] == '_DAMAGE' and event['amount'] > 0: direction = -1 hot_dict[key] -= event['amount'] + event['extra'] #wound = wound_manager.get(event, value=(0, 0, 0, 0, '')) #wound_manager.add(event, value=(wound['amount'] + event['amount'] - event['extra'] + hot_dict[key], -event['amount'] + event['extra'], -1, 0, event['spellName'])) #hot_dict[key] = 0 elif event['suffix'] == '_HEAL' and event['amount'] - event['extra'] > 0: # and (event['amount'] - event['extra'] > 2000 or event['extra'] > 0): # We don't set direction=1 on HOTs because we only # want direction to track actions, not automatic # effects. We should probably also screen out spells # like Earth Shield. FIXME if event['prefix'] == 'SPELL': direction = 1 if event['extra'] > 0: wound = wound_manager.get(event, value=(0, 0, 0, 0, '')) if wound['amount'] < 0: wound_manager.add(event, value=(0, event['amount'] - event['extra'], direction, 0, event['spellName'])) hot_dict[key] = 0 else: hot_dict[key] += event['amount'] - event['extra'] # wound = wound_manager.get(event, value=(0, 0, 0, 0, '')) # wound_manager.add(event, value=(wound['amount'] - event['amount'] - hot_dict[key], event['amount'] - event['extra'], direction, 0, event['spellName'])) #hot_dict[key] = 0 #elif event['suffix'] == '_HEAL' and event['amount'] - event['extra'] > 0: # hot_dict[key] += event['amount'] - event['extra'] elif event['suffix'] == '_DIED' and event['fakeDeath'] != 1: wound_manager.add(event, value=(0, 0, -1, 1, event['spellName'])) hot_dict[key] = 0 elif event['suffix'] == '_RESURRECT': wound_manager.add(event, value=(0, 0, 1, 0, event['spellName'])) hot_dict[key] = 0 #if event['destName'] == 'Naxxar': # print key, hot_dict[key], event['spellName'], event['time'] try: if hot_dict[key] < -2000 or hot_dict[key] > 2000: wound = wound_manager.get(event, value=(0, 0, 0, 0, '')) wound_manager.add(event, value=(wound['amount'] + hot_dict[key], (direction or 1) * (event['amount'] - event['extra']), direction, 0, event['spellName'])) hot_dict[key] = 0 except: #for k in event.keys(): # print k, '\t', event[k] #print key, hot_dict[key] raise #if event['destType'] == 'PC': # if event['suffix'] == '_DAMAGE' and event['amount'] > 0: # wound = wound_manager.get(event, value=(0, 0, 0, 0, '')) # wound_manager.add(event, value=(wound['amount'] + event['amount'] - event['extra'] + hot_dict[wound_manager.eventKey(event)], -event['amount'] + event['extra'], -1, 0, event['spellName'])) # hot_dict[wound_manager.eventKey(event)] = 0 # # elif event['suffix'] == '_HEAL' and event['amount'] - event['extra'] > 0 and (event['amount'] - event['extra'] > 2000 or event['extra'] > 0): # # We don't set direction=1 on HOTs because we only # # want direction to track actions, not automatic # # effects. We should probably also screen out spells # # like Earth Shield. FIXME # if event['prefix'] == 'SPELL_PERIODIC': # direction = 0 # else: # direction = 1 # # if event['extra'] > 0: # wound_manager.add(event, value=(0, event['amount'] - event['extra'], direction, 0, event['spellName'])) # else: # wound = wound_manager.get(event, value=(0, 0, 0, 0, '')) # wound_manager.add(event, value=(wound['amount'] - event['amount'] - hot_dict[wound_manager.eventKey(event)], event['amount'] - event['extra'], direction, 0, event['spellName'])) # hot_dict[wound_manager.eventKey(event)] = 0 # # elif event['suffix'] == '_HEAL' and event['amount'] - event['extra'] > 0: # hot_dict[wound_manager.eventKey(event)] += event['amount'] - event['extra'] # # elif event['suffix'] == '_DIED' and event['fakeDeath'] != 1: # wound_manager.add(event, value=(0, 0, -1, 1, event['spellName'])) # hot_dict[wound_manager.eventKey(event)] = 0 # # elif event['suffix'] == '_RESURRECT': # wound_manager.add(event, value=(0, 0, 1, 0, event['spellName'])) # hot_dict[wound_manager.eventKey(event)] = 0 #self.conn.commit() #count += 1 #if count % 200 == 0: # self.conn.commit() event = basicparse.getEventData(self.conn, id=combat['end_event_id']).fetchone() wound_manager.close(event)