-
-
Save aheadley/1568155 to your computer and use it in GitHub Desktop.
Reads in a minecraft server log ranking users by time spent
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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)' |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
""" | |
Minecraft Server Log Time Spent Ranking | |
""" | |
__author__ = 'Gavin M. Roy' | |
__email__ = '[email protected]' | |
__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 '%s%s' % (string.ljust('User ranking by time spent', 30), | |
string.rjust('(Hours:Minutes:Seconds)', 30)) | |
print ''.join(['-' for x in xrange(0, 60)]) | |
for user in time_spent: | |
print '%s%s' % (string.ljust(user[0], 30), | |
string.rjust(str(user[1]), 30)) | |
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