Commit 046b87dd6c65b50e1cea4bdb669e6c7746742b43

Authored by Olivier
1 parent 063262b6b0
Exists in master

Scripts for interpreting the logs

Showing 3 changed files with 1369 additions and 0 deletions Side-by-side Diff

scripts/logFileReader.py View file @ 046b87d
  1 +#!/usr/bin/python
  2 +
  3 +import re
  4 +import sys
  5 +import os
  6 +import random
  7 +from functools import reduce #All of
  8 +from operator import mul #this is for
  9 +from fractions import Fraction #n choose k
  10 +from collections import defaultdict
  11 +
  12 +
  13 +#
  14 +#Methods
  15 +#
  16 +
  17 +#n choose k
  18 +def nChooseK(n,k):
  19 + return int( reduce(mul, (Fraction(n-i, i+1) for i in range(k)), 1) )
  20 +
  21 +#Counts the number of SNPs corresponding to the given ID by checking the superchagedMapping dict
  22 +#id is a string
  23 +def numberSNPsInside(id):
  24 +
  25 + if not superchargedMapping[id]: #not in the mapping
  26 + return 1
  27 +
  28 + else:
  29 + sum = 0
  30 +
  31 + for otherId in superchargedMapping[id]:
  32 + sum += numberSNPsInside(otherId)
  33 +
  34 + return sum
  35 +
  36 +#Recursive method that returns a list of strings, representing the ids of SNPs inside a supercharged SNP
  37 +def getListOfSNPsInsideSupercharged(snpId):
  38 +
  39 + if not superchargedMapping[snpId]:
  40 + #print("This SNP: " + snpId + " is not supercharged, returning it.")
  41 + return [getOriginalIdOfSNP(snpId)]
  42 +
  43 + else:
  44 + listOfSNPs = []
  45 + for otherId in superchargedMapping[snpId]:
  46 + #print("otherId = " + otherId + ", calling the recursive method on it.")
  47 + listOfSNPs.extend(getListOfSNPsInsideSupercharged(otherId)) #could be a list, this is why I use concat instead of append
  48 +
  49 + return listOfSNPs
  50 +
  51 +#Returns the Id of the original SNP corresponding to snpId; nbOfOriginalSNPs is a global variable representing the total number of original SNPs (comes from the graph file)
  52 +#snpId is a string, returns a string
  53 +def getOriginalIdOfSNP(snpId):
  54 +
  55 + snpId = int(snpId)
  56 + #print(str(snpId) + " = ") #test
  57 + if snpId > 0 and snpId <= nbOfOriginalSNPs:
  58 + return str(snpId)
  59 +
  60 + elif snpId < 0:
  61 + snpId *= -1 #change it to a positive value
  62 +
  63 + while snpId > nbOfOriginalSNPs:
  64 + snpId -= nbOfOriginalSNPs
  65 +
  66 + #print(str(snpId) + "\n")
  67 + return str(snpId)
  68 +
  69 + elif snpId == 0:
  70 + print("snpId == 0 --> Big problem!\nScript was stopped. Fix the bug :P") #should never get here
  71 + sys.exit(0)
  72 +
  73 + else: ###We have a supercharged SNP
  74 + return str(snpId)
  75 +
  76 +#Takes a list of SNP ids and returns a string representing the colors in common.
  77 +def findColorsInCommon(snpIdList):
  78 +
  79 + intersectionOfColors = [True] * totalNbOfColors
  80 +
  81 + for snpId in snpIdList:
  82 +
  83 + if int(snpId) > nbOfOriginalSNPs: #supercharged SNP
  84 + colorsOfSNP = findColorsInCommon(superchargedMapping[snpId])
  85 +
  86 + else:
  87 + colorsOfSNP = SNPtoColorsDict[getOriginalIdOfSNP(snpId)]
  88 +
  89 + for x in range(totalNbOfColors):
  90 + if str(x+1) not in colorsOfSNP:
  91 + intersectionOfColors[x] = False
  92 +
  93 + stringColCommon = ""
  94 + for x in range(totalNbOfColors):
  95 + if intersectionOfColors[x]:
  96 + if stringColCommon == "":
  97 + stringColCommon += str(x+1)
  98 + else:
  99 + stringColCommon += "," + str(x+1)
  100 +
  101 + return stringColCommon
  102 +
  103 +#Takes a snpId from a solution and the colorsInCommon of the solution, and puts it in all the indirect solutions possible (see declaration of allSolutions_indirect)
  104 +def lookForIndirectSolutions(snpId, colorsInCommon):
  105 +
  106 + for colors in allSolutions_indirect: #colors is the key
  107 + if checkIfColsAreIncluded(colors, colorsInCommon):
  108 + allSolutions_indirect[colors].add(snpId)
  109 +
  110 +#To check if a combination of colors is found inside the colors of a SNP. colCombination and SNPcols are strings.
  111 +#Returns True or False
  112 +def checkIfColsAreIncluded(colCombination, SNPcols):
  113 +
  114 + commaSplit = colCombination.split(",")
  115 + for color in commaSplit:
  116 + if color not in SNPcols:
  117 + return False
  118 +
  119 + return True
  120 +
  121 +
  122 +################################################################
  123 +################################################################
  124 +################################################################
  125 +
  126 +
  127 +if len(sys.argv) < 6:
  128 + print ("USAGE: python logFileReader.py superchargedMappingFile logFile graphFile.dimacs exactSolutionsFile inputLogFile [inter-experiments_statsFile]")
  129 + sys.exit()
  130 +
  131 +if len(sys.argv) == 7: #we have a inter-experiments_statsFile
  132 + interExpStatsFile = open(sys.argv[6], 'a') #in this file, we will gather information from the different experiments; will be used mostly to study perks
  133 + #First thing we want to do is print the current working directory, which should be a good descriptor of the experiment
  134 + interExpStatsFile.write(os.getcwd() + "\n")
  135 +
  136 +#
  137 +# Opening and reading the mapping file
  138 +#
  139 +
  140 +mappingFile = open(sys.argv[1], 'r')
  141 +superchargedMapping = defaultdict(list)
  142 +
  143 +for line in mappingFile:
  144 +
  145 + if line[0] == '/':
  146 + graphPath = line
  147 +
  148 + else:
  149 + colonSplit = line.split(": ")
  150 + superID = colonSplit[0]
  151 +
  152 + #checking if the superID is already in the mappingFile dict (should not)
  153 + if superchargedMapping[superID]: #evaluated as true if the list is not empty
  154 + print("Something is wrong: " + superID + " is already in the dict of supercharged SNPs.")
  155 +
  156 + else: #Not there yet, as expected
  157 + commaSplit = colonSplit[1].split(", ")
  158 +
  159 + for id in commaSplit:
  160 + superchargedMapping[superID].append(id.strip())
  161 +
  162 + if len(superchargedMapping[superID]) != 10:
  163 + print("Big problem: supercharged SNP " + superID + " does not contain 10 merged SNPs")
  164 +
  165 +mappingFile.close()
  166 +####TEST
  167 +#print(str(numberSNPsInside(2500)))
  168 +#print(str(numberSNPsInside(2501)))
  169 +#print(str(numberSNPsInside(2585)))
  170 +#sys.exit()
  171 +
  172 +
  173 +#
  174 +# Opening and reading the graph file
  175 +#
  176 +
  177 +graphFile = open(sys.argv[3], 'r')
  178 +
  179 +global nbOfOriginalSNPs, totalNbOfColors
  180 +nbOfOriginalSNPs = 0 #not counting the copies
  181 +SNPtoColorsDict = {} #a dict mapping the SNP id (string) to the list of colors (string, comma separated)
  182 +
  183 +for line in graphFile:
  184 +
  185 + spaceSplit = line.split(" ")
  186 +
  187 + if nbOfOriginalSNPs == 0: #we are reading the first line
  188 + nbOfOriginalSNPs = int(spaceSplit[0])
  189 + totalNbOfColors = int(spaceSplit[1].strip())
  190 +
  191 + else:
  192 + SNPtoColorsDict[spaceSplit[1]] = spaceSplit[2].strip()
  193 +
  194 +graphFile.close()
  195 +
  196 +#
  197 +# Opening and reading the exact solutions file
  198 +#
  199 +
  200 +exactSolFile = open(sys.argv[4], 'r')
  201 +
  202 +exactSolDict = defaultdict(set) ### We will put the exact solutions in a dict, where the key is the color (string) and the value is a set of all the SNP ids for that color (string too)
  203 +
  204 +allSolutions_indirect = {} ###NEW: for this dict, we will initialize a new set for each possible subset of colors (given in the exact solutions file), and we
  205 + ### will put in this dict the indirect solutions (e.g. a RED-GREEN-BLUE solution contains solutions for RED, GREEN, BLUE, RED-GREEN, RED-BLUE and GREEN-BLUE)
  206 +
  207 +for line in exactSolFile:
  208 +
  209 + colString = line.split(" ")[0]
  210 +
  211 + allSolutions_indirect[colString] = set() #initializing
  212 +
  213 + if colString == "\n":
  214 + break
  215 + SNPidIter = re.finditer(r'\'(\d+)\'', line)
  216 +
  217 + for id in SNPidIter:
  218 + exactSolDict[colString].add(id.group(1))
  219 +
  220 +
  221 +#
  222 +# Opening and reading the input log file
  223 +#
  224 +
  225 +inputFile = open(sys.argv[5], 'r')
  226 +
  227 +playerIdToUsernameDict = {} # a dict, mapping id to username
  228 +nbInputsDict = {} # a dict, mapping a player ID to its total number of inputs
  229 +perkLevelsDict = defaultdict(list) # a defaultdict of lists, will map a player ID to a list of 4 ints, representing the levels of the 4 skills in the same order as in the game
  230 + # which means: Buyout King, Color Expert, Sequence Collector and Master Trader
  231 +playerIdToXP = {} # a dict mapping a player ID to the player's total experience points
  232 +leaderboardSection = False #to indicate if we are at the end of the file, reading the info on the leaderboard
  233 +for line in inputFile:
  234 +
  235 + if line.strip() == "leaderboard":
  236 + leaderboardSection = True
  237 + continue
  238 +
  239 + if not leaderboardSection and line != "\n":
  240 + if line[0:4] != "Perk": #should be the line with username, ID and number of inputs
  241 + tabSplit = line.split("\t")
  242 + playerIdToUsernameDict[tabSplit[1]] = tabSplit[0]
  243 + nbInputsDict[tabSplit[1]] = int(tabSplit[2].strip())
  244 + #print("hola, tabsplit[0] = " + tabSplit[0] + " and tabSplit[1] = " + tabSplit[1])
  245 + currentPlayerId = tabSplit[1]
  246 +
  247 + else: #perks
  248 + spaceSplit = line.split(" ")
  249 + perkLevelsDict[currentPlayerId].append(int(spaceSplit[4].strip()))
  250 + #print("Current player id = " + currentPlayerId + " and perk level = " + spaceSplit[4].strip())
  251 +
  252 + if leaderboardSection:
  253 + colonSplit = line.split(" : ")
  254 + playerIdToXP[colonSplit[0]] = int(colonSplit[2].strip())
  255 +
  256 +#
  257 +# Opening and reading the log file
  258 +#
  259 +
  260 +logFile = open(sys.argv[2], 'r')
  261 +
  262 +#Sequences sold to the bank
  263 +seqSoldToBank = [] #saving all the solution for sequences sold to the bank
  264 +averageSizeSeqToBank = 0
  265 +sizesSeqToBankDict = defaultdict(int) #stores for all the possible sizes the frequencies
  266 +averageSizeSeqToBankConsideringSupercharge = 0
  267 +averageColorsSeqToBank = 0
  268 +nbColorsSeqToBankDict = defaultdict(int) #stores for all the possible numbers of colors the frequencies
  269 +averagePriceSeqToBank = 0
  270 +
  271 +playerID_sizes_seqSoldToBank = defaultdict(list) #dict that maps a player ID to the list of sizes of all the sequences he sold to the bank
  272 +playerID_nbColors_seqSoldToBank = defaultdict(list) #dict that maps a player ID to the list of nb of colors of all the sequences he sold to the bank
  273 +
  274 +#Sequences bought by other players
  275 +seqSoldToPlayer = []
  276 +averageSizeSeqToPlayer = 0
  277 +averageColorsSeqToPlayer = 0
  278 +averagePriceSeqToPlayer = 0
  279 +
  280 +playerID_sizes_seqToPlayer = defaultdict(list) #dict that maps a player ID to the list of sizes of all the sequences he bought
  281 +playerID_nbColors_seqToPlayer = defaultdict(list) #dict that maps a player ID to the list of nb of colors of all the sequences he bought
  282 +
  283 +#Individual SNPs sold to other players
  284 +snpSoldToPlayer = 0 #just saving the number of SNPs that were sold
  285 +colorsToPriceListDict = defaultdict(list) #This will record the list of the history of prices for each subset of colors
  286 +
  287 +playerID_nbColors_snpsBought = defaultdict(list) #dict that maps a player ID to the list of nb of colors of SNPs he bought (by bidding)
  288 +playerID_nbColors_snpsSold = defaultdict(list) #dict that maps a player ID to the list of nb of colors of SNPs he sold to other players
  289 +
  290 +#Challenges
  291 +challengeTypeCompletedDict = defaultdict(int) #counts the number of times each type of challenge has been completed
  292 +
  293 +playerID_challengesCompletedDict = defaultdict(lambda : defaultdict(int)) #dict that maps a player ID to a dict of challenge names mapping to the number of times it was completed
  294 +
  295 +#Gambles
  296 +totalNbGambles = 0
  297 +nbSuccessfulGambles = 0
  298 +averageChance = 0
  299 +
  300 +#Solutions, organized by colors in common (key)
  301 +allSolutions = defaultdict(set)
  302 +
  303 +playerID_allSolutions = defaultdict(lambda : defaultdict(set)) #a dict mapping each player to his allSolutions defaultdict(set)
  304 +
  305 +for line in logFile:
  306 +
  307 + if line[0] == '/':
  308 + if graphPath != line:
  309 + print("Big problem: graph file in mapping file does not match graph file in log file.")
  310 + sys.exit()
  311 +
  312 + else:
  313 + spaceSplit = line.split("\t")[1].split(" ") #getting rid of the first character and tab
  314 +
  315 + transactionList = [] # a list that will contain the information for the transaction
  316 +
  317 + for number in spaceSplit: #number can also be the id of the seller (and buyer)
  318 +
  319 + if number[len(number)-1] == ';': #removing the semicolon
  320 + number = number[:-1]
  321 +
  322 + transactionList.append(number.strip()) #warning: in the case of a V line (challenge), number is not necessarily a number
  323 +
  324 + if line[0] == 'B':
  325 + seqSoldToBank.append(transactionList)
  326 + size = int(transactionList[1])
  327 + averageSizeSeqToBank += size
  328 + sizesSeqToBankDict[size] += 1
  329 + nbColors = int(transactionList[2])
  330 + averageColorsSeqToBank += nbColors
  331 + nbColorsSeqToBankDict[nbColors] += 1
  332 + averagePriceSeqToBank += int(transactionList[3])
  333 +
  334 + #player reports
  335 + playerId = transactionList[0]
  336 + playerID_sizes_seqSoldToBank[playerId].append(size)
  337 + playerID_nbColors_seqSoldToBank[playerId].append(nbColors)
  338 + #
  339 +
  340 + for x in range(4, len(transactionList)):
  341 + averageSizeSeqToBankConsideringSupercharge += numberSNPsInside(transactionList[x])
  342 +
  343 + #solutions
  344 + snpIdList = transactionList[4:]
  345 + colorsInCommonString = findColorsInCommon(snpIdList)
  346 + for snpId in snpIdList:
  347 + if superchargedMapping[snpId]:
  348 + for otherSNP in getListOfSNPsInsideSupercharged(snpId):
  349 + allSolutions[colorsInCommonString].add(getOriginalIdOfSNP(otherSNP))
  350 + #player reports
  351 + playerID_allSolutions[playerId][colorsInCommonString].add(getOriginalIdOfSNP(otherSNP))
  352 + #indirect solutions
  353 + lookForIndirectSolutions(getOriginalIdOfSNP(otherSNP), colorsInCommonString)
  354 + else:
  355 + allSolutions[colorsInCommonString].add(getOriginalIdOfSNP(snpId))
  356 + #player reports
  357 + playerID_allSolutions[playerId][colorsInCommonString].add(getOriginalIdOfSNP(snpId))
  358 + #indirect solutions
  359 + lookForIndirectSolutions(getOriginalIdOfSNP(snpId), colorsInCommonString)
  360 +
  361 + elif line[0] == 'A':
  362 + seqSoldToPlayer.append(transactionList)
  363 + averageSizeSeqToPlayer += int(transactionList[1])
  364 + averageColorsSeqToPlayer += int(transactionList[2])
  365 + averagePriceSeqToPlayer += int(transactionList[3])
  366 +
  367 + #player reports
  368 + buyerId = transactionList[0].split(">")[1]
  369 + playerID_sizes_seqToPlayer[buyerId].append(int(transactionList[1]))
  370 + playerID_nbColors_seqToPlayer[buyerId].append(int(transactionList[2]))
  371 +
  372 + elif line[0] == 'S':
  373 + snpSoldToPlayer += 1
  374 + colors = findColorsInCommon([getOriginalIdOfSNP(transactionList[3])]) #sending a list to the method
  375 + colorsToPriceListDict[colors].append(int(transactionList[2]))
  376 +
  377 + #player reports
  378 + sellerId = transactionList[0].split(">")[0]
  379 + buyerId = transactionList[0].split(">")[1]
  380 + playerID_nbColors_snpsSold[sellerId].append(int(transactionList[1]))
  381 + playerID_nbColors_snpsBought[buyerId].append(int(transactionList[1]))
  382 +
  383 + elif line[0] == 'V':
  384 + challengeTypeCompletedDict[transactionList[len(transactionList)-1]] += 1 #the last index of transactionList corresponds to the challenge type
  385 +
  386 + #player reports
  387 + playerId = transactionList[0]
  388 + playerID_challengesCompletedDict[playerId][transactionList[len(transactionList)-1]] += 1
  389 +
  390 + elif line[0] == 'G':
  391 + totalNbGambles += 1
  392 + averageChance += float(transactionList[len(transactionList)-2]) #we are going to make the division at the end to get the average
  393 + if transactionList[len(transactionList)-1] == "SUCCESS":
  394 + nbSuccessfulGambles += 1
  395 +
  396 + else:
  397 + print("WARNING: unexpected line in log file")
  398 +
  399 +logFile.close()
  400 +if totalNbGambles != 0:
  401 + averageChance /= totalNbGambles
  402 +
  403 +## Preparing the outputs
  404 +
  405 +nbSeqsSoldToBank = len(seqSoldToBank)
  406 +averageSizeSeqToBank /= nbSeqsSoldToBank
  407 +averageSizeSeqToBankConsideringSupercharge /= nbSeqsSoldToBank
  408 +averageColorsSeqToBank /= nbSeqsSoldToBank
  409 +averagePriceSeqToBank /= nbSeqsSoldToBank
  410 +
  411 +nbSeqsSoldToPlayer = len(seqSoldToPlayer)
  412 +if nbSeqsSoldToPlayer != 0:
  413 + averageSizeSeqToPlayer /= nbSeqsSoldToPlayer
  414 + averageColorsSeqToPlayer /= nbSeqsSoldToPlayer
  415 + averagePriceSeqToPlayer /= nbSeqsSoldToPlayer
  416 +
  417 +print(str(snpSoldToPlayer) + " individual SNPs were sold to another player.\n")
  418 +print("Colors and price histories:")
  419 +for colors, priceList in colorsToPriceListDict.items():
  420 + print("- " + colors + ": " + str(priceList))
  421 +
  422 +print("\n" + str(nbSeqsSoldToBank) + " sequences were sold to the bank:")
  423 +print("- the average size of those sequence was: " + str(averageSizeSeqToBank))
  424 +print("- if we consider the contents of supercharged SNPs, the average size of the solutions found by the players was: " + str(averageSizeSeqToBankConsideringSupercharge))
  425 +print("- the average number of colors of those sequences was: " + str(averageColorsSeqToBank))
  426 +print("- the average price of those sequences was: " + str(averagePriceSeqToBank) + "\n")
  427 +
  428 +print(str(nbSeqsSoldToPlayer) + " sequences were sold to another player:")
  429 +print("- the average size of those sequence was: " + str(averageSizeSeqToPlayer))
  430 +print("- the average number of colors of those sequences was: " + str(averageColorsSeqToPlayer))
  431 +print("- the average price of those sequences was: " + str(averagePriceSeqToPlayer) + "\n")
  432 +
  433 +print("Challenges:")
  434 +for challenge, nb in challengeTypeCompletedDict.items():
  435 + print("- " + challenge + " was completed " + str(nb) + " times")
  436 +
  437 +print("\nGambles:")
  438 +print("- Rate of successful gambles: " + str(nbSuccessfulGambles) + "/" + str(totalNbGambles))
  439 +print("- Average chance (or percentage of the search queue) used by the players: " + "{0:.2f}".format(averageChance*100) + "%")
  440 +
  441 +
  442 +print("\nAll Solutions")
  443 +totalNumberOfGameSolutions = 0
  444 +totalNumberOfExactSolutions = 0
  445 +totalNumberOfIndirectGameSolutions = 0 #new
  446 +numberOfGameSolutionsPerNbColor = [0] * (totalNbOfColors+1) #Cell 0 will be empty
  447 +numberOfExactSolutionsPerNbColor = [0] * (totalNbOfColors+1) #Cell 0 will be empty
  448 +for key in exactSolDict:
  449 + #Couting the number of SNP ids for this color
  450 + exactNb = len(exactSolDict[key])
  451 + gameNb = len(allSolutions[key])
  452 + indirectGameNb = len(allSolutions_indirect[key])
  453 +
  454 + #Counting the number of SNP ids for this number of colors
  455 + numberOfCols = len(key.split(","))
  456 + numberOfExactSolutionsPerNbColor[numberOfCols] += exactNb
  457 + numberOfGameSolutionsPerNbColor[numberOfCols] += gameNb
  458 +
  459 + allSolutionsString = " "
  460 + #allSolutionsIndirectString = str(allSolutions_indirect[key]) #for testing purposes only
  461 + if gameNb > 0:
  462 + allSolutionsString = str(allSolutions[key])
  463 + #Making sure that there is no mistake in the solutions of the game
  464 + for gameId in allSolutions[key]:
  465 + if gameId not in exactSolDict[key]:
  466 + print("BIG PROBLEM! GAME SOLUTION NOT CONTAINED IN EXACT SOLUTION")
  467 + sys.exit()
  468 + #Making sure that there are no mistakes in the indirect solutions of the game
  469 + for indirectGameId in allSolutions_indirect[key]:
  470 + if indirectGameId not in exactSolDict[key]:
  471 + print("BIG PROBLEM! **INDIRECT** GAME SOLUTION NOT CONTAINED IN EXACT SOLUTION")
  472 + sys.exit()
  473 +
  474 + print(key + ": " + allSolutionsString + " --> " + str(gameNb) + "/" + str(exactNb) + " (" + str(indirectGameNb) + "/" + str(exactNb) + " indirect)")
  475 + #print("indirect sols = " + allSolutionsIndirectString) #for testing purposes only
  476 + totalNumberOfExactSolutions += exactNb
  477 + totalNumberOfGameSolutions += gameNb
  478 + totalNumberOfIndirectGameSolutions += indirectGameNb
  479 +
  480 +solutionPercent = "{0:.2f}".format(float(totalNumberOfGameSolutions)/float(totalNumberOfExactSolutions) * 100) #format returns a string
  481 +print("\nIn total, the players have found " + solutionPercent + "% (" + str(totalNumberOfGameSolutions) + "/" + str(totalNumberOfExactSolutions) + ") of the solutions.\n")
  482 +#indirect:
  483 +solutionPercentInd = "{0:.2f}".format(float(totalNumberOfIndirectGameSolutions)/float(totalNumberOfExactSolutions) * 100) #format returns a string
  484 +print("\nConsidering indirect solutions, in total, the players have found " + solutionPercentInd + "% (" +
  485 + str(totalNumberOfIndirectGameSolutions) + "/" + str(totalNumberOfExactSolutions) + ") of the solutions.\n")
  486 +
  487 +#To help calculate the scoring function, based on the exact solutions
  488 +for x in range(1, totalNbOfColors+1):
  489 + print("For " + str(x) + " colors, there are on average " + "{0:.2f}".format(numberOfExactSolutionsPerNbColor[x] / float(nChooseK(totalNbOfColors, x))) +
  490 + " SNPs in the exact solutions.")
  491 +
  492 +################
  493 +#### Graphs ####
  494 +################
  495 +
  496 +#Size of sequences sold to the bank
  497 +file = open("sizesSeqsSoldToBank.dat", 'w')
  498 +for size in sorted(sizesSeqToBankDict):
  499 + file.write(str(size) + "\t" + str(sizesSeqToBankDict[size]) + "\n")
  500 +file.close()
  501 +
  502 +file = open("sizesSeqsSoldToBank.plot", "w")
  503 +file.write("unset key\n")
  504 +file.write("set boxwidth 0.75\n")
  505 +file.write("set style fill solid\n")
  506 +file.write("set title\"Size of sequences sold to the bank\"\n")
  507 +file.write("plot \"sizesSeqsSoldToBank.dat\" using 2:xtic(1) with boxes linecolor rgb \"steelblue\"\n")
  508 +file.write("set term pdfcairo\n")
  509 +file.write("set output \"sizesSeqsSoldToBank.pdf\"\n")
  510 +file.write("replot\n")
  511 +file.close()
  512 +
  513 +os.system("gnuplot sizesSeqsSoldToBank.plot")
  514 +
  515 +#Nb of colors of sequences sold to the bank
  516 +file = open("nbColorsSeqsSoldToBank.dat", 'w')
  517 +for nbColors in sorted(nbColorsSeqToBankDict):
  518 + file.write(str(nbColors) + "\t" + str(nbColorsSeqToBankDict[nbColors]) + "\n")
  519 +file.close()
  520 +
  521 +file = open("nbColorsSeqsSoldToBank.plot", 'w')
  522 +file.write("unset key\n")
  523 +file.write("set boxwidth 0.75\n")
  524 +file.write("set style fill solid\n")
  525 +file.write("set title\"Number of colors of sequences sold to the bank\"\n")
  526 +file.write("plot \"nbColorsSeqsSoldToBank.dat\" using 2:xtic(1) with boxes linecolor rgb \"steelblue\"\n")
  527 +file.write("set term pdfcairo\n")
  528 +file.write("set output \"nbColorsSeqsSoldToBank.pdf\"\n")
  529 +file.write("replot\n")
  530 +file.close()
  531 +
  532 +os.system("gnuplot nbColorsSeqsSoldToBank.plot")
  533 +
  534 +#Percentages of solutions found for each number of colors
  535 +file = open("solutionsPercentages.dat", 'w')
  536 +file2 = open("solutionsPerColor.dat", 'w')
  537 +file2.write("NbCols\tExact\tGame\n")
  538 +for x in range(1, totalNbOfColors+1):
  539 + percentage = "{0:.2f}".format(numberOfGameSolutionsPerNbColor[x] / numberOfExactSolutionsPerNbColor[x] * 100)
  540 + file.write(str(x) + "\t" + percentage + "\n")
  541 + file2.write(str(x) + "\t" + str(numberOfExactSolutionsPerNbColor[x]) + "\t" + str(numberOfGameSolutionsPerNbColor[x]) + "\n")
  542 +file.close()
  543 +file2.close()
  544 +
  545 +file = open("solutionsPercentages.plot", 'w')
  546 +file.write("unset key\n")
  547 +file.write("set boxwidth 0.75\n")
  548 +file.write("set yrange [0:100]\n")
  549 +file.write("set ytics 10\n")
  550 +file.write("set style fill solid\n")
  551 +file.write("set title\"Percentage of solutions found for each nb of colors\"\n")
  552 +file.write("plot \"solutionsPercentages.dat\" using 2:xtic(1) with boxes linecolor rgb \"steelblue\"\n")
  553 +file.write("set term pdfcairo\n")
  554 +file.write("set output \"solutionsPercentages.pdf\"\n")
  555 +file.write("replot\n")
  556 +file.close()
  557 +
  558 +os.system("gnuplot solutionsPercentages.plot")
  559 +
  560 +file2 = open("solutionsPerColor.plot", 'w')
  561 +file2.write("set auto x\n")
  562 +file2.write("set boxwidth 1.0\n")
  563 +file2.write("set style data histogram\n")
  564 +file2.write("set style histogram cluster gap 1\n")
  565 +file2.write("set style fill solid border -1\n")
  566 +file2.write("set title\"Number of solutions found for each nb of colors\"\n")
  567 +file2.write("plot \"solutionsPerColor.dat\" using 2:xtic(1) ti col fc rgb \"steelblue\", '' u 3 ti col fc rgb \"blue\"\n")
  568 +file2.write("set term pdfcairo\n")
  569 +file2.write("set output \"solutionsPerColor.pdf\"\n")
  570 +file2.write("replot\n")
  571 +file2.close()
  572 +
  573 +os.system("gnuplot solutionsPerColor.plot")
  574 +
  575 +
  576 +#Leaderboard and nb of inputs bar plots
  577 +nbOfPlayerIds = len(playerIdToXP)
  578 +fileXp = open("leaderboard.dat", 'w')
  579 +fileInputs = open("inputs.dat", 'w')
  580 +fileRatio = open("inputRatio.dat", 'w')
  581 +playerCounter = 1
  582 +averageRatio_all = 0
  583 +averageRatio_top5 = 0
  584 +averageRatio_others = 0
  585 +for playerId in sorted(playerIdToXP, key=playerIdToXP.get, reverse=True): #this should order the dict values in decreasing order
  586 + playerName_noSpaces = playerIdToUsernameDict[playerId].replace(" ", "_")
  587 + if(playerCounter <= 5): #First 5 players have a different color, that is written in the 3rd column of the data file
  588 + colorString = "\t1\n"
  589 + averageRatio_top5 += playerIdToXP[playerId] / nbInputsDict[playerId]
  590 + else:
  591 + colorString = "\t2\n"
  592 + averageRatio_others += playerIdToXP[playerId] / nbInputsDict[playerId]
  593 + averageRatio_all += playerIdToXP[playerId] / nbInputsDict[playerId]
  594 + fileXp.write(playerName_noSpaces + "\t" + str(playerIdToXP[playerId]) + colorString)
  595 + fileInputs.write(playerName_noSpaces + "\t" + str(nbInputsDict[playerId]) + colorString)
  596 + fileRatio.write(playerName_noSpaces + "\t" + str(playerIdToXP[playerId] / nbInputsDict[playerId]) + colorString)
  597 + playerCounter += 1
  598 +
  599 +#Adding average ratios for the best players, the others and all of them together
  600 +averageRatio_top5 /= 5
  601 +averageRatio_others /= (nbOfPlayerIds - 5)
  602 +averageRatio_all /= nbOfPlayerIds
  603 +fileRatio.write("Top5\t" + str(averageRatio_top5) + "\t1\n")
  604 +fileRatio.write("Others\t" + str(averageRatio_others) + "\t2\n")
  605 +fileRatio.write("All\t" + str(averageRatio_all) + "\t3\n")
  606 +
  607 +fileXp.close()
  608 +fileInputs.close()
  609 +fileRatio.close()
  610 +
  611 +file = open("leaderboardAndInputs.plot", 'w')
  612 +file.write("set term pdfcairo\n")
  613 +file.write("set output \"leaderboardAndInputs.pdf\"\n")
  614 +file.write("unset key\n")
  615 +file.write("unset colorbox\n")
  616 +file.write("set xtics rotate by -25 offset -1,0\n")
  617 +file.write("set palette defined (1 \"gold\", 2 \"steelblue\")\n")
  618 +file.write("set boxwidth 0.75\n")
  619 +file.write("set style fill solid\n")
  620 +file.write("set title \"Leaderboard\"\n")
  621 +file.write("plot \"leaderboard.dat\" using 0:2:3:xticlabel(1) with boxes lc palette\n")
  622 +
  623 +file.write("set title \"Inputs\"\n")
  624 +file.write("plot \"inputs.dat\" using 0:2:3:xticlabel(1) with boxes lc palette\n")
  625 +
  626 +file.write("set palette defined (1 \"gold\", 2 \"steelblue\", 3 \"#556B2F\")\n")
  627 +file.write("set title \"Xp / inputs ratio\"\n")
  628 +file.write("plot \"inputRatio.dat\" using 0:2:3:xticlabel(1) with boxes lc palette\n")
  629 +file.close()
  630 +
  631 +os.system("gnuplot leaderboardAndInputs.plot")
  632 +
  633 +##########################
  634 +# Creating a styles file #
  635 +##########################
  636 +
  637 +styles = open("styles.gp", 'w')
  638 +#Setting line styles for the linespoints graphs
  639 +styles.write("set style line 1 pt 1 ps 1.0 lw 3 lc rgb '#FF0000'\n")
  640 +styles.write("set style line 2 pt 2 ps 1.0 lw 3 lc rgb '#00FF00'\n")
  641 +styles.write("set style line 3 pt 3 ps 1.0 lw 3 lc rgb '#0000FF'\n")
  642 +styles.write("set style line 4 pt 4 ps 1.0 lw 3 lc rgb '#FFFF00'\n")
  643 +styles.write("set style line 5 pt 5 ps 1.0 lw 3 lc rgb '#FF00FF'\n")
  644 +styles.write("set style line 6 pt 6 ps 1.0 lw 3 lc rgb '#00FFFF'\n")
  645 +styles.write("set style line 7 pt 7 ps 1.0 lw 3 lc rgb '#000000'\n")
  646 +styles.write("set style line 8 pt 8 ps 1.0 lw 3 lc rgb '#800000'\n")
  647 +styles.write("set style line 9 pt 9 ps 1.0 lw 3 lc rgb '#008000'\n")
  648 +styles.write("set style line 10 pt 10 ps 1.0 lw 3 lc rgb '#000080'\n")
  649 +styles.write("set style line 11 pt 11 ps 1.0 lw 3 lc rgb '#808000'\n")
  650 +styles.write("set style line 12 pt 12 ps 1.0 lw 3 lc rgb '#800080'\n")
  651 +styles.write("set style line 13 pt 13 ps 1.0 lw 3 lc rgb '#008080'\n")
  652 +styles.write("set style line 14 pt 14 ps 1.0 lw 3 lc rgb '#808080'\n")
  653 +styles.write("set style line 15 pt 15 ps 1.0 lw 3 lc rgb '#C00000'\n")
  654 +styles.write("set style line 16 pt 16 ps 1.0 lw 3 lc rgb '#00C000'\n")
  655 +styles.write("set style line 17 pt 17 ps 1.0 lw 3 lc rgb '#0000C0'\n")
  656 +styles.write("set style line 18 pt 18 ps 1.0 lw 3 lc rgb '#C0C000'\n")
  657 +styles.write("set style line 19 pt 19 ps 1.0 lw 3 lc rgb '#C000C0'\n")
  658 +styles.write("set style line 20 pt 20 ps 1.0 lw 3 lc rgb '#00C0C0'\n")
  659 +styles.close()
  660 +
  661 +
  662 +##################
  663 +# Player reports #
  664 +##################
  665 +
  666 +playerCounter = 1
  667 +
  668 +#opening two files to show all the players in a graph for the sizes, and one for the nb of colors
  669 +allPlayersSizeFile = open("allPlayersSize_time.plot", 'w')
  670 +allPlayersSizeFile.write("set style data linespoints\n")
  671 +allPlayersSizeFile.write("set title\"Seq to bank - size time series\"\n")
  672 +allPlayersSizeFile.write("set yrange [1:10]\n")
  673 +allPlayersSizeFile.write("load \"styles.gp\"\n")
  674 +allPlayersSizeFile.write("plot -1 with line notitle\n") #should not appear, this is just to have a plot, so we can use replot later
  675 +
  676 +allPlayersNbColsFile = open("allPlayersNbCols_time.plot", 'w')
  677 +allPlayersNbColsFile.write("set style data linespoints\n")
  678 +allPlayersNbColsFile.write("set title\"Seq to bank - nb colors time series\"\n")
  679 +allPlayersNbColsFile.write("set yrange [1:" + str(totalNbOfColors) + "]\n")
  680 +allPlayersNbColsFile.write("load \"styles.gp\"\n")
  681 +allPlayersNbColsFile.write("plot -1 with line notitle\n") #should not appear, this is just to have a plot, so we can use replot later
  682 +
  683 +for playerId in playerIdToUsernameDict:
  684 +
  685 + if playerId not in playerIdToXP or playerIdToXP[playerId] == 0: #skipping the 'Test' player
  686 + continue
  687 +
  688 + if not os.path.exists("PlayerReports"):
  689 + os.makedirs("PlayerReports")
  690 + prefix = "PlayerReports/"
  691 + playerName = playerIdToUsernameDict[playerId]
  692 + playerReportFile = open(prefix + playerName + ".plot", 'w')
  693 +
  694 + #interExpStats file - player name
  695 + interExpStatsFile.write("--- Player: " + playerName + "\n")
  696 +
  697 + #########
  698 + # Perks #
  699 + #########
  700 + #data file
  701 + perkDat = open(prefix + playerName + ".perks", 'w')
  702 + perkDat.write("BuyoutKing\t" + str(perkLevelsDict[playerId][0]) + "\n")
  703 + perkDat.write("ColorExpert\t" + str(perkLevelsDict[playerId][1]) + "\n")
  704 + perkDat.write("SequenceCollector\t" + str(perkLevelsDict[playerId][2]) + "\n")
  705 + perkDat.write("MasterTrader\t" + str(perkLevelsDict[playerId][3]) + "\n")
  706 + perkDat.close()
  707 +
  708 + #interExpStats file
  709 + interExpStatsFile.write("Perks: " + str(perkLevelsDict[playerId]) + "\n")
  710 +
  711 + #gnuplot file
  712 + playerReportFile.write("set term pdfcairo\n")
  713 + playerReportFile.write("set output \"" + prefix + playerName + ".pdf\"\n")
  714 + playerReportFile.write("unset key\n")
  715 + playerReportFile.write("set boxwidth 0.75\n")
  716 + playerReportFile.write("set yrange [0:6]\n")
  717 + playerReportFile.write("set style fill solid\n")
  718 + playerReportFile.write("set title\"Skills chosen\"\n")
  719 + playerReportFile.write("plot \"" + prefix + playerName + ".perks\" using 2:xtic(1) with boxes linecolor rgb \"steelblue\"\n")
  720 +
  721 + ################
  722 + # Size to bank #
  723 + ################
  724 + averageSeqLength = 0 #for interExpStats
  725 + playerSizesSeqToBankList = [0] * (10)
  726 + for size in playerID_sizes_seqSoldToBank[playerId]:
  727 + playerSizesSeqToBankList[size-1] += 1 #we start to count from 0 in the list
  728 + averageSeqLength += size
  729 +
  730 + #interExpStats
  731 + if len(playerID_sizes_seqSoldToBank[playerId]) > 0:
  732 + averageSeqLength /= len(playerID_sizes_seqSoldToBank[playerId])
  733 + interExpStatsFile.write("NbSeqsSoldToBank: " + str(len(playerID_sizes_seqSoldToBank[playerId])) + "\n")
  734 + interExpStatsFile.write("AverageSeqLength: " + str(averageSeqLength) + "\n")
  735 +
  736 + sizeToBankDat = open(prefix + playerName + ".sizeToBank", 'w')
  737 + for x in range(10):
  738 + sizeToBankDat.write(str(x+1) + "\t" + str(playerSizesSeqToBankList[x]) + "\n")
  739 + sizeToBankDat.close()
  740 +
  741 + playerReportFile.write("set title\"Sequences sold to bank - sizes\"\n")
  742 + playerReportFile.write("set yrange [*:*]\n")
  743 + playerReportFile.write("plot \"" + prefix + playerName + ".sizeToBank\" using 2:xtic(1) with boxes linecolor rgb \"steelblue\"\n")
  744 +
  745 + #####################
  746 + # Nb colors to bank #
  747 + #####################
  748 + proportionOfSeqsWithMoreThanOneColor = 0 #for interExpStats
  749 + averageNbOfColors = 0 #for interExpStats
  750 + playerNbColorsToBankList = [0] * totalNbOfColors
  751 + for nbCols in playerID_nbColors_seqSoldToBank[playerId]:
  752 + playerNbColorsToBankList[nbCols-1] += 1 #we start to count from 0 in the list
  753 + averageNbOfColors += nbCols
  754 + if nbCols > 1:
  755 + proportionOfSeqsWithMoreThanOneColor += 1
  756 +
  757 + #interExpStats
  758 + averageNbOfColors /= len(playerID_nbColors_seqSoldToBank[playerId])
  759 + proportionOfSeqsWithMoreThanOneColor /= len(playerID_nbColors_seqSoldToBank[playerId])
  760 + interExpStatsFile.write("AverageNbColors: " + str(averageNbOfColors) + "\n")
  761 + interExpStatsFile.write("MoreThan1Col: " + str(proportionOfSeqsWithMoreThanOneColor) + "\n")
  762 +
  763 + nbColsToBank = open(prefix + playerName + ".nbColsToBank", 'w')
  764 + for x in range(totalNbOfColors):
  765 + nbColsToBank.write(str(x+1) + "\t" + str(playerNbColorsToBankList[x]) + "\n")
  766 + nbColsToBank.close()
  767 +
  768 + playerReportFile.write("set title\"Sequences sold to bank - Nb colors\"\n")
  769 + playerReportFile.write("plot \"" + prefix + playerName + ".nbColsToBank\" using 2:xtic(1) with boxes linecolor rgb \"steelblue\"\n")
  770 +
  771 +
  772 + ###############
  773 + # Size buyout #
  774 + ###############
  775 + playerSizesSeqToPlayerList = [0] * 9 #should not be greater than 9
  776 + for size in playerID_sizes_seqToPlayer[playerId]:
  777 + playerSizesSeqToPlayerList[size-1] += 1 #we start to count from 0 in the list
  778 +
  779 + #interExpStats
  780 + interExpStatsFile.write("NbBuyouts: " + str(len(playerID_sizes_seqToPlayer[playerId])) + "\n")
  781 +
  782 + sizeToPlayerDat = open(prefix + playerName + ".sizeToPlayer", 'w')
  783 + for x in range(9):
  784 + sizeToPlayerDat.write(str(x+1) + "\t" + str(playerSizesSeqToPlayerList[x]) + "\n")
  785 + sizeToPlayerDat.close()
  786 +
  787 + playerReportFile.write("set title\"Sequences bought - sizes\"\n")
  788 + playerReportFile.write("plot \"" + prefix + playerName + ".sizeToPlayer\" using 2:xtic(1) with boxes linecolor rgb \"steelblue\"\n")
  789 +
  790 +
  791 + ####################
  792 + # Nb colors buyout #
  793 + ####################
  794 + playerNbColorsToPlayerList = [0] * totalNbOfColors
  795 + for nbCols in playerID_nbColors_seqToPlayer[playerId]:
  796 + playerNbColorsToPlayerList[nbCols-1] += 1 #we start to count from 0 in the list
  797 +
  798 + nbColsToPlayer = open(prefix + playerName + ".nbColsToPlayer", 'w')
  799 + for x in range(totalNbOfColors):
  800 + nbColsToPlayer.write(str(x+1) + "\t" + str(playerNbColorsToPlayerList[x]) + "\n")
  801 + nbColsToPlayer.close()
  802 +
  803 + playerReportFile.write("set title\"Sequences bought - Nb colors\"\n")
  804 + playerReportFile.write("plot \"" + prefix + playerName + ".nbColsToPlayer\" using 2:xtic(1) with boxes linecolor rgb \"steelblue\"\n")
  805 +
  806 +
  807 + #######################
  808 + # Nb colors SNPs sold #
  809 + #######################
  810 + playerNbColorsSNPsSoldList = [0] * totalNbOfColors
  811 + for nbCols in playerID_nbColors_snpsSold[playerId]:
  812 + playerNbColorsSNPsSoldList[nbCols-1] += 1 #we start to count from 0 in the list
  813 +
  814 + #interExpStats
  815 + interExpStatsFile.write("NbSNPsSold: " + str(len(playerID_nbColors_snpsSold[playerId])) + "\n")
  816 +
  817 + nbColsSNPsSold = open(prefix + playerName + ".nbColsSNPsSold", 'w')
  818 + for x in range(totalNbOfColors):
  819 + nbColsSNPsSold.write(str(x+1) + "\t" + str(playerNbColorsSNPsSoldList[x]) + "\n")
  820 + nbColsSNPsSold.close()
  821 +
  822 + playerReportFile.write("set title\"SNPs sold - Nb colors\"\n")
  823 + playerReportFile.write("plot \"" + prefix + playerName + ".nbColsSNPsSold\" using 2:xtic(1) with boxes linecolor rgb \"steelblue\"\n")
  824 +
  825 +
  826 + #########################
  827 + # Nb colors SNPs bought #
  828 + #########################
  829 + playerNbColorsSNPsBoughtList = [0] * totalNbOfColors
  830 + for nbCols in playerID_nbColors_snpsBought[playerId]:
  831 + playerNbColorsSNPsBoughtList[nbCols-1] += 1 #we start to count from 0 in the list
  832 +
  833 + nbColsSNPsBought = open(prefix + playerName + ".nbColsSNPsBought", 'w')
  834 + for x in range(totalNbOfColors):
  835 + nbColsSNPsBought.write(str(x+1) + "\t" + str(playerNbColorsSNPsBoughtList[x]) + "\n")
  836 + nbColsSNPsBought.close()
  837 +
  838 + playerReportFile.write("set title\"SNPs bought - Nb colors\"\n")
  839 + playerReportFile.write("plot \"" + prefix + playerName + ".nbColsSNPsBought\" using 2:xtic(1) with boxes linecolor rgb \"steelblue\"\n")
  840 +
  841 +
  842 + ##################
  843 + # Challenges won #
  844 + ##################
  845 + atLeastOne = False
  846 + chalCompleted = open(prefix + playerName + ".chalCompleted", 'w')
  847 + for challengeType, nb in sorted(playerID_challengesCompletedDict[playerId].items()):
  848 + atLeastOne = True
  849 + chalCompleted.write(challengeType + "\t" + str(nb) + "\n")
  850 + chalCompleted.close()
  851 +
  852 + if(atLeastOne):
  853 + playerReportFile.write("set title\"Challenges completed\"\n")
  854 + playerReportFile.write("set ytics 1\n")
  855 + playerReportFile.write("plot \"" + prefix + playerName + ".chalCompleted\" using 2:xticlabel(1) with boxes linecolor rgb \"steelblue\"\n")
  856 +
  857 +
  858 + ####################################
  859 + # Size to bank and nbColors / time #
  860 + ####################################
  861 + dataFileSize = open(prefix + playerName + ".sizeToBankTime", 'w')
  862 + dataFileNbCols = open(prefix + playerName + ".nbColsToBankTime", 'w')
  863 + atLeastOne = False
  864 + counter = 0;
  865 + averageSize = 0;
  866 + averageNbCols = 0;
  867 + timeSlice = 5; #specifies the length of the time slice (every 5 observations for example corresponds to a dot in the graph)
  868 + for x in range(len(playerID_sizes_seqSoldToBank[playerId])): #the 2 lists (size and nbCols) should be the same length
  869 + counter += 1
  870 + averageSize += playerID_sizes_seqSoldToBank[playerId][x]
  871 + averageNbCols += playerID_nbColors_seqSoldToBank[playerId][x]
  872 + if counter % timeSlice == 0:
  873 + atLeastOne = True
  874 + averageSize /= timeSlice
  875 + averageNbCols /= timeSlice
  876 + dataFileSize.write(str(counter) + "\t" + str(averageSize) + "\n")
  877 + dataFileNbCols.write(str(counter) + "\t" + str(averageNbCols) + "\n")
  878 + averageSize = 0 #reset the averages
  879 + averageNbCols = 0
  880 + dataFileSize.close()
  881 + dataFileNbCols.close()
  882 +
  883 + if atLeastOne:
  884 + playerReportFile.write("set style data linespoints\n")
  885 + playerReportFile.write("set title\"Seq to bank - size time series\"\n")
  886 + playerReportFile.write("set xtics auto\n")
  887 + playerReportFile.write("set yrange [1:10]\n")
  888 + playerReportFile.write("plot \"" + prefix + playerName + ".sizeToBankTime\" using 1:2 with linespoints pt 13 ps 1.5 lw 3 linecolor rgb \"steelblue\"\n")
  889 + #Plotting also in the file with all the other players
  890 + allPlayersSizeFile.write("replot \"" + prefix + playerName + ".sizeToBankTime\" using 1:2 with linespoints ls " + str(playerCounter) + "title '" + playerName + "'\n") #using one of the line styles above
  891 +
  892 + playerReportFile.write("set title\"Seq to bank - nb colors time series\"\n")
  893 + playerReportFile.write("set yrange [1:" + str(totalNbOfColors) + "]\n")
  894 + playerReportFile.write("plot \"" + prefix + playerName + ".nbColsToBankTime\" using 1:2 with linespoints pt 13 ps 1.5 lw 3 linecolor rgb \"steelblue\"\n")
  895 + #Plotting also in the file with all the other players
  896 + allPlayersNbColsFile.write("replot \"" + prefix + playerName + ".nbColsToBankTime\" using 1:2 with linespoints ls " + str(playerCounter) + "title '" + playerName + "'\n") #using one of the line styles above
  897 +
  898 + ############################
  899 + # #
  900 + ############################
  901 +
  902 +
  903 + #Calling gnuplot
  904 + playerReportFile.close()
  905 + os.system("gnuplot \"" + prefix + playerName + ".plot\"")
  906 +
  907 + #incrementing the player counter
  908 + playerCounter += 1
  909 +
  910 +#printing the 2 time series with all the players
  911 +allPlayersSizeFile.write("set term pdfcairo\n")
  912 +allPlayersSizeFile.write("set output \"allPlayersSize_time.pdf\"\n")
  913 +allPlayersSizeFile.write("replot")
  914 +allPlayersSizeFile.close()
  915 +
  916 +allPlayersNbColsFile.write("set term pdfcairo\n")
  917 +allPlayersNbColsFile.write("set output \"allPlayersNbColors_time.pdf\"\n")
  918 +allPlayersNbColsFile.write("replot")
  919 +allPlayersNbColsFile.close()
  920 +
  921 +os.system("gnuplot " + "allPlayersSize_time.plot")
  922 +os.system("gnuplot " + "allPlayersNbCols_time.plot")
  923 +
  924 +
  925 +###TESTS
  926 +#print(getListOfSNPsInsideSupercharged("301"))
  927 +
  928 +#print(getListOfSNPsInsideSupercharged("413"))
  929 +
  930 +#print(getListOfSNPsInsideSupercharged("300"))
  931 +
  932 +#for x in range(1,7):
  933 +# print("6 choose " + str(x) + " = " + str(nChooseK(6, x)))
