all latent changes, undisclosed and without warranty.

This commit is contained in:
Gabor Körber 2014-10-20 18:47:28 +02:00
parent 8411ed858c
commit 10c557dea3
10 changed files with 180 additions and 23 deletions

View File

@ -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

View File

@ -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)

View File

@ -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)

View File

@ -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
View 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

View File

@ -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

View File

@ -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()

View File

@ -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
View File

28
utils/steam.py Normal file
View 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
"""