Skip to content

Instantly share code, notes, and snippets.

@aheadley
Forked from gmr/timespent_ranking.py
Created January 6, 2012 00:21
Show Gist options
  • Save aheadley/1568155 to your computer and use it in GitHub Desktop.
Save aheadley/1568155 to your computer and use it in GitHub Desktop.
Reads in a minecraft server log ranking users by time spent
#!/usr/bin/env python
import datetime
import re
class LogParser(object):
"""
"""
def __init__(self):
self._data = {
'players': {},
'server': {},
}
self._events = list()
def add_event(self, pattern, callback, cont=False):
"""
"""
self._events.append({
'pattern': re.compile(pattern),
'callback': callback,
'continue': cont})
def parse_log(self, server_log):
"""
"""
with open(server_log, 'rb') as f:
for log_line in f:
self._parse_line(log_line)
return self._data
def _parse_line(self, line):
for event in self._events:
m = event['pattern'].match(line)
if m:
event['callback'](self, **m.groupdict())
if not event['continue']:
break
@staticmethod
def parse_timestamp(timestamp):
return datetime.datetime.strptime(timestamp, '%Y-%m-%d %H:%M:%S')
@staticmethod
def format_results(results, length=30):
time_spent = sorted(results['players'].iteritems(),
key=lambda x: x[1]['total'],
reverse=True)
for user in time_spent[:length]:
print '%020s = %s' % (user[0], user[1]['total'])
if __name__ == '__main__':
import sys
parser = LogParser()
def c_login(self, **kwargs):
try:
player = self._data['players'][kwargs['nickname']]
except KeyError:
player = {
'total': datetime.timedelta(),
'online': False,
}
self._data['players'][kwargs['nickname']] = player
#print 'New player: %s' % kwargs['nickname']
if player['online']:
#print 'Player logged in before logging out: %s' % kwargs['nickname']
pass
else:
player['online'] = self.parse_timestamp(kwargs['timestamp'])
def c_logout(self, **kwargs):
try:
player = self._data['players'][kwargs['nickname']]
except KeyError:
#print 'Player logged out before being seen: %s' % kwargs['nickname']
pass
else:
if player['online']:
player['total'] += \
(self.parse_timestamp(kwargs['timestamp']) -
player['online'])
player['online'] = False
else:
#print 'Player logged out before logging in: %s' % kwargs['nickname']
pass
def c_server_start(self, **kwargs):
for nickname in self._data['players']:
player = self._data['players'][nickname]
if player['online']:
player['total'] += (self.parse_timestamp(kwargs['timestamp']) -
player['online'])
player['online'] = False
parser.add_event(
r'(?P<timestamp>(?P<date>\d{4}-\d{2}-\d{2}) (?P<time>\d{2}:\d{2}:\d{2})) ' +
r'\[INFO\] (?P<nickname>\w*) ' +
r'\[/(?P<ip_address>(?:\d{1,3}\.){3}\d{1,3})\:(?P<port>\d{3,5})\] logged in.*',
c_login)
parser.add_event(
r'(?P<timestamp>(?P<date>\d{4}-\d{2}-\d{2}) (?P<time>\d{2}:\d{2}:\d{2})) ' +
r'\[INFO\] (?P<nickname>\w*) ' +
r'lost connection.*',
c_logout)
parser.add_event(
r'(?P<timestamp>(?P<date>\d{4}-\d{2}-\d{2}) (?P<time>\d{2}:\d{2}:\d{2})) ' +
r'\[INFO\] Starting minecraft server version (?P<version>.*)',
c_server_start)
parser.add_event(
r'(?P<timestamp>(?P<date>\d{4}-\d{2}-\d{2}) (?P<time>\d{2}:\d{2}:\d{2})) ' +
r'\[INFO\] Stopping server',
c_server_start)
try:
for f in sys.argv[1:]:
LogParser.format_results(parser.parse_log(f))
except IndexError:
print 'Missing log file argument(s)'
"""
Minecraft Server Log Time Spent Ranking
"""
__author__ = 'Gavin M. Roy'
__email__ = 'gavinmroy@gmail.com'
__since__ = '2012-01-05'
import datetime
import operator
import re
import string
import sys
_LOGIN = re.compile("(?P<date>\d\d\d\d-\d\d-\d\d) "
"(?P<time>\d\d:\d\d\:\d\d) \[INFO\] "
"(?P<nickname>\w*) \[/"
"(?P<ipaddress>[0-9]{1,3}\.[0-9]{1,3}\."
"[0-9]{1,3}\.[0-9]{1,3}):"
"(?P<port>[0-9]{2,8})\] logged in with entity id "
"(?P<entity>[0-9]{1,20}) at \("
"(?P<x>[\-0-9\.]*), "
"(?P<y>[\-0-9\.]*), "
"(?P<z>[\-0-9\.]*)\)")
_LOGOUT = re.compile("(?P<date>\d\d\d\d-\d\d-\d\d) "
"(?P<time>\d\d:\d\d:\d\d) \[INFO\] "
"(?P<nickname>\w*) lost connection: disconnect."
"(?P<reason>\w*)")
# Globals that carry state across methods
users = dict()
last = dict()
def get_datetime(date, time):
temp = '%s %s' % (date, time)
return datetime.datetime.strptime(temp, '%Y-%m-%d %H:%M:%S')
def set_duration(nickname, start, end):
global users
delta = end - start
if nickname not in users:
users[nickname] = delta
else:
users[nickname] += delta
def read_file():
if len(sys.argv) > 1:
filename = sys.argv[1]
else:
filename = 'sever.log'
with open(filename) as handle:
return handle.read()
def process_line(line):
global last
matches = _LOGIN.match(line)
if matches:
login = matches.groupdict()
last[login['nickname']] = get_datetime(login['date'], login['time'])
else:
matches = _LOGOUT.match(line)
if matches:
logout = matches.groupdict()
set_duration(logout['nickname'],
last[logout['nickname']],
get_datetime(logout['date'], logout['time']))
def display_results():
time_spent = sorted(users.iteritems(),
key=operator.itemgetter(1),
reverse=True)
print
print '%s%s' % (string.ljust('User ranking by time spent', 30),
string.rjust('(Hours:Minutes:Seconds)', 30))
print ''.join(['-' for x in xrange(0, 60)])
print
for user in time_spent:
print '%s%s' % (string.ljust(user[0], 30),
string.rjust(str(user[1]), 30))
print
def main():
# Read in the server log
data = read_file().split('\n')
# Iterate over each line
for line in data:
process_line(line)
# Display the results
display_results()
if __name__ == '__main__':
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment