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
|
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,6 +69,7 @@ class Submitter(asyncore.dispatcher):
|
||||||
|
|
||||||
team = team or points.house
|
team = team or points.house
|
||||||
|
|
||||||
|
if self.flags.get(cat) != team:
|
||||||
self.flags[cat] = team
|
self.flags[cat] = team
|
||||||
self.submit(now, cat, team, 1)
|
self.submit(now, cat, team, 1)
|
||||||
|
|
||||||
|
@ -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():
|
||||||
|
|
70
histogram.py
70
histogram.py
|
@ -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:
|
|
||||||
|
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]))
|
plotparts.append('"%s" using 1:%d with lines linewidth 2 linetype rgb "#%s"' % (fn, i, teamcolors[team]))
|
||||||
scores[team] = 0
|
scores[team] = 0
|
||||||
i += 1
|
i += 1
|
||||||
|
|
||||||
def write_scores(t):
|
def write_scores(t):
|
||||||
scoresfile.write('%d' % t)
|
scoresfile.write('%d' % t)
|
||||||
for team in teams:
|
for team in teams:
|
||||||
scoresfile.write('\t%d' % (scores[team]))
|
scoresfile.write('\t%f' % (scores[team]))
|
||||||
scoresfile.write('\n')
|
scoresfile.write('\n')
|
||||||
|
|
||||||
for when, cat, team, points in s.log:
|
for when, cat, team, score in s.log:
|
||||||
if when > now:
|
if when > now:
|
||||||
if now:
|
if now:
|
||||||
write_scores(now)
|
write_scores(now)
|
||||||
now = when
|
now = when
|
||||||
scores[team] += points
|
pct = score / catscores[cat]
|
||||||
|
scores[team] += pct
|
||||||
#print('%d [%s] [%s] %d' % (when, cat, team, points))
|
#print('%d [%s] [%s] %d' % (when, cat, team, points))
|
||||||
|
|
||||||
write_scores(when)
|
write_scores(when)
|
||||||
|
scoresfile.flush()
|
||||||
|
|
||||||
for f in teamfiles.values():
|
gp = os.popen('gnuplot 2> /dev/null', 'w')
|
||||||
f.close()
|
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()
|
||||||
|
|
||||||
gp = os.popen('gnuplot > /dev/null', 'w')
|
if __name__ == '__main__':
|
||||||
gp.write('set style data lines\n')
|
main()
|
||||||
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()
|
|
||||||
|
|
50
points.py
50
points.py
|
@ -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,24 +120,25 @@ 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')
|
||||||
|
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(lb)
|
||||||
|
self.f.write(b)
|
||||||
self.f.flush()
|
self.f.flush()
|
||||||
|
|
||||||
def categories(self):
|
def categories(self):
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
|
||||||
|
|
36
pointsd.py
36
pointsd.py
|
@ -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()
|
||||||
|
|
13
ubersrv.py
13
ubersrv.py
|
@ -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()
|
||||||
|
|
Loading…
Reference in New Issue