#!/usr/local/bin/python # # Duke Nukem score machine. # # by billo 12-jul-1996 # # input file has contents like this: # - '#' character in first column of line denotes comment # - '%' character in first column denotes game record: # game record has three fields: gameid, minutes and gamename # other records are player entries. # - column 0 is player in the game. # - column 1 is a unique ID to designate a game. This is how minutes # are computed (each score entry for a player points to a game record # in the game file) # - columns 2-n denote the players who played in the game, giving # the number of times the column player was killed by the row player # The columns are ordered alphabetically. # sample data: # % 2 3 TierDrops # billo 2 0 1 2 # dougy 2 0 0 1 # schwenk 2 0 0 0 import time, os, posixpath, socket, string, sys, types scores = [] # list of kill records, sorted by player name games = [] # list of game records, sorted by gameid playerlist = [] # list of player names, sorted by player name players = {} # Players is a dictionary: # key - player's name # value - another dictionary of subtotals. - # gives the number of kills, deaths, # minutes played and amount of times # this player has killed each player, # including himself. highest_game = [0] last_games = 0 def dukecmp (x, y): if x[1] < y[1]: return -1 elif x[1] > y[1]: return 1 else: return 0 def dukecmprev (x, y): if x[1] < y[1]: return 1 elif x[1] > y[1]: return -1 else: return 0 def dukecmp_player (x, y): if x[0] < y[0]: return -1 elif x[0] > y[0]: return 1 else: return 0 def dukify(entry): newentry = entry for i in range(len(entry)): try: # Convert to integer if possible. newentry[i] = string.atoi(entry[i]) except: newentry[i] = entry[i] return newentry # suck_and_sort_scores () # Arguments: filename - Duke File's filename # Returns: dukefile - file object of Duke File # # Read the Duke File, designated by filename. def suck_and_sort_scores (filename, gamename='any'): if os.path.isfile (filename): try: dukefile = open (filename, "r+") except IOError: print "Unable to open %s" % filename sys.exit () else: return None if (dukefile != None): dukeline = dukefile.readline() while dukeline != '': if dukeline[0] == '%': # game record gamentry = string.split(dukeline) gamentry = dukify(gamentry[1:]) if highest_game[0] < gamentry[0]: highest_game[0] = gamentry[0] if gamename == 'any' or gamentry[2] == gamename: games.append (gamentry) elif dukeline[0] != '#': dukentry = string.split(dukeline) if len(dukentry) > 0: # kill record dukentry = dukify(dukentry) if find_game(dukentry[1]): scores.append (dukentry) dukeline = dukefile.readline() # sort kill records by player name scores.sort(dukecmp) return dukefile def find_game(gameid): for entry in games: if entry[0] == gameid: return entry return None # create_player_table () # Arguments: none # Returns: nothing # # Create playerlist, list of player names, and players def create_player_table (): # Create playerlist. for i in range(len(scores)): if players.has_key(scores[i][0]) == 0: # add player name to playerlist if not already there. playerlist.append(scores[i][0]) players[scores[i][0]] = {} # sort playerlist by player name playerlist.sort() # Create players dictionary. for i in range(len(playerlist)): killer = playerlist[i] for j in range(len(playerlist)): victim = playerlist[j] victim_time = victim + 'time' players[killer][victim] = 0 players[killer][victim_time] = 0 players[killer]['minutes'] = 0 players[killer]['kills'] = 0 players[killer]['deaths'] = 0 # score_games () # Arguments: none # Returns: nothing # # Figures out scores. def score_games(): for gameidx in range(len(games)): gameplayers = [] game = [] gameid = games[gameidx][0] if last_games > 0 and gameid <= highest_game[0] - last_games: continue gametime = games[gameidx][1] # find all players who played in this game for i in range(len(scores)): scoregameid = scores[i][1] if scoregameid == gameid: scoreplayer = scores[i] game.append(scoreplayer) gameplayers.append(scoreplayer[0]) if len(game) > 0: # sys.stdout.write("Game: %d, Players: %d\n" % (gameid, len(game))) game.sort(dukecmp_player) gameplayers.sort() for i in range(len(game)): killer = gameplayers[i] players[killer]['minutes'] = players[killer]['minutes'] + \ gametime for j in range(2, len(game[i])): victim = gameplayers[j-2] victim_time = victim + 'time' players[killer][victim] = players[killer][victim] + \ game[i][j] if killer != victim: players[killer][victim_time] = players[killer][victim_time] + \ gametime players[killer]['kills'] = players[killer]['kills'] + \ game[i][j] players[victim]['deaths'] = players[victim]['deaths'] + \ game[i][j] for i in range(len(playerlist)): killer = playerlist[i] try: players[killer]['KPM'] = float(players[killer]['kills']) / \ players[killer]['minutes'] players[killer]['DPM'] = float(players[killer]['deaths']) / \ players[killer]['minutes'] players[killer]['KPD'] = float(players[killer]['kills']) / \ players[killer]['deaths'] players[killer]['KPD-S'] = float(players[killer]['kills']) / \ (players[killer]['deaths'] - \ players[killer][killer]) if players[killer][killer] == 0: players[killer]['KPS'] = 0 else: players[killer]['KPS'] = float(players[killer]['kills']) / \ players[killer][killer] except: players[killer]['KPM'] = 0 players[killer]['DPM'] = 0 players[killer]['KPD'] = 0 players[killer]['KPD-S'] = 0 players[killer]['KPS'] = 0 def new_game(filename): dukefile = open (filename, "a") # Default Game ID is +1 of the last Game ID. defGameID = highest_game[0] + 1 defMinutes = 29 prompt = "Game ID [%s]: " % defGameID GameID = raw_input (prompt) if GameID == '': GameID = defGameID prompt = "Game Minutes [%s]: " % defMinutes Minutes = raw_input (prompt) if Minutes == '': Minutes = defMinutes prompt = "Game Name: " GameName = raw_input (prompt) # Write Game Record to Duke File dukefile.write ("\n%% %s %s %s\n" % (GameID, Minutes, GameName)) # Write Scores to Duke File writeScores (dukefile, GameID) # Close dukefile dukefile.close () def namesub(name): if (name == 'schwenk'): return 'dick' elif (name == 'frankkim'): return 'wolf' else: return name def versus(killer): sys.stdout.write("%s vs.\n" % namesub(killer)) sys.stdout.write("%13s: %-10s %-8s %7s %7s (total minutes)\n" % ('victim', 'kill-death', 'margin', 'ratio', 'KPM')) accum = 0 world_kills = 0 world_deaths = 0 for enemy in playerlist: if enemy != killer: if players[enemy]['minutes'] == 0: continue pkills = players[killer][enemy] pminutes = players[killer][enemy+'time'] ekills = players[enemy][killer] world_kills = world_kills + pkills world_deaths = world_deaths + ekills diff = pkills - ekills accum = accum + diff if diff > 0: plus = '+' else: plus = '-' if ekills == 0: ratio = 0.0 else: ratio = pkills * 1.0 / ekills if pminutes == 0: kpm = 0.0 else: kpm = pkills * 1.0 / pminutes sys.stdout.write("%13s: %-10s %s%-7d %7.2f %7.2f (%d minutes)\n" % (namesub(enemy), "%d-%d" % (pkills, ekills), plus, abs(diff), ratio, kpm, pminutes)) if accum > 0: plus = '+' else: plus = '-' try: world_ratio = world_kills * 1.0 / world_deaths except: world_ratio = 0 sys.stdout.write("%13s: %-10s %s%-7d %7.2f\n\n" % ("world", "%d-%d" % (world_kills, world_deaths), plus, abs(accum), world_ratio)) report_output = {} def report_by(column, direction): report = [] for i in range(len(playerlist)): killer = playerlist[i] if players[killer]['minutes'] < 100: continue report.append([killer, players[killer][column]]) if direction: report.sort(dukecmp) else: report.sort(dukecmprev) report_output[column] = report def print_reports(): output_lines=[] for i in range(len(playerlist)+1): output_lines.append(' ') for rep in report_output.keys(): i = 0 output_lines[i] = output_lines[i] + ("%9s%6s " % (" ", rep)) for stat in report_output[rep]: i = i+1 if rep == 'deaths' or rep == 'kills': output_lines[i] = output_lines[i] + ("%9s%6d " % (namesub(stat[0]), stat[1])) else: output_lines[i] = output_lines[i] + ("%9s%6.2f " % (namesub(stat[0]), stat[1])) i = 0; for output in output_lines: if i == 1 and g_whichgame == 'any': sys.stdout.write(" len 2.48 len 0.09 len 9.73 len 73.36 len 99 len 7236 \n") sys.stdout.write('%s\n' % output) i = i + 1 # writeScores () # Arguments: dukefile - file object of Duke File # gameid - Game ID # Returns: nothing # # Gets from input the scores and writes them sorted to the Duke File. def writeScores (dukefile, gameid): print "Enter scores. Press Ctrl-D on it's own line when you're done." flag = 1 rawScores = [] while flag: try: rawScores.append (raw_input ()) except EOFError: flag = 0 newScores = [] # Split up the rawScores and put the split strings into newScores. for i in range (len (rawScores)): newScore = string.split (rawScores[i]) if len (newScore) != 0: newScores.append (newScore) # Check if Column and Row sizes match. for newScore in newScores: if len (newScore)-1 != len (newScores): sys.stderr.write ("Column and row sizes don't match: %s, %s\n"\ % (len(newScore)-1, len(newScores))) sys.exit () # Sort the list sortDone = 0 while sortDone == 0: sortDone = 1 for i in range (len(newScores) - 1): if dukecmp_player (newScores[i], newScores[i+1]) == 1: for newScore in newScores: # Swap respective kills in each player's score # list. tempKill = newScore[i+1] newScore[i+1] = newScore[i+2] newScore[i+2] = tempKill # Swap order of players and their scores. tempScore = newScores[i] newScores[i] = newScores[i+1] newScores[i+1] = tempScore # Sort not done sortDone = 0 for newScore in newScores: sys.stdout.write ("%-9s" % newScore[0]) dukefile.write ("%-9s" % newScore[0]) dukefile.write ("%-4s" % gameid) for element in newScore[1:]: sys.stdout.write ("%4s" % element) dukefile.write ("%4s" % element) dukefile.write ("\n") sys.stdout.write ("\n") g_dukefile = '' g_whichgame = 'any' g_newgame = 0 def parse_args(argv): global g_dukefile global g_whichgame global g_newgame global last_games argc = len(argv) if argc < 2: sys.stdout.write('usage:\n %s DUKEDATAFILE [-new | -last NGAMES | LEVELNAME]\n' % (argv[0])) sys.exit(0) g_dukefile = argv[1] if argc == 2: return if argc == 4 and argv[2] == '-last': last_games = string.atoi(argv[3]) if argc == 3 and argv[2] != '-new': g_whichgame = argv[2] if argc == 3 and argv[2] == '-new': g_newgame = 1 if __name__ == '__main__': global g_dukefile global g_whichgame global g_newgame global last_games parse_args(sys.argv) # Copy the dukefile before changing/reading it. os.system ("cp %s dukefile.bak" % g_dukefile) if (last_games > 0): sys.stdout.write('Score report for last %s games as of' % last_games) elif g_whichgame != 'any': sys.stdout.write('Score report for %s as of' % g_whichgame) elif g_newgame: sys.stdout.write('Entering a new game report\n') else: sys.stdout.write('Score report for all games as of ') sys.stdout.write(" %s\n\n" % time.ctime(time.time())) dukefile = suck_and_sort_scores(g_dukefile, g_whichgame) create_player_table() if g_newgame: # Read in data for new game. new_game(g_dukefile) else: # Print out table of Duke Nukem scores. score_games() # header sys.stdout.write ("%8s" % "Killer") for header in ['Minute', 'Kills', 'Deaths', 'KPM', 'DPM', 'KPD', 'KPS']: sys.stdout.write ("%7s" % header) for victim in playerlist: if players[victim]['minutes'] == 0: continue subvictim = namesub(victim) sys.stdout.write ("%5s" % subvictim[:4]) sys.stdout.write ("\n") if g_whichgame == 'any': sys.stdout.write(" len 5000 7236 1001 2.48 0.09 73.36 9.73 778 853 94 333 52 847 578 23 1356 268 36 4 115 12 56 290 10 1195 65 548 14 37 0 9\n") for killer in playerlist: if players[killer]['minutes'] == 0: continue sys.stdout.write ("%8s" % namesub(killer)) for key in ['minutes', 'kills', 'deaths']: sys.stdout.write ("%7d" % players[killer][key]) for key in ['KPM', 'DPM', 'KPD', 'KPS']: sys.stdout.write ("%7.2f" % players[killer][key]) for victim in playerlist: if players[victim]['minutes'] == 0: continue sys.stdout.write ("%5d" % players[killer][victim]) sys.stdout.write ("\n") sys.stdout.write("\nLEADERBOARD (100 minute qualification) KPM = Kills/Minute DPM = Deaths/Minute KPS = Kills/Suicides KPD = Kills/Deaths\n") sys.stdout.write("--------------------------------------\n") report_by('kills', 0) report_by('deaths', 1) report_by('KPM', 0) report_by('DPM', 1) report_by('KPD', 0) report_by('KPS', 0) print_reports() sys.stdout.write("\nHEAD TO HEAD\n") sys.stdout.write("------------\n") for player in playerlist: if players[player]['minutes'] == 0: continue versus(player)