Fix medusa bugs

This commit is contained in:
Neale Pickett 2009-09-01 09:34:15 -06:00
parent c2d685005b
commit f3f5e797b3
5 changed files with 112 additions and 89 deletions

View File

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

View File

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

View File

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

View File

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

View File

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