-
-
Save ctfaddict/142a72cfd91e6b5106a8 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/python | |
import psycopg2 | |
import sys | |
def bubbleSort(data, begin): | |
idx = [x for x in range(len(data))] | |
for j in range(begin, len(data) - 1): | |
swap = False | |
for k in range(begin, len(data) - j): | |
if data[idx[k]] < data[idx[k + 1]]: | |
t = idx[k] | |
idx[k] = idx[k + 1] | |
idx[k + 1] = t | |
swap = True | |
if not swap: | |
break | |
return idx | |
class Replay: | |
def __init__(self): | |
self.pollPlus = [0 for x in range(21)] | |
self.pollMinus = [0 for x in range(21)] | |
self.capturePlus = [0 for x in range(21)] | |
self.captureMinus = [0 for x in range(21)] | |
self.teamFlags = [2500 for x in range(21)] | |
self.legitFlags = 0 | |
self.history = [(0, list(self.teamFlags))] | |
def runTheGame(self, cur): | |
cur.execute("select min(id), max(id) from rounds;") | |
row = cur.fetchone() | |
minRound = row[0] | |
maxRound = row[1] | |
cur.execute("select min(id), max(id) from services;") | |
row = cur.fetchone() | |
minService = row[0] | |
maxService = row[1] | |
for r in range(minRound, maxRound + 1): | |
for s in range(minService, maxService + 1): | |
up = [] | |
down = [] | |
cur.execute("select i.team_id, a.status from availabilities a, instances i where a.round_id = %s and i.service_id = %s and a.instance_id = i.id and i.team_id != 21", (r, s, )) | |
failPool = 0 | |
while True: | |
row = cur.fetchone() | |
if row == None: | |
break | |
team = row[0] | |
status = row[1] | |
if status != 0: | |
down.append(team) | |
flags = min(19, self.teamFlags[team]) | |
self.teamFlags[team] -= flags | |
self.pollMinus[team] += flags | |
failPool += flags | |
else: | |
up.append(team) | |
if len(up) > 0: | |
share = failPool / len(up) | |
for t in up: | |
self.teamFlags[t] += share | |
self.pollPlus[t] += share | |
self.legitFlags += failPool % len(up) | |
else: | |
self.legitFlags += failPool | |
for s in range(minService, maxService + 1): | |
pwners = [list() for x in range(21)] | |
cur.execute("select r.team_id as attacker, i.team_id as victim from redemptions r, tokens t, instances i where t.round_id = %s and i.service_id = %s and r.token_id = t.id and t.instance_id = i.id", (r, s, )) | |
while True: | |
row = cur.fetchone() | |
if row == None: | |
break | |
pwners[row[1]].append(row[0]) | |
for v in range(1, 21): | |
if len(pwners[v]) > 0: | |
flags = min(19, self.teamFlags[v]) | |
self.teamFlags[v] -= flags | |
self.captureMinus[v] += flags | |
share = flags / len(pwners[v]) | |
for a in pwners[v]: | |
self.teamFlags[a] += share | |
self.capturePlus[a] += share | |
self.legitFlags += flags % len(pwners[v]) | |
self.history.append((r, list(self.teamFlags))) | |
if __name__ == "__main__": | |
conn = psycopg2.connect("dbname=scorebot_production user=postgres") | |
cur = conn.cursor() | |
teams = {} | |
cur.execute("select id, name from teams;") | |
rows = cur.fetchall() | |
maxNameLen = 0 | |
for r in rows: | |
teams[r[0]] = r[1] | |
maxNameLen = max(maxNameLen, len(r[1])) | |
pad = " " * maxNameLen | |
replay = Replay() | |
replay.runTheGame(cur) | |
print "LegitBS remainder flags: %d\n" % replay.legitFlags | |
idx = bubbleSort(replay.teamFlags, 1) | |
print "Estimated final scores" | |
for i in range(1, 21): | |
print " %s | %d" % ((teams[idx[i]] + pad)[:maxNameLen], replay.teamFlags[idx[i]]) | |
idx = bubbleSort(replay.capturePlus, 1) | |
print "\nFlags gained per team from captures" | |
for i in range(1, 21): | |
print " %s | %d" % ((teams[idx[i]] + pad)[:maxNameLen], replay.capturePlus[idx[i]]) | |
idx = bubbleSort(replay.captureMinus, 1) | |
print "\nFlags lost per team from captures" | |
for i in range(1, 21): | |
print " %s | %d" % ((teams[idx[i]] + pad)[:maxNameLen], replay.captureMinus[idx[i]]) | |
idx = bubbleSort(replay.pollPlus, 1) | |
print "\nFlags gained per team from polls" | |
for i in range(1, 21): | |
print " %s | %d" % ((teams[idx[i]] + pad)[:maxNameLen], replay.pollPlus[idx[i]]) | |
idx = bubbleSort(replay.pollMinus, 1) | |
print "\nFlags lost per team from polls" | |
for i in range(1, 21): | |
print " %s | %d" % ((teams[idx[i]] + pad)[:maxNameLen], replay.pollMinus[idx[i]]) | |
if len(sys.argv) == 2: | |
f = open(sys.argv[1], "w") | |
for h in replay.history: | |
scores = h[1] | |
# f.write("%d:" % h[0]) | |
for i in range(1, 21): | |
f.write("%d%s" % (scores[i], "," if i != 20 else "")) | |
f.write('\n') | |
f.close() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment