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 self.unacked[id] = q
def writable(self): def writable(self):
print('writable?')
now = int(time.time()) now = int(time.time())
if now >= self.lastupdate + 60: if now >= self.lastupdate + 60:
for cat, team in self.flags.items(): for cat, team in self.flags.items():
@ -45,7 +44,6 @@ class Submitter(asyncore.dispatcher):
self.pending.append(q) self.pending.append(q)
self.lastretrans = now self.lastretrans = now
ret = bool(self.pending) ret = bool(self.pending)
print(ret)
return ret return ret
def handle_write(self): def handle_write(self):
@ -71,8 +69,9 @@ class Submitter(asyncore.dispatcher):
team = team or points.house team = team or points.house
self.flags[cat] = team if self.flags.get(cat) != team:
self.submit(now, cat, team, 1) self.flags[cat] = team
self.submit(now, cat, team, 1)
class Listener(asyncore.dispatcher): class Listener(asyncore.dispatcher):
@ -132,6 +131,7 @@ class FlagServer(asynchat.async_chat):
def handle_close(self): def handle_close(self):
self.set_flag(None) self.set_flag(None)
self.close()
def start(): def start():

View File

@ -3,54 +3,62 @@
import points import points
import time import time
import os import os
import tempfile
teamfiles = {} def main(s=None):
scores = {} scores = {}
now = 0 now = 0
s = points.Storage('scores.dat') if not s:
s = points.Storage('scores.dat')
plotparts = [] plotparts = []
teams = s.teams() teams = s.teams()
teamcolors = points.colors(teams) teamcolors = points.colors(teams)
fn = 'scores.hist' catscores = {}
scoresfile = open(fn, 'w') for cat in s.categories():
i = 2 catscores[cat] = s.cat_points(cat)
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
def write_scores(t): scoresfile = tempfile.NamedTemporaryFile('w')
scoresfile.write('%d' % t) fn = scoresfile.name
i = 2
for team in teams: for team in teams:
scoresfile.write('\t%d' % (scores[team])) plotparts.append('"%s" using 1:%d with lines linewidth 2 linetype rgb "#%s"' % (fn, i, teamcolors[team]))
scoresfile.write('\n') scores[team] = 0
i += 1
for when, cat, team, points in s.log: def write_scores(t):
if when > now: scoresfile.write('%d' % t)
if now: for team in teams:
write_scores(now) scoresfile.write('\t%f' % (scores[team]))
now = when scoresfile.write('\n')
scores[team] += points
#print('%d [%s] [%s] %d' % (when, cat, team, points))
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(): write_scores(when)
f.close() scoresfile.flush()
gp = os.popen('gnuplot > /dev/null', 'w') gp = os.popen('gnuplot 2> /dev/null', 'w')
gp.write('set style data lines\n') gp.write('set style data lines\n')
gp.write('set xdata time\n') gp.write('set xdata time\n')
gp.write('set timefmt "%s"\n') gp.write('set timefmt "%s"\n')
gp.write('set format ""\n') gp.write('set format ""\n')
gp.write('set border 3\n') gp.write('set border 3\n')
gp.write('set xtics nomirror\n') gp.write('set xtics nomirror\n')
gp.write('set ytics nomirror\n') gp.write('set ytics nomirror\n')
gp.write('set nokey\n') gp.write('set nokey\n')
gp.write('set terminal png transparent size 640,200 x000000 xffffff\n') gp.write('set terminal png transparent size 640,200 x000000 xffffff\n')
gp.write('set output "histogram.png"\n') gp.write('set output "histogram.png"\n')
gp.write('plot %s\n' % ','.join(plotparts)) gp.write('plot %s\n' % ','.join(plotparts))
gp.flush() gp.close()
if __name__ == '__main__':
main()

View File

