Git repository creation. Added initial files
This commit is contained in:
parent
1236824d92
commit
d1990aa41f
3
README
Executable file
3
README
Executable file
@ -0,0 +1,3 @@
|
|||||||
|
Swtor combat log parser (work in progress)
|
||||||
|
|
||||||
|
To use: parser.py filename
|
147
parser.py
Executable file
147
parser.py
Executable file
@ -0,0 +1,147 @@
|
|||||||
|
# Danial Afzal
|
||||||
|
# iotasquared@gmail.com
|
||||||
|
import os
|
||||||
|
import re
|
||||||
|
from datetime import datetime
|
||||||
|
import sys
|
||||||
|
#[03/16/2012 22:53:45] [@Asdffljklasdfj] [@Asdffljklasdfj] [Unnatural Might {1781509484707840}] [RemoveEffect {836045448945478}: Unnatural Might {1781509484707840}] ()
|
||||||
|
#[date] [src] [target] [ability] [effect] (value) <threat>
|
||||||
|
#src = [foo {id}] or [@player]
|
||||||
|
# ability = abil {id}
|
||||||
|
# effect = type:effect
|
||||||
|
# value = # or # type
|
||||||
|
# roll? int
|
||||||
|
class Event:
|
||||||
|
regex = r'[\[<\(]([^\[<\(\]>\)]*)[\]>\)]'
|
||||||
|
def __init__(self, x):
|
||||||
|
#print x
|
||||||
|
data = re.findall(Event.regex, x)
|
||||||
|
data.append('')
|
||||||
|
self.to_string = ' '.join(data)
|
||||||
|
|
||||||
|
date = datetime.strptime(data[0], '%m/%d/%Y %H:%M:%S')
|
||||||
|
self.date = date
|
||||||
|
self.source = Entity(data[1])
|
||||||
|
self.target = Entity(data[2])
|
||||||
|
self.ability = Ability(data[3])
|
||||||
|
self.effect = Effect(data[4])
|
||||||
|
self.value = Value(data[5])
|
||||||
|
self.threat = Threat(data[6])
|
||||||
|
|
||||||
|
class Entity:
|
||||||
|
def __init__(self, x):
|
||||||
|
if not x:
|
||||||
|
self.name = x
|
||||||
|
self.player = False
|
||||||
|
elif x[0] == '@':
|
||||||
|
self.name = x[1:]
|
||||||
|
self.player = True
|
||||||
|
else:
|
||||||
|
self.name = x
|
||||||
|
self.player = False
|
||||||
|
|
||||||
|
class Ability:
|
||||||
|
def __init__(self, x):
|
||||||
|
self.name = x
|
||||||
|
|
||||||
|
class Effect:
|
||||||
|
def __init__(self, x):
|
||||||
|
if not x:
|
||||||
|
self.type = ''
|
||||||
|
self.detail = ''
|
||||||
|
return
|
||||||
|
foo = x.split(':')
|
||||||
|
if len(foo) > 1:
|
||||||
|
self.type = foo[0]
|
||||||
|
self.detail = foo[1]
|
||||||
|
else:
|
||||||
|
self.type = x
|
||||||
|
self.detail = ''
|
||||||
|
|
||||||
|
class Value:
|
||||||
|
def __init__(self, x):
|
||||||
|
if not x:
|
||||||
|
self.value = 0
|
||||||
|
self.type = ''
|
||||||
|
return
|
||||||
|
foo = x.replace('*','').split(' ')
|
||||||
|
self.value = int(foo[0])
|
||||||
|
if len(foo) > 1:
|
||||||
|
self.type = foo[1]
|
||||||
|
else:
|
||||||
|
self.type=''
|
||||||
|
|
||||||
|
class Threat:
|
||||||
|
def __init__(self, x):
|
||||||
|
if not x:
|
||||||
|
self.value = 0
|
||||||
|
self.type = ''
|
||||||
|
return
|
||||||
|
foo = x.replace('*','').split(' ')
|
||||||
|
self.value = int(foo[0])
|
||||||
|
if len(foo) > 1:
|
||||||
|
self.type = foo[1]
|
||||||
|
else:
|
||||||
|
self.type=''
|
||||||
|
|
||||||
|
#date, source, target, ability, effect.type/detail, value.value/type, threat
|
||||||
|
# TODO:
|
||||||
|
# multiple sources
|
||||||
|
# more interesting output, graphs? What about that metric site? Google charts?
|
||||||
|
# App engine seems fun
|
||||||
|
# Details for abilities:
|
||||||
|
# dmg per ability
|
||||||
|
# Combine multiple entries per ability
|
||||||
|
def main():
|
||||||
|
if len(sys.argv) == 1:
|
||||||
|
filename = 'argorash.txt'
|
||||||
|
print 'File not specified, defaulting to ' + filename
|
||||||
|
else:
|
||||||
|
filename = sys.argv[1]
|
||||||
|
file = open(filename, 'r')
|
||||||
|
events = []
|
||||||
|
for line in file.readlines():
|
||||||
|
events.append(Event(line))
|
||||||
|
|
||||||
|
players = set([event.source.name for event in events])
|
||||||
|
fights = []
|
||||||
|
fight = []
|
||||||
|
for event in events:
|
||||||
|
if 'EnterCombat' in event.effect.detail:
|
||||||
|
fight = []
|
||||||
|
if 'ExitCombat' in event.effect.detail:
|
||||||
|
fight.append(event)
|
||||||
|
fights.append(fight)
|
||||||
|
fight = []
|
||||||
|
continue
|
||||||
|
fight.append(event)
|
||||||
|
|
||||||
|
for i, fight in enumerate(fights):
|
||||||
|
duration = fight[-1].date - fight[0].date
|
||||||
|
print '\nCombat Statistics for Fight # %d (duration: %s)' %(i+1, str(duration))
|
||||||
|
print str(fight[0].date) +" -> " + str(fight[-1].date)
|
||||||
|
for player in players:
|
||||||
|
dmg = 0
|
||||||
|
heal = 0
|
||||||
|
threat = 0
|
||||||
|
for event in fight:
|
||||||
|
if event.source.name == player and 'Damage ' in event.effect.detail:
|
||||||
|
dmg += event.value.value
|
||||||
|
if event.source.name == player and event.threat.value:
|
||||||
|
threat += event.threat.value
|
||||||
|
if event.source.name == player and 'Heal ' in event.effect.detail:
|
||||||
|
heal += event.value.value
|
||||||
|
secs = duration.seconds
|
||||||
|
if not secs:
|
||||||
|
secs = 1
|
||||||
|
if dmg:
|
||||||
|
print '%s did %d damage in %s (%d DPS)' % (player, dmg, str(duration), dmg/secs)
|
||||||
|
if heal:
|
||||||
|
print '%s did %d heals in %s (%d HPS)' % (player, heal, str(duration), heal/secs)
|
||||||
|
if threat:
|
||||||
|
print '%s did %d threat in %s (%d TPS)' % (player, threat, str(duration), threat/secs)
|
||||||
|
|
||||||
|
|
||||||
|
#print "\n".join([event.to_string for event in events])
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
4
setup.py
Executable file
4
setup.py
Executable file
@ -0,0 +1,4 @@
|
|||||||
|
from distutils.core import setup
|
||||||
|
import py2exe
|
||||||
|
|
||||||
|
setup(console=['parser.py'])
|
171
swtor-parser.php
Executable file
171
swtor-parser.php
Executable file
@ -0,0 +1,171 @@
|
|||||||
|
#!/usr/bin/php
|
||||||
|
|
||||||
|
<?php
|
||||||
|
|
||||||
|
$listEncounters = array(
|
||||||
|
## The Dread Fortress
|
||||||
|
'Nefra, Who Bars the Way {3266533082005504}','Gate Commander Draxus {3273924720721920}','Grob\'thok, Who Feeds the Forge {3273929015689216}','Corruptor Zero {3273933310656512}','Dread Master Brontes {3273937605623808}',
|
||||||
|
## Eternity Vault
|
||||||
|
'Soa {2289823159156736}',
|
||||||
|
## Assation
|
||||||
|
'The Writhing Horror {2938874321960960}','Heirad {2938002443599872}','Ciphas {2938011033534464}','Kel\'sara {2938006738567168}','Operator IX {2942606648541184}','Kephess the Undying {2937620191510528}','The Terror From Beyond {2978340776443904}',
|
||||||
|
##
|
||||||
|
'The Eyeless {3328380611067904}',
|
||||||
|
## Toborro
|
||||||
|
'Golden Fury {3232800408862720}', 'Golden Fury {3232817588731904}',
|
||||||
|
## The False Emperor
|
||||||
|
'Tregg the Destroyer {1690314444111872}','Jindo Krey {770959514533888}','HK-47 {770955219566592}','Chondrus Berani {1690331623981056}','Sith Entity {1695962326106112}','Forsaken Sith Lord {781830076760064}','Darth Malgus {770963809501184}',
|
||||||
|
## Battle of Rishi
|
||||||
|
'Marko Ka {3533564083699712}','Rarrook {3533559788732416}','Lord Vodd {3533585558536192}','Shield Squadron Unit 1 {3533594148470784}','Darth Yun {4257506591244288}',
|
||||||
|
## Objective Meridian
|
||||||
|
'Commander Aster {4258021987319808}','Darth Malgus {4257502296276992}',
|
||||||
|
## Heart of Ruin
|
||||||
|
'Colossal Monolith {3541140406009856}',
|
||||||
|
##
|
||||||
|
'Toxxun {3340011382505472}',
|
||||||
|
## Mutated Geonosian Queen
|
||||||
|
'Mutated Geonosian Queen {4197299739688960}'
|
||||||
|
);
|
||||||
|
|
||||||
|
$dmgTypes = array('energy','elemental','kinetic','internal');
|
||||||
|
$instTypes = array('Story','Veteran','Master');
|
||||||
|
$zoneNames = array(
|
||||||
|
# Planet zones
|
||||||
|
'Corellia','Coruscant','CZ-198','Rishi','Taris','Tatooine','Voss','Yavin 4','Ziost',
|
||||||
|
# Instances zones
|
||||||
|
'Lair of the Eyeless','Toborro\'s Palace Courtyard','The False Emperor','Battle of Rishi','Objective Meridian','Hive of the Mountain Queen'
|
||||||
|
);
|
||||||
|
|
||||||
|
class loadFile
|
||||||
|
{
|
||||||
|
// Declare properties
|
||||||
|
public $filename = "";
|
||||||
|
public $handle = null;
|
||||||
|
|
||||||
|
// Constructor
|
||||||
|
public function __construct(){
|
||||||
|
// echo 'The class "' . __CLASS__ . '" was initiated!<br>';
|
||||||
|
$this->fileName = "";
|
||||||
|
$this->handle = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Destructor
|
||||||
|
public function __destruct(){
|
||||||
|
// echo 'The class "' . __CLASS__ . '" was destroyed.<br>';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Method to get the filename
|
||||||
|
public function getFileName(){
|
||||||
|
return $this->fileName;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Method to set the filename
|
||||||
|
public function setFileName($filename){
|
||||||
|
$this->fileName = $filename;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Method to get the handle content
|
||||||
|
public function getHandle(){
|
||||||
|
// TODO Check file exists
|
||||||
|
$this->handle = fopen($this->fileName, "r");
|
||||||
|
// if($this->handle) {
|
||||||
|
// while (($line = fgets($this->handle)) !== false) {
|
||||||
|
// echo $line;
|
||||||
|
// }
|
||||||
|
// fclose($this->handle);
|
||||||
|
// } else {
|
||||||
|
// $this->handle = False;
|
||||||
|
// }
|
||||||
|
|
||||||
|
return $this->handle;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// class Event:
|
||||||
|
// regex = r'[\[<\(]([^\[<\(\]>\)]*)[\]>\)]'
|
||||||
|
// def __init__(self, x):
|
||||||
|
// data = re.findall(Event.regex, x)
|
||||||
|
// data.append('')
|
||||||
|
// self.to_string = ' '.join(data)
|
||||||
|
//
|
||||||
|
// dateandtime = datetime.strptime(list(sys.argv[1].split("_"))[1]+" "+data[0], '%Y-%m-%d %H:%M:%S.%f')
|
||||||
|
//
|
||||||
|
// self.date = dateandtime
|
||||||
|
// self.source = Entity(data[1])
|
||||||
|
// self.target = Entity(data[2])
|
||||||
|
// self.ability = Ability(data[3])
|
||||||
|
// self.effect = Effect(data[4])
|
||||||
|
// self.value = Value(data[5])
|
||||||
|
// self.threat = Threat(data[6])
|
||||||
|
|
||||||
|
class LogEvent
|
||||||
|
{
|
||||||
|
// Properties declaration
|
||||||
|
public $event = "";
|
||||||
|
// public $date = "";
|
||||||
|
// public $source = "";
|
||||||
|
// public $target = "";
|
||||||
|
// public $ability = "";
|
||||||
|
// public $effect = "";
|
||||||
|
// public $value = 0;
|
||||||
|
// public $threat = 0;
|
||||||
|
|
||||||
|
// Constructor
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
// echo 'The class "' . __CLASS__ . '" was initiated!<br>';
|
||||||
|
$this->event = "";
|
||||||
|
// $this->date = $date;
|
||||||
|
// $this->source = $source;
|
||||||
|
// $this->target = $target;
|
||||||
|
// $this->ability = $ability;
|
||||||
|
// $this->effect = $effect;
|
||||||
|
// $this->value = $value;
|
||||||
|
// $this->threat = $threat;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Destructor
|
||||||
|
public function __destruct(){
|
||||||
|
// echo 'The class "' . __CLASS__ . '" was destroyed.<br>';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Method to set the event
|
||||||
|
public function arrayEvent($logEvent){
|
||||||
|
// [23:40:42.150] [@Comendatore] [Combat Training Target MK-10 {2816257300627456}:133000004817] [Ion Pulse {2199843594305536}] [ApplyEffect {836045448945477}: Damage {836045448945501}] (7659* elemental {836045448940875}) <19146>
|
||||||
|
// [date] [src] [target] [ability] [effect] (value) <threat>
|
||||||
|
$isMatching = preg_match_all('/[\[<\(]([^\[<\(\]>\)]*)[\]>\)]/m', $logEvent, $this->event, PREG_SET_ORDER, 0);
|
||||||
|
return $this->event;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// $handle = fopen("combat_2020-06-11_18_06_42_493608.txt", "r");
|
||||||
|
$handlecontent = new loadFile;
|
||||||
|
$handlecontent->setFileName("combat_2020-07-25_22_39_58_532658.txt");
|
||||||
|
$handleresult = $handlecontent->getHandle();
|
||||||
|
|
||||||
|
if($handleresult) {
|
||||||
|
$totalAmount=0;$totalThreat=0;
|
||||||
|
while (($line = fgets($handleresult)) !== false) {
|
||||||
|
$log = new LogEvent;
|
||||||
|
$log = $log->arrayEvent($line);
|
||||||
|
if( array_key_exists(6, $log) );
|
||||||
|
// print_r($log);
|
||||||
|
$logDate = $log[0][1];
|
||||||
|
$logSource = $log[1][1];
|
||||||
|
$logTarget = $log[2][1];
|
||||||
|
$logAbility = $log[3][1];
|
||||||
|
$logEffect = $log[4][1];
|
||||||
|
$logValue = (isset($log[5][1]) && ($log[5][1] != 0))?$log[5][1]:null;
|
||||||
|
$logThreat = isset($log[6][1])?$log[6][1]:null;
|
||||||
|
print("Date : ".$logDate." Source : ".$logSource." Target : ".$logTarget." Ability : ".$logAbility." Effect : ".$logEffect." Amount : ".$logValue." Menace : ".$logThreat."\n");
|
||||||
|
|
||||||
|
// if( $log[1][1]
|
||||||
|
|
||||||
|
$totalAmount+=$logValue;$totalThreat+=$logThreat;
|
||||||
|
}
|
||||||
|
print("Total Damages : ".$totalAmount."\n");
|
||||||
|
print("Total Menace : ".$totalThreat."\n");
|
||||||
|
} else {
|
||||||
|
echo "Error while loading file handle !";
|
||||||
|
}
|
||||||
|
?>
|
318
swtor-parser.py
Executable file
318
swtor-parser.py
Executable file
@ -0,0 +1,318 @@
|
|||||||
|
#!/usr/bin/python
|
||||||
|
|
||||||
|
import os, re, sys
|
||||||
|
from time import strftime
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
#import matplotlib.pyplot as plt
|
||||||
|
|
||||||
|
## Declaring the points for first line plot
|
||||||
|
#X1 = [1,2,3,4,5]
|
||||||
|
#Y1 = [2,4,6,8,10]
|
||||||
|
|
||||||
|
## Setting the figure size
|
||||||
|
#fig = plt.figure(figsize=(10,5))
|
||||||
|
|
||||||
|
## plotting the first plot
|
||||||
|
#plt.plot(X1, Y1, label = "plot 1")
|
||||||
|
|
||||||
|
## Declaring the points for second line plot
|
||||||
|
#X2 = [1,2,3,4,5]
|
||||||
|
#Y2 = [1,4,9,16,25]
|
||||||
|
|
||||||
|
## plotting the second plot
|
||||||
|
#plt.plot(X2, Y2, label = "plot 2")
|
||||||
|
|
||||||
|
## Labeling the X-axis
|
||||||
|
#plt.xlabel('X-axis')
|
||||||
|
|
||||||
|
## Labeling the Y-axis
|
||||||
|
#plt.ylabel('Y-axis')
|
||||||
|
|
||||||
|
## Give a title to the graph
|
||||||
|
#plt.title('Two plots on the same graph')
|
||||||
|
|
||||||
|
## Show a legend on the plot
|
||||||
|
#plt.legend()
|
||||||
|
|
||||||
|
##Saving the plot as an image
|
||||||
|
#fig.savefig('line plot.png', bbox_inches='tight', dpi=150)
|
||||||
|
|
||||||
|
##Showing the plot
|
||||||
|
#plt.show()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# [03/16/2012 22:53:45] [@Asdffljklasdfj] [@Asdffljklasdfj] [Unnatural Might {1781509484707840}] [RemoveEffect {836045448945478}: Unnatural Might {1781509484707840}] ()
|
||||||
|
# [21:18:16.172] [@Comendatore] [@Comendatore] [] [Event {836045448945472}: EnterCombat {836045448945489}] (Asation (8 Player Story))
|
||||||
|
#[date] [src] [target] [ability] [effect] (value) <threat>
|
||||||
|
#src = [foo {id}] or [@player]
|
||||||
|
# ability = abil {id}
|
||||||
|
# effect = type:effect
|
||||||
|
# value = # or # type
|
||||||
|
# roll? int
|
||||||
|
|
||||||
|
listEncounters = [
|
||||||
|
## The Dread Fortress
|
||||||
|
'Nefra, Who Bars the Way {3266533082005504}','Gate Commander Draxus {3273924720721920}','Grob\'thok, Who Feeds the Forge {3273929015689216}','Corruptor Zero {3273933310656512}','Dread Master Brontes {3273937605623808}',
|
||||||
|
## Eternity Vault
|
||||||
|
'Soa {2289823159156736}',
|
||||||
|
##
|
||||||
|
'The Writhing Horror {2938874321960960}','Heirad {2938002443599872}','Ciphas {2938011033534464}','Kel\'sara {2938006738567168}','Operator IX {2942606648541184}','Kephess the Undying {2937620191510528}','The Terror From Beyond {2978340776443904}','The Terror From Beyond {3025233229381632}',
|
||||||
|
##
|
||||||
|
'The Eyeless {3328380611067904}','Golden Fury {3232800408862720}','Golden Fury {3232817588731904}',
|
||||||
|
## The False Emperor
|
||||||
|
'Tregg the Destroyer {1690314444111872}','Jindo Krey {770959514533888}','HK-47 {770955219566592}','Chondrus Berani {1690331623981056}','Sith Entity {1695962326106112}','Forsaken Sith Lord {781830076760064}','Darth Malgus {770963809501184}',
|
||||||
|
## Battle of Rishi
|
||||||
|
'Marko Ka {3533564083699712}','Rarrook {3533559788732416}','Lord Vodd {3533585558536192}','Shield Squadron Unit 1 {3533594148470784}','Darth Yun {4257506591244288}',
|
||||||
|
## Objective Meridian
|
||||||
|
'Commander Aster {4258021987319808}','Darth Malgus {4257502296276992}',
|
||||||
|
## Heart of Ruin
|
||||||
|
'Colossal Monolith {3541140406009856}',
|
||||||
|
##
|
||||||
|
'Toxxun {3340011382505472}',
|
||||||
|
## Mutated Geonosian Queen
|
||||||
|
'Mutated Geonosian Queen {4197299739688960}',
|
||||||
|
##
|
||||||
|
'SCYVA {4108140513591296}'
|
||||||
|
]
|
||||||
|
|
||||||
|
dmgTypes = ['energy','elemental','kinetic','internal']
|
||||||
|
instTypes = ['Story','Veteran','Master']
|
||||||
|
zoneNames = [
|
||||||
|
# Planet zones
|
||||||
|
'Corellia','Coruscant','CZ-198','Rishi','Taris','Tatooine','Voss','Yavin 4','Ziost',
|
||||||
|
# Instances zones
|
||||||
|
'Asation','Lair of the Eyeless','Toborro\'s Palace Courtyard','The False Emperor','Battle of Rishi','Objective Meridian','Hive of the Mountain Queen',
|
||||||
|
# Operations Zones
|
||||||
|
'Valley of the Machine Gods'
|
||||||
|
]
|
||||||
|
|
||||||
|
class Event:
|
||||||
|
regex = r'[\[<\(]([^\[<\(\]>\)]*)[\]>\)]'
|
||||||
|
def __init__(self, x):
|
||||||
|
data = re.findall(Event.regex, x)
|
||||||
|
data.append('')
|
||||||
|
self.to_string = ' '.join(data)
|
||||||
|
|
||||||
|
dateandtime = datetime.strptime(list(sys.argv[1].split("_"))[1]+" "+data[0], '%Y-%m-%d %H:%M:%S.%f')
|
||||||
|
|
||||||
|
self.date = dateandtime
|
||||||
|
self.source = Entity(data[1])
|
||||||
|
self.target = Entity(data[2])
|
||||||
|
self.ability = Ability(data[3])
|
||||||
|
self.effect = Effect(data[4])
|
||||||
|
self.value = Value(data[5])
|
||||||
|
self.threat = Threat(data[6])
|
||||||
|
|
||||||
|
class Entity:
|
||||||
|
def __init__(self, x):
|
||||||
|
if not x:
|
||||||
|
self.name = x
|
||||||
|
self.player = False
|
||||||
|
#print(x+" is not a player !")
|
||||||
|
elif x[0] == '@':
|
||||||
|
self.name = x[1:]
|
||||||
|
self.player = True
|
||||||
|
#print(x+" is a player !")
|
||||||
|
else:
|
||||||
|
self.name = x
|
||||||
|
self.player = False
|
||||||
|
#print(x+" is not a player !")
|
||||||
|
|
||||||
|
class Ability:
|
||||||
|
def __init__(self, x):
|
||||||
|
self.name = x
|
||||||
|
|
||||||
|
class Effect:
|
||||||
|
def __init__(self, x):
|
||||||
|
if not x:
|
||||||
|
self.type = ''
|
||||||
|
self.detail = ''
|
||||||
|
return
|
||||||
|
foo = x.split(':')
|
||||||
|
if len(foo) > 1:
|
||||||
|
self.type = foo[0]
|
||||||
|
self.detail = foo[1]
|
||||||
|
else:
|
||||||
|
self.type = x
|
||||||
|
self.detail = ''
|
||||||
|
|
||||||
|
#class Value:
|
||||||
|
#def __init__(self, x):
|
||||||
|
#if not x:
|
||||||
|
#self.value = 0
|
||||||
|
#self.type = ''
|
||||||
|
#return
|
||||||
|
#foo = x.replace('*','').split(' ')
|
||||||
|
#self.value = int(foo[0])
|
||||||
|
#if len(foo) > 1:
|
||||||
|
#self.type = foo[1]
|
||||||
|
#else:
|
||||||
|
#self.type=''
|
||||||
|
|
||||||
|
# [20:06:53.053] [@Comendatore] [@Comendatore] [] [Event {836045448945472}: EnterCombat {836045448945489}] (Ziost)
|
||||||
|
# [21:31:45.974] [@Comendatore] [@Comendatore] [] [Event {836045448945472}: EnterCombat {836045448945489}] (Hive of the Mountain Queen (8 Player Story))
|
||||||
|
# [21:32:18.105] [@Bidobulle] [@Comendatore] [Slow-release Medpac {3406415871868928}] [ApplyEffect {836045448945477}: Heal {836045448945500}] (5683*)
|
||||||
|
# [21:32:19.499] [@Bidobulle] [@Comendatore] [Slow-release Medpac {3406415871868928}] [ApplyEffect {836045448945477}: Heal {836045448945500}] (3641)
|
||||||
|
# [22:37:11.036] [@Comendatore] [Colossal Monolith {3541140406009856}:15814000004760] [Shocked {2044520397013249}] [ApplyEffect {836045448945477}: Damage {836045448945501}] (165 energy {836045448940874}) <1646>
|
||||||
|
# [22:37:46.168] [@Comendatore] [Colossal Monolith {3541140406009856}:15814000004760] [Ion Storm {3389987621961728}] [ApplyEffect {836045448945477}: Damage {836045448945501}] (20879* elemental {836045448940875}) <52197>
|
||||||
|
# [22:37:51.623] [Colossal Monolith {3541140406009856}:15814000004760] [@Comendatore] [Great Slam {3543287889657856}] [ApplyEffect {836045448945477}: Damage {836045448945501}] (86 kinetic {836045448940873} -shield {836045448945509} (86 absorbed {836045448945511})) <86>
|
||||||
|
# [22:38:30.231] [Colossal Monolith {3541140406009856}:15814000004760] [@Comendatore] [Bleeding {3546045258662192}] [ApplyEffect {836045448945477}: Damage {836045448945501}] (10668 internal {836045448940876}) <10668>
|
||||||
|
|
||||||
|
class Value:
|
||||||
|
def __init__(self, x):
|
||||||
|
if not x:
|
||||||
|
self.value = 0
|
||||||
|
self.type = ''
|
||||||
|
return
|
||||||
|
foo = x.replace('*','')
|
||||||
|
#print(foo)
|
||||||
|
#if not re.search('[a-zA-Z]+', x):
|
||||||
|
#print(foo)
|
||||||
|
if any(z in foo for z in dmgTypes) and not any(y in foo for y in instTypes) or not any(w in foo for w in zoneNames) or foo.isdigit():
|
||||||
|
foo = x.replace('*','').split(' ')
|
||||||
|
if foo[0].isdigit():
|
||||||
|
self.value = int(foo[0])
|
||||||
|
else:
|
||||||
|
self.value = 0
|
||||||
|
if len(foo) > 1:
|
||||||
|
self.type = foo[1]
|
||||||
|
else:
|
||||||
|
self.type=''
|
||||||
|
else:
|
||||||
|
#print(foo)
|
||||||
|
self.type = ''
|
||||||
|
|
||||||
|
class Threat:
|
||||||
|
def __init__(self, x):
|
||||||
|
if not x:
|
||||||
|
self.value = 0
|
||||||
|
self.type = ''
|
||||||
|
return
|
||||||
|
foo = x.replace('*','').split(' ')
|
||||||
|
self.value = int(foo[0])
|
||||||
|
if len(foo) > 1:
|
||||||
|
self.type = foo[1]
|
||||||
|
else:
|
||||||
|
self.type=''
|
||||||
|
|
||||||
|
#date, source, target, ability, effect.type/detail, value.value/type, threat
|
||||||
|
# TODO:
|
||||||
|
# multiple sources
|
||||||
|
# more interesting output, graphs? What about that metric site? Google charts?
|
||||||
|
# App engine seems fun
|
||||||
|
# Details for abilities:
|
||||||
|
# dmg per ability
|
||||||
|
# Combine multiple entries per ability
|
||||||
|
def main():
|
||||||
|
if len(sys.argv) == 1:
|
||||||
|
filename = 'combat_2020-07-25_22_39_58_532658.txt'
|
||||||
|
print('File not specified, defaulting to ' + filename)
|
||||||
|
else:
|
||||||
|
filename = sys.argv[1]
|
||||||
|
file = open(filename, 'r')
|
||||||
|
events = []
|
||||||
|
for line in file.readlines():
|
||||||
|
events.append(Event(line))
|
||||||
|
|
||||||
|
players = set([event.source.name for event in events])
|
||||||
|
fights = []
|
||||||
|
isBoss = False
|
||||||
|
fight = []
|
||||||
|
for event in events:
|
||||||
|
if 'EnterCombat' in event.effect.detail:
|
||||||
|
fight = []
|
||||||
|
#fight.extend(fight)
|
||||||
|
#isBoss = False
|
||||||
|
|
||||||
|
if 'Death' in event.effect.detail:
|
||||||
|
#print(event.effect.detail)
|
||||||
|
#if any(t in event.target.name for t in listEncounters):
|
||||||
|
fight.append(event)
|
||||||
|
#print(listEncounters)
|
||||||
|
#isBoss = False
|
||||||
|
for event in fight:
|
||||||
|
##print(event.source.name)
|
||||||
|
if any(t in event.target.name for t in listEncounters):
|
||||||
|
isBoss = True
|
||||||
|
if isBoss:
|
||||||
|
fights.append(fight)
|
||||||
|
fight = []
|
||||||
|
continue
|
||||||
|
|
||||||
|
if 'ExitCombat' in event.effect.detail:
|
||||||
|
#if any(t in event.effect.detail for t in ['ExitCombat','Death']):
|
||||||
|
fight.append(event)
|
||||||
|
#print(listEncounters)
|
||||||
|
isBoss = False
|
||||||
|
for event in fight:
|
||||||
|
#print(event.source.name)
|
||||||
|
if any(t in event.target.name for t in listEncounters):
|
||||||
|
isBoss = True
|
||||||
|
if isBoss:
|
||||||
|
fights.append(fight)
|
||||||
|
fight = []
|
||||||
|
continue
|
||||||
|
|
||||||
|
fight.append(event)
|
||||||
|
|
||||||
|
for i, fight in enumerate(fights):
|
||||||
|
duration = fight[-1].date - fight[0].date
|
||||||
|
for event in fight:
|
||||||
|
if any(t in event.target.name for t in listEncounters):
|
||||||
|
namedTarget = event.target.name.split(' {')
|
||||||
|
namedTarget = namedTarget[0]
|
||||||
|
#print('\nCombat Statistics for Fight # %d (duration: %s)' %(i+1, str(duration)))
|
||||||
|
print('\nCombat Statistics for Fight #%d -> %s (%s)' %(i+1, namedTarget, str(duration)))
|
||||||
|
print("Started: " + str(fight[0].date) +" Ended: " + str(fight[-1].date))
|
||||||
|
for player in players:
|
||||||
|
if '{' not in player:
|
||||||
|
dmg = 0
|
||||||
|
tdmg = 0
|
||||||
|
heal = 0
|
||||||
|
theal = 0
|
||||||
|
threat = 0
|
||||||
|
death = False
|
||||||
|
for event in fight:
|
||||||
|
## Domages done by player (DPS)
|
||||||
|
if event.source.name == player and 'Damage ' in event.effect.detail:
|
||||||
|
dmg += event.value.value
|
||||||
|
## Domages taken by player (DTPS)
|
||||||
|
if event.target.name == player and 'Damage ' in event.effect.detail:
|
||||||
|
tdmg += event.value.value
|
||||||
|
## Heal done by player (HPS)
|
||||||
|
if event.source.name == player and 'Heal ' in event.effect.detail:
|
||||||
|
heal += event.value.value
|
||||||
|
## Heal received by player (HTPS)
|
||||||
|
if event.target.name == player and 'Heal ' in event.effect.detail:
|
||||||
|
theal += event.value.value
|
||||||
|
## Generated threat by player (TPS)
|
||||||
|
if event.source.name == player and event.threat.value:
|
||||||
|
threat += event.threat.value
|
||||||
|
## Dead
|
||||||
|
if event.source.name == player and 'Death' in event.effect.detail:
|
||||||
|
death = True
|
||||||
|
|
||||||
|
secs = duration.seconds
|
||||||
|
|
||||||
|
if not secs:
|
||||||
|
secs = 1
|
||||||
|
if dmg:
|
||||||
|
print('%s did %d damage in %s (%d DPS)' % (player, dmg, str(duration), dmg/secs))
|
||||||
|
if tdmg:
|
||||||
|
print('%s took %d damage in %s (%d DTPS)' % (player, tdmg, str(duration), tdmg/secs))
|
||||||
|
if heal:
|
||||||
|
print('%s did %d heals in %s (%d HPS)' % (player, heal, str(duration), heal/secs))
|
||||||
|
if theal:
|
||||||
|
print('%s received %d heals in %s (%d HTPS)' % (player, theal, str(duration), theal/secs))
|
||||||
|
if threat:
|
||||||
|
print('%s did %d threat in %s (%d TPS)' % (player, threat, str(duration), threat/secs))
|
||||||
|
if death:
|
||||||
|
print('%s died on %s' % (player, namedTarget))
|
||||||
|
|
||||||
|
|
||||||
|
#print("\n".join([event.to_string for event in events]))
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
Loading…
Reference in New Issue
Block a user