From f3f5e797b3e0dff4c348fb43cd727d74b39a21d2 Mon Sep 17 00:00:00 2001 From: Neale Pickett Date: Tue, 1 Sep 2009 09:34:15 -0600 Subject: [PATCH] Fix medusa bugs --- flagd.py | 8 ++--- histogram.py | 90 ++++++++++++++++++++++++++++------------------------ points.py | 54 ++++++++++++++++--------------- pointsd.py | 36 +++++++++++---------- ubersrv.py | 13 ++++++-- 5 files changed, 112 insertions(+), 89 deletions(-) diff --git a/flagd.py b/flagd.py index 5692ff7..2e48be4 100755 --- a/flagd.py +++ b/flagd.py @@ -34,7 +34,6 @@ class Submitter(asyncore.dispatcher): self.unacked[id] = q def writable(self): - print('writable?') now = int(time.time()) if now >= self.lastupdate + 60: for cat, team in self.flags.items(): @@ -45,7 +44,6 @@ class Submitter(asyncore.dispatcher): self.pending.append(q) self.lastretrans = now ret = bool(self.pending) - print(ret) return ret def handle_write(self): @@ -71,8 +69,9 @@ class Submitter(asyncore.dispatcher): team = team or points.house - self.flags[cat] = team - self.submit(now, cat, team, 1) + if self.flags.get(cat) != team: + self.flags[cat] = team + self.submit(now, cat, team, 1) class Listener(asyncore.dispatcher): @@ -132,6 +131,7 @@ class FlagServer(asynchat.async_chat): def handle_close(self): self.set_flag(None) + self.close() def start(): diff --git a/histogram.py b/histogram.py index 6fb4a44..b638fe4 100755 --- a/histogram.py +++ b/histogram.py @@ -3,54 +3,62 @@ import points import time import os +import tempfile -teamfiles = {} -scores = {} -now = 0 +def main(s=None): + scores = {} + now = 0 -s = points.Storage('scores.dat') + if not s: + s = points.Storage('scores.dat') -plotparts = [] -teams = s.teams() -teamcolors = points.colors(teams) + plotparts = [] + teams = s.teams() + teamcolors = points.colors(teams) -fn = 'scores.hist' -scoresfile = open(fn, 'w') -i = 2 -for team in teams: - plotparts.append('"%s" using 1:%d with lines linewidth 2 linetype rgb "#%s"' % (fn, i, teamcolors[team])) - scores[team] = 0 - i += 1 + catscores = {} + for cat in s.categories(): + catscores[cat] = s.cat_points(cat) -def write_scores(t): - scoresfile.write('%d' % t) + scoresfile = tempfile.NamedTemporaryFile('w') + fn = scoresfile.name + i = 2 for team in teams: - scoresfile.write('\t%d' % (scores[team])) - scoresfile.write('\n') + plotparts.append('"%s" using 1:%d with lines linewidth 2 linetype rgb "#%s"' % (fn, i, teamcolors[team])) + scores[team] = 0 + i += 1 -for when, cat, team, points in s.log: - if when > now: - if now: - write_scores(now) - now = when - scores[team] += points - #print('%d [%s] [%s] %d' % (when, cat, team, points)) + def write_scores(t): + scoresfile.write('%d' % t) + for team in teams: + scoresfile.write('\t%f' % (scores[team])) + scoresfile.write('\n') -write_scores(when) + for when, cat, team, score in s.log: + if when > now: + if now: + write_scores(now) + now = when + pct = score / catscores[cat] + scores[team] += pct + #print('%d [%s] [%s] %d' % (when, cat, team, points)) -for f in teamfiles.values(): - f.close() + write_scores(when) + scoresfile.flush() -gp = os.popen('gnuplot > /dev/null', 'w') -gp.write('set style data lines\n') -gp.write('set xdata time\n') -gp.write('set timefmt "%s"\n') -gp.write('set format ""\n') -gp.write('set border 3\n') -gp.write('set xtics nomirror\n') -gp.write('set ytics nomirror\n') -gp.write('set nokey\n') -gp.write('set terminal png transparent size 640,200 x000000 xffffff\n') -gp.write('set output "histogram.png"\n') -gp.write('plot %s\n' % ','.join(plotparts)) -gp.flush() + gp = os.popen('gnuplot 2> /dev/null', 'w') + gp.write('set style data lines\n') + gp.write('set xdata time\n') + gp.write('set timefmt "%s"\n') + gp.write('set format ""\n') + gp.write('set border 3\n') + gp.write('set xtics nomirror\n') + gp.write('set ytics nomirror\n') + gp.write('set nokey\n') + gp.write('set terminal png transparent size 640,200 x000000 xffffff\n') + gp.write('set output "histogram.png"\n') + gp.write('plot %s\n' % ','.join(plotparts)) + gp.close() + +if __name__ == '__main__': + main() diff --git a/points.py b/points.py index 55a74fa..952ee00 100755 --- a/points.py +++ b/points.py @@ -5,6 +5,8 @@ import hmac import struct import io +## Name of the house team +house = 'dirtbags' ## ## Authentication @@ -48,8 +50,8 @@ def unpackstr(b): ## ## Request ## -def encode_request(when, cat, team, score): - base = (struct.pack('!I', when) + +def encode_request(id, when, cat, team, score): + base = (struct.pack('!II', id, when) + packstr(cat) + packstr(team) + struct.pack('!i', score)) @@ -57,36 +59,35 @@ def encode_request(when, cat, team, score): def decode_request(b): base = check_sig(b) - when, base = unpack('!I', base) + id, when, base = unpack('!II', base) cat, base = unpackstr(base) team, base = unpackstr(base) score, base = unpack('!i', base) assert not base - return (when, cat, team, score) + return (id, when, cat, team, score) ## ## Response ## -def encode_response(when, txt): - base = (struct.pack('!I', when) + +def encode_response(id, txt): + base = (struct.pack('!I', id) + packstr(txt)) return sign(base) def decode_response(b): base = check_sig(b) - when, base = unpack('!I', base) + id, base = unpack('!I', base) txt, base = unpackstr(base) assert not base - return (when, txt) + return (id, txt) ## ## Storage ## def incdict(dict, key, amt=1): - dict.setdefault(key, 0) - dict[key] += amt + dict[key] = dict.get(key, 0) + amt class Storage: def __init__(self, fn): @@ -94,7 +95,6 @@ class Storage: self.points_by_cat = {} self.points_by_cat_team = {} self.log = [] - self.events = set() self.f = io.BytesIO() # Read stored scores @@ -106,8 +106,11 @@ class Storage: break (l,) = struct.unpack('!I', l) b = f.read(l) - req = decode_request(b) - self.add(req) + when, score, catlen, teamlen, b = unpack('!IiHH', b) + cat = b[:catlen].decode('utf-8') + team = b[catlen:].decode('utf-8') + req = (when, cat, team, score) + self.add(req, False) f.close() except IOError: pass @@ -117,25 +120,26 @@ class Storage: except IOError: self.f = None - def __contains__(self, req): - return req in self.events - - def add(self, req): - if req in self.events: - return + def __len__(self): + return len(self.log) + def add(self, req, write=True): when, cat, team, score = req incdict(self.points_by_team, team, score) incdict(self.points_by_cat, cat, score) incdict(self.points_by_cat_team, (cat, team), score) self.log.append(req) - self.events.add(req) - b = encode_request(*req) - lb = struct.pack('!I', len(b)) + b - self.f.write(lb) - self.f.flush() + if write: + cat = cat.encode('utf-8') + team = team.encode('utf-8') + b = (struct.pack('!IiHH', when, score, len(cat), len(team)) + + cat + team) + lb = struct.pack('!I', len(b)) + self.f.write(lb) + self.f.write(b) + self.f.flush() def categories(self): return sorted(self.points_by_cat) @@ -179,7 +183,7 @@ def test(): req = (now, 'category 5', 'foobers in heat', 43) assert decode_request(encode_request(*req)) == req - rsp = (now, 'hello world') + rsp = (now, 'cat6', 'hello world') assert decode_response(encode_response(*rsp)) == rsp diff --git a/pointsd.py b/pointsd.py index 1b5a908..c415dbc 100755 --- a/pointsd.py +++ b/pointsd.py @@ -6,12 +6,15 @@ import struct import points import time +house = 'dirtbags' + class MyHandler(asyncore.dispatcher): - def __init__(self, port): + def __init__(self, port=6667): asyncore.dispatcher.__init__(self) self.create_socket(socket.AF_INET, socket.SOCK_DGRAM) self.bind(('', port)) - self.acked = points.Storage('scores.dat') + self.store = points.Storage('scores.dat') + self.acked = set() self.outq = [] def writable(self): @@ -22,30 +25,31 @@ class MyHandler(asyncore.dispatcher): self.socket.sendto(dgram, peer) def handle_read(self): - dgram, peer = self.socket.recvfrom(4096) now = int(time.time()) + dgram, peer = self.socket.recvfrom(4096) try: - req = points.decode_request(dgram) + id, when, cat, team, score = points.decode_request(dgram) except ValueError as e: - return self.respond(now, str(e)) - when, cat, team, score = req + return self.respond(peer, now, str(e)) + team = team or house # Replays can happen legitimately. - if not req in self.acked: + if not (id in self.acked): if not (now - 2 < when <= now): - resp = points.encode_response(when, 'Your clock is off') - self.outq.append((resp, peer)) - return - self.acked.add(req) + return self.respond(peer, id, 'Your clock is off') + self.store.add((when, cat, team, score)) + self.acked.add(id) - resp = points.encode_response(when, 'OK') + self.respond(peer, id, 'OK') + + def respond(self, peer, id, txt): + resp = points.encode_response(id, txt) self.outq.append((resp, peer)) - def respond(self, peer, when, txt): - resp = points.encode_response(when, txt) - self.outq.append((resp, peer)) +def start(): + return MyHandler() if __name__ == "__main__": - h = MyHandler(6667) + h = start() asyncore.loop() diff --git a/ubersrv.py b/ubersrv.py index 830b954..de0bb83 100755 --- a/ubersrv.py +++ b/ubersrv.py @@ -3,10 +3,17 @@ import asyncore import pointsd import flagd +import histogram def main(): - pointsd.start() - flagd.start() - asyncore.loop(timeout=30, use_poll=True) + pointsrv = pointsd.start() + flagsrv = flagd.start() + s = pointsrv.store + slen = 0 + while True: + asyncore.loop(timeout=30, use_poll=True, count=1) + if len(s) > slen: + slen = len(s) + histogram.main(s) main()