scripts/perksAnalyzer.py View file @ 046b87d
  1 +import re
  2 +import sys
  3 +import os
  4 +from collections import defaultdict
  5 +
  6 +
  7 +###METHODS
  8 +
  9 +#To return the median of a sorted list
  10 +def findMedian(aSortedList):
  11 +
  12 + if len(aSortedList) % 2 == 0: #pair number of items in the list
  13 + middle = int(len(aSortedList) / 2)
  14 +
  15 + return (aSortedList[middle] + aSortedList[middle-1]) / 2
  16 +
  17 + else:
  18 + return aSortedList[int(len(aSortedList)/2)]
  19 +
  20 +
  21 +#To calculate the average of a list
  22 +def findAverage(aList):
  23 +
  24 + sum = 0
  25 + for elem in aList:
  26 + sum += elem
  27 +
  28 + return sum / len(aList)
  29 +
  30 +
  31 +#Rounding to the nearest integer
  32 +def myRound(floatValue):
  33 +
  34 + if (floatValue > 0):
  35 + return int(floatValue+.5)
  36 + else:
  37 + return int(floatValue-.5)
  38 +
  39 +
  40 +#Getting the sum of a list
  41 +def mySum(aList):
  42 +
  43 + theSum = 0
  44 + for nb in aList:
  45 + theSum += nb
  46 +
  47 + return theSum
  48 +
  49 +##########
  50 +
  51 +
  52 +if len(sys.argv) < 2:
  53 + print("USAGE: python perksAnalyzer.py interExpStatsFile")
  54 + sys.exit()
  55 +
  56 +#
  57 +# Reading the interExpStatsFile
  58 +#
  59 +file = open(sys.argv[1], 'r')
  60 +
  61 +featuresToListOfPlayerDict = defaultdict(list) #This is a dict that maps a feature (e.g. 'ALL' or 'NO_MARKET') to a list of all the players in the test.
  62 +#A player will be represented by a dict, mapping the name of the stat to its numerical value (read from the file)
  63 +
  64 +for line in file:
  65 +
  66 + if line[0:3] == "C:\\": #the title of the experiment, followed by the features description
  67 +
  68 + expFeatures = line.split(" ")[1].strip()
  69 +
  70 + elif line[0:3] == "---": #player name
  71 +
  72 + currentPlayerDict = {}
  73 + currentPlayerDict["Player"] = line.split(": ")[1].strip()
  74 +
  75 + elif line[0:5] == "Perks":
  76 +
  77 + perkLevelsIter = re.finditer(r'(\d)', line)
  78 +
  79 + counter = 1
  80 + for level in perkLevelsIter:
  81 + currentPlayerDict["Perk" + str(counter)] = level.group(1)
  82 + counter += 1
  83 +
  84 + else:
  85 +
  86 + currentPlayerDict[line.split(": ")[0]] = line.split(": ")[1].strip() #Warning: we leave the value as a string here, because we'll choose later if it should be a float or int
  87 +
  88 + if line[0:10] == "NbSNPsSold": #that was the last stat for the player
  89 + featuresToListOfPlayerDict[expFeatures].append(currentPlayerDict) #appending the player to the list corresponding to the features of the experiment
  90 + #print(currentPlayerDict) #test
  91 +
  92 +#
  93 +# Calculating and printing stats
  94 +#
  95 +
  96 +########################
  97 +# Perk 1 : Buyout King #
  98 +########################
  99 +
  100 +#Stats on players without the perk (level 0)
  101 +nbBuyoutsList_noPerk = []
  102 +averageNbBuyouts_noPerk = 0
  103 +
  104 +#Stats on players with the perk (level >= 1)
  105 +nbBuyoutsList_withPerk = []
  106 +averageNbBuyouts_withPerk = 0
  107 +
  108 +for features in featuresToListOfPlayerDict: #iterating through the features
  109 +
  110 + if features == "NO_MARKET": #not counting the NO_MARKET condition, because it's impossible to do a buyout
  111 + continue
  112 +
  113