all latent changes, undisclosed and without warranty.
This commit is contained in:
		
							parent
							
								
									8411ed858c
								
							
						
					
					
						commit
						10c557dea3
					
				
							
								
								
									
										28
									
								
								analyze.py
									
									
									
									
									
								
							
							
						
						
									
										28
									
								
								analyze.py
									
									
									
									
									
								
							@ -27,31 +27,39 @@ if __name__ == '__main__':
 | 
			
		||||
                        'Documents', 'My Games', 'sc'))
 | 
			
		||||
    coll.collect_unique()
 | 
			
		||||
    #f = open('output.txt', 'w')
 | 
			
		||||
    rex = {}
 | 
			
		||||
    rex_combat = {}
 | 
			
		||||
    rex_game = {}
 | 
			
		||||
    for logf in coll.sessions:
 | 
			
		||||
        logf.parse_files(['game.log',])
 | 
			
		||||
        print "Combat Log %s" % logf.idstr
 | 
			
		||||
        logf.parse_files(['game.log', 'combat.log'])
 | 
			
		||||
        print "----- Log %s -----" % logf.idstr
 | 
			
		||||
        if logf.combat_log:
 | 
			
		||||
            for l in logf.combat_log.lines:
 | 
			
		||||
                if isinstance(l, dict):
 | 
			
		||||
                    #print l
 | 
			
		||||
                    pass
 | 
			
		||||
                    rex_combat['dict'] = rex_combat.get('dict', 0) + 1
 | 
			
		||||
                else:
 | 
			
		||||
                    if not l.unpack():
 | 
			
		||||
                        rex[l.__class__.__name__] = rex.get(l.__class__.__name__, 0) + 1
 | 
			
		||||
                        rex_combat[l.__class__.__name__] = rex_combat.get(l.__class__.__name__, 0) + 1
 | 
			
		||||
                        if not isinstance(l, combat.UserEvent):
 | 
			
		||||
                            print l.values['log']
 | 
			
		||||
        if logf.game_log:
 | 
			
		||||
            for l in logf.game_log.lines:
 | 
			
		||||
                if isinstance(l, dict):
 | 
			
		||||
                    pass
 | 
			
		||||
                    rex_game['dict'] = rex_game.get('dict', 0) + 1 
 | 
			
		||||
                elif isinstance(l, str):
 | 
			
		||||
                    print l
 | 
			
		||||
                else:
 | 
			
		||||
                    if l.unpack():
 | 
			
		||||
                        pass
 | 
			
		||||
                    else:
 | 
			
		||||
                        rex_game[l.__class__.__name__] = rex_game.get(l.__class__.__name__, 0) + 1
 | 
			
		||||
                        print l.values['log']
 | 
			
		||||
                    # ClientInfo introspection for ping
 | 
			
		||||
                    if isinstance(l, ClientInfo) and l.values.get('clinfo', '') == 'avgPing':
 | 
			
		||||
                        print l.values
 | 
			
		||||
                        # fix avgPing parsing!
 | 
			
		||||
    print rex
 | 
			
		||||
                    #if isinstance(l, ClientInfo) and l.values.get('clinfo', '') == 'avgPing':
 | 
			
		||||
                    #    print l.values
 | 
			
		||||
                    #    # fix avgPing parsing!
 | 
			
		||||
    print 'Analysis complete:'
 | 
			
		||||
    print '#'*20+' RexCombat ' + '#' *20
 | 
			
		||||
    print rex_combat
 | 
			
		||||
    print '#'*20+' RexGame ' + '#' *20
 | 
			
		||||
    print rex_game
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										31
									
								
								battle.py
									
									
									
									
									
								
							
							
						
						
									
										31
									
								
								battle.py
									
									
									
									
									
								
							@ -1,2 +1,33 @@
 | 
			
		||||
#!/usr/bin/python
 | 
			
		||||
# -*- coding: utf-8 -*-
 | 
			
		||||
"""
 | 
			
		||||
    Tool to analyze Logs in general.
 | 
			
		||||
"""
 | 
			
		||||
import os, sys, logging
 | 
			
		||||
from logs.logfiles import LogFileResolver as LogFile
 | 
			
		||||
from logs import combat, game, chat
 | 
			
		||||
from logs.session import LogSessionCollector
 | 
			
		||||
from logs.game import ClientInfo
 | 
			
		||||
 | 
			
		||||
# for windows its kinda this:
 | 
			
		||||
settings = {'root_path': os.path.join(os.path.expanduser('~'),
 | 
			
		||||
                                     'Documents',
 | 
			
		||||
                                     'My Games',
 | 
			
		||||
                                     'StarConflict',),            
 | 
			
		||||
            'logfiles': os.path.join(os.path.expanduser('~'),
 | 
			
		||||
                                     'Documents',
 | 
			
		||||
                                     'My Games',
 | 
			
		||||
                                     'StarConflict',
 | 
			
		||||
                                     'logs'
 | 
			
		||||
                                     )}
 | 
			
		||||
