Search code examples
pythonprobability

Calculate probability of a team ranking inside a league


the goal of this project is to calculate the probability of each making the top 6(the remaining scenarios where each team win or loses the remaining matches but still make it to the top 6) so I made a 3D list to input the match history(the matches that are played and we know the results) the problem is I don't know how to calculate the probability of the team rank because it also depends on other teams I wanna find a formula or a code to solve it

class Team:
    def __init__(self, name, pos):
       self.name = name
       self.pos = pos
       self.w = 0
       self.l = 0
       self.score = ""

    def upd_score(self, history):
        # check the rows
        for match in history[self.pos]:
            if match == ["w"]:
                self.w += 1
            elif match == ["l"]:
                self.l += 1
        # check the columns
        for match in history:
            if match[self.pos] == ["l"]:
                self.w += 1
            elif match[self.pos] == ["w"]:
                self.l += 1
        self.score = f"{self.w} - {self.l}"

    def get_score(self):
        print(f"the score is {self.score} ")

RGE = Team("RGE", 1)
VIT = Team("VIT", 2)
G2 = Team("G2", 3)
MSF = Team("MSF", 4)
AST = Team("AST", 5)
MAD = Team("MAD", 6)
FNC = Team("FNC", 7)
SK = Team("SK", 8)
XL = Team("XL", 9)
BDS = Team("BDS", 10)


MATCH_HISTORY = [
    [["X"], [RGE], [VIT], [G2], [MSF], [AST], [MAD], [FNC], [SK], [XL], [BDS]],
    [[RGE], ["X"], ["w"], ["w"], ["l"], [""], [""], [""], [""], [""], [""]],
    [[VIT], ["w"], ["X"], [""], [""], [""], [""], [""], [""], [""], [""]],
    [[G2], ["w"], [""], ["X"], [""], [""], [""], [""], [""], [""], [""]],
    [[MSF], ["w"], [""], [""], ["X"], [""], [""], [""], [""], [""], [""]],
    [[AST], ["l"], [""], [""], [""], ["X"], [""], [""], [""], [""], [""]],
    [[MAD], ["w"], [""], [""], [""], [""], ["X"], [""], [""], [""], [""]],
    [[FNC], ["l"], [""], [""], [""], [""], [""], ["X"], [""], [""], [""]],
    [[SK], ["w"], [""], [""], [""], [""], [""], [""], ["X"], [""], [""]],
    [[XL], ["w"], [""], [""], [""], [""], [""], [""], [""], ["X"], [""]],
    [[BDS], ["w"], [""], [""], [""], [""], [""], [""], [""], [""], ["X"]],
]

# SCORE UPDATING
RGE.upd_score(MATCH_HISTORY)
VIT.upd_score(MATCH_HISTORY)
G2.upd_score(MATCH_HISTORY)
MSF.upd_score(MATCH_HISTORY)
AST.upd_score(MATCH_HISTORY)
MAD.upd_score(MATCH_HISTORY)
FNC.upd_score(MATCH_HISTORY)
SK.upd_score(MATCH_HISTORY)
XL.upd_score(MATCH_HISTORY)
BDS.upd_score(MATCH_HISTORY)

to calculate the score: if the team is in the rows win I'll put "w" and if the team is in the columns I'll put "l" and "X" for cases that can't be filled(a team cannot play against itself)

btw I am still a beginner so please if there is a way to optimize my code tell me and if you suggest me something it will be nice if explain it or link me something that can help


