mirror of https://github.com/dirtbags/moth.git
Fix medusa bugs
This commit is contained in:
parent
c2d685005b
commit
f3f5e797b3
4
flagd.py
4
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,6 +69,7 @@ class Submitter(asyncore.dispatcher):
|
|||
|
||||
team = team or points.house
|
||||
|
||||
if self.flags.get(cat) != team:
|
||||
self.flags[cat] = team
|
||||
self.submit(now, cat, team, 1)
|
||||
|
||||
|
@ -132,6 +131,7 @@ class FlagServer(asynchat.async_chat):
|
|||
|
||||
def handle_close(self):
|
||||
self.set_flag(None)
|
||||
self.close()
|
||||
|
||||
|
||||
def start():
|
||||
|
|
30
histogram.py
30
histogram.py
|
@ -3,19 +3,25 @@
|
|||
import points
|
||||
import time
|
||||
import os
|
||||
import tempfile
|
||||
|
||||
teamfiles = {}
|
||||
def main(s=None):
|
||||
scores = {}
|
||||
now = 0
|
||||
|
||||
if not s:
|
||||
s = points.Storage('scores.dat')
|
||||
|
||||
plotparts = []
|
||||
teams = s.teams()
|
||||
teamcolors = points.colors(teams)
|
||||
|
||||
fn = 'scores.hist'
|
||||
scoresfile = open(fn, 'w')
|
||||
catscores = {}
|
||||
for cat in s.categories():
|
||||
catscores[cat] = s.cat_points(cat)
|
||||
|
||||
scoresfile = tempfile.NamedTemporaryFile('w')
|
||||
fn = scoresfile.name
|
||||
i = 2
|
||||
for team in teams:
|
||||
plotparts.append('"%s" using 1:%d with lines linewidth 2 linetype rgb "#%s"' % (fn, i, teamcolors[team]))
|
||||
|
@ -25,23 +31,22 @@ for team in teams:
|
|||
def write_scores(t):
|
||||
scoresfile.write('%d' % t)
|
||||
for team in teams:
|
||||
scoresfile.write('\t%d' % (scores[team]))
|
||||
scoresfile.write('\t%f' % (scores[team]))
|
||||
scoresfile.write('\n')
|
||||
|
||||
for when, cat, team, points in s.log:
|
||||
for when, cat, team, score in s.log:
|
||||
if when > now:
|
||||
if now:
|
||||
write_scores(now)
|
||||
now = when
|
||||
scores[team] += points
|
||||
pct = score / catscores[cat]
|
||||
scores[team] += pct
|
||||
#print('%d [%s] [%s] %d' % (when, cat, team, points))
|
||||
|
||||
write_scores(when)
|
||||
scoresfile.flush()
|
||||
|
||||
for f in teamfiles.values():
|
||||
f.close()
|
||||
|
||||
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 xdata time\n')
|
||||
gp.write('set timefmt "%s"\n')
|
||||
|
@ -53,4 +58,7 @@ 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.close()
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
|
50
points.py
50
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,24 +120,25 @@ 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
|
||||
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):
|
||||
|
@ -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
|
||||
|
||||
|
||||
|
|
36
pointsd.py
36
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()
|
||||
|
|
13
ubersrv.py
13
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()
|
||||
|
|
Loading…
Reference in New Issue