if __name__ == '__main__':
 | 
			
		||||
    coll = LogSessionCollector(os.path.join(os.path.expanduser('~'),
 | 
			
		||||
                        'Documents', 'My Games', 'sc'))
 | 
			
		||||
    coll.collect_unique()
 | 
			
		||||
    for logf in coll.sessions:
 | 
			
		||||
        logf.parse_files(['game.log', 'combat.log'])
 | 
			
		||||
        logf.clean()
 | 
			
		||||
        if logf.combat_log:
 | 
			
		||||
            print 'length combat log ', len(logf.combat_log.lines)
 | 
			
		||||
        if logf.game_log:
 | 
			
		||||
            print 'length game log ', len(logf.game_log.lines)
 | 
			
		||||
@ -28,6 +28,7 @@ QUALITY_TYPES = (
 | 
			
		||||
  (5, 'Mk5'),
 | 
			
		||||
  (10, 'Universal'),
 | 
			
		||||
  (14, 'Pirate Mk4'),
 | 
			
		||||
  (99, 'Alien'),
 | 
			
		||||
  )
 | 
			
		||||
D_QUALITY = dict(QUALITY_TYPES)
 | 
			
		||||
 | 
			
		||||
@ -51,9 +52,13 @@ ROLE_TYPES = (
 | 
			
		||||
  (6, 'Gunship'),
 | 
			
		||||
  (7, 'Engineer'),
 | 
			
		||||
  (8, 'Guard'),
 | 
			
		||||
  (9, 'Longrange')    
 | 
			
		||||
  (9, 'Longrange'),
 | 
			
		||||
  (10, 'Interceptors'),
 | 
			
		||||
  (20, 'Fighters'),
 | 
			
		||||
  (30, 'Frigates'),    
 | 
			
		||||
  )
 | 
			
		||||
# Create your models here.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Item(models.Model):
 | 
			
		||||
    name = models.CharField(max_length=128)
 | 
			
		||||
    description = models.TextField(blank=True, null=True)
 | 
			
		||||
 | 
			
		||||
@ -5,13 +5,25 @@
 | 
			
		||||
"""
 | 
			
		||||
 | 
			
		||||
class Battle(object):
 | 
			
		||||
    __slots__ = ['players',
 | 
			
		||||
                 'teams', 
 | 
			
		||||
                 'time_start',
 | 
			
		||||
                 'time_end',]
 | 
			
		||||
    def __init__(self, parent=None):
 | 
			
		||||
        # parent is a log-session usually
 | 
			
		||||
        self.players = []
 | 
			
		||||
        self.teams = []
 | 
			
		||||
        self.time_start = None
 | 
			
		||||
        self.time_end = None
 | 
			
		||||
        self.owner = None
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
def battle_factory(logs):
 | 
			
		||||
    ''' takes a log session and returns the battles in it 
 | 
			
		||||
        makes a preliminary scan for information
 | 
			
		||||
    '''
 | 
			
		||||
    
 | 
			
		||||
    if logs.combat_log and logs.game_log:
 | 
			
		||||
        # without these it does not make sense
 | 
			
		||||
        # check combat_log
 | 
			
		||||
        
 | 
			
		||||
        pass
 | 
			
		||||
    
 | 
			
		||||
    return []
 | 
			
		||||
    
 | 
			
		||||
        
 | 
			
		||||
							
								
								
									
										28
									
								
								game/screener.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								game/screener.py
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,28 @@
 | 
			
		||||
#
 | 
			
		||||
#
 | 
			
		||||
#
 | 
			
		||||
"""
 | 
			
		||||
    Screener Module.
 | 
			
		||||
    
 | 
			
		||||
    Upon receiving a logfile, the screener module tries a first pass to retrieve the informations:
 | 
			
		||||
     - who am i? am i in steam? 
 | 
			
		||||
     - which os do i use? whats the date? other specifics?
 | 
			
		||||
     - battles, when did they begin, when did they end, which players were in it, which teams (game.log)
 | 
			
		||||
    
 | 
			
		||||
    It should act as a factory for a second, more in depth parsing mechanism, which can retrieve and
 | 
			
		||||
    manage the rest of the details.
 | 
			
		||||
     
 | 
			
		||||
