Continuing with prettified results
authorSam Moore <[email protected]>
Mon, 12 Dec 2011 16:13:00 +0000 (00:13 +0800)
committerSam Moore <[email protected]>
Mon, 12 Dec 2011 16:13:00 +0000 (00:13 +0800)
Now generating html files for each agent showing the results for each round as the rounds are played.

progcomp/judge/simulator/simulate.py

index 269c8b8..76ca0a5 100755 (executable)
@@ -7,6 +7,8 @@
        Plays exactly ONE round, but does not overwrite previously played rounds
        eg: run once to generate round1.results, twice to generate round2.results etc
        Also generates total.scores based on results from every round.
        Plays exactly ONE round, but does not overwrite previously played rounds
        eg: run once to generate round1.results, twice to generate round2.results etc
        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:
 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:
 
 startTime = time() #Record time at which simulation starts
 
 
 startTime = time() #Record time at which simulation starts
 
-#Do each round...
-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
-
+if verbose:
+       if nRounds > 1:
+               print "Simulating " + str(nRounds) + " rounds (" + str(totalRounds) + " to " + str(totalRounds + nRounds-1) + ")"
+       else:
+               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)
-               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:
-               #sys.stdout.write("\nLooking at Agent: \""+ str(name)+"\"... ")
+               sys.stdout.write("Scan \""+name+"\"... ")
+       if os.path.isdir(agentsDirectory+name) == False: #Remove non-directories
                if verbose:
                if verbose:
-                       sys.stdout.write("Scan \""+name+"\"... ")
-               if os.path.isdir(agentsDirectory+name) == False: #Remove non-directories
-                       if verbose:
-                               sys.stdout.write(" Invalid! (Not a directory)\n")
-                       continue
+                       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 verbose:
-                               sys.stdout.write(" Invalid! (No \"info\" file found)\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 verbose:
+                       sys.stdout.write(" Invalid! (No \"info\" file found)\n")
+               continue
 
 
+       agentExecutable = agentsDirectory+name+"/"+(open(agentsDirectory+name+"/info").readline().strip())
        
        
-       
-               agentExecutable = agentsDirectory+name+"/"+(open(agentsDirectory+name+"/info").readline().strip())
-       
-               if os.path.exists(agentExecutable) == False:
-                       if verbose:
-                               sys.stdout.write(" Invalid! (File \""+agentExecutable+"\" does not exist!)\n")
-                       continue
+       if os.path.exists(agentExecutable) == False:
+               if verbose:
+                       sys.stdout.write(" Invalid! (Path: \""+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)"
-               print ""
-               print "Commencing ROUND " + str(roundNumber) + " combat! This could take a while... "
+               sys.stdout.write(" Valid! (Path: \""+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":[], "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
        #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.
        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.
-       gameID = 0
+       gameNumber = 0
        for red in agents:  #for each agent playing as red,
                for blue in agents: #against each other agent, playing as blue
                        if red == blue:
                                continue #Exclude battles against self
        for red in agents:  #for each agent playing as red,
                for blue in agents: #against each other agent, playing as blue
                        if red == blue:
                                continue #Exclude battles against self
-                       gameID += 1
+                       gameNumber += 1
+                       gameID = str(roundNumber) + "." + str(gameNumber)
                        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
                                if verbose:
                        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
                                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)
                                outline = os.popen(managerPath + " -o " + logFile + " " + red["path"] + " " + blue["path"], "r").read()
                                results = outline.split(' ')
                                logFile = logDirectory + "round"+str(roundNumber) + "/"+red["name"]+".vs."+blue["name"]+"."+str(i)
                                outline = os.popen(managerPath + " -o " + logFile + " " + red["path"] + " " + blue["path"], "r").read()
                                results = outline.split(' ')
@@ -149,24 +182,40 @@ for roundNumber in range(totalRounds, totalRounds + nRounds):
                                if len(results) != 6:
                                        if verbose:
                                                sys.stdout.write("Garbage output! \"" + outline + "\"\n")
                                if len(results) != 6:
                                        if verbose:
                                                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
                                else:
 
                                        if results[1] == "RED":
                                                endColour = red
                                                otherColour = blue
                                        managerErrors += 1
                                else:
 
                                        if results[1] == "RED":
                                                endColour = red
                                                otherColour = blue
+                                               endStr = "RED"
+                                               otherStr = "BLUE"
                                        elif results[1] == "BLUE":
                                                endColour = blue
                                                otherColour = red
                                        elif results[1] == "BLUE":
                                                endColour = blue
                                                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:
                                                endColour["score"].insert(0,endColour["score"][0] + scores[results[2]][0])
                                                endColour[results[2]].append((otherColour["name"], gameID, scores[results[2]][0]))
                                        else:
                                                endColour["score"].insert(0,endColour["score"][0] + 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[scores[results[2]][2]].append((endColour["name"], gameID, 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["ALL"].append((endColour["name"], gameID, scores[results[2]][1], scores[results[2]][2], otherStr))
 
 
+                                       
                                        if verbose:
                                                sys.stdout.write(" Result \"")
                                                for ii in range(1, len(results)):
                                        if verbose:
                                                sys.stdout.write(" Result \"")
                                                for ii in range(1, len(results)):
@@ -176,16 +225,16 @@ for roundNumber in range(totalRounds, totalRounds + nRounds):
                                                sys.stdout.write("\"\n")
                
        if verbose:
                                                sys.stdout.write("\"\n")
                
        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:
                print "" 
        #We should now have complete score values.
                
        if verbose:
 
        if verbose:
                print "" 
        #We should now have complete score values.
                
        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):
                print "Finished writing results for ROUND " + str(roundNumber)
                print ""
        
                print "Finished writing results for ROUND " + str(roundNumber)
                print ""
        
-       
-       print "RESULTS FOR ROUND " + str(roundNumber)
+       if verbose:     
+               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:
-       if verbose:
-               print "Now creating prettiful .html files..."
+       for agent in agents:
+               agentFile = open(htmlDir + agent["name"]+".html", "a")
+               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:
        print "Done!"
        
 if verbose:
        print "Done!"
+
+endTime = time()
+print "Completed simulating " + str(nRounds) + " rounds in " + str(endTime - startTime) + " seconds."
 sys.exit(0)
 sys.exit(0)

UCC git Repository :: git.ucc.asn.au