@ -5,6 +5,8 @@ import hmac
import struct import struct
import io import io
## Name of the house team
house = 'dirtbags'
## ##
## Authentication ## Authentication
@ -48,8 +50,8 @@ def unpackstr(b):
## ##
## Request ## Request
## ##
def encode_request(when, cat, team, score): def encode_request(id, when, cat, team, score):
base = (struct.pack('!I', when) + base = (struct.pack('!II', id, when) +
packstr(cat) + packstr(cat) +
packstr(team) + packstr(team) +
struct.pack('!i', score)) struct.pack('!i', score))
@ -57,36 +59,35 @@ def encode_request(when, cat, team, score):
def decode_request(b): def decode_request(b):
base = check_sig(b) base = check_sig(b)
when, base = unpack('!I', base) id, when, base = unpack('!II', base)
cat, base = unpackstr(base) cat, base = unpackstr(base)
team, base = unpackstr(base) team, base = unpackstr(base)
score, base = unpack('!i', base) score, base = unpack('!i', base)
assert not base assert not base
return (when, cat, team, score) return (id, when, cat, team, score)
## ##
## Response ## Response
## ##
def encode_response(when, txt): def encode_response(id, txt):
base = (struct.pack('!I', when) + base = (struct.pack('!I', id) +
packstr(txt)) packstr(txt))
return sign(base) return sign(base)
def decode_response(b): def decode_response(b):
base = check_sig(b) base = check_sig(b)
when, base = unpack('!I', base) id, base = unpack('!I', base)
txt, base = unpackstr(base) txt, base = unpackstr(base)
assert not base assert not base
return (when, txt) return (id, txt)
## ##
## Storage ## Storage
## ##
def incdict(dict, key, amt=1): def incdict(dict, key, amt=1):
dict.setdefault(key, 0) dict[key] = dict.get(key, 0) + amt
dict[key] += amt
class Storage: class Storage:
def __init__(self, fn): def __init__(self, fn):
@ -94,7 +95,6 @@ class Storage:
self.points_by_cat = {} self.points_by_cat = {}
self.points_by_cat_team = {} self.points_by_cat_team = {}
self.log = [] self.log = []
self.events = set()
self.f = io.BytesIO() self.f = io.BytesIO()
# Read stored scores # Read stored scores
@ -106,8 +106,11 @@ class Storage:
break break
(l,) = struct.unpack('!I', l) (l,) = struct.unpack('!I', l)
b = f.read(l) b = f.read(l)
req = decode_request(b) when, score, catlen, teamlen, b = unpack('!IiHH', b)
self.add(req) cat = b[:catlen].decode('utf-8')
team = b[catlen:].decode('utf-8')
req = (when, cat, team, score)
self.add(req, False)
f.close() f.close()
except IOError: except IOError:
pass pass
@ -117,25 +120,26 @@ class Storage:
except IOError: except IOError:
self.f = None self.f = None
def __contains__(self, req): def __len__(self):
return req in self.events return len(self.log)
def add(self, req):
if req in self.events:
return
def add(self, req, write=True):
when, cat, team, score = req when, cat, team, score = req
incdict(self.points_by_team, team, score) incdict(self.points_by_team, team, score)
incdict(self.points_by_cat, cat, score) incdict(self.points_by_cat, cat, score)
incdict(self.points_by_cat_team, (cat, team), score) incdict(self.points_by_cat_team, (cat, team), score)
self.log.append(req) self.log.append(req)
self.events.add(req)
b = encode_request(*req) if write:
lb = struct.pack('!I', len(b)) + b cat = cat.encode('utf-8')
self.f.write(lb) team = team.encode('utf-8')
self.f.flush() 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): def categories(self):
return sorted(self.points_by_cat) return sorted(self.points_by_cat)
@ -179,7 +183,7 @@ def test():
req = (now, 'category 5', 'foobers in heat', 43) req = (now, 'category 5', 'foobers in heat', 43)
assert decode_request(encode_request(*req)) == req assert decode_request(encode_request(*req)) == req
rsp = (now, 'hello world') rsp = (now, 'cat6', 'hello world')
assert decode_response(encode_response(*rsp)) == rsp assert decode_response(encode_response(*rsp)) == rsp

View File

@ -6,12 +6,15 @@ import struct
import points import points
import time import time
house = 'dirtbags'
class MyHandler(asyncore.dispatcher): class MyHandler(asyncore.dispatcher):
def __init__(self, port): def __init__(self, port=6667):
asyncore.dispatcher.__init__(self) asyncore.dispatcher.__init__(self)
self.create_socket(socket.AF_INET, socket.SOCK_DGRAM) self.create_socket(socket.AF_INET, socket.SOCK_DGRAM)
self.bind(('', port)) self.bind(('', port))
self.acked = points.Storage('scores.dat') self.store = points.Storage('scores.dat')
self.acked = set()
self.outq = [] self.outq = []
def writable(self): def writable(self):
@ -22,30 +25,31 @@ class MyHandler(asyncore.dispatcher):
self.socket.sendto(dgram, peer) self.socket.sendto(dgram, peer)
def handle_read(self): def handle_read(self):
dgram, peer = self.socket.recvfrom(4096)
now = int(time.time()) now = int(time.time())
dgram, peer = self.socket.recvfrom(4096)
try: try:
req = points.decode_request(dgram) id, when, cat, team, score = points.decode_request(dgram)
except ValueError as e: except ValueError as e:
return self.respond(now, str(e)) return self.respond(peer, now, str(e))
when, cat, team, score = req team = team or house
# Replays can happen legitimately. # Replays can happen legitimately.
if not req in self.acked: if not (id in self.acked):
if not (now - 2 < when <= now): if not (now - 2 < when <= now):
resp = points.encode_response(when, 'Your clock is off') return self.respond(peer, id, 'Your clock is off')
self.outq.append((resp, peer)) self.store.add((when, cat, team, score))
return self.acked.add(id)
self.acked.add(req)
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)) 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__": if __name__ == "__main__":
h = MyHandler(6667) h = start()
asyncore.loop() asyncore.loop()

View File

@ -3,10 +3,17 @@
import asyncore import asyncore
import pointsd import pointsd
import flagd import flagd
import histogram
def main(): def main():
pointsd.start() pointsrv = pointsd.start()
flagd.start() flagsrv = flagd.start()
asyncore.loop(timeout=30, use_poll=True) 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() main()