"""
 | 
			
		||||
class Information:
 | 
			
		||||
    def __init__(self):
 | 
			
		||||
        self.steam_id = None # steam id
 | 
			
		||||
        self.steam_username = None # optional steam username.
 | 
			
		||||
        self.username = None # ingame username.
 | 
			
		||||
        self.uid = None # does not change.
 | 
			
		||||
        self.pid = None # changes per battle. needed once to identify pilot.
 | 
			
		||||
        
 | 
			
		||||
        
 | 
			
		||||
        
 | 
			
		||||
class Screener(object):
 | 
			
		||||
    def __init__(self):
 | 
			
		||||
        pass
 | 
			
		||||
@ -92,11 +92,14 @@ class WarningLog(Log):
 | 
			
		||||
# Individual logs.
 | 
			
		||||
 | 
			
		||||
class SteamInitialization(GameLog):
 | 
			
		||||
    matcher = []
 | 
			
		||||
    matcher = [
 | 
			
		||||
        re.compile(r"^Steam\sinitialized\sappId\s(?P<steam_app_id>\d+),\suserSteamID\s(?P<steam_id_universe>\d+)\|(?P<steam_id_type>\d+)\|(?P<steam_id_account_hex>\w+),\suserName\s'(?P<steam_username>[^']+)'"),
 | 
			
		||||
        ]
 | 
			
		||||
 | 
			
		||||
class MasterServerSession(GameLog):
 | 
			
		||||
    matcher = [
 | 
			
		||||
        re.compile(r"^MasterServerSession\:\sconnect\sto\sdedicated\sserver(?:,\s|session\s(?P<session_id>\d+)|at addr (?P<addr>\d+\.\d+\.\d+\.\d+)\|(?P<port>\d+))+"),
 | 
			
		||||
        re.compile(r"^MasterServerSession:\sconnect\sto\sZoneInstance,\ssession\s(?P<session_id>\d+),\sat\saddr\s(?P<addr>\d+\.\d+\.\d+\.\d+)\|(?P<port>\d+),\szoneId\s(?P<zone_id>\d+)"),
 | 
			
		||||
        ]
 | 
			
		||||
    
 | 
			
		||||
    @classmethod
 | 
			
		||||
 | 
			
		||||
@ -9,6 +9,7 @@
 | 
			
		||||
    data by setting the LogFile<instance>._data yourself.
 | 
			
		||||
"""
 | 
			
		||||
import re
 | 
			
		||||
from .base import Log
 | 
			
		||||
RE_SCLOG = r'^(?P<hh>\d{2,2})\:(?P<mm>\d{2,2})\:(?P<ss>\d{2,2})\.(?P<ns>\d{3,3})\s(?P<logtype>\s*[^\|\s]+\s*|\s+)\|\s(?P<log>.*)'
 | 
			
		||||
R_SCLOG = re.compile(RE_SCLOG) 
 | 
			
		||||
 | 
			
		||||
@ -34,6 +35,15 @@ class LogFile(object):
 | 
			
		||||
    def _unset_data(self):
 | 
			
		||||
        self._data = None
 | 
			
		||||
        
 | 
			
		||||
    def filter(self, klasses):
 | 
			
		||||
        ret = []
 | 
			
		||||
        for line in self.lines:
 | 
			
		||||
            for k in klasses:
 | 
			
		||||
                if isinstance(line, k):
 | 
			
		||||
                    ret.append(line)
 | 
			
		||||
                    break
 | 
			
		||||
        return ret
 | 
			
		||||
    
 | 
			
		||||
    def parse(self):
 | 
			
		||||
        # parse _data if we still have no lines.
 | 
			
		||||
        if self._data:
 | 
			
		||||
@ -84,3 +94,17 @@ class LogFile(object):
 | 
			
		||||
        # try to find a class that is responsible for this log.
 | 
			
		||||
        return line
 | 
			
		||||
    
 | 
			
		||||
    def clean(self):
 | 
			
		||||
        # cleans the logs by removing all non parsed packets.
 | 
			
		||||
        lines = []
 | 
			
		||||
        for l in self.lines:
 | 
			
		||||
            if isinstance(l, Log):
 | 
			
		||||
                if l.unpack():
 | 
			
		||||
                    if not getattr(l, 'trash', False):
 | 
			
		||||
                        lines.append(l)
 | 
			
		||||
                    else:
 | 
			
		||||
                        print type(l)
 | 
			
		||||
                        print l
 | 
			
		||||
        self.lines = lines
 | 
			
		||||
        self._unset_data()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -15,6 +15,7 @@ class LogSession(object):
 | 
			
		||||
        ''' if directory is a file, it will be handled as a compressed folder '''
 | 
			
		||||
        self.battles = []
 | 
			
		||||
        self.user = None
 | 
			
		||||
        self.files_parsed = []
 | 
			
		||||
        
 | 
			
		||||
        # various logfiles used.
 | 
			
		||||
        self.combat_log = None
 | 
			
		||||
@ -27,6 +28,15 @@ class LogSession(object):
 | 
			
		||||
        self.idstr = None # id string to identify this log instance.
 | 
			
		||||
        self._error = False
 | 
			
		||||
    
 | 
			
		||||
    def clean(self):
 | 
			
		||||
        if self.combat_log:
 | 
			
		||||
            self.combat_log.clean()
 | 
			
		||||
        if self.game_log:
 | 
			
		||||
            self.game_log.clean()
 | 
			
		||||
        if self.chat_log:
 | 
			
		||||
            self.chat_log.clean()
 | 
			
		||||
        
 | 
			
		||||
    
 | 
			
		||||
    def validate(self, contents=False):
 | 
			
		||||
        """ 
 | 
			
		||||
          - validates if the logfiles are within this package.
 | 
			
		||||
@ -56,14 +66,18 @@ class LogSession(object):
 | 
			
		||||
        if self._zip_source:
 | 
			
		||||
            self._unzip_logs(files)
 | 
			
		||||
        else:
 | 
			
		||||
            if 'combat.log' in files:
 | 
			
		||||
            if files is None:
 | 
			
		||||
                files = self.VALID_FILES
 | 
			
		||||
            if 'combat.log' in files and not 'combat.log' in self.files_parsed:
 | 
			
		||||
                self.combat_log = CombatLogFile(os.path.join(self.directory, 'combat.log'))
 | 
			
		||||
                self.combat_log.read()
 | 
			
		||||
                self.combat_log.parse()
 | 
			
		||||
            if 'game.log' in files:
 | 
			
		||||
                self.files_parsed.append('combat.log')
 | 
			
		||||
            if 'game.log' in files and not 'game.log' in self.files_parsed:
 | 
			
		||||
                self.game_log = GameLogFile(os.path.join(self.directory, 'game.log'))
 | 
			
		||||
                self.game_log.read()
 | 
			
		||||
                self.game_log.parse()
 | 
			
		||||
                self.files_parsed.append('game.log')
 | 
			
		||||
    
 | 
			
		||||
    def determine_owner(self):
 | 
			
		||||
        ''' determines the user in the parsed gamelog '''
 | 
			
		||||
@ -80,12 +94,16 @@ class LogSession(object):
 | 
			
		||||
                fn = os.path.split(filename)[1] or ''
 | 
			
		||||
                fn = fn.lower()
 | 
			
		||||
                if fn:
 | 
			
		||||
                    if fn == 'combat.log' and (not files or fn in files):
 | 
			
		||||
                    if fn == 'combat.log' and (not files or fn in files) and not 'combat.log' in self.files_parsed:
 | 
			
		||||
                        self.combat_log = CombatLogFile(fn)
 | 
			
		||||
                        self.combat_log.set_data(z.read(filename))
 | 
			
		||||
                    elif fn == 'game.log' and (not files or fn in files):
 | 
			
		||||
                        self.combat_log.parse()
 | 
			
		||||
                        self.files_parsed.append('combat.log')
 | 
			
		||||
                    elif fn == 'game.log' and (not files or fn in files) and not 'game.log' in self.files_parsed:
 | 
			
		||||
                        self.game_log = GameLogFile(fn)
 | 
			
		||||
                        self.game_log.set_data(z.read(filename))
 | 
			
		||||
                        self.game_log.parse()
 | 
			
		||||
                        self.files_parsed.append('game.log')
 | 
			
		||||
        except:
 | 
			
		||||
            self._error = True
 | 
			
		||||
            return
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										0
									
								
								utils/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								utils/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										28
									
								
								utils/steam.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								utils/steam.py
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,28 @@
 | 
			
		||||
"""
 | 
			
		||||
X:Y:Z
 | 
			
		||||
 | 
			
		||||
X - Universe
 | 
			
		||||
0     Individual / Unspecified
 | 
			
		||||
1     Public
 | 
			
		||||
2     Beta
 | 
			
		||||
3     Internal
 | 
			
		||||
4     Dev
 | 
			
		||||
5     RC 
 | 
			
		||||
 | 
			
		||||
Y - Steam Type
 | 
			
		||||
0     I     Invalid     No         
 | 
			
		||||
1     U     Individual     Yes     profiles / id     0x0110000100000000
 | 
			
		||||
2     M     Multiseat     Yes         
 | 
			
		||||
3     G     GameServer     Yes         
 | 
			
		||||
4     A     AnonGameServer     Yes         
 | 
			
		||||
5     P     Pending     No         
 | 
			
		||||
6     C     ContentServer     Unknown         
 | 
			
		||||
7     g     Clan     Yes     groups / gid     0x0170000000000000
 | 
			
		||||
8     c, L, T     Chat     Yes         
 | 
			
		||||
9         P2P SuperSeeder     No         
 | 
			
		||||
10         AnonUser     No
 | 
			
		||||
 | 
			
		||||
Z - account or group uid
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
""" 
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user