Solution

  • I loved the idea and couldn't resist doing it, so here is the code

    Basically it iterates over all the possibilities that exist for all the matches that have not been done yet, and calculate the stats of each team beeing in the top N (that you can change in the code)

    Only problem is that the number of possibilities is 2^undone_matches and it goes high really quickly, so you can't run the program for more than 15 undone matches...

    An other possibility would be to do it not recursivly but mathematicaly with probabilities, but I'm too lazy for it xD

    PS: right now the program do not handle equalities in score and take the 1st team with the same score, I let you take care of it if you want :)

    import copy
    
    class Team:
        def __init__(self, name):
           self.name = name
           self.w = 0
           self.l = 0
    
        def init_scores(self, MH):
            for rowIndex in range(0, len(MH[0])):
                if MH[rowIndex][0] == self.name:
                    index = rowIndex
            for columnIndex in range(0, len(MH[0])):
                result = MH[columnIndex][index]
                if result == "w":
                    self.l += 1
                elif result == "l":
                    self.w += 1
                    
            for columnIndex in range(0, len(MH[0])):
                if MH[0][columnIndex] == self.name:
                    index = columnIndex
            for rowIndex in range(0, len(MH[0])):
                result = MH[index][rowIndex]
                if result == "w":
                    self.w += 1
                elif result == "l":
                    self.l += 1
        
                
        def toString(self):
            r  = "| " + self.name.ljust(9) + "|\n"
            r += "|" + "----------" + "|\n"
            r += "| w: " + str(self.w).ljust(6) + "|\n"
            r += "| l: " + str(self.l).ljust(6) + "|\n"
            return r
        
        def getScore(self):
            return [self.name, self.w]
            
            
    def createAllPossibilities(MH, topN, results):
        coo = emptyCellExist(MH)
        if coo[0] >= 0:
            cp1 = copy.deepcopy(MH)
            cp1[coo[0]][coo[1]] = "w"
            createAllPossibilities(cp1, topN, results)
            cp2 = copy.deepcopy(MH)
            cp2[coo[0]][coo[1]] = "l"
            createAllPossibilities(cp2, topN, results)
        else:
            Teams = []
            Teams.append(Team("RGE"))
            Teams.append(Team("VIT"))
            Teams.append(Team("G2"))
            Teams.append(Team("MSF"))
            Teams.append(Team("AST"))
            Teams.append(Team("MAD"))
            Teams.append(Team("FNC"))
            Teams.append(Team("SK"))
            Teams.append(Team("XL"))
            Teams.append(Team("BDS"))
            
            for t in Teams:
                t.init_scores(MH)
                
            scores = []
            for t in Teams:
                scores.append(t.getScore())
            
            for n in range(topN):
                best = 0
                index = -1
                for t in range(len(scores)):
                    if best < scores[t][1]:
                        best = scores[t][1]
                        index = t
                scores[index][1] = 0
                #print(scores)
                results[index] += 1
                
    
    def emptyCellExist(MH):
        for row in range(len(MH[0])):
            for cell in range(len(MH[0])):
                if MH[row][cell] == "":
                    return [row, cell]
        return [-1, -1]
    
    
    
    # current score
    MATCH_HISTORY = [   ["X",   "RGE", "VIT", "G2", "MSF", "AST", "MAD", "FNC", "SK", "XL", "BDS"],
                        ["RGE", "X",   "w",   "w",  "l",   "l",   "w",   "l",   "l",  "w",  ""],
                        ["VIT", "w",   "X",   "l",  "w",   "l",   "w",   "l",   "w",  "w",  ""],
                        ["G2",  "w",   "l",   "X",  "w",   "w",   "l",   "l",   "w",  "w",  ""],
                        ["MSF", "w",   "l",   "v",  "X",   "w",   "w",   "l",   "w",  "w",  ""],
                        ["AST", "l",   "l",   "l",  "l",   "X",   "l",   "l",   "l",  "",  ""],
                        ["MAD", "w",   "l",   "v",  "w",   "l",   "X",   "l",   "l",  "",  ""],
                        ["FNC", "l",   "l",   "l",  "w",   "l",   "l",   "X",   "w",  "",  ""],
                        ["SK",  "w",   "l",   "w",  "l",   "w",   "w",   "l",   "X",  "",  ""],
                        ["XL",  "w",   "l",   "w",  "w",   "l",   "l",   "w",   "w",  "X",  ""],
                        ["BDS", "w",   "l",   "w",  "w",   "l",   "w",   "w",   "l",  "",  "X"]]
    
    # top teams must be top X
    topN = 6
    
    # count the number of matches done and left to do
    matchesDone = 0
    matchesLeft = 0
    for row in MATCH_HISTORY:
        for cell in row:
            if cell == "w" or cell == "l":
                matchesDone += 1
            elif cell == "":
                matchesLeft += 1
    print("matches done : " + str(matchesDone))
    print("matches left to do : " + str(matchesLeft))
    print("that's " + str(pow(2, matchesLeft)) + " possibilities\n")
    
    if matchesLeft > 20:
        print("that's way to much for me")
    else:
        # if the number of matches left to do is low enought, then start calculating the probabilities
        results = [0 for a in range(len(MATCH_HISTORY[0]))]
        createAllPossibilities(MATCH_HISTORY, topN, results)
        
        print(MATCH_HISTORY[0][1:])
        for a in range(len(results)):
            results[a] /= (pow(2, matchesLeft)*topN)
            results[a] = int(results[a]*1000)/10
        print(results)
        
    
    while 1:
        pass