Commit 0c7750e6 authored by Sam Moore's avatar Sam Moore

Continuing with prettified results

Now generating html files for each agent showing the results for each round as the rounds are played.
parent 6515461b
...@@ -7,6 +7,8 @@ ...@@ -7,6 +7,8 @@
Plays exactly ONE round, but does not overwrite previously played rounds Plays exactly ONE round, but does not overwrite previously played rounds
eg: run once to generate round1.results, twice to generate round2.results etc eg: run once to generate round1.results, twice to generate round2.results etc
Also generates total.scores based on results from every round. Also generates total.scores based on results from every round.
Now (sortof) generates .html files to display results in a prettiful manner.
author Sam Moore (matches) [SZM] author Sam Moore (matches) [SZM]
...@@ -49,9 +51,9 @@ if len(sys.argv) >= 5: ...@@ -49,9 +51,9 @@ if len(sys.argv) >= 5:
scores = {"VICTORY":(3,1, "DEFEAT"), "DEFEAT":(1,3, "VICTORY"), "SURRENDER":(1,3, "VICTORY"), "DRAW":(2,2, "DRAW"), "DRAW_DEFAULT":(1,1, "DRAW_DEFAULT"), "ILLEGAL":(-1,2, "DEFAULT"), "DEFAULT":(2,-1, "ILLEGAL"), "BOTH_ILLEGAL":(-1,-1, "BOTH_ILLEGAL"), "INTERNAL_ERROR":(0,0, "INTERNAL_ERROR"), "BAD_SETUP":(0,0,"BAD_SETUP")} scores = {"VICTORY":(3,1, "DEFEAT"), "DEFEAT":(1,3, "VICTORY"), "SURRENDER":(1,3, "VICTORY"), "DRAW":(2,2, "DRAW"), "DRAW_DEFAULT":(1,1, "DRAW_DEFAULT"), "ILLEGAL":(-1,2, "DEFAULT"), "DEFAULT":(2,-1, "ILLEGAL"), "BOTH_ILLEGAL":(-1,-1, "BOTH_ILLEGAL"), "INTERNAL_ERROR":(0,0, "INTERNAL_ERROR"), "BAD_SETUP":(0,0,"BAD_SETUP")}
#Verbose - print lots of useless stuff about what you are doing (kind of like matches in irc...) #Verbose - print lots of useless stuff about what you are doing (kind of like matches talking on irc...)
verbose = True verbose = True
makePrettyResults = False
#Check the manager program exists TODO: And is executable! #Check the manager program exists TODO: And is executable!
...@@ -74,74 +76,105 @@ if os.path.exists(logDirectory) == False: ...@@ -74,74 +76,105 @@ if os.path.exists(logDirectory) == False:
startTime = time() #Record time at which simulation starts startTime = time() #Record time at which simulation starts
#Do each round... if verbose:
for roundNumber in range(totalRounds, totalRounds + nRounds): if nRounds > 1:
print "Simulating " + str(nRounds) + " rounds (" + str(totalRounds) + " to " + str(totalRounds + nRounds-1) + ")"
if os.path.exists(logDirectory + "round"+str(roundNumber)) == False: else:
os.mkdir(logDirectory + "round"+str(roundNumber)) #Check there is a directory for this round's logs print "Simulating one round."
print ""
print "Identifying possible agents in \""+agentsDirectory+"\""
#Get all agent names from agentsDirectory
#TODO: Move this part outside the loop? It only has to happen once
agentNames = os.listdir(agentsDirectory)
agents = []
for name in agentNames:
if verbose: if verbose:
print "Simulating ROUND " +str(roundNumber) sys.stdout.write("Scan \""+name+"\"... ")
print "Identifying possible agents in \""+agentsDirectory+"\"" if os.path.isdir(agentsDirectory+name) == False: #Remove non-directories
#Get all agent names from agentsDirectory
#TODO: Move this part outside the loop? It only has to happen once
agentNames = os.listdir(agentsDirectory)
agents = []
for name in agentNames:
#sys.stdout.write("\nLooking at Agent: \""+ str(name)+"\"... ")
if verbose: if verbose:
sys.stdout.write("Scan \""+name+"\"... ") sys.stdout.write(" Invalid! (Not a directory)\n")
if os.path.isdir(agentsDirectory+name) == False: #Remove non-directories continue
if verbose:
sys.stdout.write(" Invalid! (Not a directory)\n")
continue
if os.path.exists(agentsDirectory+name+"/info") == False: #Try and find the special "info" file in each directory; ignore if it doesn't exist if os.path.exists(agentsDirectory+name+"/info") == False: #Try and find the special "info" file in each directory; ignore if it doesn't exist
if verbose: if verbose:
sys.stdout.write(" Invalid! (No \"info\" file found)\n") sys.stdout.write(" Invalid! (No \"info\" file found)\n")
continue continue
agentExecutable = agentsDirectory+name+"/"+(open(agentsDirectory+name+"/info").readline().strip())
if os.path.exists(agentExecutable) == False:
agentExecutable = agentsDirectory+name+"/"+(open(agentsDirectory+name+"/info").readline().strip()) if verbose:
sys.stdout.write(" Invalid! (Path: \""+agentExecutable+"\" does not exist!)\n")
if os.path.exists(agentExecutable) == False: continue
if verbose:
sys.stdout.write(" Invalid! (File \""+agentExecutable+"\" does not exist!)\n")
continue
if verbose:
sys.stdout.write(" Valid! (To run: \""+agentExecutable+"\")\n")
#Convert array of valid names into array of dictionaries containing information about each agent
#I'm starting to like python...
agents.append({"name":name, "path":agentExecutable,"score":[0], "totalScore":0, "VICTORY":[], "DEFEAT":[], "DRAW":[], "ILLEGAL":[], "INTERNAL_ERROR":[]})
if len(agents) == 0:
print "Couldn't find any agents! Check paths (Edit this script) or generate \"info\" files for agents."
sys.exit(0)
if verbose: if verbose:
print "Total: " + str(len(agents)) + " valid agents found (From "+str(len(agentNames))+" possibilities)" sys.stdout.write(" Valid! (Path: \""+agentExecutable+"\")\n")
print ""
print "Commencing ROUND " + str(roundNumber) + " combat! This could take a while... " #Convert array of valid names into array of dictionaries containing information about each agent
#I'm starting to like python...
agents.append({"name":name, "path":agentExecutable,"score":[0], "totalScore":0, "VICTORY":[], "DEFEAT":[], "DRAW":[], "ILLEGAL":[], "INTERNAL_ERROR":[], "ALL":[]})
if len(agents) == 0:
print "Couldn't find any agents! Check paths (Edit this script) or generate \"info\" files for agents."
sys.exit(0)
if verbose:
print "Total: " + str(len(agents)) + " valid agents found (From "+str(len(agentNames))+" possibilities)"
print ""
#Prepare the pretty .html files if they don't exist
htmlDir = resultsDirectory + "pretty/"
if os.path.exists(htmlDir) == False:
os.mkdir(htmlDir)
if os.path.exists(htmlDir) == False:
print "Couldn't create directory \""+htmlDir+"\"."
sys.exit(1)
for agent in agents:
if os.path.exists(htmlDir+agent["name"] + ".html") == False:
agentFile = open(htmlDir+agent["name"] + ".html", "w")
agentFile.write("<html>\n<head>\n <title> " + agent["name"] + " results</title>\n</head>\n<body>\n<h1> Results for " + agent["name"]+" </h1>\n</body>\n</html>\n")
agentFile.close()
os.rename(htmlDir+agent["name"] + ".html", "tmpfile")
oldFile = open("tmpfile")
agentFile = open(htmlDir+agent["name"] + ".html", "w")
for line in oldFile:
if line.strip() == "</body>":
break
agentFile.write(line + "\n")
oldFile.close()
agentFile.close()
os.remove("tmpfile")
#Do each round...
totalGames = nGames/2 * len(agents) * (len(agents)-1)
for roundNumber in range(totalRounds, totalRounds + nRounds):
if os.path.exists(logDirectory + "round"+str(roundNumber)) == False:
os.mkdir(logDirectory + "round"+str(roundNumber)) #Check there is a directory for this round's logs
print "Commencing ROUND " + str(roundNumber) + " combat!"
print "Total: " + str(totalGames) + " games to be played. This could take a while... (Estimate 60s/game)"
normalGames = 0
draws = 0
aiErrors = 0
managerErrors = 0 managerErrors = 0
#This double for loop simulates a round robin, with each agent getting the chance to play as both red and blue against every other agent. #This double for loop simulates a round robin, with each agent getting the chance to play as both red and blue against every other agent.
gameID = 0 gameNumber = 0
for red in agents: #for each agent playing as red, for red in agents: #for each agent playing as red,
for blue in agents: #against each other agent, playing as blue for blue in agents: #against each other agent, playing as blue
if red == blue: if red == blue:
continue #Exclude battles against self continue #Exclude battles against self
gameID += 1 gameNumber += 1
gameID = str(roundNumber) + "." + str(gameNumber)
for i in range(1, nGames/2 + 1): for i in range(1, nGames/2 + 1):
#Play a game and read the result. Note the game is logged to a file based on the agent's names #Play a game and read the result. Note the game is logged to a file based on the agent's names
if verbose: if verbose:
sys.stdout.write("Agents: \""+red["name"]+"\" and \""+blue["name"]+"\" playing game " + str(i) + "/"+str(nGames/2) + "... ") sys.stdout.write("Agents: \""+red["name"]+"\" and \""+blue["name"]+"\" playing game (ID: " + gameID + ") ... ")
logFile = logDirectory + "round"+str(roundNumber) + "/"+red["name"]+".vs."+blue["name"]+"."+str(i) logFile = logDirectory + "round"+str(roundNumber) + "/"+red["name"]+".vs."+blue["name"]+"."+str(i)
outline = os.popen(managerPath + " -o " + logFile + " " + red["path"] + " " + blue["path"], "r").read() outline = os.popen(managerPath + " -o " + logFile + " " + red["path"] + " " + blue["path"], "r").read()
results = outline.split(' ') results = outline.split(' ')
...@@ -149,24 +182,40 @@ for roundNumber in range(totalRounds, totalRounds + nRounds): ...@@ -149,24 +182,40 @@ for roundNumber in range(totalRounds, totalRounds + nRounds):
if len(results) != 6: if len(results) != 6:
if verbose: if verbose:
sys.stdout.write("Garbage output! \"" + outline + "\"\n") sys.stdout.write("Garbage output! \"" + outline + "\"\n")
red["manager_errors"].append((gameID, blue["name"])) red["INTERNAL_ERROR"].append((blue["name"], gameID, scores["INTERNAL_ERROR"][0]))
blue["INTERNAL_ERROR"].append((red["name"], gameID, scores["INTERNAL_ERROR"][0]))
red["ALL"].append((blue["name"], gameID, scores["INTERNAL_ERROR"][0], "INTERNAL_ERROR"))
blue["ALL"].append((red["name"], gameID, scores["INTERNAL_ERROR"][0], "INTERNAL_ERROR"))
managerErrors += 1 managerErrors += 1
else: else:
if results[1] == "RED": if results[1] == "RED":
endColour = red endColour = red
otherColour = blue otherColour = blue
endStr = "RED"
otherStr = "BLUE"
elif results[1] == "BLUE": elif results[1] == "BLUE":
endColour = blue endColour = blue
otherColour = red otherColour = red
endStr = "BLUE"
otherStr = "RED"
if results[1] == "BOTH": if results[1] == "BOTH":
pass red["INTERNAL_ERROR"].append((blue["name"], gameID, scores["INTERNAL_ERROR"][0]))
blue["INTERNAL_ERROR"].append((red["name"], gameID, scores["INTERNAL_ERROR"][0]))
red["ALL"].append((blue["name"], gameID, scores["INTERNAL_ERROR"][0], "INTERNAL_ERROR", "RED"))
blue["ALL"].append((red["name"], gameID, scores["INTERNAL_ERROR"][0], "INTERNAL_ERROR", "BLUE"))
managerErrors += 1
else: else:
endColour["score"].insert(0,endColour["score"][0] + scores[results[2]][0]) endColour["score"].insert(0,endColour["score"][0] + scores[results[2]][0])
endColour[results[2]].append((otherColour["name"], gameID, scores[results[2]][0])) endColour[results[2]].append((otherColour["name"], gameID, scores[results[2]][0]))
endColour["ALL"].append((otherColour["name"], gameID, scores[results[2]][0], results[2], endStr))
otherColour["score"].insert(0, otherColour["score"][0] + scores[results[2]][1]) otherColour["score"].insert(0, otherColour["score"][0] + scores[results[2]][1])
otherColour[scores[results[2]][2]].append((endColour["name"], gameID, scores[results[2]][1])) otherColour[scores[results[2]][2]].append((endColour["name"], gameID, scores[results[2]][1]))
otherColour["ALL"].append((endColour["name"], gameID, scores[results[2]][1], scores[results[2]][2], otherStr))
if verbose: if verbose:
sys.stdout.write(" Result \"") sys.stdout.write(" Result \"")
for ii in range(1, len(results)): for ii in range(1, len(results)):
...@@ -176,16 +225,16 @@ for roundNumber in range(totalRounds, totalRounds + nRounds): ...@@ -176,16 +225,16 @@ for roundNumber in range(totalRounds, totalRounds + nRounds):
sys.stdout.write("\"\n") sys.stdout.write("\"\n")
if verbose: if verbose:
print "Completed combat. Total of " + str(normalGames + draws + aiErrors + managerErrors) + " games played. " print "Completed combat. Total of " + str(gameNumber) + " games played. "
if managerErrors != 0: if managerErrors != 0:
print "WARNING: Recieved "+str(managerErrors)+" garbage outputs. Check the manager program." print "WARNING: Registered "+str(managerErrors)+" errors. Check the manager program."
if verbose: if verbose:
print "" print ""
#We should now have complete score values. #We should now have complete score values.
if verbose: if verbose:
sys.stdout.write("Creating results files for ROUND " + str(roundNumber) + "... ") sys.stdout.write("Creating raw results files for ROUND " + str(roundNumber) + "... ")
agents.sort(key = lambda e : e["score"], reverse=True) #Sort the agents based on score agents.sort(key = lambda e : e["score"], reverse=True) #Sort the agents based on score
...@@ -221,24 +270,51 @@ for roundNumber in range(totalRounds, totalRounds + nRounds): ...@@ -221,24 +270,51 @@ for roundNumber in range(totalRounds, totalRounds + nRounds):
print "Finished writing results for ROUND " + str(roundNumber) print "Finished writing results for ROUND " + str(roundNumber)
print "" print ""
if verbose:
print "RESULTS FOR ROUND " + str(roundNumber) print "RESULTS FOR ROUND " + str(roundNumber)
totalFile = open(resultsDirectory+"total.scores", "w") #Recreate the file totalFile = open(resultsDirectory+"total.scores", "w") #Recreate the file
for agent in agents: for agent in agents:
totalFile.write(agent["name"] + " " + str(agent["totalScore"]) +"\n") #Write the total scores in descending order totalFile.write(agent["name"] + " " + str(agent["totalScore"]) +"\n") #Write the total scores in descending order
print "Agent: " + str(agent) if verbose:
print "Agent: " + str(agent)
if verbose:
print "Updating pretty .html files... "
#I just want to say the even though I still think python is evil, it is much better than bash. Using bash makes me cry.
endTime = time()
print "Completed simulating " + str(nRounds) + " rounds in " + str(endTime - startTime) + " seconds."
if makePrettyResults: for agent in agents:
if verbose: agentFile = open(htmlDir + agent["name"]+".html", "a")
print "Now creating prettiful .html files..." agentFile.write("<h2> Round " + str(roundNumber) + "</h2>\n")
agentFile.write("<h3> Summary </h3>\n")
agentFile.write("<table border=\"0\" cellpadding=\"10\">\n")
agentFile.write("<tr> <th> Score </th> <th> Wins </th> <th> Losses </th> <th> Draws </th> <th> Illegal </th> <th> Errors </th></tr>\n")
agentFile.write("<tr> <td> "+str(agent["score"][0])+" </td> <td> "+str(len(agent["VICTORY"]))+" </td> <td> "+str(len(agent["DEFEAT"]))+" </td> <td> "+str(len(agent["DRAW"]))+" </td> <td> "+str(len(agent["ILLEGAL"]))+" </td> <td> " +str(len(agent["INTERNAL_ERROR"]))+" </td> </tr>\n")
agentFile.write("</table>\n")
agentFile.write("<h3> Detailed </h3>\n")
agentFile.write("<table border=\"0\" cellpadding=\"10\">\n")
agentFile.write("<tr> <th> Game ID </th> <th> Opponent </th> <th> Played as </th> <th> Outcome </th> <th> Score </th> <th> Accumulated Score </th> </tr> </th>\n")
for index in range(0, len(agent["ALL"])):
agentFile.write("<tr> <td> " + str(agent["ALL"][index][1]) + " </td> <td> <a href="+agent["ALL"][index][0]+".html>"+agent["ALL"][index][0] + " </a> </td> <td> " + agent["ALL"][index][4] + " </td> <td> " + agent["ALL"][index][3] + " </td> <td> " + str(agent["ALL"][index][2]) + "</td> <td> " + str(agent["score"][len(agent["score"])-index -2]) + " </td> </tr> </th>\n")
agentFile.write("</table>\n")
agentFile.close()
if verbose:
print "Finalising .html files... "
for agent in agents:
agentFile = open(htmlDir + agent["name"]+".html", "a")
agentFile.write("</body>\n<!-- Results file for \"" + agent["name"] + "\" autogenerated by \"" + sys.argv[0] + "\" at time " + str(time()) + " -->\n</html>\n\n")
agentFile.close()
if verbose: if verbose:
print "Done!" print "Done!"
endTime = time()
print "Completed simulating " + str(nRounds) + " rounds in " + str(endTime - startTime) + " seconds."
sys.exit(0) sys.exit(0)
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment