#1
  1. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Sep 2004
    Location
    FL
    Posts
    19
    Rep Power
    0

    creating a dps parser, need some advice


    `lo

    What I'm trying to do is write an app that will read lines from a text log file from a game, parse the data for start/end times of fights and the damge done per fight, get the total seconds fight lasted from the start/end times, and finally apply damage/seconds to get a float dps value.

    The size of the log file is variable, depending on when a player starts/ends the logging. I'm using the readlins() method to put each line(conviently written as newlines for each line by default ^^) into a list(log[]). What I'm trying to do with the list is to create a list of sessions for each fight and have the value for each item in the list be the dps for that fight, the total damage for that fight, the total attempts to hit, total hits landed/missed, and how long the fight took. I'm guessing the best way to do that would be with a list of dictionaries, but I'm starting to feel a little winded with what I've done already , so I want to try to get the basics down first before trying for all that.

    Any way, this is what I have so far for itterating through the list, getting the time stamps for start/end, and getting the damage (haven't done the regex's yet for that, but i want to make sure this works the way i think first). :
    Code:
    fightCnt = 0
    swingCnt = 0
    fightList = []
    stFightList = []
    endFightList = []
    swingList = []
    if place <=  len(log):
        for i in log[place:]:
            stFight = re.match('^.*(You start fighting).',i)
            if stFight:
                stFightTime = re.compile('^.*(\d{2}) (\d{2})\D+(\d{2})\D+(\d{2})')
                stFightList.append(stFightTime.search(log[cnt]).groups())
    	endFight = re.match('^.*(You stop fighting).',i)
    	fightDmg = 0
    	dmgMatch = re.match()
    	dmgMiss = re.match()
    	if dmgMatch:
                fightDmg += string.atoi(dmgMatch.group(2))
    	    swingCnt += 1
    	if dmgMiss:
    	    swingCnt += 1
            if endFight:
                endFightTime = re.compile('^.*(\d{2}) (\d{2})\D+(\d{2})\D+(\d{2})')
                endFightList.append(endFightTime.search(log[cnt]).groups())
                place = log.index(i)
    	    fightCnt = 0
    	    fightList[fightCnt] = fightDmg
    	    swingList[fightCnt] = swingCnt
                fightDmg = 0
            cnt += 1
    the reason for the place is that a log file will almost certainly contain more than one fight in it and i don't want to rerecord any data that's already been taken into account. the final ouput i want looks like this:
    Code:
    Number of fights : [ fightCnt ]
    
    Fight #		Hits		Misses		Dmg		Dps
    sessionID	sessionHit	sessionMiss	sessionDmg	sessionDPS
    
    Overall damage : [ totalDmg ]
    Overall hits   : [ totalHits ]
    Overall misses : [ totalMiss ]
    
    Average dps : [ averageDPS ]
    I'm planning to have the output both be spit out to the console and also into a text file. Later on I want to add a gui to this and make it spit data real time, but that's for much much later one ^^; . Anything seem wonky in that for loop ? Is there a better, faster way to have it done? Are there any output formatting methods like perl's ? Thanks in advanced!
  2. #2
  3. No Profile Picture
    Contributing User
    Devshed Intermediate (1500 - 1999 posts)

    Join Date
    Feb 2004
    Location
    London, England
    Posts
    1,585
    Rep Power
    1373
    The easiest way to see if it works the way you think is to run it.

    Here are some random thoughs from reading through the code:

    0) It is difficult to tell if the code is correct without seeing a sample of the input data.

    1) it is generally better to iterate through a file a line at a time, rather than read the whole thing into memory. File objects are iterable, so you can do this:

    Code:
    log = open('fight.log')
    for line in log:
       #do stuff with line
    2) You do not need to use regex if you just want to test if a substring appears in a string. From Python 2.3 you can use if substr in string: e.g.
    replace
    Code:
            stFight = re.match('^.*(You start fighting).',i)
            if stFight:
    with:
    Code:
            if 'You start fighting' in i:
    3) rather than have several lists that each hold part of the information you want, it is usually better to have one list holding objects that contains all the information for a fight. The object could be a class instance or a dictionary. Having all the information for a fight in one object will make it much easier to deal with afterwards. I suggest you create a new object when you see the line 'You start fighting', and add the object to a list when you see the line 'You stop fighting'.

    4) I notice you set fightDmg to zero every time round the loop. This is clearly a bug if the intention is for it to be holding the cumulative damage.

    The string '%' operator is used for formatting. See http://docs.python.org/lib/typesseq-strings.html

    Dave - The Developers' Coach
  4. #3
  5. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Sep 2004
    Location
    FL
    Posts
    19
    Rep Power
    0
    Thank you for the reply DevCoach, it helps out alot. Here is a sample of the log file:
    Code:
    01:32:54 ] You start fighting.
     01:32:54 ] Your target is too far! Move closer!
     16 01:32:55 ] Bob hits a thingy for 6 points of crushing damage.
     16 01:32:55 ] YOU hit a thingy for 8 points of slashing damage.
     16 01:32:56 ] a thingy tries to crush Bob, but misses.
     16 01:32:57 ] Bob hits a thingy for 9 points of crushing damage.
     16 01:32:57 ] YOUR Kick hits a thingy for 12 points of crushing damage.
    This particular log has over 700 lines, and further logs will have alot more to get a better sampling of dps numbers. It's why I thought it would be better to read the file into memory to have the script run faster.

    3) rather than have several lists that each hold part of the information you want, it is usually better to have one list holding objects that contains all the information for a fight. The object could be a class instance or a dictionary. Having all the information for a fight in one object will make it much easier to deal with afterwards. I suggest you create a new object when you see the line 'You start fighting', and add the object to a list when you see the line 'You stop fighting'.
    I'm having a little trouble understanding how to implement this. I know that lists can hold just about any type of object, but wouldn't it be quite large if it held everything in it and hard to pull the data? Could you give me an example .

    I set fight damage back to 0 because I want to use it for each instance of a fight. A log file contains more than one fight and having it not set to 0 for each new fight would throw the numbers off. To get over all damage, at the end I can just add the total damage from each fight because that is stored in one of the lists.

IMN logo majestic logo threadwatch logo seochat tools logo